[Impeller] make VerticesGeometry delegate to the DL class (#37835)

* [Impeller] make VerticesGeometry delegate to the DL class

* ++

* ++

* licenses

* ++
diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index 141f9e3..1cbe4bd 100644
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -1144,10 +1144,10 @@
 FILE: ../../../flutter/impeller/display_list/display_list_playground.cc
 FILE: ../../../flutter/impeller/display_list/display_list_playground.h
 FILE: ../../../flutter/impeller/display_list/display_list_unittests.cc
+FILE: ../../../flutter/impeller/display_list/display_list_vertices_geometry.cc
+FILE: ../../../flutter/impeller/display_list/display_list_vertices_geometry.h
 FILE: ../../../flutter/impeller/display_list/nine_patch_converter.cc
 FILE: ../../../flutter/impeller/display_list/nine_patch_converter.h
-FILE: ../../../flutter/impeller/display_list/vertices_converter.cc
-FILE: ../../../flutter/impeller/display_list/vertices_converter.h
 FILE: ../../../flutter/impeller/docs/assets/launch-app.png
 FILE: ../../../flutter/impeller/docs/assets/read_frame_captures/image1.png
 FILE: ../../../flutter/impeller/docs/assets/read_frame_captures/image10.png
@@ -1355,8 +1355,6 @@
 FILE: ../../../flutter/impeller/geometry/type_traits.h
 FILE: ../../../flutter/impeller/geometry/vector.cc
 FILE: ../../../flutter/impeller/geometry/vector.h
-FILE: ../../../flutter/impeller/geometry/vertices.cc
-FILE: ../../../flutter/impeller/geometry/vertices.h
 FILE: ../../../flutter/impeller/image/backends/skia/compressed_image_skia.cc
 FILE: ../../../flutter/impeller/image/backends/skia/compressed_image_skia.h
 FILE: ../../../flutter/impeller/image/compressed_image.cc
diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc
index 996ea68..7ff85c5 100644
--- a/impeller/aiks/canvas.cc
+++ b/impeller/aiks/canvas.cc
@@ -18,7 +18,6 @@
 #include "impeller/entity/contents/vertices_contents.h"
 #include "impeller/entity/geometry.h"
 #include "impeller/geometry/path_builder.h"
-#include "impeller/geometry/vertices.h"
 
 namespace impeller {
 
@@ -373,11 +372,9 @@
   GetCurrentPass().AddEntity(entity);
 }
 
-void Canvas::DrawVertices(const Vertices& vertices,
+void Canvas::DrawVertices(std::unique_ptr<VerticesGeometry> vertices,
                           BlendMode blend_mode,
                           Paint paint) {
-  auto geometry = Geometry::MakeVertices(vertices);
-
   Entity entity;
   entity.SetTransformation(GetCurrentTransformation());
   entity.SetStencilDepth(GetStencilDepth());
@@ -386,7 +383,7 @@
   if (paint.color_source.has_value()) {
     auto& source = paint.color_source.value();
     auto contents = source();
-    contents->SetGeometry(std::move(geometry));
+    contents->SetGeometry(std::move(vertices));
     contents->SetAlpha(paint.color.alpha);
     entity.SetContents(paint.WithFilters(std::move(contents), true));
   } else {
@@ -394,7 +391,7 @@
         std::make_shared<VerticesContents>();
     contents->SetColor(paint.color);
     contents->SetBlendMode(blend_mode);
-    contents->SetGeometry(std::move(geometry));
+    contents->SetGeometry(std::move(vertices));
     entity.SetContents(paint.WithFilters(std::move(contents), true));
   }
 
diff --git a/impeller/aiks/canvas.h b/impeller/aiks/canvas.h
index 7638c88..456948b 100644
--- a/impeller/aiks/canvas.h
+++ b/impeller/aiks/canvas.h
@@ -14,11 +14,11 @@
 #include "impeller/aiks/paint.h"
 #include "impeller/aiks/picture.h"
 #include "impeller/entity/entity_pass.h"
+#include "impeller/entity/geometry.h"
 #include "impeller/geometry/matrix.h"
 #include "impeller/geometry/path.h"
 #include "impeller/geometry/point.h"
 #include "impeller/geometry/vector.h"
-#include "impeller/geometry/vertices.h"
 #include "impeller/renderer/sampler_descriptor.h"
 #include "impeller/typographer/glyph_atlas.h"
 #include "impeller/typographer/text_frame.h"
@@ -97,7 +97,7 @@
                      Point position,
                      const Paint& paint);
 
-  void DrawVertices(const Vertices& vertices,
+  void DrawVertices(std::unique_ptr<VerticesGeometry> vertices,
                     BlendMode blend_mode,
                     Paint paint);
 
diff --git a/impeller/display_list/BUILD.gn b/impeller/display_list/BUILD.gn
index a6c4fcd..48cf0f1 100644
--- a/impeller/display_list/BUILD.gn
+++ b/impeller/display_list/BUILD.gn
@@ -10,10 +10,10 @@
     "display_list_dispatcher.h",
     "display_list_image_impeller.cc",
     "display_list_image_impeller.h",
+    "display_list_vertices_geometry.cc",
+    "display_list_vertices_geometry.h",
     "nine_patch_converter.cc",
     "nine_patch_converter.h",
-    "vertices_converter.cc",
-    "vertices_converter.h",
   ]
 
   public_deps = [
diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc
index a5fe27b..eba5782 100644
--- a/impeller/display_list/display_list_dispatcher.cc
+++ b/impeller/display_list/display_list_dispatcher.cc
@@ -20,8 +20,8 @@
 #include "flutter/fml/logging.h"
 #include "flutter/fml/trace_event.h"
 #include "impeller/display_list/display_list_image_impeller.h"
+#include "impeller/display_list/display_list_vertices_geometry.h"
 #include "impeller/display_list/nine_patch_converter.h"
-#include "impeller/display_list/vertices_converter.h"
 #include "impeller/entity/contents/filters/filter_contents.h"
 #include "impeller/entity/contents/filters/inputs/filter_input.h"
 #include "impeller/entity/contents/linear_gradient_contents.h"
@@ -35,7 +35,6 @@
 #include "impeller/geometry/path_builder.h"
 #include "impeller/geometry/scalar.h"
 #include "impeller/geometry/sigma.h"
-#include "impeller/geometry/vertices.h"
 #include "impeller/renderer/formats.h"
 #include "impeller/typographer/backends/skia/text_frame_skia.h"
 
@@ -1104,7 +1103,8 @@
 // |flutter::Dispatcher|
 void DisplayListDispatcher::drawVertices(const flutter::DlVertices* vertices,
                                          flutter::DlBlendMode dl_mode) {
-  canvas_.DrawVertices(ToVertices(vertices), ToBlendMode(dl_mode), paint_);
+  canvas_.DrawVertices(DLVerticesGeometry::MakeVertices(vertices),
+                       ToBlendMode(dl_mode), paint_);
 }
 
 // |flutter::Dispatcher|
diff --git a/impeller/display_list/display_list_unittests.cc b/impeller/display_list/display_list_unittests.cc
index 91e8863..6b904e9 100644
--- a/impeller/display_list/display_list_unittests.cc
+++ b/impeller/display_list/display_list_unittests.cc
@@ -1054,5 +1054,71 @@
   ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
 }
 
+TEST_P(DisplayListTest, DrawVerticesSolidColorTrianglesWithoutIndices) {
+  std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
+                                    SkPoint::Make(200, 100),
+                                    SkPoint::Make(300, 300)};
+  std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
+                                          flutter::DlColor::kGreen(),
+                                          flutter::DlColor::kWhite()};
+
+  auto vertices = flutter::DlVertices::Make(
+      flutter::DlVertexMode::kTriangles, 3, positions.data(),
+      /*texture_coorindates=*/nullptr, colors.data());
+
+  flutter::DisplayListBuilder builder;
+  flutter::DlPaint paint;
+
+  paint.setColor(flutter::DlColor::kRed().modulateOpacity(0.5));
+  builder.drawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
+
+  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
+}
+
+TEST_P(DisplayListTest, DrawVerticesLinearGradientWithoutIndices) {
+  std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
+                                    SkPoint::Make(200, 100),
+                                    SkPoint::Make(300, 300)};
+
+  auto vertices = flutter::DlVertices::Make(
+      flutter::DlVertexMode::kTriangles, 3, positions.data(),
+      /*texture_coorindates=*/nullptr, /*colors=*/nullptr);
+
+  std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
+                                          flutter::DlColor::kRed()};
+  const float stops[2] = {0.0, 1.0};
+
+  auto linear = flutter::DlColorSource::MakeLinear(
+      {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
+      flutter::DlTileMode::kRepeat);
+
+  flutter::DisplayListBuilder builder;
+  flutter::DlPaint paint;
+
+  paint.setColorSource(linear);
+  builder.drawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
+
+  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
+}
+
+TEST_P(DisplayListTest, DrawVerticesSolidColorTrianglesWithIndices) {
+  std::vector<SkPoint> positions = {
+      SkPoint::Make(100, 300), SkPoint::Make(200, 100), SkPoint::Make(300, 300),
+      SkPoint::Make(200, 500)};
+  std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
+
+  auto vertices = flutter::DlVertices::Make(
+      flutter::DlVertexMode::kTriangles, 6, positions.data(),
+      /*texture_coorindates=*/nullptr, /*colors=*/nullptr, 6, indices.data());
+
+  flutter::DisplayListBuilder builder;
+  flutter::DlPaint paint;
+
+  paint.setColor(flutter::DlColor::kWhite());
+  builder.drawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
+
+  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
+}
+
 }  // namespace testing
 }  // namespace impeller
