Change SkCanvas to *not* inherit from SkRefCnt

Definitely tricky for classes like SkNWayCanvas, where the caller (today)
need not pay attention to ownership of the canvases it gave the NWay
(after this CL, the caller *must* managed ownership)

BUG=skia:

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4441

DOCS_PREVIEW= https://skia.org/?cl=4441

Change-Id: Ib1ac07a3cdf0686d78e7aaa4735d45cc90bea081
Reviewed-on: https://skia-review.googlesource.com/4441
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 3bef299..b495520 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -1192,8 +1192,7 @@
 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
 Error NullSink::draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const {
-    std::unique_ptr<SkCanvas> canvas(SkCreateNullCanvas());
-    return src.draw(canvas.get());
+    return src.draw(SkMakeNullCanvas().get());
 }
 
 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
@@ -1356,7 +1355,7 @@
     if (!err.isEmpty()) {
         return err;
     }
-    sk_sp<SkCanvas> nullCanvas(SkCreateNullCanvas());
+    std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
     UrlDataManager dataManager(SkString("data"));
     Json::Value json = debugCanvas.toJSON(
             dataManager, debugCanvas.getSize(), nullCanvas.get());
@@ -1371,10 +1370,9 @@
 Error SVGSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
 #if defined(SK_XML)
     std::unique_ptr<SkXMLWriter> xmlWriter(new SkXMLStreamWriter(dst));
-    sk_sp<SkCanvas> canvas(SkSVGCanvas::Create(
-        SkRect::MakeWH(SkIntToScalar(src.size().width()), SkIntToScalar(src.size().height())),
-        xmlWriter.get()));
-    return src.draw(canvas.get());
+    return src.draw(SkSVGCanvas::Make(SkRect::MakeWH(SkIntToScalar(src.size().width()),
+                                                     SkIntToScalar(src.size().height())),
+                                      xmlWriter.get()).get());
 #else
     return Error("SVG sink is disabled.");
 #endif // SK_XML
diff --git a/gm/aaclip.cpp b/gm/aaclip.cpp
index dd83b7c..683f5ff 100644
--- a/gm/aaclip.cpp
+++ b/gm/aaclip.cpp
@@ -8,6 +8,7 @@
 #include "gm.h"
 #include "SkCanvas.h"
 #include "SkPath.h"
+#include "SkMakeUnique.h"
 
 static void do_draw(SkCanvas* canvas, const SkRect& r) {
     SkPaint paint;
@@ -166,14 +167,14 @@
 
 #ifdef SK_BUILD_FOR_MAC
 
-static SkCanvas* make_canvas(const SkBitmap& bm) {
+static std::unique_ptr<SkCanvas> make_canvas(const SkBitmap& bm) {
     const SkImageInfo& info = bm.info();
     if (info.bytesPerPixel() == 4) {
-        return SkCanvas::NewRasterDirectN32(info.width(), info.height(),
-                                            (SkPMColor*)bm.getPixels(),
-                                            bm.rowBytes());
+        return SkCanvas::MakeRasterDirectN32(info.width(), info.height(),
+                                             (SkPMColor*)bm.getPixels(),
+                                             bm.rowBytes());
     } else {
-        return new SkCanvas(bm);
+        return skstd::make_unique<SkCanvas>(bm);
     }
 }
 
@@ -182,7 +183,6 @@
     SkBitmap bm;
     bm.allocPixels(info);
 
-    sk_sp<SkCanvas> newc(make_canvas(bm));
     if (info.isOpaque()) {
         bm.eraseColor(SK_ColorGREEN);
     } else {
@@ -192,7 +192,7 @@
     SkPaint paint;
     paint.setAntiAlias(true);
     paint.setColor(SK_ColorBLUE);
-    newc->drawCircle(50, 50, 49, paint);
+    make_canvas(bm)->drawCircle(50, 50, 49, paint);
     canvas->drawBitmap(bm, 10, 10);
 
     CGImageRef image = SkCreateCGImageRefWithColorspace(bm, nullptr);
diff --git a/gn/android_framework_defines.gni b/gn/android_framework_defines.gni
index 12e3b11..90fea2f 100644
--- a/gn/android_framework_defines.gni
+++ b/gn/android_framework_defines.gni
@@ -12,6 +12,7 @@
   "SK_SUPPORT_LEGACY_GRADIENT_DITHERING",
   "SK_SUPPORT_LEGACY_DRAWFILTER",
   "SK_IGNORE_GPU_DITHER",
+  "SK_SUPPORT_LEGACY_CANVAS_IS_REFCNT",
   "SK_SUPPORT_LEGACY_CLIP_REGIONOPS",
   "SK_SUPPORT_LEGACY_SHADER_ISABITMAP",
 ]
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index ab47edd..ba8a383 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -60,7 +60,13 @@
     color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns),
     etc.
 */
-class SK_API SkCanvas : public SkRefCnt {
+class SK_API SkCanvas
+#ifdef SK_SUPPORT_LEGACY_CANVAS_IS_REFCNT
+: public SkRefCnt
+#else
+: SkNoncopyable
+#endif
+{
     enum PrivateSaveLayerFlags {
         kDontClipToLayer_PrivateSaveLayerFlag   = 1U << 31,
     };
@@ -100,11 +106,22 @@
      *  Note: it is valid to request a supported ImageInfo, but with zero
      *  dimensions.
      */
-    static SkCanvas* NewRasterDirect(const SkImageInfo&, void*, size_t);
+    static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo&, void*, size_t);
+
+    static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels,
+                                                         size_t rowBytes) {
+        return MakeRasterDirect(SkImageInfo::MakeN32Premul(width, height), pixels, rowBytes);
+    }
+
+#ifdef SK_SUPPORT_LEGACY_CANVAS_IS_REFCNT
+    static SkCanvas* NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
+        return MakeRasterDirect(info, pixels, rowBytes).release();
+    }
 
     static SkCanvas* NewRasterDirectN32(int width, int height, SkPMColor* pixels, size_t rowBytes) {
-        return NewRasterDirect(SkImageInfo::MakeN32Premul(width, height), pixels, rowBytes);
+        return MakeRasterDirectN32(width, height, pixels, rowBytes).release();
     }
