1 /* 2 * 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. 6 */ 7 8 #include "SkPixelXorXfermode.h" 9 #include "SkColorPriv.h" 10 #include "SkReadBuffer.h" 11 #include "SkWriteBuffer.h" 12 #include "SkString.h" 13 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. 16 SkPMColor SkPixelXorXfermode::xferColor(SkPMColor src, SkPMColor dst) const { 17 SkPMColor res = src ^ dst ^ fOpColor; 18 19 res |= (SK_A32_MASK << SK_A32_SHIFT); // force it to be opaque 20 return res; 21 } 22 23 void SkPixelXorXfermode::flatten(SkWriteBuffer& wb) const { 24 wb.writeColor(SkColorSetRGB(SkGetPackedR32(fOpColor), 25 SkGetPackedG32(fOpColor), 26 SkGetPackedB32(fOpColor))); 27 } 28 29 SkFlattenable* SkPixelXorXfermode::CreateProc(SkReadBuffer& buffer) { 30 return Create(buffer.readColor()); 31 } 32 33 #ifndef SK_IGNORE_TO_STRING 34 void SkPixelXorXfermode::toString(SkString* str) const { 35 str->append("SkPixelXorXfermode: "); 36 str->appendHex(fOpColor); 37 } 38 #endif 39 40 #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 55 static 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 69 // 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 71 // 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 121 class GLPixelXorFP; 122 123 class PixelXorFP : public GrFragmentProcessor { 124 public: 125 static const GrFragmentProcessor* Create(SkPMColor opColor, const GrFragmentProcessor* dst) { 126 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 139 SkPMColor opColor() const { return fOpColor; } 140 141 private: 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 155 PixelXorFP(SkPMColor opColor, const GrFragmentProcessor* dst) 156 : fOpColor(opColor) { 157 this->initClassID<PixelXorFP>(); 158 159 SkASSERT(dst); 160 SkDEBUGCODE(int dstIndex = )this->registerChildProcessor(dst); 161 SkASSERT(0 == dstIndex); 162 } 163 164 SkPMColor fOpColor; 165 166 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 167 typedef GrFragmentProcessor INHERITED; 168 }; 169 170 /////////////////////////////////////////////////////////////////////////////// 171 172 class GLPixelXorFP : public GrGLSLFragmentProcessor { 173 public: 174 void emitCode(EmitArgs& args) override { 175 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 176 SkString dstColor("dstColor"); 177 this->emitChild(0, nullptr, &dstColor, args); 178 179 fOpColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, 180 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 190 protected: 191 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override { 192 const PixelXorFP& pixXor = proc.cast<PixelXorFP>(); 193 pdman.set3f(fOpColorUni, 194 SkGetPackedR32(pixXor.opColor())/255.0f, 195 SkGetPackedG32(pixXor.opColor())/255.0f, 196 SkGetPackedB32(pixXor.opColor())/255.0f); 197 } 198 199 private: 200 GrGLSLProgramDataManager::UniformHandle fOpColorUni; 201 202 typedef GrGLSLFragmentProcessor INHERITED; 203 }; 204 205 /////////////////////////////////////////////////////////////////////////////// 206 207 GrGLSLFragmentProcessor* PixelXorFP::onCreateGLSLInstance() const { 208 return new GLPixelXorFP; 209 } 210 211 void PixelXorFP::onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const { 212 GLPixelXorFP::GenKey(*this, caps, b); 213 } 214 215 const GrFragmentProcessor* PixelXorFP::TestCreate(GrProcessorTestData* d) { 216 SkColor color = d->fRandom->nextU(); 217 218 SkAutoTUnref<const GrFragmentProcessor> dst(GrProcessorUnitTest::CreateChildFP(d)); 219 return new PixelXorFP(SkPreMultiplyColor(color), dst); 220 } 221 222 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(PixelXorFP); 223 224 /////////////////////////////////////////////////////////////////////////////// 225 // Xfer Processor 226 /////////////////////////////////////////////////////////////////////////////// 227 228 class PixelXorXP : public GrXferProcessor { 229 public: 230 PixelXorXP(const DstTexture* dstTexture, bool hasMixedSamples, SkPMColor opColor) 231 : 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 240 SkPMColor opColor() const { return fOpColor; } 241 242 private: 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 258 SkPMColor fOpColor; 259 260 typedef GrXferProcessor INHERITED; 261 }; 262 263 /////////////////////////////////////////////////////////////////////////////// 264 265 class GLPixelXorXP : public GrGLSLXferProcessor { 266 public: 267 GLPixelXorXP(const PixelXorXP& pixelXorXP) { } 268 269 ~GLPixelXorXP() override {} 270 271 static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*) { } 272 273 private: 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 { 282 fOpColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 283 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>(); 297 pdman.set3f(fOpColorUni, 298 SkGetPackedR32(pixelXor.opColor())/255.0f, 299 SkGetPackedG32(pixelXor.opColor())/255.0f, 300 SkGetPackedB32(pixelXor.opColor())/255.0f); 301 }; 302 303 GrGLSLProgramDataManager::UniformHandle fOpColorUni; 304 305 typedef GrGLSLXferProcessor INHERITED; 306 }; 307 308 /////////////////////////////////////////////////////////////////////////////// 309 310 void PixelXorXP::onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const { 311 GLPixelXorXP::GenKey(*this, caps, b); 312 } 313 314 GrGLSLXferProcessor* PixelXorXP::createGLSLInstance() const { return new GLPixelXorXP(*this); } 315 316 /////////////////////////////////////////////////////////////////////////////// 317 318 class GrPixelXorXPFactory : public GrXPFactory { 319 public: 320 static GrXPFactory* Create(SkPMColor opColor) { 321 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 330 private: 331 GrPixelXorXPFactory(SkPMColor opColor) 332 : 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 343 bool onWillReadDstColor(const GrCaps& caps, 344 const GrPipelineOptimizations& optimizations, 345 bool hasMixedSamples) const override { 346 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 356 SkPMColor fOpColor; 357 358 typedef GrXPFactory INHERITED; 359 }; 360 361 GR_DEFINE_XP_FACTORY_TEST(GrPixelXorXPFactory); 362 363 const GrXPFactory* GrPixelXorXPFactory::TestCreate(GrProcessorTestData* d) { 364 SkColor color = d->fRandom->nextU(); 365 366 return GrPixelXorXPFactory::Create(SkPreMultiplyColor(color)); 367 } 368 369 /////////////////////////////////////////////////////////////////////////////// 370 371 const GrFragmentProcessor* SkPixelXorXfermode::getFragmentProcessorForImageFilter( 372 const GrFragmentProcessor* dst) const { 373 return PixelXorFP::Create(fOpColor, dst); 374 } 375 376 GrXPFactory* SkPixelXorXfermode::asXPFactory() const { 377 return GrPixelXorXPFactory::Create(fOpColor); 378 } 379 380 #endif 381