| Flutter Impeller |

canvas.h
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 #ifndef FLUTTER_IMPELLER_DISPLAY_LIST_CANVAS_H_
6 #define FLUTTER_IMPELLER_DISPLAY_LIST_CANVAS_H_
7
8 #include <deque>
9 #include <functional>
10 #include <memory>
11 #include <optional>
12 #include <utility>
13 #include <vector>
14
15 #include "display_list/effects/dl_image_filter.h"
16 #include "impeller/core/sampler_descriptor.h"
17 #include "impeller/display_list/paint.h"
18 #include "impeller/entity/contents/atlas_contents.h"
19 #include "impeller/entity/contents/clip_contents.h"
20 #include "impeller/entity/entity.h"
21 #include "impeller/entity/entity_pass_clip_stack.h"
22 #include "impeller/entity/geometry/geometry.h"
23 #include "impeller/entity/geometry/vertices_geometry.h"
24 #include "impeller/entity/inline_pass_context.h"
25 #include "impeller/geometry/matrix.h"
26 #include "impeller/geometry/path.h"
27 #include "impeller/geometry/point.h"
28 #include "impeller/geometry/round_rect.h"
29 #include "impeller/geometry/vector.h"
30 #include "impeller/renderer/snapshot.h"
31 #include "impeller/typographer/text_frame.h"
32
33 namespace impeller {
34
35 struct BackdropData {
36 size_t backdrop_count = 0;
37 bool all_filters_equal = true;
38 std::shared_ptr<Texture> texture_slot;
39 // A single snapshot of the backdrop filter that is used when there are
40 // multiple backdrops that share an identical filter.
41 std::optional<Snapshot> shared_filter_snapshot;
42 std::shared_ptr<flutter::DlImageFilter> last_backdrop;
43 };
44
45 struct CanvasStackEntry {
46 Matrix transform;
47 uint32_t clip_depth = 0u;
48 size_t clip_height = 0u;
49 // The number of clips tracked for this canvas stack entry.
50 size_t num_clips = 0u;
51 Scalar distributed_opacity = 1.0f;
52 Entity::RenderingMode rendering_mode = Entity::RenderingMode::kDirect;
53 // Whether all entities in the current save should be skipped.
54 bool skipping = false;
55 // Whether subpass coverage was rounded out to pixel coverage, or if false
56 // truncated.
57 bool did_round_out = false;
58 };
59
60 enum class PointStyle {
61 /// @brief Points are drawn as squares.
62 kRound,
63
64 /// @brief Points are drawn as circles.
65 kSquare,
66 };
67
68 /// Controls the behavior of the source rectangle given to DrawImageRect.
69 enum class SourceRectConstraint {
70 /// @brief Faster, but may sample outside the bounds of the source rectangle.
71 kFast,
72
73 /// @brief Sample only within the source rectangle. May be slower.
74 kStrict,
75 };
76
77 /// Specifies how much to trust the bounds rectangle provided for a list
78 /// of contents. Used by both |EntityPass| and |Canvas::SaveLayer|.
79 enum class ContentBoundsPromise {
80 /// @brief The caller makes no claims related to the size of the bounds.
81 kUnknown,
82
83 /// @brief The caller claims the bounds are a reasonably tight estimate
84 /// of the coverage of the contents and should contain all of the
85 /// contents.
86 kContainsContents,
87
88 /// @brief The caller claims the bounds are a subset of an estimate of
89 /// the reasonably tight bounds but likely clips off some of the
90 /// contents.
91 kMayClipContents,
92 };
93
94 struct LazyRenderingConfig {
95 std::unique_ptr<EntityPassTarget> entity_pass_target;
96 std::unique_ptr<InlinePassContext> inline_pass_context;
97
98 /// Whether or not the clear color texture can still be updated.
99 bool IsApplyingClearColor() const { return !inline_pass_context->IsActive(); }
100
101 LazyRenderingConfig(ContentContext& renderer,
102 std::unique_ptr<EntityPassTarget> p_entity_pass_target)
103 : entity_pass_target(std::move(p_entity_pass_target)) {
104 inline_pass_context =
105 std::make_unique<InlinePassContext>(renderer, *entity_pass_target);
106 }
107
108 LazyRenderingConfig(ContentContext& renderer,
109 std::unique_ptr<EntityPassTarget> entity_pass_target,
110 std::unique_ptr<InlinePassContext> inline_pass_context)
111 : entity_pass_target(std::move(entity_pass_target)),
112 inline_pass_context(std::move(inline_pass_context)) {}
113 };
114
115 class Canvas {
116 public:
117 static constexpr uint32_t kMaxDepth = 1 << 24;
118
119 using BackdropFilterProc = std::function<std::shared_ptr<FilterContents>(
120 FilterInput::Ref,
121 const Matrix& effect_transform,
122 Entity::RenderingMode rendering_mode)>;
123
124 Canvas(ContentContext& renderer,
125 const RenderTarget& render_target,
126 bool is_onscreen,
127 bool requires_readback);
128
129 explicit Canvas(ContentContext& renderer,
130 const RenderTarget& render_target,
131 bool is_onscreen,
132 bool requires_readback,
133 Rect cull_rect);
134
135 explicit Canvas(ContentContext& renderer,
136 const RenderTarget& render_target,
137 bool is_onscreen,
138 bool requires_readback,
139 IRect cull_rect);
140
141 ~Canvas() = default;
142
143 /// @brief Update the backdrop data used to group together backdrop filters
144 /// within the same layer
145 void SetBackdropData(std::unordered_map<int64_t, BackdropData> backdrop_data,
146 size_t backdrop_count);
147
148 /// @brief Return the culling bounds of the current render target, or nullopt
149 /// if there is no coverage.
150 std::optional<Rect> GetLocalCoverageLimit() const;
151
152 void Save(uint32_t total_content_depth = kMaxDepth);
153
154 void SaveLayer(
155 const Paint& paint,
156 std::optional<Rect> bounds = std::nullopt,
157 const flutter::DlImageFilter* backdrop_filter = nullptr,
158 ContentBoundsPromise bounds_promise = ContentBoundsPromise::kUnknown,
159 uint32_t total_content_depth = kMaxDepth,
160 bool can_distribute_opacity = false,
161 std::optional<int64_t> backdrop_id = std::nullopt);
162
163 bool Restore();
164
165 size_t GetSaveCount() const;
166
167 void RestoreToCount(size_t count);
168
169 const Matrix& GetCurrentTransform() const;
170
171 void ResetTransform();
172
173 void Transform(const Matrix& transform);
174
175 void Concat(const Matrix& transform);
176
177 void PreConcat(const Matrix& transform);
178
179 void Translate(const Vector3& offset);
180
181 void Scale(const Vector2& scale);
182
183 void Scale(const Vector3& scale);
184
185 void Skew(Scalar sx, Scalar sy);
186
187 void Rotate(Radians radians);
188
189 void DrawPath(const Path& path, const Paint& paint);
190
191 void DrawPaint(const Paint& paint);
192
193 void DrawLine(const Point& p0,
194 const Point& p1,
195 const Paint& paint,
196 bool reuse_depth = false);
197
198 void DrawRect(const Rect& rect, const Paint& paint);
199
200 void DrawOval(const Rect& rect, const Paint& paint);
201
202 void DrawRoundRect(const RoundRect& rect, const Paint& paint);
203
204 void DrawCircle(const Point& center, Scalar radius, const Paint& paint);
205
206 void DrawPoints(const Point points[],
207 uint32_t count,
208 Scalar radius,
209 const Paint& paint,
210 PointStyle point_style);
211
212 void DrawImage(const std::shared_ptr<Texture>& image,
213 Point offset,
214 const Paint& paint,
215 const SamplerDescriptor& sampler = {});
216
217 void DrawImageRect(
218 const std::shared_ptr<Texture>& image,
219 Rect source,
220 Rect dest,
221 const Paint& paint,
222 const SamplerDescriptor& sampler = {},
223 SourceRectConstraint src_rect_constraint = SourceRectConstraint::kFast);
224
225 void DrawTextFrame(const std::shared_ptr<TextFrame>& text_frame,
226 Point position,
227 const Paint& paint);
228
229 void DrawVertices(const std::shared_ptr<VerticesGeometry>& vertices,
230 BlendMode blend_mode,
231 const Paint& paint);
232
233 void DrawAtlas(const std::shared_ptr<AtlasContents>& atlas_contents,
234 const Paint& paint);
235
236 void ClipGeometry(const Geometry& geometry,
237 Entity::ClipOperation clip_op,
238 bool is_aa = true);
239
240 void EndReplay();
241
242 uint64_t GetOpDepth() const { return current_depth_; }
243
244 uint64_t GetMaxOpDepth() const { return transform_stack_.back().clip_depth; }
245
246 struct SaveLayerState {
247 Paint paint;
248 Rect coverage;
249 };
250
251 // Visible for testing.
252 bool RequiresReadback() const { return requires_readback_; }
253
254 // Whether the current device has the capabilities to blit an offscreen
255 // texture into the onscreen.
256 //
257 // This requires the availibility of the blit framebuffer command, but is
258 // disabled for GLES. A simple glBlitFramebuffer does not support resolving
259 // different sample counts which may be present in GLES when using MSAA.
260 //
261 // Visible for testing.
262 bool SupportsBlitToOnscreen() const;
263
264 private:
265 ContentContext& renderer_;
266 RenderTarget render_target_;
267 const bool is_onscreen_;
268 bool requires_readback_;
269 EntityPassClipStack clip_coverage_stack_;
270
271 std::deque<CanvasStackEntry> transform_stack_;
272 std::optional<Rect> initial_cull_rect_;
273 std::vector<LazyRenderingConfig> render_passes_;
274 std::vector<SaveLayerState> save_layer_state_;
275
276 /// Backdrop layers identified by an optional backdrop id.
277 ///
278 /// This is not the same as the [backdrop_count_] below as not
279 /// all backdrop filters will have an identified backdrop id. The
280 /// backdrop_count_ is also mutated during rendering.
281 std::unordered_map<int64_t, BackdropData> backdrop_data_;
282
283 /// The remaining number of backdrop filters.
284 ///
285 /// This value is decremented while rendering. When it reaches 0, then
286 /// the FlipBackdrop can use the onscreen render target instead of
287 /// another offscreen.
288 ///
289 /// This optimization is disabled on devices that do not support framebuffer
290 /// fetch (iOS Simulator and certain OpenGLES devices).
291 size_t backdrop_count_ = 0u;
292
293 // All geometry objects created for regular draws can be stack allocated,
294 // but clip geometries must be cached for record/replay for backdrop filters
295 // and so must be kept alive longer.
296 std::vector<std::unique_ptr<Geometry>> clip_geometry_;
297
298 uint64_t current_depth_ = 0u;
299
300 Point GetGlobalPassPosition() const;
301
302 // clip depth of the previous save or 0.
303 size_t GetClipHeightFloor() const;
304
305 /// @brief Whether all entites should be skipped until a corresponding
306 /// restore.
307 bool IsSkipping() const;
308
309 /// @brief Skip all rendering/clipping entities until next restore.
310 void SkipUntilMatchingRestore(size_t total_content_depth);
311
312 void SetupRenderPass();
313
314 /// @brief Ends the current render pass, saving the result as a texture, and
315 /// thenrestart it with the backdrop cleared to the previous contents.
316 ///
317 /// The returned texture is used as the input for backdrop filters and
318 /// emulated advanced blends. Returns nullptr if there was a validation
319 /// failure.
320 ///
321 /// [should_remove_texture] defaults to false. If true, the render target
322 /// texture is removed from the entity pass target. This allows the texture to
323 /// be cached by the canvas dispatcher for usage in the backdrop filter reuse
324 /// mechanism.
325 ///
326 /// [should_use_onscreen] defaults to false. If true, the results are flipped
327 /// to the onscreen render target. This will set requires_readback_ to false.
328 /// This action is only safe to perform when there are no more backdrop
329 /// filters or advanced blends, or no more backdrop filters and the device
330 /// supports framebuffer fetch.
331 std::shared_ptr<Texture> FlipBackdrop(Point global_pass_position,
332 bool should_remove_texture = false,
333 bool should_use_onscreen = false);
334
335 bool BlitToOnscreen(bool is_onscreen = false);
336
337 size_t GetClipHeight() const;
338
339 void Initialize(std::optional<Rect> cull_rect);
340
341 void Reset();
342
343 void AddRenderEntityWithFiltersToCurrentPass(Entity& entity,
344 const Geometry* geometry,
345 const Paint& paint,
346 bool reuse_depth = false);
347
348 void AddRenderEntityToCurrentPass(Entity& entity, bool reuse_depth = false);
349
350 bool AttemptDrawBlurredRRect(const Rect& rect,
351 Size corner_radii,
352 const Paint& paint);
353
354 RenderPass& GetCurrentRenderPass() const;
355
356 Canvas(const Canvas&) = delete;
357
358 Canvas& operator=(const Canvas&) = delete;
359 };
360
361 } // namespace impeller
362
363 #endif // FLUTTER_IMPELLER_DISPLAY_LIST_CANVAS_H_
impeller::LazyRenderingConfig::IsApplyingClearColor
bool IsApplyingClearColor() const
Whether or not the clear color texture can still be updated.
Definition: canvas.h:99
impeller::RoundRect
Definition: round_rect.h:15
impeller::CanvasStackEntry::distributed_opacity
Scalar distributed_opacity
Definition: canvas.h:51
impeller::CanvasStackEntry::skipping
bool skipping
Definition: canvas.h:54
point.h
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::Canvas::RestoreToCount
void RestoreToCount(size_t count)
Definition: canvas.cc:285
impeller::SourceRectConstraint::kFast
@ kFast
Faster, but may sample outside the bounds of the source rectangle.
impeller::ContentBoundsPromise::kMayClipContents
@ kMayClipContents
The caller claims the bounds are a subset of an estimate of the reasonably tight bounds but likely cl...
impeller::Canvas::RequiresReadback
bool RequiresReadback() const
Definition: canvas.h:252
impeller::Canvas::SaveLayer
void SaveLayer(const Paint &paint, std::optional< Rect > bounds=std::nullopt, const flutter::DlImageFilter *backdrop_filter=nullptr, ContentBoundsPromise bounds_promise=ContentBoundsPromise::kUnknown, uint32_t total_content_depth=kMaxDepth, bool can_distribute_opacity=false, std::optional< int64_t > backdrop_id=std::nullopt)
Definition: canvas.cc:966
geometry.h
entity.h
impeller::CanvasStackEntry
Definition: canvas.h:45
impeller::Paint
Definition: paint.h:26
impeller::BackdropData::texture_slot
std::shared_ptr< Texture > texture_slot
Definition: canvas.h:38
impeller::Canvas::Skew
void Skew(Scalar sx, Scalar sy)
Definition: canvas.cc:254
impeller::BlendMode
BlendMode
Definition: color.h:58
impeller::LazyRenderingConfig
Definition: canvas.h:94
impeller::PointStyle
PointStyle
Definition: canvas.h:60
impeller::Canvas::DrawTextFrame
void DrawTextFrame(const std::shared_ptr< TextFrame > &text_frame, Point position, const Paint &paint)
Definition: canvas.cc:1346
impeller::Canvas
Definition: canvas.h:115
impeller::PointStyle::kRound
@ kRound
Points are drawn as squares.
impeller::FilterInput::Ref
std::shared_ptr< FilterInput > Ref
Definition: filter_input.h:32
impeller::BackdropData
Definition: canvas.h:35
impeller::Canvas::ResetTransform
void ResetTransform()
Definition: canvas.cc:230
impeller::Canvas::DrawVertices
void DrawVertices(const std::shared_ptr< VerticesGeometry > &vertices, BlendMode blend_mode, const Paint &paint)
Definition: canvas.cc:739
impeller::ContentBoundsPromise
ContentBoundsPromise
Definition: canvas.h:79
impeller::ContentBoundsPromise::kUnknown
@ kUnknown
The caller makes no claims related to the size of the bounds.
impeller::CanvasStackEntry::num_clips
size_t num_clips
Definition: canvas.h:50
impeller::LazyRenderingConfig::LazyRenderingConfig
LazyRenderingConfig(ContentContext &renderer, std::unique_ptr< EntityPassTarget > p_entity_pass_target)
Definition: canvas.h:101
impeller::BackdropData::shared_filter_snapshot
std::optional< Snapshot > shared_filter_snapshot
Definition: canvas.h:41
impeller::CanvasStackEntry::rendering_mode
Entity::RenderingMode rendering_mode
Definition: canvas.h:52
impeller::Canvas::SetBackdropData
void SetBackdropData(std::unordered_map< int64_t, BackdropData > backdrop_data, size_t backdrop_count)
Update the backdrop data used to group together backdrop filters within the same layer.
Definition: canvas.cc:1558
impeller::BackdropData::backdrop_count
size_t backdrop_count
Definition: canvas.h:36
impeller::Canvas::DrawRect
void DrawRect(const Rect &rect, const Paint &paint)
Definition: canvas.cc:468
offset
SeparatedVector2 offset
Definition: stroke_path_geometry.cc:319
impeller::Canvas::GetCurrentTransform
const Matrix & GetCurrentTransform() const
Definition: canvas.cc:238
impeller::Canvas::Concat
void Concat(const Matrix &transform)
Definition: canvas.cc:222
impeller::Canvas::DrawRoundRect
void DrawRoundRect(const RoundRect &rect, const Paint &paint)
Definition: canvas.cc:516
impeller::CanvasStackEntry::clip_height
size_t clip_height
Definition: canvas.h:48
impeller::SamplerDescriptor
Definition: sampler_descriptor.h:14
matrix.h
impeller::BackdropData::all_filters_equal
bool all_filters_equal
Definition: canvas.h:37
impeller::Canvas::GetMaxOpDepth
uint64_t GetMaxOpDepth() const
Definition: canvas.h:244
impeller::Entity
Definition: entity.h:20
impeller::Canvas::SaveLayerState
Definition: canvas.h:246
impeller::SourceRectConstraint::kStrict
@ kStrict
Sample only within the source rectangle. May be slower.
impeller::TSize< Scalar >
impeller::PointStyle::kSquare
@ kSquare
Points are drawn as circles.
impeller::Point
TPoint< Scalar > Point
Definition: point.h:327
impeller::Canvas::Scale
void Scale(const Vector2 &scale)
Definition: canvas.cc:246
impeller::Canvas::ClipGeometry
void ClipGeometry(const Geometry &geometry, Entity::ClipOperation clip_op, bool is_aa=true)
Definition: canvas.cc:566
impeller::LazyRenderingConfig::LazyRenderingConfig
LazyRenderingConfig(ContentContext &renderer, std::unique_ptr< EntityPassTarget > entity_pass_target, std::unique_ptr< InlinePassContext > inline_pass_context)
Definition: canvas.h:108
impeller::Path
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
Definition: path.h:53
impeller::Canvas::GetLocalCoverageLimit
std::optional< Rect > GetLocalCoverageLimit() const
Return the culling bounds of the current render target, or nullopt if there is no coverage.
Definition: canvas.cc:935
impeller::LazyRenderingConfig::inline_pass_context
std::unique_ptr< InlinePassContext > inline_pass_context
Definition: canvas.h:96
transform
Matrix transform
Definition: gaussian_blur_filter_contents.cc:214
impeller::Canvas::SaveLayerState::coverage
Rect coverage
Definition: canvas.h:248
impeller::Canvas::~Canvas
~Canvas()=default
impeller::Canvas::DrawPoints
void DrawPoints(const Point points[], uint32_t count, Scalar radius, const Paint &paint, PointStyle point_style)
Definition: canvas.cc:647
impeller::Canvas::DrawImageRect
void DrawImageRect(const std::shared_ptr< Texture > &image, Rect source, Rect dest, const Paint &paint, const SamplerDescriptor &sampler={}, SourceRectConstraint src_rect_constraint=SourceRectConstraint::kFast)
Definition: canvas.cc:679
impeller::Canvas::DrawCircle
void DrawCircle(const Point &center, Scalar radius, const Paint &paint)
Definition: canvas.cc:543
impeller::SourceRectConstraint
SourceRectConstraint
Controls the behavior of the source rectangle given to DrawImageRect.
Definition: canvas.h:69
impeller::Canvas::Restore
bool Restore()
Definition: canvas.cc:1204
impeller::Radians
Definition: scalar.h:43
impeller::Entity::RenderingMode::kDirect
@ kDirect
impeller::CanvasStackEntry::clip_depth
uint32_t clip_depth
Definition: canvas.h:47
clip_contents.h
impeller::RenderTarget
Definition: render_target.h:38
impeller::Canvas::DrawPath
void DrawPath(const Path &path, const Paint &paint)
Definition: canvas.cc:293
impeller::Canvas::DrawPaint
void DrawPaint(const Paint &paint)
Definition: canvas.cc:308
impeller::Canvas::GetSaveCount
size_t GetSaveCount() const
Definition: canvas.cc:277
impeller::Canvas::SupportsBlitToOnscreen
bool SupportsBlitToOnscreen() const
Definition: canvas.cc:1684
vertices_geometry.h
impeller::Canvas::DrawAtlas
void DrawAtlas(const std::shared_ptr< AtlasContents > &atlas_contents, const Paint &paint)
Definition: canvas.cc:852
entity_pass_clip_stack.h
impeller::Canvas::GetOpDepth
uint64_t GetOpDepth() const
Definition: canvas.h:242
impeller::Canvas::PreConcat
void PreConcat(const Matrix &transform)
Definition: canvas.cc:226
impeller::Canvas::BackdropFilterProc
std::function< std::shared_ptr< FilterContents >(FilterInput::Ref, const Matrix &effect_transform, Entity::RenderingMode rendering_mode)> BackdropFilterProc
Definition: canvas.h:122
impeller::RenderPass
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:30
atlas_contents.h
sampler_descriptor.h
impeller::CanvasStackEntry::transform
Matrix transform
Definition: canvas.h:46
impeller::Canvas::DrawOval
void DrawOval(const Rect &rect, const Paint &paint)
Definition: canvas.cc:486
impeller::Geometry
Definition: geometry.h:50
impeller::Canvas::Rotate
void Rotate(Radians radians)
Definition: canvas.cc:258
vector.h
std
Definition: comparable.h:95
snapshot.h
impeller::Canvas::SaveLayerState::paint
Paint paint
Definition: canvas.h:247
impeller::TPoint< Scalar >
impeller::Canvas::Transform
void Transform(const Matrix &transform)
Definition: canvas.cc:234
impeller::Canvas::DrawLine
void DrawLine(const Point &p0, const Point &p1, const Paint &paint, bool reuse_depth=false)
Definition: canvas.cc:455
impeller::Canvas::DrawImage
void DrawImage(const std::shared_ptr< Texture > &image, Point offset, const Paint &paint, const SamplerDescriptor &sampler={})
Definition: canvas.cc:665
impeller::Canvas::Save
void Save(uint32_t total_content_depth=kMaxDepth)
Definition: canvas.cc:918
scale
const Scalar scale
Definition: stroke_path_geometry.cc:316
impeller::Entity::ClipOperation
ClipOperation
Definition: entity.h:61
impeller::EntityPassClipStack
A class that tracks all clips that have been recorded in the current entity pass stencil.
Definition: entity_pass_clip_stack.h:23
round_rect.h
impeller::LazyRenderingConfig::entity_pass_target
std::unique_ptr< EntityPassTarget > entity_pass_target
Definition: canvas.h:95
impeller::Entity::RenderingMode
RenderingMode
Definition: entity.h:27
impeller::Canvas::EndReplay
void EndReplay()
Definition: canvas.cc:1742
impeller::BackdropData::last_backdrop
std::shared_ptr< flutter::DlImageFilter > last_backdrop
Definition: canvas.h:42
text_frame.h
impeller::Canvas::Canvas
Canvas(ContentContext &renderer, const RenderTarget &render_target, bool is_onscreen, bool requires_readback)
Definition: canvas.cc:164
impeller::CanvasStackEntry::did_round_out
bool did_round_out
Definition: canvas.h:57
path.h
paint.h
impeller::ContentBoundsPromise::kContainsContents
@ kContainsContents
The caller claims the bounds are a reasonably tight estimate of the coverage of the contents and shou...
impeller
Definition: allocation.cc:12
impeller::ContentContext
Definition: content_context.h:371
impeller::TRect
Definition: rect.h:122
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::Vector3
Definition: vector.h:20
inline_pass_context.h
impeller::Canvas::Translate
void Translate(const Vector3 &offset)
Definition: canvas.cc:242
impeller::Canvas::kMaxDepth
static constexpr uint32_t kMaxDepth
Definition: canvas.h:117