Apply matrix early in draw bitmap
authorcommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 24 Oct 2013 01:46:11 +0000 (01:46 +0000)
committercommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 24 Oct 2013 01:46:11 +0000 (01:46 +0000)
Committed: http://code.google.com/p/skia/source/detail?r=11930

Reverted: https://code.google.com/p/skia/source/detail?r=11932

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@11933 2bbb7eff-a529-9590-31e7-b0007b416f81

expectations/gm/ignored-tests.txt
gm/imagefiltersgraph.cpp
include/gpu/SkGpuDevice.h
src/core/SkImageFilterUtils.cpp
src/gpu/SkGpuDevice.cpp

index 561ac6b4749c3d6aa2d00705a393216a857ee37c..2c38df0438c7800e3324f9a7cb718feb354985a2 100644 (file)
@@ -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
index 363a4147e9c2e1f18858d128a1e37b107ef0f273..98f82f534069df79e4d13f97a7ef818d4168d5f0 100644 (file)
@@ -7,22 +7,88 @@
 
 #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 "SkOnce.h"
 #include "SkXfermodeImageFilter.h"
 
 #include "SkTestImageFilters.h"
 
 ///////////////////////////////////////////////////////////////////////////////
 
+namespace {
+// 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;
+};
+}
+
+static void init_flattenable(int*) {
+    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SimpleOffsetFilter)
+}
+
 class ImageFiltersGraphGM : public skiagm::GM {
 public:
-    ImageFiltersGraphGM() : fInitialized(false) {}
+    ImageFiltersGraphGM() : fInitialized(false) {
+        int dummy;
+        SK_DECLARE_STATIC_ONCE(once);
+        SkOnce(&once, init_flattenable, &dummy);
+    }
 
 protected:
     virtual SkString onShortName() {
@@ -43,7 +109,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 +147,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:
index 5d669e40fd379768281c84bbb40b8bc84182d6a2..debfd37170b65790db9f9e15170e2aef317c5ce4 100644 (file)
@@ -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);
index a4ce51eb9101f2ceb336738d7c48220bab1e47af..8385fb446ae0726ade2ccfbad3250239e6209211 100644 (file)
@@ -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);
             }
index 47ddd521cb8fd01b3a6cde8e808516eba9a3a52f..6617989848771e231c7141dd16c4b458b3adad05 100644 (file)
@@ -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,