OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2016 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 "SkOverdrawMode.h" | |
9 #include "SkXfermode.h" | |
10 | |
11 #if SK_SUPPORT_GPU | |
12 #include "GrFragmentProcessor.h" | |
13 #include "GrInvariantOutput.h" | |
14 #include "GrXferProcessor.h" | |
15 #include "glsl/GrGLSLFragmentProcessor.h" | |
16 #include "glsl/GrGLSLFragmentShaderBuilder.h" | |
17 #include "glsl/GrGLSLXferProcessor.h" | |
18 | |
19 /////////////////////////////////////////////////////////////////////////////// | |
20 // Fragment Processor | |
21 /////////////////////////////////////////////////////////////////////////////// | |
22 | |
23 class GLOverdrawFP; | |
24 | |
25 class GrOverdrawFP : public GrFragmentProcessor { | |
26 public: | |
27 static const GrFragmentProcessor* Create(const GrFragmentProcessor* dst) { | |
28 return new GrOverdrawFP(dst); | |
29 } | |
30 | |
31 ~GrOverdrawFP() override { } | |
32 | |
33 const char* name() const override { return "Overdraw"; } | |
34 | |
35 SkString dumpInfo() const override { | |
36 SkString str; | |
37 return str; | |
38 } | |
39 | |
40 private: | |
41 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; | |
42 | |
43 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder* b) cons t override; | |
44 | |
45 bool onIsEqual(const GrFragmentProcessor&) const override { return true; } | |
46 | |
47 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | |
48 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); | |
49 } | |
50 | |
51 GrOverdrawFP(const GrFragmentProcessor* dst) { | |
52 this->initClassID<GrOverdrawFP>(); | |
53 | |
54 SkASSERT(dst); | |
55 SkDEBUGCODE(int dstIndex = )this->registerChildProcessor(dst); | |
56 SkASSERT(0 == dstIndex); | |
57 } | |
58 | |
59 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; | |
60 typedef GrFragmentProcessor INHERITED; | |
61 }; | |
62 | |
63 /////////////////////////////////////////////////////////////////////////////// | |
64 | |
65 static void add_overdraw_code(GrGLSLFragmentBuilder* fragBuilder, | |
66 const char* dstColor, | |
67 const char* outputColor) { | |
68 | |
69 fragBuilder->codeAppend("vec4 gTable[11] = vec4[11]("); | |
70 fragBuilder->codeAppend("vec4(0, 0, 0, 0.0),"); | |
71 fragBuilder->codeAppend("vec4(0.5, 0.617, 1.0, 1.0),"); | |
72 fragBuilder->codeAppend("vec4(0.664, 0.723, 0.83, 1.0),"); | |
73 fragBuilder->codeAppend("vec4(0.832, 0.762, 0.664, 1.0),"); | |
74 fragBuilder->codeAppend("vec4(1, 0.75, 0.496, 1.0),"); | |
75 fragBuilder->codeAppend("vec4(1, 0.723, 0.332, 1.0),"); | |
76 fragBuilder->codeAppend("vec4(1, 0.645, 0.164, 1.0),"); | |
77 fragBuilder->codeAppend("vec4(1, 0.527, 0, 1.0),"); | |
78 fragBuilder->codeAppend("vec4(1, 0.371, 0, 1.0),"); | |
79 fragBuilder->codeAppend("vec4(1, 0.195, 0, 1.0),"); | |
80 fragBuilder->codeAppend("vec4(1, 0, 0, 1.0)"); | |
81 fragBuilder->codeAppend(");"); | |
82 | |
83 fragBuilder->codeAppend("int idx;"); | |
84 fragBuilder->codeAppendf("vec4 dst = %s;", dstColor); | |
85 fragBuilder->codeAppend("if (dst.r < 0.25) { idx = 0; }"); | |
86 // cap 'idx' at 9 for upcoming increment | |
87 fragBuilder->codeAppend("else if (dst.g < 0.0977) { idx = 9; }"); | |
88 fragBuilder->codeAppend("else if (dst.b > 0.08) { idx = 7 - int(6 * dst.b + 0.5); }"); | |
89 fragBuilder->codeAppend("else { idx = 10 - int(5.7 * dst.g + 0.5); }"); | |
90 fragBuilder->codeAppend("idx++;"); | |
91 fragBuilder->codeAppendf("%s = gTable[idx];", outputColor); | |
92 } | |
93 | |
94 class GLOverdrawFP : public GrGLSLFragmentProcessor { | |
95 public: | |
96 GLOverdrawFP(const GrOverdrawFP&) {} | |
97 | |
98 ~GLOverdrawFP() override {} | |
99 | |
100 void emitCode(EmitArgs& args) override { | |
101 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; | |
102 SkString dstColor("dstColor"); | |
103 this->emitChild(0, nullptr, &dstColor, args); | |
104 | |
105 add_overdraw_code(fragBuilder, dstColor.c_str(), args.fOutputColor); | |
106 } | |
107 | |
108 static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuil der*) { } | |
109 | |
110 private: | |
111 typedef GrGLSLFragmentProcessor INHERITED; | |
112 }; | |
113 | |
114 /////////////////////////////////////////////////////////////////////////////// | |
115 | |
116 GrGLSLFragmentProcessor* GrOverdrawFP::onCreateGLSLInstance() const { | |
117 return new GLOverdrawFP(*this); | |
118 } | |
119 | |
120 void GrOverdrawFP::onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyB uilder* b) const { | |
121 GLOverdrawFP::GenKey(*this, caps, b); | |
122 } | |
123 | |
124 const GrFragmentProcessor* GrOverdrawFP::TestCreate(GrProcessorTestData* d) { | |
125 SkAutoTUnref<const GrFragmentProcessor> dst(GrProcessorUnitTest::CreateChild FP(d)); | |
126 return new GrOverdrawFP(dst); | |
127 } | |
128 | |
129 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrOverdrawFP); | |
130 | |
131 /////////////////////////////////////////////////////////////////////////////// | |
132 // Xfer Processor | |
133 /////////////////////////////////////////////////////////////////////////////// | |
134 | |
135 class OverdrawXP : public GrXferProcessor { | |
136 public: | |
137 OverdrawXP(const DstTexture* dstTexture, bool hasMixedSamples) | |
138 : INHERITED(dstTexture, true, hasMixedSamples) { | |
139 this->initClassID<OverdrawXP>(); | |
140 } | |
141 | |
142 const char* name() const override { return "Overdraw"; } | |
143 | |
144 GrGLSLXferProcessor* createGLSLInstance() const override; | |
145 | |
146 private: | |
147 GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations, | |
148 bool doesStencilWrite, | |
149 GrColor* overrideColor, | |
150 const GrCaps& caps) const overr ide { | |
151 return GrXferProcessor::kNone_OptFlags; | |
egdaniel
2016/01/20 14:28:34
I think this can return ignore color right?
robertphillips
2016/01/20 15:45:10
Done.
| |
152 } | |
153 | |
154 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override; | |
155 | |
156 bool onIsEqual(const GrXferProcessor&) const override { return true; } | |
157 | |
158 typedef GrXferProcessor INHERITED; | |
159 }; | |
160 | |
161 /////////////////////////////////////////////////////////////////////////////// | |
162 | |
163 class GLOverdrawXP : public GrGLSLXferProcessor { | |
164 public: | |
165 GLOverdrawXP(const OverdrawXP&) { } | |
166 | |
167 ~GLOverdrawXP() override {} | |
168 | |
169 static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuil der*) { } | |
170 | |
171 private: | |
172 void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder, | |
173 GrGLSLUniformHandler* uniformHandler, | |
174 const char* srcColor, | |
175 const char* srcCoverage, | |
176 const char* dstColor, | |
177 const char* outColor, | |
178 const char* outColorSecondary, | |
179 const GrXferProcessor& proc) override { | |
180 add_overdraw_code(fragBuilder, dstColor, outColor); | |
181 | |
182 // Apply coverage. | |
183 if (proc.dstReadUsesMixedSamples()) { | |
egdaniel
2016/01/20 14:28:34
Instead of copying and pasting this code into almo
robertphillips
2016/01/20 15:45:10
Done.
| |
184 if (srcCoverage) { | |
185 fragBuilder->codeAppendf("%s *= %s;", outColor, srcCoverage); | |
186 fragBuilder->codeAppendf("%s = %s;", outColorSecondary, srcCover age); | |
187 } else { | |
188 fragBuilder->codeAppendf("%s = vec4(1.0);", outColorSecondary); | |
189 } | |
190 } else if (srcCoverage) { | |
191 fragBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;", | |
192 outColor, srcCoverage, outColor, srcCoverage, dstColor); | |
193 } | |
194 } | |
195 | |
196 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) over ride { }; | |
197 | |
198 typedef GrGLSLXferProcessor INHERITED; | |
199 }; | |
200 | |
201 /////////////////////////////////////////////////////////////////////////////// | |
202 | |
203 void OverdrawXP::onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBui lder* b) const { | |
204 GLOverdrawXP::GenKey(*this, caps, b); | |
205 } | |
206 | |
207 GrGLSLXferProcessor* OverdrawXP::createGLSLInstance() const { return new GLOverd rawXP(*this); } | |
208 | |
209 /////////////////////////////////////////////////////////////////////////////// | |
210 class GrOverdrawXPFactory : public GrXPFactory { | |
211 public: | |
212 static GrXPFactory* Create() { return new GrOverdrawXPFactory(); } | |
213 | |
214 void getInvariantBlendedColor(const GrProcOptInfo& colorPOI, | |
215 GrXPFactory::InvariantBlendedColor* blendedCol or) const override { | |
216 blendedColor->fWillBlendWithDst = true; | |
217 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; | |
218 } | |
219 | |
220 private: | |
221 GrOverdrawXPFactory() { | |
222 this->initClassID<GrOverdrawXPFactory>(); | |
223 } | |
224 | |
225 GrXferProcessor* onCreateXferProcessor(const GrCaps& caps, | |
226 const GrPipelineOptimizations& optimi zations, | |
227 bool hasMixedSamples, | |
228 const DstTexture* dstTexture) const o verride { | |
229 return new OverdrawXP(dstTexture, hasMixedSamples); | |
230 } | |
231 | |
232 bool willReadDstColor(const GrCaps& caps, | |
233 const GrPipelineOptimizations& optimizations, | |
234 bool hasMixedSamples) const override { | |
235 return true; | |
236 } | |
237 | |
238 bool onIsEqual(const GrXPFactory& xpfBase) const override { return true; } | |
239 | |
240 GR_DECLARE_XP_FACTORY_TEST; | |
241 | |
242 typedef GrXPFactory INHERITED; | |
243 }; | |
244 | |
245 GR_DEFINE_XP_FACTORY_TEST(GrOverdrawXPFactory); | |
246 | |
247 const GrXPFactory* GrOverdrawXPFactory::TestCreate(GrProcessorTestData* d) { | |
248 return GrOverdrawXPFactory::Create(); | |
249 } | |
250 #endif | |
251 | |
252 /////////////////////////////////////////////////////////////////////////////// | |
253 class SkOverdrawXfermode : public SkXfermode { | |
254 public: | |
255 static SkXfermode* Create() { | |
256 return new SkOverdrawXfermode; | |
257 } | |
258 | |
259 SkPMColor xferColor(SkPMColor src, SkPMColor dst) const override { | |
260 // This table encodes the color progression of the overdraw visualizatio n | |
261 static const SkPMColor gTable[] = { | |
262 SkPackARGB32(0x00, 0x00, 0x00, 0x00), | |
263 SkPackARGB32(0xFF, 128, 158, 255), | |
264 SkPackARGB32(0xFF, 170, 185, 212), | |
265 SkPackARGB32(0xFF, 213, 195, 170), | |
266 SkPackARGB32(0xFF, 255, 192, 127), | |
267 SkPackARGB32(0xFF, 255, 185, 85), | |
268 SkPackARGB32(0xFF, 255, 165, 42), | |
269 SkPackARGB32(0xFF, 255, 135, 0), | |
270 SkPackARGB32(0xFF, 255, 95, 0), | |
271 SkPackARGB32(0xFF, 255, 50, 0), | |
272 SkPackARGB32(0xFF, 255, 0, 0) | |
273 }; | |
274 | |
275 | |
276 int idx; | |
277 if (SkColorGetR(dst) < 64) { // 0 | |
278 idx = 0; | |
279 } else if (SkColorGetG(dst) < 25) { // 10 | |
280 idx = 9; // cap at 9 for upcoming increment | |
281 } else if ((SkColorGetB(dst)+21)/42 > 0) { // 1-6 | |
282 idx = 7 - (SkColorGetB(dst)+21)/42; | |
283 } else { // 7-9 | |
284 idx = 10 - (SkColorGetG(dst)+22)/45; | |
285 } | |
286 ++idx; | |
egdaniel
2016/01/20 14:28:34
Why is this +1 here? Why not either get right of t
robertphillips
2016/01/20 15:45:10
Done. Here and in the gpu implementation.
| |
287 SkASSERT(idx < (int)SK_ARRAY_COUNT(gTable)); | |
288 | |
289 return gTable[idx]; | |
290 } | |
291 | |
292 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkOverdrawXfermode) | |
293 | |
294 #if SK_SUPPORT_GPU | |
295 bool asFragmentProcessor(const GrFragmentProcessor** output, | |
296 const GrFragmentProcessor* dst) const override { | |
297 if (output) { | |
298 *output = GrOverdrawFP::Create(dst); | |
299 } | |
300 return true; | |
301 } | |
302 | |
303 bool asXPFactory(GrXPFactory** xpf) const override { | |
304 if (xpf) { | |
305 *xpf = GrOverdrawXPFactory::Create(); | |
306 } | |
307 return true; | |
308 } | |
309 #endif | |
310 | |
311 #ifndef SK_IGNORE_TO_STRING | |
312 void toString(SkString* str) const override { str->set("SkOverdrawXfermode") ; } | |
313 #endif | |
314 | |
315 private: | |
316 friend class SkOverdrawMode; | |
317 | |
318 void flatten(SkWriteBuffer& buffer) const override { } | |
319 | |
320 typedef SkXfermode INHERITED; | |
321 }; | |
322 | |
323 SkFlattenable* SkOverdrawXfermode::CreateProc(SkReadBuffer& buffer) { | |
324 return Create(); | |
325 } | |
326 | |
327 SkXfermode* SkOverdrawMode::Create() { return new SkOverdrawXfermode; } | |
328 | |
329 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkOverdrawMode) | |
330 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkOverdrawXfermode) | |
331 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | |
OLD | NEW |