[Impeller] basic outline of geometry classes + vertices (#36649)

diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index c3264a2..c6e7b4f 100644
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -1233,6 +1233,8 @@
 FILE: ../../../flutter/impeller/entity/entity_playground.cc
 FILE: ../../../flutter/impeller/entity/entity_playground.h
 FILE: ../../../flutter/impeller/entity/entity_unittests.cc
+FILE: ../../../flutter/impeller/entity/geometry.cc
+FILE: ../../../flutter/impeller/entity/geometry.h
 FILE: ../../../flutter/impeller/entity/inline_pass_context.cc
 FILE: ../../../flutter/impeller/entity/inline_pass_context.h
 FILE: ../../../flutter/impeller/entity/shaders/atlas_fill.frag
@@ -1272,6 +1274,9 @@
 FILE: ../../../flutter/impeller/entity/shaders/linear_to_srgb_filter.vert
 FILE: ../../../flutter/impeller/entity/shaders/morphology_filter.frag
 FILE: ../../../flutter/impeller/entity/shaders/morphology_filter.vert
+FILE: ../../../flutter/impeller/entity/shaders/position.vert
+FILE: ../../../flutter/impeller/entity/shaders/position_color.vert
+FILE: ../../../flutter/impeller/entity/shaders/position_uv.vert
 FILE: ../../../flutter/impeller/entity/shaders/radial_gradient_fill.frag
 FILE: ../../../flutter/impeller/entity/shaders/rrect_blur.frag
 FILE: ../../../flutter/impeller/entity/shaders/rrect_blur.vert
@@ -1287,7 +1292,6 @@
 FILE: ../../../flutter/impeller/entity/shaders/tiled_texture_fill.frag
 FILE: ../../../flutter/impeller/entity/shaders/tiled_texture_fill.vert
 FILE: ../../../flutter/impeller/entity/shaders/vertices.frag
-FILE: ../../../flutter/impeller/entity/shaders/vertices.vert
 FILE: ../../../flutter/impeller/geometry/color.cc
 FILE: ../../../flutter/impeller/geometry/color.h
 FILE: ../../../flutter/impeller/geometry/constants.cc
diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc
index a767649..2c42a17 100644
--- a/impeller/aiks/canvas.cc
+++ b/impeller/aiks/canvas.cc
@@ -15,6 +15,7 @@
 #include "impeller/entity/contents/text_contents.h"
 #include "impeller/entity/contents/texture_contents.h"
 #include "impeller/entity/contents/vertices_contents.h"
+#include "impeller/entity/geometry.h"
 #include "impeller/geometry/path_builder.h"
 #include "impeller/geometry/vertices.h"
 
@@ -355,9 +356,10 @@
                           BlendMode blend_mode,
                           Paint paint) {
   std::shared_ptr<VerticesContents> contents =
-      std::make_shared<VerticesContents>(std::move(vertices));
+      std::make_shared<VerticesContents>();
   contents->SetColor(paint.color);
   contents->SetBlendMode(blend_mode);
+  contents->SetGeometry(Geometry::MakeVertices(std::move(vertices)));
   Entity entity;
   entity.SetTransformation(GetCurrentTransformation());
   entity.SetStencilDepth(GetStencilDepth());
diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn
index 0add8e8..3003b96 100644
--- a/impeller/entity/BUILD.gn
+++ b/impeller/entity/BUILD.gn
@@ -59,7 +59,9 @@
     "shaders/tiled_texture_fill.frag",
     "shaders/tiled_texture_fill.vert",
     "shaders/vertices.frag",
-    "shaders/vertices.vert",
+    "shaders/position_color.vert",
+    "shaders/position.vert",
+    "shaders/position_uv.vert",
   ]
 }
 
@@ -133,6 +135,8 @@
     "entity_pass.h",
     "entity_pass_delegate.cc",
     "entity_pass_delegate.h",
+    "geometry.cc",
+    "geometry.h",
     "inline_pass_context.cc",
     "inline_pass_context.h",
   ]
diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc
index adc57b7..c713e91 100644
--- a/impeller/entity/contents/content_context.cc
+++ b/impeller/entity/contents/content_context.cc
@@ -211,7 +211,10 @@
       CreateDefaultPipeline<GlyphAtlasPipeline>(*context_);
   glyph_atlas_sdf_pipelines_[{}] =
       CreateDefaultPipeline<GlyphAtlasSdfPipeline>(*context_);
-  vertices_pipelines_[{}] = CreateDefaultPipeline<VerticesPipeline>(*context_);
+  geometry_color_pipelines_[{}] =
+      CreateDefaultPipeline<GeometryColorPipeline>(*context_);
+  geometry_position_pipelines_[{}] =
+      CreateDefaultPipeline<GeometryPositionPipeline>(*context_);
   atlas_pipelines_[{}] = CreateDefaultPipeline<AtlasPipeline>(*context_);
 
   // Pipelines that are variants of the base pipelines with custom descriptors.
diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h
index ce96fde..5a38cdb 100644
--- a/impeller/entity/contents/content_context.h
+++ b/impeller/entity/contents/content_context.h
@@ -63,10 +63,13 @@
 #include "impeller/entity/tiled_texture_fill.frag.h"
 #include "impeller/entity/tiled_texture_fill.vert.h"
 #include "impeller/entity/vertices.frag.h"
-#include "impeller/entity/vertices.vert.h"
 #include "impeller/renderer/formats.h"
 #include "impeller/renderer/pipeline.h"
 
