| 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/geometry/point.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
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_ = 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_) {
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_coordinates() != nullptr;
89 }
90
91 std::optional<Rect> DlVerticesGeometry::GetTextureCoordinateCoverge() 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_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
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_->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
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 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()
175 : Color::BlackTransparent();
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
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::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