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