/*
 * Copyright (C) 2010 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.
 */

#define LOG_TAG "OpenGLRenderer"

#include <utils/Log.h>

#include <SkMatrix.h>

#include "Caches.h"
#include "SkiaShader.h"
#include "Texture.h"
#include "Matrix.h"

namespace android {
namespace uirenderer {

///////////////////////////////////////////////////////////////////////////////
// Support
///////////////////////////////////////////////////////////////////////////////

static const GLint gTileModes[] = {
        GL_CLAMP_TO_EDGE,   // == SkShader::kClamp_TileMode
        GL_REPEAT,          // == SkShader::kRepeat_Mode
        GL_MIRRORED_REPEAT  // == SkShader::kMirror_TileMode
};

/**
 * This function does not work for n == 0.
 */
static inline bool isPowerOfTwo(unsigned int n) {
    return !(n & (n - 1));
}

static inline void bindUniformColor(int slot, uint32_t color) {
    const float a = ((color >> 24) & 0xff) / 255.0f;
    glUniform4f(slot,
            a * ((color >> 16) & 0xff) / 255.0f,
            a * ((color >>  8) & 0xff) / 255.0f,
            a * ((color      ) & 0xff) / 255.0f,
            a);
}

///////////////////////////////////////////////////////////////////////////////
// Base shader
///////////////////////////////////////////////////////////////////////////////

void SkiaShader::copyFrom(const SkiaShader& shader) {
    mType = shader.mType;
    mKey = shader.mKey;
    mTileX = shader.mTileX;
    mTileY = shader.mTileY;
    mBlend = shader.mBlend;
    mUnitMatrix = shader.mUnitMatrix;
    mShaderMatrix = shader.mShaderMatrix;
    mGenerationId = shader.mGenerationId;
}

SkiaShader::SkiaShader(): mCaches(NULL) {
}

SkiaShader::SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX,
        SkShader::TileMode tileY, SkMatrix* matrix, bool blend):
        mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mBlend(blend),
        mCaches(NULL) {
    setMatrix(matrix);
    mGenerationId = 0;
}

SkiaShader::~SkiaShader() {
}

void SkiaShader::describe(ProgramDescription& description, const Extensions& extensions) {
}

void SkiaShader::setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
        GLuint* textureUnit) {
}

void SkiaShader::bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT) {
    mCaches->bindTexture(texture->id);
    texture->setWrapST(wrapS, wrapT);
}

void SkiaShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) {
    screenSpace.loadMultiply(mUnitMatrix, mShaderMatrix);
    screenSpace.multiply(modelView);
}

///////////////////////////////////////////////////////////////////////////////
// Bitmap shader
///////////////////////////////////////////////////////////////////////////////

SkiaBitmapShader::SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX,
        SkShader::TileMode tileY, SkMatrix* matrix, bool blend):
        SkiaShader(kBitmap, key, tileX, tileY, matrix, blend), mBitmap(bitmap), mTexture(NULL) {
    updateLocalMatrix(matrix);
}

SkiaShader* SkiaBitmapShader::copy() {
    SkiaBitmapShader* copy = new SkiaBitmapShader();
    copy->copyFrom(*this);
    copy->mBitmap = mBitmap;
    return copy;
}

void SkiaBitmapShader::describe(ProgramDescription& description, const Extensions& extensions) {
    Texture* texture = mCaches->textureCache.get(mBitmap);
    if (!texture) return;
    mTexture = texture;

    const float width = texture->width;
    const float height = texture->height;

    description.hasBitmap = true;
    // The driver does not support non-power of two mirrored/repeated
    // textures, so do it ourselves
    if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) &&
            (mTileX != SkShader::kClamp_TileMode || mTileY != SkShader::kClamp_TileMode)) {
        description.isBitmapNpot = true;
        description.bitmapWrapS = gTileModes[mTileX];
        description.bitmapWrapT = gTileModes[mTileY];
        mWrapS = GL_CLAMP_TO_EDGE;
        mWrapT = GL_CLAMP_TO_EDGE;
    } else {
        mWrapS = gTileModes[mTileX];
        mWrapT = gTileModes[mTileY];
    }
}

void SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView,
        const Snapshot& snapshot, GLuint* textureUnit) {
    GLuint textureSlot = (*textureUnit)++;
    Caches::getInstance().activeTexture(textureSlot);

    Texture* texture = mTexture;
    mTexture = NULL;
    if (!texture) return;
    const AutoTexture autoCleanup(texture);

    const float width = texture->width;
    const float height = texture->height;

    mat4 textureTransform;
    computeScreenSpaceMatrix(textureTransform, modelView);

    // Uniforms
    bindTexture(texture, mWrapS, mWrapT);
    texture->setFilter(GL_LINEAR);

    glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
    glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
            GL_FALSE, &textureTransform.data[0]);
    glUniform2f(program->getUniform("textureDimension"), 1.0f / width, 1.0f / height);
}