+#endif
 
     /**
      *  Creates an empty canvas with no backing device/pixels, and zero
diff --git a/include/core/SkMultiPictureDraw.h b/include/core/SkMultiPictureDraw.h
index cd46a30..9995721 100644
--- a/include/core/SkMultiPictureDraw.h
+++ b/include/core/SkMultiPictureDraw.h
@@ -57,7 +57,7 @@
 
 private:
     struct DrawData {
-        SkCanvas*        fCanvas;  // reffed
+        SkCanvas*        fCanvas;
         const SkPicture* fPicture; // reffed
         SkMatrix         fMatrix;
         SkPaint*         fPaint;   // owned
diff --git a/include/core/SkPictureRecorder.h b/include/core/SkPictureRecorder.h
index 59e8f14..a440790 100644
--- a/include/core/SkPictureRecorder.h
+++ b/include/core/SkPictureRecorder.h
@@ -111,13 +111,13 @@
     friend class SkPictureRecorderReplayTester; // for unit testing
     void partialReplay(SkCanvas* canvas) const;
 
-    bool                   fActivelyRecording;
-    uint32_t               fFlags;
-    SkRect                 fCullRect;
-    sk_sp<SkBBoxHierarchy> fBBH;
-    sk_sp<SkRecorder>      fRecorder;
-    sk_sp<SkRecord>        fRecord;
-    SkMiniRecorder         fMiniRecorder;
+    bool                        fActivelyRecording;
+    uint32_t                    fFlags;
+    SkRect                      fCullRect;
+    sk_sp<SkBBoxHierarchy>      fBBH;
+    std::unique_ptr<SkRecorder> fRecorder;
+    sk_sp<SkRecord>             fRecord;
+    SkMiniRecorder              fMiniRecorder;
 
     typedef SkNoncopyable INHERITED;
 };
diff --git a/include/svg/SkSVGCanvas.h b/include/svg/SkSVGCanvas.h
index e285faa..b72f273 100644
--- a/include/svg/SkSVGCanvas.h
+++ b/include/svg/SkSVGCanvas.h
@@ -25,7 +25,13 @@
      *  The 'bounds' parameter defines an initial SVG viewport (viewBox attribute on the root
      *  SVG element).
      */
-    static SkCanvas* Create(const SkRect& bounds, SkXMLWriter*);
+    static std::unique_ptr<SkCanvas> Make(const SkRect& bounds, SkXMLWriter*);
+
+#ifdef SK_SUPPORT_LEGACY_CANVAS_IS_REFCNT
+    static SkCanvas* Create(const SkRect& bounds, SkXMLWriter* writer) {
+        return Make(bounds, writer).release();
+    }
+#endif
 };
 
 #endif
diff --git a/include/utils/SkCanvasStateUtils.h b/include/utils/SkCanvasStateUtils.h
index 3071c75..fbc3a6f 100644
--- a/include/utils/SkCanvasStateUtils.h
+++ b/include/utils/SkCanvasStateUtils.h
@@ -62,7 +62,12 @@
      *         identical to the captured canvas. The caller is responsible for
      *         calling unref on the SkCanvas.
      */
