/*
 * 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.
 */

#include "SkiaShader.h"

#include "Caches.h"
#include "Extensions.h"
#include "Layer.h"
#include "Matrix.h"
#include "Texture.h"

#include <SkMatrix.h>
#include <utils/Log.h>

namespace android {
namespace uirenderer {

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

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

static_assert(gTileModes[SkShader::kClamp_TileMode] == GL_CLAMP_TO_EDGE,
        "SkShader TileModes have changed");
static_assert(gTileModes[SkShader::kRepeat_TileMode] == GL_REPEAT,
        "SkShader TileModes have changed");
static_assert(gTileModes[SkShader::kMirror_TileMode] == GL_MIRRORED_REPEAT,
        "SkShader TileModes have changed");

/**
 * 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, FloatColor color) {
    glUniform4fv(slot, 1, reinterpret_cast<const float*>(&color));
}

static inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) {
    caches->textureState().bindTexture(texture->id);
    texture->setWrapST(wrapS, wrapT);
}

/**
 * Compute the matrix to transform to screen space.
 * @param screenSpace Output param for the computed matrix.
 * @param unitMatrix The unit matrix for gradient shaders, as returned by SkShader::asAGradient,
 *      or identity.
 * @param localMatrix Local matrix, as returned by SkShader::getLocalMatrix().
 * @param modelViewMatrix Model view matrix, as supplied by the OpenGLRenderer.
 */
static void computeScreenSpaceMatrix(mat4& screenSpace, const SkMatrix& unitMatrix,
        const SkMatrix& localMatrix, const mat4& modelViewMatrix) {
    mat4 shaderMatrix;
    // uses implicit construction
    shaderMatrix.loadInverse(localMatrix);
    // again, uses implicit construction
    screenSpace.loadMultiply(unitMatrix, shaderMatrix);
    screenSpace.multiply(modelViewMatrix);
}

///////////////////////////////////////////////////////////////////////////////
// gradient shader matrix helpers
///////////////////////////////////////////////////////////////////////////////

static void toLinearUnitMatrix(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);
}

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);
}

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

///////////////////////////////////////////////////////////////////////////////
// Common gradient code
///////////////////////////////////////////////////////////////////////////////

static bool isSimpleGradient(const SkShader::GradientInfo& gradInfo) {
    return gradInfo.fColorCount == 2 && gradInfo.fTileMode == SkShader::kClamp_TileMode;
}

///////////////////////////////////////////////////////////////////////////////
// Store / apply
///////////////////////////////////////////////////////////////////////////////

bool tryStoreGradient(Caches& caches, const SkShader& shader, const Matrix4 modelViewMatrix,
        GLuint* textureUnit, ProgramDescription* description,
        SkiaShaderData::GradientShaderData* outData) {
    SkShader::GradientInfo gradInfo;
    gradInfo.fColorCount = 0;
    gradInfo.fColors = nullptr;
    gradInfo.fColorOffsets = nullptr;

    SkMatrix unitMatrix;
    switch (shader.asAGradient(&gradInfo)) {
        case SkShader::kLinear_GradientType:
            description->gradientType = ProgramDescription::kGradientLinear;

            toLinearUnitMatrix(gradInfo.fPoint, &unitMatrix);
            break;
        case SkShader::kRadial_GradientType:
            description->gradientType = ProgramDescription::kGradientCircular;

            toCircularUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY,
                    gradInfo.fRadius[0], &unitMatrix);
            break;
        case SkShader::kSweep_GradientType:
            description->gradientType = ProgramDescription::kGradientSweep;

            toSweepUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, &unitMatrix);
            break;
        default:
            // Do nothing. This shader is unsupported.
            return false;
    }
    description->hasGradient = true;
    description->isSimpleGradient = isSimpleGradient(gradInfo);

    computeScreenSpaceMatrix(outData->screenSpace, unitMatrix,
            shader.getLocalMatrix(), modelViewMatrix);

    // re-query shader to get full color / offset data
    std::unique_ptr<SkColor[]> colorStorage(new SkColor[gradInfo.fColorCount]);
    std::unique_ptr<SkScalar[]> colorOffsets(new SkScalar[gradInfo.fColorCount]);
    gradInfo.fColors = &colorStorage[0];
    gradInfo.fColorOffsets = &colorOffsets[0];
    shader.asAGradient(&gradInfo);

    if (CC_UNLIKELY(!isSimpleGradient(gradInfo))) {
        outData->gradientSampler = (*textureUnit)++;

#ifndef SK_SCALAR_IS_FLOAT
    #error Need to convert gradInfo.fColorOffsets to float!
#endif
        outData->gradientTexture = caches.gradientCache.get(
                gradInfo.fColors, gradInfo.fColorOffsets, gradInfo.fColorCount);
        outData->wrapST = gTileModes[gradInfo.fTileMode];
    } else {
        outData->gradientSampler = 0;
        outData->gradientTexture = nullptr;

        outData->startColor.set(gradInfo.fColors[0]);
        outData->endColor.set(gradInfo.fColors[1]);
    }

    outData->ditherSampler = (*textureUnit)++;
    return true;
}

