| Flutter Impeller |

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/geometry.h"
6
7 #include <memory>
8 #include <optional>
9
10 #include "fml/status.h"
11 #include "impeller/entity/contents/content_context.h"
12 #include "impeller/entity/geometry/circle_geometry.h"
13 #include "impeller/entity/geometry/cover_geometry.h"
14 #include "impeller/entity/geometry/ellipse_geometry.h"
15 #include "impeller/entity/geometry/fill_path_geometry.h"
16 #include "impeller/entity/geometry/line_geometry.h"
17 #include "impeller/entity/geometry/point_field_geometry.h"
18 #include "impeller/entity/geometry/rect_geometry.h"
19 #include "impeller/entity/geometry/round_rect_geometry.h"
20 #include "impeller/entity/geometry/stroke_path_geometry.h"
21 #include "impeller/geometry/rect.h"
22
23 namespace impeller {
24
25 GeometryResult Geometry::ComputePositionGeometry(
26 const ContentContext& renderer,
27 const Tessellator::VertexGenerator& generator,
28 const Entity& entity,
29 RenderPass& pass) {
30 using VT = SolidFillVertexShader::PerVertexData;
31
32 size_t count = generator.GetVertexCount();
33
34 return GeometryResult{
35 .type = generator.GetTriangleType(),
36 .vertex_buffer =
37 {
38 .vertex_buffer = renderer.GetTransientsBuffer().Emplace(
39 count * sizeof(VT), alignof(VT),
40 [&generator](uint8_t* buffer) {
41 auto vertices = reinterpret_cast<VT*>(buffer);
42 generator.GenerateVertices([&vertices](const Point& p) {
43 *vertices++ = {
44 .position = p,
45 };
46 });
47 FML_DCHECK(vertices == reinterpret_cast<VT*>(buffer) +
48 generator.GetVertexCount());
49 }),
50 .vertex_count = count,
51 .index_type = IndexType::kNone,
52 },
53 .transform = entity.GetShaderTransform(pass),
54 };
55 }
56
57 GeometryResult Geometry::ComputePositionUVGeometry(
58 const ContentContext& renderer,
59 const Tessellator::VertexGenerator& generator,
60 const Matrix& uv_transform,
61 const Entity& entity,
62 RenderPass& pass) {
63 using VT = TextureFillVertexShader::PerVertexData;
64
65 size_t count = generator.GetVertexCount();
66
67 return GeometryResult{
68 .type = generator.GetTriangleType(),
69 .vertex_buffer =
70 {
71 .vertex_buffer = renderer.GetTransientsBuffer().Emplace(
72 count * sizeof(VT), alignof(VT),
73 [&generator, &uv_transform](uint8_t* buffer) {
74 auto vertices = reinterpret_cast<VT*>(buffer);
75 generator.GenerateVertices(
76 [&vertices, &uv_transform](const Point& p) { //
77 *vertices++ = {
78 .position = p,
79 .texture_coords = uv_transform * p,
80 };
81 });
82 FML_DCHECK(vertices == reinterpret_cast<VT*>(buffer) +
83 generator.GetVertexCount());
84 }),
85 .vertex_count = count,
86 .index_type = IndexType::kNone,
87 },
88 .transform = entity.GetShaderTransform(pass),
89 };
90 }
91
92 VertexBufferBuilder<TextureFillVertexShader::PerVertexData>
93 ComputeUVGeometryCPU(
94 VertexBufferBuilder<SolidFillVertexShader::PerVertexData>& input,
95 Point texture_origin,
96 Size texture_coverage,
97 Matrix effect_transform) {
98 VertexBufferBuilder<TextureFillVertexShader::PerVertexData> vertex_builder;
99 vertex_builder.Reserve(input.GetVertexCount());
100 input.IterateVertices(
101 [&vertex_builder, &texture_coverage, &effect_transform,
102 &texture_origin](SolidFillVertexShader::PerVertexData old_vtx) {
103 TextureFillVertexShader::PerVertexData data;
104 data.position = old_vtx.position;
105 data.texture_coords = effect_transform *
106 (old_vtx.position - texture_origin) /
107 texture_coverage;
108 vertex_builder.AppendVertex(data);
109 });
110 return vertex_builder;
111 }
112
113 GeometryResult ComputeUVGeometryForRect(Rect source_rect,
114 Rect texture_bounds,
115 Matrix effect_transform,
116 const ContentContext& renderer,
117 const Entity& entity,
118 RenderPass& pass) {
119 auto& host_buffer = renderer.GetTransientsBuffer();
120
121 // Calculate UV-specific transform based on texture coverage and effect.
122 // For example, if the texture is 100x100 and the effect transform is
123 // scaling by 2.0, texture_bounds.GetNormalizingTransform() will result in a
124 // Matrix that scales by 0.01, and then if the effect_transform is
125 // Matrix::MakeScale(Vector2{2, 2}), the resulting uv_transform will have x
126 // and y basis vectors with scale 0.02.
127 auto uv_transform = texture_bounds.GetNormalizingTransform() * //
128 effect_transform;
129
130 // Allocate space for vertex and UV data (4 vertices)
131 // 0: position
132 // 1: UV
133 // 2: position
134 // 3: UV
135 // etc.
136 Point data[8];
137
138 // Get the raw points from the rect and transform them into UV space.
139 auto points = source_rect.GetPoints();
140 for (auto i = 0u, j = 0u; i < 8; i += 2, j++) {
141 // Store original coordinates.
142 data[i] = points[j];
143
144 // Store transformed UV coordinates.
145 data[i + 1] = uv_transform * points[j];
146 }
147
148 return GeometryResult{
149 .type = PrimitiveType::kTriangleStrip,
150 .vertex_buffer =
151 {
152 .vertex_buffer = host_buffer.Emplace(
153 /*buffer=*/data,
154 /*length=*/16 * sizeof(float),
155 /*align=*/alignof(float)),
156 .vertex_count = 4,
157 .index_type = IndexType::kNone,
158 },
159 .transform = entity.GetShaderTransform(pass),
160 };
161 }
162
163 GeometryResult Geometry::GetPositionUVBuffer(Rect texture_coverage,
164 Matrix effect_transform,
165 const ContentContext& renderer,
166 const Entity& entity,
167 RenderPass& pass) const {
168 return {};
169 }
170
171 GeometryResult::Mode Geometry::GetResultMode() const {
172 return GeometryResult::Mode::kNormal;
173 }
174
175 std::shared_ptr<Geometry> Geometry::MakeFillPath(
176 const Path& path,
177 std::optional<Rect> inner_rect) {
178 return std::make_shared<FillPathGeometry>(path, inner_rect);
179 }
180
181 std::shared_ptr<Geometry> Geometry::MakePointField(std::vector<Point> points,
182 Scalar radius,
183 bool round) {
184 return std::make_shared<PointFieldGeometry>(std::move(points), radius, round);
185 }
186
187 std::shared_ptr<Geometry> Geometry::MakeStrokePath(const Path& path,
188 Scalar stroke_width,
189 Scalar miter_limit,
190 Cap stroke_cap,
191 Join stroke_join) {
192 // Skia behaves like this.
193 if (miter_limit < 0) {
194 miter_limit = 4.0;
195 }
196 return std::make_shared<StrokePathGeometry>(path, stroke_width, miter_limit,
197 stroke_cap, stroke_join);
198 }
199
200 std::shared_ptr<Geometry> Geometry::MakeCover() {
201 return std::make_shared<CoverGeometry>();
202 }
203
204 std::shared_ptr<Geometry> Geometry::MakeRect(const Rect& rect) {
205 return std::make_shared<RectGeometry>(rect);
206 }
207
208 std::shared_ptr<Geometry> Geometry::MakeOval(const Rect& rect) {
209 return std::make_shared<EllipseGeometry>(rect);
210 }
211
212 std::shared_ptr<Geometry> Geometry::MakeLine(const Point& p0,
213 const Point& p1,
214 Scalar width,
215 Cap cap) {
216 return std::make_shared<LineGeometry>(p0, p1, width, cap);
217 }
218
219 std::shared_ptr<Geometry> Geometry::MakeCircle(const Point& center,
220 Scalar radius) {
221 return std::make_shared<CircleGeometry>(center, radius);
222 }
223
224 std::shared_ptr<Geometry> Geometry::MakeStrokedCircle(const Point& center,
225 Scalar radius,
226 Scalar stroke_width) {
227 return std::make_shared<CircleGeometry>(center, radius, stroke_width);
228 }
229
230 std::shared_ptr<Geometry> Geometry::MakeRoundRect(const Rect& rect,
231 const Size& radii) {
232 return std::make_shared<RoundRectGeometry>(rect, radii);
233 }
234
235 bool Geometry::CoversArea(const Matrix& transform, const Rect& rect) const {
236 return false;
237 }
238
239 bool Geometry::IsAxisAlignedRect() const {
240 return false;
241 }
242
243 bool Geometry::CanApplyMaskFilter() const {
244 return true;
245 }
246
247 } // namespace impeller
impeller::GeometryResult::Mode::kNormal
@ kNormal
The geometry has no overlapping triangles.
impeller::Entity::GetShaderTransform
Matrix GetShaderTransform(const RenderPass &pass) const
Get the vertex shader transform used for drawing this Entity.
Definition: entity.cc:53
impeller::Geometry::MakePointField
static std::shared_ptr< Geometry > MakePointField(std::vector< Point > points, Scalar radius, bool round)
Definition: geometry.cc:181
impeller::Geometry::MakeStrokedCircle
static std::shared_ptr< Geometry > MakeStrokedCircle(const Point &center, Scalar radius, Scalar stroke_width)
Definition: geometry.cc:224
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::Geometry::MakeStrokePath
static std::shared_ptr< Geometry > MakeStrokePath(const Path &path, Scalar stroke_width=0.0, Scalar miter_limit=4.0, Cap stroke_cap=Cap::kButt, Join stroke_join=Join::kMiter)
Definition: geometry.cc:187
stroke_path_geometry.h
impeller::Geometry::MakeRoundRect
static std::shared_ptr< Geometry > MakeRoundRect(const Rect &rect, const Size &radii)
Definition: geometry.cc:230
impeller::VertexBufferBuilder::GetVertexCount
size_t GetVertexCount() const
Definition: vertex_buffer_builder.h:54
cover_geometry.h
point_field_geometry.h
impeller::Geometry::CanApplyMaskFilter
virtual bool CanApplyMaskFilter() const
Definition: geometry.cc:243
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
rect_geometry.h
impeller::Geometry::IsAxisAlignedRect
virtual bool IsAxisAlignedRect() const
Definition: geometry.cc:239
impeller::Geometry::GetResultMode
virtual GeometryResult::Mode GetResultMode() const
Definition: geometry.cc:171
impeller::Geometry::CoversArea
virtual bool CoversArea(const Matrix &transform, const Rect &rect) const
Determines if this geometry, transformed by the given transform, will completely cover all surface ar...
Definition: geometry.cc:235
impeller::Tessellator::VertexGenerator::GenerateVertices
virtual void GenerateVertices(const TessellatedVertexProc &proc) const =0
Generate the vertices and deliver them in the necessary order (as required by the PrimitiveType) to t...
stroke_width
const Scalar stroke_width
Definition: stroke_path_geometry.cc:293
impeller::ComputeUVGeometryCPU
VertexBufferBuilder< TextureFillVertexShader::PerVertexData > ComputeUVGeometryCPU(VertexBufferBuilder< SolidFillVertexShader::PerVertexData > &input, Point texture_origin, Size texture_coverage, Matrix effect_transform)
Compute UV geometry for a VBB that contains only position geometry.
Definition: geometry.cc:93
impeller::GeometryResult::Mode
Mode
Definition: geometry.h:21
impeller::TRect::GetPoints
constexpr std::array< TPoint< T >, 4 > GetPoints() const
Get the points that represent the 4 corners of this rectangle in a Z order that is compatible with tr...
Definition: rect.h:382
impeller::Geometry::MakeOval
static std::shared_ptr< Geometry > MakeOval(const Rect &rect)
Definition: geometry.cc:208
impeller::Geometry::ComputePositionGeometry
static GeometryResult ComputePositionGeometry(const ContentContext &renderer, const Tessellator::VertexGenerator &generator, const Entity &entity, RenderPass &pass)
Definition: geometry.cc:25
impeller::Entity
Definition: entity.h:21
impeller::Geometry::MakeFillPath
static std::shared_ptr< Geometry > MakeFillPath(const Path &path, std::optional< Rect > inner_rect=std::nullopt)
Definition: geometry.cc:175
impeller::TSize
Definition: size.h:19
impeller::Tessellator::VertexGenerator
An object which produces a list of vertices as |Point|s that tessellate a previously provided shape a...
Definition: tessellator.h:93
impeller::PrimitiveType::kTriangleStrip
@ kTriangleStrip
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::VertexBufferBuilder
Definition: vertex_buffer_builder.h:24
impeller::Geometry::ComputePositionUVGeometry
static GeometryResult ComputePositionUVGeometry(const ContentContext &renderer, const Tessellator::VertexGenerator &generator, const Matrix &uv_transform, const Entity &entity, RenderPass &pass)
Definition: geometry.cc:57
geometry.h
impeller::Geometry::GetPositionUVBuffer
virtual GeometryResult GetPositionUVBuffer(Rect texture_coverage, Matrix effect_transform, const ContentContext &renderer, const Entity &entity, RenderPass &pass) const =0
Definition: geometry.cc:163
impeller::GeometryResult
Definition: geometry.h:20
impeller::IndexType::kNone
@ kNone
Does not use the index buffer.
ellipse_geometry.h
fill_path_geometry.h
impeller::VertexBufferBuilder::IterateVertices
void IterateVertices(const std::function< void(VertexType &)> &iterator)
Definition: vertex_buffer_builder.h:103
impeller::RenderPass
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:33
impeller::Geometry::MakeRect
static std::shared_ptr< Geometry > MakeRect(const Rect &rect)
Definition: geometry.cc:204
content_context.h
impeller::Join
Join
Definition: path.h:23
rect.h
impeller::Tessellator::VertexGenerator::GetTriangleType
virtual PrimitiveType GetTriangleType() const =0
Returns the |PrimitiveType| that describes the relationship among the list of vertices produced by th...
impeller::TPoint< Scalar >
impeller::VertexBufferBuilder::AppendVertex
VertexBufferBuilder & AppendVertex(VertexType_ vertex)
Definition: vertex_buffer_builder.h:65
impeller::Tessellator::VertexGenerator::GetVertexCount
virtual size_t GetVertexCount() const =0
Returns the number of vertices that the generator plans to produce, if known.
line_geometry.h
impeller::ComputeUVGeometryForRect
GeometryResult ComputeUVGeometryForRect(Rect source_rect, Rect texture_bounds, Matrix effect_transform, const ContentContext &renderer, const Entity &entity, RenderPass &pass)
Computes geometry and UV coordinates for a rectangle to be rendered.
Definition: geometry.cc:113
impeller::Geometry::MakeCircle
static std::shared_ptr< Geometry > MakeCircle(const Point &center, Scalar radius)
Definition: geometry.cc:219
circle_geometry.h
impeller::VertexBufferBuilder::Reserve
void Reserve(size_t count)
Definition: vertex_buffer_builder.h:48
round_rect_geometry.h
impeller
Definition: aiks_blur_unittests.cc:20
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::Cap
Cap
Definition: path.h:17
impeller::Geometry::MakeCover
static std::shared_ptr< Geometry > MakeCover()
Definition: geometry.cc:200
impeller::Geometry::MakeLine
static std::shared_ptr< Geometry > MakeLine(const Point &p0, const Point &p1, Scalar width, Cap cap)
Definition: geometry.cc:212