OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkBlitRow.h" | 8 #include "SkBlitRow.h" |
9 #include "SkColorFilter.h" | 9 #include "SkColorFilter.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 | 58 |
59 SkFlattenable* SkModeColorFilter::CreateProc(SkReadBuffer& buffer) { | 59 SkFlattenable* SkModeColorFilter::CreateProc(SkReadBuffer& buffer) { |
60 SkColor color = buffer.readColor(); | 60 SkColor color = buffer.readColor(); |
61 SkXfermode::Mode mode = (SkXfermode::Mode)buffer.readUInt(); | 61 SkXfermode::Mode mode = (SkXfermode::Mode)buffer.readUInt(); |
62 return SkColorFilter::CreateModeFilter(color, mode); | 62 return SkColorFilter::CreateModeFilter(color, mode); |
63 } | 63 } |
64 | 64 |
65 /////////////////////////////////////////////////////////////////////////////// | 65 /////////////////////////////////////////////////////////////////////////////// |
66 #if SK_SUPPORT_GPU | 66 #if SK_SUPPORT_GPU |
67 #include "GrBlend.h" | 67 #include "GrBlend.h" |
68 #include "GrFragmentProcessor.h" | |
69 #include "GrInvariantOutput.h" | 68 #include "GrInvariantOutput.h" |
70 #include "GrProcessorUnitTest.h" | 69 #include "effects/GrXfermodeFragmentProcessor.h" |
| 70 #include "effects/GrConstColorProcessor.h" |
71 #include "SkGr.h" | 71 #include "SkGr.h" |
72 #include "gl/GrGLFragmentProcessor.h" | |
73 #include "gl/builders/GrGLProgramBuilder.h" | |
74 | |
75 namespace { | |
76 /** | |
77 * A definition of blend equation for one coefficient. Generates a | |
78 * blend_coeff * value "expression". | |
79 */ | |
80 template<typename ColorExpr> | |
81 static inline ColorExpr blend_term(SkXfermode::Coeff coeff, | |
82 const ColorExpr& src, | |
83 const ColorExpr& dst, | |
84 const ColorExpr& value) { | |
85 switch (coeff) { | |
86 default: | |
87 SkFAIL("Unexpected xfer coeff."); | |
88 case SkXfermode::kZero_Coeff: /** 0 */ | |
89 return ColorExpr(0); | |
90 case SkXfermode::kOne_Coeff: /** 1 */ | |
91 return value; | |
92 case SkXfermode::kSC_Coeff: | |
93 return src * value; | |
94 case SkXfermode::kISC_Coeff: | |
95 return (ColorExpr(1) - src) * dst; | |
96 case SkXfermode::kDC_Coeff: | |
97 return dst * value; | |
98 case SkXfermode::kIDC_Coeff: | |
99 return (ColorExpr(1) - dst) * value; | |
100 case SkXfermode::kSA_Coeff: /** src alpha */ | |
101 return src.a() * value; | |
102 case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */ | |
103 return (typename ColorExpr::AExpr(1) - src.a()) * value; | |
104 case SkXfermode::kDA_Coeff: /** dst alpha */ | |
105 return dst.a() * value; | |
106 case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */ | |
107 return (typename ColorExpr::AExpr(1) - dst.a()) * value; | |
108 } | |
109 } | |
110 /** | |
111 * Creates a color filter expression which modifies the color by | |
112 * the specified color filter. | |
113 */ | |
114 template <typename ColorExpr> | |
115 static inline ColorExpr color_filter_expression(const SkXfermode::Mode& mode, | |
116 const ColorExpr& filterColor, | |
117 const ColorExpr& inColor) { | |
118 SkXfermode::Coeff colorCoeff; | |
119 SkXfermode::Coeff filterColorCoeff; | |
120 SkAssertResult(SkXfermode::ModeAsCoeff(mode, &filterColorCoeff, &colorCoeff)
); | |
121 return blend_term(colorCoeff, filterColor, inColor, inColor) + | |
122 blend_term(filterColorCoeff, filterColor, inColor, filterColor); | |
123 } | |
124 | |
125 } | |
126 | |
127 class ModeColorFilterEffect : public GrFragmentProcessor { | |
128 public: | |
129 static GrFragmentProcessor* Create(const GrColor& c, SkXfermode::Mode mode)
{ | |
130 // TODO: Make the effect take the coeffs rather than mode since we alrea
dy do the | |
131 // conversion here. | |
132 SkXfermode::Coeff srcCoeff, dstCoeff; | |
133 if (!SkXfermode::ModeAsCoeff(mode, &srcCoeff, &dstCoeff)) { | |
134 // SkDebugf("Failing to create color filter for mode %d\n", mode); | |
135 return nullptr; | |
136 } | |
137 return new ModeColorFilterEffect(c, mode); | |
138 } | |
139 | |
140 bool willUseFilterColor() const { | |
141 SkXfermode::Coeff dstCoeff; | |
142 SkXfermode::Coeff srcCoeff; | |
143 SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff)); | |
144 if (SkXfermode::kZero_Coeff == srcCoeff) { | |
145 return GrBlendCoeffRefsSrc(sk_blend_to_grblend(dstCoeff)); | |
146 } | |
147 return true; | |
148 } | |
149 | |
150 const char* name() const override { return "ModeColorFilterEffect"; } | |
151 | |
152 SkXfermode::Mode mode() const { return fMode; } | |
153 GrColor color() const { return fColor; } | |
154 | |
155 class GLProcessor : public GrGLFragmentProcessor { | |
156 public: | |
157 GLProcessor(const GrProcessor&) { | |
158 } | |
159 | |
160 virtual void emitCode(EmitArgs& args) override { | |
161 SkXfermode::Mode mode = args.fFp.cast<ModeColorFilterEffect>().mode(
); | |
162 | |
163 SkASSERT(SkXfermode::kDst_Mode != mode); | |
164 const char* colorFilterColorUniName = nullptr; | |
165 if (args.fFp.cast<ModeColorFilterEffect>().willUseFilterColor()) { | |
166 fFilterColorUni = args.fBuilder->addUniform( | |
167 GrGLProgramBuilder::kFragm
ent_Visibility, | |
168 kVec4f_GrSLType, kDefault_
GrSLPrecision, | |
169 "FilterColor", | |
170 &colorFilterColorUniName); | |
171 } | |
172 | |
173 GrGLSLExpr4 filter = | |
174 color_filter_expression(mode, GrGLSLExpr4(colorFilterColorUniNam
e), | |
175 GrGLSLExpr4(args.fInputColor)); | |
176 | |
177 args.fBuilder->getFragmentShaderBuilder()-> | |
178 codeAppendf("\t%s = %s;\n", args.fOutputColor, filter.c_str(
)); | |
179 } | |
180 | |
181 static void GenKey(const GrProcessor& fp, const GrGLSLCaps&, | |
182 GrProcessorKeyBuilder* b) { | |
183 const ModeColorFilterEffect& colorModeFilter = fp.cast<ModeColorFilt
erEffect>(); | |
184 // The SL code does not depend on filter color at the moment, so no
need to represent it | |
185 // in the key. | |
186 b->add32(colorModeFilter.mode()); | |
187 } | |
188 | |
189 protected: | |
190 virtual void onSetData(const GrGLProgramDataManager& pdman, | |
191 const GrProcessor& fp) override { | |
192 if (fFilterColorUni.isValid()) { | |
193 const ModeColorFilterEffect& colorModeFilter = fp.cast<ModeColor
FilterEffect>(); | |
194 GrGLfloat c[4]; | |
195 GrColorToRGBAFloat(colorModeFilter.color(), c); | |
196 pdman.set4fv(fFilterColorUni, 1, c); | |
197 } | |
198 } | |
199 | |
200 private: | |
201 | |
202 GrGLProgramDataManager::UniformHandle fFilterColorUni; | |
203 typedef GrGLFragmentProcessor INHERITED; | |
204 }; | |
205 | |
206 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; | |
207 | |
208 private: | |
209 ModeColorFilterEffect(GrColor color, SkXfermode::Mode mode) | |
210 : fMode(mode), | |
211 fColor(color) { | |
212 this->initClassID<ModeColorFilterEffect>(); | |
213 } | |
214 | |
215 GrGLFragmentProcessor* onCreateGLInstance() const override { return new GLPr
ocessor(*this); } | |
216 | |
217 virtual void onGetGLProcessorKey(const GrGLSLCaps& caps, | |
218 GrProcessorKeyBuilder* b) const override { | |
219 GLProcessor::GenKey(*this, caps, b); | |
220 } | |
221 | |
222 bool onIsEqual(const GrFragmentProcessor& other) const override { | |
223 const ModeColorFilterEffect& s = other.cast<ModeColorFilterEffect>(); | |
224 return fMode == s.fMode && fColor == s.fColor; | |
225 } | |
226 | |
227 void onComputeInvariantOutput(GrInvariantOutput* inout) const override; | |
228 | |
229 SkXfermode::Mode fMode; | |
230 GrColor fColor; | |
231 | |
232 typedef GrFragmentProcessor INHERITED; | |
233 }; | |
234 | |
235 namespace { | |
236 | |
237 /** Function color_component_to_int tries to reproduce the GLSL rounding. The sp
ec doesn't specify | |
238 * to which direction the 0.5 goes. | |
239 */ | |
240 static inline int color_component_to_int(float value) { | |
241 return sk_float_round2int(SkTMax(0.f, SkTMin(1.f, value)) * 255.f); | |
242 } | |
243 | |
244 /** MaskedColorExpr is used to evaluate the color and valid color component flag
s through the | |
245 * blending equation. It has members similar to GrGLSLExpr so that it can be use
d with the | |
246 * templated helpers above. | |
247 */ | |
248 class MaskedColorExpr { | |
249 public: | |
250 MaskedColorExpr(const float color[], uint32_t flags) | |
251 : fFlags(flags) { | |
252 fColor[0] = color[0]; | |
253 fColor[1] = color[1]; | |
254 fColor[2] = color[2]; | |
255 fColor[3] = color[3]; | |
256 } | |
257 | |
258 MaskedColorExpr(float v, uint32_t flags = kRGBA_GrColorComponentFlags) | |
259 : fFlags(flags) { | |
260 fColor[0] = v; | |
261 fColor[1] = v; | |
262 fColor[2] = v; | |
263 fColor[3] = v; | |
264 } | |
265 | |
266 MaskedColorExpr operator*(const MaskedColorExpr& other) const { | |
267 float tmp[4]; | |
268 tmp[0] = fColor[0] * other.fColor[0]; | |
269 tmp[1] = fColor[1] * other.fColor[1]; | |
270 tmp[2] = fColor[2] * other.fColor[2]; | |
271 tmp[3] = fColor[3] * other.fColor[3]; | |
272 | |
273 return MaskedColorExpr(tmp, fFlags & other.fFlags); | |
274 } | |
275 | |
276 MaskedColorExpr operator+(const MaskedColorExpr& other) const { | |
277 float tmp[4]; | |
278 tmp[0] = fColor[0] + other.fColor[0]; | |
279 tmp[1] = fColor[1] + other.fColor[1]; | |
280 tmp[2] = fColor[2] + other.fColor[2]; | |
281 tmp[3] = fColor[3] + other.fColor[3]; | |
282 | |
283 return MaskedColorExpr(tmp, fFlags & other.fFlags); | |
284 } | |
285 | |
286 MaskedColorExpr operator-(const MaskedColorExpr& other) const { | |
287 float tmp[4]; | |
288 tmp[0] = fColor[0] - other.fColor[0]; | |
289 tmp[1] = fColor[1] - other.fColor[1]; | |
290 tmp[2] = fColor[2] - other.fColor[2]; | |
291 tmp[3] = fColor[3] - other.fColor[3]; | |
292 | |
293 return MaskedColorExpr(tmp, fFlags & other.fFlags); | |
294 } | |
295 | |
296 MaskedColorExpr a() const { | |
297 uint32_t flags = (fFlags & kA_GrColorComponentFlag) ? kRGBA_GrColorCompo
nentFlags : 0; | |
298 return MaskedColorExpr(fColor[3], flags); | |
299 } | |
300 | |
301 GrColor getColor() const { | |
302 return GrColorPackRGBA(color_component_to_int(fColor[0]), | |
303 color_component_to_int(fColor[1]), | |
304 color_component_to_int(fColor[2]), | |
305 color_component_to_int(fColor[3])); | |
306 } | |
307 | |
308 uint32_t getValidComponents() const { return fFlags; } | |
309 | |
310 typedef MaskedColorExpr AExpr; | |
311 private: | |
312 float fColor[4]; | |
313 uint32_t fFlags; | |
314 }; | |
315 | |
316 } | |
317 | |
318 void ModeColorFilterEffect::onComputeInvariantOutput(GrInvariantOutput* inout) c
onst { | |
319 float inputColor[4]; | |
320 GrColorToRGBAFloat(inout->color(), inputColor); | |
321 float filterColor[4]; | |
322 GrColorToRGBAFloat(fColor, filterColor); | |
323 MaskedColorExpr result = | |
324 color_filter_expression(fMode, | |
325 MaskedColorExpr(filterColor, kRGBA_GrColorCompon
entFlags), | |
326 MaskedColorExpr(inputColor, inout->validFlags())
); | |
327 | |
328 // Check if we will use the input color | |
329 SkXfermode::Coeff dstCoeff; | |
330 SkXfermode::Coeff srcCoeff; | |
331 SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff)); | |
332 GrInvariantOutput::ReadInput readInput = GrInvariantOutput::kWill_ReadInput; | |
333 // These could be calculated from the blend equation with template trickery.
. | |
334 if (SkXfermode::kZero_Coeff == dstCoeff && | |
335 !GrBlendCoeffRefsDst(sk_blend_to_grblend(srcCoeff))) { | |
336 readInput = GrInvariantOutput::kWillNot_ReadInput; | |
337 } | |
338 inout->setToOther(result.getValidComponents(), result.getColor(), readInput)
; | |
339 } | |
340 | |
341 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ModeColorFilterEffect); | |
342 const GrFragmentProcessor* ModeColorFilterEffect::TestCreate(GrProcessorTestData
* d) { | |
343 SkXfermode::Mode mode = SkXfermode::kDst_Mode; | |
344 while (SkXfermode::kDst_Mode == mode) { | |
345 mode = static_cast<SkXfermode::Mode>(d->fRandom->nextRangeU(0, SkXfermod
e::kLastCoeffMode)); | |
346 } | |
347 | |
348 // pick a random premul color | |
349 uint8_t alpha = d->fRandom->nextULessThan(256); | |
350 GrColor color = GrColorPackRGBA(d->fRandom->nextRangeU(0, alpha), | |
351 d->fRandom->nextRangeU(0, alpha), | |
352 d->fRandom->nextRangeU(0, alpha), | |
353 alpha); | |
354 return ModeColorFilterEffect::Create(color, mode); | |
355 } | |
356 | 72 |
357 bool SkModeColorFilter::asFragmentProcessors(GrContext*, GrProcessorDataManager*
, | 73 bool SkModeColorFilter::asFragmentProcessors(GrContext*, GrProcessorDataManager*
, |
358 SkTDArray<GrFragmentProcessor*>* ar
ray) const { | 74 SkTDArray<const GrFragmentProcessor
*>* array) const { |
359 if (SkXfermode::kDst_Mode != fMode) { | 75 if (SkXfermode::kDst_Mode != fMode) { |
360 GrFragmentProcessor* frag = ModeColorFilterEffect::Create(SkColor2GrColo
r(fColor), fMode); | 76 SkAutoTUnref<const GrFragmentProcessor> constFP( |
361 if (frag) { | 77 GrConstColorProcessor::Create(SkColor2GrColor(fColor), |
| 78 GrConstColorProcessor::kIgnore_InputMo
de)); |
| 79 const GrFragmentProcessor* fp = |
| 80 GrXfermodeFragmentProcessor::CreateFromSrcProcessor(constFP, fMode); |
| 81 if (fp) { |
| 82 #ifdef SK_DEBUG |
| 83 // With a solid color input this should always be able to compute th
e blended color |
| 84 // (at least for coeff modes) |
| 85 if (fMode <= SkXfermode::kLastCoeffMode) { |
| 86 static SkRandom gRand; |
| 87 GrInvariantOutput io(GrPremulColor(gRand.nextU()), kRGBA_GrColor
ComponentFlags, |
| 88 false); |
| 89 fp->computeInvariantOutput(&io); |
| 90 SkASSERT(io.validFlags() == kRGBA_GrColorComponentFlags); |
| 91 } |
| 92 #endif |
362 if (array) { | 93 if (array) { |
363 *array->append() = frag; | 94 *array->append() = fp; |
364 } else { | 95 } else { |
365 frag->unref(); | 96 fp->unref(); |
366 SkDEBUGCODE(frag = nullptr;) | 97 SkDEBUGCODE(fp = nullptr;) |
367 } | 98 } |
368 return true; | 99 return true; |
369 } | 100 } |
370 } | 101 } |
371 return false; | 102 return false; |
372 } | 103 } |
373 | 104 |
374 #endif | 105 #endif |
375 | 106 |
376 /////////////////////////////////////////////////////////////////////////////// | 107 /////////////////////////////////////////////////////////////////////////////// |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 byte_to_scale(SkColorGetG(mul)), | 192 byte_to_scale(SkColorGetG(mul)), |
462 byte_to_scale(SkColorGetB(mul)), | 193 byte_to_scale(SkColorGetB(mul)), |
463 1); | 194 1); |
464 matrix.postTranslate(SkIntToScalar(SkColorGetR(add)), | 195 matrix.postTranslate(SkIntToScalar(SkColorGetR(add)), |
465 SkIntToScalar(SkColorGetG(add)), | 196 SkIntToScalar(SkColorGetG(add)), |
466 SkIntToScalar(SkColorGetB(add)), | 197 SkIntToScalar(SkColorGetB(add)), |
467 0); | 198 0); |
468 return SkColorMatrixFilter::Create(matrix); | 199 return SkColorMatrixFilter::Create(matrix); |
469 } | 200 } |
470 | 201 |
OLD | NEW |