blob: 58b47edc8cd868a81b071035f7dece8d4b149794 [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:
bungeman06ca8ec2016-06-09 08:01:03 -070029 static sk_sp<GrFragmentProcessor> Make(sk_sp<GrFragmentProcessor> dst) {
30 return sk_sp<GrFragmentProcessor>(new GrOverdrawFP(std::move(dst)));
robertphillipsf42fca42016-01-27 05:00:04 -080031 }
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
bungeman06ca8ec2016-06-09 08:01:03 -070053 GrOverdrawFP(sk_sp<GrFragmentProcessor> dst) {
robertphillipsf42fca42016-01-27 05:00:04 -080054 this->initClassID<GrOverdrawFP>();
55
56 SkASSERT(dst);
bungeman06ca8ec2016-06-09 08:01:03 -070057 SkDEBUGCODE(int dstIndex = )this->registerChildProcessor(std::move(dst));
robertphillipsf42fca42016-01-27 05:00:04 -080058 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
bungeman06ca8ec2016-06-09 08:01:03 -0700132sk_sp<GrFragmentProcessor> GrOverdrawFP::TestCreate(GrProcessorTestData* d) {
133 return GrOverdrawFP::Make(GrProcessorUnitTest::MakeChildFP(d));
robertphillipsf42fca42016-01-27 05:00:04 -0800134}
135
136GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrOverdrawFP);
137
138///////////////////////////////////////////////////////////////////////////////
139// Xfer Processor
140///////////////////////////////////////////////////////////////////////////////
141
142class OverdrawXP : public GrXferProcessor {
143public:
144 OverdrawXP(const DstTexture* dstTexture, bool hasMixedSamples)
145 : INHERITED(dstTexture, true, hasMixedSamples) {
146 this->initClassID<OverdrawXP>();
147 }
148
149 const char* name() const override { return "Overdraw"; }
150
151 GrGLSLXferProcessor* createGLSLInstance() const override;
152
153private:
154 GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations,
155 bool doesStencilWrite,
156 GrColor* overrideColor,
157 const GrCaps& caps) const override {
158 // We never look at the color input
159 return GrXferProcessor::kIgnoreColor_OptFlag;
160 }
161
162 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
163
164 bool onIsEqual(const GrXferProcessor&) const override { return true; }
165
166 typedef GrXferProcessor INHERITED;
167};
168
169///////////////////////////////////////////////////////////////////////////////
170
171class GLOverdrawXP : public GrGLSLXferProcessor {
172public:
173 GLOverdrawXP(const OverdrawXP&) { }
174
175 ~GLOverdrawXP() override {}
176
177 static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*) { }
178
179private:
180 void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder,
181 GrGLSLUniformHandler* uniformHandler,
182 const char* srcColor,
183 const char* srcCoverage,
184 const char* dstColor,
185 const char* outColor,
186 const char* outColorSecondary,
187 const GrXferProcessor& proc) override {
188 add_overdraw_code(fragBuilder, dstColor, outColor);
189
190 // Apply coverage.
191 INHERITED::DefaultCoverageModulation(fragBuilder, srcCoverage, dstColor, outColor,
192 outColorSecondary, proc);
193 }
194
195 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override { };
196
197 typedef GrGLSLXferProcessor INHERITED;
198};
199
200///////////////////////////////////////////////////////////////////////////////
201
202void OverdrawXP::onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
203 GLOverdrawXP::GenKey(*this, caps, b);
204}
205
206GrGLSLXferProcessor* OverdrawXP::createGLSLInstance() const { return new GLOverdrawXP(*this); }
207
208///////////////////////////////////////////////////////////////////////////////
209class GrOverdrawXPFactory : public GrXPFactory {
210public:
bungeman06ca8ec2016-06-09 08:01:03 -0700211 static sk_sp<GrXPFactory> Make() { return sk_sp<GrXPFactory>(new GrOverdrawXPFactory()); }
robertphillipsf42fca42016-01-27 05:00:04 -0800212
213 void getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
214 GrXPFactory::InvariantBlendedColor* blendedColor) const override {
215 blendedColor->fWillBlendWithDst = true;
216 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
217 }
218
219private:
220 GrOverdrawXPFactory() {
221 this->initClassID<GrOverdrawXPFactory>();
222 }
223
224 GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
225 const GrPipelineOptimizations& optimizations,
226 bool hasMixedSamples,
227 const DstTexture* dstTexture) const override {
228 return new OverdrawXP(dstTexture, hasMixedSamples);
229 }
230
cdalton3ccf2e72016-05-06 09:41:16 -0700231 bool onWillReadDstColor(const GrCaps&, const GrPipelineOptimizations&) const override {
robertphillipsf42fca42016-01-27 05:00:04 -0800232 return true;
233 }
234
235 bool onIsEqual(const GrXPFactory& xpfBase) const override { return true; }
236
237 GR_DECLARE_XP_FACTORY_TEST;
238
239 typedef GrXPFactory INHERITED;
240};
241
242GR_DEFINE_XP_FACTORY_TEST(GrOverdrawXPFactory);
243
bungeman06ca8ec2016-06-09 08:01:03 -0700244sk_sp<GrXPFactory> GrOverdrawXPFactory::TestCreate(GrProcessorTestData* d) {
245 return GrOverdrawXPFactory::Make();
robertphillipsf42fca42016-01-27 05:00:04 -0800246}
247#endif
248
249///////////////////////////////////////////////////////////////////////////////
250class SkOverdrawXfermode : public SkXfermode {
251public:
252 static SkXfermode* Create() {
253 return new SkOverdrawXfermode;
254 }
255
256 SkPMColor xferColor(SkPMColor src, SkPMColor dst) const override {
257 // This table encodes the color progression of the overdraw visualization
258 static const SkPMColor gTable[] = {
259 SkPackARGB32(0x00, 0x00, 0x00, 0x00),
260 SkPackARGB32(0xFF, 128, 158, 255),
261 SkPackARGB32(0xFF, 170, 185, 212),
262 SkPackARGB32(0xFF, 213, 195, 170),
263 SkPackARGB32(0xFF, 255, 192, 127),
264 SkPackARGB32(0xFF, 255, 185, 85),
265 SkPackARGB32(0xFF, 255, 165, 42),
266 SkPackARGB32(0xFF, 255, 135, 0),
267 SkPackARGB32(0xFF, 255, 95, 0),
268 SkPackARGB32(0xFF, 255, 50, 0),
269 SkPackARGB32(0xFF, 255, 0, 0)
270 };
271
272
273 int nextIdx;
274 if (SkColorGetR(dst) < 64) { // dst color is the 0th color so the next color is 1
275 nextIdx = 1;
276 } else if (SkColorGetG(dst) < 25) { // dst color is the 10th color so cap there
277 nextIdx = 10;
278 } else if ((SkColorGetB(dst)+21)/42 > 0) { // dst color is one of 1-6
279 nextIdx = 8 - (SkColorGetB(dst)+21)/42;
280 } else { // dst color is between 7 and 9
281 nextIdx = 11 - (SkColorGetG(dst)+22)/45;
282 }
283 SkASSERT(nextIdx < (int)SK_ARRAY_COUNT(gTable));
284
285 return gTable[nextIdx];
286 }
287
288 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkOverdrawXfermode)
289
290#if SK_SUPPORT_GPU
bungeman06ca8ec2016-06-09 08:01:03 -0700291 sk_sp<GrFragmentProcessor> makeFragmentProcessorForImageFilter(
292 sk_sp<GrFragmentProcessor> dst) const override {
293 return GrOverdrawFP::Make(dst);
robertphillipsf42fca42016-01-27 05:00:04 -0800294 }
295
bungeman06ca8ec2016-06-09 08:01:03 -0700296 sk_sp<GrXPFactory> asXPFactory() const override {
297 return GrOverdrawXPFactory::Make();
robertphillipsf42fca42016-01-27 05:00:04 -0800298 }
299#endif
300
301#ifndef SK_IGNORE_TO_STRING
302 void toString(SkString* str) const override { str->set("SkOverdrawXfermode"); }
303#endif
304
305private:
306 friend class SkOverdrawMode;
307
308 void flatten(SkWriteBuffer& buffer) const override { }
309
310 typedef SkXfermode INHERITED;
311};
312
reed60c9b582016-04-03 09:11:13 -0700313sk_sp<SkFlattenable> SkOverdrawXfermode::CreateProc(SkReadBuffer& buffer) {
314 return sk_sp<SkFlattenable>(Create());
robertphillipsf42fca42016-01-27 05:00:04 -0800315}
316
reedcfb6bdf2016-03-29 11:32:50 -0700317sk_sp<SkXfermode> SkOverdrawMode::Make() { return sk_make_sp<SkOverdrawXfermode>(); }
robertphillipsf42fca42016-01-27 05:00:04 -0800318
319SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkOverdrawMode)
320 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkOverdrawXfermode)
321SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END