// Copyright (C) 2010-2011 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma version(1)

#pragma rs java_package_name(com.android.perftest)

#include "rs_graphics.rsh"
#include "shader_def.rsh"
#include "subtest_def.rsh"

/* Message sent from script to renderscript */
const int RS_MSG_TEST_DONE = 100;
const int RS_MSG_RESULTS_READY = 101;

static const int gMaxModes = 64;
int gMaxLoops = 1;
int gDisplayMode = 1;

// Allocation to write the results into
static float gResultBuffer[gMaxModes];

rs_font gFontSerif;
rs_sampler gLinearClamp;

rs_program_vertex gProgVertex;
rs_program_fragment gProgFragmentTexture;

rs_allocation gRenderBufferColor;
rs_allocation gRenderBufferDepth;

VertexShaderInputs *gVSInputs;

typedef struct TestScripts_s {
    rs_allocation testData;
    rs_allocation testName;
    rs_allocation debugName;
    rs_script testScript;
} TestScripts;
TestScripts *gTestScripts;

bool gLoadComplete = false;
bool gPauseRendering = false;

static float gDt = 0;

void init() {
}

static int gRenderSurfaceW;
static int gRenderSurfaceH;

static void fillSurfaceParams(TestData *testData) {
    testData->renderSurfaceW = gRenderSurfaceW;
    testData->renderSurfaceH = gRenderSurfaceH;
    testData->dt = gDt;
}

static void setupOffscreenTarget() {
    rsgBindColorTarget(gRenderBufferColor, 0);
    rsgBindDepthTarget(gRenderBufferDepth);
}

static void bindProgramVertexOrtho() {
    // Default vertex shader
    rsgBindProgramVertex(gProgVertex);
    // Setup the projection matrix
    rs_matrix4x4 proj;
    rsMatrixLoadOrtho(&proj, 0, gRenderSurfaceW, gRenderSurfaceH, 0, -500, 500);
    rsgProgramVertexLoadProjectionMatrix(&proj);
}

static void runSubTest(int index) {
    TestData testData;
    fillSurfaceParams(&testData);

    rs_allocation null_alloc;
    rsForEach(gTestScripts[index].testScript,
              gTestScripts[index].testData,
              null_alloc,
              &testData,
              sizeof(testData));
}


static bool checkInit() {

    static int countdown = 3;

    // Perform all the uploads so we only measure rendered time
    if(countdown > 1) {
        int testCount = rsAllocationGetDimX(rsGetAllocation(gTestScripts));
        for(int i = 0; i < testCount; i ++) {
            rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f);
            runSubTest(i);
            rsgFinish();
        }
        countdown --;
        rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f);

        rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
        rsgBindFont(gFontSerif);
        if (countdown == 1) {
            rsgDrawText("Rendering", 50, 50);
        } else {
            rsgDrawText("Initializing", 50, 50);
        }

        return false;
    }

    return true;
}

static int benchMode = 0;
static bool benchmarkSingleTest = false;
static int benchSubMode = 0;
static int runningLoops = 0;
static bool sendMsgFlag = false;

static bool gIsDebugMode = false;
void setDebugMode(int testNumber) {
    gIsDebugMode = true;
    benchMode = testNumber;
    rsgClearAllRenderTargets();
}

void setBenchmarkMode(int testNumber) {
    gIsDebugMode = false;
    if (testNumber == -1) {
        benchmarkSingleTest = false;
        benchMode = 0;
    } else {
        benchmarkSingleTest = true;
        benchMode = testNumber;
    }

    runningLoops = 0;
}

static void drawOffscreenResult(int posX, int posY, int width, int height) {
    bindProgramVertexOrtho();

    rs_matrix4x4 matrix;
    rsMatrixLoadIdentity(&matrix);
    rsgProgramVertexLoadModelMatrix(&matrix);

    rsgBindProgramFragment(gProgFragmentTexture);

    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
    rsgBindTexture(gProgFragmentTexture, 0, gRenderBufferColor);

    float startX = posX, startY = posY;
    rsgDrawQuadTexCoords(startX, startY, 0, 0, 1,
                         startX, startY + height, 0, 0, 0,
                         startX + width, startY + height, 0, 1, 0,
                         startX + width, startY, 0, 1, 1);
}