-    static SkCanvas* CreateFromCanvasState(const SkCanvasState* state);
+    static std::unique_ptr<SkCanvas> MakeFromCanvasState(const SkCanvasState* state);
+#ifdef SK_SUPPORT_LEGACY_CANVAS_IS_REFCNT
+    static SkCanvas* CreateFromCanvasState(const SkCanvasState* state) {
+        return MakeFromCanvasState(state).release();
+    }
+#endif
 
     /**
      * Free the memory associated with the captured canvas state.  The state
diff --git a/include/utils/SkNullCanvas.h b/include/utils/SkNullCanvas.h
index 99a26da..884b68b 100644
--- a/include/utils/SkNullCanvas.h
+++ b/include/utils/SkNullCanvas.h
@@ -15,6 +15,12 @@
 /**
  * Creates a canvas that draws nothing. This is useful for performance testing.
  */
-SK_API SkCanvas* SkCreateNullCanvas();
+SK_API std::unique_ptr<SkCanvas> SkMakeNullCanvas();
+
+#ifdef SK_SUPPORT_LEGACY_CANVAS_IS_REFCNT
+static inline SkCanvas* SkCreateNullCanvas() {
+    return SkMakeNullCanvas().release();
+}
+#endif
 
 #endif
diff --git a/public.bzl b/public.bzl
index de3d6f2..734aaaf 100644
--- a/public.bzl
+++ b/public.bzl
@@ -600,6 +600,7 @@
     "GOOGLE3",
     # Staging flags for API changes
     "SK_SUPPORT_LEGACY_ACCESSBITMAP",
+    "SK_SUPPORT_LEGACY_CANVAS_IS_REFCNT",
     "SK_SUPPORT_LEGACY_CLIP_REGIONOPS",
 ]
 
diff --git a/samplecode/SamplePathFuzz.cpp b/samplecode/SamplePathFuzz.cpp
index 05eb76f..b66b881 100644
--- a/samplecode/SamplePathFuzz.cpp
+++ b/samplecode/SamplePathFuzz.cpp
@@ -629,8 +629,8 @@
         const SkPath& path = fuzzPath.getPath();
         const SkPaint& paint = fuzzPath.getPaint();
         const SkImageInfo& info = bitmap->info();
-        SkCanvas* canvas(
-            SkCanvas::NewRasterDirect(info, bitmap->getPixels(), bitmap->rowBytes()));
+        std::unique_ptr<SkCanvas> canvas(
+            SkCanvas::MakeRasterDirect(info, bitmap->getPixels(), bitmap->rowBytes()));
         int w = info.width() / 4;
         int h = info.height() / 4;
         int x = localSeed / 4 % 4;
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index cd4dcbc..a8d73a9 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -19,6 +19,7 @@
 #include "SkImageFilter.h"
 #include "SkImageFilterCache.h"
 #include "SkLatticeIter.h"
+#include "SkMakeUnique.h"
 #include "SkMatrixUtils.h"
 #include "SkMetaData.h"
 #include "SkNx.h"
@@ -3323,7 +3324,8 @@
     return true;
 }
 
-SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
+std::unique_ptr<SkCanvas> SkCanvas::MakeRasterDirect(const SkImageInfo& info, void* pixels,
+                                                     size_t rowBytes) {
     if (!supported_for_raster_canvas(info)) {
         return nullptr;
     }
@@ -3332,7 +3334,7 @@
     if (!bitmap.installPixels(info, pixels, rowBytes)) {
         return nullptr;
     }
-    return new SkCanvas(bitmap);
+    return skstd::make_unique<SkCanvas>(bitmap);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkConfig8888.cpp b/src/core/SkConfig8888.cpp
index 639a444..fd945cf 100644
--- a/src/core/SkConfig8888.cpp
+++ b/src/core/SkConfig8888.cpp
@@ -354,8 +354,8 @@
         if (!bm.installPixels(srcInfo, const_cast<void*>(srcPixels), srcRB, ctable, nullptr, nullptr)) {
             return false;
         }
-        sk_sp<SkCanvas> canvas(SkCanvas::NewRasterDirect(dstInfo, dstPixels, dstRB));
-        if (nullptr == canvas.get()) {
+        std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(dstInfo, dstPixels, dstRB);
+        if (!canvas) {
             return false;
         }
 
diff --git a/src/core/SkMultiPictureDraw.cpp b/src/core/SkMultiPictureDraw.cpp
index b3c6368..1df27ff 100644
--- a/src/core/SkMultiPictureDraw.cpp
+++ b/src/core/SkMultiPictureDraw.cpp
@@ -18,7 +18,7 @@
 void SkMultiPictureDraw::DrawData::init(SkCanvas* canvas, const SkPicture* picture,
                                         const SkMatrix* matrix, const SkPaint* paint) {
     fPicture = SkRef(picture);
-    fCanvas = SkRef(canvas);
+    fCanvas = canvas;
     if (matrix) {
         fMatrix = *matrix;
     } else {
@@ -34,7 +34,6 @@
 void SkMultiPictureDraw::DrawData::Reset(SkTDArray<DrawData>& data) {
     for (int i = 0; i < data.count(); ++i) {
         data[i].fPicture->unref();
-        data[i].fCanvas->unref();
         delete data[i].fPaint;
     }
     data.rewind();
diff --git a/src/core/SkSpecialSurface.cpp b/src/core/SkSpecialSurface.cpp
index beba915..b490421 100644
--- a/src/core/SkSpecialSurface.cpp
+++ b/src/core/SkSpecialSurface.cpp
@@ -29,7 +29,7 @@
     virtual sk_sp<SkSpecialImage> onMakeImageSnapshot() = 0;
 
 protected:
-    sk_sp<SkCanvas> fCanvas;   // initialized by derived classes in ctors
+    std::unique_ptr<SkCanvas> fCanvas;   // initialized by derived classes in ctors
 
 private:
     typedef SkSpecialSurface INHERITED;
diff --git a/src/image/SkSurface.cpp b/src/image/SkSurface.cpp
index 38bab9e..3d6670f 100644
--- a/src/image/SkSurface.cpp
+++ b/src/image/SkSurface.cpp
@@ -58,14 +58,12 @@
 SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props)
     : INHERITED(width, height, props)
 {
-    fCachedCanvas = nullptr;
     fCachedImage = nullptr;
 }
 
 SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props)
     : INHERITED(info, props)
 {
-    fCachedCanvas = nullptr;
     fCachedImage = nullptr;
 }
 
@@ -76,7 +74,6 @@
     }
 
     SkSafeUnref(fCachedImage);
-    SkSafeUnref(fCachedCanvas);
 }
 
 void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
diff --git a/src/image/SkSurface_Base.h b/src/image/SkSurface_Base.h
index 8351bb8..a8c1d8f 100644
--- a/src/image/SkSurface_Base.h
+++ b/src/image/SkSurface_Base.h
@@ -89,8 +89,8 @@
     uint32_t newGenerationID();
 
 private:
-    SkCanvas*   fCachedCanvas;
-    SkImage*    fCachedImage;
+    std::unique_ptr<SkCanvas>   fCachedCanvas;
+    SkImage*                    fCachedImage;
 
     void aboutToDraw(ContentChangeMode mode);
 
@@ -106,12 +106,12 @@
 
 SkCanvas* SkSurface_Base::getCachedCanvas() {
     if (nullptr == fCachedCanvas) {
-        fCachedCanvas = this->onNewCanvas();
+        fCachedCanvas = std::unique_ptr<SkCanvas>(this->onNewCanvas());
         if (fCachedCanvas) {
             fCachedCanvas->setSurfaceBase(this);
         }
     }
-    return fCachedCanvas;
+    return fCachedCanvas.get();
 }
 
 sk_sp<SkImage> SkSurface_Base::refCachedImage(SkBudgeted budgeted, ForceUnique unique) {
diff --git a/src/pdf/SkPDFDocument.cpp b/src/pdf/SkPDFDocument.cpp
index ab5f465..92e82fc 100644
--- a/src/pdf/SkPDFDocument.cpp
+++ b/src/pdf/SkPDFDocument.cpp
@@ -217,7 +217,7 @@
             SkScalarRoundToInt(width), SkScalarRoundToInt(height));
     fPageDevice.reset(
             SkPDFDevice::Create(pageSize, fRasterDpi, this));
-    fCanvas = sk_make_sp<SkPDFCanvas>(fPageDevice);
+    fCanvas.reset(new SkPDFCanvas(fPageDevice));
     fCanvas->clipRect(trimBox);
     fCanvas->translate(trimBox.x(), trimBox.y());
     return fCanvas.get();
diff --git a/src/pdf/SkPDFDocument.h b/src/pdf/SkPDFDocument.h
index b62a7a5..15e1479 100644
--- a/src/pdf/SkPDFDocument.h
+++ b/src/pdf/SkPDFDocument.h
@@ -76,7 +76,7 @@
     SkTHashSet<SkPDFFont*> fFonts;
     sk_sp<SkPDFDict> fDests;
     sk_sp<SkPDFDevice> fPageDevice;
-    sk_sp<SkCanvas> fCanvas;
+    std::unique_ptr<SkCanvas> fCanvas;
     sk_sp<SkPDFObject> fID;
     sk_sp<SkPDFObject> fXMP;
     SkScalar fRasterDpi;
diff --git a/src/svg/SkSVGCanvas.cpp b/src/svg/SkSVGCanvas.cpp
index d3511c0..95a4625 100644
--- a/src/svg/SkSVGCanvas.cpp
+++ b/src/svg/SkSVGCanvas.cpp
@@ -7,11 +7,12 @@
 
 #include "SkSVGCanvas.h"
 #include "SkSVGDevice.h"
+#include "SkMakeUnique.h"
 
-SkCanvas* SkSVGCanvas::Create(const SkRect& bounds, SkXMLWriter* writer) {
+std::unique_ptr<SkCanvas> SkSVGCanvas::Make(const SkRect& bounds, SkXMLWriter* writer) {
     // TODO: pass full bounds to the device
     SkISize size = bounds.roundOut().size();
     sk_sp<SkBaseDevice> device(SkSVGDevice::Create(size, writer));
 
-    return new SkCanvas(device.get());
+    return skstd::make_unique<SkCanvas>(device.get());
 }
diff --git a/src/utils/SkCanvasStateUtils.cpp b/src/utils/SkCanvasStateUtils.cpp
index 062dc13..58f26b6 100644
--- a/src/utils/SkCanvasStateUtils.cpp
+++ b/src/utils/SkCanvasStateUtils.cpp
@@ -100,14 +100,12 @@
 public:
     static const int32_t kVersion = 1;
 
-    SkCanvasState_v1(SkCanvas* canvas)
-    : INHERITED(kVersion, canvas)
-    {
+    SkCanvasState_v1(SkCanvas* canvas) : INHERITED(kVersion, canvas) {
         layerCount = 0;
         layers = nullptr;
         mcState.clipRectCount = 0;
         mcState.clipRects = nullptr;
-        originalCanvas = SkRef(canvas);
+        originalCanvas = canvas;
     }
 
     ~SkCanvasState_v1() {
@@ -118,10 +116,6 @@
 
         sk_free(mcState.clipRects);
         sk_free(layers);
-
-        // it is now safe to free the canvas since there should be no remaining
-        // references to the content that is referenced by this canvas (e.g. pixels)
-        originalCanvas->unref();
     }
 
     SkMCState mcState;
@@ -284,7 +278,8 @@
     canvas->clipRegion(clip, SkCanvas::kReplace_Op);
 }
 
-static SkCanvas* create_canvas_from_canvas_layer(const SkCanvasLayerState& layerState) {
+static std::unique_ptr<SkCanvas>
+make_canvas_from_canvas_layer(const SkCanvasLayerState& layerState) {
     SkASSERT(kRaster_CanvasBackend == layerState.type);
 
     SkBitmap bitmap;
@@ -304,15 +299,15 @@
     SkASSERT(!bitmap.empty());
     SkASSERT(!bitmap.isNull());
 
-    sk_sp<SkCanvas> canvas(new SkCanvas(bitmap));
+    std::unique_ptr<SkCanvas> canvas(new SkCanvas(bitmap));
 
     // setup the matrix and clip
     setup_canvas_from_MC_state(layerState.mcState, canvas.get());
 
-    return canvas.release();
+    return canvas;
 }
 
-SkCanvas* SkCanvasStateUtils::CreateFromCanvasState(const SkCanvasState* state) {
+std::unique_ptr<SkCanvas> SkCanvasStateUtils::MakeFromCanvasState(const SkCanvasState* state) {
     SkASSERT(state);
     // Currently there is only one possible version.
     SkASSERT(SkCanvasState_v1::kVersion == state->version);
@@ -323,14 +318,14 @@
         return nullptr;
     }
 
-    sk_sp<SkCanvasStack> canvas(new SkCanvasStack(state->width, state->height));
+    std::unique_ptr<SkCanvasStack> canvas(new SkCanvasStack(state->width, state->height));
 
     // setup the matrix and clip on the n-way canvas
     setup_canvas_from_MC_state(state_v1->mcState, canvas.get());
 
     // Iterate over the layers and add them to the n-way canvas
     for (int i = state_v1->layerCount - 1; i >= 0; --i) {
-        sk_sp<SkCanvas> canvasLayer(create_canvas_from_canvas_layer(state_v1->layers[i]));
+        std::unique_ptr<SkCanvas> canvasLayer = make_canvas_from_canvas_layer(state_v1->layers[i]);
         if (!canvasLayer.get()) {
             return nullptr;
         }
@@ -338,7 +333,7 @@
                                                              state_v1->layers[i].y));
     }
 
-    return canvas.release();
+    return std::move(canvas);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/utils/SkLua.cpp b/src/utils/SkLua.cpp
index a223456..27127df 100644
--- a/src/utils/SkLua.cpp
+++ b/src/utils/SkLua.cpp
@@ -73,6 +73,13 @@
     lua_setmetatable(L, -2);
 }
 
+template <typename T> T* push_ptr(lua_State* L, T* ptr) {
+    *(T**)lua_newuserdata(L, sizeof(T*)) = ptr;
+    luaL_getmetatable(L, get_mtname<T>());
+    lua_setmetatable(L, -2);
+    return ptr;
+}
+
 template <typename T> T* push_ref(lua_State* L, T* ref) {
     *(T**)lua_newuserdata(L, sizeof(T*)) = SkSafeRef(ref);
     luaL_getmetatable(L, get_mtname<T>());
@@ -333,7 +340,7 @@
 }
 
 void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) {
-    push_ref(fL, canvas);
+    push_ptr(fL, canvas);
     CHECK_SETFIELD(key);
 }
 
