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 <variant>
11#include <vector>
12
18
19#if IMPELLER_SUPPORTS_RENDERING
21#include "flutter/impeller/renderer/context.h" // nogncheck
22#else // IMPELLER_SUPPORTS_RENDERING
23namespace impeller {
24class Context;
25class AiksContext;
26} // namespace impeller
27#endif // !IMPELLER_SUPPORTS_RENDERING
28
29class GrDirectContext;
30
31namespace flutter {
32
42
43// Represents an image filter mutation.
44//
45// Should be used for image_filter_layer and backdrop_filter_layer.
47 public:
48 ImageFilterMutation(std::shared_ptr<DlImageFilter> filter,
49 const DlRect& filter_rect)
50 : filter_(std::move(filter)), filter_rect_(filter_rect) {}
51
52 const DlImageFilter& GetFilter() const { return *filter_; }
53 const DlRect& GetFilterRect() const { return filter_rect_; }
54
55 bool operator==(const ImageFilterMutation& other) const {
56 return *filter_ == *other.filter_ && filter_rect_ == other.filter_rect_;
57 }
58
59 private:
60 std::shared_ptr<DlImageFilter> filter_;
61 const DlRect filter_rect_;
62};
63
64// Stores mutation information like clipping or kTransform.
65//
66// The `type` indicates the type of the mutation: kClipRect, kTransform and etc.
67// Each `type` is paired with an object that supports the mutation. For example,
68// if the `type` is kClipRect, `rect()` is used the represent the rect to be
69// clipped. One mutation object must only contain one type of mutation.
70class Mutator {
71 public:
72 Mutator(const Mutator& other) : data_(other.data_) {}
73
74 explicit Mutator(const DlRect& rect) : data_(rect) {}
75 explicit Mutator(const DlRoundRect& rrect) : data_(rrect) {}
76 explicit Mutator(const DlRoundSuperellipse& rrect) : data_(rrect) {}
77 explicit Mutator(const DlPath& path) : data_(path) {}
78 explicit Mutator(const DlMatrix& matrix) : data_(matrix) {}
79 explicit Mutator(const uint8_t& alpha) : data_(alpha) {}
80 explicit Mutator(const std::shared_ptr<DlImageFilter>& filter,
81 const DlRect& filter_rect)
82 : data_(ImageFilterMutation(filter, filter_rect)) {}
83
85 return static_cast<MutatorType>(data_.index());
86 }
87
88 const DlRect& GetRect() const { return std::get<DlRect>(data_); }
89 const DlRoundRect& GetRRect() const { return std::get<DlRoundRect>(data_); }
90 const DlRoundSuperellipse& GetRSE() const {
91 return std::get<DlRoundSuperellipse>(data_);
92 }
95 }
96 const DlPath& GetPath() const { return std::get<DlPath>(data_); }
97 const DlMatrix& GetMatrix() const { return std::get<DlMatrix>(data_); }
99 return std::get<ImageFilterMutation>(data_);
100 }
101 const uint8_t& GetAlpha() const { return std::get<uint8_t>(data_); }
102 float GetAlphaFloat() const { return DlColor::toOpacity(GetAlpha()); }
103
104 bool operator==(const Mutator& other) const { return data_ == other.data_; }
105
106 bool IsClipType() {
107 switch (GetType()) {
112 return true;
116 return false;
117 }
118 }
119
120 private:
121 std::variant<DlRect,
124 DlPath,
125 DlMatrix,
126 uint8_t,
128 data_;
129}; // Mutator
130
131// A stack of mutators that can be applied to an embedded platform view.
132//
133// The stack may include mutators like transforms and clips, each mutator
134// applies to all the mutators that are below it in the stack and to the
135// embedded view.
136//
137// For example consider the following stack: [T1, T2, T3], where T1 is the top
138// of the stack and T3 is the bottom of the stack. Applying this mutators stack
139// to a platform view P1 will result in T1(T2(T3(P1))).
141 public:
142 MutatorsStack() = default;
143
144 void PushClipRect(const DlRect& rect);
145 void PushClipRRect(const DlRoundRect& rrect);
146 void PushClipRSE(const DlRoundSuperellipse& rrect);
147 void PushClipPath(const DlPath& path);
148 void PushTransform(const DlMatrix& matrix);
149 void PushOpacity(const uint8_t& alpha);
150 // `filter_rect` is in global coordinates.
151 void PushBackdropFilter(const std::shared_ptr<DlImageFilter>& filter,
152 const DlRect& filter_rect);
153
154 // Removes the `Mutator` on the top of the stack
155 // and destroys it.
156 void Pop();
157
158 void PopTo(size_t stack_count);
159
160 // Returns a reverse iterator pointing to the top of the stack, which is the
161 // mutator that is furtherest from the leaf node.
162 const std::vector<std::shared_ptr<Mutator>>::const_reverse_iterator Top()
163 const;
164 // Returns a reverse iterator pointing to the bottom of the stack, which is
165 // the mutator that is closeset from the leaf node.
166 const std::vector<std::shared_ptr<Mutator>>::const_reverse_iterator Bottom()
167 const;
168
169 // Returns an iterator pointing to the beginning of the mutator vector, which
170 // is the mutator that is furtherest from the leaf node.
171 const std::vector<std::shared_ptr<Mutator>>::const_iterator Begin() const;
172
173 // Returns an iterator pointing to the end of the mutator vector, which is the
174 // mutator that is closest from the leaf node.
175 const std::vector<std::shared_ptr<Mutator>>::const_iterator End() const;
176
177 bool is_empty() const { return vector_.empty(); }
178 size_t stack_count() const { return vector_.size(); }
179
180 bool operator==(const MutatorsStack& other) const {
181 if (vector_.size() != other.vector_.size()) {
182 return false;
183 }
184 for (size_t i = 0; i < vector_.size(); i++) {
185 if (*vector_[i] != *other.vector_[i]) {
186 return false;
187 }
188 }
189 return true;
190 }
191
192 bool operator==(const std::vector<Mutator>& other) const {
193 if (vector_.size() != other.size()) {
194 return false;
195 }
196 for (size_t i = 0; i < vector_.size(); i++) {
197 if (*vector_[i] != other[i]) {
198 return false;
199 }
200 }
201 return true;
202 }
203
204 bool operator!=(const MutatorsStack& other) const {
205 return !operator==(other);
206 }
207
208 bool operator!=(const std::vector<Mutator>& other) const {
209 return !operator==(other);
210 }
211
212 private:
213 std::vector<std::shared_ptr<Mutator>> vector_;
214}; // MutatorsStack
215
217 public:
219
221 DlSize size_points,
222 MutatorsStack mutators_stack)
223 : matrix_(matrix),
224 size_points_(size_points),
225 mutators_stack_(std::move(mutators_stack)) {
226 final_bounding_rect_ =
227 DlRect::MakeSize(size_points).TransformAndClipBounds(matrix);
228 }
229
230 // The transformation Matrix corresponding to the sum of all the
231 // transformations in the platform view's mutator stack.
232 const DlMatrix& transformMatrix() const { return matrix_; };
233 // The original size of the platform view before any mutation matrix is
234 // applied.
235 const DlSize& sizePoints() const { return size_points_; };
236 // The mutators stack contains the detailed step by step mutations for this
237 // platform view.
238 const MutatorsStack& mutatorsStack() const { return mutators_stack_; };
239 // The bounding rect of the platform view after applying all the mutations.
240 //
241 // Clippings are ignored.
242 const DlRect& finalBoundingRect() const { return final_bounding_rect_; }
243
244 // Pushes the stored DlImageFilter object to the mutators stack.
245 //
246 // `filter_rect` is in global coordinates.
247 void PushImageFilter(const std::shared_ptr<DlImageFilter>& filter,
248 const DlRect& filter_rect) {
249 mutators_stack_.PushBackdropFilter(filter, filter_rect);
250 }
251
252 bool operator==(const EmbeddedViewParams& other) const {
253 return size_points_ == other.size_points_ &&
254 mutators_stack_ == other.mutators_stack_ &&
255 final_bounding_rect_ == other.final_bounding_rect_ &&
256 matrix_ == other.matrix_;
257 }
258
259 private:
260 DlMatrix matrix_;
261 DlSize size_points_;
262 MutatorsStack mutators_stack_;
263 DlRect final_bounding_rect_;
264};
265
267 // Frame has successfully rasterized.
268 kSuccess,
269 // Frame is submitted twice. This is currently only used when
270 // thread configuration change occurs.
272 // Frame is dropped and a new frame with the same layer tree is
273 // attempted. This is currently only used when thread configuration
274 // change occurs.
276};
277
278// The |EmbedderViewSlice| represents the details of recording all of
279// the layer tree rendering operations that appear before, after
280// and between the embedded views.
282 public:
283 virtual ~EmbedderViewSlice() = default;
284 virtual DlCanvas* canvas() = 0;
285 virtual void end_recording() = 0;
286 virtual const DlRegion& getRegion() const = 0;
287 DlRegion region(const DlRect& query) const {
288 DlRegion rquery = DlRegion(DlIRect::RoundOut(query));
289 return DlRegion::MakeIntersection(getRegion(), rquery);
290 }
291
292 virtual void render_into(DlCanvas* canvas) = 0;
293};
294
296 public:
297 explicit DisplayListEmbedderViewSlice(DlRect view_bounds);
298 ~DisplayListEmbedderViewSlice() override = default;
299
300 DlCanvas* canvas() override;
301 void end_recording() override;
302 const DlRegion& getRegion() const override;
303
304 void render_into(DlCanvas* canvas) override;
305 void dispatch(DlOpReceiver& receiver);
306 bool is_empty();
307 bool recording_ended();
308
309 private:
310 std::unique_ptr<DisplayListBuilder> builder_;
311 sk_sp<DisplayList> display_list_;
312};
313
314// Facilitates embedding of platform views within the flow layer tree.
315//
316// Used on iOS, Android (hybrid composite mode), and on embedded platforms
317// that provide a system compositor as part of the project arguments.
318//
319// There are two kinds of "view IDs" in the context of ExternalViewEmbedder, and
320// specific names are used to avoid ambiguation:
321//
322// * ExternalViewEmbedder composites a stack of layers. Each layer's content
323// might be from Flutter widgets, or a platform view, which displays platform
324// native components. Each platform view is labeled by a view ID, which
325// corresponds to the ID from `PlatformViewsRegistry.getNextPlatformViewId`
326// from the framework. In the context of `ExternalViewEmbedder`, this ID is
327// called platform_view_id.
328// * The layers are compositied into a single rectangular surface, displayed by
329// taking up an entire native window or part of a window. Each such surface
330// is labeled by a view ID, which corresponds to `FlutterView.viewID` from
331// dart:ui. In the context of `ExternalViewEmbedder`, this ID is called
332// flutter_view_id.
333//
334// The lifecycle of drawing a frame using ExternalViewEmbedder is:
335//
336// 1. At the start of a frame, call |BeginFrame|, then |SetUsedThisFrame| to
337// true.
338// 2. For each view to be drawn, call |PrepareFlutterView|, then
339// |SubmitFlutterView|.
340// 3. At the end of a frame, if |GetUsedThisFrame| is true, call |EndFrame|.
342 // TODO(cyanglaz): Make embedder own the `EmbeddedViewParams`.
343
344 public:
346
347 virtual ~ExternalViewEmbedder() = default;
348
349 // Deallocate the resources for displaying a view.
350 //
351 // This method must be called when a view is removed from the engine.
352 //
353 // When the ExternalViewEmbedder is requested to draw an unrecognized view, it
354 // implicitly allocates necessary resources. These resources must be
355 // explicitly deallocated.
356 virtual void CollectView(int64_t view_id);
357
358 // Usually, the root canvas is not owned by the view embedder. However, if
359 // the view embedder wants to provide a canvas to the rasterizer, it may
360 // return one here. This canvas takes priority over the canvas materialized
361 // from the on-screen render target.
362 virtual DlCanvas* GetRootCanvas() = 0;
363
364 // Call this in-lieu of |SubmitFlutterView| to clear pre-roll state and
365 // sets the stage for the next pre-roll.
366 virtual void CancelFrame() = 0;
367
368 // Indicates the beginning of a frame.
369 //
370 // The `raster_thread_merger` will be null if |SupportsDynamicThreadMerging|
371 // returns false.
372 virtual void BeginFrame(
373 GrDirectContext* context,
374 const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) = 0;
375
377 int64_t platform_view_id,
378 std::unique_ptr<EmbeddedViewParams> params) = 0;
379
380 // This needs to get called after |Preroll| finishes on the layer tree.
381 // Returns kResubmitFrame if the frame needs to be processed again, this is
382 // after it does any requisite tasks needed to bring itself to a valid state.
383 // Returns kSuccess if the view embedder is already in a valid state.
388
389 // Must be called on the UI thread.
390 virtual DlCanvas* CompositeEmbeddedView(int64_t platform_view_id) = 0;
391
392 // Prepare for a view to be drawn.
393 virtual void PrepareFlutterView(DlISize frame_size,
394 double device_pixel_ratio) = 0;
395
396 // Submits the content stored since |PrepareFlutterView| to the specified
397 // Flutter view.
398 //
399 // Implementers must submit the frame by calling frame.Submit().
400 //
401 // This method can mutate the root canvas before submitting the frame.
402 //
403 // It can also allocate frames for overlay surfaces to compose hybrid views.
404 virtual void SubmitFlutterView(
405 int64_t flutter_view_id,
406 GrDirectContext* context,
407 const std::shared_ptr<impeller::AiksContext>& aiks_context,
408 std::unique_ptr<SurfaceFrame> frame);
409
410 // This method provides the embedder a way to do additional tasks after
411 // |SubmitFrame|. For example, merge task runners if `should_resubmit_frame`
412 // is true.
413 //
414 // For example on the iOS embedder, threads are merged in this call.
415 // A new frame on the platform thread starts immediately. If the GPU thread
416 // still has some task running, there could be two frames being rendered
417 // concurrently, which causes undefined behaviors.
418 //
419 // The `raster_thread_merger` will be null if |SupportsDynamicThreadMerging|
420 // returns false.
421 virtual void EndFrame(
422 bool should_resubmit_frame,
423 const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {}
424
425 // Whether the embedder should support dynamic thread merging.
426 //
427 // Returning `true` results a |RasterThreadMerger| instance to be created.
428 // * See also |BegineFrame| and |EndFrame| for getting the
429 // |RasterThreadMerger| instance.
430 virtual bool SupportsDynamicThreadMerging();
431
432 // Called when the rasterizer is being torn down.
433 // This method provides a way to release resources associated with the current
434 // embedder.
435 virtual void Teardown();
436
437 // Change the flag about whether it is used in this frame, it will be set to
438 // true when 'BeginFrame' and false when 'EndFrame'.
439 void SetUsedThisFrame(bool used_this_frame) {
440 used_this_frame_ = used_this_frame;
441 }
442
443 // Whether it is used in this frame, returns true between 'BeginFrame' and
444 // 'EndFrame', otherwise returns false.
445 bool GetUsedThisFrame() const { return used_this_frame_; }
446
447 // Pushes the platform view id of a visited platform view to a list of
448 // visited platform views.
449 virtual void PushVisitedPlatformView(int64_t platform_view_id) {}
450
451 // Pushes a DlImageFilter object to each platform view within a list of
452 // visited platform views.
453 //
454 // `filter_rect` is in global coordinates.
455 //
456 // See also: |PushVisitedPlatformView| for pushing platform view ids to the
457 // visited platform views list.
459 const std::shared_ptr<DlImageFilter>& filter,
460 const DlRect& filter_rect) {}
461
462 private:
463 bool used_this_frame_ = false;
464
466
467}; // ExternalViewEmbedder
468
469} // namespace flutter
470
471#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:32
Internal API for rendering recorded display lists to backends.
static DlRegion MakeIntersection(const DlRegion &a, const DlRegion &b)
Definition dl_region.cc:496
void PushImageFilter(const std::shared_ptr< DlImageFilter > &filter, const DlRect &filter_rect)
const DlSize & sizePoints() const
const DlRect & finalBoundingRect() const
EmbeddedViewParams(DlMatrix matrix, DlSize size_points, MutatorsStack mutators_stack)
bool operator==(const EmbeddedViewParams &other) const
const MutatorsStack & mutatorsStack() const
const DlMatrix & transformMatrix() const
DlRegion region(const DlRect &query) const
virtual void render_into(DlCanvas *canvas)=0
virtual DlCanvas * canvas()=0
virtual ~EmbedderViewSlice()=default
virtual void end_recording()=0
virtual const DlRegion & getRegion() const =0
virtual bool SupportsDynamicThreadMerging()
virtual void PrepareFlutterView(DlISize frame_size, double device_pixel_ratio)=0
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 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
virtual void PushFilterToVisitedPlatformViews(const std::shared_ptr< DlImageFilter > &filter, const DlRect &filter_rect)
ImageFilterMutation(std::shared_ptr< DlImageFilter > filter, const DlRect &filter_rect)
bool operator==(const ImageFilterMutation &other) const
const DlRect & GetFilterRect() const
const DlImageFilter & GetFilter() const
Mutator(const DlPath &path)
const DlMatrix & GetMatrix() const
float GetAlphaFloat() const
const ImageFilterMutation & GetFilterMutation() const
const uint8_t & GetAlpha() const
Mutator(const DlRoundSuperellipse &rrect)
MutatorType GetType() const
const DlRoundRect GetRSEApproximation() const
const DlPath & GetPath() const
Mutator(const DlRect &rect)
bool operator==(const Mutator &other) const
Mutator(const DlMatrix &matrix)
Mutator(const std::shared_ptr< DlImageFilter > &filter, const DlRect &filter_rect)
Mutator(const DlRoundRect &rrect)
Mutator(const Mutator &other)
const DlRoundSuperellipse & GetRSE() const
Mutator(const uint8_t &alpha)
const DlRect & GetRect() const
const DlRoundRect & GetRRect() const
size_t stack_count() const
void PushTransform(const DlMatrix &matrix)
void PushBackdropFilter(const std::shared_ptr< DlImageFilter > &filter, const DlRect &filter_rect)
void PushClipRect(const DlRect &rect)
void PushClipPath(const DlPath &path)
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
const std::vector< std::shared_ptr< Mutator > >::const_iterator End() const
void PopTo(size_t stack_count)
void PushClipRRect(const DlRoundRect &rrect)
void PushOpacity(const uint8_t &alpha)
void PushClipRSE(const DlRoundSuperellipse &rrect)
const std::vector< std::shared_ptr< Mutator > >::const_iterator Begin() const
bool operator!=(const MutatorsStack &other) const
const EmbeddedViewParams * params
G_BEGIN_DECLS FlutterViewId view_id
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition macros.h:27
impeller::RoundRect DlRoundRect
impeller::Matrix DlMatrix
impeller::Rect DlRect
impeller::RoundSuperellipse DlRoundSuperellipse
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 switch_defs.h:52
Definition ref_ptr.h:261
static constexpr DlScalar toOpacity(uint8_t alpha)
Definition dl_color.h:65
A 4x4 matrix using column-major storage.
Definition matrix.h:37
RoundRect ToApproximateRoundRect() const
RoundOut(const TRect< U > &r)
Definition rect.h:679
constexpr TRect TransformAndClipBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle, clipped against the near clippin...
Definition rect.h:438
static constexpr TRect MakeSize(const TSize< U > &size)
Definition rect.h:150