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