/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
#include "FPSCounter.h"


bool FPSCounter::loadFPSShader(ShaderProgram* pShaderProgram)
{
    uiFPSProgram = glCreateProgram();
    std::string vertShaderName = VERTSHADER;
    std::string fragShaderName = FRAGSHADER;
    pShaderProgram->loadShader(uiFPSProgram, vertShaderName, GL_VERTEX_SHADER);
    pShaderProgram->loadShader(uiFPSProgram, fragShaderName, GL_FRAGMENT_SHADER);
    pFont->setShaderProgram(uiFPSProgram);
    return true;
}

void FPSCounter::timeStampStart()
{
#ifdef _WIN32
    _LARGE_INTEGER tmp;
    QueryPerformanceCounter(&tmp);
    mStartTime = (double)tmp.QuadPart;
#else
    mStartTime = clock();
#endif
}

void FPSCounter::timeStampEnd()
{
#ifdef _WIN32
    _LARGE_INTEGER tmp;
    QueryPerformanceCounter(&tmp);
    mEndTime = (double)tmp.QuadPart;
#else
    mEndTime = clock();
#endif
}

void FPSCounter::gpuTimeStampStart()
{
#ifdef _WIN32
    _LARGE_INTEGER tmp;
    QueryPerformanceCounter(&tmp);
    mGPUStartTime = (double)tmp.QuadPart;
#else
    mGPUStartTime = clock();
#endif
}

void FPSCounter::gpuTimeStampEnd()
{
#ifdef _WIN32
    _LARGE_INTEGER tmp;
    QueryPerformanceCounter(&tmp);
    mGPUEndTime = (double)tmp.QuadPart;
#else
    mGPUEndTime = clock();
#endif
}

void FPSCounter::gpuTimeAccumulation()
{
    mGPUDuration += mGPUEndTime - mGPUStartTime;
}

int FPSCounter::getFPS()
{
    double renderTime = getExecutionTime();
    double FPS = 1/renderTime;
    return (int)ceil(FPS);
}

void FPSCounter::gpuAccumulationTimeclear()
{
    mGPUDuration = 0;
}

double FPSCounter::getExecutionTime()
{
    double renderTime =0;
#ifdef _WIN32
    renderTime = (double)(mEndTime - mStartTime) / dqFreq;
#else
    renderTime = (double)(mEndTime - mStartTime) / CLOCKS_PER_SEC;
#endif
    return renderTime;
}

double FPSCounter::getGPUTime()
{
    double gpuTime =0;
#ifdef _WIN32
    gpuTime = (double)mGPUDuration/dqFreq;
#else
    gpuTime = (double)mGPUDuration/ CLOCKS_PER_SEC;
#endif
    return gpuTime;
}

void FPSCounter::printFPS(glTFViewport* pViewport ) 
{
    glUseProgram(uiFPSProgram);
    glDisable(GL_DEPTH_TEST);
    GLuint iLoc = glGetUniformLocation(uiFPSProgram, "matrices.projMatrix");
    glUniformMatrix4fv(iLoc, 1,false, (GLfloat*)(&glm::ortho(0.0f, float(pViewport->width), 0.0f, float(pViewport->height))));
    glm::vec4 lightVector = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
    iLoc = glGetUniformLocation(uiFPSProgram, "vColor");
    glUniform4fv(iLoc, 1, (GLfloat*)&lightVector);
    if (mDurationTime >= CLOCKS_PER_SEC)
    {
        mFPS = getFPS();
        mDurationTime = 0;
        mTotalTime = getExecutionTime();
        mGPUTime = mGPUDuration/dqFreq;
    } 
    else
    {
#ifdef _WIN32
        mDurationTime += ((mEndTime - mStartTime)/dqFreq)*1000;
#else
        mDurationTime += mEndTime - mStartTime;
#endif 
    }

    pFont->printFormattedString(20, pViewport->height-30, 20, "FPS: %d", mFPS);
    pFont->printFormattedString(20, pViewport->height-60, 20, "Render Total Time: %.2f ms, Draw Time: %.2f ms", mTotalTime*1000,mGPUTime*1000);
    glEnable(GL_DEPTH_TEST);
}