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
13GrXferProcessor::GrXferProcessor(ClassID classID)
14 : INHERITED(classID)
15 , fWillReadDstColor(false)
16 , fDstReadUsesMixedSamples(false)
17 , fIsLCD(false) {}
18
19GrXferProcessor::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
26bool GrXferProcessor::hasSecondaryOutput() const {
27 if (!this->willReadDstColor()) {
28 return this->onHasSecondaryOutput();
29 }
30 return this->dstReadUsesMixedSamples();
31}
32
33void 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
55static 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
100static 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
141SkString 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
152GrXPFactory::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
177sk_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