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

#include "GrXferProcessor.h"
#include "GrPipelineBuilder.h"
#include "GrProcOptInfo.h"
#include "gl/GrGLCaps.h"

GrXferProcessor::GrXferProcessor()
    : fWillReadDstColor(false)
    , fDstReadUsesMixedSamples(false)
    , fReadsCoverage(true)
    , fDstTextureOffset() {
}

GrXferProcessor::GrXferProcessor(const DstTexture* dstTexture,
                                 bool willReadDstColor,
                                 bool hasMixedSamples)
    : fWillReadDstColor(willReadDstColor)
    , fDstReadUsesMixedSamples(willReadDstColor && hasMixedSamples)
    , fReadsCoverage(true)
    , fDstTextureOffset() {
    if (dstTexture && dstTexture->texture()) {
        SkASSERT(willReadDstColor);
        fDstTexture.reset(dstTexture->texture());
        fDstTextureOffset = dstTexture->offset();
        this->addTextureAccess(&fDstTexture);
        this->setWillReadFragmentPosition();
    }
}

GrXferProcessor::OptFlags GrXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI,
                                                            const GrProcOptInfo& coveragePOI,
                                                            bool doesStencilWrite,
                                                            GrColor* overrideColor,
                                                            const GrCaps& caps) {
    GrXferProcessor::OptFlags flags = this->onGetOptimizations(colorPOI,
                                                               coveragePOI,
                                                               doesStencilWrite,
                                                               overrideColor,
                                                               caps);

    if (this->willReadDstColor()) {
        // When performing a dst read we handle coverage in the base class.
        SkASSERT(!(flags & GrXferProcessor::kIgnoreCoverage_OptFlag));
        if (coveragePOI.isSolidWhite()) {
            flags |= GrXferProcessor::kIgnoreCoverage_OptFlag;
        }
    }
    if (flags & GrXferProcessor::kIgnoreCoverage_OptFlag) {
        fReadsCoverage = false;
    }
    return flags;
}

bool GrXferProcessor::hasSecondaryOutput() const {
    if (!this->willReadDstColor()) {
        return this->onHasSecondaryOutput();
    }
    return this->dstReadUsesMixedSamples();
}

void GrXferProcessor::getBlendInfo(BlendInfo* blendInfo) const {
    blendInfo->reset();
    if (!this->willReadDstColor()) {
        this->onGetBlendInfo(blendInfo);
    } else if (this->dstReadUsesMixedSamples()) {
        blendInfo->fDstBlend = kIS2A_GrBlendCoeff;
    }
}

void GrXferProcessor::getGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
    uint32_t key = this->willReadDstColor() ? 0x1 : 0x0;
    if (key) {
        if (const GrTexture* dstTexture = this->getDstTexture()) {
            key |= 0x2;
            if (kTopLeft_GrSurfaceOrigin == dstTexture->origin()) {
                key |= 0x4;
            }
        }
        if (this->readsCoverage()) {
            key |= 0x8;
        }
        if (this->dstReadUsesMixedSamples()) {
            key |= 0x10;
        }
    }
    b->add32(key);
    this->onGetGLProcessorKey(caps, b);
}

GrXferBarrierType GrXferProcessor::xferBarrierType(const GrRenderTarget* rt,
                                                   const GrCaps& caps) const {
    SkASSERT(rt);
    if (static_cast<const GrSurface*>(rt) == this->getDstTexture()) {
        // Texture barriers are required when a shader reads and renders to the same texture.
        SkASSERT(caps.textureBarrierSupport());
        return kTexture_GrXferBarrierType;
    }
    return this->onXferBarrier(rt, caps);
}

