blob: ddc5d96fc8b442631c1141280619da850f1b7687 [file] [log] [blame]
jvanverth6c177a12016-08-17 07:59:41 -07001/*
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 "SkGaussianEdgeShader.h"
9#include "SkReadBuffer.h"
10#include "SkWriteBuffer.h"
11
12 /** \class SkGaussianEdgeShaderImpl
13 This subclass of shader applies a Gaussian to shadow edge
jvanverthd7315f912016-08-17 10:06:18 -070014
jvanverthd99858a2016-09-12 07:51:04 -070015 If largerBlur is false:
jvanvertha4f1af82016-08-29 07:17:47 -070016 The radius of the Gaussian blur is specified by the g value of the color, in 6.2 fixed point.
17 For spot shadows, we increase the stroke width to set the shadow against the shape. This pad
18 is specified by b, also in 6.2 fixed point. The r value represents the max final alpha.
19 The incoming alpha should be 1.
jvanverthd99858a2016-09-12 07:51:04 -070020
21 If largerBlur is true:
22 The radius of the Gaussian blur is specified by the r & g values of the color in 14.2 fixed point.
23 For spot shadows, we increase the stroke width to set the shadow against the shape. This pad
24 is specified by b, also in 6.2 fixed point. The a value represents the max final alpha.
25
26 LargerBlur will be removed once Android is migrated to the updated shader.
jvanverth6c177a12016-08-17 07:59:41 -070027 */
28class SkGaussianEdgeShaderImpl : public SkShader {
29public:
jvanvertha8370b22016-09-16 09:13:15 -070030 SkGaussianEdgeShaderImpl() {}
jvanverth6c177a12016-08-17 07:59:41 -070031
32 bool isOpaque() const override;
33
34#if SK_SUPPORT_GPU
35 sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const override;
36#endif
37
38 SK_TO_STRING_OVERRIDE()
39 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkGaussianEdgeShaderImpl)
40
41protected:
42 void flatten(SkWriteBuffer&) const override;
43
44private:
45 friend class SkGaussianEdgeShader;
46
47 typedef SkShader INHERITED;
48};
49
50////////////////////////////////////////////////////////////////////////////
51
52#if SK_SUPPORT_GPU
53
54#include "GrCoordTransform.h"
55#include "GrFragmentProcessor.h"
56#include "GrInvariantOutput.h"
57#include "glsl/GrGLSLFragmentProcessor.h"
58#include "glsl/GrGLSLFragmentShaderBuilder.h"
59#include "glsl/GrGLSLProgramDataManager.h"
60#include "glsl/GrGLSLUniformHandler.h"
61#include "SkGr.h"
62#include "SkGrPriv.h"
63
64class GaussianEdgeFP : public GrFragmentProcessor {
65public:
jvanvertha8370b22016-09-16 09:13:15 -070066 GaussianEdgeFP() {
jvanverth6c177a12016-08-17 07:59:41 -070067 this->initClassID<GaussianEdgeFP>();
68
69 // enable output of distance information for shape
70 fUsesDistanceVectorField = true;
71 }
72
73 class GLSLGaussianEdgeFP : public GrGLSLFragmentProcessor {
74 public:
jvanvertha8370b22016-09-16 09:13:15 -070075 GLSLGaussianEdgeFP() {}
jvanverth6c177a12016-08-17 07:59:41 -070076
77 void emitCode(EmitArgs& args) override {
jvanverth6c177a12016-08-17 07:59:41 -070078 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
79
robertphillips05a4cf52016-09-08 09:02:43 -070080 if (!args.fGpImplementsDistanceVector) {
81 fragBuilder->codeAppendf("// GP does not implement fsDistanceVector - "
82 " returning grey in GLSLGaussianEdgeFP\n");
83 fragBuilder->codeAppendf("vec4 color = %s;", args.fInputColor);
jvanverthdb856652016-09-12 10:09:16 -070084 fragBuilder->codeAppendf("%s = vec4(0.0, 0.0, 0.0, color.r);", args.fOutputColor);
jvanvertha8370b22016-09-16 09:13:15 -070085 } else {
jvanverthd99858a2016-09-12 07:51:04 -070086 fragBuilder->codeAppendf("vec4 color = %s;", args.fInputColor);
jvanverthdb856652016-09-12 10:09:16 -070087 fragBuilder->codeAppend("float radius = color.r*256.0*64.0 + color.g*64.0;");
88 fragBuilder->codeAppend("float pad = color.b*64.0;");
jvanverthd99858a2016-09-12 07:51:04 -070089
jvanverthdb856652016-09-12 10:09:16 -070090 fragBuilder->codeAppendf("float factor = 1.0 - clamp((%s.z - pad)/radius, 0.0, 1.0);",
jvanverthd99858a2016-09-12 07:51:04 -070091 fragBuilder->distanceVectorName());
jvanverthdb856652016-09-12 10:09:16 -070092 fragBuilder->codeAppend("factor = exp(-factor * factor * 4.0) - 0.018;");
93 fragBuilder->codeAppendf("%s = factor*vec4(0.0, 0.0, 0.0, color.a);",
jvanverthd99858a2016-09-12 07:51:04 -070094 args.fOutputColor);
robertphillips05a4cf52016-09-08 09:02:43 -070095 }
jvanverth6c177a12016-08-17 07:59:41 -070096 }
97
98 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&,
99 GrProcessorKeyBuilder* b) {
jvanvertha8370b22016-09-16 09:13:15 -0700100 // only one shader generated currently
101 b->add32(0x0);
jvanverth6c177a12016-08-17 07:59:41 -0700102 }
103
104 protected:
105 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override {}
jvanverthd99858a2016-09-12 07:51:04 -0700106
107 bool fLargerBlur;
jvanverth6c177a12016-08-17 07:59:41 -0700108 };
109
110 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
111 GLSLGaussianEdgeFP::GenKey(*this, caps, b);
112 }
113
114 const char* name() const override { return "GaussianEdgeFP"; }
115
116 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
117 inout->mulByUnknownFourComponents();
118 }
119
120private:
jvanverthd99858a2016-09-12 07:51:04 -0700121 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
jvanvertha8370b22016-09-16 09:13:15 -0700122 return new GLSLGaussianEdgeFP();
jvanverthd99858a2016-09-12 07:51:04 -0700123 }
jvanverth6c177a12016-08-17 07:59:41 -0700124
125 bool onIsEqual(const GrFragmentProcessor& proc) const override { return true; }
126};
127
128////////////////////////////////////////////////////////////////////////////
129
jvanvertha8370b22016-09-16 09:13:15 -0700130sk_sp<GrFragmentProcessor> SkGaussianEdgeShaderImpl::asFragmentProcessor(const AsFPArgs&) const {
131 return sk_make_sp<GaussianEdgeFP>();
jvanverth6c177a12016-08-17 07:59:41 -0700132}
133
134#endif
135
136////////////////////////////////////////////////////////////////////////////
137
138bool SkGaussianEdgeShaderImpl::isOpaque() const {
139 return false;
140}
141
142////////////////////////////////////////////////////////////////////////////
143
144#ifndef SK_IGNORE_TO_STRING
145void SkGaussianEdgeShaderImpl::toString(SkString* str) const {
146 str->appendf("GaussianEdgeShader: ()");
147}
148#endif
149
150sk_sp<SkFlattenable> SkGaussianEdgeShaderImpl::CreateProc(SkReadBuffer& buf) {
151 return sk_make_sp<SkGaussianEdgeShaderImpl>();
152}
153
154void SkGaussianEdgeShaderImpl::flatten(SkWriteBuffer& buf) const {
jvanverth6c177a12016-08-17 07:59:41 -0700155}
156
157///////////////////////////////////////////////////////////////////////////////
158
jvanvertha8370b22016-09-16 09:13:15 -0700159sk_sp<SkShader> SkGaussianEdgeShader::Make() {
160 return sk_make_sp<SkGaussianEdgeShaderImpl>();
jvanverth6c177a12016-08-17 07:59:41 -0700161}
162
163///////////////////////////////////////////////////////////////////////////////
164
165SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkGaussianEdgeShader)
166SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkGaussianEdgeShaderImpl)
167SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
168
169///////////////////////////////////////////////////////////////////////////////