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 "gl/GrGLCaps.h"
10 
GrXferProcessor()11 GrXferProcessor::GrXferProcessor()
12     : fWillReadDstColor(false), fReadsCoverage(true), fDstCopyTextureOffset() {
13 }
14 
GrXferProcessor(const GrDeviceCoordTexture * dstCopy,bool willReadDstColor)15 GrXferProcessor::GrXferProcessor(const GrDeviceCoordTexture* dstCopy, bool willReadDstColor)
16     : fWillReadDstColor(willReadDstColor)
17     , fReadsCoverage(true)
18     , fDstCopyTextureOffset() {
19     if (dstCopy && dstCopy->texture()) {
20         fDstCopy.reset(dstCopy->texture());
21         fDstCopyTextureOffset = dstCopy->offset();
22         this->addTextureAccess(&fDstCopy);
23         this->setWillReadFragmentPosition();
24     }
25 }
26 
getOptimizations(const GrProcOptInfo & colorPOI,const GrProcOptInfo & coveragePOI,bool doesStencilWrite,GrColor * overrideColor,const GrDrawTargetCaps & caps)27 GrXferProcessor::OptFlags GrXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI,
28                                                             const GrProcOptInfo& coveragePOI,
29                                                             bool doesStencilWrite,
30                                                             GrColor* overrideColor,
31                                                             const GrDrawTargetCaps& caps) {
32     GrXferProcessor::OptFlags flags = this->onGetOptimizations(colorPOI,
33                                                                coveragePOI,
34                                                                doesStencilWrite,
35                                                                overrideColor,
36                                                                caps);
37 
38     if (flags & GrXferProcessor::kIgnoreCoverage_OptFlag) {
39         fReadsCoverage = false;
40     }
41     return flags;
42 }
43 
getGLProcessorKey(const GrGLSLCaps & caps,GrProcessorKeyBuilder * b) const44 void GrXferProcessor::getGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
45     uint32_t key = this->willReadDstColor() ? 0x1 : 0x0;
46     if (this->getDstCopyTexture() &&
47         kTopLeft_GrSurfaceOrigin == this->getDstCopyTexture()->origin()) {
48         key |= 0x2;
49     }
50     b->add32(key);
51     this->onGetGLProcessorKey(caps, b);
52 }
53 
willNeedXferBarrier(const GrRenderTarget * rt,const GrDrawTargetCaps & caps,GrXferBarrierType * outBarrierType) const54 bool GrXferProcessor::willNeedXferBarrier(const GrRenderTarget* rt,
55                                           const GrDrawTargetCaps& caps,
56                                           GrXferBarrierType* outBarrierType) const {
57     if (static_cast<const GrSurface*>(rt) == this->getDstCopyTexture()) {
58         // Texture barriers are required when a shader reads and renders to the same texture.
59         SkASSERT(rt);
60         SkASSERT(caps.textureBarrierSupport());
61         *outBarrierType = kTexture_GrXferBarrierType;
62         return true;
63     }
64     return this->onWillNeedXferBarrier(rt, caps, outBarrierType);
65 }
66 
67 #ifdef SK_DEBUG
equation_string(GrBlendEquation eq)68 static const char* equation_string(GrBlendEquation eq) {
69     switch (eq) {
70         case kAdd_GrBlendEquation:
71             return "add";
72         case kSubtract_GrBlendEquation:
73             return "subtract";
74         case kReverseSubtract_GrBlendEquation:
75             return "reverse_subtract";
76         case kScreen_GrBlendEquation:
77             return "screen";
78         case kOverlay_GrBlendEquation:
79             return "overlay";
80         case kDarken_GrBlendEquation:
81             return "darken";
82         case kLighten_GrBlendEquation:
83             return "lighten";
84         case kColorDodge_GrBlendEquation:
85             return "color_dodge";
86         case kColorBurn_GrBlendEquation:
87             return "color_burn";
88         case kHardLight_GrBlendEquation:
89             return "hard_light";
90         case kSoftLight_GrBlendEquation:
91             return "soft_light";
92         case kDifference_GrBlendEquation:
93             return "difference";
94         case kExclusion_GrBlendEquation:
95             return "exclusion";
96         case kMultiply_GrBlendEquation:
97             return "multiply";
98         case kHSLHue_GrBlendEquation:
99             return "hsl_hue";
100         case kHSLSaturation_GrBlendEquation:
101             return "hsl_saturation";
102         case kHSLColor_GrBlendEquation:
103             return "hsl_color";
104         case kHSLLuminosity_GrBlendEquation:
105             return "hsl_luminosity";
106     };
107     return "";
108 }
109 
coeff_string(GrBlendCoeff coeff)110 static const char* coeff_string(GrBlendCoeff coeff) {
111     switch (coeff) {
112         case kZero_GrBlendCoeff:
113             return "zero";
114         case kOne_GrBlendCoeff:
115             return "one";
116         case kSC_GrBlendCoeff:
117             return "src_color";
118         case kISC_GrBlendCoeff:
119             return "inv_src_color";
120         case kDC_GrBlendCoeff:
121             return "dst_color";
122         case kIDC_GrBlendCoeff:
123             return "inv_dst_color";
124         case kSA_GrBlendCoeff:
125             return "src_alpha";
126         case kISA_GrBlendCoeff:
127             return "inv_src_alpha";
128         case kDA_GrBlendCoeff:
129             return "dst_alpha";
130         case kIDA_GrBlendCoeff:
131             return "inv_dst_alpha";
132         case kConstC_GrBlendCoeff:
133             return "const_color";
134         case kIConstC_GrBlendCoeff:
135             return "inv_const_color";
136         case kConstA_GrBlendCoeff:
137             return "const_alpha";
138         case kIConstA_GrBlendCoeff:
139             return "inv_const_alpha";
140         case kS2C_GrBlendCoeff:
141             return "src2_color";
142         case kIS2C_GrBlendCoeff:
143             return "inv_src2_color";
144         case kS2A_GrBlendCoeff:
145             return "src2_alpha";
146         case kIS2A_GrBlendCoeff:
147             return "inv_src2_alpha";
148     }
149     return "";
150 }
151 
dump() const152 SkString GrXferProcessor::BlendInfo::dump() const {
153     SkString out;
154     out.printf("write_color(%d) equation(%s) src_coeff(%s) dst_coeff:(%s) const(0x%08x)",
155                fWriteColor, equation_string(fEquation), coeff_string(fSrcBlend),
156                coeff_string(fDstBlend), fBlendConstant);
157     return out;
158 }
159 #endif
160 
161 ///////////////////////////////////////////////////////////////////////////////
162 
createXferProcessor(const GrProcOptInfo & colorPOI,const GrProcOptInfo & coveragePOI,const GrDeviceCoordTexture * dstCopy,const GrDrawTargetCaps & caps) const163 GrXferProcessor* GrXPFactory::createXferProcessor(const GrProcOptInfo& colorPOI,
164                                                   const GrProcOptInfo& coveragePOI,
165                                                   const GrDeviceCoordTexture* dstCopy,
166                                                   const GrDrawTargetCaps& caps) const {
167 #ifdef SK_DEBUG
168     if (this->willReadDstColor(caps, colorPOI, coveragePOI)) {
169         if (!caps.shaderCaps()->dstReadInShaderSupport()) {
170             SkASSERT(dstCopy && dstCopy->texture());
171         } else {
172             SkASSERT(!dstCopy || !dstCopy->texture());
173         }
174     } else {
175         SkASSERT(!dstCopy || !dstCopy->texture());
176     }
177 #endif
178     return this->onCreateXferProcessor(caps, colorPOI, coveragePOI, dstCopy);
179 }
180 
willNeedDstCopy(const GrDrawTargetCaps & caps,const GrProcOptInfo & colorPOI,const GrProcOptInfo & coveragePOI) const181 bool GrXPFactory::willNeedDstCopy(const GrDrawTargetCaps& caps, const GrProcOptInfo& colorPOI,
182                                   const GrProcOptInfo& coveragePOI) const {
183     return (this->willReadDstColor(caps, colorPOI, coveragePOI)
184             && !caps.shaderCaps()->dstReadInShaderSupport());
185 }
186 
187