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

#include "src/gpu/glsl/GrGLSLXferProcessor.h"

#include "include/gpu/GrTexture.h"
#include "src/gpu/GrShaderCaps.h"
#include "src/gpu/GrXferProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
#include "src/gpu/glsl/GrGLSLUniformHandler.h"

// This is only called for cases where we are doing LCD coverage and not using in shader blending.
// For these cases we assume the the src alpha is 1, thus we can just use the max for the alpha
// coverage since src alpha will always be greater than or equal to dst alpha.
static void adjust_for_lcd_coverage(GrGLSLXPFragmentBuilder* fragBuilder,
                                    const char* srcCoverage,
                                    const GrXferProcessor& proc) {
    if (srcCoverage && proc.isLCD()) {
        fragBuilder->codeAppendf("%s.a = max(max(%s.r, %s.g), %s.b);",
                                 srcCoverage, srcCoverage, srcCoverage, srcCoverage);
    }
}


void GrGLSLXferProcessor::emitCode(const EmitArgs& args) {
    if (!args.fXP.willReadDstColor()) {
        adjust_for_lcd_coverage(args.fXPFragBuilder, args.fInputCoverage, args.fXP);
        this->emitOutputsForBlendState(args);
    } else {
        GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
        GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
        const char* dstColor = fragBuilder->dstColor();

        bool needsLocalOutColor = false;

        if (args.fDstTextureSamplerHandle.isValid()) {
            bool flipY = kBottomLeft_GrSurfaceOrigin == args.fDstTextureOrigin;

            if (args.fInputCoverage) {
                // We don't think any shaders actually output negative coverage, but just as a
                // safety check for floating point precision errors we compare with <= here. We just
                // check the rgb values of the coverage since the alpha may not have been set when
                // using lcd. If we are using single channel coverage alpha will equal to rgb
                // anyways.
                //
                // The discard here also helps for batching text draws together which need to read
                // from a dst copy for blends. Though this only helps the case where the outer
                // bounding boxes of each letter overlap and not two actually parts of the text.
                fragBuilder->codeAppendf("if (all(lessThanEqual(%s.rgb, half3(0)))) {"
                                         "    discard;"
                                         "}", args.fInputCoverage);
            }

            const char* dstTopLeftName;
            const char* dstCoordScaleName;

            fDstTopLeftUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                                        kHalf2_GrSLType,
                                                        "DstTextureUpperLeft",
                                                        &dstTopLeftName);
            fDstScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                                      kHalf2_GrSLType,
                                                      "DstTextureCoordScale",
                                                      &dstCoordScaleName);

            fragBuilder->codeAppend("// Read color from copy of the destination.\n");
            fragBuilder->codeAppendf("half2 _dstTexCoord = (half2(sk_FragCoord.xy) - %s) * %s;",
                                     dstTopLeftName, dstCoordScaleName);

            if (flipY) {
                fragBuilder->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
            }

            fragBuilder->codeAppendf("half4 %s = ", dstColor);
            fragBuilder->appendTextureLookup(args.fDstTextureSamplerHandle, "_dstTexCoord");
            fragBuilder->codeAppend(";");
        } else {
            needsLocalOutColor = args.fShaderCaps->requiresLocalOutputColorForFBFetch();
        }

        const char* outColor = "_localColorOut";
        if (!needsLocalOutColor) {
            outColor = args.fOutputPrimary;
        } else {
            fragBuilder->codeAppendf("half4 %s;", outColor);
        }

        this->emitBlendCodeForDstRead(fragBuilder,
                                      uniformHandler,
                                      args.fInputColor,
                                      args.fInputCoverage,
                                      dstColor,
                                      outColor,
                                      args.fOutputSecondary,
                                      args.fXP);
        if (needsLocalOutColor) {
            fragBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, outColor);
        }
    }

    // Swizzle the fragment shader outputs if necessary.
    this->emitOutputSwizzle(
            args.fXPFragBuilder, args.fOutputSwizzle, args.fOutputPrimary, args.fOutputSecondary);
}

void GrGLSLXferProcessor::emitOutputSwizzle(
        GrGLSLXPFragmentBuilder* x, const GrSwizzle& swizzle, const char* outColor,
        const char* outColorSecondary) const {
    if (GrSwizzle::RGBA() != swizzle) {
        x->codeAppendf("%s = %s.%s;", outColor, outColor, swizzle.asString().c_str());
        if (outColorSecondary) {
            x->codeAppendf("%s = %s.%s;", outColorSecondary, outColorSecondary,
                           swizzle.asString().c_str());
        }
    }
}

void GrGLSLXferProcessor::setData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp,
                                  const GrTexture* dstTexture, const SkIPoint& dstTextureOffset) {
    if (dstTexture) {
        if (fDstTopLeftUni.isValid()) {
            pdm.set2f(fDstTopLeftUni, static_cast<float>(dstTextureOffset.fX),
                      static_cast<float>(dstTextureOffset.fY));
            pdm.set2f(fDstScaleUni, 1.f / dstTexture->width(), 1.f / dstTexture->height());
        } else {
            SkASSERT(!fDstScaleUni.isValid());
        }
    } else {
        SkASSERT(!fDstTopLeftUni.isValid());
        SkASSERT(!fDstScaleUni.isValid());
    }
    this->onSetData(pdm, xp);
}

void GrGLSLXferProcessor::DefaultCoverageModulation(GrGLSLXPFragmentBuilder* fragBuilder,
                                                    const char* srcCoverage,
                                                    const char* dstColor,
                                                    const char* outColor,
                                                    const char* outColorSecondary,
                                                    const GrXferProcessor& proc) {
    if (proc.dstReadUsesMixedSamples()) {
        if (srcCoverage) {
            // TODO: Once we are no longer using legacy mesh ops, it will not be possible to even
            // create a mixed sample with lcd so we can uncomment the below assert. In practice
            // today this never happens except for GLPrograms test which can make one. skia:6661
            // SkASSERT(!proc.isLCD());
            fragBuilder->codeAppendf("%s *= %s;", outColor, srcCoverage);
            fragBuilder->codeAppendf("%s = %s;", outColorSecondary, srcCoverage);
        } else {
            fragBuilder->codeAppendf("%s = half4(1.0);", outColorSecondary);
        }
    } else if (srcCoverage) {
        if (proc.isLCD()) {
            fragBuilder->codeAppendf("half lerpRed = mix(%s.a, %s.a, %s.r);",
                                     dstColor, outColor, srcCoverage);
            fragBuilder->codeAppendf("half lerpBlue = mix(%s.a, %s.a, %s.g);",
                                     dstColor, outColor, srcCoverage);
            fragBuilder->codeAppendf("half lerpGreen = mix(%s.a, %s.a, %s.b);",
                                     dstColor, outColor, srcCoverage);
        }
        fragBuilder->codeAppendf("%s = %s * %s + (half4(1.0) - %s) * %s;",
                                 outColor, srcCoverage, outColor, srcCoverage, dstColor);
        if (proc.isLCD()) {
            fragBuilder->codeAppendf("%s.a = max(max(lerpRed, lerpBlue), lerpGreen);", outColor);
        }
    }
}