diff --git a/impeller/display_list/display_list_vertices_geometry.cc b/impeller/display_list/display_list_vertices_geometry.cc
new file mode 100644
index 0000000..1cab24c
--- /dev/null
+++ b/impeller/display_list/display_list_vertices_geometry.cc
@@ -0,0 +1,247 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "impeller/display_list/display_list_vertices_geometry.h"
+
+#include "impeller/entity/contents/content_context.h"
+#include "impeller/entity/entity.h"
+#include "impeller/entity/position_color.vert.h"
+#include "impeller/geometry/matrix.h"
+#include "impeller/geometry/path_builder.h"
+#include "impeller/geometry/point.h"
+#include "impeller/renderer/device_buffer.h"
+#include "impeller/renderer/render_pass.h"
+#include "third_party/skia/include/core/SkPoint.h"
+#include "third_party/skia/include/core/SkRect.h"
+
+namespace impeller {
+
+static Rect ToRect(const SkRect& rect) {
+  return Rect::MakeLTRB(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
+}
+
+// Fan mode isn't natively supported. Unroll into triangle mode by
+// manipulating the index array.
+//
+// In Triangle fan, the first vertex is shared across all triangles, and then
+// each sliding window of two vertices plus that first vertex defines a
+// triangle.
+static std::vector<uint16_t> fromFanIndices(
+    const flutter::DlVertices* vertices) {
+  FML_DCHECK(vertices->vertex_count() >= 3);
+  FML_DCHECK(vertices->mode() == flutter::DlVertexMode::kTriangleFan);
+
+  std::vector<uint16_t> indices;
+
+  // Un-fan index buffer if provided.
+  if (vertices->index_count() > 0) {
+    auto* dl_indices = vertices->indices();
+    auto center_point = dl_indices[0];
+    for (int i = 1; i < vertices->index_count() - 1; i++) {
+      indices.push_back(center_point);
+      indices.push_back(dl_indices[i]);
+      indices.push_back(dl_indices[i + 1]);
+    }
+  } else {
+    // If indices were not provided, create an index buffer that unfans
+    // triangles instead of re-writing points, colors, et cetera.
+    for (int i = 1; i < vertices->vertex_count() - 1; i++) {
+      indices.push_back(0);
+      indices.push_back(i);
+      indices.push_back(i + 1);
+    }
+  }
+  return indices;
+}
+
+/////// Vertices Geometry ///////
+
+// static
+std::unique_ptr<VerticesGeometry> DLVerticesGeometry::MakeVertices(
+    const flutter::DlVertices* vertices) {
+  return std::make_unique<DLVerticesGeometry>(vertices);
+}
+
+DLVerticesGeometry::DLVerticesGeometry(const flutter::DlVertices* vertices)
+    : vertices_(vertices) {
+  NormalizeIndices();
+}
+
+DLVerticesGeometry::~DLVerticesGeometry() = default;
+
+void DLVerticesGeometry::NormalizeIndices() {
+  // Convert triangle fan if present.
+  if (vertices_->mode() == flutter::DlVertexMode::kTriangleFan) {
+    normalized_indices_ = fromFanIndices(vertices_);
+    return;
+  }
+
+  auto index_count = vertices_->index_count();
+  auto vertex_count = vertices_->vertex_count();
+  if (index_count != 0 || vertex_count == 0) {
+    return;
+  }
+  normalized_indices_.reserve(vertex_count);
+  for (auto i = 0; i < vertex_count; i++) {
+    normalized_indices_.push_back(i);
+  }
+}
+
+static PrimitiveType GetPrimitiveType(const flutter::DlVertices* vertices) {
+  switch (vertices->mode()) {
+    case flutter::DlVertexMode::kTriangles:
+      return PrimitiveType::kTriangle;
+    case flutter::DlVertexMode::kTriangleStrip:
+      return PrimitiveType::kTriangleStrip;
+    case flutter::DlVertexMode::kTriangleFan:
+      // Unrolled into triangle mode.
+      return PrimitiveType::kTriangle;
+  }
+}
+
+GeometryResult DLVerticesGeometry::GetPositionBuffer(
+    const ContentContext& renderer,
+    const Entity& entity,
+    RenderPass& pass) {
+  auto index_count = normalized_indices_.size() == 0
+                         ? vertices_->index_count()
+                         : normalized_indices_.size();
+  auto vertex_count = vertices_->vertex_count();
+  auto* dl_indices = normalized_indices_.size() == 0
+                         ? vertices_->indices()
+                         : normalized_indices_.data();
+  auto* dl_vertices = vertices_->vertices();
+
+  size_t total_vtx_bytes = vertex_count * sizeof(float) * 2;
+  size_t total_idx_bytes = index_count * sizeof(uint16_t);
+
+  DeviceBufferDescriptor buffer_desc;
+  buffer_desc.size = total_vtx_bytes + total_idx_bytes;
+  buffer_desc.storage_mode = StorageMode::kHostVisible;
+
+  auto buffer =
+      renderer.GetContext()->GetResourceAllocator()->CreateBuffer(buffer_desc);
+
+  if (!buffer->CopyHostBuffer(reinterpret_cast<const uint8_t*>(dl_vertices),
+                              Range{0, total_vtx_bytes}, 0)) {
+    return {};
+  }
+  if (!buffer->CopyHostBuffer(
+          reinterpret_cast<uint8_t*>(const_cast<uint16_t*>(dl_indices)),
+          Range{0, total_idx_bytes}, total_vtx_bytes)) {
+    return {};
+  }
+
+  return GeometryResult{
+      .type = GetPrimitiveType(vertices_),
+      .vertex_buffer =
+          {
+              .vertex_buffer = {.buffer = buffer,
+                                .range = Range{0, total_vtx_bytes}},
+              .index_buffer = {.buffer = buffer,
+                               .range =
+                                   Range{total_vtx_bytes, total_idx_bytes}},
+              .index_count = index_count,
+              .index_type = IndexType::k16bit,
+          },
+      .transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
+                   entity.GetTransformation(),
+      .prevent_overdraw = false,
+  };
+}
+
+GeometryResult DLVerticesGeometry::GetPositionColorBuffer(
+    const ContentContext& renderer,
+    const Entity& entity,
+    RenderPass& pass,
+    Color paint_color,
+    BlendMode blend_mode) {
+  using VS = GeometryColorPipeline::VertexShader;
+
+  auto index_count = normalized_indices_.size() == 0
+                         ? vertices_->index_count()
+                         : normalized_indices_.size();
+  auto vertex_count = vertices_->vertex_count();
+  auto* dl_indices = normalized_indices_.size() == 0
+                         ? vertices_->indices()
+                         : normalized_indices_.data();
+  auto* dl_vertices = vertices_->vertices();
+  auto* dl_colors = vertices_->colors();
+
+  std::vector<VS::PerVertexData> vertex_data(vertex_count);
+  {
+    for (auto i = 0; i < vertex_count; i++) {
+      auto dl_color = dl_colors[i];
+      auto pre_color = Color(dl_color.getRedF(), dl_color.getGreenF(),
+                             dl_color.getBlueF(), dl_color.getAlphaF());
+      auto color = Color::BlendColor(paint_color, pre_color, blend_mode);
+      auto sk_point = dl_vertices[i];
+      vertex_data[i] = {
+          .position = Point(sk_point.x(), sk_point.y()),
+          .color = color,
+      };
+    }
+  }
+
+  size_t total_vtx_bytes = vertex_data.size() * sizeof(VS::PerVertexData);
+  size_t total_idx_bytes = index_count * sizeof(uint16_t);
+
+  DeviceBufferDescriptor buffer_desc;
+  buffer_desc.size = total_vtx_bytes + total_idx_bytes;
+  buffer_desc.storage_mode = StorageMode::kHostVisible;
+
+  auto buffer =
+      renderer.GetContext()->GetResourceAllocator()->CreateBuffer(buffer_desc);
+
+  if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(vertex_data.data()),
+                              Range{0, total_vtx_bytes}, 0)) {
+    return {};
+  }
+  if (!buffer->CopyHostBuffer(
+          reinterpret_cast<uint8_t*>(const_cast<uint16_t*>(dl_indices)),
+          Range{0, total_idx_bytes}, total_vtx_bytes)) {
+    return {};
+  }
+
+  return GeometryResult{
+      .type = GetPrimitiveType(vertices_),
+      .vertex_buffer =
+          {
+              .vertex_buffer = {.buffer = buffer,
+                                .range = Range{0, total_vtx_bytes}},
+              .index_buffer = {.buffer = buffer,
+                               .range =
+                                   Range{total_vtx_bytes, total_idx_bytes}},
+              .index_count = index_count,
+              .index_type = IndexType::k16bit,
+          },
+      .transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
+                   entity.GetTransformation(),
+      .prevent_overdraw = false,
+  };
+}
+
+GeometryResult DLVerticesGeometry::GetPositionUVBuffer(
+    const ContentContext& renderer,
+    const Entity& entity,
+    RenderPass& pass) {
+  // TODO(jonahwilliams): support texture coordinates in vertices
+  // https://github.com/flutter/flutter/issues/109956
+  return {};
+}
+
+GeometryVertexType DLVerticesGeometry::GetVertexType() const {
+  auto* dl_colors = vertices_->colors();
+  if (dl_colors != nullptr) {
+    return GeometryVertexType::kColor;
+  }
+  return GeometryVertexType::kPosition;
+}
+
+std::optional<Rect> DLVerticesGeometry::GetCoverage(
+    const Matrix& transform) const {
+  return ToRect(vertices_->bounds());
+}
+
+}  // namespace impeller
diff --git a/impeller/display_list/display_list_vertices_geometry.h b/impeller/display_list/display_list_vertices_geometry.h
new file mode 100644
index 0000000..510f496
--- /dev/null
+++ b/impeller/display_list/display_list_vertices_geometry.h
@@ -0,0 +1,61 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <optional>
+#include <vector>
+
+#include "flutter/display_list/display_list_vertices.h"
+
+#include "impeller/entity/geometry.h"
+#include "impeller/geometry/color.h"
+#include "impeller/geometry/point.h"
+#include "impeller/geometry/rect.h"
+
+namespace impeller {
+
+/// @brief A geometry that is created from a vertices object.
+class DLVerticesGeometry : public VerticesGeometry {
+ public:
+  explicit DLVerticesGeometry(const flutter::DlVertices* vertices);
+
+  ~DLVerticesGeometry();
+
+  static std::unique_ptr<VerticesGeometry> MakeVertices(
+      const flutter::DlVertices* vertices);
+
+  // |VerticesGeometry|
+  GeometryResult GetPositionColorBuffer(const ContentContext& renderer,
+                                        const Entity& entity,
+                                        RenderPass& pass,
+                                        Color paint_color,
+                                        BlendMode blend_mode) override;
+
+  // |VerticesGeometry|
+  GeometryResult GetPositionUVBuffer(const ContentContext& renderer,
+                                     const Entity& entity,
+                                     RenderPass& pass) override;
+
+  // |Geometry|
+  GeometryResult GetPositionBuffer(const ContentContext& renderer,
+                                   const Entity& entity,
+                                   RenderPass& pass) override;
+
+  // |Geometry|
+  std::optional<Rect> GetCoverage(const Matrix& transform) const override;
+
+  // |Geometry|
+  GeometryVertexType GetVertexType() const override;
+
+ private:
+  void NormalizeIndices();
+
+  const flutter::DlVertices* vertices_;
+  std::vector<uint16_t> normalized_indices_;
+
+  FML_DISALLOW_COPY_AND_ASSIGN(DLVerticesGeometry);
+};
+
+}  // namespace impeller
diff --git a/impeller/display_list/vertices_converter.cc b/impeller/display_list/vertices_converter.cc
deleted file mode 100644
index 3bcb5e9..0000000
--- a/impeller/display_list/vertices_converter.cc
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "impeller/display_list/vertices_converter.h"
-#include "flutter/display_list/display_list_vertices.h"
-#include "impeller/entity/entity.h"
-#include "impeller/geometry/point.h"
-
-namespace impeller {
-
-static Rect ToRect(const SkRect& rect) {
-  return Rect::MakeLTRB(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
-}
-
-static std::vector<Color> fromColors(const flutter::DlVertices* vertices) {
-  std::vector<Color> colors;
-  auto* dl_colors = vertices->colors();
-  if (dl_colors == nullptr) {
-    return colors;
-  }
-  auto color_count = vertices->vertex_count();
-  colors.reserve(color_count);
-  for (int i = 0; i < color_count; i++) {
-    auto dl_color = dl_colors[i];
-    colors.push_back({
-        dl_color.getRedF(),
-        dl_color.getGreenF(),
-        dl_color.getBlueF(),
-        dl_color.getAlphaF(),
-    });
-  }
-  return colors;
-}
-
-static std::vector<Point> fromPoints(const flutter::DlVertices* vertices) {
-  std::vector<Point> points;
-  auto vertex_count = vertices->vertex_count();
-  auto* dl_vertices = vertices->vertices();
-  points.reserve(vertex_count);
-  for (int i = 0; i < vertex_count; i++) {
-    auto point = dl_vertices[i];
-    points.push_back(Point(point.x(), point.y()));
-  }
-  return points;
-}
-
-// Fan mode isn't natively supported. Unroll into triangle mode by
-// manipulating the index array.
-//
-// In Triangle fan, the first vertex is shared across all triangles, and then
-// each sliding window of two vertices plus that first vertex defines a
-// triangle.
-static std::vector<uint16_t> fromFanIndices(
-    const flutter::DlVertices* vertices) {
-  FML_DCHECK(vertices->vertex_count() >= 3);
-  FML_DCHECK(vertices->mode() == flutter::DlVertexMode::kTriangleFan);
-
-  std::vector<uint16_t> indices;
-
-  // Un-fan index buffer if provided.
-  if (vertices->index_count() > 0) {
-    auto* dl_indices = vertices->indices();
-    auto center_point = dl_indices[0];
-    for (int i = 1; i < vertices->index_count() - 1; i++) {
-      indices.push_back(center_point);
-      indices.push_back(dl_indices[i]);
-      indices.push_back(dl_indices[i + 1]);
-    }
-  } else {
-    // If indices were not provided, create an index buffer that unfans
-    // triangles instead of re-writing points, colors, et cetera.
-    for (int i = 1; i < vertices->vertex_count() - 1; i++) {
-      indices.push_back(0);
-      indices.push_back(i);
-      indices.push_back(i + 1);
-    }
-  }
-  return indices;
-}
-
-static std::vector<uint16_t> fromIndices(const flutter::DlVertices* vertices) {
-  if (vertices->mode() == flutter::DlVertexMode::kTriangleFan) {
-    return fromFanIndices(vertices);
-  }
-
-  std::vector<uint16_t> indices;
-  auto index_count = vertices->index_count();
-  auto* dl_indices = vertices->indices();
-  indices.reserve(index_count);
-  for (int i = 0; i < index_count; i++) {
-    auto index = dl_indices[i];
-    indices.push_back(index);
-  }
-  return indices;
-}
-
-Vertices ToVertices(const flutter::DlVertices* vertices) {
-  std::vector<uint16_t> indices = fromIndices(vertices);
-  std::vector<Point> points = fromPoints(vertices);
-  std::vector<Color> colors = fromColors(vertices);
-
-  VertexMode mode;
-  switch (vertices->mode()) {
-    case flutter::DlVertexMode::kTriangles:
-      mode = VertexMode::kTriangle;
-      break;
-    case flutter::DlVertexMode::kTriangleStrip:
-      mode = VertexMode::kTriangleStrip;
-      break;
-    case flutter::DlVertexMode::kTriangleFan:
-      // Unrolled into triangle mode by fromIndices.
-      mode = VertexMode::kTriangle;
-      break;
-  }
-
-  auto bounds = vertices->bounds();
-  return Vertices(std::move(points), std::move(indices), std::move(colors),
-                  mode, ToRect(bounds));
-}
-
-}  // namespace impeller
diff --git a/impeller/display_list/vertices_converter.h b/impeller/display_list/vertices_converter.h
deleted file mode 100644
index 0b68fc5..0000000
--- a/impeller/display_list/vertices_converter.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#pragma once
-
-#include "flutter/display_list/display_list.h"
-#include "flutter/display_list/display_list_vertices.h"
-#include "impeller/geometry/vertices.h"
-
-namespace impeller {
-
-/// Convert DlVertices into impeller Vertices.
-Vertices ToVertices(const flutter::DlVertices* vertices);
-
-}  // namespace impeller
diff --git a/impeller/entity/contents/vertices_contents.h b/impeller/entity/contents/vertices_contents.h
index b509b0a..0f754c4 100644
--- a/impeller/entity/contents/vertices_contents.h
+++ b/impeller/entity/contents/vertices_contents.h
@@ -15,7 +15,6 @@
 #include "impeller/geometry/color.h"
 #include "impeller/geometry/path.h"
 #include "impeller/geometry/point.h"
-#include "impeller/geometry/vertices.h"
 #include "impeller/renderer/sampler_descriptor.h"
 
 namespace impeller {
diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc
index 83ad0b4..ed89d7f 100644
--- a/impeller/entity/entity_unittests.cc
+++ b/impeller/entity/entity_unittests.cc
@@ -1203,77 +1203,6 @@
   }
 }
 
