Home | History | Annotate | Download | only in effects
      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