//
// Copyright 2014 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.
//

//            Based on Hello_Triangle.c from
// Book:      OpenGL(R) ES 2.0 Programming Guide
// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
// ISBN-10:   0321502795
// ISBN-13:   9780321502797
// Publisher: Addison-Wesley Professional
// URLs:      http://safari.informit.com/9780321563835
//            http://www.opengles-book.com

#include "SampleApplication.h"

#include "util/shader_utils.h"

#include <cstring>
#include <iostream>

// This small sample compares the per-frame render time for a series of
// squares drawn with TRIANGLE_FANS versus squares drawn with TRIANGLES.
// To exacerbate differences between the two, we use a large collection
// of short buffers with pre-translated vertex data.

class TriangleFanBenchSample : public SampleApplication
{
  public:
    TriangleFanBenchSample(int argc, char **argv)
        : SampleApplication("Microbench", argc, argv, 2, 0, 1280, 1280), mFrameCount(0)
    {}

    void createVertexBuffers()
    {
        const unsigned int slices         = 8;
        const unsigned int numFanVertices = slices + 2;
        const unsigned int fanFloats      = numFanVertices * 3;

        mNumFanVerts = numFanVertices;

        const GLfloat halfDim = 0.0625;
        GLfloat fanVertices[] = {
            0.0f,     0.0f,     0.0f,  // center
            -halfDim, -halfDim, 0.0f,  // LL
            -halfDim, 0.0f,     0.0f,  // CL
            -halfDim, halfDim,  0.0f,  // UL
            0.0f,     halfDim,  0.0f,  // UC
            halfDim,  halfDim,  0.0f,  // UR
            halfDim,  0.0f,     0.0f,  // CR
            halfDim,  -halfDim, 0.0f,  // LR
            0.0f,     -halfDim, 0.0f,  // LC
            -halfDim, -halfDim, 0.0f   // LL (closes the fan)
        };

        const GLfloat xMin = -1.0f;  // We leave viewport/worldview untransformed in this sample
        const GLfloat xMax = 1.0f;
        const GLfloat yMin = -1.0f;
        // const GLfloat yMax = 1.0f;

        glGenBuffers(mNumSquares, mFanBufId);

        GLfloat xOffset = xMin;
        GLfloat yOffset = yMin;
        for (unsigned int i = 0; i < mNumSquares; ++i)
        {
            GLfloat tempVerts[fanFloats] = {0};
            for (unsigned int j = 0; j < numFanVertices; ++j)
            {
                tempVerts[j * 3]     = fanVertices[j * 3] + xOffset;
                tempVerts[j * 3 + 1] = fanVertices[j * 3 + 1] + yOffset;
                tempVerts[j * 3 + 2] = 0.0f;
            }

            glBindBuffer(GL_ARRAY_BUFFER, mFanBufId[i]);
            glBufferData(GL_ARRAY_BUFFER, fanFloats * sizeof(GLfloat), tempVerts, GL_STATIC_DRAW);

            xOffset += 2 * halfDim;
            if (xOffset > xMax)
            {
                xOffset = xMin;
                yOffset += 2 * halfDim;
            }
        }

        const unsigned int numTriVertices = slices * 3;
        const unsigned int triFloats      = numTriVertices * 3;
        GLfloat triVertices[triFloats];
        GLfloat *triPointer = triVertices;

        mNumTriVerts = numTriVertices;

        for (unsigned int i = 0; i < slices; ++i)
        {
            memcpy(triPointer, fanVertices,
                   3 * sizeof(GLfloat));  // copy center point as first vertex for this slice
            triPointer += 3;
            for (unsigned int j = 1; j < 3; ++j)
            {
                GLfloat *vertex =
                    &(fanVertices[(i + j) * 3]);  // copy two outer vertices for this point
                memcpy(triPointer, vertex, 3 * sizeof(GLfloat));
                triPointer += 3;
            }
        }

        // GLfloat triVertices2[triFloats];
        glGenBuffers(mNumSquares, mTriBufId);
        xOffset = xMin;
        yOffset = yMin;

        for (unsigned int i = 0; i < mNumSquares; ++i)
        {
            triPointer = triVertices;
            GLfloat tempVerts[triFloats];
            for (unsigned int j = 0; j < numTriVertices; ++j)
            {
                tempVerts[j * 3]     = triPointer[0] + xOffset;
                tempVerts[j * 3 + 1] = triPointer[1] + yOffset;
                tempVerts[j * 3 + 2] = 0.0f;
                triPointer += 3;
            }

            glBindBuffer(GL_ARRAY_BUFFER, mTriBufId[i]);
            glBufferData(GL_ARRAY_BUFFER, triFloats * sizeof(GLfloat), tempVerts, GL_STATIC_DRAW);
            xOffset += 2 * halfDim;
            if (xOffset > xMax)
            {
                yOffset += 2 * halfDim;
                xOffset = xMin;
            }
        }
    }