#ifdef SK_DEBUG
static const char* equation_string(GrBlendEquation eq) {
    switch (eq) {
        case kAdd_GrBlendEquation:
            return "add";
        case kSubtract_GrBlendEquation:
            return "subtract";
        case kReverseSubtract_GrBlendEquation:
            return "reverse_subtract";
        case kScreen_GrBlendEquation:
            return "screen";
        case kOverlay_GrBlendEquation:
            return "overlay";
        case kDarken_GrBlendEquation:
            return "darken";
        case kLighten_GrBlendEquation:
            return "lighten";
        case kColorDodge_GrBlendEquation:
            return "color_dodge";
        case kColorBurn_GrBlendEquation:
            return "color_burn";
        case kHardLight_GrBlendEquation:
            return "hard_light";
        case kSoftLight_GrBlendEquation:
            return "soft_light";
        case kDifference_GrBlendEquation:
            return "difference";
        case kExclusion_GrBlendEquation:
            return "exclusion";
        case kMultiply_GrBlendEquation:
            return "multiply";
        case kHSLHue_GrBlendEquation:
            return "hsl_hue";
        case kHSLSaturation_GrBlendEquation:
            return "hsl_saturation";
        case kHSLColor_GrBlendEquation:
            return "hsl_color";
        case kHSLLuminosity_GrBlendEquation:
            return "hsl_luminosity";
    };
    return "";
}

static const char* coeff_string(GrBlendCoeff coeff) {
    switch (coeff) {
        case kZero_GrBlendCoeff:
            return "zero";
        case kOne_GrBlendCoeff:
            return "one";
        case kSC_GrBlendCoeff:
            return "src_color";
        case kISC_GrBlendCoeff:
            return "inv_src_color";
        case kDC_GrBlendCoeff:
            return "dst_color";
        case kIDC_GrBlendCoeff:
            return "inv_dst_color";
        case kSA_GrBlendCoeff:
            return "src_alpha";
        case kISA_GrBlendCoeff:
            return "inv_src_alpha";
        case kDA_GrBlendCoeff:
            return "dst_alpha";
        case kIDA_GrBlendCoeff:
            return "inv_dst_alpha";
        case kConstC_GrBlendCoeff:
            return "const_color";
        case kIConstC_GrBlendCoeff:
            return "inv_const_color";
        case kConstA_GrBlendCoeff:
            return "const_alpha";
        case kIConstA_GrBlendCoeff:
            return "inv_const_alpha";
        case kS2C_GrBlendCoeff:
            return "src2_color";
        case kIS2C_GrBlendCoeff:
            return "inv_src2_color";
        case kS2A_GrBlendCoeff:
            return "src2_alpha";
        case kIS2A_GrBlendCoeff:
            return "inv_src2_alpha";
    }
    return "";
}

SkString GrXferProcessor::BlendInfo::dump() const {
    SkString out;
    out.printf("write_color(%d) equation(%s) src_coeff(%s) dst_coeff:(%s) const(0x%08x)",
               fWriteColor, equation_string(fEquation), coeff_string(fSrcBlend),
               coeff_string(fDstBlend), fBlendConstant);
    return out;
}
#endif

///////////////////////////////////////////////////////////////////////////////

GrXferProcessor* GrXPFactory::createXferProcessor(const GrProcOptInfo& colorPOI,
                                                  const GrProcOptInfo& coveragePOI,
                                                  bool hasMixedSamples,
                                                  const DstTexture* dstTexture,
                                                  const GrCaps& caps) const {
#ifdef SK_DEBUG
    if (this->willReadDstColor(caps, colorPOI, coveragePOI, hasMixedSamples)) {
        if (!caps.shaderCaps()->dstReadInShaderSupport()) {
            SkASSERT(dstTexture && dstTexture->texture());
        } else {
            SkASSERT(!dstTexture || !dstTexture->texture()); 
        }
    } else {
        SkASSERT(!dstTexture || !dstTexture->texture()); 
    }
    SkASSERT(!hasMixedSamples || caps.shaderCaps()->dualSourceBlendingSupport());
#endif
    return this->onCreateXferProcessor(caps, colorPOI, coveragePOI, hasMixedSamples, dstTexture);
}

bool GrXPFactory::willNeedDstTexture(const GrCaps& caps,
                                     const GrProcOptInfo& colorPOI,
                                     const GrProcOptInfo& coveragePOI,
                                     bool hasMixedSamples) const {
    return (this->willReadDstColor(caps, colorPOI, coveragePOI, hasMixedSamples) &&
            !caps.shaderCaps()->dstReadInShaderSupport());
}
