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