static void benchmark() {

    gDt = 1.0f / 60.0f;

    rsgFinish();
    int64_t start = rsUptimeMillis();

    int drawPos = 0;
    int frameCount = 100;
    for(int i = 0; i < frameCount; i ++) {
        setupOffscreenTarget();
        gRenderSurfaceW = rsAllocationGetDimX(gRenderBufferColor);
        gRenderSurfaceH = rsAllocationGetDimY(gRenderBufferColor);
        rsgClearColor(0.1f, 0.1f, 0.1f, 1.0f);
        rsgClearDepth(1.0f);

        runSubTest(benchMode);
        rsgClearAllRenderTargets();
        gRenderSurfaceW = rsgGetWidth();
        gRenderSurfaceH = rsgGetHeight();
        int size = 8;
        // draw each frame at (8, 3/4 gRenderSurfaceH) with size
        drawOffscreenResult((drawPos+=size)%gRenderSurfaceW, (gRenderSurfaceH * 3) / 4, size, size);
    }

    rsgFinish();

    int64_t end = rsUptimeMillis();
    float fps = (float)(frameCount) / ((float)(end - start)*0.001f);
    const char *testName = rsGetElementAt(gTestScripts[benchMode].debugName, 0);
    rsDebug(testName, fps);

    gResultBuffer[benchMode] = fps;
    int bufferW = rsAllocationGetDimX(gRenderBufferColor);
    int bufferH = rsAllocationGetDimY(gRenderBufferColor);

    int quadW = gRenderSurfaceW / 2;
    int quadH = (quadW * bufferH) / bufferW;
    drawOffscreenResult(0, 0, quadW, quadH);

    int left = 0, right = 0, top = 0, bottom = 0;
    uint width = rsgGetWidth();
    uint height = rsgGetHeight();
    rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
    rsgBindFont(gFontSerif);
    rsgMeasureText(gTestScripts[benchMode].testName, &left, &right, &top, &bottom);
    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
    rsgDrawText(gTestScripts[benchMode].testName, 2 -left, height - 2 + bottom);

    if (benchmarkSingleTest) {
        return;
    }

    benchMode ++;
    int testCount = rsAllocationGetDimX(rsGetAllocation(gTestScripts));
    if (benchMode == testCount) {
        rsSendToClientBlocking(RS_MSG_RESULTS_READY, gResultBuffer, testCount*sizeof(float));
        benchMode = 0;
        runningLoops++;
        if ((gMaxLoops > 0) && (runningLoops > gMaxLoops) && !sendMsgFlag) {
            //Notifiy the test to stop and get results
            rsDebug("gMaxLoops and runningLoops: ", gMaxLoops, runningLoops);
            rsSendToClientBlocking(RS_MSG_TEST_DONE);
            sendMsgFlag = true;
        }
    }
}

static void debug() {
    gDt = rsGetDt();
    runSubTest(benchMode);
}

int root(void) {
    gRenderSurfaceW = rsgGetWidth();
    gRenderSurfaceH = rsgGetHeight();
    rsgClearColor(0.2f, 0.2f, 0.2f, 1.0f);
    rsgClearDepth(1.0f);

    if (!gLoadComplete) {
        rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
        rsgBindFont(gFontSerif);
        rsgDrawText("Loading", 50, 50);
        return 0;
    }

    if(!checkInit()) {
        return 1;
    }

    if (gPauseRendering) {
        rsgDrawText("Paused", 50, 50);
        return 30;
    }
    if (gIsDebugMode) {
        debug();
    } else {
        benchmark();
    }

    return 1;
}
