Revert of Revert of Revert of Revert of Change device creation to see the (optional...
authorreed <reed@chromium.org>
Sat, 14 Mar 2015 02:52:59 +0000 (19:52 -0700)
committerCommit bot <commit-bot@chromium.org>
Sat, 14 Mar 2015 02:52:59 +0000 (19:52 -0700)
Reason for revert:
chrome now has the new virtual, so trying again

Original issue's description:
> Revert of Revert of Revert of Change device creation to see the (optional) layer-paint (patchset #1 id:1 of https://codereview.chromium.org/1006923002/)
>
> Reason for revert:
> platform_canvas tests failures
>
> skia_unittests (with patch) skia_unittests (with patch) PlatformCanvas.TranslateLayer failed 2
> Flakiness dashboard
>
> failures:
> PlatformCanvas.TranslateLayer
> PlatformCanvas.FillLayer
>
> Original issue's description:
> > Revert of Revert of Change device creation to see the (optional) layer-paint (patchset #1 id:1 of https://codereview.chromium.org/1008863002/)
> >
> > Reason for revert:
> > guard in chrome has landed
> >
> > Original issue's description:
> > > Revert of Change device creation to see the (optional) layer-paint (patchset #9 id:160001 of https://codereview.chromium.org/988413003/)
> > >
> > > Reason for revert:
> > > need to have chrome opt-in for the older API before this can land (in chrome)
> > >
> > > Original issue's description:
> > > > Change device creation to see the (optional) layer-paint
> > > >
> > > > Motivation:
> > > >
> > > > PDFDevice currently relies on 1) being told that the layer's paint has an imagefilter, and in the case, it creates a rasterdevice. It then relies on (2) canvas itself sniffing the layer's paint and offering to apply-the-imagefilter to call drawSprite instead of drawDevice.
> > > >
> > > > This subtle interchange is fragile, and also does not support other unsupported PDF features like colorfilters. This CL is a step toward making this use-raster-instead-of-native approach to layers more completely in the subclass' hands.
> > > >
> > > > Committed: https://skia.googlesource.com/skia/+/1182d9a96b80bd12183ee7c81325a979a51ee0c0
> > >
> > > TBR=halcanary@google.com,senorblanco@google.com,robertphillips@google.com
> > > NOPRESUBMIT=true
> > > NOTREECHECKS=true
> > > NOTRY=true
> > >
> > > Committed: https://skia.googlesource.com/skia/+/0e040f7da2fdfeb49aa60d24117306e3b1e6ea90
> >
> > TBR=halcanary@google.com,senorblanco@google.com,robertphillips@google.com
> > NOPRESUBMIT=true
> > NOTREECHECKS=true
> > NOTRY=true
> >
> > Committed: https://skia.googlesource.com/skia/+/f7076a13e2d4269903b34ef2780e1c84723e4477
>
> TBR=halcanary@google.com,senorblanco@google.com,robertphillips@google.com
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
>
> Committed: https://skia.googlesource.com/skia/+/8e14d660b2a434bc708a70180c84210883611683

TBR=halcanary@google.com,senorblanco@google.com,robertphillips@google.com,reed@google.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true

Review URL: https://codereview.chromium.org/1005173004

14 files changed:
include/core/SkBitmapDevice.h
include/core/SkCanvas.h
include/core/SkDevice.h
include/device/xps/SkXPSDevice.h
src/core/SkBitmapDevice.cpp
src/core/SkCanvas.cpp
src/core/SkDevice.cpp
src/core/SkDeviceImageFilterProxy.h
src/device/xps/SkXPSDevice.cpp
src/gpu/SkGpuDevice.cpp
src/gpu/SkGpuDevice.h
src/pdf/SkPDFDevice.cpp
src/pdf/SkPDFDevice.h
src/utils/SkDeferredCanvas.cpp

index 8ca6a523be9d3b2412635616ff02f82fff6a11fa..caff6857da08341185884f89de13efa0e462d324 100644 (file)
@@ -98,11 +98,7 @@ protected:
                               const SkColor colors[], SkXfermode* xmode,
                               const uint16_t indices[], int indexCount,
                               const SkPaint& paint) SK_OVERRIDE;
-    /** The SkBaseDevice passed will be an SkBaseDevice which was returned by a call to
-        onCreateCompatibleDevice on this device with kSaveLayer_Usage.
-     */
-    virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
-                            const SkPaint&) SK_OVERRIDE;
+    virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, const SkPaint&) SK_OVERRIDE;
 
     ///////////////////////////////////////////////////////////////////////////
 