+#include "impeller/entity/position.vert.h"
+#include "impeller/entity/position_color.vert.h"
+#include "impeller/entity/position_uv.vert.h"
+
 namespace impeller {
 
 using LinearGradientFillPipeline =
@@ -148,8 +151,6 @@
     RenderPipelineT<GlyphAtlasVertexShader, GlyphAtlasFragmentShader>;
 using GlyphAtlasSdfPipeline =
     RenderPipelineT<GlyphAtlasSdfVertexShader, GlyphAtlasSdfFragmentShader>;
-using VerticesPipeline =
-    RenderPipelineT<VerticesVertexShader, VerticesFragmentShader>;
 using AtlasPipeline =
     RenderPipelineT<AtlasFillVertexShader, AtlasFillFragmentShader>;
 // Instead of requiring new shaders for clips, the solid fill stages are used
@@ -157,6 +158,11 @@
 using ClipPipeline =
     RenderPipelineT<SolidFillVertexShader, SolidFillFragmentShader>;
 
+using GeometryPositionPipeline =
+    RenderPipelineT<PositionVertexShader, VerticesFragmentShader>;
+using GeometryColorPipeline =
+    RenderPipelineT<PositionColorVertexShader, VerticesFragmentShader>;
+
 struct ContentContextOptions {
   SampleCount sample_count = SampleCount::kCount1;
   BlendMode blend_mode = BlendMode::kSourceOver;
@@ -285,9 +291,14 @@
     return GetPipeline(glyph_atlas_sdf_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetVerticesPipeline(
+  std::shared_ptr<Pipeline<PipelineDescriptor>> GetGeometryColorPipeline(
       ContentContextOptions opts) const {
-    return GetPipeline(vertices_pipelines_, opts);
+    return GetPipeline(geometry_color_pipelines_, opts);
+  }
+
+  std::shared_ptr<Pipeline<PipelineDescriptor>> GetGeometryPositionPipeline(
+      ContentContextOptions opts) const {
+    return GetPipeline(geometry_position_pipelines_, opts);
   }
 
   std::shared_ptr<Pipeline<PipelineDescriptor>> GetAtlasPipeline(
@@ -413,8 +424,9 @@
   mutable Variants<ClipPipeline> clip_pipelines_;
   mutable Variants<GlyphAtlasPipeline> glyph_atlas_pipelines_;
   mutable Variants<GlyphAtlasSdfPipeline> glyph_atlas_sdf_pipelines_;
-  mutable Variants<VerticesPipeline> vertices_pipelines_;
   mutable Variants<AtlasPipeline> atlas_pipelines_;
+  mutable Variants<GeometryPositionPipeline> geometry_position_pipelines_;
+  mutable Variants<GeometryColorPipeline> geometry_color_pipelines_;
   // Advanced blends.
   mutable Variants<BlendColorPipeline> blend_color_pipelines_;
   mutable Variants<BlendColorBurnPipeline> blend_colorburn_pipelines_;
diff --git a/impeller/entity/contents/vertices_contents.cc b/impeller/entity/contents/vertices_contents.cc
index 4ab78afbe..d5a4bac 100644
--- a/impeller/entity/contents/vertices_contents.cc
+++ b/impeller/entity/contents/vertices_contents.cc
@@ -5,8 +5,10 @@
 #include "vertices_contents.h"
 
 #include "impeller/entity/contents/content_context.h"
+#include "impeller/entity/position.vert.h"
+#include "impeller/entity/position_color.vert.h"
+#include "impeller/entity/position_uv.vert.h"
 #include "impeller/entity/vertices.frag.h"
-#include "impeller/entity/vertices.vert.h"
 #include "impeller/geometry/color.h"
 #include "impeller/renderer/formats.h"
 #include "impeller/renderer/render_pass.h"
@@ -15,15 +17,18 @@
 
 namespace impeller {
 
-VerticesContents::VerticesContents(Vertices vertices)
-    : vertices_(std::move(vertices)){};
+VerticesContents::VerticesContents() = default;
 
 VerticesContents::~VerticesContents() = default;
 
 std::optional<Rect> VerticesContents::GetCoverage(const Entity& entity) const {
-  return vertices_.GetTransformedBoundingBox(entity.GetTransformation());
+  return geometry_->GetCoverage(entity.GetTransformation());
 };
 
+void VerticesContents::SetGeometry(std::unique_ptr<Geometry> geometry) {
+  geometry_ = std::move(geometry);
+}
+
 void VerticesContents::SetColor(Color color) {
   color_ = color.Premultiply();
 }
@@ -32,88 +37,54 @@
   blend_mode_ = blend_mode;
 }
 
-static PrimitiveType GetPrimitiveType(const Vertices& vertices) {
-  switch (vertices.GetMode()) {
-    case VertexMode::kTriangle:
-      return PrimitiveType::kTriangle;
-    case VertexMode::kTriangleStrip:
-      return PrimitiveType::kTriangleStrip;
-  }
-}
-
 bool VerticesContents::Render(const ContentContext& renderer,
                               const Entity& entity,
                               RenderPass& pass) const {
-  if (!vertices_.IsValid()) {
-    return true;
-  }
-
-  using VS = VerticesPipeline::VertexShader;
-
-  const auto coverage_rect = vertices_.GetBoundingBox();
-
-  if (!coverage_rect.has_value()) {
-    return true;
-  }
-
-  if (coverage_rect->size.IsEmpty()) {
-    return true;
-  }
-
-  std::vector<VS::PerVertexData> vertex_data;
-  {
-    const auto& positions = vertices_.GetPositions();
-    const auto& colors = vertices_.GetColors();
-    for (size_t i = 0; i < positions.size(); i++) {
-      auto color = i < colors.size()
-                       ? Color::BlendColor(color_, colors[i], blend_mode_)
-                       : color_;
-      vertex_data.push_back(VS::PerVertexData{
-          .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 false;
-  }
-  if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(const_cast<uint16_t*>(
-                                  vertices_.GetIndices().data())),
-                              Range{0, total_idx_bytes}, total_vtx_bytes)) {
-    return false;
-  }
-
   auto& host_buffer = pass.GetTransientsBuffer();
+  auto allocator = renderer.GetContext()->GetResourceAllocator();
+  auto vertex_type = geometry_->GetVertexType();
 
-  VS::FrameInfo frame_info;
-  frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
-                   entity.GetTransformation();
   Command cmd;
   cmd.label = "Vertices";
-  cmd.pipeline =
-      renderer.GetVerticesPipeline(OptionsFromPassAndEntity(pass, entity));
   cmd.stencil_reference = entity.GetStencilDepth();
-  cmd.primitive_type = GetPrimitiveType(vertices_);
-  cmd.BindVertices({
-      .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,
-  });
-  VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
+
+  switch (vertex_type) {
+    case GeometryVertexType::kColor: {
+      using VS = GeometryColorPipeline::VertexShader;
+
+      auto geometry_result = geometry_->GetPositionColorBuffer(
+          allocator, host_buffer, color_, blend_mode_);
+      cmd.pipeline = renderer.GetGeometryColorPipeline(
+          OptionsFromPassAndEntity(pass, entity));
+      cmd.primitive_type = geometry_result.type;
+      cmd.BindVertices(geometry_result.vertex_buffer);
+
+      VS::VertInfo vert_info;
+      vert_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
+                      entity.GetTransformation();
+      VS::BindVertInfo(cmd, host_buffer.EmplaceUniform(vert_info));
+      break;
+    }
+    case GeometryVertexType::kUV:
+    case GeometryVertexType::kPosition: {
+      using VS = GeometryPositionPipeline::VertexShader;
+
+      auto geometry_result =
+          geometry_->GetPositionBuffer(allocator, host_buffer);
+      cmd.pipeline = renderer.GetGeometryPositionPipeline(
+          OptionsFromPassAndEntity(pass, entity));
+      cmd.primitive_type = geometry_result.type;
+      cmd.BindVertices(geometry_result.vertex_buffer);
+
+      VS::VertInfo vert_info;
+      vert_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
+                      entity.GetTransformation();
+      vert_info.color = color_.Premultiply();
+      VS::BindVertInfo(cmd,
+                       pass.GetTransientsBuffer().EmplaceUniform(vert_info));
+      break;
+    }
+  }
   pass.AddCommand(std::move(cmd));
 
   return true;
diff --git a/impeller/entity/contents/vertices_contents.h b/impeller/entity/contents/vertices_contents.h
index ae8637f..1912141 100644
--- a/impeller/entity/contents/vertices_contents.h
+++ b/impeller/entity/contents/vertices_contents.h
@@ -11,6 +11,7 @@
 #include "flutter/fml/macros.h"
 #include "impeller/entity/contents/contents.h"
 #include "impeller/entity/entity.h"
+#include "impeller/entity/geometry.h"
 #include "impeller/geometry/color.h"
 #include "impeller/geometry/path.h"
 #include "impeller/geometry/point.h"
@@ -21,10 +22,12 @@
 
 class VerticesContents final : public Contents {
  public:
-  explicit VerticesContents(Vertices vertices);
+  VerticesContents();
 
   ~VerticesContents() override;
 
+  void SetGeometry(std::unique_ptr<Geometry> geometry);
+
   void SetColor(Color color);
 
   void SetBlendMode(BlendMode blend_mode);
@@ -38,8 +41,8 @@
               RenderPass& pass) const override;
 
  public:
-  Vertices vertices_;
   Color color_;
+  std::unique_ptr<Geometry> geometry_;
   BlendMode blend_mode_ = BlendMode::kSource;
 
   FML_DISALLOW_COPY_AND_ASSIGN(VerticesContents);
diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc
index 10aab60..58dc2a3 100644
--- a/impeller/entity/entity_unittests.cc
+++ b/impeller/entity/entity_unittests.cc
@@ -27,6 +27,7 @@
 #include "impeller/entity/entity_pass.h"
 #include "impeller/entity/entity_pass_delegate.h"
 #include "impeller/entity/entity_playground.h"
+#include "impeller/entity/geometry.h"
 #include "impeller/geometry/color.h"
 #include "impeller/geometry/geometry_unittests.h"
 #include "impeller/geometry/path_builder.h"
@@ -1218,7 +1219,8 @@
                                VertexMode::kTriangle, Rect(100, 100, 300, 300));
 
   std::shared_ptr<VerticesContents> contents =
-      std::make_shared<VerticesContents>(vertices);
+      std::make_shared<VerticesContents>();
+  contents->SetGeometry(Geometry::MakeVertices(vertices));
   contents->SetBlendMode(BlendMode::kSourceOver);
   contents->SetColor(Color::Red().WithAlpha(0.5));
 
@@ -1238,7 +1240,8 @@
                                VertexMode::kTriangle, Rect(100, 100, 300, 300));
 
   std::shared_ptr<VerticesContents> contents =
-      std::make_shared<VerticesContents>(vertices);
+      std::make_shared<VerticesContents>();
+  contents->SetGeometry(Geometry::MakeVertices(vertices));
   contents->SetColor(Color::White());
   Entity e;
   e.SetTransformation(Matrix::MakeScale(GetContentScale()));
diff --git a/impeller/entity/geometry.cc b/impeller/entity/geometry.cc
new file mode 100644
index 0000000..73776c6
--- /dev/null
+++ b/impeller/entity/geometry.cc
@@ -0,0 +1,159 @@
+// 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/entity/geometry.h"
+#include "impeller/entity/contents/content_context.h"
+#include "impeller/entity/position_color.vert.h"
+#include "impeller/renderer/device_buffer.h"
+
+namespace impeller {
+
+Geometry::Geometry() = default;
+
+Geometry::~Geometry() = default;
+
+// static
+std::unique_ptr<Geometry> Geometry::MakeVertices(Vertices vertices) {
+  return std::make_unique<VerticesGeometry>(std::move(vertices));
+}
+
+VerticesGeometry::VerticesGeometry(Vertices vertices)
+    : vertices_(std::move(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(
+    std::shared_ptr<Allocator> device_allocator,
+    HostBuffer& host_buffer) {
+  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 = device_allocator->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,
+          },
+      .prevent_overdraw = false,
+  };
+}
+
+GeometryResult VerticesGeometry::GetPositionColorBuffer(
+    std::shared_ptr<Allocator> device_allocator,
+    HostBuffer& host_buffer,
+    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 = device_allocator->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,
+          },
+      .prevent_overdraw = false,
+  };
+}
+
+GeometryResult VerticesGeometry::GetPositionUVBuffer(
+    std::shared_ptr<Allocator> device_allocator,
+    HostBuffer& host_buffer,
+    ISize render_target_size) {
+  // TODO(jonahwilliams): support texture coordinates in vertices.
+  return {};
+}
+
+GeometryVertexType VerticesGeometry::GetVertexType() {
+  if (vertices_.GetColors().size()) {
+    return GeometryVertexType::kColor;
+  }
+  return GeometryVertexType::kPosition;
+}
+
+std::optional<Rect> VerticesGeometry::GetCoverage(Matrix transform) {
+  return vertices_.GetTransformedBoundingBox(transform);
+}
+
+}  // namespace impeller
diff --git a/impeller/entity/geometry.h b/impeller/entity/geometry.h
new file mode 100644
index 0000000..a6f63d9
--- /dev/null
+++ b/impeller/entity/geometry.h
@@ -0,0 +1,91 @@
+// 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 "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"
+
+namespace impeller {
+
+struct GeometryResult {
+  PrimitiveType type;
+  VertexBuffer vertex_buffer;
+  bool prevent_overdraw;
+};
+
+enum GeometryVertexType {
+  kPosition,
+  kColor,
+  kUV,
+};
+
+class Geometry {
+ public:
+  Geometry();
+
+  virtual ~Geometry();
+
+  static std::unique_ptr<Geometry> MakeVertices(Vertices vertices);
+
+  virtual GeometryResult GetPositionBuffer(
+      std::shared_ptr<Allocator> device_allocator,
+      HostBuffer& host_buffer) = 0;
+
+  virtual GeometryResult GetPositionColorBuffer(
+      std::shared_ptr<Allocator> device_allocator,
+      HostBuffer& host_buffer,
+      Color paint_color,
+      BlendMode blend_mode) = 0;
+
+  virtual GeometryResult GetPositionUVBuffer(
+      std::shared_ptr<Allocator> device_allocator,
+      HostBuffer& host_buffer,
+      ISize render_target_size) = 0;
+
+  virtual GeometryVertexType GetVertexType() = 0;
+
+  virtual std::optional<Rect> GetCoverage(Matrix transform) = 0;
+};
+
+class VerticesGeometry : public Geometry {
+ public:
+  VerticesGeometry(Vertices vertices);
+
+  ~VerticesGeometry();
+
+ private:
+  // |Geometry|
+  GeometryResult GetPositionBuffer(std::shared_ptr<Allocator> device_allocator,
+                                   HostBuffer& host_buffer) override;
+
+  // |Geometry|
+  GeometryResult GetPositionColorBuffer(
+      std::shared_ptr<Allocator> device_allocator,
+      HostBuffer& host_buffer,
+      Color paint_color,
+      BlendMode blend_mode) override;
+
+  // |Geometry|
+  GeometryResult GetPositionUVBuffer(
+      std::shared_ptr<Allocator> device_allocator,
+      HostBuffer& host_buffer,
+      ISize render_target_size) override;
+
+  // |Geometry|
+  GeometryVertexType GetVertexType() override;
+
+  // |Geometry|
+  std::optional<Rect> GetCoverage(Matrix transform) override;
+
+  Vertices vertices_;
+
+  FML_DISALLOW_COPY_AND_ASSIGN(VerticesGeometry);
+};
+
+}  // namespace impeller
diff --git a/impeller/entity/shaders/position.vert b/impeller/entity/shaders/position.vert
new file mode 100644
index 0000000..9b1c5c7
--- /dev/null
+++ b/impeller/entity/shaders/position.vert
@@ -0,0 +1,21 @@
+// 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/transform.glsl>
+
+uniform VertInfo {
+  mat4 mvp;
+  vec4 color;
+} vert_info;
+
+in vec2 position;
+
+out vec4 v_color;
+out vec2 v_position;
+
+void main() {
+  gl_Position = vert_info.mvp * vec4(position, 0.0, 1.0);
+  v_color = vert_info.color;
+  v_position = IPVec2TransformPosition(vert_info.mvp, position);
+}
diff --git a/impeller/entity/shaders/position_color.vert b/impeller/entity/shaders/position_color.vert
new file mode 100644
index 0000000..88b19f6
--- /dev/null
+++ b/impeller/entity/shaders/position_color.vert
@@ -0,0 +1,21 @@
+// 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/transform.glsl>
+
+uniform VertInfo {
+  mat4 mvp;
+} vert_info;
+
+in vec2 position;
+in vec4 color;
+
+out vec4 v_color;
+out vec2 v_position;
+
+void main() {
+  gl_Position = vert_info.mvp * vec4(position, 0.0, 1.0);
+  v_color = color;
+  v_position = IPVec2TransformPosition(vert_info.mvp, position);
+}
diff --git a/impeller/entity/shaders/position_uv.vert b/impeller/entity/shaders/position_uv.vert
new file mode 100644
index 0000000..cb8850b
--- /dev/null
+++ b/impeller/entity/shaders/position_uv.vert
@@ -0,0 +1,21 @@
+// 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/transform.glsl>
+
+uniform VertInfo {
+  mat4 mvp;
+} vert_info;
+
+in vec2 position;
+in vec2 uv;
+
+out vec2 v_uv;
+out vec2 v_position;
+
+void main() {
+  gl_Position = vert_info.mvp * vec4(position, 0.0, 1.0);
+  v_uv = uv;
+  v_position = IPVec2TransformPosition(vert_info.mvp, position);
+}
diff --git a/impeller/entity/shaders/vertices.vert b/impeller/entity/shaders/vertices.vert
deleted file mode 100644
index 7923be81..0000000
--- a/impeller/entity/shaders/vertices.vert
+++ /dev/null
@@ -1,17 +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.
-
-uniform FrameInfo {
-  mat4 mvp;
-} frame_info;
-
-in vec2 position;
-in vec4 color;
-
-out vec4 v_color;
-
-void main() {
-  gl_Position = frame_info.mvp * vec4(position, 0.0, 1.0);
-  v_color = color;
-}