Implement offset for GPU filter path. Although we can't yet use this in Blink for FEOffset, due to SVG semantics, we can use it to support crop rect (upcoming patch).
This patch adds the parameter to the filterImageGPU() signature, plumbs through the code on the GPU side, and implements support for it in SkXfermodeImageFilter for both raster and GPU. Of the remaining filters with GPU implementations, Blur, Morphology, Bicubic and Displacement work fine; they're commutative wrt offset and can simply pass it up the chain. Blend is not, but will be removed shortly anyway (has been replaced with SkXfermodeImageFilter in Blink). R=reed@google.com, bsalomon@google.com Author: senorblanco@chromium.org Review URL: https://chromiumcodereview.appspot.com/15995026 git-svn-id: http://skia.googlecode.com/svn/trunk@9977 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
b446fc7f05
commit
7b320703d4
@ -7,6 +7,7 @@
|
||||
|
||||
#include "gm.h"
|
||||
#include "SkArithmeticMode.h"
|
||||
#include "SkOffsetImageFilter.h"
|
||||
#include "SkXfermodeImageFilter.h"
|
||||
#include "SkBitmapSource.h"
|
||||
|
||||
@ -68,7 +69,8 @@ protected:
|
||||
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())));
|
||||
@ -125,7 +127,8 @@ protected:
|
||||
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;
|
||||
@ -148,6 +151,40 @@ protected:
|
||||
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;
|
||||
|
@ -109,10 +109,11 @@ public:
|
||||
* 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
|
||||
|
@ -28,7 +28,8 @@ public:
|
||||
* 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
|
||||
|
@ -27,7 +27,8 @@ public:
|
||||
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();
|
||||
|
||||
@ -42,7 +43,8 @@ protected:
|
||||
|
||||
#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:
|
||||
|
@ -33,7 +33,8 @@ public:
|
||||
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:
|
||||
|
@ -25,7 +25,8 @@ 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;
|
||||
|
@ -22,7 +22,10 @@ public:
|
||||
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();
|
||||
|
||||
@ -35,7 +38,8 @@ public:
|
||||
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:
|
||||
|
@ -28,7 +28,8 @@ public:
|
||||
* 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
|
||||
|
@ -38,7 +38,8 @@ public:
|
||||
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)
|
||||
@ -58,7 +59,8 @@ public:
|
||||
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)
|
||||
|
@ -21,7 +21,8 @@ class SK_API SkXfermodeImageFilter : public SkImageFilter {
|
||||
*/
|
||||
|
||||
public:
|
||||
SkXfermodeImageFilter(SkXfermode* mode, SkImageFilter* background, SkImageFilter* foreground = NULL);
|
||||
SkXfermodeImageFilter(SkXfermode* mode, SkImageFilter* background,
|
||||
SkImageFilter* foreground = NULL);
|
||||
|
||||
virtual ~SkXfermodeImageFilter();
|
||||
|
||||
@ -34,7 +35,8 @@ public:
|
||||
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:
|
||||
|
@ -98,11 +98,12 @@ bool SkImageFilter::canFilterImageGPU() const {
|
||||
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();
|
||||
|
@ -20,15 +20,16 @@ bool SkImageFilterUtils::WrapTexture(GrTexture* texture, int width, int height,
|
||||
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,
|
||||
|
@ -341,9 +341,9 @@ GrEffectRef* GrBicubicEffect::TestCreate(SkMWCRandom* random,
|
||||
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();
|
||||
|
@ -68,10 +68,13 @@ bool SkBlendImageFilter::onFilterImage(Proxy* proxy,
|
||||
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);
|
||||
@ -83,9 +86,9 @@ bool SkBlendImageFilter::onFilterImage(Proxy* proxy,
|
||||
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;
|
||||
}
|
||||
|
||||
@ -124,8 +127,11 @@ class GrBlendEffect : public GrEffect {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -133,6 +139,8 @@ public:
|
||||
|
||||
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"; }
|
||||
@ -142,22 +150,31 @@ public:
|
||||
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();
|
||||
@ -176,7 +193,7 @@ bool SkBlendImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBit
|
||||
|
||||
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);
|
||||
@ -187,12 +204,20 @@ bool SkBlendImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBit
|
||||
|
||||
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() {
|
||||
@ -288,11 +313,11 @@ void GrGLBlendEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect
|
||||
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);
|
||||
|
||||
|
@ -119,7 +119,8 @@ static void boxBlurY(const SkBitmap& src, SkBitmap* dst, int kernelSize,
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
@ -192,10 +193,11 @@ bool SkBlurImageFilter::onFilterImage(Proxy* proxy,
|
||||
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();
|
||||
|
@ -275,14 +275,19 @@ private:
|
||||
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();
|
||||
@ -308,7 +313,9 @@ bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src,
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -502,9 +502,10 @@ GrTexture* apply_morphology(GrTexture* srcTexture,
|
||||
|
||||
};
|
||||
|
||||
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();
|
||||
@ -515,9 +516,10 @@ bool SkDilateImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBi
|
||||
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();
|
||||
|
@ -19,7 +19,9 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkXfermodeImageFilter::SkXfermodeImageFilter(SkXfermode* mode, SkImageFilter* background, SkImageFilter* foreground)
|
||||
SkXfermodeImageFilter::SkXfermodeImageFilter(SkXfermode* mode,
|
||||
SkImageFilter* background,
|
||||
SkImageFilter* foreground)
|
||||
: INHERITED(background, foreground), fMode(mode) {
|
||||
SkSafeRef(fMode);
|
||||
}
|
||||
@ -46,10 +48,14 @@ bool SkXfermodeImageFilter::onFilterImage(Proxy* proxy,
|
||||
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());
|
||||
@ -59,20 +65,32 @@ bool SkXfermodeImageFilter::onFilterImage(Proxy* proxy,
|
||||
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();
|
||||
@ -96,23 +114,31 @@ bool SkXfermodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, Sk
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1377,7 +1377,7 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
|
||||
|
||||
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);
|
||||
|
||||
@ -1385,7 +1385,7 @@ static bool filter_texture(SkDevice* device, GrContext* context,
|
||||
// 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;
|
||||
}
|
||||
@ -1419,9 +1419,10 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
|
||||
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();
|
||||
@ -1435,8 +1436,10 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
|
||||
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,
|
||||
@ -1498,12 +1501,15 @@ void SkGpuDevice::drawDevice(const SkDraw& draw, SkDevice* device,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1542,7 +1548,7 @@ bool SkGpuDevice::filterImage(SkImageFilter* filter, const SkBitmap& src,
|
||||
// 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);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
Loading…
Reference in New Issue
Block a user