-TEST_P(EntityTest, DrawVerticesSolidColorTrianglesWithoutIndices) {
-  std::vector<Point> positions = {Point(100, 300), Point(200, 100),
-                                  Point(300, 300)};
-  std::vector<Color> colors = {Color::White(), Color::Green(), Color::White()};
-
-  Vertices vertices = Vertices(positions, {} /* indices */, colors,
-                               VertexMode::kTriangle, Rect(100, 100, 300, 300));
-
-  std::shared_ptr<VerticesContents> contents =
-      std::make_shared<VerticesContents>();
-  contents->SetGeometry(Geometry::MakeVertices(vertices));
-  contents->SetBlendMode(BlendMode::kSourceOver);
-  contents->SetColor(Color::Red().WithAlpha(0.5));
-
-  Entity e;
-  e.SetTransformation(Matrix::MakeScale(GetContentScale()));
-  e.SetContents(contents);
-
-  ASSERT_TRUE(OpenPlaygroundHere(e));
-}
-
-TEST_P(EntityTest, DrawVerticesLinearGradientWithoutIndices) {
-  std::vector<Point> positions = {Point(100, 300), Point(200, 100),
-                                  Point(300, 300)};
-
-  Vertices vertices = Vertices(positions, {} /* indices */, {} /* colors */,
-                               VertexMode::kTriangle, Rect(100, 100, 300, 300));
-
-  std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
-                               Color{0.1294, 0.5882, 0.9529, 1.0}};
-  std::vector<Scalar> stops = {0.0, 1.0};
-  Matrix matrix = {
-      1, 0, 0, 0,  //
-      0, 1, 0, 0,  //
-      0, 0, 1, 0,  //
-      0, 0, 0, 1   //
-  };
-  auto contents = std::make_shared<LinearGradientContents>();
-  contents->SetEndPoints({100, 100}, {300, 300});
-  contents->SetColors(std::move(colors));
-  contents->SetStops(std::move(stops));
-  contents->SetTileMode(Entity::TileMode::kRepeat);
-  contents->SetMatrix(matrix);
-  contents->SetGeometry(Geometry::MakeVertices(vertices));
-
-  Entity e;
-  e.SetTransformation(Matrix::MakeScale(GetContentScale()));
-  e.SetContents(contents);
-
-  ASSERT_TRUE(OpenPlaygroundHere(e));
-}
-
-TEST_P(EntityTest, DrawVerticesSolidColorTrianglesWithIndices) {
-  std::vector<Point> positions = {Point(100, 300), Point(200, 100),
-                                  Point(300, 300), Point(200, 500)};
-  std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
-
-  Vertices vertices = Vertices(positions, indices, {} /* colors */,
-                               VertexMode::kTriangle, Rect(100, 100, 300, 300));
-
-  std::shared_ptr<VerticesContents> contents =
-      std::make_shared<VerticesContents>();
-  contents->SetGeometry(Geometry::MakeVertices(vertices));
-  contents->SetColor(Color::White());
-  Entity e;
-  e.SetTransformation(Matrix::MakeScale(GetContentScale()));
-  e.SetContents(contents);
-
-  ASSERT_TRUE(OpenPlaygroundHere(e));
-}
-
 TEST_P(EntityTest, DrawAtlasNoColor) {
   // Draws the image as four squares stiched together.
   auto atlas = CreateTextureForFixture("bay_bridge.jpg");
diff --git a/impeller/entity/geometry.cc b/impeller/entity/geometry.cc
index 7c46548..8bc37b3 100644
--- a/impeller/entity/geometry.cc
+++ b/impeller/entity/geometry.cc
@@ -18,11 +18,6 @@
 Geometry::~Geometry() = default;
 
 // static
-std::unique_ptr<VerticesGeometry> Geometry::MakeVertices(
-    const Vertices& vertices) {
-  return std::make_unique<VerticesGeometry>(vertices);
-}
-
 std::unique_ptr<Geometry> Geometry::MakeFillPath(const Path& path) {
   return std::make_unique<FillPathGeometry>(path);
 }
@@ -48,156 +43,6 @@
   return std::make_unique<RectGeometry>(rect);
 }
 
