Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
embedded_views.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_FLOW_EMBEDDED_VIEWS_H_
6#define FLUTTER_FLOW_EMBEDDED_VIEWS_H_
7
8#include <memory>
9#include <utility>
10#include <vector>
11
12#include "flutter/display_list/dl_builder.h"
13#include "flutter/display_list/skia/dl_sk_canvas.h"
14#include "flutter/flow/surface_frame.h"
15#include "flutter/fml/memory/ref_counted.h"
16#include "flutter/fml/raster_thread_merger.h"
22
23#if IMPELLER_SUPPORTS_RENDERING
24#include "flutter/impeller/aiks/aiks_context.h" // nogncheck
25#include "flutter/impeller/renderer/context.h" // nogncheck
26#else // IMPELLER_SUPPORTS_RENDERING
27namespace impeller {
28class Context;
29class AiksContext;
30} // namespace impeller
31#endif // !IMPELLER_SUPPORTS_RENDERING
32
33class GrDirectContext;
34
35namespace flutter {
36
45
46// Represents an image filter mutation.
47//
48// Should be used for image_filter_layer and backdrop_filter_layer.
49// TODO(cyanglaz): Refactor this into a ImageFilterMutator class.
50// https://github.com/flutter/flutter/issues/108470
52 public:
53 ImageFilterMutation(std::shared_ptr<const DlImageFilter> filter,
54 const SkRect& filter_rect)
55 : filter_(std::move(filter)), filter_rect_(filter_rect) {}
56
57 const DlImageFilter& GetFilter() const { return *filter_; }
58 const SkRect& GetFilterRect() const { return filter_rect_; }
59
60 bool operator==(const ImageFilterMutation& other) const {
61 return *filter_ == *other.filter_ && filter_rect_ == other.filter_rect_;
62 }
63
64 bool operator!=(const ImageFilterMutation& other) const {
65 return !operator==(other);
66 }
67
68 private:
69 std::shared_ptr<const DlImageFilter> filter_;
70 const SkRect filter_rect_;
71};
72
73// Stores mutation information like clipping or kTransform.
74//
75// The `type` indicates the type of the mutation: kClipRect, kTransform and etc.
76// Each `type` is paired with an object that supports the mutation. For example,
77// if the `type` is kClipRect, `rect()` is used the represent the rect to be
78// clipped. One mutation object must only contain one type of mutation.
79class Mutator {
80 public:
81 Mutator(const Mutator& other) {
82 type_ = other.type_;
83 switch (other.type_) {
84 case kClipRect:
85 rect_ = other.rect_;
86 break;
87 case kClipRRect:
88 rrect_ = other.rrect_;
89 break;
90 case kClipPath:
91 path_ = new SkPath(*other.path_);
92 break;
93 case kTransform:
94 matrix_ = other.matrix_;
95 break;
96 case kOpacity:
97 alpha_ = other.alpha_;
98 break;
99 case kBackdropFilter:
100 filter_mutation_ = other.filter_mutation_;
101 break;
102 default:
103 break;
104 }
105 }
106
107 explicit Mutator(const SkRect& rect) : type_(kClipRect), rect_(rect) {}
108 explicit Mutator(const SkRRect& rrect) : type_(kClipRRect), rrect_(rrect) {}
109 explicit Mutator(const SkPath& path)
110 : type_(kClipPath), path_(new SkPath(path)) {}
111 explicit Mutator(const SkMatrix& matrix)
112 : type_(kTransform), matrix_(matrix) {}
113 explicit Mutator(const int& alpha) : type_(kOpacity), alpha_(alpha) {}
114 explicit Mutator(const std::shared_ptr<const DlImageFilter>& filter,
115 const SkRect& filter_rect)
116 : type_(kBackdropFilter),
117 filter_mutation_(
118 std::make_shared<ImageFilterMutation>(filter, filter_rect)) {}
119
120 const MutatorType& GetType() const { return type_; }
121 const SkRect& GetRect() const { return rect_; }
122 const SkRRect& GetRRect() const { return rrect_; }
123 const SkPath& GetPath() const { return *path_; }
124 const SkMatrix& GetMatrix() const { return matrix_; }
126 return *filter_mutation_;
127 }
128 const int& GetAlpha() const { return alpha_; }
129 float GetAlphaFloat() const { return (alpha_ / 255.0f); }
130
131 bool operator==(const Mutator& other) const {
132 if (type_ != other.type_) {
133 return false;
134 }
135 switch (type_) {
136 case kClipRect:
137 return rect_ == other.rect_;
138 case kClipRRect:
139 return rrect_ == other.rrect_;
140 case kClipPath:
141 return *path_ == *other.path_;
142 case kTransform:
143 return matrix_ == other.matrix_;
144 case kOpacity:
145 return alpha_ == other.alpha_;
146 case kBackdropFilter:
147 return *filter_mutation_ == *other.filter_mutation_;
148 }
149
150 return false;
151 }
152
153 bool operator!=(const Mutator& other) const { return !operator==(other); }
154
155 bool IsClipType() {
156 return type_ == kClipRect || type_ == kClipRRect || type_ == kClipPath;
157 }
158
160 if (type_ == kClipPath) {
161 delete path_;
162 }
163 };
164
165 private:
166 MutatorType type_;
167
168 // TODO(cyanglaz): Remove union.
169 // https://github.com/flutter/flutter/issues/108470
170 union {
176 };
177
178 std::shared_ptr<ImageFilterMutation> filter_mutation_;
179}; // Mutator
180
181// A stack of mutators that can be applied to an embedded platform view.
182//
183// The stack may include mutators like transforms and clips, each mutator
184// applies to all the mutators that are below it in the stack and to the
185// embedded view.
186//
187// For example consider the following stack: [T1, T2, T3], where T1 is the top
188// of the stack and T3 is the bottom of the stack. Applying this mutators stack
189// to a platform view P1 will result in T1(T2(T3(P1))).
191 public:
192 MutatorsStack() = default;
193
194 void PushClipRect(const SkRect& rect);
195 void PushClipRRect(const SkRRect& rrect);
196 void PushClipPath(const SkPath& path);
197 void PushTransform(const SkMatrix& matrix);
198 void PushOpacity(const int& alpha);
199 // `filter_rect` is in global coordinates.
200 void PushBackdropFilter(const std::shared_ptr<const DlImageFilter>& filter,
201 const SkRect& filter_rect);
202
203 // Removes the `Mutator` on the top of the stack
204 // and destroys it.
205 void Pop();
206
207 void PopTo(size_t stack_count);
208
209 // Returns a reverse iterator pointing to the top of the stack, which is the
210 // mutator that is furtherest from the leaf node.
211 const std::vector<std::shared_ptr<Mutator>>::const_reverse_iterator Top()
212 const;
213 // Returns a reverse iterator pointing to the bottom of the stack, which is
214 // the mutator that is closeset from the leaf node.
215 const std::vector<std::shared_ptr<Mutator>>::const_reverse_iterator Bottom()
216 const;
217
218 // Returns an iterator pointing to the beginning of the mutator vector, which
219 // is the mutator that is furtherest from the leaf node.
220 const std::vector<std::shared_ptr<Mutator>>::const_iterator Begin() const;
221
222 // Returns an iterator pointing to the end of the mutator vector, which is the
223 // mutator that is closest from the leaf node.
224 const std::vector<std::shared_ptr<Mutator>>::const_iterator End() const;
225
226 bool is_empty() const { return vector_.empty(); }
227 size_t stack_count() const { return vector_.size(); }
228
229 bool operator==(const MutatorsStack& other) const {
230 if (vector_.size() != other.vector_.size()) {
231 return false;
232 }
233 for (size_t i = 0; i < vector_.size(); i++) {
234 if (*vector_[i] != *other.vector_[i]) {
235 return false;
236 }
237 }
238 return true;
239 }
240
241 bool operator==(const std::vector<Mutator>& other) const {
242 if (vector_.size() != other.size()) {
243 return false;
244 }
245 for (size_t i = 0; i < vector_.size(); i++) {
246 if (*vector_[i] != other[i]) {
247 return false;
248 }
249 }
250 return true;
251 }
252
253 bool operator!=(const MutatorsStack& other) const {
254 return !operator==(other);
255 }
256
257 bool operator!=(const std::vector<Mutator>& other) const {
258 return !operator==(other);
259 }
260
261 private:
262 std::vector<std::shared_ptr<Mutator>> vector_;
263}; // MutatorsStack
264
266 public:
268
270 SkSize size_points,
271 MutatorsStack mutators_stack)
272 : matrix_(matrix),
273 size_points_(size_points),
274 mutators_stack_(std::move(mutators_stack)) {
275 SkPath path;
276 SkRect starting_rect = SkRect::MakeSize(size_points);
277 path.addRect(starting_rect);
278 path.transform(matrix);
279 final_bounding_rect_ = path.getBounds();
280 }
281
282 // The transformation Matrix corresponding to the sum of all the
283 // transformations in the platform view's mutator stack.
284 const SkMatrix& transformMatrix() const { return matrix_; };
285 // The original size of the platform view before any mutation matrix is
286 // applied.
287 const SkSize& sizePoints() const { return size_points_; };
288 // The mutators stack contains the detailed step by step mutations for this
289 // platform view.
290 const MutatorsStack& mutatorsStack() const { return mutators_stack_; };
291 // The bounding rect of the platform view after applying all the mutations.
292 //
293 // Clippings are ignored.
294 const SkRect& finalBoundingRect() const { return final_bounding_rect_; }
295
296 // Pushes the stored DlImageFilter object to the mutators stack.
297 //
298 // `filter_rect` is in global coordinates.
299 void PushImageFilter(const std::shared_ptr<const DlImageFilter>& filter,
300 const SkRect& filter_rect) {
301 mutators_stack_.PushBackdropFilter(filter, filter_rect);
302 }
303
304 bool operator==(const EmbeddedViewParams& other) const {
305 return size_points_ == other.size_points_ &&
306 mutators_stack_ == other.mutators_stack_ &&
307 final_bounding_rect_ == other.final_bounding_rect_ &&
308 matrix_ == other.matrix_;
309 }
310
311 private:
312 SkMatrix matrix_;
313 SkSize size_points_;
314 MutatorsStack mutators_stack_;
315 SkRect final_bounding_rect_;
316};
317
319 // Frame has successfully rasterized.
320 kSuccess,
321 // Frame is submitted twice. This is currently only used when
322 // thread configuration change occurs.
324 // Frame is dropped and a new frame with the same layer tree is
325 // attempted. This is currently only used when thread configuration
326 // change occurs.
328};
329
330// The |EmbedderViewSlice| represents the details of recording all of
331// the layer tree rendering operations that appear between before, after
332// and between the embedded views. The Slice used to abstract away
333// implementations that were based on either an SkPicture or a
334// DisplayListBuilder but more recently all of the embedder recordings
335// have standardized on the DisplayList.
337 public:
338 virtual ~EmbedderViewSlice() = default;
339 virtual DlCanvas* canvas() = 0;
340 virtual void end_recording() = 0;
341 virtual const DlRegion& getRegion() const = 0;
342 DlRegion region(const SkRect& query) const {
344 }
345
346 virtual void render_into(DlCanvas* canvas) = 0;
347};
348
350 public:
351 explicit DisplayListEmbedderViewSlice(SkRect view_bounds);
352 ~DisplayListEmbedderViewSlice() override = default;
353
354 DlCanvas* canvas() override;
355 void end_recording() override;
356 const DlRegion& getRegion() const override;
357
358 void render_into(DlCanvas* canvas) override;
359 void dispatch(DlOpReceiver& receiver);
360 bool is_empty();
361 bool recording_ended();
362
363 private:
364 std::unique_ptr<DisplayListBuilder> builder_;
365 sk_sp<DisplayList> display_list_;
366};
367
368// Facilitates embedding of platform views within the flow layer tree.
369//
370// Used on iOS, Android (hybrid composite mode), and on embedded platforms
371// that provide a system compositor as part of the project arguments.
372//
373// There are two kinds of "view IDs" in the context of ExternalViewEmbedder, and
374// specific names are used to avoid ambiguation:
375//
376// * ExternalViewEmbedder composites a stack of layers. Each layer's content
377// might be from Flutter widgets, or a platform view, which displays platform
378// native components. Each platform view is labeled by a view ID, which
379// corresponds to the ID from `PlatformViewsRegistry.getNextPlatformViewId`
380// from the framework. In the context of `ExternalViewEmbedder`, this ID is
381// called platform_view_id.
382// * The layers are compositied into a single rectangular surface, displayed by
383// taking up an entire native window or part of a window. Each such surface
384// is labeled by a view ID, which corresponds to `FlutterView.viewID` from
385// dart:ui. In the context of `ExternalViewEmbedder`, this ID is called
386// flutter_view_id.
387//
388// The lifecycle of drawing a frame using ExternalViewEmbedder is:
389//
390// 1. At the start of a frame, call |BeginFrame|, then |SetUsedThisFrame| to
391// true.
392// 2. For each view to be drawn, call |PrepareFlutterView|, then
393// |SubmitFlutterView|.
394// 3. At the end of a frame, if |GetUsedThisFrame| is true, call |EndFrame|.
396 // TODO(cyanglaz): Make embedder own the `EmbeddedViewParams`.
397
398 public:
400
401 virtual ~ExternalViewEmbedder() = default;
402
403 // Deallocate the resources for displaying a view.
404 //
405 // This method must be called when a view is removed from the engine.
406 //
407 // When the ExternalViewEmbedder is requested to draw an unrecognized view, it
408 // implicitly allocates necessary resources. These resources must be
409 // explicitly deallocated.
410 virtual void CollectView(int64_t view_id);
411
412 // Usually, the root canvas is not owned by the view embedder. However, if
413 // the view embedder wants to provide a canvas to the rasterizer, it may
414 // return one here. This canvas takes priority over the canvas materialized
415 // from the on-screen render target.
416 virtual DlCanvas* GetRootCanvas() = 0;
417
418 // Call this in-lieu of |SubmitFlutterView| to clear pre-roll state and
419 // sets the stage for the next pre-roll.
420 virtual void CancelFrame() = 0;
421
422 // Indicates the beginning of a frame.
423 //
424 // The `raster_thread_merger` will be null if |SupportsDynamicThreadMerging|
425 // returns false.
426 virtual void BeginFrame(
427 GrDirectContext* context,
428 const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) = 0;
429
431 int64_t platform_view_id,
432 std::unique_ptr<EmbeddedViewParams> params) = 0;
433
434 // This needs to get called after |Preroll| finishes on the layer tree.
435 // Returns kResubmitFrame if the frame needs to be processed again, this is
436 // after it does any requisite tasks needed to bring itself to a valid state.
437 // Returns kSuccess if the view embedder is already in a valid state.
442
443 // Must be called on the UI thread.
444 virtual DlCanvas* CompositeEmbeddedView(int64_t platform_view_id) = 0;
445
446 // Prepare for a view to be drawn.
447 virtual void PrepareFlutterView(SkISize frame_size,
448 double device_pixel_ratio) = 0;
449
450 // Submits the content stored since |PrepareFlutterView| to the specified
451 // Flutter view.
452 //
453 // Implementers must submit the frame by calling frame.Submit().
454 //
455 // This method can mutate the root Skia canvas before submitting the frame.
456 //
457 // It can also allocate frames for overlay surfaces to compose hybrid views.
458 virtual void SubmitFlutterView(
459 int64_t flutter_view_id,
460 GrDirectContext* context,
461 const std::shared_ptr<impeller::AiksContext>& aiks_context,
462 std::unique_ptr<SurfaceFrame> frame);
463
464 // This method provides the embedder a way to do additional tasks after
465 // |SubmitFrame|. For example, merge task runners if `should_resubmit_frame`
466 // is true.
467 //
468 // For example on the iOS embedder, threads are merged in this call.
469 // A new frame on the platform thread starts immediately. If the GPU thread
470 // still has some task running, there could be two frames being rendered
471 // concurrently, which causes undefined behaviors.
472 //
473 // The `raster_thread_merger` will be null if |SupportsDynamicThreadMerging|
474 // returns false.
475 virtual void EndFrame(
476 bool should_resubmit_frame,
477 const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {}
478
479 // Whether the embedder should support dynamic thread merging.
480 //
481 // Returning `true` results a |RasterThreadMerger| instance to be created.
482 // * See also |BegineFrame| and |EndFrame| for getting the
483 // |RasterThreadMerger| instance.
484 virtual bool SupportsDynamicThreadMerging();
485
486 // Called when the rasterizer is being torn down.
487 // This method provides a way to release resources associated with the current
488 // embedder.
489 virtual void Teardown();
490
491 // Change the flag about whether it is used in this frame, it will be set to
492 // true when 'BeginFrame' and false when 'EndFrame'.
493 void SetUsedThisFrame(bool used_this_frame) {
494 used_this_frame_ = used_this_frame;
495 }
496
497 // Whether it is used in this frame, returns true between 'BeginFrame' and
498 // 'EndFrame', otherwise returns false.
499 bool GetUsedThisFrame() const { return used_this_frame_; }
500
501 // Pushes the platform view id of a visited platform view to a list of
502 // visited platform views.
503 virtual void PushVisitedPlatformView(int64_t platform_view_id) {}
504
505 // Pushes a DlImageFilter object to each platform view within a list of
506 // visited platform views.
507 //
508 // `filter_rect` is in global coordinates.
509 //
510 // See also: |PushVisitedPlatformView| for pushing platform view ids to the
511 // visited platform views list.
513 const std::shared_ptr<const DlImageFilter>& filter,
514 const SkRect& filter_rect) {}
515
516 private:
517 bool used_this_frame_ = false;
518
520
521}; // ExternalViewEmbedder
522
523} // namespace flutter
524
525#endif // FLUTTER_FLOW_EMBEDDED_VIEWS_H_
void dispatch(DlOpReceiver &receiver)
~DisplayListEmbedderViewSlice() override=default
const DlRegion & getRegion() const override
void render_into(DlCanvas *canvas) override
Developer-facing API for rendering anything within the engine.
Definition dl_canvas.h:37
Internal API for rendering recorded display lists to backends.
static DlRegion MakeIntersection(const DlRegion &a, const DlRegion &b)
Definition dl_region.cc:497
const SkSize & sizePoints() const
void PushImageFilter(const std::shared_ptr< const DlImageFilter > &filter, const SkRect &filter_rect)
const SkRect & finalBoundingRect() const
const SkMatrix & transformMatrix() const
EmbeddedViewParams(SkMatrix matrix, SkSize size_points, MutatorsStack mutators_stack)
bool operator==(const EmbeddedViewParams &other) const
const MutatorsStack & mutatorsStack() const
virtual void render_into(DlCanvas *canvas)=0
virtual DlCanvas * canvas()=0
virtual ~EmbedderViewSlice()=default
virtual void end_recording()=0
DlRegion region(const SkRect &query) const
virtual const DlRegion & getRegion() const =0
virtual void PushFilterToVisitedPlatformViews(const std::shared_ptr< const DlImageFilter > &filter, const SkRect &filter_rect)
virtual bool SupportsDynamicThreadMerging()
virtual void EndFrame(bool should_resubmit_frame, const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger)
virtual void BeginFrame(GrDirectContext *context, const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger)=0
virtual void PrerollCompositeEmbeddedView(int64_t platform_view_id, std::unique_ptr< EmbeddedViewParams > params)=0
virtual void PushVisitedPlatformView(int64_t platform_view_id)
virtual void CollectView(int64_t view_id)
virtual DlCanvas * CompositeEmbeddedView(int64_t platform_view_id)=0
void SetUsedThisFrame(bool used_this_frame)
virtual void PrepareFlutterView(SkISize frame_size, double device_pixel_ratio)=0
virtual DlCanvas * GetRootCanvas()=0
virtual ~ExternalViewEmbedder()=default
virtual PostPrerollResult PostPrerollAction(const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger)
virtual void SubmitFlutterView(int64_t flutter_view_id, GrDirectContext *context, const std::shared_ptr< impeller::AiksContext > &aiks_context, std::unique_ptr< SurfaceFrame > frame)
virtual void CancelFrame()=0
bool operator!=(const ImageFilterMutation &other) const
bool operator==(const ImageFilterMutation &other) const
const SkRect & GetFilterRect() const
ImageFilterMutation(std::shared_ptr< const DlImageFilter > filter, const SkRect &filter_rect)
const DlImageFilter & GetFilter() const
float GetAlphaFloat() const
const SkMatrix & GetMatrix() const
Mutator(const SkRRect &rrect)
const ImageFilterMutation & GetFilterMutation() const
const MutatorType & GetType() const
Mutator(const std::shared_ptr< const DlImageFilter > &filter, const SkRect &filter_rect)
const SkPath & GetPath() const
const SkRRect & GetRRect() const
bool operator==(const Mutator &other) const
Mutator(const SkMatrix &matrix)
const int & GetAlpha() const
Mutator(const Mutator &other)
bool operator!=(const Mutator &other) const
Mutator(const int &alpha)
Mutator(const SkRect &rect)
Mutator(const SkPath &path)
const SkRect & GetRect() const
size_t stack_count() const
void PushClipPath(const SkPath &path)
void PushOpacity(const int &alpha)
bool operator==(const MutatorsStack &other) const
bool operator==(const std::vector< Mutator > &other) const
const std::vector< std::shared_ptr< Mutator > >::const_reverse_iterator Top() const
bool operator!=(const std::vector< Mutator > &other) const
const std::vector< std::shared_ptr< Mutator > >::const_reverse_iterator Bottom() const
void PushBackdropFilter(const std::shared_ptr< const DlImageFilter > &filter, const SkRect &filter_rect)
const std::vector< std::shared_ptr< Mutator > >::const_iterator End() const
void PopTo(size_t stack_count)
void PushClipRect(const SkRect &rect)
void PushTransform(const SkMatrix &matrix)
const std::vector< std::shared_ptr< Mutator > >::const_iterator Begin() const
void PushClipRRect(const SkRRect &rrect)
bool operator!=(const MutatorsStack &other) const
const EmbeddedViewParams * params
double frame
Definition examples.cpp:31
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition macros.h:27
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switches.h:57
Definition ref_ptr.h:256
void roundOut(SkIRect *dst) const
Definition SkRect.h:1241
static constexpr SkRect MakeSize(const SkSize &size)
Definition SkRect.h:633