| Flutter Impeller |

fill_path_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/fill_path_geometry.h"
6
7 #include "fml/logging.h"
8 #include "impeller/core/formats.h"
9 #include "impeller/core/vertex_buffer.h"
10 #include "impeller/entity/contents/content_context.h"
11 #include "impeller/entity/geometry/geometry.h"
12
13 namespace impeller {
14
15 FillPathGeometry::FillPathGeometry(const Path& path,
16 std::optional<Rect> inner_rect)
17 : path_(path), inner_rect_(inner_rect) {}
18
19 GeometryResult FillPathGeometry::GetPositionBuffer(
20 const ContentContext& renderer,
21 const Entity& entity,
22 RenderPass& pass) const {
23 auto& host_buffer = renderer.GetTransientsBuffer();
24
25 const auto& bounding_box = path_.GetBoundingBox();
26 if (bounding_box.has_value() && bounding_box->IsEmpty()) {
27 return GeometryResult{
28 .type = PrimitiveType::kTriangle,
29 .vertex_buffer =
30 VertexBuffer{
31 .vertex_buffer = {},
32 .vertex_count = 0,
33 .index_type = IndexType::k16bit,
34 },
35 .transform = pass.GetOrthographicTransform() * entity.GetTransform(),
36 };
37 }
38
39 VertexBuffer vertex_buffer;
40 if constexpr (!ContentContext::kEnableStencilThenCover) {
41 if (!path_.IsConvex()) {
42 auto tesselation_result = renderer.GetTessellator()->Tessellate(
43 path_, entity.GetTransform().GetMaxBasisLength(),
44 [&vertex_buffer, &host_buffer](
45 const float* vertices, size_t vertices_count,
46 const uint16_t* indices, size_t indices_count) {
47 vertex_buffer.vertex_buffer = host_buffer.Emplace(
48 vertices, vertices_count * sizeof(float) * 2, alignof(float));
49 if (indices != nullptr) {
50 vertex_buffer.index_buffer = host_buffer.Emplace(
51 indices, indices_count * sizeof(uint16_t), alignof(uint16_t));
52 vertex_buffer.vertex_count = indices_count;
53 vertex_buffer.index_type = IndexType::k16bit;
54 } else {
55 vertex_buffer.index_buffer = {};
56 vertex_buffer.vertex_count = vertices_count;
57 vertex_buffer.index_type = IndexType::kNone;
58 }
59 return true;
60 });
61 if (tesselation_result != Tessellator::Result::kSuccess) {
62 return {};
63 }
64 return GeometryResult{
65 .type = PrimitiveType::kTriangle,
66 .vertex_buffer = vertex_buffer,
67 .transform = entity.GetShaderTransform(pass),
68 };
69 }
70 }
71
72 auto points = renderer.GetTessellator()->TessellateConvex(
73 path_, entity.GetTransform().GetMaxBasisLength());
74
75 vertex_buffer.vertex_buffer = host_buffer.Emplace(
76 points.data(), points.size() * sizeof(Point), alignof(Point));
77 vertex_buffer.index_buffer = {}, vertex_buffer.vertex_count = points.size();
78 vertex_buffer.index_type = IndexType::kNone;
79
80 return GeometryResult{
81 .type = PrimitiveType::kTriangleStrip,
82 .vertex_buffer = vertex_buffer,
83 .transform = entity.GetShaderTransform(pass),
84 .mode = GetResultMode(),
85 };
86 }
87
88 // |Geometry|
89 GeometryResult FillPathGeometry::GetPositionUVBuffer(
90 Rect texture_coverage,
91 Matrix effect_transform,
92 const ContentContext& renderer,
93 const Entity& entity,
94 RenderPass& pass) const {
95 using VS = TextureFillVertexShader;
96
97 const auto& bounding_box = path_.GetBoundingBox();
98 if (bounding_box.has_value() && bounding_box->IsEmpty()) {
99 return GeometryResult{
100 .type = PrimitiveType::kTriangle,
101 .vertex_buffer =
102 VertexBuffer{
103 .vertex_buffer = {},
104 .vertex_count = 0,
105 .index_type = IndexType::k16bit,
106 },
107 .transform = pass.GetOrthographicTransform() * entity.GetTransform(),
108 };
109 }
110
111 auto uv_transform =
112 texture_coverage.GetNormalizingTransform() * effect_transform;
113
114 if constexpr (!ContentContext::kEnableStencilThenCover) {
115 if (!path_.IsConvex()) {
116 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
117 auto tesselation_result = renderer.GetTessellator()->Tessellate(
118 path_, entity.GetTransform().GetMaxBasisLength(),
119 [&vertex_builder, &uv_transform](
120 const float* vertices, size_t vertices_count,
121 const uint16_t* indices, size_t indices_count) {
122 for (auto i = 0u; i < vertices_count * 2; i += 2) {
123 VS::PerVertexData data;
124 Point vtx = {vertices[i], vertices[i + 1]};
125 data.position = vtx;
126 data.texture_coords = uv_transform * vtx;
127 vertex_builder.AppendVertex(data);
128 }
129 FML_DCHECK(vertex_builder.GetVertexCount() == vertices_count);
130 if (indices != nullptr) {
131 for (auto i = 0u; i < indices_count; i++) {
132 vertex_builder.AppendIndex(indices[i]);
133 }
134 }
135 return true;
136 });
137 if (tesselation_result != Tessellator::Result::kSuccess) {
138 return {};
139 }
140 return GeometryResult{
141 .type = PrimitiveType::kTriangle,
142 .vertex_buffer =
143 vertex_builder.CreateVertexBuffer(renderer.GetTransientsBuffer()),
144 .transform = entity.GetShaderTransform(pass),
145 };
146 }
147 }
148
149 auto points = renderer.GetTessellator()->TessellateConvex(
150 path_, entity.GetTransform().GetMaxBasisLength());
151
152 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
153 vertex_builder.Reserve(points.size());
154 for (auto i = 0u; i < points.size(); i++) {
155 VS::PerVertexData data;
156 data.position = points[i];
157 data.texture_coords = uv_transform * points[i];
158 vertex_builder.AppendVertex(data);
159 }
160
161 return GeometryResult{
162 .type = PrimitiveType::kTriangleStrip,
163 .vertex_buffer =
164 vertex_builder.CreateVertexBuffer(renderer.GetTransientsBuffer()),
165 .transform = entity.GetShaderTransform(pass),
166 .mode = GetResultMode(),
167 };
168 }
169
170 GeometryResult::Mode FillPathGeometry::GetResultMode() const {
171 const auto& bounding_box = path_.GetBoundingBox();
172 if (!ContentContext::kEnableStencilThenCover || path_.IsConvex() ||
173 (bounding_box.has_value() && bounding_box->IsEmpty())) {
174 return GeometryResult::Mode::kNormal;
175 }
176
177 switch (path_.GetFillType()) {
178 case FillType::kNonZero:
179 return GeometryResult::Mode::kNonZero;
180 case FillType::kOdd:
181 return GeometryResult::Mode::kEvenOdd;
182 }
183
184 FML_UNREACHABLE();
185 }
186
187 GeometryVertexType FillPathGeometry::GetVertexType() const {
188 return GeometryVertexType::kPosition;
189 }
190
191 std::optional<Rect> FillPathGeometry::GetCoverage(
192 const Matrix& transform) const {
193 return path_.GetTransformedBoundingBox(transform);
194 }
195
196 bool FillPathGeometry::CoversArea(const Matrix& transform,
197 const Rect& rect) const {
198 if (!inner_rect_.has_value()) {
199 return false;
200 }
201 if (!transform.IsTranslationScaleOnly()) {
202 return false;
203 }
204 Rect coverage = inner_rect_->TransformBounds(transform);
205 return coverage.Contains(rect);
206 }
207
208 } // 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::Entity::GetTransform
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
Definition: entity.cc:49
vertex_buffer.h
impeller::VertexBuffer
Definition: vertex_buffer.h:13
impeller::TRect::TransformBounds
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
Definition: rect.h:405
formats.h
impeller::Path::GetBoundingBox
std::optional< Rect > GetBoundingBox() const
Definition: path.cc:339
impeller::VertexBuffer::vertex_buffer
BufferView vertex_buffer
Definition: vertex_buffer.h:14
impeller::RenderPass::GetOrthographicTransform
const Matrix & GetOrthographicTransform() const
Definition: render_pass.cc:47
impeller::GeometryVertexType
GeometryVertexType
Definition: geometry.h:49
impeller::ContentContext::kEnableStencilThenCover
static constexpr bool kEnableStencilThenCover
Definition: content_context.h:411
impeller::VS
SolidFillVertexShader VS
Definition: stroke_path_geometry.cc:15
impeller::PrimitiveType::kTriangle
@ kTriangle
impeller::Entity
Definition: entity.h:21
impeller::Point
TPoint< Scalar > Point
Definition: point.h:316
impeller::GeometryResult::type
PrimitiveType type
Definition: geometry.h:36
impeller::Path
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
Definition: path.h:51
impeller::Matrix::GetMaxBasisLength
Scalar GetMaxBasisLength() const
Definition: matrix.cc:196
impeller::Matrix::IsTranslationScaleOnly
constexpr bool IsTranslationScaleOnly() const
Returns true if the matrix has a scale-only basis and is non-projective. Note that an identity matrix...
Definition: matrix.h:363
geometry.h
impeller::GeometryResult
Definition: geometry.h:20
impeller::IndexType::kNone
@ kNone
Does not use the index buffer.
impeller::Tessellator::Result::kSuccess
@ kSuccess
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:661
impeller::ContentContext::GetTessellator
std::shared_ptr< Tessellator > GetTessellator() const
Definition: content_context.cc:560
fill_path_geometry.h
impeller::TRect::Contains
constexpr bool Contains(const TPoint< Type > &p) const
Returns true iff the provided point |p| is inside the half-open interior of this rectangle.
Definition: rect.h:217
impeller::RenderPass
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:33
content_context.h
impeller::Path::IsConvex
bool IsConvex() const
Definition: path.cc:55
impeller
Definition: aiks_blur_unittests.cc:20
impeller::kPosition
@ kPosition
Definition: geometry.h:50
impeller::ContentContext
Definition: content_context.h:392
impeller::TRect
Definition: rect.h:122
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::ContentContext::GetTransientsBuffer
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
Definition: content_context.h:833
impeller::FillPathGeometry::FillPathGeometry
FillPathGeometry(const Path &path, std::optional< Rect > inner_rect=std::nullopt)
Definition: fill_path_geometry.cc:15