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 
6 
7 #include "fml/logging.h"
12 
13 namespace impeller {
14 
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{
29  .vertex_buffer =
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;
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{
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 {
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