#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"
SkBitmap* result, SkIPoint* offset) const override;
virtual GrFragmentProcessor* getFragmentProcessor(GrTexture*,
const SkMatrix&,
- const SkIRect& bounds,
+ const SkIRect* srcBounds,
BoundaryMode boundaryMode) const = 0;
#endif
private:
const GrClip& clip,
const SkRect& dstRect,
BoundaryMode boundaryMode,
+ const SkIRect* srcBounds,
const SkIRect& bounds) const;
#endif
typedef SkLightingImageFilter INHERITED;
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);
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()),
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);
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;
}
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
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
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;
SkScalar fSurfaceScale;
SkMatrix fFilterMatrix;
BoundaryMode fBoundaryMode;
+ GrTextureDomain fDomain;
typedef GrSingleTextureEffect INHERITED;
};
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"; }
SkScalar surfaceScale,
const SkMatrix& matrix,
SkScalar kd,
- BoundaryMode boundaryMode);
+ BoundaryMode boundaryMode,
+ const SkIRect* srcBounds);
GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
typedef GrLightingEffect INHERITED;
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"; }
const SkMatrix& matrix,
SkScalar ks,
SkScalar shininess,
- BoundaryMode boundaryMode);
+ BoundaryMode boundaryMode,
+ const SkIRect* srcBounds);
GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
typedef GrLightingEffect INHERITED;
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
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
private:
typedef GrGLSLFragmentProcessor INHERITED;
- UniformHandle fImageIncrementUni;
- UniformHandle fSurfaceScaleUni;
- GrGLLight* fLight;
+ UniformHandle fImageIncrementUni;
+ UniformHandle fSurfaceScaleUni;
+ GrTextureDomain::GLDomain fDomain;
+ GrGLLight* fLight;
};
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
+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();
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>();
}
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));
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);
}
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 = ");
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,
pdman.set1f(fSurfaceScaleUni, lighting.surfaceScale());
SkAutoTUnref<SkImageFilterLight> transformedLight(
lighting.light()->transform(lighting.filterMatrix()));
+ fDomain.setData(pdman, lighting.domain(), texture->origin());
fLight->setData(pdman, transformedLight);
}
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>();
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();
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);
}
///////////////////////////////////////////////////////////////////////////////