aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/lighting.cpp61
-rw-r--r--src/core/SkCanvas.cpp8
-rw-r--r--src/effects/SkLightingImageFilter.cpp444
-rw-r--r--src/effects/SkMagnifierImageFilter.cpp51
-rw-r--r--src/gpu/SkGpuDevice.cpp34
-rw-r--r--src/gpu/SkGpuDevice.h13
6 files changed, 483 insertions, 128 deletions
diff --git a/gm/lighting.cpp b/gm/lighting.cpp
index 36c8ba0e45..0bfbb47a95 100644
--- a/gm/lighting.cpp
+++ b/gm/lighting.cpp
@@ -7,9 +7,10 @@
#include "gm.h"
#include "SkLightingImageFilter.h"
+#include "SkOffsetImageFilter.h"
#define WIDTH 330
-#define HEIGHT 440
+#define HEIGHT 660
namespace skiagm {
@@ -86,28 +87,70 @@ protected:
SkPaint paint;
SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 10, 60, 65));
+ SkImageFilter::CropRect fullSizeCropRect(SkRect::MakeXYWH(0, 0, 100, 100));
+ SkAutoTUnref<SkImageFilter> noopCropped(SkOffsetImageFilter::Create(0, 0, NULL, &cropRect));
int y = 0;
- for (int i = 0; i < 2; i++) {
- const SkImageFilter::CropRect* cr = (i == 0) ? NULL : &cropRect;
- paint.setImageFilter(SkLightingImageFilter::CreatePointLitDiffuse(pointLocation, white, surfaceScale, kd, NULL, cr))->unref();
+ for (int i = 0; i < 3; i++) {
+ const SkImageFilter::CropRect* cr = (i == 1) ? &cropRect : (i == 2) ? &fullSizeCropRect : NULL;
+ SkImageFilter* input = (i == 2) ? noopCropped.get() : NULL;
+ paint.setImageFilter(SkLightingImageFilter::CreatePointLitDiffuse(pointLocation,
+ white,
+ surfaceScale,
+ kd,
+ input,
+ cr))->unref();
drawClippedBitmap(canvas, paint, 0, y);
- paint.setImageFilter(SkLightingImageFilter::CreateDistantLitDiffuse(distantDirection, white, surfaceScale, kd, NULL, cr))->unref();
+ paint.setImageFilter(SkLightingImageFilter::CreateDistantLitDiffuse(distantDirection,
+ white,
+ surfaceScale,
+ kd,
+ input,
+ cr))->unref();
drawClippedBitmap(canvas, paint, 110, y);
- paint.setImageFilter(SkLightingImageFilter::CreateSpotLitDiffuse(spotLocation, spotTarget, spotExponent, cutoffAngle, white, surfaceScale, kd, NULL, cr))->unref();
+ paint.setImageFilter(SkLightingImageFilter::CreateSpotLitDiffuse(spotLocation,
+ spotTarget,
+ spotExponent,
+ cutoffAngle,
+ white,
+ surfaceScale,
+ kd,
+ input,
+ cr))->unref();
drawClippedBitmap(canvas, paint, 220, y);
y += 110;
- paint.setImageFilter(SkLightingImageFilter::CreatePointLitSpecular(pointLocation, white, surfaceScale, ks, shininess, NULL, cr))->unref();
+ paint.setImageFilter(SkLightingImageFilter::CreatePointLitSpecular(pointLocation,
+ white,
+ surfaceScale,
+ ks,
+ shininess,
+ input,
+ cr))->unref();
drawClippedBitmap(canvas, paint, 0, y);
- paint.setImageFilter(SkLightingImageFilter::CreateDistantLitSpecular(distantDirection, white, surfaceScale, ks, shininess, NULL, cr))->unref();
+ paint.setImageFilter(SkLightingImageFilter::CreateDistantLitSpecular(distantDirection,
+ white,
+ surfaceScale,
+ ks,
+ shininess,
+ input,
+ cr))->unref();
drawClippedBitmap(canvas, paint, 110, y);
- paint.setImageFilter(SkLightingImageFilter::CreateSpotLitSpecular(spotLocation, spotTarget, spotExponent, cutoffAngle, white, surfaceScale, ks, shininess, NULL, cr))->unref();
+ paint.setImageFilter(SkLightingImageFilter::CreateSpotLitSpecular(spotLocation,
+ spotTarget,
+ spotExponent,
+ cutoffAngle,
+ white,
+ surfaceScale,
+ ks,
+ shininess,
+ input,
+ cr))->unref();
drawClippedBitmap(canvas, paint, 220, y);
y += 110;
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 8426f090ec..5310c9f7d5 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -936,14 +936,6 @@ void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav
}
SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
-#if 1
- // this seems needed for current GMs, but makes us draw slower on the GPU
- // Related to https://code.google.com/p/skia/issues/detail?id=3519 ?
- //
- if (paint && paint->getImageFilter()) {
- usage = SkBaseDevice::kPossible_TileUsage;
- }
-#endif
device = device->onCreateDevice(SkBaseDevice::CreateInfo(info, usage, geo), paint);
if (NULL == device) {
SkErrorInternals::SetError( kInternalError_SkError,
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index 72dcf64c58..972d9ac68b 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -277,7 +277,136 @@ void writePoint3(const SkPoint3& point, SkWriteBuffer& buffer) {
buffer.writeScalar(point.fZ);
};
-class SkDiffuseLightingImageFilter : public SkLightingImageFilter {
+enum BoundaryMode {
+ kTopLeft_BoundaryMode,
+ kTop_BoundaryMode,
+ kTopRight_BoundaryMode,
+ kLeft_BoundaryMode,
+ kInterior_BoundaryMode,
+ kRight_BoundaryMode,
+ kBottomLeft_BoundaryMode,
+ kBottom_BoundaryMode,
+ kBottomRight_BoundaryMode,
+
+ kBoundaryModeCount,
+};
+
+class SkLightingImageFilterInternal : public SkLightingImageFilter {
+protected:
+ SkLightingImageFilterInternal(SkLight* light,
+ SkScalar surfaceScale,
+ SkImageFilter* input,
+ const CropRect* cropRect)
+ : INHERITED(light, surfaceScale, input, cropRect) {}
+
+#if SK_SUPPORT_GPU
+ bool canFilterImageGPU() const override { return true; }
+ bool filterImageGPU(Proxy*, const SkBitmap& src, const Context&,
+ SkBitmap* result, SkIPoint* offset) const override;
+ virtual GrFragmentProcessor* getFragmentProcessor(GrTexture*,
+ const SkMatrix&,
+ const SkIRect& bounds,
+ BoundaryMode boundaryMode) const = 0;
+#endif
+private:
+#if SK_SUPPORT_GPU
+ void drawRect(GrContext* context,
+ GrTexture* src,
+ GrTexture* dst,
+ const SkMatrix& matrix,
+ const GrClip& clip,
+ const SkRect& dstRect,
+ BoundaryMode boundaryMode,
+ const SkIRect& bounds) const;
+#endif
+ typedef SkLightingImageFilter INHERITED;
+};
+
+#if SK_SUPPORT_GPU
+void SkLightingImageFilterInternal::drawRect(GrContext* context,
+ GrTexture* src,
+ GrTexture* dst,
+ const SkMatrix& matrix,
+ const GrClip& clip,
+ const SkRect& dstRect,
+ BoundaryMode boundaryMode,
+ const SkIRect& bounds) const {
+ SkRect srcRect = dstRect.makeOffset(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()));
+ GrFragmentProcessor* fp = this->getFragmentProcessor(src, matrix, bounds, boundaryMode);
+ GrPaint paint;
+ paint.addColorProcessor(fp)->unref();
+ context->drawNonAARectToRect(dst->asRenderTarget(), clip, paint, SkMatrix::I(),
+ dstRect, srcRect);
+}
+
+bool SkLightingImageFilterInternal::filterImageGPU(Proxy* proxy,
+ const SkBitmap& src,
+ const Context& ctx,
+ SkBitmap* result,
+ SkIPoint* offset) const {
+ SkBitmap input = src;
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (this->getInput(0) &&
+ !this->getInput(0)->getInputResultGPU(proxy, src, ctx, &input, &srcOffset)) {
+ return false;
+ }
+ SkIRect bounds;
+ if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) {
+ return false;
+ }
+ SkRect dstRect = SkRect::MakeWH(SkIntToScalar(bounds.width()),
+ SkIntToScalar(bounds.height()));
+ GrTexture* srcTexture = input.getTexture();
+ GrContext* context = srcTexture->getContext();
+
+ GrSurfaceDesc desc;
+ desc.fFlags = kRenderTarget_GrSurfaceFlag,
+ desc.fWidth = bounds.width();
+ desc.fHeight = bounds.height();
+ desc.fConfig = kRGBA_8888_GrPixelConfig;
+
+ SkAutoTUnref<GrTexture> dst(
+ context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch));
+ if (!dst) {
+ return false;
+ }
+
+ // setup new clip
+ GrClip clip(dstRect);
+
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
+ SkMatrix matrix(ctx.ctm());
+ matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
+ bounds.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);
+ SkRect left = SkRect::MakeXYWH(0, 1, 1, dstRect.height() - 2);
+ SkRect interior = dstRect.makeInset(1, 1);
+ SkRect right = SkRect::MakeXYWH(dstRect.width() - 1, 1, 1, dstRect.height() - 2);
+ SkRect bottomLeft = SkRect::MakeXYWH(0, dstRect.height() - 1, 1, 1);
+ SkRect bottom = SkRect::MakeXYWH(1, dstRect.height() - 1, dstRect.width() - 2, 1);
+ SkRect bottomRight = SkRect::MakeXYWH(dstRect.width() - 1, dstRect.height() - 1, 1, 1);
+ this->drawRect(context, srcTexture, dst, matrix, clip, topLeft, kTopLeft_BoundaryMode, bounds);
+ this->drawRect(context, srcTexture, dst, matrix, clip, top, kTop_BoundaryMode, bounds);
+ this->drawRect(context, srcTexture, dst, matrix, clip, topRight, kTopRight_BoundaryMode,
+ bounds);
+ this->drawRect(context, srcTexture, dst, matrix, clip, left, kLeft_BoundaryMode, bounds);
+ this->drawRect(context, srcTexture, dst, matrix, clip, interior, kInterior_BoundaryMode,
+ bounds);
+ this->drawRect(context, srcTexture, dst, matrix, clip, right, kRight_BoundaryMode, bounds);
+ this->drawRect(context, srcTexture, dst, matrix, clip, bottomLeft, kBottomLeft_BoundaryMode,
+ bounds);
+ this->drawRect(context, srcTexture, dst, matrix, clip, bottom, kBottom_BoundaryMode, bounds);
+ this->drawRect(context, srcTexture, dst, matrix, clip, bottomRight, kBottomRight_BoundaryMode,
+ bounds);
+ WrapTexture(dst, bounds.width(), bounds.height(), result);
+ return true;
+}
+#endif
+
+class SkDiffuseLightingImageFilter : public SkLightingImageFilterInternal {
public:
static SkImageFilter* Create(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter*,
const CropRect*);
@@ -290,20 +419,20 @@ protected:
SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale,
SkScalar kd, SkImageFilter* input, const CropRect* cropRect);
void flatten(SkWriteBuffer& buffer) const override;
- virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
- SkBitmap* result, SkIPoint* offset) const override;
+ bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
+ SkBitmap* result, SkIPoint* offset) const override;
#if SK_SUPPORT_GPU
- virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
- const SkIRect& bounds) const override;
+ GrFragmentProcessor* getFragmentProcessor(GrTexture*, const SkMatrix&,
+ const SkIRect& bounds, BoundaryMode) const override;
#endif
private:
friend class SkLightingImageFilter;
- typedef SkLightingImageFilter INHERITED;
+ typedef SkLightingImageFilterInternal INHERITED;
SkScalar fKD;
};
-class SkSpecularLightingImageFilter : public SkLightingImageFilter {
+class SkSpecularLightingImageFilter : public SkLightingImageFilterInternal {
public:
static SkImageFilter* Create(SkLight* light, SkScalar surfaceScale,
SkScalar ks, SkScalar shininess, SkImageFilter*, const CropRect*);
@@ -318,30 +447,32 @@ protected:
SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks,
SkScalar shininess, SkImageFilter* input, const CropRect*);
void flatten(SkWriteBuffer& buffer) const override;
- virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
- SkBitmap* result, SkIPoint* offset) const override;
+ bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
+ SkBitmap* result, SkIPoint* offset) const override;
#if SK_SUPPORT_GPU
- virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
- const SkIRect& bounds) const override;
+ GrFragmentProcessor* getFragmentProcessor(GrTexture*, const SkMatrix&,
+ const SkIRect& bounds, BoundaryMode) const override;
#endif
private:
SkScalar fKS;
SkScalar fShininess;
friend class SkLightingImageFilter;
- typedef SkLightingImageFilter INHERITED;
+ typedef SkLightingImageFilterInternal INHERITED;
};
#if SK_SUPPORT_GPU
class GrLightingEffect : public GrSingleTextureEffect {
public:
- GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, const SkMatrix& matrix);
+ GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale,
+ const SkMatrix& matrix, BoundaryMode boundaryMode);
virtual ~GrLightingEffect();
const SkLight* light() const { return fLight; }
SkScalar surfaceScale() const { return fSurfaceScale; }
const SkMatrix& filterMatrix() const { return fFilterMatrix; }
+ BoundaryMode boundaryMode() const { return fBoundaryMode; }
protected:
bool onIsEqual(const GrFragmentProcessor&) const override;
@@ -356,6 +487,7 @@ private:
const SkLight* fLight;
SkScalar fSurfaceScale;
SkMatrix fFilterMatrix;
+ BoundaryMode fBoundaryMode;
};
class GrDiffuseLightingEffect : public GrLightingEffect {
@@ -364,12 +496,14 @@ public:
const SkLight* light,
SkScalar surfaceScale,
const SkMatrix& matrix,
- SkScalar kd) {
+ SkScalar kd,
+ BoundaryMode boundaryMode) {
return SkNEW_ARGS(GrDiffuseLightingEffect, (texture,
light,
surfaceScale,
matrix,
- kd));
+ kd,
+ boundaryMode));
}
const char* name() const override { return "DiffuseLighting"; }
@@ -387,7 +521,8 @@ private:
const SkLight* light,
SkScalar surfaceScale,
const SkMatrix& matrix,
- SkScalar kd);
+ SkScalar kd,
+ BoundaryMode boundaryMode);
GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
typedef GrLightingEffect INHERITED;
@@ -401,13 +536,15 @@ public:
SkScalar surfaceScale,
const SkMatrix& matrix,
SkScalar ks,
- SkScalar shininess) {
+ SkScalar shininess,
+ BoundaryMode boundaryMode) {
return SkNEW_ARGS(GrSpecularLightingEffect, (texture,
light,
surfaceScale,
matrix,
ks,
- shininess));
+ shininess,
+ boundaryMode));
}
const char* name() const override { return "SpecularLighting"; }
@@ -427,7 +564,8 @@ private:
SkScalar surfaceScale,
const SkMatrix& matrix,
SkScalar ks,
- SkScalar shininess);
+ SkScalar shininess,
+ BoundaryMode boundaryMode);
GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
typedef GrLightingEffect INHERITED;
@@ -481,8 +619,7 @@ private:
class GrGLDistantLight : public GrGLLight {
public:
virtual ~GrGLDistantLight() {}
- virtual void setData(const GrGLProgramDataManager&,
- const SkLight* light) const override;
+ void setData(const GrGLProgramDataManager&, const SkLight* light) const override;
void emitSurfaceToLight(GrGLFPBuilder*, const char* z) override;
private:
@@ -495,8 +632,7 @@ private:
class GrGLPointLight : public GrGLLight {
public:
virtual ~GrGLPointLight() {}
- virtual void setData(const GrGLProgramDataManager&,
- const SkLight* light) const override;
+ void setData(const GrGLProgramDataManager&, const SkLight* light) const override;
void emitSurfaceToLight(GrGLFPBuilder*, const char* z) override;
private:
@@ -509,8 +645,7 @@ private:
class GrGLSpotLight : public GrGLLight {
public:
virtual ~GrGLSpotLight() {}
- virtual void setData(const GrGLProgramDataManager&,
- const SkLight* light) const override;
+ void setData(const GrGLProgramDataManager&, const SkLight* light) const override;
void emitSurfaceToLight(GrGLFPBuilder*, const char* z) override;
void emitLightColor(GrGLFPBuilder*, const char *surfaceToLight) override;
@@ -695,7 +830,11 @@ private:
class SkSpotLight : public SkLight {
public:
- SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle, SkColor color)
+ SkSpotLight(const SkPoint3& location,
+ const SkPoint3& target,
+ SkScalar specularExponent,
+ SkScalar cutoffAngle,
+ SkColor color)
: INHERITED(color),
fLocation(location),
fTarget(target),
@@ -723,7 +862,14 @@ public:
SkPoint3 target(target2.fX, target2.fY, SkScalarAve(targetZ.fX, targetZ.fY));
SkPoint3 s = target - location;
s.normalize();
- return new SkSpotLight(location, target, fSpecularExponent, fCosOuterConeAngle, fCosInnerConeAngle, fConeScale, s, color());
+ return new SkSpotLight(location,
+ target,
+ fSpecularExponent,
+ fCosOuterConeAngle,
+ fCosInnerConeAngle,
+ fConeScale,
+ s,
+ color());
}
SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
@@ -777,7 +923,14 @@ public:
SkScalarIsFinite(fConeScale));
}
protected:
- SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cosOuterConeAngle, SkScalar cosInnerConeAngle, SkScalar coneScale, const SkPoint3& s, const SkPoint3& color)
+ SkSpotLight(const SkPoint3& location,
+ const SkPoint3& target,
+ SkScalar specularExponent,
+ SkScalar cosOuterConeAngle,
+ SkScalar cosInnerConeAngle,
+ SkScalar coneScale,
+ const SkPoint3& s,
+ const SkPoint3& color)
: INHERITED(color),
fLocation(location),
fTarget(target),
@@ -960,8 +1113,12 @@ SkImageFilter* SkDiffuseLightingImageFilter::Create(SkLight* light, SkScalar sur
return SkNEW_ARGS(SkDiffuseLightingImageFilter, (light, surfaceScale, kd, input, cropRect));
}
-SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter* input, const CropRect* cropRect)
- : SkLightingImageFilter(light, surfaceScale, input, cropRect),
+SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light,
+ SkScalar surfaceScale,
+ SkScalar kd,
+ SkImageFilter* input,
+ const CropRect* cropRect)
+ : INHERITED(light, surfaceScale, input, cropRect),
fKD(kd)
{
}
@@ -1020,13 +1177,28 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy,
bounds.offset(-srcOffset);
switch (transformedLight->type()) {
case SkLight::kDistant_LightType:
- lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
+ lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType,
+ transformedLight,
+ src,
+ dst,
+ surfaceScale(),
+ bounds);
break;
case SkLight::kPoint_LightType:
- lightBitmap<DiffuseLightingType, SkPointLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
+ lightBitmap<DiffuseLightingType, SkPointLight>(lightingType,
+ transformedLight,
+ src,
+ dst,
+ surfaceScale(),
+ bounds);
break;
case SkLight::kSpot_LightType:
- lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
+ lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType,
+ transformedLight,
+ src,
+ dst,
+ surfaceScale(),
+ bounds);
break;
}
@@ -1042,15 +1214,14 @@ void SkDiffuseLightingImageFilter::toString(SkString* str) const {
#endif
#if SK_SUPPORT_GPU
-bool SkDiffuseLightingImageFilter::asFragmentProcessor(GrFragmentProcessor** fp,
+GrFragmentProcessor* SkDiffuseLightingImageFilter::getFragmentProcessor(
GrTexture* texture,
const SkMatrix& matrix,
- const SkIRect&) const {
- if (fp) {
- SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
- *fp = GrDiffuseLightingEffect::Create(texture, light(), scale, matrix, kd());
- }
- return true;
+ const SkIRect&,
+ BoundaryMode boundaryMode
+) const {
+ SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
+ return GrDiffuseLightingEffect::Create(texture, light(), scale, matrix, kd(), boundaryMode);
}
#endif
@@ -1073,8 +1244,13 @@ SkImageFilter* SkSpecularLightingImageFilter::Create(SkLight* light, SkScalar su
(light, surfaceScale, ks, shininess, input, cropRect));
}
-SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect)
- : SkLightingImageFilter(light, surfaceScale, input, cropRect),
+SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light,
+ SkScalar surfaceScale,
+ SkScalar ks,
+ SkScalar shininess,
+ SkImageFilter* input,
+ const CropRect* cropRect)
+ : INHERITED(light, surfaceScale, input, cropRect),
fKS(ks),
fShininess(shininess)
{
@@ -1136,13 +1312,28 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy,
SkAutoTUnref<SkLight> transformedLight(light()->transform(ctx.ctm()));
switch (transformedLight->type()) {
case SkLight::kDistant_LightType:
- lightBitmap<SpecularLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
+ lightBitmap<SpecularLightingType, SkDistantLight>(lightingType,
+ transformedLight,
+ src,
+ dst,
+ surfaceScale(),
+ bounds);
break;
case SkLight::kPoint_LightType:
- lightBitmap<SpecularLightingType, SkPointLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
+ lightBitmap<SpecularLightingType, SkPointLight>(lightingType,
+ transformedLight,
+ src,
+ dst,
+ surfaceScale(),
+ bounds);
break;
case SkLight::kSpot_LightType:
- lightBitmap<SpecularLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
+ lightBitmap<SpecularLightingType, SkSpotLight>(lightingType,
+ transformedLight,
+ src,
+ dst,
+ surfaceScale(),
+ bounds);
break;
}
return true;
@@ -1157,15 +1348,14 @@ void SkSpecularLightingImageFilter::toString(SkString* str) const {
#endif
#if SK_SUPPORT_GPU
-bool SkSpecularLightingImageFilter::asFragmentProcessor(GrFragmentProcessor** fp,
- GrTexture* texture,
- const SkMatrix& matrix,
- const SkIRect&) const {
- if (fp) {
- SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
- *fp = GrSpecularLightingEffect::Create(texture, light(), scale, matrix, ks(), shininess());
- }
- return true;
+GrFragmentProcessor* SkSpecularLightingImageFilter::getFragmentProcessor(
+ GrTexture* texture,
+ const SkMatrix& matrix,
+ const SkIRect&,
+ BoundaryMode boundaryMode) const {
+ SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
+ return GrSpecularLightingEffect::Create(texture, light(), scale, matrix, ks(), shininess(),
+ boundaryMode);
}
#endif
@@ -1202,6 +1392,81 @@ SkLight* create_random_light(SkRandom* random) {
}
}
+SkString emitNormalFunc(BoundaryMode mode,
+ const char* pointToNormalName,
+ const char* sobelFuncName) {
+ SkString result;
+ switch (mode) {
+ case kTopLeft_BoundaryMode:
+ result.printf("\treturn %s(%s(0.0, 0.0, m[4], m[5], m[7], m[8], %g),\n"
+ "\t %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),\n"
+ "\t surfaceScale);\n",
+ pointToNormalName, sobelFuncName, gTwoThirds,
+ sobelFuncName, gTwoThirds);
+ break;
+ case kTop_BoundaryMode:
+ result.printf("\treturn %s(%s(0.0, 0.0, m[3], m[5], m[6], m[8], %g),\n"
+ "\t %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),\n"
+ "\t surfaceScale);\n",
+ pointToNormalName, sobelFuncName, gOneThird,
+ sobelFuncName, gOneHalf);
+ break;
+ case kTopRight_BoundaryMode:
+ result.printf("\treturn %s(%s( 0.0, 0.0, m[3], m[4], m[6], m[7], %g),\n"
+ "\t %s(m[3], m[6], m[4], m[7], 0.0, 0.0, %g),\n"
+ "\t surfaceScale);\n",
+ pointToNormalName, sobelFuncName, gTwoThirds,
+ sobelFuncName, gTwoThirds);
+ break;
+ case kLeft_BoundaryMode:
+ result.printf("\treturn %s(%s(m[1], m[2], m[4], m[5], m[7], m[8], %g),\n"
+ "\t %s( 0.0, 0.0, m[1], m[7], m[2], m[8], %g),\n"
+ "\t surfaceScale);\n",
+ pointToNormalName, sobelFuncName, gOneHalf,
+ sobelFuncName, gOneThird);
+ break;
+ case kInterior_BoundaryMode:
+ result.printf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], %g),\n"
+ "\t %s(m[0], m[6], m[1], m[7], m[2], m[8], %g),\n"
+ "\t surfaceScale);\n",
+ pointToNormalName, sobelFuncName, gOneQuarter,
+ sobelFuncName, gOneQuarter);
+ break;
+ case kRight_BoundaryMode:
+ result.printf("\treturn %s(%s(m[0], m[1], m[3], m[4], m[6], m[7], %g),\n"
+ "\t %s(m[0], m[6], m[1], m[7], 0.0, 0.0, %g),\n"
+ "\t surfaceScale);\n",
+ pointToNormalName, sobelFuncName, gOneHalf,
+ sobelFuncName, gOneThird);
+ break;
+ case kBottomLeft_BoundaryMode:
+ result.printf("\treturn %s(%s(m[1], m[2], m[4], m[5], 0.0, 0.0, %g),\n"
+ "\t %s( 0.0, 0.0, m[1], m[4], m[2], m[5], %g),\n"
+ "\t surfaceScale);\n",
+ pointToNormalName, sobelFuncName, gTwoThirds,
+ sobelFuncName, gTwoThirds);
+ break;
+ case kBottom_BoundaryMode:
+ result.printf("\treturn %s(%s(m[0], m[2], m[3], m[5], 0.0, 0.0, %g),\n"
+ "\t %s(m[0], m[3], m[1], m[4], m[2], m[5], %g),\n"
+ "\t surfaceScale);\n",
+ pointToNormalName, sobelFuncName, gOneThird,
+ sobelFuncName, gOneHalf);
+ break;
+ case kBottomRight_BoundaryMode:
+ result.printf("\treturn %s(%s(m[0], m[1], m[3], m[4], 0.0, 0.0, %g),\n"
+ "\t %s(m[0], m[3], m[1], m[4], 0.0, 0.0, %g),\n"
+ "\t surfaceScale);\n",
+ pointToNormalName, sobelFuncName, gTwoThirds,
+ sobelFuncName, gTwoThirds);
+ break;
+ default:
+ SkASSERT(false);
+ break;
+ }
+ return result;
+}
+
}
class GrGLLightingEffect : public GrGLFragmentProcessor {
@@ -1209,12 +1474,12 @@ public:
GrGLLightingEffect(const GrProcessor&);
virtual ~GrGLLightingEffect();
- virtual void emitCode(GrGLFPBuilder*,
- const GrFragmentProcessor&,
- const char* outputColor,
- const char* inputColor,
- const TransformedCoordsArray&,
- const TextureSamplerArray&) override;
+ void emitCode(GrGLFPBuilder*,
+ const GrFragmentProcessor&,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) override;
static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder* b);
@@ -1232,6 +1497,7 @@ private:
UniformHandle fImageIncrementUni;
UniformHandle fSurfaceScaleUni;
GrGLLight* fLight;
+ BoundaryMode fBoundaryMode;
};
///////////////////////////////////////////////////////////////////////////////
@@ -1268,11 +1534,13 @@ private:
GrLightingEffect::GrLightingEffect(GrTexture* texture,
const SkLight* light,
SkScalar surfaceScale,
- const SkMatrix& matrix)
+ const SkMatrix& matrix,
+ BoundaryMode boundaryMode)
: INHERITED(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture))
, fLight(light)
, fSurfaceScale(surfaceScale)
- , fFilterMatrix(matrix) {
+ , fFilterMatrix(matrix)
+ , fBoundaryMode(boundaryMode) {
fLight->ref();
if (light->requiresFragmentPosition()) {
this->setWillReadFragmentPosition();
@@ -1286,7 +1554,8 @@ GrLightingEffect::~GrLightingEffect() {
bool GrLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
const GrLightingEffect& s = sBase.cast<GrLightingEffect>();
return fLight->isEqual(*s.fLight) &&
- fSurfaceScale == s.fSurfaceScale;
+ fSurfaceScale == s.fSurfaceScale &&
+ fBoundaryMode == s.fBoundaryMode;
}
///////////////////////////////////////////////////////////////////////////////
@@ -1295,8 +1564,9 @@ GrDiffuseLightingEffect::GrDiffuseLightingEffect(GrTexture* texture,
const SkLight* light,
SkScalar surfaceScale,
const SkMatrix& matrix,
- SkScalar kd)
- : INHERITED(texture, light, surfaceScale, matrix), fKD(kd) {
+ SkScalar kd,
+ BoundaryMode boundaryMode)
+ : INHERITED(texture, light, surfaceScale, matrix, boundaryMode), fKD(kd) {
this->initClassID<GrDiffuseLightingEffect>();
}
@@ -1328,8 +1598,9 @@ GrFragmentProcessor* GrDiffuseLightingEffect::TestCreate(SkRandom* random,
for (int i = 0; i < 9; i++) {
matrix[i] = random->nextUScalar1();
}
+ BoundaryMode mode = static_cast<BoundaryMode>(random->nextU() % kBoundaryModeCount);
return GrDiffuseLightingEffect::Create(textures[GrProcessorUnitTest::kAlphaTextureIdx],
- light, surfaceScale, matrix, kd);
+ light, surfaceScale, matrix, kd, mode);
}
@@ -1338,6 +1609,7 @@ GrFragmentProcessor* GrDiffuseLightingEffect::TestCreate(SkRandom* random,
GrGLLightingEffect::GrGLLightingEffect(const GrProcessor& fp) {
const GrLightingEffect& m = fp.cast<GrLightingEffect>();
fLight = m.light()->createGLLight();
+ fBoundaryMode = m.boundaryMode();
}
GrGLLightingEffect::~GrGLLightingEffect() {
@@ -1388,27 +1660,23 @@ void GrGLLightingEffect::emitCode(GrGLFPBuilder* builder,
"pointToNormal",
SK_ARRAY_COUNT(gPointToNormalArgs),
gPointToNormalArgs,
- "\treturn normalize(vec3(-x * scale, y * scale, 1));\n",
+ "\treturn normalize(vec3(-x * scale, -y * scale, 1));\n",
&pointToNormalName);
static const GrGLShaderVar gInteriorNormalArgs[] = {
GrGLShaderVar("m", kFloat_GrSLType, 9),
GrGLShaderVar("surfaceScale", kFloat_GrSLType),
};
- SkString interiorNormalBody;
- interiorNormalBody.appendf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], 0.25),\n"
- "\t %s(m[0], m[6], m[1], m[7], m[2], m[8], 0.25),\n"
- "\t surfaceScale);\n",
- pointToNormalName.c_str(),
- sobelFuncName.c_str(),
- sobelFuncName.c_str());
- SkString interiorNormalName;
+ SkString normalBody = emitNormalFunc(fBoundaryMode,
+ pointToNormalName.c_str(),
+ sobelFuncName.c_str());
+ SkString normalName;
fsBuilder->emitFunction(kVec3f_GrSLType,
- "interiorNormal",
+ "normal",
SK_ARRAY_COUNT(gInteriorNormalArgs),
gInteriorNormalArgs,
- interiorNormalBody.c_str(),
- &interiorNormalName);
+ normalBody.c_str(),
+ &normalName);
fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str());
fsBuilder->codeAppend("\t\tfloat m[9];\n");
@@ -1417,7 +1685,7 @@ void GrGLLightingEffect::emitCode(GrGLFPBuilder* builder,
const char* surfScale = builder->getUniformCStr(fSurfaceScaleUni);
int index = 0;
- for (int dy = -1; dy <= 1; dy++) {
+ for (int dy = 1; dy >= -1; dy--) {
for (int dx = -1; dx <= 1; dx++) {
SkString texCoords;
texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc);
@@ -1432,7 +1700,7 @@ void GrGLLightingEffect::emitCode(GrGLFPBuilder* builder,
fLight->emitSurfaceToLight(builder, arg.c_str());
fsBuilder->codeAppend(";\n");
fsBuilder->codeAppendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ",
- outputColor, lightFunc.c_str(), interiorNormalName.c_str(), surfScale);
+ outputColor, lightFunc.c_str(), normalName.c_str(), surfScale);
fLight->emitLightColor(builder, "surfaceToLight");
fsBuilder->codeAppend(");\n");
SkString modulate;
@@ -1442,7 +1710,8 @@ void GrGLLightingEffect::emitCode(GrGLFPBuilder* builder,
void GrGLLightingEffect::GenKey(const GrProcessor& proc,
const GrGLCaps& caps, GrProcessorKeyBuilder* b) {
- b->add32(proc.cast<GrLightingEffect>().light()->type());
+ const GrLightingEffect& lighting = proc.cast<GrLightingEffect>();
+ b->add32(lighting.boundaryMode() << 2 | lighting.light()->type());
}
void GrGLLightingEffect::setData(const GrGLProgramDataManager& pdman,
@@ -1500,8 +1769,9 @@ GrSpecularLightingEffect::GrSpecularLightingEffect(GrTexture* texture,
SkScalar surfaceScale,
const SkMatrix& matrix,
SkScalar ks,
- SkScalar shininess)
- : INHERITED(texture, light, surfaceScale, matrix),
+ SkScalar shininess,
+ BoundaryMode boundaryMode)
+ : INHERITED(texture, light, surfaceScale, matrix, boundaryMode),
fKS(ks),
fShininess(shininess) {
this->initClassID<GrSpecularLightingEffect>();
@@ -1537,8 +1807,9 @@ GrFragmentProcessor* GrSpecularLightingEffect::TestCreate(SkRandom* random,
for (int i = 0; i < 9; i++) {
matrix[i] = random->nextUScalar1();
}
+ BoundaryMode mode = static_cast<BoundaryMode>(random->nextU() % kBoundaryModeCount);
return GrSpecularLightingEffect::Create(textures[GrProcessorUnitTest::kAlphaTextureIdx],
- light, surfaceScale, matrix, ks, shininess);
+ light, surfaceScale, matrix, ks, shininess, mode);
}
///////////////////////////////////////////////////////////////////////////////
@@ -1554,7 +1825,10 @@ void GrGLSpecularLightingEffect::emitLightFunc(GrGLFPBuilder* builder, SkString*
fKSUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kFloat_GrSLType, kDefault_GrSLPrecision, "KS", &ks);
fShininessUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kFloat_GrSLType, kDefault_GrSLPrecision, "Shininess", &shininess);
+ kFloat_GrSLType,
+ kDefault_GrSLPrecision,
+ "Shininess",
+ &shininess);
static const GrGLShaderVar gLightArgs[] = {
GrGLShaderVar("normal", kVec3f_GrSLType),
diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp
index 622713d796..6d2ee01d52 100644
--- a/src/effects/SkMagnifierImageFilter.cpp
+++ b/src/effects/SkMagnifierImageFilter.cpp
@@ -25,6 +25,7 @@ class GrMagnifierEffect : public GrSingleTextureEffect {
public:
static GrFragmentProcessor* Create(GrTexture* texture,
+ const SkRect& bounds,
float xOffset,
float yOffset,
float xInvZoom,
@@ -32,6 +33,7 @@ public:
float xInvInset,
float yInvInset) {
return SkNEW_ARGS(GrMagnifierEffect, (texture,
+ bounds,
xOffset,
yOffset,
xInvZoom,
@@ -48,15 +50,22 @@ public:
GrGLFragmentProcessor* createGLInstance() const override;
+ const SkRect& bounds() const { return fBounds; } // Bounds of source image.
+ // Offset to apply to zoomed pixels, (srcRect position / texture size).
float x_offset() const { return fXOffset; }
float y_offset() const { return fYOffset; }
+
+ // Scale to apply to zoomed pixels (srcRect size / bounds size).
float x_inv_zoom() const { return fXInvZoom; }
float y_inv_zoom() const { return fYInvZoom; }
+
+ // 1/radius over which to transition from unzoomed to zoomed pixels (bounds size / inset).
float x_inv_inset() const { return fXInvInset; }
float y_inv_inset() const { return fYInvInset; }
private:
GrMagnifierEffect(GrTexture* texture,
+ const SkRect& bounds,
float xOffset,
float yOffset,
float xInvZoom,
@@ -64,6 +73,7 @@ private:
float xInvInset,
float yInvInset)
: GrSingleTextureEffect(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture))
+ , fBounds(bounds)
, fXOffset(xOffset)
, fYOffset(yOffset)
, fXInvZoom(xInvZoom)
@@ -79,6 +89,7 @@ private:
GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
+ SkRect fBounds;
float fXOffset;
float fYOffset;
float fXInvZoom;
@@ -109,6 +120,7 @@ private:
UniformHandle fOffsetVar;
UniformHandle fInvZoomVar;
UniformHandle fInvInsetVar;
+ UniformHandle fBoundsVar;
typedef GrGLFragmentProcessor INHERITED;
};
@@ -134,6 +146,10 @@ void GrGLMagnifierEffect::emitCode(GrGLFPBuilder* builder,
GrGLProgramBuilder::kFragment_Visibility |
GrGLProgramBuilder::kVertex_Visibility,
kVec2f_GrSLType, kDefault_GrSLPrecision, "InvInset");
+ fBoundsVar = builder->addUniform(
+ GrGLProgramBuilder::kFragment_Visibility |
+ GrGLProgramBuilder::kVertex_Visibility,
+ kVec4f_GrSLType, kDefault_GrSLPrecision, "Bounds");
GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
@@ -142,9 +158,9 @@ void GrGLMagnifierEffect::emitCode(GrGLFPBuilder* builder,
builder->getUniformCStr(fOffsetVar),
coords2D.c_str(),
builder->getUniformCStr(fInvZoomVar));
-
- fsBuilder->codeAppend("\t\tvec2 delta = min(coord, vec2(1.0, 1.0) - coord);\n");
-
+ const char* bounds = builder->getUniformCStr(fBoundsVar);
+ fsBuilder->codeAppendf("\t\tvec2 delta = (coord - %s.xy) * %s.zw;\n", bounds, bounds);
+ fsBuilder->codeAppendf("\t\tdelta = min(delta, vec2(1.0, 1.0) - delta);\n");
fsBuilder->codeAppendf("\t\tdelta = delta * %s;\n", builder->getUniformCStr(fInvInsetVar));
fsBuilder->codeAppend("\t\tfloat weight = 0.0;\n");
@@ -175,6 +191,8 @@ void GrGLMagnifierEffect::setData(const GrGLProgramDataManager& pdman,
pdman.set2f(fOffsetVar, zoom.x_offset(), zoom.y_offset());
pdman.set2f(fInvZoomVar, zoom.x_inv_zoom(), zoom.y_inv_zoom());
pdman.set2f(fInvInsetVar, zoom.x_inv_inset(), zoom.y_inv_inset());
+ pdman.set4f(fBoundsVar, zoom.bounds().x(), zoom.bounds().y(),
+ zoom.bounds().width(), zoom.bounds().height());
}
/////////////////////////////////////////////////////////////////////
@@ -206,6 +224,7 @@ GrFragmentProcessor* GrMagnifierEffect::TestCreate(SkRandom* random,
GrFragmentProcessor* effect = GrMagnifierEffect::Create(
texture,
+ SkRect::MakeWH(SkIntToScalar(kMaxWidth), SkIntToScalar(kMaxHeight)),
(float) width / texture->width(),
(float) height / texture->height(),
texture->width() / (float) x,
@@ -220,7 +239,8 @@ GrFragmentProcessor* GrMagnifierEffect::TestCreate(SkRandom* random,
bool GrMagnifierEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
const GrMagnifierEffect& s = sBase.cast<GrMagnifierEffect>();
- return (this->fXOffset == s.fXOffset &&
+ return (this->fBounds == s.fBounds &&
+ this->fXOffset == s.fXOffset &&
this->fYOffset == s.fYOffset &&
this->fXInvZoom == s.fXInvZoom &&
this->fYInvZoom == s.fYInvZoom &&
@@ -258,18 +278,27 @@ SkMagnifierImageFilter::SkMagnifierImageFilter(const SkRect& srcRect, SkScalar i
#if SK_SUPPORT_GPU
bool SkMagnifierImageFilter::asFragmentProcessor(GrFragmentProcessor** fp, GrTexture* texture,
- const SkMatrix&, const SkIRect&) const {
+ const SkMatrix&, const SkIRect&bounds) const {
if (fp) {
- SkScalar yOffset = (texture->origin() == kTopLeft_GrSurfaceOrigin) ? fSrcRect.y() :
- (texture->height() - (fSrcRect.y() + fSrcRect.height()));
+ SkScalar yOffset = texture->origin() == kTopLeft_GrSurfaceOrigin ? fSrcRect.y() :
+ texture->height() - fSrcRect.height() * texture->height() / bounds.height()
+ - fSrcRect.y();
+ int boundsY = (texture->origin() == kTopLeft_GrSurfaceOrigin) ? bounds.y() :
+ (texture->height() - bounds.height());
+ SkRect effectBounds = SkRect::MakeXYWH(
+ SkIntToScalar(bounds.x()) / texture->width(),
+ SkIntToScalar(boundsY) / texture->height(),
+ SkIntToScalar(texture->width()) / bounds.width(),
+ SkIntToScalar(texture->height()) / bounds.height());
SkScalar invInset = fInset > 0 ? SkScalarInvert(fInset) : SK_Scalar1;
*fp = GrMagnifierEffect::Create(texture,
+ effectBounds,
fSrcRect.x() / texture->width(),
yOffset / texture->height(),
- fSrcRect.width() / texture->width(),
- fSrcRect.height() / texture->height(),
- texture->width() * invInset,
- texture->height() * invInset);
+ fSrcRect.width() / bounds.width(),
+ fSrcRect.height() / bounds.height(),
+ bounds.width() * invInset,
+ bounds.height() * invInset);
}
return true;
}
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 38a22e69f5..021cfba106 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -121,10 +121,15 @@ public:
///////////////////////////////////////////////////////////////////////////////
SkGpuDevice* SkGpuDevice::Create(GrRenderTarget* rt, const SkSurfaceProps* props, unsigned flags) {
+ return SkGpuDevice::Create(rt, rt->width(), rt->height(), props, flags);
+}
+
+SkGpuDevice* SkGpuDevice::Create(GrRenderTarget* rt, int width, int height,
+ const SkSurfaceProps* props, unsigned flags) {
if (!rt || rt->wasDestroyed()) {
return NULL;
}
- return SkNEW_ARGS(SkGpuDevice, (rt, props, flags));
+ return SkNEW_ARGS(SkGpuDevice, (rt, width, height, props, flags));
}
static SkDeviceProperties surfaceprops_to_deviceprops(const SkSurfaceProps* props) {
@@ -143,7 +148,8 @@ static SkSurfaceProps copy_or_default_props(const SkSurfaceProps* props) {
}
}
-SkGpuDevice::SkGpuDevice(GrRenderTarget* rt, const SkSurfaceProps* props, unsigned flags)
+SkGpuDevice::SkGpuDevice(GrRenderTarget* rt, int width, int height,
+ const SkSurfaceProps* props, unsigned flags)
: INHERITED(surfaceprops_to_deviceprops(props))
, fSurfaceProps(copy_or_default_props(props))
{
@@ -154,7 +160,7 @@ SkGpuDevice::SkGpuDevice(GrRenderTarget* rt, const SkSurfaceProps* props, unsign
fRenderTarget = SkRef(rt);
- SkImageInfo info = rt->surfacePriv().info();
+ SkImageInfo info = rt->surfacePriv().info().makeWH(width, height);
SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (info, rt));
fLegacyBitmap.setInfo(info);
fLegacyBitmap.setPixelRef(pr)->unref();
@@ -211,7 +217,7 @@ SkGpuDevice* SkGpuDevice::Create(GrContext* context, SkSurface::Budgeted budgete
return NULL;
}
- return SkNEW_ARGS(SkGpuDevice, (rt, props, flags));
+ return SkNEW_ARGS(SkGpuDevice, (rt, info.width(), info.height(), props, flags));
}
SkGpuDevice::~SkGpuDevice() {
@@ -736,9 +742,9 @@ GrTexture* create_mask_GPU(GrContext* context,
return mask;
}
-SkBitmap wrap_texture(GrTexture* texture) {
+SkBitmap wrap_texture(GrTexture* texture, int width, int height) {
SkBitmap result;
- result.setInfo(texture->surfacePriv().info());
+ result.setInfo(SkImageInfo::MakeN32Premul(width, height));
result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (result.info(), texture)))->unref();
return result;
}
@@ -1474,6 +1480,7 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
}
bool SkGpuDevice::filterTexture(GrContext* context, GrTexture* texture,
+ int width, int height,
const SkImageFilter* filter,
const SkImageFilter::Context& ctx,
SkBitmap* result, SkIPoint* offset) {
@@ -1484,7 +1491,8 @@ bool SkGpuDevice::filterTexture(GrContext* context, GrTexture* texture,
SkDeviceImageFilterProxy proxy(this, SkSurfaceProps(0, getLeakyProperties().pixelGeometry()));
if (filter->canFilterImageGPU()) {
- return filter->filterImageGPU(&proxy, wrap_texture(texture), ctx, result, offset);
+ return filter->filterImageGPU(&proxy, wrap_texture(texture, width, height),
+ ctx, result, offset);
} else {
return false;
}
@@ -1523,7 +1531,7 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
// This cache is transient, and is freed (along with all its contained
// textures) when it goes out of scope.
SkImageFilter::Context ctx(matrix, clipBounds, cache);
- if (this->filterTexture(fContext, texture, filter, ctx, &filteredBitmap,
+ if (this->filterTexture(fContext, texture, w, h, filter, ctx, &filteredBitmap,
&offset)) {
texture = (GrTexture*) filteredBitmap.getTexture();
w = filteredBitmap.width();
@@ -1637,8 +1645,8 @@ void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
// textures) when it goes out of scope.
SkAutoTUnref<SkImageFilter::Cache> cache(getImageFilterCache());
SkImageFilter::Context ctx(matrix, clipBounds, cache);
- if (this->filterTexture(fContext, devTex, filter, ctx, &filteredBitmap,
- &offset)) {
+ if (this->filterTexture(fContext, devTex, device->width(), device->height(),
+ filter, ctx, &filteredBitmap, &offset)) {
devTex = filteredBitmap.getTexture();
w = filteredBitmap.width();
h = filteredBitmap.height();
@@ -1691,7 +1699,8 @@ bool SkGpuDevice::filterImage(const SkImageFilter* filter, const SkBitmap& src,
// must be pushed upstack.
AutoBitmapTexture abt(fContext, src, NULL, &texture);
- return this->filterTexture(fContext, texture, filter, ctx, result, offset);
+ return this->filterTexture(fContext, texture, src.width(), src.height(),
+ filter, ctx, result, offset);
}
///////////////////////////////////////////////////////////////////////////////
@@ -1901,7 +1910,8 @@ SkBaseDevice* SkGpuDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint
if (texture) {
SkSurfaceProps props(fSurfaceProps.flags(), cinfo.fPixelGeometry);
- return SkGpuDevice::Create(texture->asRenderTarget(), &props, flags);
+ return SkGpuDevice::Create(
+ texture->asRenderTarget(), cinfo.fInfo.width(), cinfo.fInfo.height(), &props, flags);
} else {
SkErrorInternals::SetError( kInternalError_SkError,
"---- failed to create compatible device texture [%d %d]\n",
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index ad0c2d63f0..522cba80a1 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -41,6 +41,13 @@ public:
static SkGpuDevice* Create(GrRenderTarget* target, const SkSurfaceProps*, unsigned flags = 0);
/**
+ * Creates an SkGpuDevice from a GrRenderTarget whose texture width/height is
+ * different than its actual width/height (e.g., approx-match scratch texture).
+ */
+ static SkGpuDevice* Create(GrRenderTarget* target, int width, int height,
+ const SkSurfaceProps*, unsigned flags = 0);
+
+ /**
* New device that will create an offscreen renderTarget based on the ImageInfo and
* sampleCount. The Budgeted param controls whether the device's backing store counts against
* the resource cache budget. On failure, returns NULL.
@@ -67,7 +74,7 @@ public:
GrRenderTarget* accessRenderTarget() override;
SkImageInfo imageInfo() const override {
- return fRenderTarget ? fRenderTarget->surfacePriv().info() : SkImageInfo::MakeUnknown();
+ return fLegacyBitmap.info();
}
const SkSurfaceProps& surfaceProps() const { return fSurfaceProps; }
@@ -121,7 +128,7 @@ public:
const SkImageFilter::Context&,
SkBitmap*, SkIPoint*) override;
- bool filterTexture(GrContext*, GrTexture*, const SkImageFilter*,
+ bool filterTexture(GrContext*, GrTexture*, int width, int height, const SkImageFilter*,
const SkImageFilter::Context&,
SkBitmap* result, SkIPoint* offset);
@@ -147,7 +154,7 @@ private:
SkBitmap fLegacyBitmap;
bool fNeedClear;
- SkGpuDevice(GrRenderTarget*, const SkSurfaceProps*, unsigned flags);
+ SkGpuDevice(GrRenderTarget*, int width, int height, const SkSurfaceProps*, unsigned flags);
SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override;