//
// Copyright (c) 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 "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()
        : SampleApplication("Microbench", 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;
            }
        }
    }

    virtual bool initialize()
    {
        const std::string vs = SHADER_SOURCE
        (
            attribute vec4 vPosition;
            void main()
            {
                gl_Position = vPosition;
            }
        );

        const std::string fs = SHADER_SOURCE
        (
            precision mediump float;
            void main()
            {
                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
            }
        );

        mProgram = CompileProgram(vs, fs);
        if (!mProgram)
        {
            return false;
        }

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

        createVertexBuffers();

        mFanTimer = CreateTimer();
        mTriTimer = CreateTimer();
        mFanTotalTime = 0;
        mTriTotalTime = 0;

        return true;
    }

    virtual void destroy()
    {
        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);
    }

    virtual void draw()
    {
        // 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;
    return app.run();
}
