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 "src/gpu/GrXferProcessor.h"
9 
10 #include "src/gpu/GrCaps.h"
11 #include "src/gpu/GrPipeline.h"
12 
GrXferProcessor(ClassID classID)13 GrXferProcessor::GrXferProcessor(ClassID classID)
14         : INHERITED(classID)
15         , fWillReadDstColor(false)
16         , fDstReadUsesMixedSamples(false)
17         , fIsLCD(false) {}
18 
GrXferProcessor(ClassID classID,bool willReadDstColor,bool hasMixedSamples,GrProcessorAnalysisCoverage coverage)19 GrXferProcessor::GrXferProcessor(ClassID classID, bool willReadDstColor, bool hasMixedSamples,
20                                  GrProcessorAnalysisCoverage coverage)
21         : INHERITED(classID)
22         , fWillReadDstColor(willReadDstColor)
23         , fDstReadUsesMixedSamples(willReadDstColor && hasMixedSamples)
24         , fIsLCD(GrProcessorAnalysisCoverage::kLCD == coverage) {}
25 
hasSecondaryOutput() const26 bool GrXferProcessor::hasSecondaryOutput() const {
27     if (!this->willReadDstColor()) {
28         return this->onHasSecondaryOutput();
29     }
30     return this->dstReadUsesMixedSamples();
31 }
32 
getGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b,const GrSurfaceOrigin * originIfDstTexture,GrDstSampleType dstSampleType) const33 void GrXferProcessor::getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b,
34                                           const GrSurfaceOrigin* originIfDstTexture,
35                                           GrDstSampleType dstSampleType) const {
36     uint32_t key = this->willReadDstColor() ? 0x1 : 0x0;
37     if (key) {
38         if (originIfDstTexture) {
39             key |= 0x2;
40             if (kTopLeft_GrSurfaceOrigin == *originIfDstTexture) {
41                 key |= 0x4;
42             }
43             // We don't just add the whole dstSampleType to the key because sampling a copy or the
44             // rt directly produces the same shader code.
45             if (dstSampleType == GrDstSampleType::kAsInputAttachment) {
46                 key |= 0x8;
47             }
48         }
49         if (this->dstReadUsesMixedSamples()) {
50             key |= 0x10;
51         }
52     }
53     if (fIsLCD) {
54         key |= 0x20;
55     }
56     b->add32(key);
57     this->onGetGLSLProcessorKey(caps, b);
58 }
59 
60 #ifdef SK_DEBUG
equation_string(GrBlendEquation eq)61 static const char* equation_string(GrBlendEquation eq) {
62     switch (eq) {
63         case kAdd_GrBlendEquation:
64             return "add";
65         case kSubtract_GrBlendEquation:
66             return "subtract";
67         case kReverseSubtract_GrBlendEquation:
68             return "reverse_subtract";
69         case kScreen_GrBlendEquation:
70             return "screen";
71         case kOverlay_GrBlendEquation:
72             return "overlay";
73         case kDarken_GrBlendEquation:
74             return "darken";
75         case kLighten_GrBlendEquation:
76             return "lighten";
77         case kColorDodge_GrBlendEquation:
78             return "color_dodge";
79         case kColorBurn_GrBlendEquation:
80             return "color_burn";
81         case kHardLight_GrBlendEquation:
82             return "hard_light";
83         case kSoftLight_GrBlendEquation:
84             return "soft_light";
85         case kDifference_GrBlendEquation:
86             return "difference";
87         case kExclusion_GrBlendEquation:
88             return "exclusion";
89         case kMultiply_GrBlendEquation:
90             return "multiply";
91         case kHSLHue_GrBlendEquation:
92             return "hsl_hue";
93         case kHSLSaturation_GrBlendEquation:
94             return "hsl_saturation";
95         case kHSLColor_GrBlendEquation:
96             return "hsl_color";
97         case kHSLLuminosity_GrBlendEquation:
98             return "hsl_luminosity";
99         case kIllegal_GrBlendEquation:
100             SkASSERT(false);
101             return "<illegal>";
102     }
103     return "";
104 }
105 
coeff_string(GrBlendCoeff coeff)106 static const char* coeff_string(GrBlendCoeff coeff) {
107     switch (coeff) {
108         case kZero_GrBlendCoeff:
109             return "zero";
110         case kOne_GrBlendCoeff:
111             return "one";
112         case kSC_GrBlendCoeff:
113             return "src_color";
114         case kISC_GrBlendCoeff:
115             return "inv_src_color";
116         case kDC_GrBlendCoeff:
117             return "dst_color";
118         case kIDC_GrBlendCoeff:
119             return "inv_dst_color";
120         case kSA_GrBlendCoeff:
121             return "src_alpha";
122         case kISA_GrBlendCoeff:
123             return "inv_src_alpha";
124         case kDA_GrBlendCoeff:
125             return "dst_alpha";
126         case kIDA_GrBlendCoeff:
127             return "inv_dst_alpha";
128         case kConstC_GrBlendCoeff:
129             return "const_color";
130         case kIConstC_GrBlendCoeff:
131             return "inv_const_color";
132         case kS2C_GrBlendCoeff:
133             return "src2_color";
134         case kIS2C_GrBlendCoeff:
135             return "inv_src2_color";
136         case kS2A_GrBlendCoeff:
137             return "src2_alpha";
138         case kIS2A_GrBlendCoeff:
139             return "inv_src2_alpha";
140         case kIllegal_GrBlendCoeff:
141             SkASSERT(false);
142             return "<illegal>";
143     }
144     return "";
145 }
146 
dump() const147 SkString GrXferProcessor::BlendInfo::dump() const {
148     SkString out;
149     out.printf("write_color(%d) equation(%s) src_coeff(%s) dst_coeff:(%s) const(0x%08x)",
150                fWriteColor, equation_string(fEquation), coeff_string(fSrcBlend),
151                coeff_string(fDstBlend), fBlendConstant.toBytes_RGBA());
152     return out;
153 }
154 #endif
155 
156 ///////////////////////////////////////////////////////////////////////////////
157 
GetAnalysisProperties(const GrXPFactory * factory,const GrProcessorAnalysisColor & color,const GrProcessorAnalysisCoverage & coverage,const GrCaps & caps,GrClampType clampType)158 GrXPFactory::AnalysisProperties GrXPFactory::GetAnalysisProperties(
159         const GrXPFactory* factory,
160         const GrProcessorAnalysisColor& color,
161         const GrProcessorAnalysisCoverage& coverage,
162         const GrCaps& caps,
163         GrClampType clampType) {
164     AnalysisProperties result;
165     if (factory) {
166         result = factory->analysisProperties(color, coverage, caps, clampType);
167     } else {
168         result = GrPorterDuffXPFactory::SrcOverAnalysisProperties(color, coverage, caps,
169                                                                   clampType);
170     }
171     if (coverage == GrProcessorAnalysisCoverage::kNone) {
172         result |= AnalysisProperties::kCompatibleWithCoverageAsAlpha;
173     }
174     SkASSERT(!(result & AnalysisProperties::kRequiresDstTexture));
175     if ((result & AnalysisProperties::kReadsDstInShader) &&
176         !caps.shaderCaps()->dstReadInShaderSupport()) {
177         result |= AnalysisProperties::kRequiresDstTexture |
178                   AnalysisProperties::kRequiresNonOverlappingDraws;
179     }
180     return result;
181 }
182 
MakeXferProcessor(const GrXPFactory * factory,const GrProcessorAnalysisColor & color,GrProcessorAnalysisCoverage coverage,bool hasMixedSamples,const GrCaps & caps,GrClampType clampType)183 sk_sp<const GrXferProcessor> GrXPFactory::MakeXferProcessor(const GrXPFactory* factory,
184                                                             const GrProcessorAnalysisColor& color,
185                                                             GrProcessorAnalysisCoverage coverage,
186                                                             bool hasMixedSamples,
187                                                             const GrCaps& caps,
188                                                             GrClampType clampType) {
189     SkASSERT(!hasMixedSamples || caps.shaderCaps()->dualSourceBlendingSupport());
190 
191     if (factory) {
192         return factory->makeXferProcessor(color, coverage, hasMixedSamples, caps, clampType);
193     } else {
194         return GrPorterDuffXPFactory::MakeSrcOverXferProcessor(color, coverage, hasMixedSamples,
195                                                                caps);
196     }
197 }
198