OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 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 "SkDisplacementMapEffect.h" | 8 #include "SkDisplacementMapEffect.h" |
9 #include "SkFlattenableBuffers.h" | 9 #include "SkFlattenableBuffers.h" |
10 #include "SkUnPreMultiply.h" | 10 #include "SkUnPreMultiply.h" |
11 #include "SkColorPriv.h" | 11 #include "SkColorPriv.h" |
12 #if SK_SUPPORT_GPU | 12 #if SK_SUPPORT_GPU |
13 #include "GrContext.h" | 13 #include "GrContext.h" |
| 14 #include "GrCoordTransform.h" |
14 #include "gl/GrGLEffect.h" | 15 #include "gl/GrGLEffect.h" |
15 #include "gl/GrGLEffectMatrix.h" | |
16 #include "GrTBackendEffectFactory.h" | 16 #include "GrTBackendEffectFactory.h" |
17 #include "SkImageFilterUtils.h" | 17 #include "SkImageFilterUtils.h" |
18 #endif | 18 #endif |
19 | 19 |
20 namespace { | 20 namespace { |
21 | 21 |
22 template<SkDisplacementMapEffect::ChannelSelectorType type> | 22 template<SkDisplacementMapEffect::ChannelSelectorType type> |
23 uint32_t getValue(SkColor, const SkUnPreMultiply::Scale*) { | 23 uint32_t getValue(SkColor, const SkUnPreMultiply::Scale*) { |
24 SkDEBUGFAIL("Unknown channel selector"); | 24 SkDEBUGFAIL("Unknown channel selector"); |
25 return 0; | 25 return 0; |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 public: | 202 public: |
203 GrGLDisplacementMapEffect(const GrBackendEffectFactory& factory, | 203 GrGLDisplacementMapEffect(const GrBackendEffectFactory& factory, |
204 const GrDrawEffect& drawEffect); | 204 const GrDrawEffect& drawEffect); |
205 virtual ~GrGLDisplacementMapEffect(); | 205 virtual ~GrGLDisplacementMapEffect(); |
206 | 206 |
207 virtual void emitCode(GrGLShaderBuilder*, | 207 virtual void emitCode(GrGLShaderBuilder*, |
208 const GrDrawEffect&, | 208 const GrDrawEffect&, |
209 EffectKey, | 209 EffectKey, |
210 const char* outputColor, | 210 const char* outputColor, |
211 const char* inputColor, | 211 const char* inputColor, |
| 212 const TransformedCoordsArray&, |
212 const TextureSamplerArray&) SK_OVERRIDE; | 213 const TextureSamplerArray&) SK_OVERRIDE; |
213 | 214 |
214 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); | 215 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); |
215 | 216 |
216 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER
RIDE; | 217 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER
RIDE; |
217 | 218 |
218 private: | 219 private: |
219 static const GrEffect::CoordsType kCoordsType = GrEffect::kLocal_CoordsType; | |
220 | |
221 SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector; | 220 SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector; |
222 SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector; | 221 SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector; |
223 GrGLEffectMatrix fDisplacementEffectMatrix; | |
224 GrGLEffectMatrix fColorEffectMatrix; | |
225 GrGLUniformManager::UniformHandle fScaleUni; | 222 GrGLUniformManager::UniformHandle fScaleUni; |
226 | 223 |
227 typedef GrGLEffect INHERITED; | 224 typedef GrGLEffect INHERITED; |
228 }; | 225 }; |
229 | 226 |
230 /////////////////////////////////////////////////////////////////////////////// | 227 /////////////////////////////////////////////////////////////////////////////// |
231 | 228 |
232 class GrDisplacementMapEffect : public GrEffect { | 229 class GrDisplacementMapEffect : public GrEffect { |
233 public: | 230 public: |
234 static GrEffectRef* Create(SkDisplacementMapEffect::ChannelSelectorType xCha
nnelSelector, | 231 static GrEffectRef* Create(SkDisplacementMapEffect::ChannelSelectorType xCha
nnelSelector, |
(...skipping 15 matching lines...) Expand all Loading... |
250 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector() const | 247 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector() const |
251 { return fYChannelSelector; } | 248 { return fYChannelSelector; } |
252 SkScalar scale() const { return fScale; } | 249 SkScalar scale() const { return fScale; } |
253 | 250 |
254 typedef GrGLDisplacementMapEffect GLEffect; | 251 typedef GrGLDisplacementMapEffect GLEffect; |
255 static const char* Name() { return "DisplacementMap"; } | 252 static const char* Name() { return "DisplacementMap"; } |
256 | 253 |
257 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags
) const SK_OVERRIDE; | 254 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags
) const SK_OVERRIDE; |
258 | 255 |
259 private: | 256 private: |
260 | |
261 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; | 257 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; |
262 | 258 |
263 GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChanne
lSelector, | 259 GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChanne
lSelector, |
264 SkDisplacementMapEffect::ChannelSelectorType yChanne
lSelector, | 260 SkDisplacementMapEffect::ChannelSelectorType yChanne
lSelector, |
265 SkScalar scale, GrTexture* displacement, GrTexture*
color); | 261 SkScalar scale, GrTexture* displacement, GrTexture*
color); |
266 | 262 |
267 GR_DECLARE_EFFECT_TEST; | 263 GR_DECLARE_EFFECT_TEST; |
268 | 264 |
| 265 GrCoordTransform fDisplacementTransform; |
269 GrTextureAccess fDisplacementAccess; | 266 GrTextureAccess fDisplacementAccess; |
| 267 GrCoordTransform fColorTransform; |
270 GrTextureAccess fColorAccess; | 268 GrTextureAccess fColorAccess; |
271 SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector; | 269 SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector; |
272 SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector; | 270 SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector; |
273 SkScalar fScale; | 271 SkScalar fScale; |
274 | 272 |
275 typedef GrEffect INHERITED; | 273 typedef GrEffect INHERITED; |
276 }; | 274 }; |
277 | 275 |
278 bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src,
const SkMatrix& ctm, | 276 bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src,
const SkMatrix& ctm, |
279 SkBitmap* result, SkIPoint* offset)
{ | 277 SkBitmap* result, SkIPoint* offset)
{ |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 } | 318 } |
321 | 319 |
322 /////////////////////////////////////////////////////////////////////////////// | 320 /////////////////////////////////////////////////////////////////////////////// |
323 | 321 |
324 GrDisplacementMapEffect::GrDisplacementMapEffect( | 322 GrDisplacementMapEffect::GrDisplacementMapEffect( |
325 SkDisplacementMapEffect::ChannelSelectorType xChann
elSelector, | 323 SkDisplacementMapEffect::ChannelSelectorType xChann
elSelector, |
326 SkDisplacementMapEffect::ChannelSelectorType yChann
elSelector, | 324 SkDisplacementMapEffect::ChannelSelectorType yChann
elSelector, |
327 SkScalar scale, | 325 SkScalar scale, |
328 GrTexture* displacement, | 326 GrTexture* displacement, |
329 GrTexture* color) | 327 GrTexture* color) |
330 : fDisplacementAccess(displacement) | 328 : fDisplacementTransform(kLocal_GrCoordSet, displacement) |
| 329 , fDisplacementAccess(displacement) |
| 330 , fColorTransform(kLocal_GrCoordSet, color) |
331 , fColorAccess(color) | 331 , fColorAccess(color) |
332 , fXChannelSelector(xChannelSelector) | 332 , fXChannelSelector(xChannelSelector) |
333 , fYChannelSelector(yChannelSelector) | 333 , fYChannelSelector(yChannelSelector) |
334 , fScale(scale) { | 334 , fScale(scale) { |
| 335 this->addCoordTransform(&fDisplacementTransform); |
335 this->addTextureAccess(&fDisplacementAccess); | 336 this->addTextureAccess(&fDisplacementAccess); |
| 337 this->addCoordTransform(&fColorTransform); |
336 this->addTextureAccess(&fColorAccess); | 338 this->addTextureAccess(&fColorAccess); |
337 } | 339 } |
338 | 340 |
339 GrDisplacementMapEffect::~GrDisplacementMapEffect() { | 341 GrDisplacementMapEffect::~GrDisplacementMapEffect() { |
340 } | 342 } |
341 | 343 |
342 bool GrDisplacementMapEffect::onIsEqual(const GrEffect& sBase) const { | 344 bool GrDisplacementMapEffect::onIsEqual(const GrEffect& sBase) const { |
343 const GrDisplacementMapEffect& s = CastEffect<GrDisplacementMapEffect>(sBase
); | 345 const GrDisplacementMapEffect& s = CastEffect<GrDisplacementMapEffect>(sBase
); |
344 return fDisplacementAccess.getTexture() == s.fDisplacementAccess.getTexture(
) && | 346 return fDisplacementAccess.getTexture() == s.fDisplacementAccess.getTexture(
) && |
345 fColorAccess.getTexture() == s.fColorAccess.getTexture() && | 347 fColorAccess.getTexture() == s.fColorAccess.getTexture() && |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 return GrDisplacementMapEffect::Create(xChannelSelector, yChannelSelector, s
cale, | 388 return GrDisplacementMapEffect::Create(xChannelSelector, yChannelSelector, s
cale, |
387 textures[texIdxDispl], textures[texId
xColor]); | 389 textures[texIdxDispl], textures[texId
xColor]); |
388 } | 390 } |
389 | 391 |
390 /////////////////////////////////////////////////////////////////////////////// | 392 /////////////////////////////////////////////////////////////////////////////// |
391 | 393 |
392 GrGLDisplacementMapEffect::GrGLDisplacementMapEffect(const GrBackendEffectFactor
y& factory, | 394 GrGLDisplacementMapEffect::GrGLDisplacementMapEffect(const GrBackendEffectFactor
y& factory, |
393 const GrDrawEffect& drawEff
ect) | 395 const GrDrawEffect& drawEff
ect) |
394 : INHERITED(factory) | 396 : INHERITED(factory) |
395 , fXChannelSelector(drawEffect.castEffect<GrDisplacementMapEffect>().xChanne
lSelector()) | 397 , fXChannelSelector(drawEffect.castEffect<GrDisplacementMapEffect>().xChanne
lSelector()) |
396 , fYChannelSelector(drawEffect.castEffect<GrDisplacementMapEffect>().yChanne
lSelector()) | 398 , fYChannelSelector(drawEffect.castEffect<GrDisplacementMapEffect>().yChanne
lSelector()) { |
397 , fDisplacementEffectMatrix(kCoordsType) | |
398 , fColorEffectMatrix(kCoordsType) { | |
399 } | 399 } |
400 | 400 |
401 GrGLDisplacementMapEffect::~GrGLDisplacementMapEffect() { | 401 GrGLDisplacementMapEffect::~GrGLDisplacementMapEffect() { |
402 } | 402 } |
403 | 403 |
404 void GrGLDisplacementMapEffect::emitCode(GrGLShaderBuilder* builder, | 404 void GrGLDisplacementMapEffect::emitCode(GrGLShaderBuilder* builder, |
405 const GrDrawEffect&, | 405 const GrDrawEffect&, |
406 EffectKey key, | 406 EffectKey key, |
407 const char* outputColor, | 407 const char* outputColor, |
408 const char* inputColor, | 408 const char* inputColor, |
| 409 const TransformedCoordsArray& coords, |
409 const TextureSamplerArray& samplers) { | 410 const TextureSamplerArray& samplers) { |
410 sk_ignore_unused_variable(inputColor); | 411 sk_ignore_unused_variable(inputColor); |
411 | 412 |
412 fScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, | 413 fScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, |
413 kVec2f_GrSLType, "Scale"); | 414 kVec2f_GrSLType, "Scale"); |
414 const char* scaleUni = builder->getUniformCStr(fScaleUni); | 415 const char* scaleUni = builder->getUniformCStr(fScaleUni); |
415 | |
416 SkString dCoordsIn; | |
417 GrSLType dCoordsType = fDisplacementEffectMatrix.emitCode( | |
418 builder, key, &dCoordsIn, NULL, "DISPL"); | |
419 SkString cCoordsIn; | |
420 GrSLType cCoordsType = fColorEffectMatrix.emitCode( | |
421 builder, key, &cCoordsIn, NULL, "COLOR"); | |
422 | |
423 const char* dColor = "dColor"; | 416 const char* dColor = "dColor"; |
424 const char* cCoords = "cCoords"; | 417 const char* cCoords = "cCoords"; |
425 const char* outOfBounds = "outOfBounds"; | 418 const char* outOfBounds = "outOfBounds"; |
426 const char* nearZero = "1e-6"; // Since 6.10352e−5 is the smallest half floa
t, use | 419 const char* nearZero = "1e-6"; // Since 6.10352e−5 is the smallest half floa
t, use |
427 // a number smaller than that to approximate
0, but | 420 // a number smaller than that to approximate
0, but |
428 // leave room for 32-bit float GPU rounding e
rrors. | 421 // leave room for 32-bit float GPU rounding e
rrors. |
429 | 422 |
430 builder->fsCodeAppendf("\t\tvec4 %s = ", dColor); | 423 builder->fsCodeAppendf("\t\tvec4 %s = ", dColor); |
431 builder->fsAppendTextureLookup(samplers[0], dCoordsIn.c_str(), dCoordsType); | 424 builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].typ
e()); |
432 builder->fsCodeAppend(";\n"); | 425 builder->fsCodeAppend(";\n"); |
433 | 426 |
434 // Unpremultiply the displacement | 427 // Unpremultiply the displacement |
435 builder->fsCodeAppendf("\t\t%s.rgb = (%s.a < %s) ? vec3(0.0) : clamp(%s.rgb
/ %s.a, 0.0, 1.0);", | 428 builder->fsCodeAppendf("\t\t%s.rgb = (%s.a < %s) ? vec3(0.0) : clamp(%s.rgb
/ %s.a, 0.0, 1.0);", |
436 dColor, dColor, nearZero, dColor, dColor); | 429 dColor, dColor, nearZero, dColor, dColor); |
437 | 430 |
438 builder->fsCodeAppendf("\t\tvec2 %s = %s + %s*(%s.", | 431 builder->fsCodeAppendf("\t\tvec2 %s = %s + %s*(%s.", |
439 cCoords, cCoordsIn.c_str(), scaleUni, dColor); | 432 cCoords, coords[1].c_str(), scaleUni, dColor); |
440 | 433 |
441 switch (fXChannelSelector) { | 434 switch (fXChannelSelector) { |
442 case SkDisplacementMapEffect::kR_ChannelSelectorType: | 435 case SkDisplacementMapEffect::kR_ChannelSelectorType: |
443 builder->fsCodeAppend("r"); | 436 builder->fsCodeAppend("r"); |
444 break; | 437 break; |
445 case SkDisplacementMapEffect::kG_ChannelSelectorType: | 438 case SkDisplacementMapEffect::kG_ChannelSelectorType: |
446 builder->fsCodeAppend("g"); | 439 builder->fsCodeAppend("g"); |
447 break; | 440 break; |
448 case SkDisplacementMapEffect::kB_ChannelSelectorType: | 441 case SkDisplacementMapEffect::kB_ChannelSelectorType: |
449 builder->fsCodeAppend("b"); | 442 builder->fsCodeAppend("b"); |
(...skipping 24 matching lines...) Expand all Loading... |
474 SkDEBUGFAIL("Unknown Y channel selector"); | 467 SkDEBUGFAIL("Unknown Y channel selector"); |
475 } | 468 } |
476 builder->fsCodeAppend("-vec2(0.5));\t\t"); | 469 builder->fsCodeAppend("-vec2(0.5));\t\t"); |
477 | 470 |
478 // FIXME : This can be achieved with a "clamp to border" texture repeat mode
and | 471 // FIXME : This can be achieved with a "clamp to border" texture repeat mode
and |
479 // a 0 border color instead of computing if cCoords is out of bounds
here. | 472 // a 0 border color instead of computing if cCoords is out of bounds
here. |
480 builder->fsCodeAppendf( | 473 builder->fsCodeAppendf( |
481 "bool %s = (%s.x < 0.0) || (%s.y < 0.0) || (%s.x > 1.0) || (%s.y > 1.0);
\t\t", | 474 "bool %s = (%s.x < 0.0) || (%s.y < 0.0) || (%s.x > 1.0) || (%s.y > 1.0);
\t\t", |
482 outOfBounds, cCoords, cCoords, cCoords, cCoords); | 475 outOfBounds, cCoords, cCoords, cCoords, cCoords); |
483 builder->fsCodeAppendf("%s = %s ? vec4(0.0) : ", outputColor, outOfBounds); | 476 builder->fsCodeAppendf("%s = %s ? vec4(0.0) : ", outputColor, outOfBounds); |
484 builder->fsAppendTextureLookup(samplers[1], cCoords, cCoordsType); | 477 builder->fsAppendTextureLookup(samplers[1], cCoords, coords[1].type()); |
485 builder->fsCodeAppend(";\n"); | 478 builder->fsCodeAppend(";\n"); |
486 } | 479 } |
487 | 480 |
488 void GrGLDisplacementMapEffect::setData(const GrGLUniformManager& uman, | 481 void GrGLDisplacementMapEffect::setData(const GrGLUniformManager& uman, |
489 const GrDrawEffect& drawEffect) { | 482 const GrDrawEffect& drawEffect) { |
490 const GrDisplacementMapEffect& displacementMap = | 483 const GrDisplacementMapEffect& displacementMap = |
491 drawEffect.castEffect<GrDisplacementMapEffect>(); | 484 drawEffect.castEffect<GrDisplacementMapEffect>(); |
492 GrTexture* displTex = displacementMap.texture(0); | |
493 GrTexture* colorTex = displacementMap.texture(1); | 485 GrTexture* colorTex = displacementMap.texture(1); |
494 fDisplacementEffectMatrix.setData(uman, | |
495 GrEffect::MakeDivByTextureWHMatrix(displTex
), | |
496 drawEffect, | |
497 displTex); | |
498 fColorEffectMatrix.setData(uman, | |
499 GrEffect::MakeDivByTextureWHMatrix(colorTex), | |
500 drawEffect, | |
501 colorTex); | |
502 | |
503 SkScalar scaleX = SkScalarDiv(displacementMap.scale(), SkIntToScalar(colorTe
x->width())); | 486 SkScalar scaleX = SkScalarDiv(displacementMap.scale(), SkIntToScalar(colorTe
x->width())); |
504 SkScalar scaleY = SkScalarDiv(displacementMap.scale(), SkIntToScalar(colorTe
x->height())); | 487 SkScalar scaleY = SkScalarDiv(displacementMap.scale(), SkIntToScalar(colorTe
x->height())); |
505 uman.set2f(fScaleUni, SkScalarToFloat(scaleX), | 488 uman.set2f(fScaleUni, SkScalarToFloat(scaleX), |
506 colorTex->origin() == kTopLeft_GrSurfaceOrigin ? | 489 colorTex->origin() == kTopLeft_GrSurfaceOrigin ? |
507 SkScalarToFloat(scaleY) : SkScalarToFloat(-scaleY)); | 490 SkScalarToFloat(scaleY) : SkScalarToFloat(-scaleY)); |
508 } | 491 } |
509 | 492 |
510 GrGLEffect::EffectKey GrGLDisplacementMapEffect::GenKey(const GrDrawEffect& draw
Effect, | 493 GrGLEffect::EffectKey GrGLDisplacementMapEffect::GenKey(const GrDrawEffect& draw
Effect, |
511 const GrGLCaps&) { | 494 const GrGLCaps&) { |
512 const GrDisplacementMapEffect& displacementMap = | 495 const GrDisplacementMapEffect& displacementMap = |
513 drawEffect.castEffect<GrDisplacementMapEffect>(); | 496 drawEffect.castEffect<GrDisplacementMapEffect>(); |
514 | 497 |
515 GrTexture* displTex = displacementMap.texture(0); | 498 EffectKey xKey = displacementMap.xChannelSelector(); |
516 GrTexture* colorTex = displacementMap.texture(1); | 499 EffectKey yKey = displacementMap.yChannelSelector() << SkDisplacementMapEffe
ct::kKeyBits; |
517 | 500 |
518 EffectKey displKey = GrGLEffectMatrix::GenKey(GrEffect::MakeDivByTextureWHMa
trix(displTex), | 501 return xKey | yKey; |
519 drawEffect, | |
520 kCoordsType, | |
521 displTex); | |
522 | |
523 EffectKey colorKey = GrGLEffectMatrix::GenKey(GrEffect::MakeDivByTextureWHMa
trix(colorTex), | |
524 drawEffect, | |
525 kCoordsType, | |
526 colorTex); | |
527 | |
528 colorKey <<= GrGLEffectMatrix::kKeyBits; | |
529 EffectKey xKey = displacementMap.xChannelSelector() << (2 * GrGLEffectMatrix
::kKeyBits); | |
530 EffectKey yKey = displacementMap.yChannelSelector() << (2 * GrGLEffectMatrix
::kKeyBits + | |
531 SkDisplacementMapEff
ect::kKeyBits); | |
532 | |
533 return xKey | yKey | displKey | colorKey; | |
534 } | 502 } |
535 #endif | 503 #endif |
OLD | NEW |