//
// Copyright 2017 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.
//
// DrawElementsPerf:
//   Performance tests for ANGLE DrawElements call overhead.
//

#include <sstream>

#include "ANGLEPerfTest.h"
#include "DrawCallPerfParams.h"
#include "test_utils/draw_call_perf_utils.h"

namespace
{

GLuint CreateElementArrayBuffer(size_t count, GLenum type, GLenum usage)
{
    GLuint buffer = 0u;
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(type), nullptr, usage);

    return buffer;
}

struct DrawElementsPerfParams final : public DrawCallPerfParams
{
    // Common default options
    DrawElementsPerfParams()
    {
        runTimeSeconds = 5.0;
        numTris        = 2;
    }

    std::string story() const override
    {
        std::stringstream strstr;

        strstr << DrawCallPerfParams::story();

        if (indexBufferChanged)
        {
            strstr << "_index_buffer_changed";
        }

        if (type == GL_UNSIGNED_SHORT)
        {
            strstr << "_ushort";
        }

        return strstr.str();
    }

    GLenum type             = GL_UNSIGNED_INT;
    bool indexBufferChanged = false;
};

std::ostream &operator<<(std::ostream &os, const DrawElementsPerfParams &params)
{
    os << params.backendAndStory().substr(1);
    return os;
}

class DrawElementsPerfBenchmark : public ANGLERenderTest,
                                  public ::testing::WithParamInterface<DrawElementsPerfParams>
{
  public:
    DrawElementsPerfBenchmark();

    void initializeBenchmark() override;
    void destroyBenchmark() override;
    void drawBenchmark() override;

  private:
    GLuint mProgram     = 0;
    GLuint mBuffer      = 0;
    GLuint mIndexBuffer = 0;
    GLuint mFBO         = 0;
    GLuint mTexture     = 0;
    GLsizei mBufferSize = 0;
    int mCount          = 3 * GetParam().numTris;
    std::vector<GLuint> mIntIndexData;
    std::vector<GLushort> mShortIndexData;
};

DrawElementsPerfBenchmark::DrawElementsPerfBenchmark()
    : ANGLERenderTest("DrawElementsPerf", GetParam())
{
    if (GetParam().type == GL_UNSIGNED_INT)
    {
        addExtensionPrerequisite("GL_OES_element_index_uint");
    }
}

GLsizei ElementTypeSize(GLenum elementType)
{
    switch (elementType)
    {
        case GL_UNSIGNED_BYTE:
            return sizeof(GLubyte);
        case GL_UNSIGNED_SHORT:
            return sizeof(GLushort);
        case GL_UNSIGNED_INT:
            return sizeof(GLuint);
        default:
            return 0;
    }
}

void DrawElementsPerfBenchmark::initializeBenchmark()
{
    const auto &params = GetParam();

    mProgram = SetupSimpleDrawProgram();
    ASSERT_NE(0u, mProgram);

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    mBuffer      = Create2DTriangleBuffer(params.numTris, GL_STATIC_DRAW);
    mIndexBuffer = CreateElementArrayBuffer(mCount, params.type, GL_STATIC_DRAW);

    for (int i = 0; i < mCount; i++)
    {
        ASSERT_GE(std::numeric_limits<GLushort>::max(), mCount);
        mShortIndexData.push_back(static_cast<GLushort>(rand() % mCount));
        mIntIndexData.push_back(rand() % mCount);
    }

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);

    mBufferSize = ElementTypeSize(params.type) * mCount;

    if (params.type == GL_UNSIGNED_INT)
    {
        glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, mBufferSize, mIntIndexData.data());
    }
    else
    {
        glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, mBufferSize, mShortIndexData.data());
    }

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(0);

    // Set the viewport
    glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());

    if (params.offscreen)
    {
        CreateColorFBO(getWindow()->getWidth(), getWindow()->getHeight(), &mTexture, &mFBO);
    }

    ASSERT_GL_NO_ERROR();
}

void DrawElementsPerfBenchmark::destroyBenchmark()
{
    glDeleteProgram(mProgram);
    glDeleteBuffers(1, &mBuffer);
    glDeleteBuffers(1, &mIndexBuffer);
    glDeleteTextures(1, &mTexture);
    glDeleteFramebuffers(1, &mFBO);
}

void DrawElementsPerfBenchmark::drawBenchmark()
{
    // This workaround fixes a huge queue of graphics commands accumulating on the GL
    // back-end. The GL back-end doesn't have a proper NULL device at the moment.
    // TODO(jmadill): Remove this when/if we ever get a proper OpenGL NULL device.
    const auto &eglParams = GetParam().eglParameters;
    if (eglParams.deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE ||
        (eglParams.renderer != EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE &&
         eglParams.renderer != EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE))
    {
        glClear(GL_COLOR_BUFFER_BIT);
    }

    const DrawElementsPerfParams &params = GetParam();

    if (params.indexBufferChanged)
    {
        const void *bufferData = (params.type == GL_UNSIGNED_INT)
                                     ? static_cast<GLvoid *>(mIntIndexData.data())
                                     : static_cast<GLvoid *>(mShortIndexData.data());
        for (unsigned int it = 0; it < params.iterationsPerStep; it++)
        {
            glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, mBufferSize, bufferData);
            glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mCount), params.type, 0);
        }
    }
    else
    {
        for (unsigned int it = 0; it < params.iterationsPerStep; it++)
        {
            glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mCount), params.type, 0);
        }
    }

    ASSERT_GL_NO_ERROR();
}

TEST_P(DrawElementsPerfBenchmark, Run)
{
    run();
}

using namespace angle;
using namespace params;
using P = DrawElementsPerfParams;

P CombineIndexType(const P &in, GLenum indexType)
{
    P out    = in;
    out.type = indexType;
    return out;
}

P CombineIndexBufferChanged(const P &in, bool indexBufferChanged)
{
    P out                  = in;
    out.indexBufferChanged = indexBufferChanged;

    // Scale down iterations for slower tests.
    if (indexBufferChanged)
        out.iterationsPerStep /= 100;

    return out;
}

std::vector<GLenum> gIndexTypes = {GL_UNSIGNED_INT, GL_UNSIGNED_SHORT};
std::vector<P> gWithIndexType   = CombineWithValues({P()}, gIndexTypes, CombineIndexType);
std::vector<P> gWithRenderer =
    CombineWithFuncs(gWithIndexType, {D3D11<P>, GL<P>, Vulkan<P>, WGL<P>});
std::vector<P> gWithChange =
    CombineWithValues(gWithRenderer, {false, true}, CombineIndexBufferChanged);
std::vector<P> gWithDevice = CombineWithFuncs(gWithChange, {Passthrough<P>, NullDevice<P>});

ANGLE_INSTANTIATE_TEST_ARRAY(DrawElementsPerfBenchmark, gWithDevice);

}  // anonymous namespace
