blob: e175840d32c1d769ff0c2a2a44454366375df88e [file] [log] [blame]
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2011 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.
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +00006 */
7
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkPixelXorXfermode.h"
9#include "SkColorPriv.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000010#include "SkReadBuffer.h"
11#include "SkWriteBuffer.h"
robertphillips@google.comb83b6b42013-01-22 14:32:09 +000012#include "SkString.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000013
14// we always return an opaque color, 'cause I don't know what to do with
15// the alpha-component and still return a valid premultiplied color.
mike@reedtribe.org61490fa2012-12-24 14:38:46 +000016SkPMColor SkPixelXorXfermode::xferColor(SkPMColor src, SkPMColor dst) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +000017 SkPMColor res = src ^ dst ^ fOpColor;
robertphillips727b7d22016-01-26 12:07:13 -080018
reed@android.com8a1c16f2008-12-17 15:59:43 +000019 res |= (SK_A32_MASK << SK_A32_SHIFT); // force it to be opaque
20 return res;
21}
22
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000023void SkPixelXorXfermode::flatten(SkWriteBuffer& wb) const {
robertphillips5381b812016-01-28 08:50:26 -080024 wb.writeColor(SkColorSetRGB(SkGetPackedR32(fOpColor),
25 SkGetPackedG32(fOpColor),
26 SkGetPackedB32(fOpColor)));
reed@android.com8a1c16f2008-12-17 15:59:43 +000027}
28
reed9fa60da2014-08-21 07:59:51 -070029SkFlattenable* SkPixelXorXfermode::CreateProc(SkReadBuffer& buffer) {
30 return Create(buffer.readColor());
31}
robertphillips@google.comb83b6b42013-01-22 14:32:09 +000032
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +000033#ifndef SK_IGNORE_TO_STRING
robertphillips@google.comb83b6b42013-01-22 14:32:09 +000034void SkPixelXorXfermode::toString(SkString* str) const {
35 str->append("SkPixelXorXfermode: ");
36 str->appendHex(fOpColor);
37}
38#endif
halcanary27a6e862016-01-21 14:15:10 -080039
robertphillips727b7d22016-01-26 12:07:13 -080040#if SK_SUPPORT_GPU
41#include "GrFragmentProcessor.h"
42#include "GrInvariantOutput.h"
43#include "GrXferProcessor.h"
44
45#include "glsl/GrGLSLFragmentProcessor.h"
46#include "glsl/GrGLSLFragmentShaderBuilder.h"
47#include "glsl/GrGLSLProgramDataManager.h"
48#include "glsl/GrGLSLUniformHandler.h"
49#include "glsl/GrGLSLXferProcessor.h"
50
51///////////////////////////////////////////////////////////////////////////////
52// Fragment Processor
53///////////////////////////////////////////////////////////////////////////////
54
55static void add_pixelxor_code(GrGLSLFragmentBuilder* fragBuilder,
56 const char* srcColor,
57 const char* dstColor,
58 const char* outputColor,
59 const char* opColor) {
60 static const GrGLSLShaderVar gXorArgs[] = {
61 GrGLSLShaderVar("f1", kFloat_GrSLType),
62 GrGLSLShaderVar("f2", kFloat_GrSLType),
63 GrGLSLShaderVar("f3", kFloat_GrSLType),
64 GrGLSLShaderVar("fPowerOf2Divisor", kFloat_GrSLType),
65 };
66 SkString xorFuncName;
67
68 // The xor function checks if the three passed in floats (f1, f2, f3) would
mtkleinbbb6dc82016-01-27 13:08:33 -080069 // have a bit in the log2(fPowerOf2Divisor)-th position if they were
70 // represented by an int. It then performs an xor of the 3 bits (using
robertphillips727b7d22016-01-26 12:07:13 -080071 // the property that serial xors can be treated as a sum of 0s & 1s mod 2).
72 fragBuilder->emitFunction(kFloat_GrSLType,
73 "xor",
74 SK_ARRAY_COUNT(gXorArgs),
75 gXorArgs,
76 "float bit1 = floor(f1 / fPowerOf2Divisor);"
77 "float bit2 = floor(f2 / fPowerOf2Divisor);"
78 "float bit3 = floor(f3 / fPowerOf2Divisor);"
79 "return mod(bit1 + bit2 + bit3, 2.0);",
80 &xorFuncName);
81
82 fragBuilder->codeAppend("float red = 0.0, green = 0.0, blue = 0.0;");
83
84 if (srcColor) {
85 fragBuilder->codeAppendf("vec3 src = 255.99 * %s.rgb;", srcColor);
86 } else {
87 fragBuilder->codeAppendf("vec3 src = vec3(255.99);");
88 }
89 fragBuilder->codeAppendf("vec3 dst = 255.99 * %s.rgb;", dstColor);
90 fragBuilder->codeAppendf("vec3 op = 255.99 * %s;", opColor);
91
92 fragBuilder->codeAppend("float modValue = 128.0;");
93
94 fragBuilder->codeAppend("for (int i = 0; i < 8; i++) {");
95
96 fragBuilder->codeAppendf("float bit = %s(src.r, dst.r, op.r, modValue);", xorFuncName.c_str());
97 fragBuilder->codeAppend("red += modValue * bit;");
98 fragBuilder->codeAppend("src.r = mod(src.r, modValue);");
99 fragBuilder->codeAppend("dst.r = mod(dst.r, modValue);");
100 fragBuilder->codeAppend("op.r = mod(op.r, modValue);");
101
102 fragBuilder->codeAppendf("bit = %s(src.g, dst.g, op.g, modValue);", xorFuncName.c_str());
103 fragBuilder->codeAppend("green += modValue * bit;");
104 fragBuilder->codeAppend("src.g = mod(src.g, modValue);");
105 fragBuilder->codeAppend("dst.g = mod(dst.g, modValue);");
106 fragBuilder->codeAppend("op.g = mod(op.g, modValue);");
107
108 fragBuilder->codeAppendf("bit = %s(src.b, dst.b, op.b, modValue);", xorFuncName.c_str());
109 fragBuilder->codeAppend("blue += modValue * bit;");
110 fragBuilder->codeAppend("src.b = mod(src.b, modValue);");
111 fragBuilder->codeAppend("dst.b = mod(dst.b, modValue);");
112 fragBuilder->codeAppend("op.b = mod(op.b, modValue);");
113
114 fragBuilder->codeAppend("modValue /= 2.0;");
115
116 fragBuilder->codeAppend("}");
117
118 fragBuilder->codeAppendf("%s = vec4(red/255.0, green/255.0, blue/255.0, 1.0);", outputColor);
119}
120
121class GLPixelXorFP;
122
123class PixelXorFP : public GrFragmentProcessor {
124public:
robertphillips98124ef2016-01-28 06:41:11 -0800125 static const GrFragmentProcessor* Create(SkPMColor opColor, const GrFragmentProcessor* dst) {
robertphillips727b7d22016-01-26 12:07:13 -0800126 return new PixelXorFP(opColor, dst);
127 }
128
129 ~PixelXorFP() override {};
130
131 const char* name() const override { return "PixelXor"; }
132
133 SkString dumpInfo() const override {
134 SkString str;
135 str.appendf("Color: 0x%08x", fOpColor);
136 return str;
137 }
138
robertphillips98124ef2016-01-28 06:41:11 -0800139 SkPMColor opColor() const { return fOpColor; }
robertphillips727b7d22016-01-26 12:07:13 -0800140
141private:
142 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
143
144 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
145
146 bool onIsEqual(const GrFragmentProcessor& fpBase) const override {
147 const PixelXorFP& fp = fpBase.cast<PixelXorFP>();
148 return fOpColor == fp.fOpColor;
149 }
150
151 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
152 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
153 }
154
robertphillips98124ef2016-01-28 06:41:11 -0800155 PixelXorFP(SkPMColor opColor, const GrFragmentProcessor* dst)
robertphillips727b7d22016-01-26 12:07:13 -0800156 : fOpColor(opColor) {
157 this->initClassID<PixelXorFP>();
158
159 SkASSERT(dst);
160 SkDEBUGCODE(int dstIndex = )this->registerChildProcessor(dst);
161 SkASSERT(0 == dstIndex);
162 }
163
robertphillips98124ef2016-01-28 06:41:11 -0800164 SkPMColor fOpColor;
robertphillips727b7d22016-01-26 12:07:13 -0800165
166 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
167 typedef GrFragmentProcessor INHERITED;
168};
169
170///////////////////////////////////////////////////////////////////////////////
171
172class GLPixelXorFP : public GrGLSLFragmentProcessor {
173public:
robertphillips727b7d22016-01-26 12:07:13 -0800174 void emitCode(EmitArgs& args) override {
cdalton85285412016-02-18 12:37:07 -0800175 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
robertphillips727b7d22016-01-26 12:07:13 -0800176 SkString dstColor("dstColor");
177 this->emitChild(0, nullptr, &dstColor, args);
178
cdalton5e58cee2016-02-11 12:49:47 -0800179 fOpColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
robertphillips727b7d22016-01-26 12:07:13 -0800180 kVec3f_GrSLType, kHigh_GrSLPrecision,
181 "opColor");
182 const char* kOpColorUni = args.fUniformHandler->getUniformCStr(fOpColorUni);
183
184 add_pixelxor_code(fragBuilder, args.fInputColor, dstColor.c_str(),
185 args.fOutputColor, kOpColorUni);
186 }
187
188 static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*) { }
189
190protected:
191 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override {
192 const PixelXorFP& pixXor = proc.cast<PixelXorFP>();
193 pdman.set3f(fOpColorUni,
robertphillips98124ef2016-01-28 06:41:11 -0800194 SkGetPackedR32(pixXor.opColor())/255.0f,
195 SkGetPackedG32(pixXor.opColor())/255.0f,
196 SkGetPackedB32(pixXor.opColor())/255.0f);
robertphillips727b7d22016-01-26 12:07:13 -0800197 }
198
199private:
200 GrGLSLProgramDataManager::UniformHandle fOpColorUni;
201
202 typedef GrGLSLFragmentProcessor INHERITED;
203};
204
205///////////////////////////////////////////////////////////////////////////////
206
207GrGLSLFragmentProcessor* PixelXorFP::onCreateGLSLInstance() const {
robertphillips9cdb9922016-02-03 12:25:40 -0800208 return new GLPixelXorFP;
robertphillips727b7d22016-01-26 12:07:13 -0800209}
210
211void PixelXorFP::onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
212 GLPixelXorFP::GenKey(*this, caps, b);
213}
214
215const GrFragmentProcessor* PixelXorFP::TestCreate(GrProcessorTestData* d) {
216 SkColor color = d->fRandom->nextU();
217
218 SkAutoTUnref<const GrFragmentProcessor> dst(GrProcessorUnitTest::CreateChildFP(d));
robertphillips98124ef2016-01-28 06:41:11 -0800219 return new PixelXorFP(SkPreMultiplyColor(color), dst);
robertphillips727b7d22016-01-26 12:07:13 -0800220}
221
222GR_DEFINE_FRAGMENT_PROCESSOR_TEST(PixelXorFP);
223
224///////////////////////////////////////////////////////////////////////////////
225// Xfer Processor
226///////////////////////////////////////////////////////////////////////////////
227
228class PixelXorXP : public GrXferProcessor {
229public:
robertphillips98124ef2016-01-28 06:41:11 -0800230 PixelXorXP(const DstTexture* dstTexture, bool hasMixedSamples, SkPMColor opColor)
robertphillips727b7d22016-01-26 12:07:13 -0800231 : INHERITED(dstTexture, true, hasMixedSamples)
232 , fOpColor(opColor) {
233 this->initClassID<PixelXorXP>();
234 }
235
236 const char* name() const override { return "PixelXor"; }
237
238 GrGLSLXferProcessor* createGLSLInstance() const override;
239
robertphillips98124ef2016-01-28 06:41:11 -0800240 SkPMColor opColor() const { return fOpColor; }
robertphillips727b7d22016-01-26 12:07:13 -0800241
242private:
243 GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations,
244 bool doesStencilWrite,
245 GrColor* overrideColor,
246 const GrCaps& caps) const override {
247 return GrXferProcessor::kNone_OptFlags;
248 }
249
250 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
251
252 bool onIsEqual(const GrXferProcessor& xpBase) const override {
253 const PixelXorXP& xp = xpBase.cast<PixelXorXP>();
254
255 return fOpColor == xp.fOpColor;
256 }
257
robertphillips98124ef2016-01-28 06:41:11 -0800258 SkPMColor fOpColor;
robertphillips727b7d22016-01-26 12:07:13 -0800259
260 typedef GrXferProcessor INHERITED;
261};
262
263///////////////////////////////////////////////////////////////////////////////
264
265class GLPixelXorXP : public GrGLSLXferProcessor {
266public:
267 GLPixelXorXP(const PixelXorXP& pixelXorXP) { }
268
269 ~GLPixelXorXP() override {}
270
271 static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*) { }
272
273private:
274 void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder,
275 GrGLSLUniformHandler* uniformHandler,
276 const char* srcColor,
277 const char* srcCoverage,
278 const char* dstColor,
279 const char* outColor,
280 const char* outColorSecondary,
281 const GrXferProcessor& proc) override {
cdalton5e58cee2016-02-11 12:49:47 -0800282 fOpColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
robertphillips727b7d22016-01-26 12:07:13 -0800283 kVec3f_GrSLType, kHigh_GrSLPrecision,
284 "opColor");
285 const char* kOpColorUni = uniformHandler->getUniformCStr(fOpColorUni);
286
287 add_pixelxor_code(fragBuilder, srcColor, dstColor, outColor, kOpColorUni);
288
289 // Apply coverage.
290 INHERITED::DefaultCoverageModulation(fragBuilder, srcCoverage, dstColor, outColor,
291 outColorSecondary, proc);
292 }
293
294 void onSetData(const GrGLSLProgramDataManager& pdman,
295 const GrXferProcessor& processor) override {
296 const PixelXorXP& pixelXor = processor.cast<PixelXorXP>();
robertphillips98124ef2016-01-28 06:41:11 -0800297 pdman.set3f(fOpColorUni,
298 SkGetPackedR32(pixelXor.opColor())/255.0f,
299 SkGetPackedG32(pixelXor.opColor())/255.0f,
300 SkGetPackedB32(pixelXor.opColor())/255.0f);
robertphillips727b7d22016-01-26 12:07:13 -0800301 };
302
303 GrGLSLProgramDataManager::UniformHandle fOpColorUni;
304
305 typedef GrGLSLXferProcessor INHERITED;
306};
307
308///////////////////////////////////////////////////////////////////////////////
309
310void PixelXorXP::onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
311 GLPixelXorXP::GenKey(*this, caps, b);
312}
313
314GrGLSLXferProcessor* PixelXorXP::createGLSLInstance() const { return new GLPixelXorXP(*this); }
315
316///////////////////////////////////////////////////////////////////////////////
317
318class GrPixelXorXPFactory : public GrXPFactory {
319public:
robertphillips98124ef2016-01-28 06:41:11 -0800320 static GrXPFactory* Create(SkPMColor opColor) {
robertphillips727b7d22016-01-26 12:07:13 -0800321 return new GrPixelXorXPFactory(opColor);
322 }
323
324 void getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
325 GrXPFactory::InvariantBlendedColor* blendedColor) const override {
326 blendedColor->fWillBlendWithDst = true;
327 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
328 }
329
330private:
robertphillips98124ef2016-01-28 06:41:11 -0800331 GrPixelXorXPFactory(SkPMColor opColor)
robertphillips727b7d22016-01-26 12:07:13 -0800332 : fOpColor(opColor) {
333 this->initClassID<GrPixelXorXPFactory>();
334 }
335
336 GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
337 const GrPipelineOptimizations& optimizations,
338 bool hasMixedSamples,
339 const DstTexture* dstTexture) const override {
340 return new PixelXorXP(dstTexture, hasMixedSamples, fOpColor);
341 }
342
ethannicholas22793252016-01-30 09:59:10 -0800343 bool onWillReadDstColor(const GrCaps& caps,
robertphillipsafb188d2016-02-03 09:42:49 -0800344 const GrPipelineOptimizations& optimizations,
345 bool hasMixedSamples) const override {
robertphillips727b7d22016-01-26 12:07:13 -0800346 return true;
347 }
348
349 bool onIsEqual(const GrXPFactory& xpfBase) const override {
350 const GrPixelXorXPFactory& xpf = xpfBase.cast<GrPixelXorXPFactory>();
351 return fOpColor == xpf.fOpColor;
352 }
353
354 GR_DECLARE_XP_FACTORY_TEST;
355
robertphillips98124ef2016-01-28 06:41:11 -0800356 SkPMColor fOpColor;
robertphillips727b7d22016-01-26 12:07:13 -0800357
358 typedef GrXPFactory INHERITED;
359};
360
361GR_DEFINE_XP_FACTORY_TEST(GrPixelXorXPFactory);
362
363const GrXPFactory* GrPixelXorXPFactory::TestCreate(GrProcessorTestData* d) {
364 SkColor color = d->fRandom->nextU();
365
robertphillips98124ef2016-01-28 06:41:11 -0800366 return GrPixelXorXPFactory::Create(SkPreMultiplyColor(color));
robertphillips727b7d22016-01-26 12:07:13 -0800367}
368
369///////////////////////////////////////////////////////////////////////////////
370
robertphillips4f037942016-02-09 05:09:27 -0800371const GrFragmentProcessor* SkPixelXorXfermode::getFragmentProcessorForImageFilter(
372 const GrFragmentProcessor* dst) const {
373 return PixelXorFP::Create(fOpColor, dst);
robertphillips727b7d22016-01-26 12:07:13 -0800374}
375
robertphillips4f037942016-02-09 05:09:27 -0800376GrXPFactory* SkPixelXorXfermode::asXPFactory() const {
377 return GrPixelXorXPFactory::Create(fOpColor);
robertphillips727b7d22016-01-26 12:07:13 -0800378}
379
380#endif