blob: 1e018babdbd40944b021aecd8e60747505b2c6dd [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:
robertphillipsf42fca42016-01-27 05:00:04 -0800108 void emitCode(EmitArgs& args) override {
109 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
110 SkString dstColor("dstColor");
111 this->emitChild(0, nullptr, &dstColor, args);
112
113 add_overdraw_code(fragBuilder, dstColor.c_str(), args.fOutputColor);
114 }
115
116 static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*) { }
117
118private:
119 typedef GrGLSLFragmentProcessor INHERITED;
120};
121
122///////////////////////////////////////////////////////////////////////////////
123
124GrGLSLFragmentProcessor* GrOverdrawFP::onCreateGLSLInstance() const {
robertphillips9cdb9922016-02-03 12:25:40 -0800125 return new GLOverdrawFP;
robertphillipsf42fca42016-01-27 05:00:04 -0800126}
127
128void GrOverdrawFP::onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
129 GLOverdrawFP::GenKey(*this, caps, b);
130}
131
132const GrFragmentProcessor* GrOverdrawFP::TestCreate(GrProcessorTestData* d) {
133 SkAutoTUnref<const GrFragmentProcessor> dst(GrProcessorUnitTest::CreateChildFP(d));
134 return new GrOverdrawFP(dst);
135}
136
137GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrOverdrawFP);
138
139///////////////////////////////////////////////////////////////////////////////
140// Xfer Processor
141///////////////////////////////////////////////////////////////////////////////
142
143class OverdrawXP : public GrXferProcessor {
144public:
145 OverdrawXP(const DstTexture* dstTexture, bool hasMixedSamples)
146 : INHERITED(dstTexture, true, hasMixedSamples) {
147 this->initClassID<OverdrawXP>();
148 }
149
150 const char* name() const override { return "Overdraw"; }
151
152 GrGLSLXferProcessor* createGLSLInstance() const override;
153
154private:
155 GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations,
156 bool doesStencilWrite,
157 GrColor* overrideColor,
158 const GrCaps& caps) const override {
159 // We never look at the color input
160 return GrXferProcessor::kIgnoreColor_OptFlag;
161 }
162
163 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
164
165 bool onIsEqual(const GrXferProcessor&) const override { return true; }
166
167 typedef GrXferProcessor INHERITED;
168};
169
170///////////////////////////////////////////////////////////////////////////////
171
172class GLOverdrawXP : public GrGLSLXferProcessor {
173public:
174 GLOverdrawXP(const OverdrawXP&) { }
175
176 ~GLOverdrawXP() override {}
177
178 static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*) { }
179
180private:
181 void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder,
182 GrGLSLUniformHandler* uniformHandler,
183 const char* srcColor,
184 const char* srcCoverage,
185 const char* dstColor,
186 const char* outColor,
187 const char* outColorSecondary,
188 const GrXferProcessor& proc) override {
189 add_overdraw_code(fragBuilder, dstColor, outColor);
190
191 // Apply coverage.
192 INHERITED::DefaultCoverageModulation(fragBuilder, srcCoverage, dstColor, outColor,
193 outColorSecondary, proc);
194 }
195
196 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override { };
197
198 typedef GrGLSLXferProcessor INHERITED;
199};
200
201///////////////////////////////////////////////////////////////////////////////
202
203void OverdrawXP::onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
204 GLOverdrawXP::GenKey(*this, caps, b);
205}
206
207GrGLSLXferProcessor* OverdrawXP::createGLSLInstance() const { return new GLOverdrawXP(*this); }
208
209///////////////////////////////////////////////////////////////////////////////
210class GrOverdrawXPFactory : public GrXPFactory {
211public:
212 static GrXPFactory* Create() { return new GrOverdrawXPFactory(); }
213
214 void getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
215 GrXPFactory::InvariantBlendedColor* blendedColor) const override {
216 blendedColor->fWillBlendWithDst = true;
217 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
218 }
219
220private:
221 GrOverdrawXPFactory() {
222 this->initClassID<GrOverdrawXPFactory>();
223 }
224
225 GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
226 const GrPipelineOptimizations& optimizations,
227 bool hasMixedSamples,
228 const DstTexture* dstTexture) const override {
229 return new OverdrawXP(dstTexture, hasMixedSamples);
230 }
231
ethannicholas22793252016-01-30 09:59:10 -0800232 bool onWillReadDstColor(const GrCaps& caps,
233 const GrPipelineOptimizations& optimizations,
234 bool hasMixedSamples) const override {
robertphillipsf42fca42016-01-27 05:00:04 -0800235 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
245GR_DEFINE_XP_FACTORY_TEST(GrOverdrawXPFactory);
246
247const GrXPFactory* GrOverdrawXPFactory::TestCreate(GrProcessorTestData* d) {
248 return GrOverdrawXPFactory::Create();
249}
250#endif
251
252///////////////////////////////////////////////////////////////////////////////
253class SkOverdrawXfermode : public SkXfermode {
254public:
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 visualization
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 nextIdx;
277 if (SkColorGetR(dst) < 64) { // dst color is the 0th color so the next color is 1
278 nextIdx = 1;
279 } else if (SkColorGetG(dst) < 25) { // dst color is the 10th color so cap there
280 nextIdx = 10;
281 } else if ((SkColorGetB(dst)+21)/42 > 0) { // dst color is one of 1-6
282 nextIdx = 8 - (SkColorGetB(dst)+21)/42;
283 } else { // dst color is between 7 and 9
284 nextIdx = 11 - (SkColorGetG(dst)+22)/45;
285 }
286 SkASSERT(nextIdx < (int)SK_ARRAY_COUNT(gTable));
287
288 return gTable[nextIdx];
289 }
290
291 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkOverdrawXfermode)
292
293#if SK_SUPPORT_GPU
robertphillips4f037942016-02-09 05:09:27 -0800294 const GrFragmentProcessor* getFragmentProcessorForImageFilter(
295 const GrFragmentProcessor* dst) const override {
296 return GrOverdrawFP::Create(dst);
robertphillipsf42fca42016-01-27 05:00:04 -0800297 }
298
robertphillips4f037942016-02-09 05:09:27 -0800299 GrXPFactory* asXPFactory() const override {
300 return GrOverdrawXPFactory::Create();
robertphillipsf42fca42016-01-27 05:00:04 -0800301 }
302#endif
303
304#ifndef SK_IGNORE_TO_STRING
305 void toString(SkString* str) const override { str->set("SkOverdrawXfermode"); }
306#endif
307
308private:
309 friend class SkOverdrawMode;
310
311 void flatten(SkWriteBuffer& buffer) const override { }
312
313 typedef SkXfermode INHERITED;
314};
315
reed60c9b582016-04-03 09:11:13 -0700316sk_sp<SkFlattenable> SkOverdrawXfermode::CreateProc(SkReadBuffer& buffer) {
317 return sk_sp<SkFlattenable>(Create());
robertphillipsf42fca42016-01-27 05:00:04 -0800318}
319
reedcfb6bdf2016-03-29 11:32:50 -0700320sk_sp<SkXfermode> SkOverdrawMode::Make() { return sk_make_sp<SkOverdrawXfermode>(); }
robertphillipsf42fca42016-01-27 05:00:04 -0800321
322SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkOverdrawMode)
323 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkOverdrawXfermode)
324SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END