void applyGradient(Caches& caches, const SkiaShaderData::GradientShaderData& data) {
    if (CC_UNLIKELY(data.gradientTexture)) {
        caches.textureState().activateTexture(data.gradientSampler);
        bindTexture(&caches, data.gradientTexture, data.wrapST, data.wrapST);
        glUniform1i(caches.program().getUniform("gradientSampler"), data.gradientSampler);
    } else {
        bindUniformColor(caches.program().getUniform("startColor"), data.startColor);
        bindUniformColor(caches.program().getUniform("endColor"), data.endColor);
    }

    // TODO: remove sampler slot incrementing from dither.setupProgram,
    // since this assignment of slots is done at store, not apply time
    GLuint ditherSampler = data.ditherSampler;
    caches.dither.setupProgram(caches.program(), &ditherSampler);
    glUniformMatrix4fv(caches.program().getUniform("screenSpace"), 1,
            GL_FALSE, &data.screenSpace.data[0]);
}

bool tryStoreBitmap(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
        GLuint* textureUnit, ProgramDescription* description,
        SkiaShaderData::BitmapShaderData* outData) {
    SkBitmap bitmap;
    SkShader::TileMode xy[2];
    if (!shader.isABitmap(&bitmap, nullptr, xy)) {
        return false;
    }

    /*
     * Bypass the AssetAtlas, since those textures:
     * 1) require UV mapping, which isn't implemented in matrix computation below
     * 2) can't handle REPEAT simply
     * 3) are safe to upload here (outside of sync stage), since they're static
     */
    outData->bitmapTexture = caches.textureCache.getAndBypassAtlas(&bitmap);
    if (!outData->bitmapTexture) return false;

    outData->bitmapSampler = (*textureUnit)++;

    const float width = outData->bitmapTexture->width;
    const float height = outData->bitmapTexture->height;

    description->hasBitmap = true;
    if (!caches.extensions().hasNPot()
            && (!isPowerOfTwo(width) || !isPowerOfTwo(height))
            && (xy[0] != SkShader::kClamp_TileMode || xy[1] != SkShader::kClamp_TileMode)) {
        description->isBitmapNpot = true;
        description->bitmapWrapS = gTileModes[xy[0]];
        description->bitmapWrapT = gTileModes[xy[1]];

        outData->wrapS = GL_CLAMP_TO_EDGE;
        outData->wrapT = GL_CLAMP_TO_EDGE;
    } else {
        outData->wrapS = gTileModes[xy[0]];
        outData->wrapT = gTileModes[xy[1]];
    }

    computeScreenSpaceMatrix(outData->textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
            modelViewMatrix);
    outData->textureDimension[0] = 1.0f / width;
    outData->textureDimension[1] = 1.0f / height;

    return true;
}

void applyBitmap(Caches& caches, const SkiaShaderData::BitmapShaderData& data) {
    caches.textureState().activateTexture(data.bitmapSampler);
    bindTexture(&caches, data.bitmapTexture, data.wrapS, data.wrapT);
    data.bitmapTexture->setFilter(GL_LINEAR);

    glUniform1i(caches.program().getUniform("bitmapSampler"), data.bitmapSampler);
    glUniformMatrix4fv(caches.program().getUniform("textureTransform"), 1, GL_FALSE,
            &data.textureTransform.data[0]);
    glUniform2fv(caches.program().getUniform("textureDimension"), 1, &data.textureDimension[0]);
}

SkiaShaderType getComposeSubType(const SkShader& shader) {
    // First check for a gradient shader.
    switch (shader.asAGradient(nullptr)) {
        case SkShader::kNone_GradientType:
            // Not a gradient shader. Fall through to check for other types.
            break;
        case SkShader::kLinear_GradientType:
        case SkShader::kRadial_GradientType:
        case SkShader::kSweep_GradientType:
            return kGradient_SkiaShaderType;
        default:
            // This is a Skia gradient that has no SkiaShader equivalent. Return None to skip.
            return kNone_SkiaShaderType;
    }

    // The shader is not a gradient. Check for a bitmap shader.
    if (shader.isABitmap()) {
        return kBitmap_SkiaShaderType;
    }
    return kNone_SkiaShaderType;
}

