Flutter Impeller
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 <cstdint>
8 #include <utility>
9 
11 
12 namespace impeller {
13 
14 // Fan mode isn't natively supported. Unroll into triangle mode by
15 // manipulating the index array.
16 //
17 // In Triangle fan, the first vertex is shared across all triangles, and then
18 // each sliding window of two vertices plus that first vertex defines a
19 // triangle.
20 static std::vector<uint16_t> fromFanIndices(
21  const std::vector<Point>& vertices,
22  const std::vector<uint16_t>& indices) {
23  std::vector<uint16_t> unrolled_indices;
24 
25  // Un-fan index buffer if provided.
26  if (indices.size() > 0u) {
27  if (indices.size() < 3u) {
28  return {};
29  }
30 
31  auto center_point = indices[0];
32  for (auto i = 1u; i < indices.size() - 1; i++) {
33  unrolled_indices.push_back(center_point);
34  unrolled_indices.push_back(indices[i]);
35  unrolled_indices.push_back(indices[i + 1]);
36  }
37  } else {
38  if (vertices.size() < 3u) {
39  return {};
40  }
41 
42  // If indices were not provided, create an index buffer that unfans
43  // triangles instead of re-writing points, colors, et cetera.
44  for (auto i = 1u; i < vertices.size() - 1; i++) {
45  unrolled_indices.push_back(0);
46  unrolled_indices.push_back(i);
47  unrolled_indices.push_back(i + 1);
48  }
49  }
50  return unrolled_indices;
51 }
52 
53 /////// Vertices Geometry ///////
54 
55 VerticesGeometry::VerticesGeometry(std::vector<Point> vertices,
56  std::vector<uint16_t> indices,
57  std::vector<Point> texture_coordinates,
58  std::vector<Color> colors,
59  Rect bounds,
60  VertexMode vertex_mode)
61  : vertices_(std::move(vertices)),
62  colors_(std::move(colors)),
63  texture_coordinates_(std::move(texture_coordinates)),
64  indices_(std::move(indices)),
65  bounds_(bounds),
66  vertex_mode_(vertex_mode) {
67  NormalizeIndices();
68 }
69 
70 PrimitiveType VerticesGeometry::GetPrimitiveType() const {
71  switch (vertex_mode_) {
73  // Unrolled into triangle mode.
79  }
80 }
81 
82 void VerticesGeometry::NormalizeIndices() {
83  // Convert triangle fan if present.
84  if (vertex_mode_ == VerticesGeometry::VertexMode::kTriangleFan) {
85  indices_ = fromFanIndices(vertices_, indices_);
86  return;
87  }
88 }
89 
91  return colors_.size() > 0;
92 }
93 
95  return texture_coordinates_.size() > 0;
96 }
97 
98 std::optional<Rect> VerticesGeometry::GetTextureCoordinateCoverge() const {
99  if (!HasTextureCoordinates()) {
100  return std::nullopt;
101  }
102  auto vertex_count = vertices_.size();
103  if (vertex_count == 0) {
104  return std::nullopt;
105  }
106 
107  return Rect::MakePointBounds(texture_coordinates_.begin(),
108  texture_coordinates_.end());
109 }
110 
112  const ContentContext& renderer,
113  const Entity& entity,
114  RenderPass& pass) const {
115  auto index_count = indices_.size();
116  auto vertex_count = vertices_.size();
117 
118  size_t total_vtx_bytes = vertex_count * sizeof(float) * 2;
119  size_t total_idx_bytes = index_count * sizeof(uint16_t);
120 
121  auto vertex_buffer = renderer.GetTransientsBuffer().Emplace(
122  reinterpret_cast<const uint8_t*>(vertices_.data()), total_vtx_bytes,
123  alignof(float));
124 
125  BufferView index_buffer = {};
126  if (index_count) {
127  index_buffer = renderer.GetTransientsBuffer().Emplace(
128  indices_.data(), total_idx_bytes, alignof(uint16_t));
129  }
130 
131  return GeometryResult{
132  .type = GetPrimitiveType(),
133  .vertex_buffer =
134  {
135  .vertex_buffer = vertex_buffer,
136  .index_buffer = index_buffer,
137  .vertex_count = index_count > 0 ? index_count : vertex_count,
138  .index_type =
139  index_count > 0 ? IndexType::k16bit : IndexType::kNone,
140  },
141  .transform = entity.GetShaderTransform(pass),
142  };
143 }
144 
146  const ContentContext& renderer,
147  const Entity& entity,
148  RenderPass& pass) {
150 
151  auto index_count = indices_.size();
152  auto vertex_count = vertices_.size();
153  size_t total_vtx_bytes = vertex_count * sizeof(VS::PerVertexData);
154  size_t total_idx_bytes = index_count * sizeof(uint16_t);
155 
156  auto vertex_buffer = renderer.GetTransientsBuffer().Emplace(
157  total_vtx_bytes, alignof(VS::PerVertexData), [&](uint8_t* data) {
158  VS::PerVertexData* vtx_contents =
159  reinterpret_cast<VS::PerVertexData*>(data);
160  for (auto i = 0u; i < vertices_.size(); i++) {
161  VS::PerVertexData vertex_data = {
162  .position = vertices_[i],
163  .color = colors_[i],
164  };
165  std::memcpy(vtx_contents++, &vertex_data, sizeof(VS::PerVertexData));
166  }
167  });
168 
169  BufferView index_buffer = {};
170  if (index_count > 0) {
171  index_buffer = renderer.GetTransientsBuffer().Emplace(
172  indices_.data(), total_idx_bytes, alignof(uint16_t));
173  }
174 
175  return GeometryResult{
176  .type = GetPrimitiveType(),
177  .vertex_buffer =
178  {
179  .vertex_buffer = vertex_buffer,
180  .index_buffer = index_buffer,
181  .vertex_count = index_count > 0 ? index_count : vertex_count,
182  .index_type =
183  index_count > 0 ? IndexType::k16bit : IndexType::kNone,
184  },
185  .transform = entity.GetShaderTransform(pass),
186  };
187 }
188 
190  Rect texture_coverage,
191  Matrix effect_transform,
192  const ContentContext& renderer,
193  const Entity& entity,
194  RenderPass& pass) const {
196 
197  auto index_count = indices_.size();
198  auto vertex_count = vertices_.size();
199  auto uv_transform =
200  texture_coverage.GetNormalizingTransform() * effect_transform;
201  auto has_texture_coordinates = HasTextureCoordinates();
202 
203  size_t total_vtx_bytes = vertices_.size() * sizeof(VS::PerVertexData);
204  size_t total_idx_bytes = index_count * sizeof(uint16_t);
205  auto vertex_buffer = renderer.GetTransientsBuffer().Emplace(
206  total_vtx_bytes, alignof(VS::PerVertexData), [&](uint8_t* data) {
207  VS::PerVertexData* vtx_contents =
208  reinterpret_cast<VS::PerVertexData*>(data);
209  for (auto i = 0u; i < vertices_.size(); i++) {
210  auto vertex = vertices_[i];
211  auto texture_coord =
212  has_texture_coordinates ? texture_coordinates_[i] : vertices_[i];
213  auto uv = uv_transform * texture_coord;
214  // From experimentation we need to clamp these values to < 1.0 or else
215  // there can be flickering.
216  VS::PerVertexData vertex_data = {
217  .position = vertex,
218  .texture_coords =
219  Point(std::clamp(uv.x, 0.0f, 1.0f - kEhCloseEnough),
220  std::clamp(uv.y, 0.0f, 1.0f - kEhCloseEnough)),
221  };
222  std::memcpy(vtx_contents++, &vertex_data, sizeof(VS::PerVertexData));
223  }
224  });
225 
226  BufferView index_buffer = {};
227  if (index_count > 0) {
228  index_buffer = renderer.GetTransientsBuffer().Emplace(
229  indices_.data(), total_idx_bytes, alignof(uint16_t));
230  }
231 
232  return GeometryResult{
233  .type = GetPrimitiveType(),
234  .vertex_buffer =
235  {
236  .vertex_buffer = vertex_buffer,
237  .index_buffer = index_buffer,
238  .vertex_count = index_count > 0 ? index_count : vertex_count,
239  .index_type =
240  index_count > 0 ? IndexType::k16bit : IndexType::kNone,
241  },
242  .transform = entity.GetShaderTransform(pass),
243  };
244 }
245 
247  if (HasVertexColors()) {
249  }
250  if (HasTextureCoordinates()) {
252  }
253 
255 }
256 
257 std::optional<Rect> VerticesGeometry::GetCoverage(
258  const Matrix& transform) const {
259  return bounds_.TransformBounds(transform);
260 }
261 
262 } // namespace impeller
impeller::Entity::GetShaderTransform
Matrix GetShaderTransform(const RenderPass &pass) const
Get the vertex shader transform used for drawing this Entity.
Definition: entity.cc:53
impeller::IndexType::k16bit
@ k16bit
impeller::VerticesGeometry::VerticesGeometry
VerticesGeometry(std::vector< Point > vertices, std::vector< uint16_t > indices, std::vector< Point > texture_coordinates, std::vector< Color > colors, Rect bounds, VerticesGeometry::VertexMode vertex_mode)
Definition: vertices_geometry.cc:55
impeller::kEhCloseEnough
constexpr float kEhCloseEnough
Definition: constants.h:56
impeller::TRect::TransformBounds
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
Definition: rect.h:405
impeller::HostBuffer::Emplace
BufferView Emplace(const BufferType &buffer)
Emplace non-uniform data (like contiguous vertices) onto the host buffer.
Definition: host_buffer.h:94
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:424
impeller::VerticesGeometry::GetPositionUVBuffer
GeometryResult GetPositionUVBuffer(Rect texture_coverage, Matrix effect_transform, const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
Definition: vertices_geometry.cc:189
impeller::GeometryVertexType
GeometryVertexType
Definition: geometry.h:49
impeller::TRect< Scalar >::MakePointBounds
constexpr static std::optional< TRect > MakePointBounds(const U &value)
Definition: rect.h:151
impeller::VS
SolidFillVertexShader VS
Definition: stroke_path_geometry.cc:15
impeller::kColor
@ kColor
Definition: geometry.h:51
impeller::PrimitiveType::kTriangle
@ kTriangle
impeller::Entity
Definition: entity.h:21
impeller::PrimitiveType::kTriangleStrip
@ kTriangleStrip
impeller::PrimitiveType
PrimitiveType
Decides how backend draws pixels based on input vertices.
Definition: formats.h:353
impeller::Point
TPoint< Scalar > Point
Definition: point.h:316
impeller::VerticesGeometry::VertexMode
VertexMode
Definition: vertices_geometry.h:15
impeller::GeometryResult::type
PrimitiveType type
Definition: geometry.h:36
impeller::VerticesGeometry::HasVertexColors
bool HasVertexColors() const
Definition: vertices_geometry.cc:90
impeller::VerticesGeometry::VertexMode::kTriangleStrip
@ kTriangleStrip
impeller::VerticesGeometry::GetPositionColorBuffer
GeometryResult GetPositionColorBuffer(const ContentContext &renderer, const Entity &entity, RenderPass &pass)
Definition: vertices_geometry.cc:145
impeller::GeometryResult
Definition: geometry.h:20
impeller::IndexType::kNone
@ kNone
Does not use the index buffer.
impeller::VerticesGeometry::GetVertexType
GeometryVertexType GetVertexType() const override
Definition: vertices_geometry.cc:246
vertices_geometry.h
impeller::kUV
@ kUV
Definition: geometry.h:52
impeller::VerticesGeometry::GetCoverage
std::optional< Rect > GetCoverage(const Matrix &transform) const override
Definition: vertices_geometry.cc:257
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
std
Definition: comparable.h:95
buffer_view.h
impeller::VerticesGeometry::GetPositionBuffer
GeometryResult GetPositionBuffer(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
Definition: vertices_geometry.cc:111
impeller::VerticesGeometry::VertexMode::kTriangles
@ kTriangles
impeller::VerticesGeometry::HasTextureCoordinates
bool HasTextureCoordinates() const
Definition: vertices_geometry.cc:94
impeller::RenderPipelineT::VertexShader
VertexShader_ VertexShader
Definition: pipeline.h:93
impeller
Definition: aiks_blur_unittests.cc:20
impeller::VerticesGeometry::VertexMode::kTriangleFan
@ kTriangleFan
impeller::kPosition
@ kPosition
Definition: geometry.h:50
impeller::ContentContext
Definition: content_context.h:392
impeller::TRect< Scalar >
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::VerticesGeometry::GetTextureCoordinateCoverge
std::optional< Rect > GetTextureCoordinateCoverge() const
Definition: vertices_geometry.cc:98
impeller::ContentContext::GetTransientsBuffer
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
Definition: content_context.h:833
impeller::fromFanIndices
static std::vector< uint16_t > fromFanIndices(const std::vector< Point > &vertices, const std::vector< uint16_t > &indices)
Definition: vertices_geometry.cc:20