/*
 * Copyright (C) 2015 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 "GlopBuilder.h"

#include "Caches.h"
#include "GlLayer.h"
#include "Glop.h"
#include "Layer.h"
#include "Matrix.h"
#include "Patch.h"
#include "PathCache.h"
#include "renderstate/MeshState.h"
#include "renderstate/RenderState.h"
#include "SkiaShader.h"
#include "Texture.h"
#include "utils/PaintUtils.h"
#include "VertexBuffer.h"

#include <GLES2/gl2.h>
#include <SkPaint.h>

#define DEBUG_GLOP_BUILDER 0

#if DEBUG_GLOP_BUILDER

#define TRIGGER_STAGE(stageFlag) \
    LOG_ALWAYS_FATAL_IF((stageFlag) & mStageFlags, "Stage %d cannot be run twice", (stageFlag)); \
    mStageFlags = static_cast<StageFlags>(mStageFlags | (stageFlag))

#define REQUIRE_STAGES(requiredFlags) \
    LOG_ALWAYS_FATAL_IF((mStageFlags & (requiredFlags)) != (requiredFlags), \
            "not prepared for current stage")

#else

#define TRIGGER_STAGE(stageFlag) ((void)0)
#define REQUIRE_STAGES(requiredFlags) ((void)0)

#endif

namespace android {
namespace uirenderer {

static void setUnitQuadTextureCoords(Rect uvs, TextureVertex* quadVertex) {
    quadVertex[0] = {0, 0, uvs.left, uvs.top};
    quadVertex[1] = {1, 0, uvs.right, uvs.top};
    quadVertex[2] = {0, 1, uvs.left, uvs.bottom};
    quadVertex[3] = {1, 1, uvs.right, uvs.bottom};
}

GlopBuilder::GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop)
        : mRenderState(renderState)
        , mCaches(caches)
        , mShader(nullptr)
        , mOutGlop(outGlop) {
    mStageFlags = kInitialStage;
}

////////////////////////////////////////////////////////////////////////////////
// Mesh
////////////////////////////////////////////////////////////////////////////////

GlopBuilder& GlopBuilder::setMeshTexturedIndexedVbo(GLuint vbo, GLsizei elementCount) {
    TRIGGER_STAGE(kMeshStage);

    mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
    mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr };
    mOutGlop->mesh.vertices = {
            vbo,
            VertexAttribFlags::TextureCoord,
            nullptr, (const void*) kMeshTextureOffset, nullptr,
            kTextureVertexStride };
    mOutGlop->mesh.elementCount = elementCount;
    return *this;
}

GlopBuilder& GlopBuilder::setMeshUnitQuad() {
    TRIGGER_STAGE(kMeshStage);

    mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
    mOutGlop->mesh.indices = { 0, nullptr };
    mOutGlop->mesh.vertices = {
            mRenderState.meshState().getUnitQuadVBO(),
            VertexAttribFlags::None,
            nullptr, nullptr, nullptr,
            kTextureVertexStride };
    mOutGlop->mesh.elementCount = 4;
    return *this;
}

GlopBuilder& GlopBuilder::setMeshTexturedUnitQuad(const UvMapper* uvMapper) {
    if (uvMapper) {
        // can't use unit quad VBO, so build UV vertices manually
        return setMeshTexturedUvQuad(uvMapper, Rect(1, 1));
    }

    TRIGGER_STAGE(kMeshStage);

    mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
    mOutGlop->mesh.indices = { 0, nullptr };
    mOutGlop->mesh.vertices = {
            mRenderState.meshState().getUnitQuadVBO(),
            VertexAttribFlags::TextureCoord,
            nullptr, (const void*) kMeshTextureOffset, nullptr,
            kTextureVertexStride };
    mOutGlop->mesh.elementCount = 4;
    return *this;
}

GlopBuilder& GlopBuilder::setMeshTexturedUvQuad(const UvMapper* uvMapper, Rect uvs) {
    TRIGGER_STAGE(kMeshStage);

    if (CC_UNLIKELY(uvMapper)) {
        uvMapper->map(uvs);
    }
    setUnitQuadTextureCoords(uvs, &mOutGlop->mesh.mappedVertices[0]);

    const TextureVertex* textureVertex = mOutGlop->mesh.mappedVertices;
    mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
    mOutGlop->mesh.indices = { 0, nullptr };
    mOutGlop->mesh.vertices = {
            0,
            VertexAttribFlags::TextureCoord,
            &textureVertex[0].x, &textureVertex[0].u, nullptr,
            kTextureVertexStride };
    mOutGlop->mesh.elementCount = 4;
    return *this;
}

GlopBuilder& GlopBuilder::setMeshIndexedQuads(Vertex* vertexData, int quadCount) {
    TRIGGER_STAGE(kMeshStage);

    mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
    mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr };
    mOutGlop->mesh.vertices = {
            0,
            VertexAttribFlags::None,
            vertexData, nullptr, nullptr,
            kVertexStride };
    mOutGlop->mesh.elementCount = 6 * quadCount;
    return *this;
}

GlopBuilder& GlopBuilder::setMeshTexturedIndexedQuads(TextureVertex* vertexData, int elementCount) {
    TRIGGER_STAGE(kMeshStage);

    mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
    mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr };
    mOutGlop->mesh.vertices = {
            0,
            VertexAttribFlags::TextureCoord,
            &vertexData[0].x, &vertexData[0].u, nullptr,
            kTextureVertexStride };
    mOutGlop->mesh.elementCount = elementCount;
    return *this;
}

GlopBuilder& GlopBuilder::setMeshColoredTexturedMesh(ColorTextureVertex* vertexData, int elementCount) {
    TRIGGER_STAGE(kMeshStage);

    mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
    mOutGlop->mesh.indices = { 0, nullptr };
    mOutGlop->mesh.vertices = {
            0,
            VertexAttribFlags::TextureCoord | VertexAttribFlags::Color,
            &vertexData[0].x, &vertexData[0].u, &vertexData[0].r,
            kColorTextureVertexStride };
    mOutGlop->mesh.elementCount = elementCount;
    return *this;
}

GlopBuilder& GlopBuilder::setMeshVertexBuffer(const VertexBuffer& vertexBuffer) {
    TRIGGER_STAGE(kMeshStage);

    const VertexBuffer::MeshFeatureFlags flags = vertexBuffer.getMeshFeatureFlags();

    bool alphaVertex = flags & VertexBuffer::kAlpha;
    bool indices = flags & VertexBuffer::kIndices;

    mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
    mOutGlop->mesh.indices = { 0, vertexBuffer.getIndices() };
    mOutGlop->mesh.vertices = {
            0,
            alphaVertex ? VertexAttribFlags::Alpha : VertexAttribFlags::None,
            vertexBuffer.getBuffer(), nullptr, nullptr,
            alphaVertex ? kAlphaVertexStride : kVertexStride };
    mOutGlop->mesh.elementCount = indices
                ? vertexBuffer.getIndexCount() : vertexBuffer.getVertexCount();
    mOutGlop->mesh.vertexCount = vertexBuffer.getVertexCount(); // used for glDrawRangeElements()
    return *this;
}

GlopBuilder& GlopBuilder::setMeshPatchQuads(const Patch& patch) {
    TRIGGER_STAGE(kMeshStage);

    mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
    mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr };
    mOutGlop->mesh.vertices = {
            mCaches.patchCache.getMeshBuffer(),
            VertexAttribFlags::TextureCoord,
            (void*)patch.positionOffset, (void*)patch.textureOffset, nullptr,
            kTextureVertexStride };
    mOutGlop->mesh.elementCount = patch.indexCount;
    return *this;
}

////////////////////////////////////////////////////////////////////////////////
// Fill
////////////////////////////////////////////////////////////////////////////////

void GlopBuilder::setFill(int color, float alphaScale,
        SkBlendMode mode, Blend::ModeOrderSwap modeUsage,
        const SkShader* shader, const SkColorFilter* colorFilter) {
    if (mode != SkBlendMode::kClear) {
        if (!shader) {
            FloatColor c;
            c.set(color);
            c.r *= alphaScale;
            c.g *= alphaScale;
            c.b *= alphaScale;
            c.a *= alphaScale;
            mOutGlop->fill.color = c;
        } else {
            float alpha = (SkColorGetA(color) / 255.0f) * alphaScale;
            mOutGlop->fill.color = { 1, 1, 1, alpha };
        }
    } else {
        mOutGlop->fill.color = { 0, 0, 0, 1 };
    }

    mOutGlop->blend = { GL_ZERO, GL_ZERO };
    if (mOutGlop->fill.color.a < 1.0f
            || (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Alpha)
            || (mOutGlop->fill.texture.texture && mOutGlop->fill.texture.texture->blend)
            || mOutGlop->roundRectClipState
            || PaintUtils::isBlendedShader(shader)
            || PaintUtils::isBlendedColorFilter(colorFilter)
            || mode != SkBlendMode::kSrcOver) {
        if (CC_LIKELY(mode <= SkBlendMode::kScreen)) {
            Blend::getFactors(mode, modeUsage,
                    &mOutGlop->blend.src, &mOutGlop->blend.dst);
        } else {
            // These blend modes are not supported by OpenGL directly and have
            // to be implemented using shaders. Since the shader will perform
            // the blending, don't enable GL blending off here
            // If the blend mode cannot be implemented using shaders, fall
            // back to the default SrcOver blend mode instead
            if (CC_UNLIKELY(mCaches.extensions().hasFramebufferFetch())) {
                mDescription.framebufferMode = mode;
                mDescription.swapSrcDst = (modeUsage == Blend::ModeOrderSwap::Swap);
                // blending in shader, don't enable
            } else {
                // unsupported
                Blend::getFactors(SkBlendMode::kSrcOver, modeUsage,
                        &mOutGlop->blend.src, &mOutGlop->blend.dst);
            }
        }
    }
    mShader = shader; // shader resolved in ::build()

    if (colorFilter) {
        SkColor color;
        SkBlendMode bmode;
        SkScalar srcColorMatrix[20];
        if (colorFilter->asColorMode(&color, &bmode)) {
            mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::ColorFilterMode::Blend;
            mDescription.colorMode = bmode;
            mOutGlop->fill.filter.color.set(color);
        } else if (colorFilter->asColorMatrix(srcColorMatrix)) {
            mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::ColorFilterMode::Matrix;

            float* colorMatrix = mOutGlop->fill.filter.matrix.matrix;
            memcpy(colorMatrix, srcColorMatrix, 4 * sizeof(float));
            memcpy(&colorMatrix[4], &srcColorMatrix[5], 4 * sizeof(float));
            memcpy(&colorMatrix[8], &srcColorMatrix[10], 4 * sizeof(float));
            memcpy(&colorMatrix[12], &srcColorMatrix[15], 4 * sizeof(float));

            // Skia uses the range [0..255] for the addition vector, but we need
            // the [0..1] range to apply the vector in GLSL
            float* colorVector = mOutGlop->fill.filter.matrix.vector;
            colorVector[0] = EOCF(srcColorMatrix[4]  / 255.0f);
            colorVector[1] = EOCF(srcColorMatrix[9]  / 255.0f);
            colorVector[2] = EOCF(srcColorMatrix[14] / 255.0f);
            colorVector[3] =      srcColorMatrix[19] / 255.0f;  // alpha is linear
        } else {
            ALOGE("unsupported ColorFilter type: %s", colorFilter->getTypeName());
            LOG_ALWAYS_FATAL("unsupported ColorFilter");
        }
    } else {
        mOutGlop->fill.filterMode = ProgramDescription::ColorFilterMode::None;
    }
}

GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture,
        const int textureFillFlags, const SkPaint* paint, float alphaScale) {
    TRIGGER_STAGE(kFillStage);
    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);

    GLenum filter = (textureFillFlags & TextureFillFlags::ForceFilter)
            ? GL_LINEAR : PaintUtils::getFilter(paint);
    mOutGlop->fill.texture = { &texture, filter, GL_CLAMP_TO_EDGE, nullptr };

    if (paint) {
        int color = paint->getColor();
        SkShader* shader = paint->getShader();

        if (!(textureFillFlags & TextureFillFlags::IsAlphaMaskTexture)) {
            // Texture defines color, so disable shaders, and reset all non-alpha color channels
            color |= 0x00FFFFFF;
            shader = nullptr;
        }
        setFill(color, alphaScale,
                paint->getBlendMode(), Blend::ModeOrderSwap::NoSwap,
                shader, paint->getColorFilter());
    } else {
        mOutGlop->fill.color = { alphaScale, alphaScale, alphaScale, alphaScale };

        if (alphaScale < 1.0f
                || (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Alpha)
                || texture.blend
                || mOutGlop->roundRectClipState) {
            Blend::getFactors(SkBlendMode::kSrcOver, Blend::ModeOrderSwap::NoSwap,
                    &mOutGlop->blend.src, &mOutGlop->blend.dst);
        } else {
            mOutGlop->blend = { GL_ZERO, GL_ZERO };
        }
    }

    if (textureFillFlags & TextureFillFlags::IsAlphaMaskTexture) {
        mDescription.modulate = mOutGlop->fill.color.isNotBlack();
        mDescription.hasAlpha8Texture = true;
    } else {
        mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
    }
    return *this;
}

GlopBuilder& GlopBuilder::setFillPaint(const SkPaint& paint, float alphaScale, bool shadowInterp) {
    TRIGGER_STAGE(kFillStage);
    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);

    if (CC_LIKELY(!shadowInterp)) {
        mOutGlop->fill.texture = {
                nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
    } else {
        mOutGlop->fill.texture = {
                mCaches.textureState().getShadowLutTexture(),
                GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
    }

    setFill(paint.getColor(), alphaScale,
            paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap,
            paint.getShader(), paint.getColorFilter());
    mDescription.useShadowAlphaInterp = shadowInterp;
    mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
    return *this;
}

GlopBuilder& GlopBuilder::setFillPathTexturePaint(PathTexture& texture,
        const SkPaint& paint, float alphaScale) {
    TRIGGER_STAGE(kFillStage);
    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);

    //specify invalid filter/clamp, since these are always static for PathTextures
    mOutGlop->fill.texture = { &texture, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };

    setFill(paint.getColor(), alphaScale,
            paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap,
            paint.getShader(), paint.getColorFilter());

    mDescription.hasAlpha8Texture = true;
    mDescription.modulate = mOutGlop->fill.color.isNotBlack();
    return *this;
}

GlopBuilder& GlopBuilder::setFillShadowTexturePaint(ShadowTexture& texture, int shadowColor,
        const SkPaint& paint, float alphaScale) {
    TRIGGER_STAGE(kFillStage);
    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);

    //specify invalid filter/clamp, since these are always static for ShadowTextures
    mOutGlop->fill.texture = { &texture, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };

    const int ALPHA_BITMASK = SK_ColorBLACK;
    const int COLOR_BITMASK = ~ALPHA_BITMASK;
    if ((shadowColor & ALPHA_BITMASK) == ALPHA_BITMASK) {
        // shadow color is fully opaque: override its alpha with that of paint
        shadowColor &= paint.getColor() | COLOR_BITMASK;
    }

    setFill(shadowColor, alphaScale,
            paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap,
            paint.getShader(), paint.getColorFilter());

    mDescription.hasAlpha8Texture = true;
    mDescription.modulate = mOutGlop->fill.color.isNotBlack();
    return *this;
}

GlopBuilder& GlopBuilder::setFillBlack() {
    TRIGGER_STAGE(kFillStage);
    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);

    mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
    setFill(SK_ColorBLACK, 1.0f, SkBlendMode::kSrcOver, Blend::ModeOrderSwap::NoSwap,
            nullptr, nullptr);
    return *this;
}

GlopBuilder& GlopBuilder::setFillClear() {
    TRIGGER_STAGE(kFillStage);
    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);

    mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
    setFill(SK_ColorBLACK, 1.0f, SkBlendMode::kClear, Blend::ModeOrderSwap::NoSwap,
            nullptr, nullptr);
    return *this;
}

GlopBuilder& GlopBuilder::setFillLayer(Texture& texture, const SkColorFilter* colorFilter,
        float alpha, SkBlendMode mode, Blend::ModeOrderSwap modeUsage) {
    TRIGGER_STAGE(kFillStage);
    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);

    mOutGlop->fill.texture = { &texture, GL_LINEAR, GL_CLAMP_TO_EDGE, nullptr };

    setFill(SK_ColorWHITE, alpha, mode, modeUsage, nullptr, colorFilter);

    mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
    return *this;
}

GlopBuilder& GlopBuilder::setFillTextureLayer(GlLayer& layer, float alpha) {
    TRIGGER_STAGE(kFillStage);
    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);

    mOutGlop->fill.texture = { &(layer.getTexture()),
            GL_LINEAR, GL_CLAMP_TO_EDGE, &layer.getTexTransform() };

    setFill(SK_ColorWHITE, alpha, layer.getMode(), Blend::ModeOrderSwap::NoSwap,
            nullptr, layer.getColorFilter());

    mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
    mDescription.hasTextureTransform = true;
    return *this;
}

GlopBuilder& GlopBuilder::setFillExternalTexture(Texture& texture, Matrix4& textureTransform,
        bool requiresFilter) {
    TRIGGER_STAGE(kFillStage);
    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);

    GLenum filter = requiresFilter ? GL_LINEAR : GL_NEAREST;
    mOutGlop->fill.texture = { &texture, filter, GL_CLAMP_TO_EDGE, &textureTransform };

    setFill(SK_ColorWHITE, 1.0f, SkBlendMode::kSrc, Blend::ModeOrderSwap::NoSwap,
            nullptr, nullptr);

    mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
    mDescription.hasTextureTransform = true;
    return *this;
}

GlopBuilder& GlopBuilder::setGammaCorrection(bool enabled) {
    REQUIRE_STAGES(kFillStage);

    mDescription.hasGammaCorrection = enabled;
    return *this;
}

////////////////////////////////////////////////////////////////////////////////
// Transform
////////////////////////////////////////////////////////////////////////////////

GlopBuilder& GlopBuilder::setTransform(const Matrix4& canvas, const int transformFlags) {
    TRIGGER_STAGE(kTransformStage);

    mOutGlop->transform.canvas = canvas;
    mOutGlop->transform.transformFlags = transformFlags;
    return *this;
}

////////////////////////////////////////////////////////////////////////////////
// ModelView
////////////////////////////////////////////////////////////////////////////////

GlopBuilder& GlopBuilder::setModelViewMapUnitToRect(const Rect destination) {
    TRIGGER_STAGE(kModelViewStage);

    mOutGlop->transform.modelView.loadTranslate(destination.left, destination.top, 0.0f);
    mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f);
    return *this;
}

GlopBuilder& GlopBuilder::setModelViewMapUnitToRectSnap(const Rect destination) {
    TRIGGER_STAGE(kModelViewStage);
    REQUIRE_STAGES(kTransformStage | kFillStage);

    float left = destination.left;
    float top = destination.top;

    const Matrix4& meshTransform = mOutGlop->transform.meshTransform();
    if (CC_LIKELY(meshTransform.isPureTranslate())) {
        // snap by adjusting the model view matrix
        const float translateX = meshTransform.getTranslateX();
        const float translateY = meshTransform.getTranslateY();

        left = (int) floorf(left + translateX + 0.5f) - translateX;
        top = (int) floorf(top + translateY + 0.5f) - translateY;
        mOutGlop->fill.texture.filter = GL_NEAREST;
    }

    mOutGlop->transform.modelView.loadTranslate(left, top, 0.0f);
    mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f);
    return *this;
}

GlopBuilder& GlopBuilder::setModelViewOffsetRect(float offsetX, float offsetY, const Rect source) {
    TRIGGER_STAGE(kModelViewStage);

    mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f);
    return *this;
}

GlopBuilder& GlopBuilder::setModelViewOffsetRectSnap(float offsetX, float offsetY, const Rect source) {
    TRIGGER_STAGE(kModelViewStage);
    REQUIRE_STAGES(kTransformStage | kFillStage);

    const Matrix4& meshTransform = mOutGlop->transform.meshTransform();
    if (CC_LIKELY(meshTransform.isPureTranslate())) {
        // snap by adjusting the model view matrix
        const float translateX = meshTransform.getTranslateX();
        const float translateY = meshTransform.getTranslateY();

        offsetX = (int) floorf(offsetX + translateX + source.left + 0.5f) - translateX - source.left;
        offsetY = (int) floorf(offsetY + translateY + source.top + 0.5f) - translateY - source.top;
        mOutGlop->fill.texture.filter = GL_NEAREST;
    }

    mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f);
    return *this;
}

////////////////////////////////////////////////////////////////////////////////
// RoundRectClip
////////////////////////////////////////////////////////////////////////////////

GlopBuilder& GlopBuilder::setRoundRectClipState(const RoundRectClipState* roundRectClipState) {
    TRIGGER_STAGE(kRoundRectClipStage);

    mOutGlop->roundRectClipState = roundRectClipState;
    mDescription.hasRoundRectClip = roundRectClipState != nullptr;
    return *this;
}

////////////////////////////////////////////////////////////////////////////////
// Build
////////////////////////////////////////////////////////////////////////////////

void verify(const ProgramDescription& description, const Glop& glop) {
    if (glop.fill.texture.texture != nullptr) {
        LOG_ALWAYS_FATAL_IF(((description.hasTexture && description.hasExternalTexture)
                        || (!description.hasTexture
                                && !description.hasExternalTexture
                                && !description.useShadowAlphaInterp)
                        || ((glop.mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) == 0
                                && !description.useShadowAlphaInterp)),
                "Texture %p, hT%d, hET %d, attribFlags %x",
                glop.fill.texture.texture,
                description.hasTexture, description.hasExternalTexture,
                glop.mesh.vertices.attribFlags);
    } else {
        LOG_ALWAYS_FATAL_IF((description.hasTexture
                        || description.hasExternalTexture
                        || ((glop.mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) != 0)),
                "No texture, hT%d, hET %d, attribFlags %x",
                description.hasTexture, description.hasExternalTexture,
                glop.mesh.vertices.attribFlags);
    }

    if ((glop.mesh.vertices.attribFlags & VertexAttribFlags::Alpha)
            && glop.mesh.vertices.bufferObject) {
        LOG_ALWAYS_FATAL("VBO and alpha attributes are not currently compatible");
    }

    if (description.hasTextureTransform != (glop.fill.texture.textureTransform != nullptr)) {
        LOG_ALWAYS_FATAL("Texture transform incorrectly specified");
    }
}

void GlopBuilder::build() {
    REQUIRE_STAGES(kAllStages);
    if (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) {
        Texture* texture = mOutGlop->fill.texture.texture;
        if (texture->target() == GL_TEXTURE_2D) {
            mDescription.hasTexture = true;
        } else {
            mDescription.hasExternalTexture = true;
        }
        mDescription.hasLinearTexture = texture->isLinear();
        mDescription.hasColorSpaceConversion = texture->hasColorSpaceConversion();
        mDescription.transferFunction = texture->getTransferFunctionType();
        mDescription.hasTranslucentConversion = texture->blend;
    }

    mDescription.hasColors = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Color;
    mDescription.hasVertexAlpha = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Alpha;

    // Enable debug highlight when what we're about to draw is tested against
    // the stencil buffer and if stencil highlight debugging is on
    mDescription.hasDebugHighlight = !Properties::debugOverdraw
            && Properties::debugStencilClip == StencilClipDebug::ShowHighlight
            && mRenderState.stencil().isTestEnabled();

    // serialize shader info into ShaderData
    GLuint textureUnit = mOutGlop->fill.texture.texture ? 1 : 0;

    if (CC_LIKELY(!mShader)) {
        mOutGlop->fill.skiaShaderData.skiaShaderType = kNone_SkiaShaderType;
    } else {
        Matrix4 shaderMatrix;
        if (mOutGlop->transform.transformFlags & TransformFlags::MeshIgnoresCanvasTransform) {
            // canvas level transform was built into the modelView and geometry,
            // so the shader matrix must reverse this
            shaderMatrix.loadInverse(mOutGlop->transform.canvas);
            shaderMatrix.multiply(mOutGlop->transform.modelView);
        } else {
            shaderMatrix = mOutGlop->transform.modelView;
        }
        SkiaShader::store(mCaches, *mShader, shaderMatrix,
                &textureUnit, &mDescription, &(mOutGlop->fill.skiaShaderData));
    }

    // duplicates ProgramCache's definition of color uniform presence
    const bool singleColor = !mDescription.hasTexture
            && !mDescription.hasExternalTexture
            && !mDescription.hasGradient
            && !mDescription.hasBitmap;
    mOutGlop->fill.colorEnabled = mDescription.modulate || singleColor;

    verify(mDescription, *mOutGlop);

    // Final step: populate program and map bounds into render target space
    mOutGlop->fill.program = mCaches.programCache.get(mDescription);
}

void GlopBuilder::dump(const Glop& glop) {
    ALOGD("Glop Mesh");
    const Glop::Mesh& mesh = glop.mesh;
    ALOGD("    primitive mode: %d", mesh.primitiveMode);
    ALOGD("    indices: buffer obj %x, indices %p", mesh.indices.bufferObject, mesh.indices.indices);

    const Glop::Mesh::Vertices& vertices = glop.mesh.vertices;
    ALOGD("    vertices: buffer obj %x, flags %x, pos %p, tex %p, clr %p, stride %d",
            vertices.bufferObject, vertices.attribFlags,
            vertices.position, vertices.texCoord, vertices.color, vertices.stride);
    ALOGD("    element count: %d", mesh.elementCount);

    ALOGD("Glop Fill");
    const Glop::Fill& fill = glop.fill;
    ALOGD("    program %p", fill.program);
    if (fill.texture.texture) {
        ALOGD("    texture %p, target %d, filter %d, clamp %d",
                fill.texture.texture, fill.texture.texture->target(),
                fill.texture.filter, fill.texture.clamp);
        if (fill.texture.textureTransform) {
            fill.texture.textureTransform->dump("texture transform");
        }
    }
    ALOGD_IF(fill.colorEnabled, "    color (argb) %.2f %.2f %.2f %.2f",
            fill.color.a, fill.color.r, fill.color.g, fill.color.b);
    ALOGD_IF(fill.filterMode != ProgramDescription::ColorFilterMode::None,
            "    filterMode %d", (int)fill.filterMode);
    ALOGD_IF(fill.skiaShaderData.skiaShaderType, "    shader type %d",
            fill.skiaShaderData.skiaShaderType);

    ALOGD("Glop transform");
    glop.transform.modelView.dump("  model view");
    glop.transform.canvas.dump("  canvas");
    ALOGD_IF(glop.transform.transformFlags, "  transformFlags 0x%x", glop.transform.transformFlags);

    ALOGD_IF(glop.roundRectClipState, "Glop RRCS %p", glop.roundRectClipState);

    ALOGD("Glop blend %d %d", glop.blend.src, glop.blend.dst);
}

} /* namespace uirenderer */
} /* namespace android */