-/////// Vertices Geometry ///////
-
-VerticesGeometry::VerticesGeometry(const Vertices& vertices)
-    : vertices_(vertices) {}
-
-VerticesGeometry::~VerticesGeometry() = default;
-
-static PrimitiveType GetPrimitiveType(const Vertices& vertices) {
-  switch (vertices.GetMode()) {
-    case VertexMode::kTriangle:
-      return PrimitiveType::kTriangle;
-    case VertexMode::kTriangleStrip:
-      return PrimitiveType::kTriangleStrip;
-  }
-}
-
-GeometryResult VerticesGeometry::GetPositionBuffer(
-    const ContentContext& renderer,
-    const Entity& entity,
-    RenderPass& pass) {
-  if (!vertices_.IsValid()) {
-    return {};
-  }
-
-  auto vertex_count = vertices_.GetPositions().size();
-  size_t total_vtx_bytes = vertex_count * sizeof(float) * 2;
-  size_t total_idx_bytes = vertices_.GetIndices().size() * sizeof(uint16_t);
-
-  DeviceBufferDescriptor buffer_desc;
-  buffer_desc.size = total_vtx_bytes + total_idx_bytes;
-  buffer_desc.storage_mode = StorageMode::kHostVisible;
-
-  auto buffer =
-      renderer.GetContext()->GetResourceAllocator()->CreateBuffer(buffer_desc);
-
-  const auto& positions = vertices_.GetPositions();
-  if (!buffer->CopyHostBuffer(
-          reinterpret_cast<const uint8_t*>(positions.data()),
-          Range{0, total_vtx_bytes}, 0)) {
-    return {};
-  }
-  if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(const_cast<uint16_t*>(
-                                  vertices_.GetIndices().data())),
-                              Range{0, total_idx_bytes}, total_vtx_bytes)) {
-    return {};
-  }
-
-  return GeometryResult{
-      .type = GetPrimitiveType(vertices_),
-      .vertex_buffer =
-          {
-              .vertex_buffer = {.buffer = buffer,
-                                .range = Range{0, total_vtx_bytes}},
-              .index_buffer = {.buffer = buffer,
-                               .range =
-                                   Range{total_vtx_bytes, total_idx_bytes}},
-              .index_count = vertices_.GetIndices().size(),
-              .index_type = IndexType::k16bit,
-          },
-      .transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
-                   entity.GetTransformation(),
-      .prevent_overdraw = false,
-  };
-}
-
-GeometryResult VerticesGeometry::GetPositionColorBuffer(
-    const ContentContext& renderer,
-    const Entity& entity,
-    RenderPass& pass,
-    Color paint_color,
-    BlendMode blend_mode) {
-  using VS = GeometryColorPipeline::VertexShader;
-
-  if (!vertices_.IsValid()) {
-    return {};
-  }
-
-  auto vertex_count = vertices_.GetPositions().size();
-  std::vector<VS::PerVertexData> vertex_data(vertex_count);
-  {
-    const auto& positions = vertices_.GetPositions();
-    const auto& colors = vertices_.GetColors();
-    for (size_t i = 0; i < vertex_count; i++) {
-      auto color = Color::BlendColor(paint_color, colors[i], blend_mode);
-      vertex_data[i] = {
-          .position = positions[i],
-          .color = color,
-      };
-    }
-  }
-
-  size_t total_vtx_bytes = vertex_data.size() * sizeof(VS::PerVertexData);
-  size_t total_idx_bytes = vertices_.GetIndices().size() * sizeof(uint16_t);
-
-  DeviceBufferDescriptor buffer_desc;
-  buffer_desc.size = total_vtx_bytes + total_idx_bytes;
-  buffer_desc.storage_mode = StorageMode::kHostVisible;
-
-  auto buffer =
-      renderer.GetContext()->GetResourceAllocator()->CreateBuffer(buffer_desc);
-
-  if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(vertex_data.data()),
-                              Range{0, total_vtx_bytes}, 0)) {
-    return {};
-  }
-  if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(const_cast<uint16_t*>(
-                                  vertices_.GetIndices().data())),
-                              Range{0, total_idx_bytes}, total_vtx_bytes)) {
-    return {};
-  }
-
-  return GeometryResult{
-      .type = GetPrimitiveType(vertices_),
-      .vertex_buffer =
-          {
-              .vertex_buffer = {.buffer = buffer,
-                                .range = Range{0, total_vtx_bytes}},
-              .index_buffer = {.buffer = buffer,
-                               .range =
-                                   Range{total_vtx_bytes, total_idx_bytes}},
-              .index_count = vertices_.GetIndices().size(),
-              .index_type = IndexType::k16bit,
-          },
-      .transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
-                   entity.GetTransformation(),
-      .prevent_overdraw = false,
-  };
-}
-
-GeometryResult VerticesGeometry::GetPositionUVBuffer(
-    const ContentContext& renderer,
-    const Entity& entity,
-    RenderPass& pass) {
-  // TODO(jonahwilliams): support texture coordinates in vertices
-  // https://github.com/flutter/flutter/issues/109956
-  return {};
-}
-
-GeometryVertexType VerticesGeometry::GetVertexType() const {
-  if (vertices_.GetColors().size()) {
-    return GeometryVertexType::kColor;
-  }
-  return GeometryVertexType::kPosition;
-}
-
-std::optional<Rect> VerticesGeometry::GetCoverage(
-    const Matrix& transform) const {
-  return vertices_.GetTransformedBoundingBox(transform);
-}
-
 /////// Path Geometry ///////
 
 FillPathGeometry::FillPathGeometry(const Path& path) : path_(path) {}
