1/* 2* Copyright 2015 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 "effects/GrXfermodeFragmentProcessor.h" 9 10#include "GrFragmentProcessor.h" 11#include "GrInvariantOutput.h" 12#include "effects/GrConstColorProcessor.h" 13#include "glsl/GrGLSLFragmentProcessor.h" 14#include "glsl/GrGLSLBlend.h" 15#include "glsl/GrGLSLFragmentShaderBuilder.h" 16#include "SkGrPriv.h" 17 18class ComposeTwoFragmentProcessor : public GrFragmentProcessor { 19public: 20 ComposeTwoFragmentProcessor(const GrFragmentProcessor* src, const GrFragmentProcessor* dst, 21 SkXfermode::Mode mode) 22 : fMode(mode) { 23 this->initClassID<ComposeTwoFragmentProcessor>(); 24 SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(src); 25 SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(dst); 26 SkASSERT(0 == shaderAChildIndex); 27 SkASSERT(1 == shaderBChildIndex); 28 } 29 30 const char* name() const override { return "ComposeTwo"; } 31 32 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override { 33 b->add32(fMode); 34 } 35 36 SkXfermode::Mode getMode() const { return fMode; } 37 38protected: 39 bool onIsEqual(const GrFragmentProcessor& other) const override { 40 const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>(); 41 return fMode == cs.fMode; 42 } 43 44 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { 45 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); 46 } 47 48private: 49 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; 50 51 SkXfermode::Mode fMode; 52 53 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 54 55 typedef GrFragmentProcessor INHERITED; 56}; 57 58///////////////////////////////////////////////////////////////////// 59 60class GLComposeTwoFragmentProcessor : public GrGLSLFragmentProcessor { 61public: 62 void emitCode(EmitArgs&) override; 63 64private: 65 typedef GrGLSLFragmentProcessor INHERITED; 66}; 67 68///////////////////////////////////////////////////////////////////// 69 70GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor); 71 72const GrFragmentProcessor* ComposeTwoFragmentProcessor::TestCreate(GrProcessorTestData* d) { 73 // Create two random frag procs. 74 SkAutoTUnref<const GrFragmentProcessor> fpA(GrProcessorUnitTest::CreateChildFP(d)); 75 SkAutoTUnref<const GrFragmentProcessor> fpB(GrProcessorUnitTest::CreateChildFP(d)); 76 77 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>( 78 d->fRandom->nextRangeU(0, SkXfermode::kLastMode)); 79 return new ComposeTwoFragmentProcessor(fpA, fpB, mode); 80} 81 82GrGLSLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLSLInstance() const{ 83 return new GLComposeTwoFragmentProcessor; 84} 85 86///////////////////////////////////////////////////////////////////// 87 88void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) { 89 90 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 91 const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>(); 92 93 const char* inputColor = nullptr; 94 if (args.fInputColor) { 95 inputColor = "inputColor"; 96 fragBuilder->codeAppendf("vec4 inputColor = vec4(%s.rgb, 1.0);", args.fInputColor); 97 } 98 99 // declare outputColor and emit the code for each of the two children 100 SkString srcColor("src"); 101 this->emitChild(0, inputColor, &srcColor, args); 102 103 SkString dstColor("dst"); 104 this->emitChild(1, inputColor, &dstColor, args); 105 106 // emit blend code 107 SkXfermode::Mode mode = cs.getMode(); 108 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode)); 109 GrGLSLBlend::AppendMode(fragBuilder, 110 srcColor.c_str(), 111 dstColor.c_str(), 112 args.fOutputColor, 113 mode); 114 115 // re-multiply the output color by the input color's alpha 116 if (args.fInputColor) { 117 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor); 118 } 119} 120 121const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromTwoProcessors( 122 const GrFragmentProcessor* src, const GrFragmentProcessor* dst, SkXfermode::Mode mode) { 123 switch (mode) { 124 case SkXfermode::kClear_Mode: 125 return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK, 126 GrConstColorProcessor::kIgnore_InputMode); 127 case SkXfermode::kSrc_Mode: 128 return SkRef(src); 129 case SkXfermode::kDst_Mode: 130 return SkRef(dst); 131 default: 132 return new ComposeTwoFragmentProcessor(src, dst, mode); 133 } 134} 135 136////////////////////////////////////////////////////////////////////////////// 137 138class ComposeOneFragmentProcessor : public GrFragmentProcessor { 139public: 140 enum Child { 141 kDst_Child, 142 kSrc_Child, 143 }; 144 145 ComposeOneFragmentProcessor(const GrFragmentProcessor* dst, SkXfermode::Mode mode, Child child) 146 : fMode(mode) 147 , fChild(child) { 148 this->initClassID<ComposeOneFragmentProcessor>(); 149 SkDEBUGCODE(int dstIndex = )this->registerChildProcessor(dst); 150 SkASSERT(0 == dstIndex); 151 } 152 153 const char* name() const override { return "ComposeOne"; } 154 155 SkString dumpInfo() const override { 156 SkString str; 157 158 for (int i = 0; i < this->numChildProcessors(); ++i) { 159 str.append(this->childProcessor(i).dumpInfo()); 160 } 161 return str; 162 } 163 164 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override { 165 GR_STATIC_ASSERT((SkXfermode::kLastMode & SK_MaxU16) == SkXfermode::kLastMode); 166 b->add32(fMode | (fChild << 16)); 167 } 168 169 SkXfermode::Mode mode() const { return fMode; } 170 171 Child child() const { return fChild; } 172 173protected: 174 bool onIsEqual(const GrFragmentProcessor& that) const override { 175 return fMode == that.cast<ComposeOneFragmentProcessor>().fMode; 176 } 177 178 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { 179 SkXfermode::Coeff skSrcCoeff, skDstCoeff; 180 if (SkXfermode::ModeAsCoeff(fMode, &skSrcCoeff, &skDstCoeff)) { 181 GrBlendCoeff srcCoeff = SkXfermodeCoeffToGrBlendCoeff(skSrcCoeff); 182 GrBlendCoeff dstCoeff = SkXfermodeCoeffToGrBlendCoeff(skDstCoeff); 183 GrInvariantOutput childOutput(0xFFFFFFFF, kRGBA_GrColorComponentFlags, false); 184 this->childProcessor(0).computeInvariantOutput(&childOutput); 185 GrColor blendColor; 186 GrColorComponentFlags blendFlags; 187 if (kDst_Child == fChild) { 188 GrGetCoeffBlendKnownComponents(srcCoeff, dstCoeff, 189 inout->color(), inout->validFlags(), 190 childOutput.color(), childOutput.validFlags(), 191 &blendColor, &blendFlags); 192 } else { 193 GrGetCoeffBlendKnownComponents(srcCoeff, dstCoeff, 194 childOutput.color(), childOutput.validFlags(), 195 inout->color(), inout->validFlags(), 196 &blendColor, &blendFlags); 197 } 198 // will the shader code reference the input color? 199 GrInvariantOutput::ReadInput readsInput = GrInvariantOutput::kWillNot_ReadInput; 200 if (kDst_Child == fChild) { 201 if (kZero_GrBlendCoeff != srcCoeff || GrBlendCoeffRefsSrc(dstCoeff)) { 202 readsInput = GrInvariantOutput::kWill_ReadInput; 203 } 204 } else { 205 if (kZero_GrBlendCoeff != dstCoeff || GrBlendCoeffRefsDst(srcCoeff)) { 206 readsInput = GrInvariantOutput::kWill_ReadInput; 207 } 208 } 209 inout->setToOther(blendFlags, blendColor, readsInput); 210 } else { 211 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); 212 } 213 } 214 215private: 216 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; 217 218 SkXfermode::Mode fMode; 219 Child fChild; 220 221 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 222 223 typedef GrFragmentProcessor INHERITED; 224}; 225 226////////////////////////////////////////////////////////////////////////////// 227 228class GLComposeOneFragmentProcessor : public GrGLSLFragmentProcessor { 229public: 230 void emitCode(EmitArgs& args) override { 231 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 232 SkXfermode::Mode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode(); 233 ComposeOneFragmentProcessor::Child child = 234 args.fFp.cast<ComposeOneFragmentProcessor>().child(); 235 SkString childColor("child"); 236 this->emitChild(0, nullptr, &childColor, args); 237 238 const char* inputColor = args.fInputColor; 239 // We don't try to optimize for this case at all 240 if (!inputColor) { 241 fragBuilder->codeAppendf("const vec4 ones = vec4(1);"); 242 inputColor = "ones"; 243 } 244 245 // emit blend code 246 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode)); 247 const char* childStr = childColor.c_str(); 248 if (ComposeOneFragmentProcessor::kDst_Child == child) { 249 GrGLSLBlend::AppendMode(fragBuilder, inputColor, childStr, args.fOutputColor, mode); 250 } else { 251 GrGLSLBlend::AppendMode(fragBuilder, childStr, inputColor, args.fOutputColor, mode); 252 } 253 } 254 255private: 256 typedef GrGLSLFragmentProcessor INHERITED; 257}; 258 259///////////////////////////////////////////////////////////////////// 260 261GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor); 262 263const GrFragmentProcessor* ComposeOneFragmentProcessor::TestCreate(GrProcessorTestData* d) { 264 // Create one random frag procs. 265 // For now, we'll prevent either children from being a shader with children to prevent the 266 // possibility of an arbitrarily large tree of procs. 267 SkAutoTUnref<const GrFragmentProcessor> dst(GrProcessorUnitTest::CreateChildFP(d)); 268 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>( 269 d->fRandom->nextRangeU(0, SkXfermode::kLastMode)); 270 ComposeOneFragmentProcessor::Child child = d->fRandom->nextBool() ? 271 ComposeOneFragmentProcessor::kDst_Child : 272 ComposeOneFragmentProcessor::kSrc_Child; 273 return new ComposeOneFragmentProcessor(dst, mode, child); 274} 275 276GrGLSLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLSLInstance() const { 277 return new GLComposeOneFragmentProcessor; 278} 279 280////////////////////////////////////////////////////////////////////////////// 281 282const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromDstProcessor( 283 const GrFragmentProcessor* dst, SkXfermode::Mode mode) { 284 switch (mode) { 285 case SkXfermode::kClear_Mode: 286 return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK, 287 GrConstColorProcessor::kIgnore_InputMode); 288 case SkXfermode::kSrc_Mode: 289 return nullptr; 290 default: 291 return new ComposeOneFragmentProcessor(dst, mode, 292 ComposeOneFragmentProcessor::kDst_Child); 293 } 294} 295 296const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromSrcProcessor( 297 const GrFragmentProcessor* src, SkXfermode::Mode mode) { 298 switch (mode) { 299 case SkXfermode::kClear_Mode: 300 return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK, 301 GrConstColorProcessor::kIgnore_InputMode); 302 case SkXfermode::kDst_Mode: 303 return nullptr; 304 default: 305 return new ComposeOneFragmentProcessor(src, mode, 306 ComposeOneFragmentProcessor::kSrc_Child); 307 } 308} 309