| 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
5 #include "impeller/display_list/dl_vertices_geometry.h"
6
7 #include "display_list/dl_vertices.h"
8 #include "impeller/core/formats.h"
9 #include "impeller/display_list/skia_conversions.h"
10 #include "impeller/entity/contents/pipelines.h"
11 #include "impeller/geometry/point.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
60 DlVerticesGeometry::DlVerticesGeometry(
61 const std::shared_ptr<const flutter::DlVertices>& vertices,
62 const ContentContext& renderer)
63 : vertices_(vertices) {
64 performed_normalization_ = MaybePerformIndexNormalization(renderer);
65 bounds_ = vertices_->GetBounds();
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_) {
73 return PrimitiveType::kTriangle;
74 }
75 return PrimitiveType::kTriangleFan;
76 case flutter::DlVertexMode::kTriangleStrip:
77 return PrimitiveType::kTriangleStrip;
78 case flutter::DlVertexMode::kTriangles:
79 return PrimitiveType::kTriangle;
80 }
81 }
82
83 bool DlVerticesGeometry::HasVertexColors() const {
84 return vertices_->colors() != nullptr;
85 }
86
87 bool DlVerticesGeometry::HasTextureCoordinates() const {
88 return vertices_->texture_coordinate_data() != nullptr;
89 }
90
91 std::optional<Rect> DlVerticesGeometry::GetTextureCoordinateCoverage() const {
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_coordinate_data();
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
115 GeometryResult DlVerticesGeometry::GetPositionBuffer(
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_->vertex_data(), vertex_count * sizeof(Point), alignof(Point));
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
147 GeometryResult DlVerticesGeometry::GetPositionUVColorBuffer(
148 Rect texture_coverage,
149 Matrix effect_transform,
150 const ContentContext& renderer,
151 const Entity& entity,
152 RenderPass& pass) const {
153 using VS = PorterDuffBlendPipeline::VertexShader;
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 Point* coordinates = has_texture_coordinates
162 ? vertices_->texture_coordinate_data()
163 : vertices_->vertex_data();
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 const Point* vertex_points = vertices_->vertex_data();
170 for (auto i = 0; i < vertex_count; i++) {
171 Point texture_coord = coordinates[i];
172 Point uv = uv_transform * texture_coord;
173 Color color = has_colors
174 ? skia_conversions::ToColor(vertices_->colors()[i])
175 .Premultiply()
176 : Color::BlackTransparent();
177 VS::PerVertexData vertex_data = {.vertices = vertex_points[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
208 std::optional<Rect> DlVerticesGeometry::GetCoverage(
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 &&
216 !renderer.GetDeviceCapabilities().SupportsTriangleFan()) {
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::Capabilities::SupportsTriangleFan
virtual bool SupportsTriangleFan() const =0
Whether the primitive type TriangleFan is supported by the backend.
impeller::ContentContext
Definition: content_context.h:138
impeller::ContentContext::GetTransientsBuffer
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
Definition: content_context.h:296
impeller::ContentContext::GetDeviceCapabilities
const Capabilities & GetDeviceCapabilities() const
Definition: content_context.cc:917
impeller::DlVerticesGeometry::HasTextureCoordinates
bool HasTextureCoordinates() const override
Definition: dl_vertices_geometry.cc:87
impeller::DlVerticesGeometry::GetCoverage
std::optional< Rect > GetCoverage(const Matrix &transform) const override
Definition: dl_vertices_geometry.cc:208
impeller::DlVerticesGeometry::DlVerticesGeometry
DlVerticesGeometry(const std::shared_ptr< const flutter::DlVertices > &vertices, const ContentContext &renderer)
Definition: dl_vertices_geometry.cc:60
impeller::DlVerticesGeometry::GetTextureCoordinateCoverage
std::optional< Rect > GetTextureCoordinateCoverage() const override
Definition: dl_vertices_geometry.cc:91
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::DlVerticesGeometry::GetPositionBuffer
GeometryResult GetPositionBuffer(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
Definition: dl_vertices_geometry.cc:115
impeller::DlVerticesGeometry::HasVertexColors
bool HasVertexColors() const override
Definition: dl_vertices_geometry.cc:83
impeller::Entity
Definition: entity.h:20
impeller::Entity::GetShaderTransform
Matrix GetShaderTransform(const RenderPass &pass) const
Get the vertex shader transform used for drawing this Entity.
Definition: entity.cc:48
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:93
impeller::RenderPass
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:30
impeller::RenderPipelineHandle::VertexShader
VertexShader_ VertexShader
Definition: pipeline.h:119
formats.h
dl_vertices_geometry.h
transform
Matrix transform
Definition: gaussian_blur_filter_contents.cc:214
impeller::skia_conversions::ToColor
Color ToColor(const flutter::DlColor &color)
Definition: skia_conversions.cc:13
impeller
Definition: allocation.cc:12
impeller::IndexType::k16bit
@ k16bit
impeller::IndexType::kNone
@ kNone
Does not use the index buffer.
impeller::PrimitiveType
PrimitiveType
Decides how backend draws pixels based on input vertices.
Definition: formats.h:352
impeller::PrimitiveType::kTriangleFan
@ kTriangleFan
impeller::PrimitiveType::kTriangle
@ kTriangle
impeller::PrimitiveType::kTriangleStrip
@ kTriangleStrip
impeller::VS
LinePipeline::VertexShader VS
Definition: line_contents.cc:13
pipelines.h
point.h
skia_conversions.h
impeller::BufferView
Definition: buffer_view.h:19
impeller::Color
Definition: color.h:124
impeller::Color::BlackTransparent
static constexpr Color BlackTransparent()
Definition: color.h:270
impeller::Color::Premultiply
constexpr Color Premultiply() const
Definition: color.h:212
impeller::GeometryResult
Definition: geometry.h:21
impeller::GeometryResult::type
PrimitiveType type
Definition: geometry.h:37
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::TPoint< Scalar >
impeller::TRect< Scalar >
impeller::TRect::TransformBounds
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
Definition: rect.h:476
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:495
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
data
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:67