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