Flutter Impeller
dl_vertices_geometry.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
6 
7 #include "display_list/dl_vertices.h"
11 #include "third_party/skia/include/core/SkPoint.h"
12 
13 namespace impeller {
14 
15 namespace {
16 
17 // Fan mode isn't natively supported on Metal backends. Unroll into triangle
18 // mode by manipulating the index array.
19 //
20 // In Triangle fan, the first vertex is shared across all triangles, and then
21 // each sliding window of two vertices plus that first vertex defines a
22 // triangle.
23 static std::vector<uint16_t> fromFanIndices(size_t vertex_count,
24  size_t index_count,
25  const uint16_t* indices) {
26  std::vector<uint16_t> unrolled_indices;
27 
28  // Un-fan index buffer if provided.
29  if (index_count > 0u) {
30  if (index_count < 3u) {
31  return {};
32  }
33 
34  auto center_point = indices[0];
35  for (auto i = 1u; i < index_count - 1; i++) {
36  unrolled_indices.push_back(center_point);
37  unrolled_indices.push_back(indices[i]);
38  unrolled_indices.push_back(indices[i + 1]);
39  }
40  } else {
41  if (vertex_count < 3u) {
42  return {};
43  }
44 
45  // If indices were not provided, create an index buffer that unfans
46  // triangles instead of re-writing points, colors, et cetera.
47  for (auto i = 1u; i < vertex_count - 1; i++) {
48  unrolled_indices.push_back(0);
49  unrolled_indices.push_back(i);
50  unrolled_indices.push_back(i + 1);
51  }
52  }
53  return unrolled_indices;
54 }
55 
56 } // namespace
57 
58 /////// Vertices Geometry ///////
59 
61  const std::shared_ptr<const flutter::DlVertices>& vertices,
62  const ContentContext& renderer)
63  : vertices_(vertices) {
64  performed_normalization_ = MaybePerformIndexNormalization(renderer);
65  bounds_ = skia_conversions::ToRect(vertices_->bounds());
66 }
67 
68 PrimitiveType DlVerticesGeometry::GetPrimitiveType() const {
69  switch (vertices_->mode()) {
70  case flutter::DlVertexMode::kTriangleFan:
71  // Unrolled into triangle mode.
72  if (performed_normalization_) {
74  }
76  case flutter::DlVertexMode::kTriangleStrip:
78  case flutter::DlVertexMode::kTriangles:
80  }
81 }
82 
84  return vertices_->colors() != nullptr;
85 }
86 
88  return vertices_->texture_coordinates() != nullptr;
89 }
90 
92  if (!HasTextureCoordinates()) {
93  return std::nullopt;
94  }
95  auto vertex_count = vertices_->vertex_count();
96  if (vertex_count == 0) {
97  return std::nullopt;
98  }
99 
100  auto first = vertices_->texture_coordinates();
101  auto left = first->x();
102  auto top = first->y();
103  auto right = first->x();
104  auto bottom = first->y();
105  int i = 1;
106  for (auto it = first + 1; i < vertex_count; ++it, i++) {
107  left = std::min(left, it->x());
108  top = std::min(top, it->y());
109  right = std::max(right, it->x());
110  bottom = std::max(bottom, it->y());
111  }
112  return Rect::MakeLTRB(left, top, right, bottom);
113 }
114 
116  const ContentContext& renderer,
117  const Entity& entity,
118  RenderPass& pass) const {
119  int vertex_count = vertices_->vertex_count();
120  BufferView vertex_buffer = renderer.GetTransientsBuffer().Emplace(
121  vertices_->vertices(), vertex_count * sizeof(SkPoint), alignof(SkPoint));
122 
123  BufferView index_buffer = {};
124  auto index_count =
125  performed_normalization_ ? indices_.size() : vertices_->index_count();
126  const uint16_t* indices_data =
127  performed_normalization_ ? indices_.data() : vertices_->indices();
128  if (index_count) {
129  index_buffer = renderer.GetTransientsBuffer().Emplace(
130  indices_data, index_count * sizeof(uint16_t), alignof(uint16_t));
131  }
132 
133  return GeometryResult{
134  .type = GetPrimitiveType(),
135  .vertex_buffer =
136  {
137  .vertex_buffer = vertex_buffer,
138  .index_buffer = index_buffer,
139  .vertex_count = index_count > 0 ? index_count : vertex_count,
140  .index_type =
141  index_count > 0 ? IndexType::k16bit : IndexType::kNone,
142  },
143  .transform = entity.GetShaderTransform(pass),
144  };
145 }
146 
148  Rect texture_coverage,
149  Matrix effect_transform,
150  const ContentContext& renderer,
151  const Entity& entity,
152  RenderPass& pass) const {
154 
155  int vertex_count = vertices_->vertex_count();
156  Matrix uv_transform =
157  texture_coverage.GetNormalizingTransform() * effect_transform;
158  bool has_texture_coordinates = HasTextureCoordinates();
159  bool has_colors = HasVertexColors();
160 
161  const SkPoint* coordinates = has_texture_coordinates
162  ? vertices_->texture_coordinates()
163  : vertices_->vertices();
164  BufferView vertex_buffer = renderer.GetTransientsBuffer().Emplace(
165  vertex_count * sizeof(VS::PerVertexData), alignof(VS::PerVertexData),
166  [&](uint8_t* data) {
167  VS::PerVertexData* vtx_contents =
168  reinterpret_cast<VS::PerVertexData*>(data);
169  for (auto i = 0; i < vertex_count; i++) {
170  Point texture_coord = skia_conversions::ToPoint(coordinates[i]);
171  Point uv = uv_transform * texture_coord;
172  Color color = has_colors
173  ? skia_conversions::ToColor(vertices_->colors()[i])
174  .Premultiply()
176  VS::PerVertexData vertex_data = {
177  .vertices = skia_conversions::ToPoint(vertices_->vertices()[i]),
178  .texture_coords = uv,
179  .color = color};
180  vtx_contents[i] = vertex_data;
181  }
182  });
183 
184  BufferView index_buffer = {};
185  auto index_count =
186  performed_normalization_ ? indices_.size() : vertices_->index_count();
187  const uint16_t* indices_data =
188  performed_normalization_ ? indices_.data() : vertices_->indices();
189  if (index_count) {
190  index_buffer = renderer.GetTransientsBuffer().Emplace(
191  indices_data, index_count * sizeof(uint16_t), alignof(uint16_t));
192  }
193 
194  return GeometryResult{
195  .type = GetPrimitiveType(),
196  .vertex_buffer =
197  {
198  .vertex_buffer = vertex_buffer,
199  .index_buffer = index_buffer,
200  .vertex_count = index_count > 0 ? index_count : vertex_count,
201  .index_type =
202  index_count > 0 ? IndexType::k16bit : IndexType::kNone,
203  },
204  .transform = entity.GetShaderTransform(pass),
205  };
206 }
207 
209  const Matrix& transform) const {
210  return bounds_.TransformBounds(transform);
211 }
212 
213 bool DlVerticesGeometry::MaybePerformIndexNormalization(
214  const ContentContext& renderer) {
215  if (vertices_->mode() == flutter::DlVertexMode::kTriangleFan &&
217  indices_ = fromFanIndices(vertices_->vertex_count(),
218  vertices_->index_count(), vertices_->indices());
219  return true;
220  }
221  return false;
222 }
223 
224 } // namespace impeller
impeller::Entity::GetShaderTransform
Matrix GetShaderTransform(const RenderPass &pass) const
Get the vertex shader transform used for drawing this Entity.
Definition: entity.cc:51
impeller::HostBuffer::Emplace
BufferView Emplace(const BufferType &buffer, size_t alignment=0)
Emplace non-uniform data (like contiguous vertices) onto the host buffer.
Definition: host_buffer.h:95
point.h
impeller::IndexType::k16bit
@ k16bit
impeller::Color
Definition: color.h:123
data
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
impeller::TRect::TransformBounds
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
Definition: rect.h:466
impeller::TRect::GetNormalizingTransform
constexpr Matrix GetNormalizingTransform() const
Constructs a Matrix that will map all points in the coordinate space of the rectangle into a new norm...
Definition: rect.h:485
formats.h
impeller::DlVerticesGeometry::HasVertexColors
bool HasVertexColors() const override
Definition: dl_vertices_geometry.cc:83
impeller::DlVerticesGeometry::GetPositionUVColorBuffer
GeometryResult GetPositionUVColorBuffer(Rect texture_coverage, Matrix effect_transform, const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
Definition: dl_vertices_geometry.cc:147
impeller::skia_conversions::ToColor
Color ToColor(const flutter::DlColor &color)
Definition: skia_conversions.cc:106
impeller::DlVerticesGeometry::GetPositionBuffer
GeometryResult GetPositionBuffer(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
Definition: dl_vertices_geometry.cc:115
impeller::skia_conversions::ToRect
Rect ToRect(const SkRect &rect)
Definition: skia_conversions.cc:30
impeller::VS
SolidFillVertexShader VS
Definition: stroke_path_geometry.cc:16
impeller::PrimitiveType::kTriangle
@ kTriangle
impeller::Entity
Definition: entity.h:20
impeller::PrimitiveType::kTriangleStrip
@ kTriangleStrip
impeller::PrimitiveType
PrimitiveType
Decides how backend draws pixels based on input vertices.
Definition: formats.h:352
skia_conversions.h
impeller::GeometryResult::type
PrimitiveType type
Definition: geometry.h:42
transform
Matrix transform
Definition: gaussian_blur_filter_contents.cc:213
impeller::DlVerticesGeometry::HasTextureCoordinates
bool HasTextureCoordinates() const override
Definition: dl_vertices_geometry.cc:87
impeller::RenderPipelineHandle::VertexShader
VertexShader_ VertexShader
Definition: pipeline.h:106
impeller::GeometryResult
Definition: geometry.h:26
impeller::IndexType::kNone
@ kNone
Does not use the index buffer.
impeller::skia_conversions::ToPoint
Point ToPoint(const SkPoint &point)
Definition: skia_conversions.cc:98
impeller::Capabilities::SupportsTriangleFan
virtual bool SupportsTriangleFan() const =0
Whether the primitive type TriangleFan is supported by the backend.
dl_vertices_geometry.h
impeller::RenderPass
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:33
impeller::BufferView
Definition: buffer_view.h:15
impeller::ContentContext::GetDeviceCapabilities
const Capabilities & GetDeviceCapabilities() const
Definition: content_context.cc:554
impeller::TPoint< Scalar >
impeller::Color::BlackTransparent
static constexpr Color BlackTransparent()
Definition: color.h:269
impeller::DlVerticesGeometry::GetCoverage
std::optional< Rect > GetCoverage(const Matrix &transform) const override
Definition: dl_vertices_geometry.cc:208
color
DlColor color
Definition: dl_golden_blur_unittests.cc:24
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
impeller::DlVerticesGeometry::GetTextureCoordinateCoverge
std::optional< Rect > GetTextureCoordinateCoverge() const override
Definition: dl_vertices_geometry.cc:91
impeller
Definition: allocation.cc:12
impeller::ContentContext
Definition: content_context.h:366
impeller::Color::Premultiply
constexpr Color Premultiply() const
Definition: color.h:211
impeller::TRect< Scalar >
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::PrimitiveType::kTriangleFan
@ kTriangleFan
impeller::DlVerticesGeometry::DlVerticesGeometry
DlVerticesGeometry(const std::shared_ptr< const flutter::DlVertices > &vertices, const ContentContext &renderer)
Definition: dl_vertices_geometry.cc:60
impeller::ContentContext::GetTransientsBuffer
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
Definition: content_context.h:753