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