blob: bbf61cc76b2dd545f0a2e1d117e71d73c8322921 [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
cdalton3ccf2e72016-05-06 09:41:16 -0700232 bool onWillReadDstColor(const GrCaps&, const GrPipelineOptimizations&) const override {
robertphillipsf42fca42016-01-27 05:00:04 -0800233 return true;
234 }
235
236 bool onIsEqual(const GrXPFactory& xpfBase) const override { return true; }
237
238 GR_DECLARE_XP_FACTORY_TEST;
239
240 typedef GrXPFactory INHERITED;
241};
242
243GR_DEFINE_XP_FACTORY_TEST(GrOverdrawXPFactory);
244
245const GrXPFactory* GrOverdrawXPFactory::TestCreate(GrProcessorTestData* d) {
246 return GrOverdrawXPFactory::Create();
247}
248#endif
249
250///////////////////////////////////////////////////////////////////////////////
251class SkOverdrawXfermode : public SkXfermode {
252public:
253 static SkXfermode* Create() {
254 return new SkOverdrawXfermode;
255 }
256
257 SkPMColor xferColor(SkPMColor src, SkPMColor dst) const override {
258 // This table encodes the color progression of the overdraw visualization
259 static const SkPMColor gTable[] = {
260 SkPackARGB32(0x00, 0x00, 0x00, 0x00),
261 SkPackARGB32(0xFF, 128, 158, 255),
262 SkPackARGB32(0xFF, 170, 185, 212),
263 SkPackARGB32(0xFF, 213, 195, 170),
264 SkPackARGB32(0xFF, 255, 192, 127),
265 SkPackARGB32(0xFF, 255, 185, 85),
266 SkPackARGB32(0xFF, 255, 165, 42),
267 SkPackARGB32(0xFF, 255, 135, 0),
268 SkPackARGB32(0xFF, 255, 95, 0),
269 SkPackARGB32(0xFF, 255, 50, 0),
270 SkPackARGB32(0xFF, 255, 0, 0)
271 };
272
273
274 int nextIdx;
275 if (SkColorGetR(dst) < 64) { // dst color is the 0th color so the next color is 1
276 nextIdx = 1;
277 } else if (SkColorGetG(dst) < 25) { // dst color is the 10th color so cap there
278 nextIdx = 10;
279 } else if ((SkColorGetB(dst)+21)/42 > 0) { // dst color is one of 1-6
280 nextIdx = 8 - (SkColorGetB(dst)+21)/42;
281 } else { // dst color is between 7 and 9
282 nextIdx = 11 - (SkColorGetG(dst)+22)/45;
283 }
284 SkASSERT(nextIdx < (int)SK_ARRAY_COUNT(gTable));
285
286 return gTable[nextIdx];
287 }
288
289 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkOverdrawXfermode)
290
291#if SK_SUPPORT_GPU
robertphillips4f037942016-02-09 05:09:27 -0800292 const GrFragmentProcessor* getFragmentProcessorForImageFilter(
293 const GrFragmentProcessor* dst) const override {
294 return GrOverdrawFP::Create(dst);
robertphillipsf42fca42016-01-27 05:00:04 -0800295 }
296
robertphillips4f037942016-02-09 05:09:27 -0800297 GrXPFactory* asXPFactory() const override {
298 return GrOverdrawXPFactory::Create();
robertphillipsf42fca42016-01-27 05:00:04 -0800299 }
300#endif
301
302#ifndef SK_IGNORE_TO_STRING
303 void toString(SkString* str) const override { str->set("SkOverdrawXfermode"); }
304#endif
305
306private:
307 friend class SkOverdrawMode;
308
309 void flatten(SkWriteBuffer& buffer) const override { }
310
311 typedef SkXfermode INHERITED;
312};
313
reed60c9b582016-04-03 09:11:13 -0700314sk_sp<SkFlattenable> SkOverdrawXfermode::CreateProc(SkReadBuffer& buffer) {
315 return sk_sp<SkFlattenable>(Create());
robertphillipsf42fca42016-01-27 05:00:04 -0800316}
317
reedcfb6bdf2016-03-29 11:32:50 -0700318sk_sp<SkXfermode> SkOverdrawMode::Make() { return sk_make_sp<SkOverdrawXfermode>(); }
robertphillipsf42fca42016-01-27 05:00:04 -0800319
320SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkOverdrawMode)
321 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkOverdrawXfermode)
322SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END