OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrConvolutionEffect.h" | 8 #include "GrConvolutionEffect.h" |
9 #include "gl/GrGLEffect.h" | 9 #include "gl/GrGLEffect.h" |
10 #include "gl/GrGLEffectMatrix.h" | 10 #include "gl/GrGLEffectMatrix.h" |
11 #include "gl/GrGLSL.h" | 11 #include "gl/GrGLSL.h" |
12 #include "gl/GrGLTexture.h" | 12 #include "gl/GrGLTexture.h" |
13 #include "GrTBackendEffectFactory.h" | 13 #include "GrTBackendEffectFactory.h" |
14 | 14 |
15 // For brevity | |
16 typedef GrGLUniformManager::UniformHandle UniformHandle; | |
17 static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidU
niformHandle; | |
18 | |
19 class GrGLConvolutionEffect : public GrGLEffect { | 15 class GrGLConvolutionEffect : public GrGLEffect { |
20 public: | 16 public: |
21 GrGLConvolutionEffect(const GrBackendEffectFactory&, const GrDrawEffect&); | 17 GrGLConvolutionEffect(const GrBackendEffectFactory&, const GrDrawEffect&); |
22 | 18 |
23 virtual void emitCode(GrGLShaderBuilder*, | 19 virtual void emitCode(GrGLShaderBuilder*, |
24 const GrDrawEffect&, | 20 const GrDrawEffect&, |
25 EffectKey, | 21 EffectKey, |
26 const char* outputColor, | 22 const char* outputColor, |
27 const char* inputColor, | 23 const char* inputColor, |
28 const TextureSamplerArray&) SK_OVERRIDE; | 24 const TextureSamplerArray&) SK_OVERRIDE; |
29 | 25 |
30 virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect&) SK
_OVERRIDE; | 26 virtual void setData(const GrGLContext& context, const GrDrawEffect&) SK_OVE
RRIDE; |
31 | 27 |
32 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); | 28 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); |
33 | 29 |
34 private: | 30 private: |
35 int width() const { return Gr1DKernelEffect::WidthFromRadius(fRadius); } | 31 int width() const { return Gr1DKernelEffect::WidthFromRadius(fRadius); } |
36 bool useBounds() const { return fUseBounds; } | 32 bool useBounds() const { return fUseBounds; } |
37 Gr1DKernelEffect::Direction direction() const { return fDirection; } | 33 Gr1DKernelEffect::Direction direction() const { return fDirection; } |
38 | 34 |
39 int fRadius; | 35 int fRadius; |
40 bool fUseBounds; | 36 bool fUseBounds; |
41 Gr1DKernelEffect::Direction fDirection; | 37 Gr1DKernelEffect::Direction fDirection; |
42 UniformHandle fKernelUni; | 38 GrGLUniform* fKernelUni; |
43 UniformHandle fImageIncrementUni; | 39 GrGLUniform* fImageIncrementUni; |
44 UniformHandle fBoundsUni; | 40 GrGLUniform* fBoundsUni; |
45 GrGLEffectMatrix fEffectMatrix; | 41 GrGLEffectMatrix fEffectMatrix; |
46 | 42 |
47 typedef GrGLEffect INHERITED; | 43 typedef GrGLEffect INHERITED; |
48 }; | 44 }; |
49 | 45 |
50 GrGLConvolutionEffect::GrGLConvolutionEffect(const GrBackendEffectFactory& facto
ry, | 46 GrGLConvolutionEffect::GrGLConvolutionEffect(const GrBackendEffectFactory& facto
ry, |
51 const GrDrawEffect& drawEffect) | 47 const GrDrawEffect& drawEffect) |
52 : INHERITED(factory) | 48 : INHERITED(factory) |
53 , fKernelUni(kInvalidUniformHandle) | 49 , fKernelUni(NULL) |
54 , fImageIncrementUni(kInvalidUniformHandle) | 50 , fImageIncrementUni(NULL) |
55 , fBoundsUni(kInvalidUniformHandle) | 51 , fBoundsUni(NULL) |
56 , fEffectMatrix(drawEffect.castEffect<GrConvolutionEffect>().coordsType()) { | 52 , fEffectMatrix(drawEffect.castEffect<GrConvolutionEffect>().coordsType()) { |
57 const GrConvolutionEffect& c = drawEffect.castEffect<GrConvolutionEffect>(); | 53 const GrConvolutionEffect& c = drawEffect.castEffect<GrConvolutionEffect>(); |
58 fRadius = c.radius(); | 54 fRadius = c.radius(); |
59 fUseBounds = c.useBounds(); | 55 fUseBounds = c.useBounds(); |
60 fDirection = c.direction(); | 56 fDirection = c.direction(); |
61 } | 57 } |
62 | 58 |
63 void GrGLConvolutionEffect::emitCode(GrGLShaderBuilder* builder, | 59 void GrGLConvolutionEffect::emitCode(GrGLShaderBuilder* builder, |
64 const GrDrawEffect&, | 60 const GrDrawEffect&, |
65 EffectKey key, | 61 EffectKey key, |
66 const char* outputColor, | 62 const char* outputColor, |
67 const char* inputColor, | 63 const char* inputColor, |
68 const TextureSamplerArray& samplers) { | 64 const TextureSamplerArray& samplers) { |
69 const char* coords; | 65 const char* coords; |
70 fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, &coords); | 66 fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, &coords); |
71 fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Shader
Type, | 67 GrGLShaderBuilder::Uniform* imageIncrementUni = |
72 kVec2f_GrSLType, "ImageIncrement"); | 68 builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, |
| 69 kVec2f_GrSLType, "ImageIncrement"); |
| 70 fImageIncrementUni = imageIncrementUni->glUniform(); |
| 71 |
| 72 GrGLShaderBuilder::Uniform* boundsUni = NULL; |
| 73 |
73 if (this->useBounds()) { | 74 if (this->useBounds()) { |
74 fBoundsUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType
, | 75 boundsUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, |
75 kVec2f_GrSLType, "Bounds"); | 76 kVec2f_GrSLType, "Bounds"); |
| 77 fBoundsUni = boundsUni->glUniform(); |
76 } | 78 } |
77 fKernelUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_ShaderTyp
e, | 79 |
78 kFloat_GrSLType, "Kernel", this->width
()); | 80 GrGLShaderBuilder::Uniform* kernelUni = |
| 81 builder->addUniformArray(GrGLShaderBuilder::kFragment_ShaderType, |
| 82 kFloat_GrSLType, "Kernel", this->width()); |
| 83 fKernelUni = kernelUni->glUniform(); |
79 | 84 |
80 builder->fsCodeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor); | 85 builder->fsCodeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor); |
81 | 86 |
82 int width = this->width(); | 87 int width = this->width(); |
83 const GrGLShaderVar& kernel = builder->getUniformVariable(fKernelUni); | |
84 const char* imgInc = builder->getUniformCStr(fImageIncrementUni); | |
85 | 88 |
86 builder->fsCodeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords, fRadius
, imgInc); | 89 builder->fsCodeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords, fRadius
, imageIncrementUni->c_str()); |
87 | 90 |
88 // Manually unroll loop because some drivers don't; yields 20-30% speedup. | 91 // Manually unroll loop because some drivers don't; yields 20-30% speedup. |
89 for (int i = 0; i < width; i++) { | 92 for (int i = 0; i < width; i++) { |
90 SkString index; | 93 SkString index; |
91 SkString kernelIndex; | 94 SkString kernelIndex; |
92 index.appendS32(i); | 95 index.appendS32(i); |
93 kernel.appendArrayAccess(index.c_str(), &kernelIndex); | 96 kernelUni->appendArrayAccess(index.c_str(), &kernelIndex); |
94 builder->fsCodeAppendf("\t\t%s += ", outputColor); | 97 builder->fsCodeAppendf("\t\t%s += ", outputColor); |
95 builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType, sa
mplers[0], "coord"); | 98 builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType, sa
mplers[0], "coord"); |
96 if (this->useBounds()) { | 99 if (this->useBounds()) { |
97 const char* bounds = builder->getUniformCStr(fBoundsUni); | 100 const char* bounds = boundsUni->c_str(); |
98 const char* component = this->direction() == Gr1DKernelEffect::kY_Di
rection ? "y" : "x"; | 101 const char* component = this->direction() == Gr1DKernelEffect::kY_Di
rection ? "y" : "x"; |
99 builder->fsCodeAppendf(" * float(coord.%s >= %s.x && coord.%s <= %s.
y)", | 102 builder->fsCodeAppendf(" * float(coord.%s >= %s.x && coord.%s <= %s.
y)", |
100 component, bounds, component, bounds); | 103 component, bounds, component, bounds); |
101 } | 104 } |
102 builder->fsCodeAppendf(" * %s;\n", kernelIndex.c_str()); | 105 builder->fsCodeAppendf(" * %s;\n", kernelIndex.c_str()); |
103 builder->fsCodeAppendf("\t\tcoord += %s;\n", imgInc); | 106 builder->fsCodeAppendf("\t\tcoord += %s;\n", imageIncrementUni->c_str())
; |
104 } | 107 } |
105 | 108 |
106 SkString modulate; | 109 SkString modulate; |
107 GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); | 110 GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); |
108 builder->fsCodeAppend(modulate.c_str()); | 111 builder->fsCodeAppend(modulate.c_str()); |
109 } | 112 } |
110 | 113 |
111 void GrGLConvolutionEffect::setData(const GrGLUniformManager& uman, | 114 void GrGLConvolutionEffect::setData(const GrGLContext& context, |
112 const GrDrawEffect& drawEffect) { | 115 const GrDrawEffect& drawEffect) { |
113 const GrConvolutionEffect& conv = drawEffect.castEffect<GrConvolutionEffect>
(); | 116 const GrConvolutionEffect& conv = drawEffect.castEffect<GrConvolutionEffect>
(); |
114 GrTexture& texture = *conv.texture(0); | 117 GrTexture& texture = *conv.texture(0); |
115 // the code we generated was for a specific kernel radius | 118 // the code we generated was for a specific kernel radius |
116 GrAssert(conv.radius() == fRadius); | 119 GrAssert(conv.radius() == fRadius); |
117 float imageIncrement[2] = { 0 }; | 120 float imageIncrement[2] = { 0 }; |
118 float ySign = texture.origin() != kTopLeft_GrSurfaceOrigin ? 1.0f : -1.0f; | 121 float ySign = texture.origin() != kTopLeft_GrSurfaceOrigin ? 1.0f : -1.0f; |
119 switch (conv.direction()) { | 122 switch (conv.direction()) { |
120 case Gr1DKernelEffect::kX_Direction: | 123 case Gr1DKernelEffect::kX_Direction: |
121 imageIncrement[0] = 1.0f / texture.width(); | 124 imageIncrement[0] = 1.0f / texture.width(); |
122 break; | 125 break; |
123 case Gr1DKernelEffect::kY_Direction: | 126 case Gr1DKernelEffect::kY_Direction: |
124 imageIncrement[1] = ySign / texture.height(); | 127 imageIncrement[1] = ySign / texture.height(); |
125 break; | 128 break; |
126 default: | 129 default: |
127 GrCrash("Unknown filter direction."); | 130 GrCrash("Unknown filter direction."); |
128 } | 131 } |
129 uman.set2fv(fImageIncrementUni, 0, 1, imageIncrement); | 132 fImageIncrementUni->set2fv(context, 0, 1, imageIncrement); |
130 if (conv.useBounds()) { | 133 if (conv.useBounds()) { |
131 const float* bounds = conv.bounds(); | 134 const float* bounds = conv.bounds(); |
132 if (Gr1DKernelEffect::kY_Direction == conv.direction() && | 135 if (Gr1DKernelEffect::kY_Direction == conv.direction() && |
133 texture.origin() != kTopLeft_GrSurfaceOrigin) { | 136 texture.origin() != kTopLeft_GrSurfaceOrigin) { |
134 uman.set2f(fBoundsUni, 1.0f - bounds[1], 1.0f - bounds[0]); | 137 fBoundsUni->set2f(context, 1.0f - bounds[1], 1.0f - bounds[0]); |
135 } else { | 138 } else { |
136 uman.set2f(fBoundsUni, bounds[0], bounds[1]); | 139 fBoundsUni->set2f(context, bounds[0], bounds[1]); |
137 } | 140 } |
138 } | 141 } |
139 uman.set1fv(fKernelUni, 0, this->width(), conv.kernel()); | 142 fKernelUni->set1fv(context, 0, this->width(), conv.kernel()); |
140 fEffectMatrix.setData(uman, conv.getMatrix(), drawEffect, conv.texture(0)); | 143 fEffectMatrix.setData(context, conv.getMatrix(), drawEffect, conv.texture(0)
); |
141 } | 144 } |
142 | 145 |
143 GrGLEffect::EffectKey GrGLConvolutionEffect::GenKey(const GrDrawEffect& drawEffe
ct, | 146 GrGLEffect::EffectKey GrGLConvolutionEffect::GenKey(const GrDrawEffect& drawEffe
ct, |
144 const GrGLCaps&) { | 147 const GrGLCaps&) { |
145 const GrConvolutionEffect& conv = drawEffect.castEffect<GrConvolutionEffect>
(); | 148 const GrConvolutionEffect& conv = drawEffect.castEffect<GrConvolutionEffect>
(); |
146 EffectKey key = conv.radius(); | 149 EffectKey key = conv.radius(); |
147 key <<= 2; | 150 key <<= 2; |
148 if (conv.useBounds()) { | 151 if (conv.useBounds()) { |
149 key |= 0x2; | 152 key |= 0x2; |
150 key |= GrConvolutionEffect::kY_Direction == conv.direction() ? 0x1 : 0x0
; | 153 key |= GrConvolutionEffect::kY_Direction == conv.direction() ? 0x1 : 0x0
; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 } | 244 } |
242 | 245 |
243 bool useBounds = random->nextBool(); | 246 bool useBounds = random->nextBool(); |
244 return GrConvolutionEffect::Create(textures[texIdx], | 247 return GrConvolutionEffect::Create(textures[texIdx], |
245 dir, | 248 dir, |
246 radius, | 249 radius, |
247 kernel, | 250 kernel, |
248 useBounds, | 251 useBounds, |
249 bounds); | 252 bounds); |
250 } | 253 } |
OLD | NEW |