More SkVertices implementation work

- change virtuals to take const SkVertices*, as we do for TextBobs and Images
- override onDrawVerticesObject in recording canvases
- deserialize raw-vertices into SkVertices object

Possibly a follow-on would intercept the raw-form directly in canvas,
and remove the virtual, and only support the object form.

BUG=skia:6366

Change-Id: I57a932667ccb3b3b004beb802ac3ae6898e3c6e0
Reviewed-on: https://skia-review.googlesource.com/9633
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index 81841ba..85531bb 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -1186,9 +1186,9 @@
                     shader. In this case the colors are combined with the texture
                     using mode, before being drawn using the paint.
         @param paint Specifies the shader/texture if present.
-        @param flags Allows the caller to ignore colors or texs on vertices.
      */
-    void drawVertices(sk_sp<SkVertices> vertices, SkBlendMode mode, const SkPaint& paint);
+    void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint);
+    void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint);
 
     /**
      Draw a cubic coons patch
@@ -1445,12 +1445,10 @@
     virtual void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[],
                                 const SkPoint texs[], const SkColor colors[], SkBlendMode,
                                 const uint16_t indices[], int indexCount, const SkPaint&);
-    virtual void onDrawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode mode,
-                                      const SkPaint& paint, uint32_t flags);
+    virtual void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&);
     // Subclasses can use this put the vertices object call on the regular draw vertices code path.
     // This is temporary until we teach recording and other SkCanvas classes about SkVertices.
-    void onDrawVerticesObjectFallback(sk_sp<SkVertices> vertices, SkBlendMode mode,
-                                      const SkPaint& paint, uint32_t flags);
+    void devolveSkVerticesToRaw(const SkVertices*, SkBlendMode, const SkPaint&);
 
     virtual void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
                              int count, SkBlendMode, const SkRect* cull, const SkPaint*);
diff --git a/include/private/SkRecords.h b/include/private/SkRecords.h
index b81bca8..ac492ec 100644
--- a/include/private/SkRecords.h
+++ b/include/private/SkRecords.h
@@ -21,6 +21,7 @@
 #include "SkRSXform.h"
 #include "SkString.h"
 #include "SkTextBlob.h"
+#include "SkVertices.h"
 
 // Windows.h, will pull in all of the GDI defines.  GDI #defines
 // DrawText to DrawTextA or DrawTextW, but SkRecord has a struct
@@ -345,14 +346,8 @@
         Optional<SkRect> cull);
 RECORD(DrawVertices, kDraw_Tag|kHasPaint_Tag,
         SkPaint paint;
-        SkCanvas::VertexMode vmode;
-        int vertexCount;
-        PODArray<SkPoint> vertices;
-        PODArray<SkPoint> texs;
-        PODArray<SkColor> colors;
-        SkBlendMode bmode;
-        PODArray<uint16_t> indices;
-        int indexCount);
+        sk_sp<SkVertices> vertices;
+        SkBlendMode bmode);
 RECORD(DrawAnnotation, 0,  // TODO: kDraw_Tag, skia:5548
        SkRect rect;
        SkString key;
diff --git a/include/utils/SkDumpCanvas.h b/include/utils/SkDumpCanvas.h
index 79a49bc..19e5da5 100644
--- a/include/utils/SkDumpCanvas.h
+++ b/include/utils/SkDumpCanvas.h
@@ -117,9 +117,9 @@
                         const SkColor colors[], SkBlendMode,
                         const uint16_t indices[], int indexCount,
                         const SkPaint&) override;
-    void onDrawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode mode, const SkPaint& paint,
-                              uint32_t flags) override {
-        this->onDrawVerticesObjectFallback(std::move(vertices), mode, paint, flags);
+    void onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
+                              const SkPaint& paint) override {
+        this->devolveSkVerticesToRaw(vertices, mode, paint);
     }
 
     void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;
diff --git a/include/utils/SkLuaCanvas.h b/include/utils/SkLuaCanvas.h
index ce37413..a11d72f 100644
--- a/include/utils/SkLuaCanvas.h
+++ b/include/utils/SkLuaCanvas.h
@@ -63,9 +63,9 @@
                         const SkColor colors[], SkBlendMode,
                         const uint16_t indices[], int indexCount,
                         const SkPaint&) override;
-    void onDrawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode mode, const SkPaint& paint,
-                              uint32_t flags) override {
-        this->onDrawVerticesObjectFallback(std::move(vertices), mode, paint, flags);
+    void onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
+                              const SkPaint& paint) override {
+        this->devolveSkVerticesToRaw(vertices, mode, paint);
     }
 
     void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;
diff --git a/include/utils/SkNoDrawCanvas.h b/include/utils/SkNoDrawCanvas.h
index 14b8554..75c15b2 100644
--- a/include/utils/SkNoDrawCanvas.h
+++ b/include/utils/SkNoDrawCanvas.h
@@ -68,10 +68,7 @@
                              const SkPaint*) override {}
     void onDrawVertices(VertexMode, int, const SkPoint[], const SkPoint[], const SkColor[],
                         SkBlendMode, const uint16_t[], int, const SkPaint&) override {}
-    void onDrawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode mode, const SkPaint& paint,
-                              uint32_t flags) override {
-        this->onDrawVerticesObjectFallback(std::move(vertices), mode, paint, flags);
-    }
+    void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override {}
     void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
                      int, SkBlendMode, const SkRect*, const SkPaint*) override {}
 
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 23aed12..ccdb71b 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1799,10 +1799,15 @@
                          indexCount, paint);
 }
 
-void SkCanvas::drawVertices(sk_sp<SkVertices> vertices, SkBlendMode mode, const SkPaint& paint) {
+void SkCanvas::drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode,
+                            const SkPaint& paint) {
     RETURN_ON_NULL(vertices);
-    uint32_t deprecatedFlags = 0;
-    this->onDrawVerticesObject(std::move(vertices), mode, paint, deprecatedFlags);
+    this->onDrawVerticesObject(vertices.get(), mode, paint);
+}
+
+void SkCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) {
+    RETURN_ON_NULL(vertices);
+    this->onDrawVerticesObject(vertices, mode, paint);
 }
 
 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
@@ -2671,24 +2676,24 @@
     LOOPER_END
 }
 
-void SkCanvas::onDrawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode bmode,
-                                    const SkPaint& paint, uint32_t flags) {
+void SkCanvas::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
+                                    const SkPaint& paint) {
     TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
 
     while (iter.next()) {
         // In the common case of one iteration we could std::move vertices here.
-        iter.fDevice->drawVerticesObject(vertices, bmode, looper.paint(), flags);
+        iter.fDevice->drawVerticesObject(vertices, bmode, looper.paint());
     }
 
     LOOPER_END
 }
 
-void SkCanvas::onDrawVerticesObjectFallback(sk_sp<SkVertices> vertices, SkBlendMode mode,
-                                            const SkPaint& paint, uint32_t deprecatedFlags) {
+void SkCanvas::devolveSkVerticesToRaw(const SkVertices* vertices, SkBlendMode mode,
+                                      const SkPaint& paint) {
     this->onDrawVertices(vertices->mode(), vertices->vertexCount(), vertices->positions(),
-                         vertices->texCoords(), vertices->colors(), mode, vertices->indices(),
-                         vertices->indexCount(), paint);
+                         vertices->texCoords(), vertices->colors(), mode,
+                         vertices->indices(), vertices->indexCount(), paint);
 }
 
 void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index eb507d4..44c9dfb 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -276,8 +276,8 @@
     }
 }
 
-void SkBaseDevice::drawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode mode,
-                                      const SkPaint& paint, uint32_t deprecatedFlags) {
+void SkBaseDevice::drawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
+                                      const SkPaint& paint) {
     this->drawVertices(vertices->mode(), vertices->vertexCount(), vertices->positions(),
                        vertices->texCoords(), vertices->colors(), mode, vertices->indices(),
                        vertices->indexCount(), paint);
diff --git a/src/core/SkDevice.h b/src/core/SkDevice.h
index a8a68b6..6267b44 100644
--- a/src/core/SkDevice.h
+++ b/src/core/SkDevice.h
@@ -238,8 +238,7 @@
                               const SkColor colors[], SkBlendMode,
                               const uint16_t indices[], int indexCount,
                               const SkPaint& paint) = 0;
-    virtual void drawVerticesObject(sk_sp<SkVertices>, SkBlendMode, const SkPaint&,
-                                    uint32_t flags);
+    virtual void drawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&);
     // default implementation unrolls the blob runs.
     virtual void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y,
                               const SkPaint& paint, SkDrawFilter* drawFilter);
diff --git a/src/core/SkLiteDL.cpp b/src/core/SkLiteDL.cpp
index b990c70..2da6eb5 100644
--- a/src/core/SkLiteDL.cpp
+++ b/src/core/SkLiteDL.cpp
@@ -15,6 +15,7 @@
 #include "SkRegion.h"
 #include "SkRSXform.h"
 #include "SkTextBlob.h"
+#include "SkVertices.h"
 
 #ifndef SKLITEDL_PAGE
     #define SKLITEDL_PAGE 4096
@@ -54,7 +55,7 @@
     M(DrawImage) M(DrawImageNine) M(DrawImageRect) M(DrawImageLattice)          \
     M(DrawText) M(DrawPosText) M(DrawPosTextH)                                  \
     M(DrawTextOnPath) M(DrawTextRSXform) M(DrawTextBlob)                        \
-    M(DrawPatch) M(DrawPoints) M(DrawVertices) M(DrawAtlas)
+    M(DrawPatch) M(DrawPoints) M(DrawVertices) M(DrawVerticesObject) M(DrawAtlas)
 
 #define M(T) T,
     enum class Type : uint8_t { TYPES(M) };
@@ -502,6 +503,17 @@
                             indices, nindices, paint);
         }
     };
+    struct DrawVerticesObject final : Op {
+        static const auto kType = Type::DrawVerticesObject;
+        DrawVerticesObject(const SkVertices* v, SkBlendMode m, const SkPaint& p)
+            : vertices(sk_ref_sp(const_cast<SkVertices*>(v))), mode(m), paint(p) {}
+        sk_sp<SkVertices> vertices;
+        SkBlendMode mode;
+        SkPaint paint;
+        void draw(SkCanvas* c, const SkMatrix&) {
+            c->drawVertices(vertices, mode, paint);
+        }
+    };
     struct DrawAtlas final : Op {
         static const auto kType = Type::DrawAtlas;
         DrawAtlas(const SkImage* atlas, int count, SkBlendMode xfermode,
@@ -714,6 +726,9 @@
                   colors, colors  ? count    : 0,
                  indices, indices ? nindices : 0);
 }
+void SkLiteDL::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) {
+    this->push<DrawVerticesObject>(0, vertices, mode, paint);
+}
 void SkLiteDL::drawAtlas(const SkImage* atlas, const SkRSXform xforms[], const SkRect texs[],
                          const SkColor colors[], int count, SkBlendMode xfermode,
                          const SkRect* cull, const SkPaint* paint) {
diff --git a/src/core/SkLiteDL.h b/src/core/SkLiteDL.h
index 2e1b8cc..bc5f4e7 100644
--- a/src/core/SkLiteDL.h
+++ b/src/core/SkLiteDL.h
@@ -76,6 +76,7 @@
     void drawPoints(SkCanvas::PointMode, size_t, const SkPoint[], const SkPaint&);
     void drawVertices(SkCanvas::VertexMode, int, const SkPoint[], const SkPoint[], const SkColor[],
                       SkBlendMode, const uint16_t[], int, const SkPaint&);
+    void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&);
     void drawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int,
                    SkBlendMode, const SkRect*, const SkPaint*);
 
diff --git a/src/core/SkLiteRecorder.cpp b/src/core/SkLiteRecorder.cpp
index b3314b0..a01ac65 100644
--- a/src/core/SkLiteRecorder.cpp
+++ b/src/core/SkLiteRecorder.cpp
@@ -187,6 +187,10 @@
                                     const SkPaint& paint) {
     fDL->drawVertices(mode, count, vertices, texs, colors, bmode, indices, indexCount, paint);
 }
+void SkLiteRecorder::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
+                                          const SkPaint& paint) {
+    fDL->drawVertices(vertices, mode, paint);
+}
 void SkLiteRecorder::onDrawAtlas(const SkImage* atlas,
                                  const SkRSXform xforms[],
                                  const SkRect texs[],
diff --git a/src/core/SkLiteRecorder.h b/src/core/SkLiteRecorder.h
index 4de9789..82aeca3 100644
--- a/src/core/SkLiteRecorder.h
+++ b/src/core/SkLiteRecorder.h
@@ -76,6 +76,7 @@
     void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override;
     void onDrawVertices(VertexMode, int, const SkPoint[], const SkPoint[], const SkColor[],
                         SkBlendMode, const uint16_t[], int, const SkPaint&) override;
+    void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;
     void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
                      int, SkBlendMode, const SkRect*, const SkPaint*) override;
 
diff --git a/src/core/SkPictureData.cpp b/src/core/SkPictureData.cpp
index 9780b7d..69ff736 100644
--- a/src/core/SkPictureData.cpp
+++ b/src/core/SkPictureData.cpp
@@ -87,6 +87,15 @@
         }
     }
 
+    const SkTDArray<const SkVertices*>& verts = record.getVerticesRefs();
+    fVerticesCount = verts.count();
+    if (fVerticesCount > 0) {
+        fVerticesRefs = new const SkVertices* [fVerticesCount];
+        for (int i = 0; i < fVerticesCount; ++i) {
+            fVerticesRefs[i] = SkRef(verts[i]);
+        }
+    }
+    
     const SkTDArray<const SkImage*>& imgs = record.getImageRefs();
     fImageCount = imgs.count();
     if (fImageCount > 0) {
@@ -104,6 +113,8 @@
     fDrawableCount = 0;
     fTextBlobRefs = nullptr;
     fTextBlobCount = 0;
+    fVerticesRefs = nullptr;
+    fVerticesCount = 0;
     fImageRefs = nullptr;
     fImageCount = 0;
     fFactoryPlayback = nullptr;
@@ -128,6 +139,11 @@
     }
     delete[] fTextBlobRefs;
 
+    for (int i = 0; i < fVerticesCount; i++) {
+        fVerticesRefs[i]->unref();
+    }
+    delete[] fVerticesRefs;
+
     for (int i = 0; i < fImageCount; i++) {
         fImageRefs[i]->unref();
     }
@@ -247,6 +263,13 @@
         }
     }
 
+    if (fVerticesCount > 0) {
+        write_tag_size(buffer, SK_PICT_VERTICES_BUFFER_TAG, fVerticesCount);
+        for (i = 0; i  < fVerticesCount; ++i) {
+            buffer.writeDataAsByteArray(fVerticesRefs[i]->encode().get());
+        }
+    }
+
     if (fImageCount > 0) {
         write_tag_size(buffer, SK_PICT_IMAGE_BUFFER_TAG, fImageCount);
         for (i = 0; i  < fImageCount; ++i) {
@@ -464,6 +487,10 @@
 static const SkImage* create_image_from_buffer(SkReadBuffer& buffer) {
     return buffer.readImage().release();
 }
+static const SkVertices* create_vertices_from_buffer(SkReadBuffer& buffer) {
+    auto data = buffer.readByteArrayAsData();
+    return data ? SkVertices::Decode(data->data(), data->size()).release() : nullptr;
+}
 
 static const SkImage* create_bitmap_image_from_buffer(SkReadBuffer& buffer) {
     return buffer.readBitmapAsImage().release();
@@ -549,6 +576,12 @@
                 return false;
             }
             break;
+        case SK_PICT_VERTICES_BUFFER_TAG:
+            if (!new_array_from_buffer(buffer, size, &fVerticesRefs, &fVerticesCount,
+                                       create_vertices_from_buffer)) {
+                return false;
+            }
+            break;
         case SK_PICT_IMAGE_BUFFER_TAG:
             if (!new_array_from_buffer(buffer, size, &fImageRefs, &fImageCount,
                                        create_image_from_buffer)) {
diff --git a/src/core/SkPictureData.h b/src/core/SkPictureData.h
index 332b799..37a0237 100644
--- a/src/core/SkPictureData.h
+++ b/src/core/SkPictureData.h
@@ -68,6 +68,7 @@
 #define SK_PICT_PAINT_BUFFER_TAG    SkSetFourByteTag('p', 'n', 't', ' ')
 #define SK_PICT_PATH_BUFFER_TAG     SkSetFourByteTag('p', 't', 'h', ' ')
 #define SK_PICT_TEXTBLOB_BUFFER_TAG SkSetFourByteTag('b', 'l', 'o', 'b')
+#define SK_PICT_VERTICES_BUFFER_TAG SkSetFourByteTag('v', 'e', 'r', 't')
 #define SK_PICT_IMAGE_BUFFER_TAG    SkSetFourByteTag('i', 'm', 'a', 'g')
 
 // Always write this guy last (with no length field afterwards)
@@ -143,6 +144,11 @@
         return reader->validateIndex(index, fTextBlobCount) ? fTextBlobRefs[index] : nullptr;
     }
 
+    const SkVertices* getVertices(SkReadBuffer* reader) const {
+        const int index = reader->readInt() - 1;
+        return reader->validateIndex(index, fVerticesCount) ? fVerticesRefs[index] : nullptr;
+    }
+
 #if SK_SUPPORT_GPU
     /**
      * sampleCount is the number of samples-per-pixel or zero if non-MSAA.
@@ -185,6 +191,8 @@
     int fDrawableCount;
     const SkTextBlob** fTextBlobRefs;
     int fTextBlobCount;
+    const SkVertices** fVerticesRefs;
+    int fVerticesCount;
     const SkImage** fImageRefs;
     int fImageCount;
     const SkImage** fBitmapImageRefs;
diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h
index f5b20ca..ac1483d 100644
--- a/src/core/SkPictureFlat.h
+++ b/src/core/SkPictureFlat.h
@@ -93,8 +93,9 @@
     DRAW_IMAGE_LATTICE,
     DRAW_ARC,
     DRAW_REGION,
+    DRAW_VERTICES_OBJECT,
 
-    LAST_DRAWTYPE_ENUM = DRAW_REGION
+    LAST_DRAWTYPE_ENUM = DRAW_VERTICES_OBJECT
 };
 
 // In the 'match' method, this constant will match any flavor of DRAW_BITMAP*
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index be2e5db..26dc38b 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -678,8 +678,19 @@
             BREAK_ON_READ_ERROR(reader);
 
             if (paint) {
-                canvas->drawVertices(vmode, vCount, verts, texs, colors,
-                                     bmode, indices, iCount, *paint);
+                canvas->drawVertices(SkVertices::MakeCopy(vmode, vCount, verts, texs, colors,
+                                                          iCount, indices), bmode, *paint);
+            }
+        } break;
+        case DRAW_VERTICES_OBJECT: {
+            const SkPaint* paint = fPictureData->getPaint(reader);
+            const SkVertices* vertices = fPictureData->getVertices(reader);
+            SkBlendMode bmode = static_cast<SkBlendMode>(reader->readInt());
+
+            BREAK_ON_READ_ERROR(reader);
+
+            if (paint && vertices) {
+                canvas->drawVertices(vertices, bmode, *paint);
             }
         } break;
         case RESTORE:
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 98677dd..1639cff 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -722,59 +722,26 @@
 }
 
 void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
-                                     const SkPoint vertices[], const SkPoint texs[],
-                                     const SkColor colors[], SkBlendMode bmode,
+                                     const SkPoint pos[], const SkPoint texs[],
+                                     const SkColor cols[], SkBlendMode bmode,
                                      const uint16_t indices[], int indexCount,
                                      const SkPaint& paint) {
-    uint32_t flags = 0;
-    if (texs) {
-        flags |= DRAW_VERTICES_HAS_TEXS;
+    auto vertices = SkVertices::MakeCopy(vmode, vertexCount, pos, texs, cols, indexCount, indices);
+    if (vertices) {
+        this->onDrawVerticesObject(vertices.get(), bmode, paint);
     }
-    if (colors) {
-        flags |= DRAW_VERTICES_HAS_COLORS;
-    }
-    if (indexCount > 0) {
-        flags |= DRAW_VERTICES_HAS_INDICES;
-    }
-    if (SkBlendMode::kModulate != bmode) {
-        flags |= DRAW_VERTICES_HAS_XFER;
-    }
+}
 
-    // op + paint index + flags + vmode + vCount + vertices
-    size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
-    if (flags & DRAW_VERTICES_HAS_TEXS) {
-        size += vertexCount * sizeof(SkPoint);  // + uvs
-    }
-    if (flags & DRAW_VERTICES_HAS_COLORS) {
-        size += vertexCount * sizeof(SkColor);  // + vert colors
-    }
-    if (flags & DRAW_VERTICES_HAS_INDICES) {
-        // + num indices + indices
-        size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
-    }
-    if (flags & DRAW_VERTICES_HAS_XFER) {
-        size += kUInt32Size;    // mode enum
-    }
+void SkPictureRecord::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
+                                           const SkPaint& paint) {
+    // op + paint index + vertices index + mode
+    size_t size = 4 * kUInt32Size;
+    size_t initialOffset = this->addDraw(DRAW_VERTICES_OBJECT, &size);
 
-    size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
     this->addPaint(paint);
-    this->addInt(flags);
-    this->addInt(vmode);
-    this->addInt(vertexCount);
-    this->addPoints(vertices, vertexCount);
-    if (flags & DRAW_VERTICES_HAS_TEXS) {
-        this->addPoints(texs, vertexCount);
-    }
-    if (flags & DRAW_VERTICES_HAS_COLORS) {
-        fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
-    }
-    if (flags & DRAW_VERTICES_HAS_INDICES) {
-        this->addInt(indexCount);
-        fWriter.writePad(indices, indexCount * sizeof(uint16_t));
-    }
-    if (flags & DRAW_VERTICES_HAS_XFER) {
-        this->addInt((int)bmode);
-    }
+    this->addVertices(vertices);
+    this->addInt(static_cast<uint32_t>(mode));
+
     this->validate(initialOffset, size);
 }
 
@@ -984,4 +951,9 @@
     this->addInt(find_or_append_uniqueID(fTextBlobRefs, blob) + 1);
 }
 
+void SkPictureRecord::addVertices(const SkVertices* vertices) {
+    // follow the convention of recording a 1-based index
+    this->addInt(find_or_append_uniqueID(fVerticesRefs, vertices) + 1);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index 587233c..197684e 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -44,7 +44,11 @@
         return fTextBlobRefs;
     }
 
-    const SkTDArray<const SkImage* >& getImageRefs() const {
+    const SkTDArray<const SkVertices* >& getVerticesRefs() const {
+        return fVerticesRefs;
+    }
+
+   const SkTDArray<const SkImage* >& getImageRefs() const {
         return fImageRefs;
     }
 
@@ -141,6 +145,7 @@
     void addRegion(const SkRegion& region);
     void addText(const void* text, size_t byteLength);
     void addTextBlob(const SkTextBlob* blob);
+    void addVertices(const SkVertices*);
 
     int find(const SkBitmap& bitmap);
 
@@ -204,10 +209,7 @@
                         const SkColor colors[], SkBlendMode,
                         const uint16_t indices[], int indexCount,
                         const SkPaint&) override;
-    void onDrawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode mode, const SkPaint& paint,
-                              uint32_t flags) override {
-        this->onDrawVerticesObjectFallback(std::move(vertices), mode, paint, flags);
-    }
+    void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;
 
     void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;
     void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override;
@@ -277,6 +279,7 @@
     SkTDArray<const SkPicture*>  fPictureRefs;
     SkTDArray<SkDrawable*>       fDrawableRefs;
     SkTDArray<const SkTextBlob*> fTextBlobRefs;
+    SkTDArray<const SkVertices*> fVerticesRefs;
 
     uint32_t fRecordFlags;
     int      fInitialSaveCount;
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index 8ca3f06..21f9de9 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -134,8 +134,7 @@
 DRAW(DrawTextRSXform, drawTextRSXform(r.text, r.byteLength, r.xforms, r.cull, r.paint));
 DRAW(DrawAtlas, drawAtlas(r.atlas.get(),
                           r.xforms, r.texs, r.colors, r.count, r.mode, r.cull, r.paint));
-DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors,
-                                r.bmode, r.indices, r.indexCount, r.paint));
+DRAW(DrawVertices, drawVertices(r.vertices, r.bmode, r.paint));
 DRAW(DrawAnnotation, drawAnnotation(r.rect, r.key.c_str(), r.value.get()));
 #undef DRAW
 
@@ -454,9 +453,7 @@
         return this->adjustAndMap(dst, &op.paint);
     }
     Bounds bounds(const DrawVertices& op) const {
-        SkRect dst;
-        dst.set(op.vertices, op.vertexCount);
-        return this->adjustAndMap(dst, &op.paint);
+        return this->adjustAndMap(op.vertices->bounds(), &op.paint);
     }
 
     Bounds bounds(const DrawAtlas& op) const {
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index fb0bda7..9b38bcd 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -331,15 +331,13 @@
                                 const SkPoint texs[], const SkColor colors[],
                                 SkBlendMode bmode,
                                 const uint16_t indices[], int indexCount, const SkPaint& paint) {
-    APPEND(DrawVertices, paint,
-                         vmode,
-                         vertexCount,
-                         this->copy(vertices, vertexCount),
-                         texs ? this->copy(texs, vertexCount) : nullptr,
-                         colors ? this->copy(colors, vertexCount) : nullptr,
-                         bmode,
-                         this->copy(indices, indexCount),
-                         indexCount);
+    this->onDrawVerticesObject(SkVertices::MakeCopy(vmode, vertexCount, vertices, texs, colors,
+                                                    indexCount, indices).get(), bmode, paint);
+}
+
+void SkRecorder::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
+                                      const SkPaint& paint) {
+    APPEND(DrawVertices, paint, sk_ref_sp(const_cast<SkVertices*>(vertices)), bmode);
 }
 
 void SkRecorder::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h
index b5a7903..c133442 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -129,6 +129,7 @@
                         const SkColor colors[], SkBlendMode,
                         const uint16_t indices[], int indexCount,
                         const SkPaint&) override;
+    void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;
     void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
                      int count, SkBlendMode, const SkRect* cull, const SkPaint*) override;
 
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 6370777..55f0f17 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1664,8 +1664,8 @@
                                        GrRenderTargetContext::ColorArrayType::kSkColor);
 }
 
-void SkGpuDevice::drawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode mode,
-                                     const SkPaint& paint, uint32_t deprecatedFlags) {
+void SkGpuDevice::drawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
+                                     const SkPaint& paint) {
     ASSERT_SINGLE_OWNER
     CHECK_SHOULD_DRAW();
     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawVerticesObject", fContext.get());
@@ -1685,7 +1685,7 @@
         return;
     }
     fRenderTargetContext->drawVertices(this->clip(), std::move(grPaint), this->ctm(),
-                                       std::move(vertices));
+                                       sk_ref_sp(const_cast<SkVertices*>(vertices)));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index 01bded4..ed101f9 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -92,8 +92,7 @@
     void drawVertices(SkCanvas::VertexMode, int vertexCount, const SkPoint verts[],
                       const SkPoint texs[], const SkColor colors[], SkBlendMode,
                       const uint16_t indices[], int indexCount, const SkPaint&) override;
-    void drawVerticesObject(sk_sp<SkVertices>, SkBlendMode, const SkPaint&,
-                            uint32_t flags) override;
+    void drawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;
     void drawAtlas(const SkImage* atlas, const SkRSXform[], const SkRect[],
                    const SkColor[], int count, SkBlendMode, const SkPaint&) override;
     void drawDevice(SkBaseDevice*, int x, int y, const SkPaint&) override;
diff --git a/tools/debugger/SkDebugCanvas.h b/tools/debugger/SkDebugCanvas.h
index d25fe40..2b15bba 100644
--- a/tools/debugger/SkDebugCanvas.h
+++ b/tools/debugger/SkDebugCanvas.h
@@ -230,9 +230,9 @@
                         const SkColor colors[], SkBlendMode,
                         const uint16_t indices[], int indexCount,
                         const SkPaint&) override;
-    void onDrawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode mode, const SkPaint& paint,
-                              uint32_t flags) override {
-        this->onDrawVerticesObjectFallback(std::move(vertices), mode, paint, flags);
+    void onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
+                              const SkPaint& paint) override {
+        this->devolveSkVerticesToRaw(vertices, mode, paint);
     }
     void onDrawPath(const SkPath&, const SkPaint&) override;
     void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override;