/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GLBench.h"

#if SK_SUPPORT_GPU
#include "GrGpu.h"
#include "GrTest.h"
#include "gl/GrGLContext.h"
#include "gl/builders/GrGLShaderStringBuilder.h"
#include "SkSLCompiler.h"
#include <stdio.h>
#include <string>

const GrGLContext* GLBench::getGLContext(SkCanvas* canvas) {
    // This bench exclusively tests GL calls directly
    if (nullptr == canvas->getGrContext()) {
        return nullptr;
    }
    GrContext* context = canvas->getGrContext();
    GrGpu* gpu = context->getGpu();
    if (!gpu) {
        SkDebugf("Couldn't get Gr gpu.");
        return nullptr;
    }

    const GrGLContext* ctx = gpu->glContextForTesting();
    if (!ctx) {
        SkDebugf("Couldn't get an interface\n");
        return nullptr;
    }

    return this->onGetGLContext(ctx);
}

void GLBench::onPreDraw(SkCanvas* canvas) {
    // This bench exclusively tests GL calls directly
    const GrGLContext* ctx = this->getGLContext(canvas);
    if (!ctx) {
        return;
    }
    this->setup(ctx);
}

void GLBench::onPostDraw(SkCanvas* canvas) {
    // This bench exclusively tests GL calls directly
    const GrGLContext* ctx = this->getGLContext(canvas);
    if (!ctx) {
        return;
    }
    this->teardown(ctx->interface());
}

void GLBench::onDraw(int loops, SkCanvas* canvas) {
    const GrGLContext* ctx = this->getGLContext(canvas);
    if (!ctx) {
        return;
    }
    this->glDraw(loops, ctx);
    canvas->getGrContext()->resetContext();
}

GrGLuint GLBench::CompileShader(const GrGLContext* context, const char* sksl, GrGLenum type) {
    const GrGLInterface* gl = context->interface();
    std::string glsl;
    bool result = context->compiler()->toGLSL(type == GR_GL_VERTEX_SHADER 
                                                                    ? SkSL::Program::kVertex_Kind
                                                                    : SkSL::Program::kFragment_Kind,
                                              std::string(sksl),
                                              *context->caps()->glslCaps(),
                                              &glsl);
    if (!result) {
        SkDebugf("SkSL compilation failed:\n%s\n%s\n", sksl, 
                 context->compiler()->errorText().c_str());
    }
    GrGLuint shader;
    // Create the shader object
    GR_GL_CALL_RET(gl, shader, CreateShader(type));

    // Load the shader source
    const char* glslPtr = glsl.c_str();
    GR_GL_CALL(gl, ShaderSource(shader, 1, (const char**) &glslPtr, nullptr));

    // Compile the shader
    GR_GL_CALL(gl, CompileShader(shader));

    // Check for compile time errors
    GrGLint success = GR_GL_INIT_ZERO;
    GrGLchar infoLog[512];
    GR_GL_CALL(gl, GetShaderiv(shader, GR_GL_COMPILE_STATUS, &success));
    if (!success) {
        GR_GL_CALL(gl, GetShaderInfoLog(shader, 512, nullptr, infoLog));
        SkDebugf("ERROR::SHADER::COMPLIATION_FAILED: %s\n", infoLog);
    }

    return shader;
}

GrGLuint GLBench::CreateProgram(const GrGLContext* context, const char* vshader, 
                                const char* fshader) {
    const GrGLInterface* gl = context->interface();
    GrGLuint vertexShader = CompileShader(context, vshader, GR_GL_VERTEX_SHADER);
    GrGLuint fragmentShader = CompileShader(context, fshader, GR_GL_FRAGMENT_SHADER);

    GrGLuint shaderProgram;
    GR_GL_CALL_RET(gl, shaderProgram, CreateProgram());
    GR_GL_CALL(gl, AttachShader(shaderProgram, vertexShader));
    GR_GL_CALL(gl, AttachShader(shaderProgram, fragmentShader));
    GR_GL_CALL(gl, LinkProgram(shaderProgram));

    // Check for linking errors
    GrGLint success = GR_GL_INIT_ZERO;
    GrGLchar infoLog[512];
    GR_GL_CALL(gl, GetProgramiv(shaderProgram, GR_GL_LINK_STATUS, &success));
    if (!success) {
        GR_GL_CALL(gl, GetProgramInfoLog(shaderProgram, 512, nullptr, infoLog));
        SkDebugf("Linker Error: %s\n", infoLog);
    }
    GR_GL_CALL(gl, DeleteShader(vertexShader));
    GR_GL_CALL(gl, DeleteShader(fragmentShader));

    return shaderProgram;
}

GrGLuint GLBench::SetupFramebuffer(const GrGLInterface* gl, int screenWidth, int screenHeight) {
    //Setup framebuffer
    GrGLuint texture;
    GR_GL_CALL(gl, GenTextures(1, &texture));
    GR_GL_CALL(gl, ActiveTexture(GR_GL_TEXTURE7));
    GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, texture));
    GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MAG_FILTER, GR_GL_NEAREST));
    GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
    GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_S, GR_GL_CLAMP_TO_EDGE));
    GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_T, GR_GL_CLAMP_TO_EDGE));
    GR_GL_CALL(gl, TexImage2D(GR_GL_TEXTURE_2D,
                              0, //level
                              GR_GL_RGBA, //internal format
                              screenWidth, // width
                              screenHeight, // height
                              0, //border
                              GR_GL_RGBA, //format
                              GR_GL_UNSIGNED_BYTE, // type
                              nullptr));

    // bind framebuffer
    GrGLuint framebuffer;
    GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0));
    GR_GL_CALL(gl, GenFramebuffers(1, &framebuffer));
    GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, framebuffer));
    GR_GL_CALL(gl, FramebufferTexture2D(GR_GL_FRAMEBUFFER,
                                        GR_GL_COLOR_ATTACHMENT0,
                                        GR_GL_TEXTURE_2D,
                                        texture, 0));
    GR_GL_CALL(gl, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
    GR_GL_CALL(gl, Viewport(0, 0, screenWidth, screenHeight));
    return texture;
}


void GLBench::DumpImage(const GrGLInterface* gl, uint32_t screenWidth, uint32_t screenHeight,
                        const char* filename) {
    // read back pixels
    SkAutoTArray<uint32_t> readback(screenWidth * screenHeight);
    GR_GL_CALL(gl, ReadPixels(0, // x
                              0, // y
                              screenWidth, // width
                              screenHeight, // height
                              GR_GL_RGBA, //format
                              GR_GL_UNSIGNED_BYTE, //type
                              readback.get()));

    // dump png
    SkBitmap bm;
    if (!bm.tryAllocPixels(SkImageInfo::MakeN32Premul(screenWidth, screenHeight))) {
        SkDebugf("couldn't allocate bitmap\n");
        return;
    }

    bm.setPixels(readback.get());

    if (!SkImageEncoder::EncodeFile(filename, bm, SkImageEncoder::kPNG_Type, 100)) {
        SkDebugf("------ failed to encode %s\n", filename);
        remove(filename);   // remove any partial file
        return;
    }
}

#endif