///////////////////////////////////////////////////////////////////////////////
// Linear gradient shader
///////////////////////////////////////////////////////////////////////////////

static void toUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) {
    SkVector vec = pts[1] - pts[0];
    const float mag = vec.length();
    const float inv = mag ? 1.0f / mag : 0;

    vec.scale(inv);
    matrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY);
    matrix->postTranslate(-pts[0].fX, -pts[0].fY);
    matrix->postScale(inv, inv);
}

SkiaLinearGradientShader::SkiaLinearGradientShader(float* bounds, uint32_t* colors,
        float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
        SkMatrix* matrix, bool blend):
        SkiaShader(kLinearGradient, key, tileMode, tileMode, matrix, blend),
        mBounds(bounds), mColors(colors), mPositions(positions), mCount(count) {
    SkPoint points[2];
    points[0].set(bounds[0], bounds[1]);
    points[1].set(bounds[2], bounds[3]);

    SkMatrix unitMatrix;
    toUnitMatrix(points, &unitMatrix);
    mUnitMatrix.load(unitMatrix);

    updateLocalMatrix(matrix);

    mIsSimple = count == 2 && tileMode == SkShader::kClamp_TileMode;
}

SkiaLinearGradientShader::~SkiaLinearGradientShader() {
    delete[] mBounds;
    delete[] mColors;
    delete[] mPositions;
}

SkiaShader* SkiaLinearGradientShader::copy() {
    SkiaLinearGradientShader* copy = new SkiaLinearGradientShader();
    copy->copyFrom(*this);
    copy->mBounds = new float[4];
    memcpy(copy->mBounds, mBounds, sizeof(float) * 4);
    copy->mColors = new uint32_t[mCount];
    memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
    copy->mPositions = new float[mCount];
    memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
    copy->mCount = mCount;
    copy->mIsSimple = mIsSimple;
    return copy;
}

void SkiaLinearGradientShader::describe(ProgramDescription& description,
        const Extensions& extensions) {
    description.hasGradient = true;
    description.gradientType = ProgramDescription::kGradientLinear;
    description.isSimpleGradient = mIsSimple;
}

void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelView,
        const Snapshot& snapshot, GLuint* textureUnit) {
    if (CC_UNLIKELY(!mIsSimple)) {
        GLuint textureSlot = (*textureUnit)++;
        Caches::getInstance().activeTexture(textureSlot);

        Texture* texture = mCaches->gradientCache.get(mColors, mPositions, mCount);

        // Uniforms
        bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
        glUniform1i(program->getUniform("gradientSampler"), textureSlot);
    } else {
        bindUniformColor(program->getUniform("startColor"), mColors[0]);
        bindUniformColor(program->getUniform("endColor"), mColors[1]);
    }

    Caches::getInstance().dither.setupProgram(program, textureUnit);

    mat4 screenSpace;
    computeScreenSpaceMatrix(screenSpace, modelView);
    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
}

///////////////////////////////////////////////////////////////////////////////
// Circular gradient shader
///////////////////////////////////////////////////////////////////////////////

static void toCircularUnitMatrix(const float x, const float y, const float radius,
        SkMatrix* matrix) {
    const float inv = 1.0f / radius;
    matrix->setTranslate(-x, -y);
    matrix->postScale(inv, inv);
}

SkiaCircularGradientShader::SkiaCircularGradientShader(float x, float y, float radius,
        uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
        SkMatrix* matrix, bool blend):
        SkiaSweepGradientShader(kCircularGradient, x, y, colors, positions, count, key,
                tileMode, matrix, blend) {
    SkMatrix unitMatrix;
    toCircularUnitMatrix(x, y, radius, &unitMatrix);
    mUnitMatrix.load(unitMatrix);

    updateLocalMatrix(matrix);
}

SkiaShader* SkiaCircularGradientShader::copy() {
    SkiaCircularGradientShader* copy = new SkiaCircularGradientShader();
    copy->copyFrom(*this);
    copy->mColors = new uint32_t[mCount];
    memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
    copy->mPositions = new float[mCount];
    memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
    copy->mCount = mCount;
    copy->mIsSimple = mIsSimple;
    return copy;
}

void SkiaCircularGradientShader::describe(ProgramDescription& description,
        const Extensions& extensions) {
    description.hasGradient = true;
    description.gradientType = ProgramDescription::kGradientCircular;
    description.isSimpleGradient = mIsSimple;
}