    bool initialize() override
    {
        constexpr char kVS[] = R"(attribute vec4 vPosition;
void main()
{
    gl_Position = vPosition;
})";

        constexpr char kFS[] = R"(precision mediump float;
void main()
{
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
})";

        mProgram = CompileProgram(kVS, kFS);
        if (!mProgram)
        {
            return false;
        }

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

        createVertexBuffers();

        mFanTotalTime = 0;
        mTriTotalTime = 0;

        return true;
    }

    void destroy() override
    {
        std::cout << "Total draw time using TRIANGLE_FAN: " << mFanTotalTime << "ms ("
                  << (float)mFanTotalTime / (float)mFrameCount << " average per frame)"
                  << std::endl;
        std::cout << "Total draw time using TRIANGLES: " << mTriTotalTime << "ms ("
                  << (float)mTriTotalTime / (float)mFrameCount << " average per frame)"
                  << std::endl;
        glDeleteProgram(mProgram);
    }

    void draw() override
    {
        // Set the viewport
        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());

        // Clear the color buffer
        glClear(GL_COLOR_BUFFER_BIT);

        // Use the program object
        glUseProgram(mProgram);

        // Bind the vertex data
        glEnableVertexAttribArray(0);

        // Draw using triangle fans, stored in VBO
        mFanTimer.start();
        for (unsigned i = 0; i < mNumSquares; ++i)
        {
            glBindBuffer(GL_ARRAY_BUFFER, mFanBufId[i]);
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
            glDrawArrays(GL_TRIANGLE_FAN, 0, mNumFanVerts);
        }
        mFanTimer.stop();

        mFanTotalTime += static_cast<unsigned int>(
            mFanTimer.getElapsedTime() * 1000);  // convert from usec to msec when accumulating

        // Clear to eliminate driver-side gains from occlusion
        glClear(GL_COLOR_BUFFER_BIT);

        // Draw using triangles, stored in VBO
        mTriTimer.start();
        for (unsigned i = 1; i < mNumSquares; ++i)
        {
            glBindBuffer(GL_ARRAY_BUFFER, mTriBufId[i]);
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
            glDrawArrays(GL_TRIANGLES, 0, mNumTriVerts);
        }
        mTriTimer.stop();

        mTriTotalTime += static_cast<unsigned int>(
            mTriTimer.getElapsedTime() * 1000);  // convert from usec to msec when accumulating

        mFrameCount++;
    }

  private:
    static const unsigned int mNumSquares = 289;
    unsigned int mNumFanVerts;
    unsigned int mNumTriVerts;
    GLuint mProgram;
    GLuint mFanBufId[mNumSquares];
    GLuint mTriBufId[mNumSquares];

    Timer mFanTimer;
    Timer mTriTimer;
    unsigned int mFrameCount;
    unsigned int mTriTotalTime;
    unsigned int mFanTotalTime;
};

int main(int argc, char **argv)
{
    TriangleFanBenchSample app(argc, argv);
    return app.run();
}