void storeCompose(Caches& caches, const SkShader& bitmapShader, const SkShader& gradientShader,
        const Matrix4& modelViewMatrix, GLuint* textureUnit,
        ProgramDescription* description, SkiaShaderData* outData) {
    LOG_ALWAYS_FATAL_IF(!tryStoreBitmap(caches, bitmapShader, modelViewMatrix,
                textureUnit, description, &outData->bitmapData),
            "failed storing bitmap shader data");
    LOG_ALWAYS_FATAL_IF(!tryStoreGradient(caches, gradientShader, modelViewMatrix,
                textureUnit, description, &outData->gradientData),
            "failing storing gradient shader data");
}

bool tryStoreCompose(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
        GLuint* textureUnit, ProgramDescription* description,
        SkiaShaderData* outData) {

    SkShader::ComposeRec rec;
    if (!shader.asACompose(&rec)) return false;

    const SkiaShaderType shaderAType = getComposeSubType(*rec.fShaderA);
    const SkiaShaderType shaderBType = getComposeSubType(*rec.fShaderB);

    // check that type enum values are the 2 flags that compose the kCompose value
    if ((shaderAType & shaderBType) != 0) return false;
    if ((shaderAType | shaderBType) != kCompose_SkiaShaderType) return false;

    mat4 transform;
    computeScreenSpaceMatrix(transform, SkMatrix::I(), shader.getLocalMatrix(), modelViewMatrix);
    if (shaderAType == kBitmap_SkiaShaderType) {
        description->isBitmapFirst = true;
        storeCompose(caches, *rec.fShaderA, *rec.fShaderB,
                transform, textureUnit, description, outData);
    } else {
        description->isBitmapFirst = false;
        storeCompose(caches, *rec.fShaderB, *rec.fShaderA,
                transform, textureUnit, description, outData);
    }
    if (!SkXfermode::AsMode(rec.fMode, &description->shadersMode)) {
        // TODO: Support other modes.
        description->shadersMode = SkXfermode::kSrcOver_Mode;
    }
    return true;
}

bool tryStoreLayer(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
        GLuint* textureUnit, ProgramDescription* description,
        SkiaShaderData::LayerShaderData* outData) {
    Layer* layer;
    if (!shader.asACustomShader(reinterpret_cast<void**>(&layer))) {
        return false;
    }

    description->hasBitmap = true;
    outData->layer = layer;
    outData->bitmapSampler = (*textureUnit)++;

    const float width = layer->getWidth();
    const float height = layer->getHeight();

    computeScreenSpaceMatrix(outData->textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
            modelViewMatrix);

    outData->textureDimension[0] = 1.0f / width;
    outData->textureDimension[1] = 1.0f / height;
    return true;
}

void applyLayer(Caches& caches, const SkiaShaderData::LayerShaderData& data) {
    caches.textureState().activateTexture(data.bitmapSampler);

    data.layer->bindTexture();
    data.layer->setWrap(GL_CLAMP_TO_EDGE);
    data.layer->setFilter(GL_LINEAR);

    glUniform1i(caches.program().getUniform("bitmapSampler"), data.bitmapSampler);
    glUniformMatrix4fv(caches.program().getUniform("textureTransform"), 1,
            GL_FALSE, &data.textureTransform.data[0]);
    glUniform2fv(caches.program().getUniform("textureDimension"), 1, &data.textureDimension[0]);
}

void SkiaShader::store(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
        GLuint* textureUnit, ProgramDescription* description,
        SkiaShaderData* outData) {
    if (tryStoreGradient(caches, shader, modelViewMatrix,
            textureUnit, description, &outData->gradientData)) {
        outData->skiaShaderType = kGradient_SkiaShaderType;
        return;
    }

    if (tryStoreBitmap(caches, shader, modelViewMatrix,
            textureUnit, description, &outData->bitmapData)) {
        outData->skiaShaderType = kBitmap_SkiaShaderType;
        return;
    }

    if (tryStoreCompose(caches, shader, modelViewMatrix,
            textureUnit, description, outData)) {
        outData->skiaShaderType = kCompose_SkiaShaderType;
        return;
    }

    if (tryStoreLayer(caches, shader, modelViewMatrix,
            textureUnit, description, &outData->layerData)) {
        outData->skiaShaderType = kLayer_SkiaShaderType;
        return;
    }

    // Unknown/unsupported type, so explicitly ignore shader
    outData->skiaShaderType = kNone_SkiaShaderType;
}

void SkiaShader::apply(Caches& caches, const SkiaShaderData& data) {
    if (!data.skiaShaderType) return;

    if (data.skiaShaderType & kGradient_SkiaShaderType) {
        applyGradient(caches, data.gradientData);
    }
    if (data.skiaShaderType & kBitmap_SkiaShaderType) {
        applyBitmap(caches, data.bitmapData);
    }

    if (data.skiaShaderType == kLayer_SkiaShaderType) {
        applyLayer(caches, data.layerData);
    }
}

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