/*
 * 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&, 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&, 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, 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, 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) {
    // protected method, that doesn't setup mUnitMatrix - should be handled by subclass

    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
