OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 The Android Open Source Project | 2 * Copyright 2012 The Android Open Source Project |
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 "SkBitmap.h" | 8 #include "SkBitmap.h" |
9 #include "SkMagnifierImageFilter.h" | 9 #include "SkMagnifierImageFilter.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
11 #include "SkFlattenableBuffers.h" | 11 #include "SkFlattenableBuffers.h" |
12 | 12 |
13 //////////////////////////////////////////////////////////////////////////////// | 13 //////////////////////////////////////////////////////////////////////////////// |
14 #if SK_SUPPORT_GPU | 14 #if SK_SUPPORT_GPU |
15 #include "effects/GrSingleTextureEffect.h" | 15 #include "effects/GrSingleTextureEffect.h" |
16 #include "gl/GrGLEffect.h" | 16 #include "gl/GrGLEffect.h" |
17 #include "gl/GrGLSL.h" | 17 #include "gl/GrGLSL.h" |
18 #include "gl/GrGLTexture.h" | 18 #include "gl/GrGLTexture.h" |
19 #include "GrTBackendEffectFactory.h" | 19 #include "GrTBackendEffectFactory.h" |
20 | 20 |
21 class GrGLMagnifierEffect; | 21 class GrGLMagnifierEffect; |
22 | 22 |
23 class GrMagnifierEffect : public GrSingleTextureEffect { | 23 class GrMagnifierEffect : public GrSingleTextureEffect { |
24 | 24 |
25 public: | 25 public: |
26 static GrEffectRef* Create(GrTexture* texture, | 26 static GrEffectRef* Create(GrTexture* texture, |
27 float xOffset, | 27 float xOffset, |
28 float yOffset, | 28 float yOffset, |
29 float xZoom, | 29 float xInvZoom, |
30 float yZoom, | 30 float yInvZoom, |
31 float xInset, | 31 float xInvInset, |
32 float yInset) { | 32 float yInvInset) { |
33 AutoEffectUnref effect(SkNEW_ARGS(GrMagnifierEffect, (texture, | 33 AutoEffectUnref effect(SkNEW_ARGS(GrMagnifierEffect, (texture, |
34 xOffset, | 34 xOffset, |
35 yOffset, | 35 yOffset, |
36 xZoom, | 36 xInvZoom, |
37 yZoom, | 37 yInvZoom, |
38 xInset, | 38 xInvInset, |
39 yInset))); | 39 yInvInset))); |
40 return CreateEffectRef(effect); | 40 return CreateEffectRef(effect); |
41 } | 41 } |
42 | 42 |
43 virtual ~GrMagnifierEffect() {}; | 43 virtual ~GrMagnifierEffect() {}; |
44 | 44 |
45 static const char* Name() { return "Magnifier"; } | 45 static const char* Name() { return "Magnifier"; } |
46 | 46 |
47 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; | 47 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; |
48 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags
) const SK_OVERRIDE; | 48 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags
) const SK_OVERRIDE; |
49 | 49 |
50 float x_offset() const { return fXOffset; } | 50 float x_offset() const { return fXOffset; } |
51 float y_offset() const { return fYOffset; } | 51 float y_offset() const { return fYOffset; } |
52 float x_zoom() const { return fXZoom; } | 52 float x_inv_zoom() const { return fXInvZoom; } |
53 float y_zoom() const { return fYZoom; } | 53 float y_inv_zoom() const { return fYInvZoom; } |
54 float x_inset() const { return fXInset; } | 54 float x_inv_inset() const { return fXInvInset; } |
55 float y_inset() const { return fYInset; } | 55 float y_inv_inset() const { return fYInvInset; } |
56 | 56 |
57 typedef GrGLMagnifierEffect GLEffect; | 57 typedef GrGLMagnifierEffect GLEffect; |
58 | 58 |
59 private: | 59 private: |
60 GrMagnifierEffect(GrTexture* texture, | 60 GrMagnifierEffect(GrTexture* texture, |
61 float xOffset, | 61 float xOffset, |
62 float yOffset, | 62 float yOffset, |
63 float xZoom, | 63 float xInvZoom, |
64 float yZoom, | 64 float yInvZoom, |
65 float xInset, | 65 float xInvInset, |
66 float yInset) | 66 float yInvInset) |
67 : GrSingleTextureEffect(texture, MakeDivByTextureWHMatrix(texture)) | 67 : GrSingleTextureEffect(texture, MakeDivByTextureWHMatrix(texture)) |
68 , fXOffset(xOffset) | 68 , fXOffset(xOffset) |
69 , fYOffset(yOffset) | 69 , fYOffset(yOffset) |
70 , fXZoom(xZoom) | 70 , fXInvZoom(xInvZoom) |
71 , fYZoom(yZoom) | 71 , fYInvZoom(yInvZoom) |
72 , fXInset(xInset) | 72 , fXInvInset(xInvInset) |
73 , fYInset(yInset) {} | 73 , fYInvInset(yInvInset) {} |
74 | 74 |
75 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; | 75 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; |
76 | 76 |
77 GR_DECLARE_EFFECT_TEST; | 77 GR_DECLARE_EFFECT_TEST; |
78 | 78 |
79 float fXOffset; | 79 float fXOffset; |
80 float fYOffset; | 80 float fYOffset; |
81 float fXZoom; | 81 float fXInvZoom; |
82 float fYZoom; | 82 float fYInvZoom; |
83 float fXInset; | 83 float fXInvInset; |
84 float fYInset; | 84 float fYInvInset; |
85 | 85 |
86 typedef GrSingleTextureEffect INHERITED; | 86 typedef GrSingleTextureEffect INHERITED; |
87 }; | 87 }; |
88 | 88 |
89 // For brevity | 89 // For brevity |
90 typedef GrGLUniformManager::UniformHandle UniformHandle; | 90 typedef GrGLUniformManager::UniformHandle UniformHandle; |
91 | 91 |
92 class GrGLMagnifierEffect : public GrGLEffect { | 92 class GrGLMagnifierEffect : public GrGLEffect { |
93 public: | 93 public: |
94 GrGLMagnifierEffect(const GrBackendEffectFactory&, const GrDrawEffect&); | 94 GrGLMagnifierEffect(const GrBackendEffectFactory&, const GrDrawEffect&); |
95 | 95 |
96 virtual void emitCode(GrGLShaderBuilder*, | 96 virtual void emitCode(GrGLShaderBuilder*, |
97 const GrDrawEffect&, | 97 const GrDrawEffect&, |
98 EffectKey, | 98 EffectKey, |
99 const char* outputColor, | 99 const char* outputColor, |
100 const char* inputColor, | 100 const char* inputColor, |
101 const TransformedCoordsArray&, | 101 const TransformedCoordsArray&, |
102 const TextureSamplerArray&) SK_OVERRIDE; | 102 const TextureSamplerArray&) SK_OVERRIDE; |
103 | 103 |
104 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER
RIDE; | 104 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER
RIDE; |
105 | 105 |
106 private: | 106 private: |
107 UniformHandle fOffsetVar; | 107 UniformHandle fOffsetVar; |
108 UniformHandle fZoomVar; | 108 UniformHandle fInvZoomVar; |
109 UniformHandle fInsetVar; | 109 UniformHandle fInvInsetVar; |
110 | 110 |
111 typedef GrGLEffect INHERITED; | 111 typedef GrGLEffect INHERITED; |
112 }; | 112 }; |
113 | 113 |
114 GrGLMagnifierEffect::GrGLMagnifierEffect(const GrBackendEffectFactory& factory,
const GrDrawEffect&) | 114 GrGLMagnifierEffect::GrGLMagnifierEffect(const GrBackendEffectFactory& factory,
const GrDrawEffect&) |
115 : INHERITED(factory) { | 115 : INHERITED(factory) { |
116 } | 116 } |
117 | 117 |
118 void GrGLMagnifierEffect::emitCode(GrGLShaderBuilder* builder, | 118 void GrGLMagnifierEffect::emitCode(GrGLShaderBuilder* builder, |
119 const GrDrawEffect&, | 119 const GrDrawEffect&, |
120 EffectKey key, | 120 EffectKey key, |
121 const char* outputColor, | 121 const char* outputColor, |
122 const char* inputColor, | 122 const char* inputColor, |
123 const TransformedCoordsArray& coords, | 123 const TransformedCoordsArray& coords, |
124 const TextureSamplerArray& samplers) { | 124 const TextureSamplerArray& samplers) { |
125 SkString coords2D = builder->ensureFSCoords2D(coords, 0); | 125 SkString coords2D = builder->ensureFSCoords2D(coords, 0); |
126 fOffsetVar = builder->addUniform( | 126 fOffsetVar = builder->addUniform( |
127 GrGLShaderBuilder::kFragment_Visibility | | 127 GrGLShaderBuilder::kFragment_Visibility | |
128 GrGLShaderBuilder::kVertex_Visibility, | 128 GrGLShaderBuilder::kVertex_Visibility, |
129 kVec2f_GrSLType, "uOffset"); | 129 kVec2f_GrSLType, "Offset"); |
130 fZoomVar = builder->addUniform( | 130 fInvZoomVar = builder->addUniform( |
131 GrGLShaderBuilder::kFragment_Visibility | | 131 GrGLShaderBuilder::kFragment_Visibility | |
132 GrGLShaderBuilder::kVertex_Visibility, | 132 GrGLShaderBuilder::kVertex_Visibility, |
133 kVec2f_GrSLType, "uZoom"); | 133 kVec2f_GrSLType, "InvZoom"); |
134 fInsetVar = builder->addUniform( | 134 fInvInsetVar = builder->addUniform( |
135 GrGLShaderBuilder::kFragment_Visibility | | 135 GrGLShaderBuilder::kFragment_Visibility | |
136 GrGLShaderBuilder::kVertex_Visibility, | 136 GrGLShaderBuilder::kVertex_Visibility, |
137 kVec2f_GrSLType, "uInset"); | 137 kVec2f_GrSLType, "InvInset"); |
138 | 138 |
139 builder->fsCodeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); | 139 builder->fsCodeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); |
140 builder->fsCodeAppendf("\t\tvec2 zoom_coord = %s + %s / %s;\n", | 140 builder->fsCodeAppendf("\t\tvec2 zoom_coord = %s + %s * %s;\n", |
141 builder->getUniformCStr(fOffsetVar), | 141 builder->getUniformCStr(fOffsetVar), |
142 coords2D.c_str(), | 142 coords2D.c_str(), |
143 builder->getUniformCStr(fZoomVar)); | 143 builder->getUniformCStr(fInvZoomVar)); |
144 | 144 |
145 builder->fsCodeAppend("\t\tvec2 delta = min(coord, vec2(1.0, 1.0) - coord);\
n"); | 145 builder->fsCodeAppend("\t\tvec2 delta = min(coord, vec2(1.0, 1.0) - coord);\
n"); |
146 | 146 |
147 builder->fsCodeAppendf("\t\tdelta = delta / %s;\n", builder->getUniformCStr(
fInsetVar)); | 147 builder->fsCodeAppendf("\t\tdelta = delta * %s;\n", builder->getUniformCStr(
fInvInsetVar)); |
148 | 148 |
149 builder->fsCodeAppend("\t\tfloat weight = 0.0;\n"); | 149 builder->fsCodeAppend("\t\tfloat weight = 0.0;\n"); |
150 builder->fsCodeAppend("\t\tif (delta.s < 2.0 && delta.t < 2.0) {\n"); | 150 builder->fsCodeAppend("\t\tif (delta.s < 2.0 && delta.t < 2.0) {\n"); |
151 builder->fsCodeAppend("\t\t\tdelta = vec2(2.0, 2.0) - delta;\n"); | 151 builder->fsCodeAppend("\t\t\tdelta = vec2(2.0, 2.0) - delta;\n"); |
152 builder->fsCodeAppend("\t\t\tfloat dist = length(delta);\n"); | 152 builder->fsCodeAppend("\t\t\tfloat dist = length(delta);\n"); |
153 builder->fsCodeAppend("\t\t\tdist = max(2.0 - dist, 0.0);\n"); | 153 builder->fsCodeAppend("\t\t\tdist = max(2.0 - dist, 0.0);\n"); |
154 builder->fsCodeAppend("\t\t\tweight = min(dist * dist, 1.0);\n"); | 154 builder->fsCodeAppend("\t\t\tweight = min(dist * dist, 1.0);\n"); |
155 builder->fsCodeAppend("\t\t} else {\n"); | 155 builder->fsCodeAppend("\t\t} else {\n"); |
156 builder->fsCodeAppend("\t\t\tvec2 delta_squared = delta * delta;\n"); | 156 builder->fsCodeAppend("\t\t\tvec2 delta_squared = delta * delta;\n"); |
157 builder->fsCodeAppend("\t\t\tweight = min(min(delta_squared.s, delta_squared
.y), 1.0);\n"); | 157 builder->fsCodeAppend("\t\t\tweight = min(min(delta_squared.x, delta_squared
.y), 1.0);\n"); |
158 builder->fsCodeAppend("\t\t}\n"); | 158 builder->fsCodeAppend("\t\t}\n"); |
159 | 159 |
160 builder->fsCodeAppend("\t\tvec2 mix_coord = mix(coord, zoom_coord, weight);\
n"); | 160 builder->fsCodeAppend("\t\tvec2 mix_coord = mix(coord, zoom_coord, weight);\
n"); |
161 builder->fsCodeAppend("\t\tvec4 output_color = "); | 161 builder->fsCodeAppend("\t\tvec4 output_color = "); |
162 builder->fsAppendTextureLookup(samplers[0], "mix_coord"); | 162 builder->fsAppendTextureLookup(samplers[0], "mix_coord"); |
163 builder->fsCodeAppend(";\n"); | 163 builder->fsCodeAppend(";\n"); |
164 | 164 |
165 builder->fsCodeAppendf("\t\t%s = output_color;", outputColor); | 165 builder->fsCodeAppendf("\t\t%s = output_color;", outputColor); |
166 SkString modulate; | 166 SkString modulate; |
167 GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); | 167 GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); |
168 builder->fsCodeAppend(modulate.c_str()); | 168 builder->fsCodeAppend(modulate.c_str()); |
169 } | 169 } |
170 | 170 |
171 void GrGLMagnifierEffect::setData(const GrGLUniformManager& uman, | 171 void GrGLMagnifierEffect::setData(const GrGLUniformManager& uman, |
172 const GrDrawEffect& drawEffect) { | 172 const GrDrawEffect& drawEffect) { |
173 const GrMagnifierEffect& zoom = drawEffect.castEffect<GrMagnifierEffect>(); | 173 const GrMagnifierEffect& zoom = drawEffect.castEffect<GrMagnifierEffect>(); |
174 uman.set2f(fOffsetVar, zoom.x_offset(), zoom.y_offset()); | 174 uman.set2f(fOffsetVar, zoom.x_offset(), zoom.y_offset()); |
175 uman.set2f(fZoomVar, zoom.x_zoom(), zoom.y_zoom()); | 175 uman.set2f(fInvZoomVar, zoom.x_inv_zoom(), zoom.y_inv_zoom()); |
176 uman.set2f(fInsetVar, zoom.x_inset(), zoom.y_inset()); | 176 uman.set2f(fInvInsetVar, zoom.x_inv_inset(), zoom.y_inv_inset()); |
177 } | 177 } |
178 | 178 |
179 ///////////////////////////////////////////////////////////////////// | 179 ///////////////////////////////////////////////////////////////////// |
180 | 180 |
181 GR_DEFINE_EFFECT_TEST(GrMagnifierEffect); | 181 GR_DEFINE_EFFECT_TEST(GrMagnifierEffect); |
182 | 182 |
183 GrEffectRef* GrMagnifierEffect::TestCreate(SkRandom* random, | 183 GrEffectRef* GrMagnifierEffect::TestCreate(SkRandom* random, |
184 GrContext* context, | 184 GrContext* context, |
185 const GrDrawTargetCaps&, | 185 const GrDrawTargetCaps&, |
186 GrTexture** textures) { | 186 GrTexture** textures) { |
(...skipping 23 matching lines...) Expand all Loading... |
210 | 210 |
211 const GrBackendEffectFactory& GrMagnifierEffect::getFactory() const { | 211 const GrBackendEffectFactory& GrMagnifierEffect::getFactory() const { |
212 return GrTBackendEffectFactory<GrMagnifierEffect>::getInstance(); | 212 return GrTBackendEffectFactory<GrMagnifierEffect>::getInstance(); |
213 } | 213 } |
214 | 214 |
215 bool GrMagnifierEffect::onIsEqual(const GrEffect& sBase) const { | 215 bool GrMagnifierEffect::onIsEqual(const GrEffect& sBase) const { |
216 const GrMagnifierEffect& s = CastEffect<GrMagnifierEffect>(sBase); | 216 const GrMagnifierEffect& s = CastEffect<GrMagnifierEffect>(sBase); |
217 return (this->texture(0) == s.texture(0) && | 217 return (this->texture(0) == s.texture(0) && |
218 this->fXOffset == s.fXOffset && | 218 this->fXOffset == s.fXOffset && |
219 this->fYOffset == s.fYOffset && | 219 this->fYOffset == s.fYOffset && |
220 this->fXZoom == s.fXZoom && | 220 this->fXInvZoom == s.fXInvZoom && |
221 this->fYZoom == s.fYZoom && | 221 this->fYInvZoom == s.fYInvZoom && |
222 this->fXInset == s.fXInset && | 222 this->fXInvInset == s.fXInvInset && |
223 this->fYInset == s.fYInset); | 223 this->fYInvInset == s.fYInvInset); |
224 } | 224 } |
225 | 225 |
226 void GrMagnifierEffect::getConstantColorComponents(GrColor* color, uint32_t* val
idFlags) const { | 226 void GrMagnifierEffect::getConstantColorComponents(GrColor* color, uint32_t* val
idFlags) const { |
227 this->updateConstantColorComponentsForModulation(color, validFlags); | 227 this->updateConstantColorComponentsForModulation(color, validFlags); |
228 } | 228 } |
229 | 229 |
230 #endif | 230 #endif |
231 | 231 |
232 //////////////////////////////////////////////////////////////////////////////// | 232 //////////////////////////////////////////////////////////////////////////////// |
233 SkMagnifierImageFilter::SkMagnifierImageFilter(SkFlattenableReadBuffer& buffer) | 233 SkMagnifierImageFilter::SkMagnifierImageFilter(SkFlattenableReadBuffer& buffer) |
234 : INHERITED(buffer) { | 234 : INHERITED(buffer) { |
235 float x = buffer.readScalar(); | 235 float x = buffer.readScalar(); |
236 float y = buffer.readScalar(); | 236 float y = buffer.readScalar(); |
237 float width = buffer.readScalar(); | 237 float width = buffer.readScalar(); |
238 float height = buffer.readScalar(); | 238 float height = buffer.readScalar(); |
239 fSrcRect = SkRect::MakeXYWH(x, y, width, height); | 239 fSrcRect = SkRect::MakeXYWH(x, y, width, height); |
240 fInset = buffer.readScalar(); | 240 fInset = buffer.readScalar(); |
241 } | 241 } |
242 | 242 |
243 // FIXME: implement single-input semantics | 243 // FIXME: implement single-input semantics |
244 SkMagnifierImageFilter::SkMagnifierImageFilter(SkRect srcRect, SkScalar inset) | 244 SkMagnifierImageFilter::SkMagnifierImageFilter(SkRect srcRect, SkScalar inset) |
245 : INHERITED(0), fSrcRect(srcRect), fInset(inset) { | 245 : INHERITED(0), fSrcRect(srcRect), fInset(inset) { |
246 SkASSERT(srcRect.x() >= 0 && srcRect.y() >= 0 && inset >= 0); | 246 SkASSERT(srcRect.x() >= 0 && srcRect.y() >= 0 && inset >= 0); |
247 } | 247 } |
248 | 248 |
249 #if SK_SUPPORT_GPU | 249 #if SK_SUPPORT_GPU |
250 bool SkMagnifierImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* textur
e, const SkMatrix&, const SkIRect&) const { | 250 bool SkMagnifierImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* textur
e, const SkMatrix&, const SkIRect&) const { |
251 if (effect) { | 251 if (effect) { |
| 252 SkScalar yOffset = (texture->origin() == kTopLeft_GrSurfaceOrigin) ? fSr
cRect.y() : |
| 253 (texture->height() - (fSrcRect.y() + fSrcRect.height(
))); |
| 254 SkScalar invInset = fInset > 0 ? SkScalarInvert(fInset) : SK_Scalar1; |
252 *effect = GrMagnifierEffect::Create(texture, | 255 *effect = GrMagnifierEffect::Create(texture, |
253 fSrcRect.x() / texture->width(), | 256 fSrcRect.x() / texture->width(), |
254 fSrcRect.y() / texture->height(), | 257 yOffset / texture->height(), |
255 texture->width() / fSrcRect.width(), | 258 fSrcRect.width() / texture->width(), |
256 texture->height() / fSrcRect.height(
), | 259 fSrcRect.height() / texture->height(
), |
257 fInset / texture->width(), | 260 texture->width() * invInset, |
258 fInset / texture->height()); | 261 texture->height() * invInset); |
259 } | 262 } |
260 return true; | 263 return true; |
261 } | 264 } |
262 #endif | 265 #endif |
263 | 266 |
264 void SkMagnifierImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { | 267 void SkMagnifierImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { |
265 this->INHERITED::flatten(buffer); | 268 this->INHERITED::flatten(buffer); |
266 buffer.writeScalar(fSrcRect.x()); | 269 buffer.writeScalar(fSrcRect.x()); |
267 buffer.writeScalar(fSrcRect.y()); | 270 buffer.writeScalar(fSrcRect.y()); |
268 buffer.writeScalar(fSrcRect.width()); | 271 buffer.writeScalar(fSrcRect.width()); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 | 331 |
329 int x_val = SkMin32(SkScalarFloorToInt(x_interp), width - 1); | 332 int x_val = SkMin32(SkScalarFloorToInt(x_interp), width - 1); |
330 int y_val = SkMin32(SkScalarFloorToInt(y_interp), height - 1); | 333 int y_val = SkMin32(SkScalarFloorToInt(y_interp), height - 1); |
331 | 334 |
332 *dptr = sptr[y_val * width + x_val]; | 335 *dptr = sptr[y_val * width + x_val]; |
333 dptr++; | 336 dptr++; |
334 } | 337 } |
335 } | 338 } |
336 return true; | 339 return true; |
337 } | 340 } |
OLD | NEW |