OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
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 "effects/GrXfermodeFragmentProcessor.h" | 8 #include "effects/GrXfermodeFragmentProcessor.h" |
9 | 9 |
10 #include "GrFragmentProcessor.h" | 10 #include "GrFragmentProcessor.h" |
11 #include "effects/GrConstColorProcessor.h" | 11 #include "effects/GrConstColorProcessor.h" |
12 #include "gl/GrGLBlend.h" | 12 #include "gl/GrGLSLBlend.h" |
13 #include "gl/builders/GrGLProgramBuilder.h" | 13 #include "gl/builders/GrGLProgramBuilder.h" |
| 14 #include "SkGr.h" |
14 | 15 |
15 | 16 class ComposeTwoFragmentProcessor : public GrFragmentProcessor { |
16 class GrComposeTwoFragmentProcessor : public GrFragmentProcessor { | |
17 public: | 17 public: |
18 GrComposeTwoFragmentProcessor(const GrFragmentProcessor* src, const GrFragme
ntProcessor* dst, | 18 ComposeTwoFragmentProcessor(const GrFragmentProcessor* src, const GrFragment
Processor* dst, |
19 SkXfermode::Mode mode) | 19 SkXfermode::Mode mode) |
20 : fMode(mode) { | 20 : fMode(mode) { |
21 // Only coefficient xfer modes are supported | 21 this->initClassID<ComposeTwoFragmentProcessor>(); |
22 SkASSERT(SkXfermode::kLastCoeffMode >= mode); | |
23 this->initClassID<GrComposeTwoFragmentProcessor>(); | |
24 SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(src); | 22 SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(src); |
25 SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(dst); | 23 SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(dst); |
26 SkASSERT(0 == shaderAChildIndex); | 24 SkASSERT(0 == shaderAChildIndex); |
27 SkASSERT(1 == shaderBChildIndex); | 25 SkASSERT(1 == shaderBChildIndex); |
28 } | 26 } |
29 | 27 |
30 const char* name() const override { return "ComposeShader"; } | 28 const char* name() const override { return "ComposeTwo"; } |
31 | 29 |
32 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override { | 30 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override { |
33 b->add32(fMode); | 31 b->add32(fMode); |
34 } | 32 } |
35 | 33 |
36 SkXfermode::Mode getMode() const { return fMode; } | 34 SkXfermode::Mode getMode() const { return fMode; } |
37 | 35 |
38 protected: | 36 protected: |
39 bool onIsEqual(const GrFragmentProcessor& other) const override { | 37 bool onIsEqual(const GrFragmentProcessor& other) const override { |
40 const GrComposeTwoFragmentProcessor& cs = other.cast<GrComposeTwoFragmen
tProcessor>(); | 38 const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentPro
cessor>(); |
41 return fMode == cs.fMode; | 39 return fMode == cs.fMode; |
42 } | 40 } |
43 | 41 |
44 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | 42 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
45 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); | 43 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); |
46 } | 44 } |
47 | 45 |
48 private: | 46 private: |
49 GrGLFragmentProcessor* onCreateGLInstance() const override; | 47 GrGLFragmentProcessor* onCreateGLInstance() const override; |
50 | 48 |
51 SkXfermode::Mode fMode; | 49 SkXfermode::Mode fMode; |
52 | 50 |
53 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; | 51 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; |
54 | 52 |
55 typedef GrFragmentProcessor INHERITED; | 53 typedef GrFragmentProcessor INHERITED; |
56 }; | 54 }; |
57 | 55 |
58 ///////////////////////////////////////////////////////////////////// | 56 ///////////////////////////////////////////////////////////////////// |
59 | 57 |
60 class GrGLComposeTwoFragmentProcessor : public GrGLFragmentProcessor { | 58 class GLComposeTwoFragmentProcessor : public GrGLFragmentProcessor { |
61 public: | 59 public: |
62 GrGLComposeTwoFragmentProcessor(const GrProcessor& processor) {} | 60 GLComposeTwoFragmentProcessor(const GrProcessor& processor) {} |
63 | 61 |
64 void emitCode(EmitArgs&) override; | 62 void emitCode(EmitArgs&) override; |
65 | 63 |
66 private: | 64 private: |
67 typedef GrGLFragmentProcessor INHERITED; | 65 typedef GrGLFragmentProcessor INHERITED; |
68 }; | 66 }; |
69 | 67 |
70 ///////////////////////////////////////////////////////////////////// | 68 ///////////////////////////////////////////////////////////////////// |
71 | 69 |
72 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrComposeTwoFragmentProcessor); | 70 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor); |
73 | 71 |
74 const GrFragmentProcessor* GrComposeTwoFragmentProcessor::TestCreate(GrProcessor
TestData* d) { | 72 const GrFragmentProcessor* ComposeTwoFragmentProcessor::TestCreate(GrProcessorTe
stData* d) { |
75 // Create two random frag procs. | 73 // Create two random frag procs. |
76 SkAutoTUnref<const GrFragmentProcessor> fpA(GrProcessorUnitTest::CreateChild
FP(d)); | 74 SkAutoTUnref<const GrFragmentProcessor> fpA(GrProcessorUnitTest::CreateChild
FP(d)); |
77 SkAutoTUnref<const GrFragmentProcessor> fpB(GrProcessorUnitTest::CreateChild
FP(d)); | 75 SkAutoTUnref<const GrFragmentProcessor> fpB(GrProcessorUnitTest::CreateChild
FP(d)); |
78 | 76 |
79 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>( | 77 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>( |
80 d->fRandom->nextRangeU(0, SkXfermode::kLastCoeffMode)); | 78 d->fRandom->nextRangeU(0, SkXfermode::kLastMode)); |
81 return SkNEW_ARGS(GrComposeTwoFragmentProcessor, (fpA, fpB, mode)); | 79 return new ComposeTwoFragmentProcessor(fpA, fpB, mode); |
82 } | 80 } |
83 | 81 |
84 GrGLFragmentProcessor* GrComposeTwoFragmentProcessor::onCreateGLInstance() const
{ | 82 GrGLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLInstance() const{ |
85 return SkNEW_ARGS(GrGLComposeTwoFragmentProcessor, (*this)); | 83 return new GLComposeTwoFragmentProcessor(*this); |
86 } | 84 } |
87 | 85 |
88 ///////////////////////////////////////////////////////////////////// | 86 ///////////////////////////////////////////////////////////////////// |
89 | 87 |
90 void GrGLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) { | 88 void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) { |
91 | 89 |
92 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); | 90 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); |
93 const GrComposeTwoFragmentProcessor& cs = args.fFp.cast<GrComposeTwoFragment
Processor>(); | 91 const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProc
essor>(); |
94 | 92 |
95 // Store alpha of input color and un-premultiply the input color by its alph
a. We will | 93 // Store alpha of input color and un-premultiply the input color by its alph
a. We will |
96 // re-multiply by this alpha after blending the output colors of the two chi
ld procs. | 94 // re-multiply by this alpha after blending the output colors of the two chi
ld procs. |
97 // This is because we don't want the paint's alpha to affect either child pr
oc's output | 95 // This is because we don't want the paint's alpha to affect either child pr
oc's output |
98 // before the blend; we want to apply the paint's alpha AFTER the blend. Thi
s mirrors the | 96 // before the blend; we want to apply the paint's alpha AFTER the blend. Thi
s mirrors the |
99 // software implementation of SkComposeShader. | 97 // software implementation of SkComposeShader. |
100 const char* opaqueInput = nullptr; | 98 const char* opaqueInput = nullptr; |
101 const char* inputAlpha = nullptr; | 99 const char* inputAlpha = nullptr; |
102 if (args.fInputColor) { | 100 if (args.fInputColor) { |
103 inputAlpha = "inputAlpha"; | 101 inputAlpha = "inputAlpha"; |
(...skipping 11 matching lines...) Expand all Loading... |
115 | 113 |
116 SkString outputColorDst(args.fOutputColor); | 114 SkString outputColorDst(args.fOutputColor); |
117 outputColorDst.append("_dst"); | 115 outputColorDst.append("_dst"); |
118 fsBuilder->codeAppendf("vec4 %s;\n", outputColorDst.c_str()); | 116 fsBuilder->codeAppendf("vec4 %s;\n", outputColorDst.c_str()); |
119 this->emitChild(1, opaqueInput, outputColorDst.c_str(), args); | 117 this->emitChild(1, opaqueInput, outputColorDst.c_str(), args); |
120 | 118 |
121 // emit blend code | 119 // emit blend code |
122 SkXfermode::Mode mode = cs.getMode(); | 120 SkXfermode::Mode mode = cs.getMode(); |
123 fsBuilder->codeAppend("{"); | 121 fsBuilder->codeAppend("{"); |
124 fsBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mo
de)); | 122 fsBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mo
de)); |
125 GrGLBlend::AppendPorterDuffBlend(fsBuilder, outputColorSrc.c_str(), | 123 GrGLSLBlend::AppendMode(fsBuilder, outputColorSrc.c_str(), |
126 outputColorDst.c_str(), args.fOutputColor,
mode); | 124 outputColorDst.c_str(), args.fOutputColor, mode); |
127 fsBuilder->codeAppend("}"); | 125 fsBuilder->codeAppend("}"); |
128 | 126 |
129 // re-multiply the output color by the input color's alpha | 127 // re-multiply the output color by the input color's alpha |
130 if (inputAlpha) { | 128 if (inputAlpha) { |
131 fsBuilder->codeAppendf("%s *= %s;", args.fOutputColor, inputAlpha); | 129 fsBuilder->codeAppendf("%s *= %s;", args.fOutputColor, inputAlpha); |
132 } | 130 } |
133 } | 131 } |
134 | 132 |
135 const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromTwoProcessors( | 133 const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromTwoProcessors( |
136 const GrFragmentProcessor* src, const GrFragmentProcessor* dst, SkXferm
ode::Mode mode) { | 134 const GrFragmentProcessor* src, const GrFragmentProcessor* dst, SkXferm
ode::Mode mode) { |
137 if (SkXfermode::kLastCoeffMode < mode) { | |
138 return nullptr; | |
139 } | |
140 switch (mode) { | 135 switch (mode) { |
141 case SkXfermode::kClear_Mode: | 136 case SkXfermode::kClear_Mode: |
142 return GrConstColorProcessor::Create(GrColor_TRANS_BLACK, | 137 return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK, |
143 GrConstColorProcessor::kIgnore_
InputMode); | 138 GrConstColorProcessor::kIgnore_
InputMode); |
144 break; | |
145 case SkXfermode::kSrc_Mode: | 139 case SkXfermode::kSrc_Mode: |
146 return SkRef(src); | 140 return SkRef(src); |
147 break; | |
148 case SkXfermode::kDst_Mode: | 141 case SkXfermode::kDst_Mode: |
149 return SkRef(dst); | 142 return SkRef(dst); |
150 break; | |
151 default: | 143 default: |
152 return new GrComposeTwoFragmentProcessor(src, dst, mode); | 144 return new ComposeTwoFragmentProcessor(src, dst, mode); |
153 } | 145 } |
154 } | 146 } |
| 147 |
| 148 ////////////////////////////////////////////////////////////////////////////// |
| 149 |
| 150 class ComposeOneFragmentProcessor : public GrFragmentProcessor { |
| 151 public: |
| 152 enum Child { |
| 153 kDst_Child, |
| 154 kSrc_Child, |
| 155 }; |
| 156 |
| 157 ComposeOneFragmentProcessor(const GrFragmentProcessor* dst, SkXfermode::Mode
mode, Child child) |
| 158 : fMode(mode) |
| 159 , fChild(child) { |
| 160 this->initClassID<ComposeOneFragmentProcessor>(); |
| 161 SkDEBUGCODE(int dstIndex = )this->registerChildProcessor(dst); |
| 162 SkASSERT(0 == dstIndex); |
| 163 } |
| 164 |
| 165 const char* name() const override { return "ComposeOne"; } |
| 166 |
| 167 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override { |
| 168 GR_STATIC_ASSERT((SkXfermode::kLastMode & SK_MaxU16) == SkXfermode::kLas
tMode); |
| 169 b->add32(fMode | (fChild << 16)); |
| 170 } |
| 171 |
| 172 SkXfermode::Mode mode() const { return fMode; } |
| 173 |
| 174 Child child() const { return fChild; } |
| 175 |
| 176 protected: |
| 177 bool onIsEqual(const GrFragmentProcessor& that) const override { |
| 178 return fMode == that.cast<ComposeOneFragmentProcessor>().fMode; |
| 179 } |
| 180 |
| 181 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
| 182 SkXfermode::Coeff skSrcCoeff, skDstCoeff; |
| 183 if (SkXfermode::ModeAsCoeff(fMode, &skSrcCoeff, &skDstCoeff)) { |
| 184 GrBlendCoeff srcCoeff = SkXfermodeCoeffToGrBlendCoeff(skSrcCoeff); |
| 185 GrBlendCoeff dstCoeff = SkXfermodeCoeffToGrBlendCoeff(skDstCoeff); |
| 186 GrInvariantOutput childOutput(0xFFFFFFFF, kRGBA_GrColorComponentFlag
s, false); |
| 187 this->childProcessor(0).computeInvariantOutput(&childOutput); |
| 188 GrColor blendColor; |
| 189 GrColorComponentFlags blendFlags; |
| 190 if (kDst_Child == fChild) { |
| 191 GrGetCoeffBlendKnownComponents(srcCoeff, dstCoeff, |
| 192 inout->color(), inout->validFlags
(), |
| 193 childOutput.color(), childOutput.
validFlags(), |
| 194 &blendColor, &blendFlags); |
| 195 } else { |
| 196 GrGetCoeffBlendKnownComponents(srcCoeff, dstCoeff, |
| 197 childOutput.color(), childOutput.
validFlags(), |
| 198 inout->color(), inout->validFlags
(), |
| 199 &blendColor, &blendFlags); |
| 200 } |
| 201 // will the shader code reference the input color? |
| 202 GrInvariantOutput::ReadInput readsInput = GrInvariantOutput::kWillNo
t_ReadInput; |
| 203 if (kDst_Child == fChild) { |
| 204 if (kZero_GrBlendCoeff != srcCoeff || GrBlendCoeffRefsSrc(dstCoe
ff)) { |
| 205 readsInput = GrInvariantOutput::kWill_ReadInput; |
| 206 } |
| 207 } else { |
| 208 if (kZero_GrBlendCoeff != dstCoeff || GrBlendCoeffRefsDst(srcCoe
ff)) { |
| 209 readsInput = GrInvariantOutput::kWill_ReadInput; |
| 210 } |
| 211 } |
| 212 inout->setToOther(blendFlags, blendColor, readsInput); |
| 213 } else { |
| 214 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); |
| 215 } |
| 216 } |
| 217 |
| 218 private: |
| 219 GrGLFragmentProcessor* onCreateGLInstance() const override; |
| 220 |
| 221 SkXfermode::Mode fMode; |
| 222 Child fChild; |
| 223 |
| 224 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; |
| 225 |
| 226 typedef GrFragmentProcessor INHERITED; |
| 227 }; |
| 228 |
| 229 ////////////////////////////////////////////////////////////////////////////// |
| 230 |
| 231 class GLComposeOneFragmentProcessor : public GrGLFragmentProcessor { |
| 232 public: |
| 233 GLComposeOneFragmentProcessor(const GrProcessor& processor) {} |
| 234 |
| 235 void emitCode(EmitArgs& args) override { |
| 236 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder
(); |
| 237 SkXfermode::Mode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mod
e(); |
| 238 ComposeOneFragmentProcessor::Child child = |
| 239 args.fFp.cast<ComposeOneFragmentProcessor>().child(); |
| 240 // declare _dstColor and emit the code for the two child |
| 241 fsBuilder->codeAppendf("vec4 _child;"); |
| 242 this->emitChild(0, nullptr, "_child", args); |
| 243 |
| 244 const char* inputColor = args.fInputColor; |
| 245 // We don't try to optimize for this case at all |
| 246 if (!inputColor) { |
| 247 fsBuilder->codeAppendf("const vec4 ones = vec4(1);"); |
| 248 inputColor = "ones"; |
| 249 } |
| 250 |
| 251 // emit blend code |
| 252 fsBuilder->codeAppend("{"); |
| 253 fsBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeNam
e(mode)); |
| 254 if (ComposeOneFragmentProcessor::kDst_Child == child) { |
| 255 GrGLSLBlend::AppendMode(fsBuilder, inputColor, "_child", args.fOutpu
tColor, mode); |
| 256 } else { |
| 257 GrGLSLBlend::AppendMode(fsBuilder, "_child", inputColor, args.fOutpu
tColor, mode); |
| 258 } |
| 259 fsBuilder->codeAppend("}"); |
| 260 } |
| 261 |
| 262 private: |
| 263 typedef GrGLFragmentProcessor INHERITED; |
| 264 }; |
| 265 |
| 266 ///////////////////////////////////////////////////////////////////// |
| 267 |
| 268 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor); |
| 269 |
| 270 const GrFragmentProcessor* ComposeOneFragmentProcessor::TestCreate(GrProcessorTe
stData* d) { |
| 271 // Create one random frag procs. |
| 272 // For now, we'll prevent either children from being a shader with children
to prevent the |
| 273 // possibility of an arbitrarily large tree of procs. |
| 274 SkAutoTUnref<const GrFragmentProcessor> dst(GrProcessorUnitTest::CreateChild
FP(d)); |
| 275 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>( |
| 276 d->fRandom->nextRangeU(0, SkXfermode::kLastMode)); |
| 277 ComposeOneFragmentProcessor::Child child = d->fRandom->nextBool() ? |
| 278 ComposeOneFragmentProcessor::kDst_Child : |
| 279 ComposeOneFragmentProcessor::kSrc_Child; |
| 280 return new ComposeOneFragmentProcessor(dst, mode, child); |
| 281 } |
| 282 |
| 283 GrGLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLInstance() const { |
| 284 return new GLComposeOneFragmentProcessor(*this); |
| 285 } |
| 286 |
| 287 ////////////////////////////////////////////////////////////////////////////// |
| 288 |
| 289 const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromDstProcessor( |
| 290 const GrFragmentProcessor* dst, SkXfermode::Mode mode) { |
| 291 switch (mode) { |
| 292 case SkXfermode::kClear_Mode: |
| 293 return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK, |
| 294 GrConstColorProcessor::kIgnore_
InputMode); |
| 295 case SkXfermode::kSrc_Mode: |
| 296 return nullptr; |
| 297 default: |
| 298 return new ComposeOneFragmentProcessor(dst, mode, |
| 299 ComposeOneFragmentProcessor::
kDst_Child); |
| 300 } |
| 301 } |
| 302 |
| 303 const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromSrcProcessor( |
| 304 const GrFragmentProcessor* src, SkXfermode::Mode mode) { |
| 305 switch (mode) { |
| 306 case SkXfermode::kClear_Mode: |
| 307 return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK, |
| 308 GrConstColorProcessor::kIgnore_
InputMode); |
| 309 case SkXfermode::kDst_Mode: |
| 310 return nullptr; |
| 311 default: |
| 312 return new ComposeOneFragmentProcessor(src, mode, |
| 313 ComposeOneFragmentProcessor::
kSrc_Child); |
| 314 } |
| 315 } |
OLD | NEW |