diff --git a/impeller/entity/geometry.h b/impeller/entity/geometry.h
index 99780f2..dabab1d 100644
--- a/impeller/entity/geometry.h
+++ b/impeller/entity/geometry.h
@@ -9,7 +9,6 @@
 #include "impeller/entity/solid_fill.vert.h"
 #include "impeller/geometry/color.h"
 #include "impeller/geometry/path.h"
-#include "impeller/geometry/vertices.h"
 #include "impeller/renderer/allocator.h"
 #include "impeller/renderer/host_buffer.h"
 #include "impeller/renderer/vertex_buffer.h"
@@ -43,17 +42,12 @@
   kBevel,
 };
 
-class VerticesGeometry;
-
 class Geometry {
  public:
   Geometry();
 
   virtual ~Geometry();
 
-  static std::unique_ptr<VerticesGeometry> MakeVertices(
-      const Vertices& vertices);
-
   static std::unique_ptr<Geometry> MakeFillPath(const Path& path);
 
   static std::unique_ptr<Geometry> MakeStrokePath(
@@ -79,35 +73,15 @@
 /// @brief A geometry that is created from a vertices object.
 class VerticesGeometry : public Geometry {
  public:
-  explicit VerticesGeometry(const Vertices& vertices);
+  virtual GeometryResult GetPositionColorBuffer(const ContentContext& renderer,
+                                                const Entity& entity,
+                                                RenderPass& pass,
+                                                Color paint_color,
+                                                BlendMode blend_mode) = 0;
 
-  ~VerticesGeometry();
-
-  GeometryResult GetPositionColorBuffer(const ContentContext& renderer,
-                                        const Entity& entity,
-                                        RenderPass& pass,
-                                        Color paint_color,
-                                        BlendMode blend_mode);
-
-  GeometryResult GetPositionUVBuffer(const ContentContext& renderer,
-                                     const Entity& entity,
-                                     RenderPass& pass);
-
-  // |Geometry|
-  GeometryResult GetPositionBuffer(const ContentContext& renderer,
-                                   const Entity& entity,
-                                   RenderPass& pass) override;
-
-  // |Geometry|
-  std::optional<Rect> GetCoverage(const Matrix& transform) const override;
-
-  // |Geometry|
-  GeometryVertexType GetVertexType() const override;
-
- private:
-  Vertices vertices_;
-
-  FML_DISALLOW_COPY_AND_ASSIGN(VerticesGeometry);
+  virtual GeometryResult GetPositionUVBuffer(const ContentContext& renderer,
+                                             const Entity& entity,
+                                             RenderPass& pass) = 0;
 };
 
 /// @brief A geometry that is created from a filled path object.
diff --git a/impeller/geometry/BUILD.gn b/impeller/geometry/BUILD.gn
index e8d5189..a1b511c 100644
--- a/impeller/geometry/BUILD.gn
+++ b/impeller/geometry/BUILD.gn
@@ -39,8 +39,6 @@
     "type_traits.h",
     "vector.cc",
     "vector.h",
-    "vertices.cc",
-    "vertices.h",
   ]
 
   deps = [ "//flutter/fml" ]
diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc
index 0292ffa..72d09f1 100644
--- a/impeller/geometry/geometry_unittests.cc
+++ b/impeller/geometry/geometry_unittests.cc
@@ -1646,21 +1646,6 @@
   ASSERT_EQ(polyline.points[6], Point(0, 100));
 }
 
