//
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// IndexDataManagerPerfTest:
//   Performance test for index buffer management.
//

#include "ANGLEPerfTest.h"
#include "common/unsafe_buffers.h"

#include <gmock/gmock.h>

#include "angle_unittests_utils.h"
#include "libANGLE/renderer/d3d/BufferD3D.h"
#include "libANGLE/renderer/d3d/IndexBuffer.h"
#include "libANGLE/renderer/d3d/IndexDataManager.h"

using namespace testing;

namespace
{
constexpr unsigned int kIterationsPerStep = 100;

class MockIndexBuffer : public rx::IndexBuffer
{
  public:
    MockIndexBuffer(unsigned int bufferSize, gl::DrawElementsType indexType)
        : mBufferSize(bufferSize), mIndexType(indexType)
    {}

    MOCK_METHOD4(initialize,
                 angle::Result(const gl::Context *, unsigned int, gl::DrawElementsType, bool));
    MOCK_METHOD4(mapBuffer,
                 angle::Result(const gl::Context *, unsigned int, unsigned int, void **));
    MOCK_METHOD1(unmapBuffer, angle::Result(const gl::Context *));
    MOCK_METHOD1(discard, angle::Result(const gl::Context *));
    MOCK_METHOD3(setSize, angle::Result(const gl::Context *, unsigned int, gl::DrawElementsType));

    // inlined for speed
    gl::DrawElementsType getIndexType() const override { return mIndexType; }
    unsigned int getBufferSize() const override { return mBufferSize; }

  private:
    unsigned int mBufferSize;
    gl::DrawElementsType mIndexType;
};

class MockBufferFactoryD3D : public rx::BufferFactoryD3D
{
  public:
    MockBufferFactoryD3D(unsigned int bufferSize, gl::DrawElementsType indexType)
        : mBufferSize(bufferSize), mIndexType(indexType)
    {}

    MOCK_METHOD0(createVertexBuffer, rx::VertexBuffer *());
    MOCK_CONST_METHOD1(getVertexConversionType, rx::VertexConversionType(angle::FormatID));
    MOCK_CONST_METHOD1(getVertexComponentType, GLenum(angle::FormatID));
    MOCK_CONST_METHOD7(getVertexSpaceRequired,
                       angle::Result(const gl::Context *,
                                     const gl::VertexAttribute &,
                                     const gl::VertexBinding &,
                                     size_t,
                                     GLsizei,
                                     uint64_t,
                                     unsigned int *));

    // Dependency injection
    rx::IndexBuffer *createIndexBuffer() override
    {
        return new MockIndexBuffer(mBufferSize, mIndexType);
    }

  private:
    unsigned int mBufferSize;
    gl::DrawElementsType mIndexType;
};

class MockBufferD3D : public rx::BufferD3D
{
  public:
    MockBufferD3D(rx::BufferFactoryD3D *factory) : BufferD3D(mockState, factory), mData() {}

    // BufferImpl
    angle::Result setData(const gl::Context *context,
                          gl::BufferBinding target,
                          const void *data,
                          size_t size,
                          gl::BufferUsage,
                          rx::BufferFeedback *feedback,
                          gl::ZeroFillRequired zeroFillRequired) override
    {
        mData.resize(size);
        if (data && size > 0)
        {
            ANGLE_UNSAFE_TODO(memcpy(&mData[0], data, size));
        }
        return angle::Result::Continue;
    }

    MOCK_METHOD6(setSubData,
                 angle::Result(const gl::Context *,
                               gl::BufferBinding,
                               const void *,
                               size_t,
                               size_t,
                               rx::BufferFeedback *));
    MOCK_METHOD6(copySubData,
                 angle::Result(const gl::Context *,
                               BufferImpl *,
                               GLintptr,
                               GLintptr,
                               GLsizeiptr,
                               rx::BufferFeedback *));
    MOCK_METHOD4(map,
                 angle::Result(const gl::Context *context, GLenum, void **, rx::BufferFeedback *));
    MOCK_METHOD6(mapRange,
                 angle::Result(const gl::Context *,
                               size_t,
                               size_t,
                               GLbitfield,
                               void **,
                               rx::BufferFeedback *));
    MOCK_METHOD3(unmap,
                 angle::Result(const gl::Context *context, GLboolean *, rx::BufferFeedback *));