@@ -715,7 +722,7 @@
 }
 
 static int lcanvas_gc(lua_State* L) {
-    get_ref<SkCanvas>(L, 1)->unref();
+    // don't know how to track a ptr...
     return 0;
 }
 
@@ -757,7 +764,7 @@
 
 static int ldocument_beginPage(lua_State* L) {
     const SkRect* contentPtr = nullptr;
-    push_ref(L, get_ref<SkDocument>(L, 1)->beginPage(lua2scalar(L, 2),
+    push_ptr(L, get_ref<SkDocument>(L, 1)->beginPage(lua2scalar(L, 2),
                                                      lua2scalar(L, 3),
                                                      contentPtr));
     return 1;
@@ -1750,7 +1757,7 @@
     if (nullptr == canvas) {
         lua_pushnil(L);
     } else {
-        push_ref(L, canvas);
+        push_ptr(L, canvas);
         // note: we don't unref canvas, since getCanvas did not ref it.
         // warning: this is weird: now Lua owns a ref on this canvas, but what if they let
         // the real owner (the surface) go away, but still hold onto the canvas?
@@ -1814,7 +1821,7 @@
         return 1;
     }
 
-    push_ref(L, canvas);
+    push_ptr(L, canvas);
     return 1;
 }
 
@@ -1824,7 +1831,7 @@
         lua_pushnil(L);
         return 1;
     }
-    push_ref(L, canvas);
+    push_ptr(L, canvas);
     return 1;
 }
 