@@ -145,7 +141,7 @@ private:
     // any clip information.
     void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE;
 
-    SkBaseDevice* onCreateCompatibleDevice(const CreateInfo&) SK_OVERRIDE;
+    SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) SK_OVERRIDE;
 
     SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps&) SK_OVERRIDE;
     const void* peekPixels(SkImageInfo*, size_t* rowBytes) SK_OVERRIDE;
index 74bf909c2113b2af3028a23d8136dc74dc73d54c..836f7b1115797ee20e29cfe23702c986b09aa97b 100644 (file)
@@ -1321,8 +1321,7 @@ private:
     void internalDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
                                 const SkRect& dst, const SkPaint* paint);
     void internalDrawPaint(const SkPaint& paint);
-    void internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
-                           SaveFlags, bool justForImageFilter, SaveLayerStrategy strategy);
+    void internalSaveLayer(const SkRect* bounds, const SkPaint*, SaveFlags, SaveLayerStrategy);
     void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*);
 
     // shared by save() and saveLayer()
index c7c5c30b3a03fd19909db1d5ca2d861c9ffc278e..684a08404c02f036184fc38b7c7d866ece8cea42 100644 (file)
@@ -125,10 +125,9 @@ public:
     };
 
 protected:
-    enum Usage {
-       kGeneral_Usage,
-       kSaveLayer_Usage,  // <! internal use only
-       kImageFilter_Usage // <! internal use only
+    enum TileUsage {
+        kPossible_TileUsage,    //!< the created device may be drawn tiled
+        kNever_TileUsage,       //!< the created device will never be drawn tiled
     };
 
     struct TextFlags {
@@ -231,7 +230,7 @@ protected:
     virtual void drawPatch(const SkDraw&, const SkPoint cubics[12], const SkColor colors[4],
                            const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
     /** The SkDevice passed will be an SkDevice which was returned by a call to
-        onCreateCompatibleDevice on this device with kSaveLayer_Usage.
+        onCreateDevice on this device with kNeverTile_TileExpectation.
      */
     virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
                             const SkPaint&) = 0;
@@ -254,14 +253,6 @@ protected:
     virtual void lockPixels() {}
     virtual void unlockPixels() {}
 
-    /**
-     *  Returns true if the device allows processing of this imagefilter. If
-     *  false is returned, then the filter is ignored. This may happen for
-     *  some subclasses that do not support pixel manipulations after drawing
-     *  has occurred (e.g. printing). The default implementation returns true.
-     */
-    virtual bool allowImageFilter(const SkImageFilter*) { return true; }
-
     /**
      *  Override and return true for filters that the device can handle
      *  intrinsically. Doing so means that SkCanvas will pass-through this
@@ -336,24 +327,39 @@ protected:
                                           const SkPaint*);
 
     struct CreateInfo {
-        static SkPixelGeometry AdjustGeometry(const SkImageInfo&, Usage, SkPixelGeometry geo);
+        static SkPixelGeometry AdjustGeometry(const SkImageInfo&, TileUsage, SkPixelGeometry);
 
-        // The construct may change the pixel geometry based on usage as needed.
-        CreateInfo(const SkImageInfo& info, Usage usage, SkPixelGeometry geo)
+        // The constructor may change the pixel geometry based on other parameters.
+        CreateInfo(const SkImageInfo& info, TileUsage tileUsage, SkPixelGeometry geo)
             : fInfo(info)
-            , fUsage(usage)
-            , fPixelGeometry(AdjustGeometry(info, usage, geo))
+            , fTileUsage(tileUsage)
+            , fPixelGeometry(AdjustGeometry(info, tileUsage, geo))
         {}
 
-        const SkImageInfo     fInfo;
-        const Usage           fUsage;
-        const SkPixelGeometry fPixelGeometry;
+        const SkImageInfo       fInfo;
+        const TileUsage         fTileUsage;
+        const SkPixelGeometry   fPixelGeometry;
     };
 
+#ifdef SK_SUPPORT_LEGACY_ONCREATECOMPATIBLEDEVICE
+    // legacy method name -- please override onCreateDevice instead
     virtual SkBaseDevice* onCreateCompatibleDevice(const CreateInfo&) {
         return NULL;
     }
 
+    virtual SkBaseDevice* onCreateDevice(const CreateInfo& cinfo, const SkPaint* layerPaint) {
+        return this->onCreateCompatibleDevice(cinfo);
+    }
+#else
+    /**
+     *  Create a new device based on CreateInfo. If the paint is not null, then it represents a
+     *  preview of how the new device will be composed with its creator device (this).
+     */
+    virtual SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) {
+        return NULL;
+    }
+#endif
+
     virtual void initForRootLayer(SkPixelGeometry geo);
 
 private:
index 514259dbaa2921daae8cbf72be5d0eee22331f38..10dab8118322f212637fa7f1310accd6fe6293f5 100644 (file)
@@ -135,8 +135,6 @@ protected:
         int x, int y,
         const SkPaint& paint) SK_OVERRIDE;
 
