#include "gm.h"
#include "SkArithmeticMode.h"
+#include "SkOffsetImageFilter.h"
#include "SkXfermodeImageFilter.h"
#include "SkBitmapSource.h"
return make_isize(WIDTH, HEIGHT);
}
- void drawClippedBitmap(SkCanvas* canvas, const SkBitmap& bitmap, const SkPaint& paint, SkScalar x, SkScalar y) {
+ void drawClippedBitmap(SkCanvas* canvas, const SkBitmap& bitmap, const SkPaint& paint,
+ SkScalar x, SkScalar y) {
canvas->save();
canvas->clipRect(SkRect::MakeXYWH(x, y,
SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())));
SkAutoTUnref<SkImageFilter> background(SkNEW_ARGS(SkBitmapSource, (fCheckerboard)));
for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(gModes[i].fMode));
- SkAutoTUnref<SkImageFilter> filter(SkNEW_ARGS(SkXfermodeImageFilter, (mode, background)));
+ SkAutoTUnref<SkImageFilter> filter(SkNEW_ARGS(
+ SkXfermodeImageFilter, (mode, background)));
paint.setImageFilter(filter);
drawClippedBitmap(canvas, fBitmap, paint, SkIntToScalar(x), SkIntToScalar(y));
x += fBitmap.width() + MARGIN;
filter.reset(SkNEW_ARGS(SkXfermodeImageFilter, (NULL, background)));
paint.setImageFilter(filter);
drawClippedBitmap(canvas, fBitmap, paint, SkIntToScalar(x), SkIntToScalar(y));
+ x += fBitmap.width() + MARGIN;
+ if (x + fBitmap.width() > WIDTH) {
+ x = 0;
+ y += fBitmap.height() + MARGIN;
+ }
+ // Test offsets on SrcMode (uses fixed-function blend)
+ SkAutoTUnref<SkImageFilter> foreground(SkNEW_ARGS(SkBitmapSource, (fBitmap)));
+ SkAutoTUnref<SkImageFilter> offsetForeground(SkNEW_ARGS(SkOffsetImageFilter,
+ (SkIntToScalar(4), SkIntToScalar(-4), foreground)));
+ SkAutoTUnref<SkImageFilter> offsetBackground(SkNEW_ARGS(SkOffsetImageFilter,
+ (SkIntToScalar(4), SkIntToScalar(4), background)));
+ mode.reset(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
+ filter.reset(SkNEW_ARGS(SkXfermodeImageFilter,
+ (mode, offsetBackground, offsetForeground)));
+ paint.setImageFilter(filter);
+ canvas->save();
+ canvas->clipRect(SkRect::MakeXYWH(x, y,
+ SkIntToScalar(fBitmap.width() + 4), SkIntToScalar(fBitmap.height() + 4)));
+ canvas->drawPaint(paint);
+ canvas->restore();
+ x += fBitmap.width() + MARGIN;
+ if (x + fBitmap.width() > WIDTH) {
+ x = 0;
+ y += fBitmap.height() + MARGIN;
+ }
+ // Test offsets on Darken (uses shader blend)
+ mode.reset(SkXfermode::Create(SkXfermode::kDarken_Mode));
+ filter.reset(SkNEW_ARGS(SkXfermodeImageFilter, (mode, offsetBackground, offsetForeground)));
+ paint.setImageFilter(filter);
+ canvas->save();
+ canvas->clipRect(SkRect::MakeXYWH(x, y,
+ SkIntToScalar(fBitmap.width() + 4), SkIntToScalar(fBitmap.height() + 4)));
+ canvas->drawPaint(paint);
+ canvas->restore();
}
private:
typedef GM INHERITED;
* textures. For single-pass effects, use asNewEffect(). src is the
* source image for processing, as a texture-backed bitmap. result is
* the destination bitmap, which should contain a texture-backed pixelref
- * on success. The default implementation does single-pass processing
- * using asNewEffect().
+ * on success. offset is the amount to translate the resulting image
+ * relative to the src when it is drawn. The default implementation does
+ * single-pass processing using asNewEffect().
*/
- virtual bool filterImageGPU(Proxy*, const SkBitmap& src, SkBitmap* result);
+ virtual bool filterImageGPU(Proxy*, const SkBitmap& src, SkBitmap* result, SkIPoint* offset);
/**
* Returns whether this image filter is a color filter and puts the color filter into the
* this function returns src. If the filter has no GPU implementation, it
* will be processed in software and uploaded to the GPU.
*/
- static bool GetInputResultGPU(SkImageFilter* filter, SkImageFilter::Proxy* proxy, const SkBitmap& src, SkBitmap* result);
+ static bool GetInputResultGPU(SkImageFilter* filter, SkImageFilter::Proxy* proxy,
+ const SkBitmap& src, SkBitmap* result, SkIPoint* offset);
};
#endif
passed to filterImage() is used instead.
*/
- SkBicubicImageFilter(const SkSize& scale, const SkScalar coefficients[16], SkImageFilter* input = NULL);
+ SkBicubicImageFilter(const SkSize& scale, const SkScalar coefficients[16],
+ SkImageFilter* input = NULL);
static SkBicubicImageFilter* CreateMitchell(const SkSize& scale, SkImageFilter* input = NULL);
virtual ~SkBicubicImageFilter();
#if SK_SUPPORT_GPU
virtual bool canFilterImageGPU() const SK_OVERRIDE { return true; }
- virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) SK_OVERRIDE;
+ virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result,
+ SkIPoint* offset) SK_OVERRIDE;
#endif
private:
SkIPoint* offset) SK_OVERRIDE;
#if SK_SUPPORT_GPU
virtual bool canFilterImageGPU() const SK_OVERRIDE { return true; }
- virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) SK_OVERRIDE;
+ virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result,
+ SkIPoint* offset) SK_OVERRIDE;
#endif
protected:
SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
bool canFilterImageGPU() const SK_OVERRIDE { return true; }
- virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) SK_OVERRIDE;
+ virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result,
+ SkIPoint* offset) SK_OVERRIDE;
private:
SkSize fSigma;
kKeyBits = 3 // Max value is 4, so 3 bits are required at most
};
- SkDisplacementMapEffect(ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, SkScalar scale, SkImageFilter* displacement, SkImageFilter* color = NULL);
+ SkDisplacementMapEffect(ChannelSelectorType xChannelSelector,
+ ChannelSelectorType yChannelSelector,
+ SkScalar scale, SkImageFilter* displacement,
+ SkImageFilter* color = NULL);
~SkDisplacementMapEffect();
SkIPoint* offset) SK_OVERRIDE;
#if SK_SUPPORT_GPU
virtual bool canFilterImageGPU() const SK_OVERRIDE { return true; }
- virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) SK_OVERRIDE;
+ virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result,
+ SkIPoint* offset) SK_OVERRIDE;
#endif
protected:
* this function returns src. If the filter has no GPU implementation, it
* will be processed in software and uploaded to the GPU.
*/
- static bool GetInputResultGPU(SkImageFilter* filter, SkImageFilter::Proxy* proxy, const SkBitmap& src, SkBitmap* result);
+ static bool GetInputResultGPU(SkImageFilter* filter, SkImageFilter::Proxy* proxy,
+ const SkBitmap& src, SkBitmap* result, SkIPoint* offset);
};
#endif
virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
#if SK_SUPPORT_GPU
- virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) SK_OVERRIDE;
+ virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result,
+ SkIPoint* offset) SK_OVERRIDE;
#endif
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDilateImageFilter)
virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
#if SK_SUPPORT_GPU
- virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) SK_OVERRIDE;
+ virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result,
+ SkIPoint* offset) SK_OVERRIDE;
#endif
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkErodeImageFilter)
*/
public:
- SkXfermodeImageFilter(SkXfermode* mode, SkImageFilter* background, SkImageFilter* foreground = NULL);
+ SkXfermodeImageFilter(SkXfermode* mode, SkImageFilter* background,
+ SkImageFilter* foreground = NULL);
virtual ~SkXfermodeImageFilter();
SkIPoint* offset) SK_OVERRIDE;
#if SK_SUPPORT_GPU
virtual bool canFilterImageGPU() const SK_OVERRIDE { return true; }
- virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) SK_OVERRIDE;
+ virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result,
+ SkIPoint* offset) SK_OVERRIDE;
#endif
protected:
return this->asNewEffect(NULL, NULL);
}
-bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) {
+bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result,
+ SkIPoint* offset) {
#if SK_SUPPORT_GPU
SkBitmap input;
SkASSERT(fInputCount == 1);
- if (!SkImageFilterUtils::GetInputResultGPU(this->getInput(0), proxy, src, &input)) {
+ if (!SkImageFilterUtils::GetInputResultGPU(this->getInput(0), proxy, src, &input, offset)) {
return false;
}
GrTexture* srcTexture = input.getTexture();
return true;
}
-bool SkImageFilterUtils::GetInputResultGPU(SkImageFilter* filter, SkImageFilter::Proxy* proxy, const SkBitmap& src, SkBitmap* result) {
+bool SkImageFilterUtils::GetInputResultGPU(SkImageFilter* filter, SkImageFilter::Proxy* proxy,
+ const SkBitmap& src, SkBitmap* result,
+ SkIPoint* offset) {
if (!filter) {
*result = src;
return true;
} else if (filter->canFilterImageGPU()) {
- return filter->filterImageGPU(proxy, src, result);
+ return filter->filterImageGPU(proxy, src, result, offset);
} else {
- SkIPoint offset;
- if (filter->filterImage(proxy, src, SkMatrix(), result, &offset)) {
+ if (filter->filterImage(proxy, src, SkMatrix(), result, offset)) {
if (!result->getTexture()) {
GrContext* context = ((GrTexture *) src.getTexture())->getContext();
GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context,
return GrBicubicEffect::Create(textures[texIdx], coefficients);
}
-bool SkBicubicImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) {
+bool SkBicubicImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result, SkIPoint* offset) {
SkBitmap srcBM;
- if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, &srcBM)) {
+ if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, &srcBM, offset)) {
return false;
}
GrTexture* srcTexture = srcBM.getTexture();
SkImageFilter* backgroundInput = getBackgroundInput();
SkImageFilter* foregroundInput = getForegroundInput();
SkASSERT(NULL != backgroundInput);
- if (!backgroundInput->filterImage(proxy, src, ctm, &background, offset)) {
+ SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
+ if (!backgroundInput->filterImage(proxy, src, ctm, &background, &backgroundOffset)) {
return false;
}
- if (foregroundInput && !foregroundInput->filterImage(proxy, src, ctm, &foreground, offset)) {
+ SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
+ if (foregroundInput &&
+ !foregroundInput->filterImage(proxy, src, ctm, &foreground, &foregroundOffset)) {
return false;
}
SkAutoLockPixels alp_foreground(foreground), alp_background(background);
SkCanvas canvas(*dst);
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
- canvas.drawBitmap(background, 0, 0, &paint);
+ canvas.drawBitmap(background, backgroundOffset.fX, backgroundOffset.fY, &paint);
paint.setXfermodeMode(modeToXfermode(fMode));
- canvas.drawBitmap(foreground, 0, 0, &paint);
+ canvas.drawBitmap(foreground, foregroundOffset.fX, foregroundOffset.fY, &paint);
return true;
}
public:
static GrEffectRef* Create(SkBlendImageFilter::Mode mode,
GrTexture* foreground,
- GrTexture* background) {
- AutoEffectUnref effect(SkNEW_ARGS(GrBlendEffect, (mode, foreground, background)));
+ const SkIPoint& foregroundOffset,
+ GrTexture* background,
+ const SkIPoint& backgroundOffset) {
+ AutoEffectUnref effect(SkNEW_ARGS(GrBlendEffect, (mode, foreground, foregroundOffset,
+ background, backgroundOffset)));
return CreateEffectRef(effect);
}
virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
SkBlendImageFilter::Mode mode() const { return fMode; }
+ const SkMatrix& foregroundMatrix() const { return fForegroundMatrix; }
+ const SkMatrix& backgroundMatrix() const { return fBackgroundMatrix; }
typedef GrGLBlendEffect GLEffect;
static const char* Name() { return "Blend"; }
private:
virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
- GrBlendEffect(SkBlendImageFilter::Mode mode, GrTexture* foreground, GrTexture* background);
+ GrBlendEffect(SkBlendImageFilter::Mode mode,
+ GrTexture* foreground, const SkIPoint& foregroundOffset,
+ GrTexture* background, const SkIPoint& backgroundOffset);
GrTextureAccess fForegroundAccess;
+ SkMatrix fForegroundMatrix;
GrTextureAccess fBackgroundAccess;
+ SkMatrix fBackgroundMatrix;
SkBlendImageFilter::Mode fMode;
typedef GrEffect INHERITED;
};
-bool SkBlendImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) {
+bool SkBlendImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result,
+ SkIPoint* offset) {
SkBitmap backgroundBM;
- if (!SkImageFilterUtils::GetInputResultGPU(getBackgroundInput(), proxy, src, &backgroundBM)) {
+ SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
+ if (!SkImageFilterUtils::GetInputResultGPU(getBackgroundInput(), proxy, src, &backgroundBM,
+ &backgroundOffset)) {
return false;
}
GrTexture* background = backgroundBM.getTexture();
SkBitmap foregroundBM;
- if (!SkImageFilterUtils::GetInputResultGPU(getForegroundInput(), proxy, src, &foregroundBM)) {
+ SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
+ if (!SkImageFilterUtils::GetInputResultGPU(getForegroundInput(), proxy, src, &foregroundBM,
+ &foregroundOffset)) {
return false;
}
GrTexture* foreground = foregroundBM.getTexture();
GrPaint paint;
paint.colorStage(0)->setEffect(
- GrBlendEffect::Create(fMode, foreground, background))->unref();
+ GrBlendEffect::Create(fMode, foreground, foregroundOffset, background, backgroundOffset))->unref();
SkRect srcRect;
src.getBounds(&srcRect);
context->drawRect(paint, srcRect);
GrBlendEffect::GrBlendEffect(SkBlendImageFilter::Mode mode,
GrTexture* foreground,
- GrTexture* background)
+ const SkIPoint& foregroundOffset,
+ GrTexture* background,
+ const SkIPoint& backgroundOffset)
: fForegroundAccess(foreground)
, fBackgroundAccess(background)
, fMode(mode) {
this->addTextureAccess(&fForegroundAccess);
this->addTextureAccess(&fBackgroundAccess);
+ fForegroundMatrix = GrEffect::MakeDivByTextureWHMatrix(foreground);
+ fForegroundMatrix.preTranslate(SkIntToScalar(-foregroundOffset.fX),
+ SkIntToScalar(-foregroundOffset.fY));
+ fBackgroundMatrix = GrEffect::MakeDivByTextureWHMatrix(background);
+ fBackgroundMatrix.preTranslate(SkIntToScalar(-backgroundOffset.fX),
+ SkIntToScalar(-backgroundOffset.fY));
}
GrBlendEffect::~GrBlendEffect() {
GrTexture* fgTex = blend.texture(0);
GrTexture* bgTex = blend.texture(1);
fForegroundEffectMatrix.setData(uman,
- GrEffect::MakeDivByTextureWHMatrix(fgTex),
+ blend.foregroundMatrix(),
drawEffect,
fgTex);
fBackgroundEffectMatrix.setData(uman,
- GrEffect::MakeDivByTextureWHMatrix(bgTex),
+ blend.backgroundMatrix(),
drawEffect,
bgTex);
}
}
-static void getBox3Params(SkScalar s, int *kernelSize, int* kernelSize3, int *lowOffset, int *highOffset)
+static void getBox3Params(SkScalar s, int *kernelSize, int* kernelSize3, int *lowOffset,
+ int *highOffset)
{
float pi = SkScalarToFloat(SK_ScalarPI);
int d = static_cast<int>(floorf(SkScalarToFloat(s) * 3.0f * sqrtf(2.0f * pi) / 4.0f + 0.5f));
return true;
}
-bool SkBlurImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) {
+bool SkBlurImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result,
+ SkIPoint* offset) {
#if SK_SUPPORT_GPU
SkBitmap input;
- if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, &input)) {
+ if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, &input, offset)) {
return false;
}
GrTexture* source = input.getTexture();
typedef GrEffect INHERITED;
};
-bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) {
+bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result,
+ SkIPoint* offset) {
SkBitmap colorBM;
- if (!SkImageFilterUtils::GetInputResultGPU(getColorInput(), proxy, src, &colorBM)) {
+ SkIPoint colorOffset = SkIPoint::Make(0, 0);
+ if (!SkImageFilterUtils::GetInputResultGPU(getColorInput(), proxy, src, &colorBM,
+ &colorOffset)) {
return false;
}
GrTexture* color = colorBM.getTexture();
SkBitmap displacementBM;
- if (!SkImageFilterUtils::GetInputResultGPU(getDisplacementInput(), proxy, src, &displacementBM)) {
+ SkIPoint displacementOffset = SkIPoint::Make(0, 0);
+ if (!SkImageFilterUtils::GetInputResultGPU(getDisplacementInput(), proxy, src, &displacementBM,
+ &displacementOffset)) {
return false;
}
GrTexture* displacement = displacementBM.getTexture();
color))->unref();
SkRect srcRect;
src.getBounds(&srcRect);
- context->drawRect(paint, srcRect);
+ SkRect dstRect = srcRect;
+ dstRect.offset(SkIntToScalar(colorOffset.fX), SkIntToScalar(colorOffset.fY));
+ context->drawRectToRect(paint, srcRect, dstRect);
return SkImageFilterUtils::WrapTexture(dst, src.width(), src.height(), result);
}
};
-bool SkDilateImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) {
+bool SkDilateImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result,
+ SkIPoint* offset) {
SkBitmap inputBM;
- if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, &inputBM)) {
+ if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, &inputBM, offset)) {
return false;
}
GrTexture* input = inputBM.getTexture();
return SkImageFilterUtils::WrapTexture(resultTex, src.width(), src.height(), result);
}
-bool SkErodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) {
+bool SkErodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result,
+ SkIPoint* offset) {
SkBitmap inputBM;
- if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, &inputBM)) {
+ if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, &inputBM, offset)) {
return false;
}
GrTexture* input = inputBM.getTexture();
///////////////////////////////////////////////////////////////////////////////
-SkXfermodeImageFilter::SkXfermodeImageFilter(SkXfermode* mode, SkImageFilter* background, SkImageFilter* foreground)
+SkXfermodeImageFilter::SkXfermodeImageFilter(SkXfermode* mode,
+ SkImageFilter* background,
+ SkImageFilter* foreground)
: INHERITED(background, foreground), fMode(mode) {
SkSafeRef(fMode);
}
SkBitmap background = src, foreground = src;
SkImageFilter* backgroundInput = getInput(0);
SkImageFilter* foregroundInput = getInput(1);
- if (backgroundInput && !backgroundInput->filterImage(proxy, src, ctm, &background, offset)) {
+ SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
+ if (backgroundInput &&
+ !backgroundInput->filterImage(proxy, src, ctm, &background, &backgroundOffset)) {
return false;
}
- if (foregroundInput && !foregroundInput->filterImage(proxy, src, ctm, &foreground, offset)) {
+ SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
+ if (foregroundInput &&
+ !foregroundInput->filterImage(proxy, src, ctm, &foreground, &foregroundOffset)) {
return false;
}
dst->setConfig(background.config(), background.width(), background.height());
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
canvas.drawBitmap(background, 0, 0, &paint);
paint.setXfermode(fMode);
- canvas.drawBitmap(foreground, 0, 0, &paint);
+ canvas.drawBitmap(foreground,
+ SkIntToScalar(foregroundOffset.fX - backgroundOffset.fX),
+ SkIntToScalar(foregroundOffset.fY - backgroundOffset.fY),
+ &paint);
+ offset->fX += backgroundOffset.fX;
+ offset->fY += backgroundOffset.fY;
return true;
}
#if SK_SUPPORT_GPU
-bool SkXfermodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) {
+bool SkXfermodeImageFilter::filterImageGPU(Proxy* proxy,
+ const SkBitmap& src,
+ SkBitmap* result,
+ SkIPoint* offset) {
SkBitmap background;
- if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, &background)) {
+ SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
+ if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, &background,
+ &backgroundOffset)) {
return false;
}
GrTexture* backgroundTex = background.getTexture();
SkBitmap foreground;
- if (!SkImageFilterUtils::GetInputResultGPU(getInput(1), proxy, src, &foreground)) {
+ SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
+ if (!SkImageFilterUtils::GetInputResultGPU(getInput(1), proxy, src, &foreground,
+ &foregroundOffset)) {
return false;
}
GrTexture* foregroundTex = foreground.getTexture();
return false;
}
+ SkMatrix foregroundMatrix = GrEffect::MakeDivByTextureWHMatrix(foregroundTex);
+ foregroundMatrix.preTranslate(SkIntToScalar(backgroundOffset.fX-foregroundOffset.fX),
+ SkIntToScalar(backgroundOffset.fY-foregroundOffset.fY));
+
+
GrPaint paint;
SkRect srcRect;
src.getBounds(&srcRect);
if (NULL != xferEffect) {
paint.colorStage(0)->setEffect(
- GrSimpleTextureEffect::Create(foregroundTex, GrEffect::MakeDivByTextureWHMatrix(foregroundTex)))->unref();
+ GrSimpleTextureEffect::Create(foregroundTex, foregroundMatrix))->unref();
paint.colorStage(1)->setEffect(xferEffect)->unref();
context->drawRect(paint, srcRect);
} else {
+ SkMatrix backgroundMatrix = GrEffect::MakeDivByTextureWHMatrix(backgroundTex);
paint.colorStage(0)->setEffect(
- GrSimpleTextureEffect::Create(backgroundTex, GrEffect::MakeDivByTextureWHMatrix(backgroundTex)))->unref();
+ GrSimpleTextureEffect::Create(backgroundTex, backgroundMatrix))->unref();
context->drawRect(paint, srcRect);
paint.setBlendFunc(sk_blend_to_grblend(sm), sk_blend_to_grblend(dm));
paint.colorStage(0)->setEffect(
- GrSimpleTextureEffect::Create(foregroundTex, GrEffect::MakeDivByTextureWHMatrix(foregroundTex)))->unref();
+ GrSimpleTextureEffect::Create(foregroundTex, foregroundMatrix))->unref();
context->drawRect(paint, srcRect);
}
+ offset->fX += backgroundOffset.fX;
+ offset->fY += backgroundOffset.fY;
return SkImageFilterUtils::WrapTexture(dst, src.width(), src.height(), result);
}
static bool filter_texture(SkDevice* device, GrContext* context,
GrTexture* texture, SkImageFilter* filter,
- int w, int h, SkBitmap* result) {
+ int w, int h, SkBitmap* result, SkIPoint* offset) {
GrAssert(filter);
SkDeviceImageFilterProxy proxy(device);
// Save the render target and set it to NULL, so we don't accidentally draw to it in the
// filter. Also set the clip wide open and the matrix to identity.
GrContext::AutoWideOpenIdentityDraw awo(context, NULL);
- return filter->filterImageGPU(&proxy, wrap_texture(texture), result);
+ return filter->filterImageGPU(&proxy, wrap_texture(texture), result, offset);
} else {
return false;
}
GrSimpleTextureEffect::Create(texture, SkMatrix::I()))->unref();
SkImageFilter* filter = paint.getImageFilter();
+ SkIPoint offset = SkIPoint::Make(0, 0);
if (NULL != filter) {
SkBitmap filterBitmap;
- if (filter_texture(this, fContext, texture, filter, w, h, &filterBitmap)) {
+ if (filter_texture(this, fContext, texture, filter, w, h, &filterBitmap, &offset)) {
grPaint.colorStage(kBitmapEffectIdx)->setEffect(
GrSimpleTextureEffect::Create(filterBitmap.getTexture(), SkMatrix::I()))->unref();
texture = filterBitmap.getTexture();
SkIntToScalar(top),
SkIntToScalar(w),
SkIntToScalar(h)),
- GrRect::MakeWH(SK_Scalar1 * w / texture->width(),
- SK_Scalar1 * h / texture->height()));
+ GrRect::MakeXYWH(offset.fX,
+ offset.fY,
+ SK_Scalar1 * w / texture->width(),
+ SK_Scalar1 * h / texture->height()));
}
void SkGpuDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
SkImageFilter* filter = paint.getImageFilter();
if (NULL != filter) {
SkBitmap filterBitmap;
- if (filter_texture(this, fContext, devTex, filter, w, h, &filterBitmap)) {
+ SkIPoint offset = SkIPoint::Make(0, 0);
+ if (filter_texture(this, fContext, devTex, filter, w, h, &filterBitmap, &offset)) {
grPaint.colorStage(kBitmapEffectIdx)->setEffect(
GrSimpleTextureEffect::Create(filterBitmap.getTexture(), SkMatrix::I()))->unref();
devTex = filterBitmap.getTexture();
w = filterBitmap.width();
h = filterBitmap.height();
+ x += offset.fX;
+ y += offset.fY;
}
}
// must be pushed upstack.
SkAutoCachedTexture act(this, src, NULL, &texture);
- return filter_texture(this, fContext, texture, filter, src.width(), src.height(), result);
+ return filter_texture(this, fContext, texture, filter, src.width(), src.height(), result, offset);
}
///////////////////////////////////////////////////////////////////////////////