diff --git a/src/utils/SkNWayCanvas.cpp b/src/utils/SkNWayCanvas.cpp
index b2d71d2..a910284 100644
--- a/src/utils/SkNWayCanvas.cpp
+++ b/src/utils/SkNWayCanvas.cpp
@@ -15,7 +15,6 @@
 
 void SkNWayCanvas::addCanvas(SkCanvas* canvas) {
     if (canvas) {
-        canvas->ref();
         *fList.append() = canvas;
     }
 }
@@ -23,13 +22,11 @@
 void SkNWayCanvas::removeCanvas(SkCanvas* canvas) {
     int index = fList.find(canvas);
     if (index >= 0) {
-        canvas->unref();
         fList.removeShuffle(index);
     }
 }
 
 void SkNWayCanvas::removeAll() {
-    fList.unrefAll();
     fList.reset();
 }
 
diff --git a/src/utils/SkNullCanvas.cpp b/src/utils/SkNullCanvas.cpp
index b5ee8d3..1f28706 100644
--- a/src/utils/SkNullCanvas.cpp
+++ b/src/utils/SkNullCanvas.cpp
@@ -9,10 +9,10 @@
 
 #include "SkCanvas.h"
 #include "SkNWayCanvas.h"
+#include "SkMakeUnique.h"
 
-
-SkCanvas* SkCreateNullCanvas() {
+std::unique_ptr<SkCanvas> SkMakeNullCanvas() {
     // An N-Way canvas forwards calls to N canvas's. When N == 0 it's
     // effectively a null canvas.
-    return new SkNWayCanvas(0, 0);
+    return std::unique_ptr<SkCanvas>(new SkNWayCanvas(0, 0));
 }
diff --git a/src/xps/SkDocument_XPS.cpp b/src/xps/SkDocument_XPS.cpp
index e333b5a..d05764a 100644
--- a/src/xps/SkDocument_XPS.cpp
+++ b/src/xps/SkDocument_XPS.cpp
@@ -58,7 +58,7 @@
 
 private:
     SkXPSDevice fDevice;
-    sk_sp<SkCanvas> fCanvas;
+    std::unique_ptr<SkCanvas> fCanvas;
     SkVector fUnitsPerMeter;
     SkVector fPixelsPerMeter;
 };