-    bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE;
-
 private:
     class TypefaceUse : ::SkNoncopyable {
     public:
@@ -311,7 +309,7 @@ private:
         const SkVector& ppuScale,
         IXpsOMPath* shadedPath);
 
-    SkBaseDevice* onCreateCompatibleDevice(const CreateInfo&) SK_OVERRIDE;
+    SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) SK_OVERRIDE;
 
     // Disable the default copy and assign implementation.
     SkXPSDevice(const SkXPSDevice&);
index 37cbff50e2789dae0f36ca2cdd7df7a585213d35..5fae2b58625493a6191df64d6a45824ff058e79e 100644 (file)
@@ -110,7 +110,7 @@ void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) {
     fBitmap.lockPixels();
 }
 
-SkBaseDevice* SkBitmapDevice::onCreateCompatibleDevice(const CreateInfo& cinfo) {
+SkBaseDevice* SkBitmapDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint*) {
     SkDeviceProperties leaky(cinfo.fPixelGeometry);
     return SkBitmapDevice::Create(cinfo.fInfo, &leaky);
 }
index a31ded05864a9b436532e6320f09e8efc413cd7d..11dc739f4c4dc6aa0509f8ba404a56fa246817e4 100644 (file)
@@ -299,7 +299,7 @@ public:
             SkPaint tmp;
             tmp.setImageFilter(fOrigPaint.getImageFilter());
             (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag,
-                                            true, SkCanvas::kFullLayer_SaveLayerStrategy);
+                                            SkCanvas::kFullLayer_SaveLayerStrategy);
             // we'll clear the imageFilter for the actual draws in next(), so
             // it will only be applied during the restore().
             fDoClearImageFilter = true;
@@ -880,7 +880,7 @@ int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
     }
     SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
     fSaveCount += 1;
-    this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, false, strategy);
+    this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, strategy);
     return this->getSaveCount() - 1;
 }
 
@@ -890,12 +890,12 @@ int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags fl
     }
     SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
     fSaveCount += 1;