-TEST(GeometryTest, VerticesConstructorAndGetters) {
-  std::vector<Point> points = {Point(1, 2), Point(2, 3), Point(3, 4)};
-  std::vector<uint16_t> indices = {0, 1, 2};
-  std::vector<Color> colors = {Color::White(), Color::White(), Color::White()};
-
-  Vertices vertices = Vertices(points, indices, colors, VertexMode::kTriangle,
-                               Rect(0, 0, 4, 4));
-
-  ASSERT_EQ(vertices.GetBoundingBox().value(), Rect(0, 0, 4, 4));
-  ASSERT_EQ(vertices.GetPositions(), points);
-  ASSERT_EQ(vertices.GetIndices(), indices);
-  ASSERT_EQ(vertices.GetColors(), colors);
-  ASSERT_EQ(vertices.GetMode(), VertexMode::kTriangle);
-}
-
 TEST(GeometryTest, MatrixPrinting) {
   {
     std::stringstream stream;
diff --git a/impeller/geometry/geometry_unittests.h b/impeller/geometry/geometry_unittests.h
index 84d9602..d2c63fc 100644
--- a/impeller/geometry/geometry_unittests.h
+++ b/impeller/geometry/geometry_unittests.h
@@ -11,7 +11,6 @@
 #include "impeller/geometry/rect.h"
 #include "impeller/geometry/size.h"
 #include "impeller/geometry/vector.h"
-#include "impeller/geometry/vertices.h"
 
 inline bool NumberNear(double a, double b) {
   static const double epsilon = 1e-3;
diff --git a/impeller/geometry/vertices.cc b/impeller/geometry/vertices.cc
deleted file mode 100644
index a93c7c2..0000000
--- a/impeller/geometry/vertices.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "vertices.h"
-
-namespace impeller {
-
-Vertices::Vertices(std::vector<Point> points,
-                   std::vector<uint16_t> indices,
-                   std::vector<Color> colors,
-                   VertexMode vertex_mode,
-                   Rect bounds)
-    : positions_(std::move(points)),
-      indices_(std::move(indices)),
-      colors_(std::move(colors)),
-      vertex_mode_(vertex_mode),
-      bounds_(bounds) {
-  NormalizeIndices();
-}
-
-Vertices::~Vertices() = default;
-
-bool Vertices::IsValid() const {
-  size_t points_size = positions_.size();
-  size_t colors_size = colors_.size();
-
-  if (colors_size > 0 && colors_size != points_size) {
-    return false;
-  }
-
-  return true;
-}
-
-std::optional<Rect> Vertices::GetBoundingBox() const {
-  return bounds_;
-};
-
-std::optional<Rect> Vertices::GetTransformedBoundingBox(
-    const Matrix& transform) const {
-  auto bounds = GetBoundingBox();
-  if (!bounds.has_value()) {
-    return std::nullopt;
-  }
-  return bounds->TransformBounds(transform);
-};
-
-const std::vector<Point>& Vertices::GetPositions() const {
-  return positions_;
-}
-
-const std::vector<uint16_t>& Vertices::GetIndices() const {
-  return indices_;
-}
-
-const std::vector<Color>& Vertices::GetColors() const {
-  return colors_;
-}
-
-VertexMode Vertices::GetMode() const {
-  return vertex_mode_;
-}
-
-void Vertices::NormalizeIndices() {
-  if (indices_.size() != 0 || positions_.size() == 0) {
-    return;
-  }
-  for (size_t i = 0; i < positions_.size(); i++) {
-    indices_.push_back(i);
-  }
-}
-
-}  // namespace impeller
diff --git a/impeller/geometry/vertices.h b/impeller/geometry/vertices.h
deleted file mode 100644
index b642a8d..0000000
--- a/impeller/geometry/vertices.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#pragma once
-
-#include <optional>
-#include <vector>
-
-#include "impeller/geometry/color.h"
-#include "impeller/geometry/point.h"
-#include "impeller/geometry/rect.h"
-
-namespace impeller {
-
-enum class VertexMode {
-  kTriangle,
-  kTriangleStrip,
-};
-
-class Vertices {
- public:
-  Vertices(std::vector<Point> positions,
-           std::vector<uint16_t> indices,
-           std::vector<Color> colors,
-           VertexMode vertex_mode,
-           Rect bounds);
-
-  ~Vertices();
-
-  bool IsValid() const;
-
-  std::optional<Rect> GetBoundingBox() const;
-
-  std::optional<Rect> GetTransformedBoundingBox(const Matrix& transform) const;
-
-  const std::vector<Point>& GetPositions() const;
-
-  const std::vector<uint16_t>& GetIndices() const;
-
-  const std::vector<Color>& GetColors() const;
-
-  VertexMode GetMode() const;
-
- private:
-  std::vector<Point> positions_;
-  std::vector<uint16_t> indices_;
-  std::vector<Color> colors_;
-  VertexMode vertex_mode_;
-  Rect bounds_;
-
-  void NormalizeIndices();
-};
-
-}  // namespace impeller