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