-    this->internalSaveLayer(bounds, paint, flags, false, strategy);
+    this->internalSaveLayer(bounds, paint, flags, strategy);
     return this->getSaveCount() - 1;
 }
 
 void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
-                                bool justForImageFilter, SaveLayerStrategy strategy) {
+                                 SaveLayerStrategy strategy) {
 #ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
     flags |= kClipToLayer_SaveFlag;
 #endif
@@ -917,21 +917,13 @@ void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav
         return;
     }
 
-    // Kill the imagefilter if our device doesn't allow it
-    SkLazyPaint lazyP;
-    if (paint && paint->getImageFilter()) {
-        if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) {
-            if (justForImageFilter) {
-                // early exit if the layer was just for the imageFilter
-                return;
-            }
-            SkPaint* p = lazyP.set(*paint);
-            p->setImageFilter(NULL);
-            paint = p;
+    bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
+    if (isOpaque && paint) {
+        // TODO: perhaps add a query to filters so we might preserve opaqueness...
+        if (paint->getImageFilter() || paint->getColorFilter()) {
+            isOpaque = false;
         }
     }
-
-    bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
     SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
                         isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
 
@@ -941,12 +933,17 @@ void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav
         return;
     }
 
-    SkBaseDevice::Usage usage = SkBaseDevice::kSaveLayer_Usage;
+    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::kImageFilter_Usage;
+        usage = SkBaseDevice::kPossible_TileUsage;
     }