diff --git a/tests/CanvasStateHelpers.cpp b/tests/CanvasStateHelpers.cpp
index 801eaea..98b5d23 100644
--- a/tests/CanvasStateHelpers.cpp
+++ b/tests/CanvasStateHelpers.cpp
@@ -27,12 +27,11 @@
 
 extern "C" bool complex_layers_draw_from_canvas_state(SkCanvasState* state,
         float left, float top, float right, float bottom, int32_t spacer) {
-    SkCanvas* canvas = SkCanvasStateUtils::CreateFromCanvasState(state);
+    std::unique_ptr<SkCanvas> canvas = SkCanvasStateUtils::MakeFromCanvasState(state);
     if (!canvas) {
         return false;
     }
-    complex_layers_draw(canvas, left, top, right, bottom, spacer);
-    canvas->unref();
+    complex_layers_draw(canvas.get(), left, top, right, bottom, spacer);
     return true;
 }
 
@@ -52,7 +51,7 @@
 extern "C" bool complex_clips_draw_from_canvas_state(SkCanvasState* state,
         int32_t left, int32_t top, int32_t right, int32_t bottom, int32_t clipOp,
         int32_t regionRects, int32_t* rectCoords) {
-    SkCanvas* canvas = SkCanvasStateUtils::CreateFromCanvasState(state);
+    std::unique_ptr<SkCanvas> canvas = SkCanvasStateUtils::MakeFromCanvasState(state);
     if (!canvas) {
         return false;
     }
@@ -64,8 +63,7 @@
         rectCoords += 4;
     }
 
-    complex_clips_draw(canvas, left, top, right, bottom, clipOp, localRegion);
-    canvas->unref();
+    complex_clips_draw(canvas.get(), left, top, right, bottom, clipOp, localRegion);
     return true;
 }
 #endif // SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
diff --git a/tests/CanvasStateTest.cpp b/tests/CanvasStateTest.cpp
index 890e85d..2c7c590 100644
--- a/tests/CanvasStateTest.cpp
+++ b/tests/CanvasStateTest.cpp
@@ -278,13 +278,12 @@
 
     SkCanvasState* state = SkCanvasStateUtils::CaptureCanvasState(&canvas);
     REPORTER_ASSERT(reporter, state);
-    SkCanvas* tmpCanvas = SkCanvasStateUtils::CreateFromCanvasState(state);
+    std::unique_ptr<SkCanvas> tmpCanvas = SkCanvasStateUtils::MakeFromCanvasState(state);
     REPORTER_ASSERT(reporter, tmpCanvas);
 
     REPORTER_ASSERT(reporter, canvas.getDrawFilter());
     REPORTER_ASSERT(reporter, nullptr == tmpCanvas->getDrawFilter());
 
-    tmpCanvas->unref();
     SkCanvasStateUtils::ReleaseCanvasState(state);
 }
 
diff --git a/tests/CanvasTest.cpp b/tests/CanvasTest.cpp
index c062e6c..3f418db 100644
--- a/tests/CanvasTest.cpp
+++ b/tests/CanvasTest.cpp
@@ -542,7 +542,7 @@
     SkPMColor* baseAddr = storage.get();
     sk_bzero(baseAddr, size);
 
-    SkCanvas* canvas = SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes);
+    std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(info, baseAddr, minRowBytes);
     REPORTER_ASSERT(reporter, canvas);
 
     SkPixmap pmap;
@@ -556,25 +556,23 @@
         }
         addr = (const SkPMColor*)((const char*)addr + pmap.rowBytes());
     }
-    delete canvas;
 
     // now try a deliberately bad info
     info = info.makeWH(-1, info.height());
-    REPORTER_ASSERT(reporter, nullptr == SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes));
+    REPORTER_ASSERT(reporter, nullptr == SkCanvas::MakeRasterDirect(info, baseAddr, minRowBytes));
 
     // too big
     info = info.makeWH(1 << 30, 1 << 30);
-    REPORTER_ASSERT(reporter, nullptr == SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes));
+    REPORTER_ASSERT(reporter, nullptr == SkCanvas::MakeRasterDirect(info, baseAddr, minRowBytes));
 
     // not a valid pixel type
     info = SkImageInfo::Make(10, 10, kUnknown_SkColorType, info.alphaType());
-    REPORTER_ASSERT(reporter, nullptr == SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes));
+    REPORTER_ASSERT(reporter, nullptr == SkCanvas::MakeRasterDirect(info, baseAddr, minRowBytes));
 
     // We should succeed with a zero-sized valid info
     info = SkImageInfo::MakeN32Premul(0, 0);
-    canvas = SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes);
+    canvas = SkCanvas::MakeRasterDirect(info, baseAddr, minRowBytes);
     REPORTER_ASSERT(reporter, canvas);
