| 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
5 #include "impeller/entity/geometry/vertices_geometry.h"
6
7 #include <cstdint>
8 #include <utility>
9
10 #include "impeller/core/buffer_view.h"
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_) {
72 case VerticesGeometry::VertexMode::kTriangleFan:
73 // Unrolled into triangle mode.
74 return PrimitiveType::kTriangle;
75 case VerticesGeometry::VertexMode::kTriangleStrip:
76 return PrimitiveType::kTriangleStrip;
77 case VerticesGeometry::VertexMode::kTriangles:
78 return PrimitiveType::kTriangle;
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
90 bool VerticesGeometry::HasVertexColors() const {
91 return colors_.size() > 0;
92 }
93
94 bool VerticesGeometry::HasTextureCoordinates() const {
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
111 GeometryResult VerticesGeometry::GetPositionBuffer(
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
145 GeometryResult VerticesGeometry::GetPositionColorBuffer(
146 const ContentContext& renderer,
147 const Entity& entity,
148 RenderPass& pass) {
149 using VS = GeometryColorPipeline::VertexShader;
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
189 GeometryResult VerticesGeometry::GetPositionUVBuffer(
190 Rect texture_coverage,
191 Matrix effect_transform,
192 const ContentContext& renderer,
193 const Entity& entity,
194 RenderPass& pass) const {
195 using VS = TexturePipeline::VertexShader;
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
246 GeometryVertexType VerticesGeometry::GetVertexType() const {
247 if (HasVertexColors()) {
248 return GeometryVertexType::kColor;
249 }
250 if (HasTextureCoordinates()) {
251 return GeometryVertexType::kUV;
252 }
253
254 return GeometryVertexType::kPosition;
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