aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-10-23 21:06:51 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-10-23 21:06:51 +0000
commit25e5a20e656a3d895753b61be3fc3645039c57ab (patch)
treedcd03d0328dc1a65b29048c4a4448a53d229c5ff
parente66d37606753f856492355a3bd6afe9a455e81ab (diff)
Apply matrix early in draw bitmap
R=robertphillips@google.com, senorblanco@chromium.org Author: bsalomon@google.com Review URL: https://codereview.chromium.org/30593003 git-svn-id: http://skia.googlecode.com/svn/trunk@11930 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--expectations/gm/ignored-tests.txt2
-rw-r--r--gm/imagefiltersgraph.cpp73
-rw-r--r--include/gpu/SkGpuDevice.h2
-rw-r--r--src/core/SkImageFilterUtils.cpp9
-rw-r--r--src/gpu/SkGpuDevice.cpp35
5 files changed, 97 insertions, 24 deletions
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt
index 561ac6b474..2c38df0438 100644
--- a/expectations/gm/ignored-tests.txt
+++ b/expectations/gm/ignored-tests.txt
@@ -31,3 +31,5 @@
# ('Poppler random failures'): ignore any Poppler failures, for now
pdf-poppler
+# Added by bsalomon, test case added in https://codereview.chromium.org/30593003
+imagefiltersgraph \ No newline at end of file
diff --git a/gm/imagefiltersgraph.cpp b/gm/imagefiltersgraph.cpp
index 363a4147e9..0b88b93fde 100644
--- a/gm/imagefiltersgraph.cpp
+++ b/gm/imagefiltersgraph.cpp
@@ -7,11 +7,13 @@
#include "gm.h"
+#include "SkArithmeticMode.h"
#include "SkBitmapSource.h"
#include "SkBlurImageFilter.h"
#include "SkColorFilter.h"
#include "SkColorMatrixFilter.h"
#include "SkColorFilterImageFilter.h"
+#include "SkFlattenableBuffers.h"
#include "SkMergeImageFilter.h"
#include "SkMorphologyImageFilter.h"
#include "SkXfermodeImageFilter.h"
@@ -20,6 +22,59 @@
///////////////////////////////////////////////////////////////////////////////
+// More closely models how Blink's OffsetFilter works as of 10/23/13. SkOffsetImageFilter doesn't
+// perform a draw and this one does.
+class SimpleOffsetFilter : public SkImageFilter {
+public:
+ SimpleOffsetFilter(SkScalar dx, SkScalar dy, SkImageFilter* input)
+ : SkImageFilter(input), fDX(dx), fDY(dy) {}
+
+ virtual bool onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
+ SkBitmap* dst, SkIPoint* offset) SK_OVERRIDE {
+ SkBitmap source = src;
+ SkImageFilter* input = getInput(0);
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (NULL != input && !input->filterImage(proxy, src, ctm, &source, &srcOffset)) {
+ return false;
+ }
+
+ SkIRect bounds;
+ source.getBounds(&bounds);
+
+ if (!this->applyCropRect(&bounds, ctm)) {
+ return false;
+ }
+
+ SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
+ SkCanvas canvas(device);
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ canvas.drawBitmap(source, fDX - bounds.left(), fDY - bounds.top(), &paint);
+ *dst = device->accessBitmap(false);
+ offset->fX += bounds.left();
+ offset->fY += bounds.top();
+ return true;
+ }
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SimpleOffsetFilter);
+
+protected:
+ explicit SimpleOffsetFilter(SkFlattenableReadBuffer& buffer)
+ : SkImageFilter(buffer) {
+ fDX = buffer.readScalar();
+ fDY = buffer.readScalar();
+ }
+
+ virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
+ this->SkImageFilter::flatten(buffer);
+ buffer.writeScalar(fDX);
+ buffer.writeScalar(fDY);
+ }
+
+private:
+ SkScalar fDX, fDY;
+};
+
class ImageFiltersGraphGM : public skiagm::GM {
public:
ImageFiltersGraphGM() : fInitialized(false) {}
@@ -43,7 +98,7 @@ protected:
canvas.drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint);
}
- virtual SkISize onISize() { return SkISize::Make(200, 100); }
+ virtual SkISize onISize() { return SkISize::Make(500, 150); }
virtual void onDraw(SkCanvas* canvas) {
if (!fInitialized) {
@@ -81,6 +136,22 @@ protected:
paint.setImageFilter(blendColor);
canvas->drawBitmap(fBitmap, 100, 0, &paint);
}
+ {
+ SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
+ 0, SK_Scalar1, 0, 0, 0,
+ 0, 0, SK_Scalar1, 0, 0,
+ 0, 0, 0, SkFloatToScalar(0.5f), 0 };
+ SkColorMatrixFilter matrixCF(matrix);
+ SkAutoTUnref<SkImageFilter> matrixFilter(SkColorFilterImageFilter::Create(&matrixCF));
+ SimpleOffsetFilter offsetFilter(SkIntToScalar(10), SkIntToScalar(10), matrixFilter);
+
+ SkAutoTUnref<SkXfermode> arith(SkArithmeticMode::Create(0, SK_Scalar1, SK_Scalar1, 0));
+ SkXfermodeImageFilter arithFilter(arith, matrixFilter, &offsetFilter);
+
+ SkPaint paint;
+ paint.setImageFilter(&arithFilter);
+ canvas->drawSprite(fBitmap, 200, 0, &paint);
+ }
}
private:
diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h
index 5d669e40fd..debfd37170 100644
--- a/include/gpu/SkGpuDevice.h
+++ b/include/gpu/SkGpuDevice.h
@@ -191,13 +191,11 @@ private:
const SkRect* srcRectPtr) const;
void internalDrawBitmap(const SkBitmap&,
const SkRect&,
- const SkMatrix&,
const GrTextureParams& params,
const SkPaint& paint,
SkCanvas::DrawBitmapRectFlags flags);
void drawTiledBitmap(const SkBitmap& bitmap,
const SkRect& srcRect,
- const SkMatrix& m,
const GrTextureParams& params,
const SkPaint& paint,
SkCanvas::DrawBitmapRectFlags flags);
diff --git a/src/core/SkImageFilterUtils.cpp b/src/core/SkImageFilterUtils.cpp
index a4ce51eb91..8385fb446a 100644
--- a/src/core/SkImageFilterUtils.cpp
+++ b/src/core/SkImageFilterUtils.cpp
@@ -23,6 +23,11 @@ bool SkImageFilterUtils::WrapTexture(GrTexture* texture, int width, int height,
bool SkImageFilterUtils::GetInputResultGPU(SkImageFilter* filter, SkImageFilter::Proxy* proxy,
const SkBitmap& src, const SkMatrix& ctm,
SkBitmap* result, SkIPoint* offset) {
+ // Ensure that GrContext calls under filterImage and filterImageGPU below will see an identity
+ // matrix with no clip and that the matrix, clip, and render target set before this function was
+ // called are restored before we return to the caller.
+ GrContext* context = src.getTexture()->getContext();
+ GrContext::AutoWideOpenIdentityDraw awoid(context, NULL);
if (!filter) {
*result = src;
return true;
@@ -31,9 +36,7 @@ bool SkImageFilterUtils::GetInputResultGPU(SkImageFilter* filter, SkImageFilter:
} else {
if (filter->filterImage(proxy, src, ctm, result, offset)) {
if (!result->getTexture()) {
- GrContext* context = ((GrTexture *) src.getTexture())->getContext();
- GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context,
- *result, NULL);
+ GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context, *result, NULL);
result->setPixelRef(new SkGrPixelRef(resultTex))->unref();
GrUnlockAndUnrefCachedBitmapTexture(resultTex);
}
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 47ddd521cb..6617989848 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1164,6 +1164,8 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
return;
}
+ fContext->concatMatrix(m);
+
GrTextureParams params;
SkPaint::FilterLevel paintFilterLevel = paint.getFilterLevel();
GrTextureParams::FilterMode textureFilterMode;
@@ -1195,9 +1197,9 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
if (!this->shouldTileBitmap(bitmap, params, srcRectPtr)) {
// take the simple case
- this->internalDrawBitmap(bitmap, srcRect, m, params, paint, flags);
+ this->internalDrawBitmap(bitmap, srcRect, params, paint, flags);
} else {
- this->drawTiledBitmap(bitmap, srcRect, m, params, paint, flags);
+ this->drawTiledBitmap(bitmap, srcRect, params, paint, flags);
}
}
@@ -1205,7 +1207,6 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
// been determined to be too large to fit in VRAM
void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
const SkRect& srcRect,
- const SkMatrix& m,
const GrTextureParams& params,
const SkPaint& paint,
SkCanvas::DrawBitmapRectFlags flags) {
@@ -1226,9 +1227,8 @@ void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
if (!fContext->getClip()->fClipStack->intersectRectWithClip(&clipRect)) {
return;
}
- SkMatrix matrix, inverse;
- matrix.setConcat(fContext->getMatrix(), m);
- if (!matrix.invert(&inverse)) {
+ SkMatrix inverse;
+ if (!fContext->getMatrix().invert(&inverse)) {
return;
}
inverse.mapRect(&clipRect);
@@ -1278,10 +1278,11 @@ void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
if (bitmap.extractSubset(&tmpB, iTileR)) {
// now offset it to make it "local" to our tmp bitmap
tileR.offset(-offset.fX, -offset.fY);
- SkMatrix tmpM(m);
- tmpM.preTranslate(offset.fX, offset.fY);
-
- this->internalDrawBitmap(tmpB, tileR, tmpM, params, paint, flags);
+ SkMatrix tmpM;
+ tmpM.setTranslate(offset.fX, offset.fY);
+ GrContext::AutoMatrix am;
+ am.setPreConcat(fContext, tmpM);
+ this->internalDrawBitmap(tmpB, tileR, params, paint, flags);
}
}
}
@@ -1338,7 +1339,6 @@ static bool may_color_bleed(const SkRect& srcRect,
*/
void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
const SkRect& srcRect,
- const SkMatrix& m,
const GrTextureParams& params,
const SkPaint& paint,
SkCanvas::DrawBitmapRectFlags flags) {
@@ -1366,19 +1366,18 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
// Need texture domain if drawing a sub rect.
needsTextureDomain = srcRect.width() < bitmap.width() ||
srcRect.height() < bitmap.height();
- if (needsTextureDomain && m.rectStaysRect() && fContext->getMatrix().rectStaysRect()) {
+ if (needsTextureDomain && fContext->getMatrix().rectStaysRect()) {
+ const SkMatrix& matrix = fContext->getMatrix();
// sampling is axis-aligned
SkRect transformedRect;
- SkMatrix srcToDeviceMatrix(m);
- srcToDeviceMatrix.postConcat(fContext->getMatrix());
- srcToDeviceMatrix.mapRect(&transformedRect, srcRect);
-
+ matrix.mapRect(&transformedRect, srcRect);
+
if (has_aligned_samples(srcRect, transformedRect)) {
// We could also turn off filtering here (but we already did a cache lookup with
// params).
needsTextureDomain = false;
} else {
- needsTextureDomain = may_color_bleed(srcRect, transformedRect, m);
+ needsTextureDomain = may_color_bleed(srcRect, transformedRect, matrix);
}
}
}
@@ -1421,7 +1420,7 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
return;
}
- fContext->drawRectToRect(grPaint, dstRect, paintRect, &m);
+ fContext->drawRectToRect(grPaint, dstRect, paintRect, NULL);
}
static bool filter_texture(SkBaseDevice* device, GrContext* context,