    // BufferD3D
    MOCK_METHOD2(markTransformFeedbackUsage,
                 angle::Result(const gl::Context *, rx::BufferFeedback *));

    // inlined for speed
    bool supportsDirectBinding() const override { return false; }
    size_t getSize() const override { return mData.size(); }

    angle::Result getData(const gl::Context *context, const uint8_t **outData) override
    {
        *outData = &mData[0];
        return angle::Result::Continue;
    }

  private:
    gl::BufferState mockState;
    std::vector<uint8_t> mData;
};

class MockGLFactoryD3D : public rx::MockGLFactory
{
  public:
    MockGLFactoryD3D(MockBufferFactoryD3D *bufferFactory) : mBufferFactory(bufferFactory) {}

    rx::BufferImpl *createBuffer(const gl::BufferState &state) override
    {
        MockBufferD3D *mockBufferD3D = new MockBufferD3D(mBufferFactory);
        rx::BufferFeedback feedback;

        EXPECT_CALL(*mBufferFactory, createVertexBuffer())
            .WillOnce(Return(nullptr))
            .RetiresOnSaturation();
        mockBufferD3D->initializeStaticData(nullptr, &feedback);

        return mockBufferD3D;
    }

    MockBufferFactoryD3D *mBufferFactory;
};

class IndexDataManagerPerfTest : public ANGLEPerfTest
{
  public:
    IndexDataManagerPerfTest();

    void step() override;

    rx::IndexDataManager mIndexDataManager;
    GLsizei mIndexCount;
    unsigned int mBufferSize;
    MockBufferFactoryD3D mMockBufferFactory;
    MockGLFactoryD3D mMockGLFactory;
    gl::Buffer mIndexBuffer;
};

IndexDataManagerPerfTest::IndexDataManagerPerfTest()
    : ANGLEPerfTest("IndexDataManager", "", "_run", kIterationsPerStep),
      mIndexDataManager(&mMockBufferFactory),
      mIndexCount(4000),
      mBufferSize(mIndexCount * sizeof(GLushort)),
      mMockBufferFactory(mBufferSize, gl::DrawElementsType::UnsignedShort),
      mMockGLFactory(&mMockBufferFactory),
      mIndexBuffer(&mMockGLFactory, {1})
{
    std::vector<GLushort> indexData(mIndexCount);
    for (GLsizei index = 0; index < mIndexCount; ++index)
    {
        indexData[index] = static_cast<GLushort>(index);
    }
    EXPECT_EQ(
        angle::Result::Continue,
        mIndexBuffer.bufferData(nullptr, gl::BufferBinding::Array, &indexData[0],
                                indexData.size() * sizeof(GLushort), gl::BufferUsage::StaticDraw));
}

void IndexDataManagerPerfTest::step()
{
    rx::TranslatedIndexData translatedIndexData;
    gl::IndexRange indexRange;
    for (unsigned int iteration = 0; iteration < kIterationsPerStep; ++iteration)
    {
        (void)mIndexBuffer.getIndexRange(nullptr, gl::DrawElementsType::UnsignedShort, 0,
                                         mIndexCount, false, &indexRange);
        (void)mIndexDataManager.prepareIndexData(nullptr, gl::DrawElementsType::UnsignedShort,
                                                 gl::DrawElementsType::UnsignedShort, mIndexCount,
                                                 &mIndexBuffer, nullptr, &translatedIndexData);
    }
}

TEST_F(IndexDataManagerPerfTest, Run)
{
    run();
}

}  // anonymous namespace