-    device = device->onCreateCompatibleDevice(SkBaseDevice::CreateInfo(info, usage,
-                                                                       fProps.pixelGeometry()));
+#endif
+    device = device->onCreateDevice(SkBaseDevice::CreateInfo(info, usage, fProps.pixelGeometry()),
+                                    paint);
     if (NULL == device) {
         SkErrorInternals::SetError( kInternalError_SkError,
                                     "Unable to create device for layer.");
index a77e54c2ffd39f6755e40502f542bcb744add1a1..d76a1808628418246f183b51e6bd59b2acf4948e 100644 (file)
@@ -64,19 +64,16 @@ const SkBitmap& SkBaseDevice::accessBitmap(bool changePixels) {
 }
 
 SkPixelGeometry SkBaseDevice::CreateInfo::AdjustGeometry(const SkImageInfo& info,
-                                                         Usage usage,
+                                                         TileUsage tileUsage,
                                                          SkPixelGeometry geo) {
-    switch (usage) {
-        case kGeneral_Usage:
+    switch (tileUsage) {
+        case kPossible_TileUsage:
             break;
-        case kSaveLayer_Usage:
+        case kNever_TileUsage:
             if (info.alphaType() != kOpaque_SkAlphaType) {
                 geo = kUnknown_SkPixelGeometry;
             }
             break;
-        case kImageFilter_Usage:
-            geo = kUnknown_SkPixelGeometry;
-            break;
     }
     return geo;
 }
@@ -86,7 +83,7 @@ void SkBaseDevice::initForRootLayer(SkPixelGeometry geo) {
     // anyway to document logically what is going on.
     //
     fLeakyProperties->setPixelGeometry(CreateInfo::AdjustGeometry(this->imageInfo(),
-                                                                  kGeneral_Usage,
+                                                                  kPossible_TileUsage,
                                                                   geo));
 }
 
index 0ae686d877df4b81eb0b2c68bfe566a91d96af5c..11a95ff31fff0ed4feaa82e8124392569d89d681 100644 (file)
@@ -18,15 +18,15 @@ public:
         : fDevice(device)
         , fProps(props.flags(),
                  SkBaseDevice::CreateInfo::AdjustGeometry(SkImageInfo(),
-                                                          SkBaseDevice::kImageFilter_Usage,
+                                                          SkBaseDevice::kPossible_TileUsage,
                                                           props.pixelGeometry()))
     {}
 
     SkBaseDevice* createDevice(int w, int h) SK_OVERRIDE {
         SkBaseDevice::CreateInfo cinfo(SkImageInfo::MakeN32Premul(w, h),
-                                       SkBaseDevice::kImageFilter_Usage,
+                                       SkBaseDevice::kPossible_TileUsage,
                                        kUnknown_SkPixelGeometry);
-        return fDevice->onCreateCompatibleDevice(cinfo);
+        return fDevice->onCreateDevice(cinfo, NULL);
     }
     bool canHandleImageFilter(const SkImageFilter* filter) SK_OVERRIDE {
         return fDevice->canHandleImageFilter(filter);
index 2ca799ac370a633d011da3df51c838b9fb60740a..88d118252665403dfe6abbd238004a543a0aa2cb 100644 (file)
@@ -2251,7 +2251,7 @@ void SkXPSDevice::drawDevice(const SkDraw& d, SkBaseDevice* dev,
          "Could not add layer to current visuals.");
 }
 
-SkBaseDevice* SkXPSDevice::onCreateCompatibleDevice(const CreateInfo& info) {
+SkBaseDevice* SkXPSDevice::onCreateDevice(const CreateInfo& info, const SkPaint*) {
 //Conditional for bug compatibility with PDF device.
 #if 0
     if (SkBaseDevice::kGeneral_Usage == info.fUsage) {
@@ -2282,6 +2282,3 @@ SkXPSDevice::SkXPSDevice(IXpsOMObjectFactory* xpsFactory)
          "Could not create canvas for layer.");
 }
 
-bool SkXPSDevice::allowImageFilter(const SkImageFilter*) {
-    return false;
-}
index fb5fa7cc7a5f25004fbed7c69815a16ab300edff..757dfbf521e7d6f083e03de119d15d6148eeddae 100644 (file)
@@ -1862,7 +1862,7 @@ void SkGpuDevice::flush() {
 
 ///////////////////////////////////////////////////////////////////////////////
 
-SkBaseDevice* SkGpuDevice::onCreateCompatibleDevice(const CreateInfo& cinfo) {
+SkBaseDevice* SkGpuDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint*) {
     GrSurfaceDesc desc;
     desc.fConfig = fRenderTarget->config();
     desc.fFlags = kRenderTarget_GrSurfaceFlag;
@@ -1876,7 +1876,7 @@ SkBaseDevice* SkGpuDevice::onCreateCompatibleDevice(const CreateInfo& cinfo) {
 
     // layers are never draw in repeat modes, so we can request an approx
     // match and ignore any padding.
-    const GrContext::ScratchTexMatch match = (kSaveLayer_Usage == cinfo.fUsage) ?
+    const GrContext::ScratchTexMatch match = (kNever_TileUsage == cinfo.fTileUsage) ?
                                                 GrContext::kApprox_ScratchTexMatch :
                                                 GrContext::kExact_ScratchTexMatch;
     texture.reset(fContext->refScratchTexture(desc, match));
index 6b520e71742b2784ae4524e1dbaca598346decf0..50aa58685fbc384cc66fbc6d03adf3b9c16b3786 100644 (file)
@@ -51,9 +51,9 @@ public:
     virtual ~SkGpuDevice();
 
     SkGpuDevice* cloneDevice(const SkSurfaceProps& props) {
-        SkBaseDevice* dev = this->onCreateCompatibleDevice(CreateInfo(this->imageInfo(),
-                                                                      kGeneral_Usage,
-                                                                      props.pixelGeometry()));
+        SkBaseDevice* dev = this->onCreateDevice(CreateInfo(this->imageInfo(), kPossible_TileUsage,
+                                                            props.pixelGeometry()),
+                                                 NULL);
         return static_cast<SkGpuDevice*>(dev);
     }
 
@@ -147,7 +147,7 @@ private:
 
     SkGpuDevice(GrRenderTarget*, const SkSurfaceProps*, unsigned flags);
 
-    SkBaseDevice* onCreateCompatibleDevice(const CreateInfo&) SK_OVERRIDE;
+    SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) SK_OVERRIDE;
 
     SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps&) SK_OVERRIDE;
 
index 99f3ce1188d555dc2f797b128e8e66ef40a5f31a..273b958a8c6376e33d4aa151436a730a45b80b22 100644 (file)
@@ -566,13 +566,19 @@ void GraphicStackState::updateDrawingState(const GraphicStateEntry& state) {
     }
 }
 
-SkBaseDevice* SkPDFDevice::onCreateCompatibleDevice(const CreateInfo& cinfo) {
+static bool not_supported_for_layers(const SkPaint& layerPaint) {
     // PDF does not support image filters, so render them on CPU.
     // Note that this rendering is done at "screen" resolution (100dpi), not
     // printer resolution.
     // FIXME: It may be possible to express some filters natively using PDF
     // to improve quality and file size (http://skbug.com/3043)
-    if (kImageFilter_Usage == cinfo.fUsage) {
+
+    // TODO: should we return true if there is a colorfilter?
+    return layerPaint.getImageFilter() != NULL;
+}
+
+SkBaseDevice* SkPDFDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint* layerPaint) {
+    if (layerPaint && not_supported_for_layers(*layerPaint)) {
         return SkBitmapDevice::Create(cinfo.fInfo);
     }
     SkISize size = SkISize::Make(cinfo.fInfo.width(), cinfo.fInfo.height());
index 8a883140091740fa28bfea1a62804966263f0248..a90ea115c1b69951e0a48f9dd1e7961a1c5f6329 100644 (file)
@@ -235,8 +235,7 @@ private:
     ContentEntry* getLastContentEntry();
     void setLastContentEntry(ContentEntry* contentEntry);
 
-    // override from SkBaseDevice
-    SkBaseDevice* onCreateCompatibleDevice(const CreateInfo&) SK_OVERRIDE;
+    SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) SK_OVERRIDE;
 
     void init();
     void cleanUp(bool clearFontUsage);
index 8fe9f8a4b59e5651fa3f057b42978fd9ef220fca..647105d757238ed5a6998795fdae314c9a9a74e8 100644 (file)
@@ -162,7 +162,7 @@ public:
 
     GrRenderTarget* accessRenderTarget() SK_OVERRIDE;
 
-    SkBaseDevice* onCreateCompatibleDevice(const CreateInfo&) SK_OVERRIDE;
+    SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) SK_OVERRIDE;
 
     SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps&) SK_OVERRIDE;
 
@@ -231,9 +231,6 @@ protected:
     void lockPixels() SK_OVERRIDE {}
     void unlockPixels() SK_OVERRIDE {}
 
-    bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE {
-        return false;
-    }
     bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE {
         return false;
     }
@@ -461,16 +458,13 @@ const SkBitmap& SkDeferredDevice::onAccessBitmap() {
     return immediateDevice()->accessBitmap(false);
 }
 
-SkBaseDevice* SkDeferredDevice::onCreateCompatibleDevice(const CreateInfo& cinfo) {
-    // Save layer usage not supported, and not required by SkDeferredCanvas.
-    SkASSERT(cinfo.fUsage != kSaveLayer_Usage);
-
+SkBaseDevice* SkDeferredDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint* layerPaint) {
     // Create a compatible non-deferred device.
     // We do not create a deferred device because we know the new device
     // will not be used with a deferred canvas (there is no API for that).
     // And connecting a SkDeferredDevice to non-deferred canvas can result
     // in unpredictable behavior.
-    return immediateDevice()->onCreateCompatibleDevice(cinfo);
+    return immediateDevice()->onCreateDevice(cinfo, layerPaint);
 }
 
 SkSurface* SkDeferredDevice::newSurface(const SkImageInfo& info, const SkSurfaceProps& props) {