///////////////////////////////////////////////////////////////////////////////
// Sweep gradient shader
///////////////////////////////////////////////////////////////////////////////

static void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) {
    matrix->setTranslate(-x, -y);
}

SkiaSweepGradientShader::SkiaSweepGradientShader(float x, float y, uint32_t* colors,
        float* positions, int count, SkShader* key, SkMatrix* matrix, bool blend):
        SkiaShader(kSweepGradient, key, SkShader::kClamp_TileMode,
                SkShader::kClamp_TileMode, matrix, blend),
        mColors(colors), mPositions(positions), mCount(count) {
    SkMatrix unitMatrix;
    toSweepUnitMatrix(x, y, &unitMatrix);
    mUnitMatrix.load(unitMatrix);

    updateLocalMatrix(matrix);

    mIsSimple = count == 2;
}

SkiaSweepGradientShader::SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors,
        float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
        SkMatrix* matrix, bool blend):
        SkiaShader(type, key, tileMode, tileMode, matrix, blend),
        mColors(colors), mPositions(positions), mCount(count) {

    mIsSimple = count == 2 && tileMode == SkShader::kClamp_TileMode;
}

SkiaSweepGradientShader::~SkiaSweepGradientShader() {
    delete[] mColors;
    delete[] mPositions;
}

SkiaShader* SkiaSweepGradientShader::copy() {
    SkiaSweepGradientShader* copy = new SkiaSweepGradientShader();
    copy->copyFrom(*this);
    copy->mColors = new uint32_t[mCount];
    memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
    copy->mPositions = new float[mCount];
    memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
    copy->mCount = mCount;
    copy->mIsSimple = mIsSimple;
    return copy;
}

void SkiaSweepGradientShader::describe(ProgramDescription& description,
        const Extensions& extensions) {
    description.hasGradient = true;
    description.gradientType = ProgramDescription::kGradientSweep;
    description.isSimpleGradient = mIsSimple;
}

void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelView,
        const Snapshot& snapshot, GLuint* textureUnit) {
    if (CC_UNLIKELY(!mIsSimple)) {
        GLuint textureSlot = (*textureUnit)++;
        Caches::getInstance().activeTexture(textureSlot);

        Texture* texture = mCaches->gradientCache.get(mColors, mPositions, mCount);

        // Uniforms
        bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
        glUniform1i(program->getUniform("gradientSampler"), textureSlot);
    } else {
       bindUniformColor(program->getUniform("startColor"), mColors[0]);
       bindUniformColor(program->getUniform("endColor"), mColors[1]);
    }

    mCaches->dither.setupProgram(program, textureUnit);

    mat4 screenSpace;
    computeScreenSpaceMatrix(screenSpace, modelView);
    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
}

///////////////////////////////////////////////////////////////////////////////
// Compose shader
///////////////////////////////////////////////////////////////////////////////

SkiaComposeShader::SkiaComposeShader(SkiaShader* first, SkiaShader* second,
        SkXfermode::Mode mode, SkShader* key):
        SkiaShader(kCompose, key, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
        NULL, first->blend() || second->blend()),
        mFirst(first), mSecond(second), mMode(mode), mCleanup(false) {
}

SkiaComposeShader::~SkiaComposeShader() {
    if (mCleanup) {
        delete mFirst;
        delete mSecond;
    }
}

SkiaShader* SkiaComposeShader::copy() {
    SkiaComposeShader* copy = new SkiaComposeShader();
    copy->copyFrom(*this);
    copy->mFirst = mFirst->copy();
    copy->mSecond = mSecond->copy();
    copy->mMode = mMode;
    copy->cleanup();
    return copy;
}

void SkiaComposeShader::describe(ProgramDescription& description, const Extensions& extensions) {
    mFirst->describe(description, extensions);
    mSecond->describe(description, extensions);
    if (mFirst->type() == kBitmap) {
        description.isBitmapFirst = true;
    }
    description.shadersMode = mMode;
}

void SkiaComposeShader::setupProgram(Program* program, const mat4& modelView,
        const Snapshot& snapshot, GLuint* textureUnit) {
    // Apply this compose shader's local transform and pass it down to
    // the child shaders. They will in turn apply their local transform
    // to this matrix.
    mat4 transform;
    computeScreenSpaceMatrix(transform, modelView);

    mFirst->setupProgram(program, transform, snapshot, textureUnit);
    mSecond->setupProgram(program, transform, snapshot, textureUnit);
}

}; // namespace uirenderer
}; // namespace android
