Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2015 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "GrXferProcessor.h"
      9 #include "GrPipeline.h"
     10 #include "GrPipelineBuilder.h"
     11 #include "GrProcOptInfo.h"
     12 #include "gl/GrGLCaps.h"
     13 
     14 GrXferProcessor::GrXferProcessor()
     15     : fWillReadDstColor(false)
     16     , fDstReadUsesMixedSamples(false)
     17     , fDstTextureOffset() {
     18 }
     19 
     20 GrXferProcessor::GrXferProcessor(const DstTexture* dstTexture,
     21                                  bool willReadDstColor,
     22                                  bool hasMixedSamples)
     23     : fWillReadDstColor(willReadDstColor)
     24     , fDstReadUsesMixedSamples(willReadDstColor && hasMixedSamples)
     25     , fDstTextureOffset() {
     26     if (dstTexture && dstTexture->texture()) {
     27         SkASSERT(willReadDstColor);
     28         fDstTexture.reset(dstTexture->texture());
     29         fDstTextureOffset = dstTexture->offset();
     30         this->addTextureAccess(&fDstTexture);
     31         this->setWillReadFragmentPosition();
     32     }
     33 }
     34 
     35 GrXferProcessor::OptFlags GrXferProcessor::getOptimizations(
     36                                                        const GrPipelineOptimizations& optimizations,
     37                                                        bool doesStencilWrite,
     38                                                        GrColor* overrideColor,
     39                                                        const GrCaps& caps) const {
     40     GrXferProcessor::OptFlags flags = this->onGetOptimizations(optimizations,
     41                                                                doesStencilWrite,
     42                                                                overrideColor,
     43                                                                caps);
     44 
     45     if (this->willReadDstColor()) {
     46         // When performing a dst read we handle coverage in the base class.
     47         SkASSERT(!(flags & GrXferProcessor::kIgnoreCoverage_OptFlag));
     48         if (optimizations.fCoveragePOI.isSolidWhite()) {
     49             flags |= GrXferProcessor::kIgnoreCoverage_OptFlag;
     50         }
     51     }
     52     return flags;
     53 }
     54 
     55 bool GrXferProcessor::hasSecondaryOutput() const {
     56     if (!this->willReadDstColor()) {
     57         return this->onHasSecondaryOutput();
     58     }
     59     return this->dstReadUsesMixedSamples();
     60 }
     61 
     62 void GrXferProcessor::getBlendInfo(BlendInfo* blendInfo) const {
     63     blendInfo->reset();
     64     if (!this->willReadDstColor()) {
     65         this->onGetBlendInfo(blendInfo);
     66     } else if (this->dstReadUsesMixedSamples()) {
     67         blendInfo->fDstBlend = kIS2A_GrBlendCoeff;
     68     }
     69 }
     70 
     71 void GrXferProcessor::getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
     72     uint32_t key = this->willReadDstColor() ? 0x1 : 0x0;
     73     if (key) {
     74         if (const GrTexture* dstTexture = this->getDstTexture()) {
     75             key |= 0x2;
     76             if (kTopLeft_GrSurfaceOrigin == dstTexture->origin()) {
     77                 key |= 0x4;
     78             }
     79         }
     80         if (this->dstReadUsesMixedSamples()) {
     81             key |= 0x8;
     82         }
     83     }
     84     b->add32(key);
     85     this->onGetGLSLProcessorKey(caps, b);
     86 }
     87 
     88 GrXferBarrierType GrXferProcessor::xferBarrierType(const GrRenderTarget* rt,
     89                                                    const GrCaps& caps) const {
     90     SkASSERT(rt);
     91     if (static_cast<const GrSurface*>(rt) == this->getDstTexture()) {
     92         // Texture barriers are required when a shader reads and renders to the same texture.
     93         SkASSERT(caps.textureBarrierSupport());
     94         return kTexture_GrXferBarrierType;
     95     }
     96     return this->onXferBarrier(rt, caps);
     97 }
     98 
     99 #ifdef SK_DEBUG
    100 static const char* equation_string(GrBlendEquation eq) {
    101     switch (eq) {
    102         case kAdd_GrBlendEquation:
    103             return "add";
    104         case kSubtract_GrBlendEquation:
    105             return "subtract";
    106         case kReverseSubtract_GrBlendEquation:
    107             return "reverse_subtract";
    108         case kScreen_GrBlendEquation:
    109             return "screen";
    110         case kOverlay_GrBlendEquation:
    111             return "overlay";
    112         case kDarken_GrBlendEquation:
    113             return "darken";
    114         case kLighten_GrBlendEquation:
    115             return "lighten";
    116         case kColorDodge_GrBlendEquation:
    117             return "color_dodge";
    118         case kColorBurn_GrBlendEquation:
    119             return "color_burn";
    120         case kHardLight_GrBlendEquation:
    121             return "hard_light";
    122         case kSoftLight_GrBlendEquation:
    123             return "soft_light";
    124         case kDifference_GrBlendEquation:
    125             return "difference";
    126         case kExclusion_GrBlendEquation:
    127             return "exclusion";
    128         case kMultiply_GrBlendEquation:
    129             return "multiply";
    130         case kHSLHue_GrBlendEquation:
    131             return "hsl_hue";
    132         case kHSLSaturation_GrBlendEquation:
    133             return "hsl_saturation";
    134         case kHSLColor_GrBlendEquation:
    135             return "hsl_color";
    136         case kHSLLuminosity_GrBlendEquation:
    137             return "hsl_luminosity";
    138     };
    139     return "";
    140 }
    141 
    142 static const char* coeff_string(GrBlendCoeff coeff) {
    143     switch (coeff) {
    144         case kZero_GrBlendCoeff:
    145             return "zero";
    146         case kOne_GrBlendCoeff:
    147             return "one";
    148         case kSC_GrBlendCoeff:
    149             return "src_color";
    150         case kISC_GrBlendCoeff:
    151             return "inv_src_color";
    152         case kDC_GrBlendCoeff:
    153             return "dst_color";
    154         case kIDC_GrBlendCoeff:
    155             return "inv_dst_color";
    156         case kSA_GrBlendCoeff:
    157             return "src_alpha";
    158         case kISA_GrBlendCoeff:
    159             return "inv_src_alpha";
    160         case kDA_GrBlendCoeff:
    161             return "dst_alpha";
    162         case kIDA_GrBlendCoeff:
    163             return "inv_dst_alpha";
    164         case kConstC_GrBlendCoeff:
    165             return "const_color";
    166         case kIConstC_GrBlendCoeff:
    167             return "inv_const_color";
    168         case kConstA_GrBlendCoeff:
    169             return "const_alpha";
    170         case kIConstA_GrBlendCoeff:
    171             return "inv_const_alpha";
    172         case kS2C_GrBlendCoeff:
    173             return "src2_color";
    174         case kIS2C_GrBlendCoeff:
    175             return "inv_src2_color";
    176         case kS2A_GrBlendCoeff:
    177             return "src2_alpha";
    178         case kIS2A_GrBlendCoeff:
    179             return "inv_src2_alpha";
    180     }
    181     return "";
    182 }
    183 
    184 SkString GrXferProcessor::BlendInfo::dump() const {
    185     SkString out;
    186     out.printf("write_color(%d) equation(%s) src_coeff(%s) dst_coeff:(%s) const(0x%08x)",
    187                fWriteColor, equation_string(fEquation), coeff_string(fSrcBlend),
    188                coeff_string(fDstBlend), fBlendConstant);
    189     return out;
    190 }
    191 #endif
    192 
    193 ///////////////////////////////////////////////////////////////////////////////
    194 
    195 GrXferProcessor* GrXPFactory::createXferProcessor(const GrPipelineOptimizations& optimizations,
    196                                                   bool hasMixedSamples,
    197                                                   const DstTexture* dstTexture,
    198                                                   const GrCaps& caps) const {
    199 #ifdef SK_DEBUG
    200     if (this->willReadDstColor(caps, optimizations, hasMixedSamples)) {
    201         if (!caps.shaderCaps()->dstReadInShaderSupport()) {
    202             SkASSERT(dstTexture && dstTexture->texture());
    203         } else {
    204             SkASSERT(!dstTexture || !dstTexture->texture());
    205         }
    206     } else {
    207         SkASSERT(!dstTexture || !dstTexture->texture());
    208     }
    209     SkASSERT(!hasMixedSamples || caps.shaderCaps()->dualSourceBlendingSupport());
    210 #endif
    211     return this->onCreateXferProcessor(caps, optimizations, hasMixedSamples, dstTexture);
    212 }
    213 
    214 bool GrXPFactory::willNeedDstTexture(const GrCaps& caps,
    215                                      const GrPipelineOptimizations& optimizations,
    216                                      bool hasMixedSamples) const {
    217     return (this->willReadDstColor(caps, optimizations, hasMixedSamples) &&
    218             !caps.shaderCaps()->dstReadInShaderSupport());
    219 }
    220 
    221 bool GrXPFactory::willReadDstColor(const GrCaps& caps,
    222                                    const GrPipelineOptimizations& optimizations,
    223                                    bool hasMixedSamples) const {
    224     return optimizations.fOverrides.fUsePLSDstRead || this->onWillReadDstColor(caps, optimizations,
    225                                                                                hasMixedSamples);
    226 }
    227