Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(488)

Side by Side Diff: src/effects/SkColorFilters.cpp

Issue 1334293003: Create fragment processor for performing input color blend with child processor (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/effects/SkColorCubeFilter.cpp ('k') | src/effects/SkColorMatrixFilter.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « src/effects/SkColorCubeFilter.cpp ('k') | src/effects/SkColorMatrixFilter.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698