Index: src/effects/SkLightingImageFilter.cpp |
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp |
index 4be9f17db5f2be984ecc889fe81c8ff2cb6510ba..78a24649b6e145c61c44798d1d4fe1d135a73f1c 100644 |
--- a/src/effects/SkLightingImageFilter.cpp |
+++ b/src/effects/SkLightingImageFilter.cpp |
@@ -22,6 +22,7 @@ |
#include "GrPaint.h" |
#include "SkGr.h" |
#include "effects/GrSingleTextureEffect.h" |
+#include "effects/GrTextureDomain.h" |
#include "glsl/GrGLSLFragmentProcessor.h" |
#include "glsl/GrGLSLFragmentShaderBuilder.h" |
#include "glsl/GrGLSLProgramDataManager.h" |
@@ -358,7 +359,7 @@ protected: |
SkBitmap* result, SkIPoint* offset) const override; |
virtual GrFragmentProcessor* getFragmentProcessor(GrTexture*, |
const SkMatrix&, |
- const SkIRect& bounds, |
+ const SkIRect* srcBounds, |
BoundaryMode boundaryMode) const = 0; |
#endif |
private: |
@@ -369,6 +370,7 @@ private: |
const GrClip& clip, |
const SkRect& dstRect, |
BoundaryMode boundaryMode, |
+ const SkIRect* srcBounds, |
const SkIRect& bounds) const; |
#endif |
typedef SkLightingImageFilter INHERITED; |
@@ -381,10 +383,11 @@ void SkLightingImageFilterInternal::drawRect(GrDrawContext* drawContext, |
const GrClip& clip, |
const SkRect& dstRect, |
BoundaryMode boundaryMode, |
+ const SkIRect* srcBounds, |
const SkIRect& bounds) const { |
SkRect srcRect = dstRect.makeOffset(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y())); |
GrPaint paint; |
- GrFragmentProcessor* fp = this->getFragmentProcessor(src, matrix, bounds, boundaryMode); |
+ GrFragmentProcessor* fp = this->getFragmentProcessor(src, matrix, srcBounds, boundaryMode); |
paint.addColorFragmentProcessor(fp)->unref(); |
paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); |
drawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect); |
@@ -400,8 +403,10 @@ bool SkLightingImageFilterInternal::filterImageGPU(Proxy* proxy, |
if (!this->filterInputGPU(0, proxy, src, ctx, &input, &srcOffset)) { |
return false; |
} |
+ SkIRect srcBounds = input.bounds(); |
+ srcBounds.offset(srcOffset); |
SkIRect bounds; |
- if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) { |
+ if (!this->applyCropRect(ctx, srcBounds, &bounds)) { |
return false; |
} |
SkRect dstRect = SkRect::MakeWH(SkIntToScalar(bounds.width()), |
@@ -428,6 +433,7 @@ bool SkLightingImageFilterInternal::filterImageGPU(Proxy* proxy, |
SkMatrix matrix(ctx.ctm()); |
matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top())); |
bounds.offset(-srcOffset); |
+ srcBounds.offset(-srcOffset); |
SkRect topLeft = SkRect::MakeXYWH(0, 0, 1, 1); |
SkRect top = SkRect::MakeXYWH(1, 0, dstRect.width() - 2, 1); |
SkRect topRight = SkRect::MakeXYWH(dstRect.width() - 1, 0, 1, 1); |
@@ -443,19 +449,25 @@ bool SkLightingImageFilterInternal::filterImageGPU(Proxy* proxy, |
return false; |
} |
- this->drawRect(drawContext, srcTexture, matrix, clip, topLeft, kTopLeft_BoundaryMode, bounds); |
- this->drawRect(drawContext, srcTexture, matrix, clip, top, kTop_BoundaryMode, bounds); |
+ const SkIRect* pSrcBounds = srcBounds.contains(bounds) ? nullptr : &srcBounds; |
+ this->drawRect(drawContext, srcTexture, matrix, clip, topLeft, kTopLeft_BoundaryMode, |
+ pSrcBounds, bounds); |
+ this->drawRect(drawContext, srcTexture, matrix, clip, top, kTop_BoundaryMode, |
+ pSrcBounds, bounds); |
this->drawRect(drawContext, srcTexture, matrix, clip, topRight, kTopRight_BoundaryMode, |
- bounds); |
- this->drawRect(drawContext, srcTexture, matrix, clip, left, kLeft_BoundaryMode, bounds); |
+ pSrcBounds, bounds); |
+ this->drawRect(drawContext, srcTexture, matrix, clip, left, kLeft_BoundaryMode, |
+ pSrcBounds, bounds); |
this->drawRect(drawContext, srcTexture, matrix, clip, interior, kInterior_BoundaryMode, |
- bounds); |
- this->drawRect(drawContext, srcTexture, matrix, clip, right, kRight_BoundaryMode, bounds); |
+ pSrcBounds, bounds); |
+ this->drawRect(drawContext, srcTexture, matrix, clip, right, kRight_BoundaryMode, |
+ pSrcBounds, bounds); |
this->drawRect(drawContext, srcTexture, matrix, clip, bottomLeft, kBottomLeft_BoundaryMode, |
- bounds); |
- this->drawRect(drawContext, srcTexture, matrix, clip, bottom, kBottom_BoundaryMode, bounds); |
+ pSrcBounds, bounds); |
+ this->drawRect(drawContext, srcTexture, matrix, clip, bottom, kBottom_BoundaryMode, |
+ pSrcBounds, bounds); |
this->drawRect(drawContext, srcTexture, matrix, clip, bottomRight, |
- kBottomRight_BoundaryMode, bounds); |
+ kBottomRight_BoundaryMode, pSrcBounds, bounds); |
GrWrapTextureInBitmap(dst, bounds.width(), bounds.height(), false, result); |
return true; |
} |
@@ -478,7 +490,7 @@ protected: |
bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, |
SkBitmap* result, SkIPoint* offset) const override; |
#if SK_SUPPORT_GPU |
- GrFragmentProcessor* getFragmentProcessor(GrTexture*, const SkMatrix&, const SkIRect& bounds, |
+ GrFragmentProcessor* getFragmentProcessor(GrTexture*, const SkMatrix&, const SkIRect* bounds, |
BoundaryMode) const override; |
#endif |
@@ -506,7 +518,7 @@ protected: |
bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, |
SkBitmap* result, SkIPoint* offset) const override; |
#if SK_SUPPORT_GPU |
- GrFragmentProcessor* getFragmentProcessor(GrTexture*, const SkMatrix&, const SkIRect& bounds, |
+ GrFragmentProcessor* getFragmentProcessor(GrTexture*, const SkMatrix&, const SkIRect* bounds, |
BoundaryMode) const override; |
#endif |
@@ -522,13 +534,14 @@ private: |
class GrLightingEffect : public GrSingleTextureEffect { |
public: |
GrLightingEffect(GrTexture* texture, const SkImageFilterLight* light, SkScalar surfaceScale, |
- const SkMatrix& matrix, BoundaryMode boundaryMode); |
+ const SkMatrix& matrix, BoundaryMode boundaryMode, const SkIRect* srcBounds); |
~GrLightingEffect() override; |
const SkImageFilterLight* light() const { return fLight; } |
SkScalar surfaceScale() const { return fSurfaceScale; } |
const SkMatrix& filterMatrix() const { return fFilterMatrix; } |
BoundaryMode boundaryMode() const { return fBoundaryMode; } |
+ const GrTextureDomain& domain() const { return fDomain; } |
protected: |
bool onIsEqual(const GrFragmentProcessor&) const override; |
@@ -543,6 +556,7 @@ private: |
SkScalar fSurfaceScale; |
SkMatrix fFilterMatrix; |
BoundaryMode fBoundaryMode; |
+ GrTextureDomain fDomain; |
typedef GrSingleTextureEffect INHERITED; |
}; |
@@ -554,8 +568,10 @@ public: |
SkScalar surfaceScale, |
const SkMatrix& matrix, |
SkScalar kd, |
- BoundaryMode boundaryMode) { |
- return new GrDiffuseLightingEffect(texture, light, surfaceScale, matrix, kd, boundaryMode); |
+ BoundaryMode boundaryMode, |
+ const SkIRect* srcBounds) { |
+ return new GrDiffuseLightingEffect(texture, light, surfaceScale, matrix, kd, boundaryMode, |
+ srcBounds); |
} |
const char* name() const override { return "DiffuseLighting"; } |
@@ -574,7 +590,8 @@ private: |
SkScalar surfaceScale, |
const SkMatrix& matrix, |
SkScalar kd, |
- BoundaryMode boundaryMode); |
+ BoundaryMode boundaryMode, |
+ const SkIRect* srcBounds); |
GR_DECLARE_FRAGMENT_PROCESSOR_TEST; |
typedef GrLightingEffect INHERITED; |
@@ -589,9 +606,10 @@ public: |
const SkMatrix& matrix, |
SkScalar ks, |
SkScalar shininess, |
- BoundaryMode boundaryMode) { |
+ BoundaryMode boundaryMode, |
+ const SkIRect* srcBounds) { |
return new GrSpecularLightingEffect(texture, light, surfaceScale, matrix, ks, shininess, |
- boundaryMode); |
+ boundaryMode, srcBounds); |
} |
const char* name() const override { return "SpecularLighting"; } |
@@ -612,7 +630,8 @@ private: |
const SkMatrix& matrix, |
SkScalar ks, |
SkScalar shininess, |
- BoundaryMode boundaryMode); |
+ BoundaryMode boundaryMode, |
+ const SkIRect* srcBounds); |
GR_DECLARE_FRAGMENT_PROCESSOR_TEST; |
typedef GrLightingEffect INHERITED; |
@@ -1291,12 +1310,11 @@ void SkDiffuseLightingImageFilter::toString(SkString* str) const { |
GrFragmentProcessor* SkDiffuseLightingImageFilter::getFragmentProcessor( |
GrTexture* texture, |
const SkMatrix& matrix, |
- const SkIRect&, |
- BoundaryMode boundaryMode |
-) const { |
+ const SkIRect* srcBounds, |
+ BoundaryMode boundaryMode) const { |
SkScalar scale = SkScalarMul(this->surfaceScale(), SkIntToScalar(255)); |
return GrDiffuseLightingEffect::Create(texture, this->light(), scale, matrix, this->kd(), |
- boundaryMode); |
+ boundaryMode, srcBounds); |
} |
#endif |
@@ -1435,11 +1453,11 @@ void SkSpecularLightingImageFilter::toString(SkString* str) const { |
GrFragmentProcessor* SkSpecularLightingImageFilter::getFragmentProcessor( |
GrTexture* texture, |
const SkMatrix& matrix, |
- const SkIRect&, |
+ const SkIRect* srcBounds, |
BoundaryMode boundaryMode) const { |
SkScalar scale = SkScalarMul(this->surfaceScale(), SkIntToScalar(255)); |
return GrSpecularLightingEffect::Create(texture, this->light(), scale, matrix, this->ks(), |
- this->shininess(), boundaryMode); |
+ this->shininess(), boundaryMode, srcBounds); |
} |
#endif |
@@ -1572,9 +1590,10 @@ protected: |
private: |
typedef GrGLSLFragmentProcessor INHERITED; |
- UniformHandle fImageIncrementUni; |
- UniformHandle fSurfaceScaleUni; |
- GrGLLight* fLight; |
+ UniformHandle fImageIncrementUni; |
+ UniformHandle fSurfaceScaleUni; |
+ GrTextureDomain::GLDomain fDomain; |
+ GrGLLight* fLight; |
}; |
/////////////////////////////////////////////////////////////////////////////// |
@@ -1610,16 +1629,32 @@ private: |
/////////////////////////////////////////////////////////////////////////////// |
+namespace { |
+ |
+GrTextureDomain create_domain(GrTexture* texture, const SkIRect* srcBounds, |
+ GrTextureDomain::Mode mode) { |
+ if (srcBounds) { |
+ SkRect texelDomain = GrTextureDomain::MakeTexelDomainForMode(texture, *srcBounds, mode); |
+ return GrTextureDomain(texelDomain, mode); |
+ } else { |
+ return GrTextureDomain(SkRect::MakeEmpty(), GrTextureDomain::kIgnore_Mode); |
+ } |
+} |
+ |
+}; |
+ |
GrLightingEffect::GrLightingEffect(GrTexture* texture, |
const SkImageFilterLight* light, |
SkScalar surfaceScale, |
const SkMatrix& matrix, |
- BoundaryMode boundaryMode) |
+ BoundaryMode boundaryMode, |
+ const SkIRect* srcBounds) |
: INHERITED(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture)) |
, fLight(light) |
, fSurfaceScale(surfaceScale) |
, fFilterMatrix(matrix) |
- , fBoundaryMode(boundaryMode) { |
+ , fBoundaryMode(boundaryMode) |
+ , fDomain(create_domain(texture, srcBounds, GrTextureDomain::kDecal_Mode)) { |
fLight->ref(); |
if (light->requiresFragmentPosition()) { |
this->setWillReadFragmentPosition(); |
@@ -1644,8 +1679,9 @@ GrDiffuseLightingEffect::GrDiffuseLightingEffect(GrTexture* texture, |
SkScalar surfaceScale, |
const SkMatrix& matrix, |
SkScalar kd, |
- BoundaryMode boundaryMode) |
- : INHERITED(texture, light, surfaceScale, matrix, boundaryMode), fKD(kd) { |
+ BoundaryMode boundaryMode, |
+ const SkIRect* srcBounds) |
+ : INHERITED(texture, light, surfaceScale, matrix, boundaryMode, srcBounds), fKD(kd) { |
this->initClassID<GrDiffuseLightingEffect>(); |
} |
@@ -1666,6 +1702,9 @@ GrGLSLFragmentProcessor* GrDiffuseLightingEffect::onCreateGLSLInstance() const { |
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDiffuseLightingEffect); |
const GrFragmentProcessor* GrDiffuseLightingEffect::TestCreate(GrProcessorTestData* d) { |
+ int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : |
+ GrProcessorUnitTest::kAlphaTextureIdx; |
+ GrTexture* tex = d->fTextures[texIdx]; |
SkScalar surfaceScale = d->fRandom->nextSScalar1(); |
SkScalar kd = d->fRandom->nextUScalar1(); |
SkAutoTUnref<SkImageFilterLight> light(create_random_light(d->fRandom)); |
@@ -1673,9 +1712,12 @@ const GrFragmentProcessor* GrDiffuseLightingEffect::TestCreate(GrProcessorTestDa |
for (int i = 0; i < 9; i++) { |
matrix[i] = d->fRandom->nextUScalar1(); |
} |
+ SkIRect srcBounds = SkIRect::MakeXYWH(d->fRandom->nextRangeU(0, tex->width()), |
+ d->fRandom->nextRangeU(0, tex->height()), |
+ d->fRandom->nextRangeU(0, tex->width()), |
+ d->fRandom->nextRangeU(0, tex->height())); |
BoundaryMode mode = static_cast<BoundaryMode>(d->fRandom->nextU() % kBoundaryModeCount); |
- return GrDiffuseLightingEffect::Create(d->fTextures[GrProcessorUnitTest::kAlphaTextureIdx], |
- light, surfaceScale, matrix, kd, mode); |
+ return GrDiffuseLightingEffect::Create(tex, light, surfaceScale, matrix, kd, mode, &srcBounds); |
} |
@@ -1755,9 +1797,18 @@ void GrGLLightingEffect::emitCode(EmitArgs& args) { |
for (int dx = -1; dx <= 1; dx++) { |
SkString texCoords; |
texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc); |
- fragBuilder->codeAppendf("\t\tm[%d] = ", index++); |
- fragBuilder->appendTextureLookup(args.fSamplers[0], texCoords.c_str()); |
- fragBuilder->codeAppend(".a;\n"); |
+ SkString temp; |
+ temp.appendf("temp%d", index); |
+ fragBuilder->codeAppendf("vec4 %s;", temp.c_str()); |
+ fDomain.sampleTexture(fragBuilder, |
+ args.fUniformHandler, |
+ args.fGLSLCaps, |
+ le.domain(), |
+ temp.c_str(), |
+ texCoords, |
+ args.fSamplers[0]); |
+ fragBuilder->codeAppendf("m[%d] = %s.a;", index, temp.c_str()); |
+ index++; |
} |
} |
fragBuilder->codeAppend("\t\tvec3 surfaceToLight = "); |
@@ -1778,6 +1829,7 @@ void GrGLLightingEffect::GenKey(const GrProcessor& proc, |
const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) { |
const GrLightingEffect& lighting = proc.cast<GrLightingEffect>(); |
b->add32(lighting.boundaryMode() << 2 | lighting.light()->type()); |
+ b->add32(GrTextureDomain::GLDomain::DomainKey(lighting.domain())); |
} |
void GrGLLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman, |
@@ -1793,6 +1845,7 @@ void GrGLLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman, |
pdman.set1f(fSurfaceScaleUni, lighting.surfaceScale()); |
SkAutoTUnref<SkImageFilterLight> transformedLight( |
lighting.light()->transform(lighting.filterMatrix())); |
+ fDomain.setData(pdman, lighting.domain(), texture->origin()); |
fLight->setData(pdman, transformedLight); |
} |
@@ -1839,8 +1892,9 @@ GrSpecularLightingEffect::GrSpecularLightingEffect(GrTexture* texture, |
const SkMatrix& matrix, |
SkScalar ks, |
SkScalar shininess, |
- BoundaryMode boundaryMode) |
- : INHERITED(texture, light, surfaceScale, matrix, boundaryMode) |
+ BoundaryMode boundaryMode, |
+ const SkIRect* srcBounds) |
+ : INHERITED(texture, light, surfaceScale, matrix, boundaryMode, srcBounds) |
, fKS(ks) |
, fShininess(shininess) { |
this->initClassID<GrSpecularLightingEffect>(); |
@@ -1865,6 +1919,9 @@ GrGLSLFragmentProcessor* GrSpecularLightingEffect::onCreateGLSLInstance() const |
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSpecularLightingEffect); |
const GrFragmentProcessor* GrSpecularLightingEffect::TestCreate(GrProcessorTestData* d) { |
+ int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : |
+ GrProcessorUnitTest::kAlphaTextureIdx; |
+ GrTexture* tex = d->fTextures[texIdx]; |
SkScalar surfaceScale = d->fRandom->nextSScalar1(); |
SkScalar ks = d->fRandom->nextUScalar1(); |
SkScalar shininess = d->fRandom->nextUScalar1(); |
@@ -1874,8 +1931,13 @@ const GrFragmentProcessor* GrSpecularLightingEffect::TestCreate(GrProcessorTestD |
matrix[i] = d->fRandom->nextUScalar1(); |
} |
BoundaryMode mode = static_cast<BoundaryMode>(d->fRandom->nextU() % kBoundaryModeCount); |
+ SkIRect srcBounds = SkIRect::MakeXYWH(d->fRandom->nextRangeU(0, tex->width()), |
+ d->fRandom->nextRangeU(0, tex->height()), |
+ d->fRandom->nextRangeU(0, tex->width()), |
+ d->fRandom->nextRangeU(0, tex->height())); |
return GrSpecularLightingEffect::Create(d->fTextures[GrProcessorUnitTest::kAlphaTextureIdx], |
- light, surfaceScale, matrix, ks, shininess, mode); |
+ light, surfaceScale, matrix, ks, shininess, mode, |
+ &srcBounds); |
} |
/////////////////////////////////////////////////////////////////////////////// |