-    delete canvas;
 }
 
 DEF_TEST(Canvas, reporter) {
diff --git a/tests/PipeTest.cpp b/tests/PipeTest.cpp
index 3b89441..e5d2f09 100644
--- a/tests/PipeTest.cpp
+++ b/tests/PipeTest.cpp
@@ -18,7 +18,7 @@
 #include "SkPictureRecorder.h"
 
 static void drain(SkPipeDeserializer* deserial, SkDynamicMemoryWStream* stream) {
-    std::unique_ptr<SkCanvas> canvas(SkCreateNullCanvas());
+    std::unique_ptr<SkCanvas> canvas = SkMakeNullCanvas();
     sk_sp<SkData> data = stream->detachAsData();
     deserial->playback(data->data(), data->size(), canvas.get());
 }
diff --git a/tests/SVGDeviceTest.cpp b/tests/SVGDeviceTest.cpp
index b010e57..715dbc7 100644
--- a/tests/SVGDeviceTest.cpp
+++ b/tests/SVGDeviceTest.cpp
@@ -91,7 +91,7 @@
 
     {
         SkXMLParserWriter writer(dom.beginParsing());
-        sk_sp<SkCanvas> svgCanvas(SkSVGCanvas::Create(SkRect::MakeWH(100, 100), &writer));
+        std::unique_ptr<SkCanvas> svgCanvas = SkSVGCanvas::Make(SkRect::MakeWH(100, 100), &writer);
         svgCanvas->drawText(txt, len, offset.x(), offset.y(), paint);
     }
     check_text_node(reporter, dom, dom.finishParsing(), offset, 0, expected);
@@ -103,7 +103,7 @@
         }
 
         SkXMLParserWriter writer(dom.beginParsing());
-        sk_sp<SkCanvas> svgCanvas(SkSVGCanvas::Create(SkRect::MakeWH(100, 100), &writer));
+        std::unique_ptr<SkCanvas> svgCanvas = SkSVGCanvas::Make(SkRect::MakeWH(100, 100), &writer);
         svgCanvas->drawPosTextH(txt, len, xpos, offset.y(), paint);
     }
     check_text_node(reporter, dom, dom.finishParsing(), offset, 1, expected);
@@ -115,7 +115,7 @@
         }
 
         SkXMLParserWriter writer(dom.beginParsing());
-        sk_sp<SkCanvas> svgCanvas(SkSVGCanvas::Create(SkRect::MakeWH(100, 100), &writer));
+        std::unique_ptr<SkCanvas> svgCanvas = SkSVGCanvas::Make(SkRect::MakeWH(100, 100), &writer);
         svgCanvas->drawPosText(txt, len, pos, paint);
     }
     check_text_node(reporter, dom, dom.finishParsing(), offset, 2, expected);
diff --git a/tools/lua/lua_pictures.cpp b/tools/lua/lua_pictures.cpp
index bd8fda1..639a522 100644
--- a/tools/lua/lua_pictures.cpp
+++ b/tools/lua/lua_pictures.cpp
@@ -145,7 +145,7 @@
 
             auto pic(load_picture(path));
             if (pic.get()) {
-                sk_sp<SkLuaCanvas> canvas(
+                std::unique_ptr<SkLuaCanvas> canvas(
                                     new SkLuaCanvas(SkScalarCeilToInt(pic->cullRect().width()),
                                                     SkScalarCeilToInt(pic->cullRect().height()),
                                                     L.get(), gAccumulateFunc));
diff --git a/tools/skiaserve/Request.h b/tools/skiaserve/Request.h
index 6b065a2..4058d7c 100644
--- a/tools/skiaserve/Request.h
+++ b/tools/skiaserve/Request.h
@@ -63,7 +63,7 @@
     SkColor getPixel(int x, int y);
 
     UploadContext* fUploadContext;
-    sk_sp<SkDebugCanvas> fDebugCanvas;
+    std::unique_ptr<SkDebugCanvas> fDebugCanvas;
     UrlDataManager fUrlDataManager;
 
 private:
diff --git a/tools/skp_parser.cpp b/tools/skp_parser.cpp
index d242524..887c50d 100644
--- a/tools/skp_parser.cpp
+++ b/tools/skp_parser.cpp
@@ -34,7 +34,7 @@
     SkISize size = pic->cullRect().roundOut().size();
     SkDebugCanvas debugCanvas(size.width(), size.height());
     pic->playback(&debugCanvas);
-    sk_sp<SkCanvas> nullCanvas(SkCreateNullCanvas());
+    std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
     UrlDataManager dataManager(SkString("data"));
     Json::Value json = debugCanvas.toJSON(
             dataManager, debugCanvas.getSize(), nullCanvas.get());