Flutter Engine
 
Loading...
Searching...
No Matches
dl_vertices.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
9
10namespace flutter {
11
13
14static void DlVerticesDeleter(void* p) {
15 // Some of our target environments would prefer a sized delete,
16 // but other target environments do not have that operator.
17 // Use an unsized delete until we get better agreement in the
18 // environments.
19 // See https://github.com/flutter/flutter/issues/100327
20 ::operator delete(p);
21}
22
23static size_t bytes_needed(int vertex_count, Flags flags, int index_count) {
24 int needed = sizeof(DlVertices);
25 // We always have vertices
26 needed += vertex_count * sizeof(DlPoint);
27 if (flags.has_texture_coordinates) {
28 needed += vertex_count * sizeof(DlPoint);
29 }
30 if (flags.has_colors) {
31 needed += vertex_count * sizeof(DlColor);
32 }
33 if (index_count > 0) {
34 needed += index_count * sizeof(uint16_t);
35 }
36 return needed;
37}
38
39std::shared_ptr<DlVertices> DlVertices::Make(
40 DlVertexMode mode,
41 int vertex_count,
42 const DlPoint vertices[],
43 const DlPoint texture_coordinates[],
44 const DlColor colors[],
45 int index_count,
46 const uint16_t indices[],
47 const DlRect* bounds) {
48 if (!vertices || vertex_count <= 0) {
49 vertex_count = 0;
50 texture_coordinates = nullptr;
51 colors = nullptr;
52 }
53 if (!indices || index_count <= 0) {
54 index_count = 0;
55 indices = nullptr;
56 }
57
58 Flags flags;
59 FML_DCHECK(!flags.has_texture_coordinates);
60 FML_DCHECK(!flags.has_colors);
61 if (texture_coordinates) {
63 }
64 if (colors) {
65 flags |= Builder::kHasColors;
66 }
67 Builder builder(mode, vertex_count, flags, index_count);
68
69 builder.store_vertices(vertices);
70 if (texture_coordinates) {
71 builder.store_texture_coordinates(texture_coordinates);
72 }
73 if (colors) {
74 builder.store_colors(colors);
75 }
76 if (indices) {
77 builder.store_indices(indices);
78 }
79 if (bounds != nullptr) {
80 builder.store_bounds(*bounds);
81 }
82
83 return builder.build();
84}
85
86size_t DlVertices::size() const {
87 return bytes_needed(vertex_count_,
88 {{texture_coordinates_offset_ > 0, colors_offset_ > 0}},
89 index_count_);
90}
91
92static DlRect compute_bounds(const DlPoint* points, int count) {
93 AccumulationRect accumulator;
94 for (int i = 0; i < count; i++) {
95 accumulator.accumulate(points[i]);
96 }
97 return accumulator.GetBounds();
98}
99
100DlVertices::DlVertices(DlVertexMode mode,
101 int unchecked_vertex_count,
102 const DlPoint* vertices,
103 const DlPoint* texture_coordinates,
104 const DlColor* colors,
105 int unchecked_index_count,
106 const uint16_t* indices,
107 const DlRect* bounds)
108 : mode_(mode),
109 vertex_count_(std::max(unchecked_vertex_count, 0)),
110 index_count_(indices ? std::max(unchecked_index_count, 0) : 0) {
111 bounds_ = bounds ? *bounds : compute_bounds(vertices, vertex_count_);
112
113 char* pod = reinterpret_cast<char*>(this);
114 size_t offset = sizeof(DlVertices);
115
116 auto advance = [pod, &offset](auto* src, int count) {
117 if (src != nullptr && count > 0) {
118 size_t bytes = count * sizeof(*src);
119 memcpy(pod + offset, src, bytes);
120 size_t ret = offset;
121 offset += bytes;
122 return ret;
123 } else {
124 return static_cast<size_t>(0);
125 }
126 };
127
128 vertices_offset_ = advance(vertices, vertex_count_);
129 texture_coordinates_offset_ = advance(texture_coordinates, vertex_count_);
130 colors_offset_ = advance(colors, vertex_count_);
131 indices_offset_ = advance(indices, index_count_);
132 FML_DCHECK(offset == bytes_needed(vertex_count_,
133 {{!!texture_coordinates, !!colors}},
134 index_count_));
135}
136
137DlVertices::DlVertices(const DlVertices* other)
138 : DlVertices(other->mode_,
139 other->vertex_count_,
140 other->vertex_data(),
141 other->texture_coordinate_data(),
142 other->colors(),
143 other->index_count_,
144 other->indices(),
145 &other->bounds_) {}
146
147DlVertices::DlVertices(DlVertexMode mode,
148 int unchecked_vertex_count,
149 Flags flags,
150 int unchecked_index_count)
151 : mode_(mode),
152 vertex_count_(std::max(unchecked_vertex_count, 0)),
153 index_count_(std::max(unchecked_index_count, 0)) {
154 char* pod = reinterpret_cast<char*>(this);
155 size_t offset = sizeof(DlVertices);
156
157 auto advance = [pod, &offset](size_t size, int count) {
158 if (count > 0) {
159 size_t bytes = count * size;
160 memset(pod + offset, 0, bytes);
161 size_t ret = offset;
162 offset += bytes;
163 return ret;
164 } else {
165 return static_cast<size_t>(0);
166 }
167 };
168
169 vertices_offset_ = advance(sizeof(DlPoint), vertex_count_);
170 texture_coordinates_offset_ = advance(
171 sizeof(DlPoint), flags.has_texture_coordinates ? vertex_count_ : 0);
172 colors_offset_ =
173 advance(sizeof(DlColor), flags.has_colors ? vertex_count_ : 0);
174 indices_offset_ = advance(sizeof(uint16_t), index_count_);
175 FML_DCHECK(offset == bytes_needed(vertex_count_, flags, index_count_));
176 FML_DCHECK((vertex_count_ != 0) == (vertex_data() != nullptr));
177 FML_DCHECK((vertex_count_ != 0 && flags.has_texture_coordinates) ==
178 (texture_coordinate_data() != nullptr));
179 FML_DCHECK((vertex_count_ != 0 && flags.has_colors) == (colors() != nullptr));
180 FML_DCHECK((index_count_ != 0) == (indices() != nullptr));
181}
182
183bool DlVertices::operator==(DlVertices const& other) const {
184 auto lists_equal = [](auto* a, auto* b, int count) {
185 if (a == nullptr || b == nullptr) {
186 return a == b;
187 }
188 for (int i = 0; i < count; i++) {
189 if (a[i] != b[i]) {
190 return false;
191 }
192 }
193 return true;
194 };
195 return //
196 mode_ == other.mode_ && //
197 vertex_count_ == other.vertex_count_ && //
198 lists_equal(vertex_data(), other.vertex_data(), vertex_count_) && //
199 lists_equal(texture_coordinate_data(), //
200 other.texture_coordinate_data(), //
201 vertex_count_) && //
202 lists_equal(colors(), other.colors(), vertex_count_) && //
203 index_count_ == other.index_count_ && //
204 lists_equal(indices(), other.indices(), index_count_);
205}
206
207DlVertices::Builder::Builder(DlVertexMode mode,
208 int vertex_count,
209 Flags flags,
210 int index_count)
211 : needs_texture_coords_(flags.has_texture_coordinates),
212 needs_colors_(flags.has_colors),
213 needs_indices_(index_count > 0) {
214 vertex_count = std::max(vertex_count, 0);
215 index_count = std::max(index_count, 0);
216 void* storage =
217 ::operator new(bytes_needed(vertex_count, flags, index_count));
218 vertices_.reset(new (storage)
221}
222
223static void store_points(char* dst, int offset, const float* src, int count) {
224 DlPoint* points = reinterpret_cast<DlPoint*>(dst + offset);
225 for (int i = 0; i < count; i++) {
226 points[i] = DlPoint(src[i * 2], src[i * 2 + 1]);
227 }
228}
229
231 FML_DCHECK(is_valid());
232 FML_DCHECK(needs_vertices_);
233 char* pod = reinterpret_cast<char*>(vertices_.get());
234 size_t bytes = vertices_->vertex_count_ * sizeof(vertices[0]);
235 memcpy(pod + vertices_->vertices_offset_, vertices, bytes);
236 needs_vertices_ = false;
237}
238
239void DlVertices::Builder::store_vertices(const float vertices[]) {
240 FML_DCHECK(is_valid());
241 FML_DCHECK(needs_vertices_);
242 char* pod = reinterpret_cast<char*>(vertices_.get());
243 store_points(pod, vertices_->vertices_offset_, vertices,
244 vertices_->vertex_count_);
245 needs_vertices_ = false;
246}
247
249 FML_DCHECK(is_valid());
250 FML_DCHECK(needs_texture_coords_);
251 char* pod = reinterpret_cast<char*>(vertices_.get());
252 size_t bytes = vertices_->vertex_count_ * sizeof(coords[0]);
253 memcpy(pod + vertices_->texture_coordinates_offset_, coords, bytes);
254 needs_texture_coords_ = false;
255}
256
258 FML_DCHECK(is_valid());
259 FML_DCHECK(needs_texture_coords_);
260 char* pod = reinterpret_cast<char*>(vertices_.get());
261 store_points(pod, vertices_->texture_coordinates_offset_, coords,
262 vertices_->vertex_count_);
263 needs_texture_coords_ = false;
264}
265
267 FML_DCHECK(is_valid());
268 FML_DCHECK(needs_colors_);
269 char* pod = reinterpret_cast<char*>(vertices_.get());
270 size_t bytes = vertices_->vertex_count_ * sizeof(colors[0]);
271 memcpy(pod + vertices_->colors_offset_, colors, bytes);
272 needs_colors_ = false;
273}
274
276 FML_DCHECK(is_valid());
277 FML_DCHECK(needs_colors_);
278 char* pod = reinterpret_cast<char*>(vertices_.get());
279 DlColor* dlcolors_ptr =
280 reinterpret_cast<DlColor*>(pod + vertices_->colors_offset_);
281 for (int i = 0; i < vertices_->vertex_count_; ++i) {
282 *dlcolors_ptr++ = DlColor(colors[i]);
283 }
284 needs_colors_ = false;
285}
286
288 FML_DCHECK(is_valid());
289 FML_DCHECK(needs_indices_);
290 char* pod = reinterpret_cast<char*>(vertices_.get());
291 size_t bytes = vertices_->index_count_ * sizeof(indices[0]);
292 memcpy(pod + vertices_->indices_offset_, indices, bytes);
293 needs_indices_ = false;
294}
295
297 vertices_->bounds_ = bounds;
298 needs_bounds_ = false;
299}
300
301std::shared_ptr<DlVertices> DlVertices::Builder::build() {
302 FML_DCHECK(is_valid());
303 if (vertices_->vertex_count() <= 0) {
304 // We set this to true in the constructor to make sure that they
305 // call store_vertices() only once, but if there are no vertices
306 // then we will not object to them never having stored any vertices
307 needs_vertices_ = false;
308 }
309 FML_DCHECK(!needs_vertices_);
310 FML_DCHECK(!needs_texture_coords_);
311 FML_DCHECK(!needs_colors_);
312 FML_DCHECK(!needs_indices_);
313
314 if (needs_bounds_) {
315 vertices_->bounds_ =
316 compute_bounds(vertices_->vertex_data(), vertices_->vertex_count_);
317 }
318
319 return std::move(vertices_);
320}
321
322} // namespace flutter
void accumulate(DlScalar x, DlScalar y)
A utility class to build up a |DlVertices| object one set of data at a time.
Definition dl_vertices.h:73
void store_vertices(const DlPoint vertices[])
Copies the indicated list of points as vertices.
void store_indices(const uint16_t indices[])
Copies the indicated list of 16-bit indices as vertex indices.
void store_texture_coordinates(const DlPoint points[])
Copies the indicated list of points as texture coordinates.
void store_bounds(DlRect bounds)
Overwrite the internal bounds with a precomputed bounding rect.
std::shared_ptr< DlVertices > build()
Finalizes and the constructed DlVertices object.
static constexpr Flags kHasColors
Definition dl_vertices.h:96
void store_colors(const DlColor colors[])
Copies the indicated list of colors as vertex colors.
static constexpr Flags kHasTextureCoordinates
Definition dl_vertices.h:95
Holds all of the data (both required and optional) for a DisplayList drawVertices call.
Definition dl_vertices.h:69
static std::shared_ptr< DlVertices > Make(DlVertexMode mode, int vertex_count, const DlPoint vertices[], const DlPoint texture_coordinates[], const DlColor colors[], int index_count=0, const uint16_t indices[]=nullptr, const DlRect *bounds=nullptr)
Constructs a DlVector with compact inline storage for all of its required and optional lists of data.
const DlPoint * texture_coordinate_data() const
const DlPoint * vertex_data() const
Returns a pointer to the vertex information. Should be non-null.
const DlColor * colors() const
int vertex_count() const
DlVertexMode mode() const
int index_count() const
size_t size() const
Returns the size of the object including all of the inlined data.
const uint16_t * indices() const
#define FML_DCHECK(condition)
Definition logging.h:122
impeller::Rect DlRect
static void DlVerticesDeleter(void *p)
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
static DlRect compute_bounds(const DlPoint *points, int count)
DlVertexMode
Defines the way in which the vertices of a DlVertices object are separated into triangles into which ...
Definition dl_vertices.h:18
static void store_points(char *dst, int offset, const float *src, int count)
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
impeller::Point DlPoint
static size_t bytes_needed(int vertex_count, Flags flags, int index_count)
Definition ref_ptr.h:261
std::vector< Point > points
flags to indicate/promise which of the optional texture coordinates or colors will be supplied during...
Definition dl_vertices.h:78