Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
external_view_embedder_2.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
7#include "flow/view_slicer.h"
10#include "fml/make_copyable.h"
12
13namespace flutter {
14
16 const AndroidContext& android_context,
17 std::shared_ptr<PlatformViewAndroidJNI> jni_facade,
18 std::shared_ptr<AndroidSurfaceFactory> surface_factory,
19 const TaskRunners& task_runners)
21 android_context_(android_context),
22 jni_facade_(std::move(jni_facade)),
23 surface_factory_(std::move(surface_factory)),
24 surface_pool_(
25 std::make_unique<SurfacePool>(/*use_new_surface_methods=*/true)),
26 task_runners_(task_runners) {}
27
28// |ExternalViewEmbedder|
30 int64_t view_id,
31 std::unique_ptr<EmbeddedViewParams> params) {
32 TRACE_EVENT0("flutter",
33 "AndroidExternalViewEmbedder2::PrerollCompositeEmbeddedView");
34
35 DlRect view_bounds = DlRect::MakeSize(frame_size_);
36 std::unique_ptr<EmbedderViewSlice> view;
37 view = std::make_unique<DisplayListEmbedderViewSlice>(view_bounds);
38 slices_.insert_or_assign(view_id, std::move(view));
39
40 composition_order_.push_back(view_id);
41 // Update params only if they changed.
42 if (view_params_.count(view_id) == 1 &&
43 view_params_.at(view_id) == *params.get()) {
44 return;
45 }
46 view_params_.insert_or_assign(view_id, EmbeddedViewParams(*params.get()));
47}
48
49// |ExternalViewEmbedder|
51 if (slices_.count(view_id) == 1) {
52 return slices_.at(view_id)->canvas();
53 }
54 return nullptr;
55}
56
58 int64_t view_id,
59 const std::unordered_map<int64_t, EmbeddedViewParams>& view_params) {
60 const EmbeddedViewParams& params = view_params.at(view_id);
61 // https://github.com/flutter/flutter/issues/59821
63}
64
65// |ExternalViewEmbedder|
67 int64_t flutter_view_id,
68 GrDirectContext* context,
69 const std::shared_ptr<impeller::AiksContext>& aiks_context,
70 std::unique_ptr<SurfaceFrame> frame) {
71 TRACE_EVENT0("flutter", "AndroidExternalViewEmbedder2::SubmitFlutterView");
72
73 if (!FrameHasPlatformLayers()) {
74 frame->Submit();
76 [this, jni_facade = jni_facade_,
77 views_visible_last_frame = views_visible_last_frame_]() {
78 // This pointer is guaranteed to not be dangling as long as
79 // DestroySurfaces is called before the embedder is deleted. See
80 // https://github.com/flutter/flutter/pull/176742#discussion_r2415229396.
81 this->HideOverlayLayerIfNeeded();
82 for (int64_t view_id : views_visible_last_frame) {
83 jni_facade->hidePlatformView2(view_id);
84 }
85
86 jni_facade->swapTransaction();
87 jni_facade->onEndFrame2();
88 }));
89 views_visible_last_frame_.clear();
90 return;
91 }
92
93 std::unordered_map<int64_t, DlRect> view_rects;
94 for (auto platform_id : composition_order_) {
95 view_rects[platform_id] = GetViewRect(platform_id, view_params_);
96 }
97
98 std::unordered_map<int64_t, DlRect> overlay_layers =
99 SliceViews(frame->Canvas(), //
100 composition_order_, //
101 slices_, //
102 view_rects, //
103 {} //
104 );
105
106 // If there is no overlay Surface, initialize one on the platform thread. This
107 // will only be done once per application launch, as the singular overlay
108 // surface is never released.
109 if (!surface_pool_->HasLayers()) {
110 std::shared_ptr<fml::CountDownLatch> latch =
111 std::make_shared<fml::CountDownLatch>(1u);
112 task_runners_.GetPlatformTaskRunner()->PostTask(
113 fml::MakeCopyable([&, latch]() {
114 surface_pool_->GetLayer(context, android_context_, jni_facade_,
115 surface_factory_);
116 latch->CountDown();
117 }));
118 latch->Wait();
119 }
120 surface_pool_->ResetLayers();
121
122 // Create Overlay frame. If overlay surface creation failed,
123 // all this work must be skipped.
124 std::unique_ptr<SurfaceFrame> overlay_frame;
125 if (surface_pool_->HasLayers()) {
126 for (size_t i = 0; i < composition_order_.size(); i++) {
127 int64_t view_id = composition_order_[i];
128 std::unordered_map<int64_t, DlRect>::const_iterator overlay =
129 overlay_layers.find(view_id);
130
131 if (overlay == overlay_layers.end()) {
132 continue;
133 }
134 if (overlay_frame == nullptr) {
135 std::shared_ptr<OverlayLayer> layer = surface_pool_->GetLayer(
136 context, android_context_, jni_facade_, surface_factory_);
137 overlay_frame = layer->surface->AcquireFrame(frame_size_);
138 overlay_frame->Canvas()->Clear(flutter::DlColor::kTransparent());
139 }
140
141 DlCanvas* overlay_canvas = overlay_frame->Canvas();
142 int restore_count = overlay_canvas->GetSaveCount();
143 overlay_canvas->Save();
144 overlay_canvas->ClipRect(overlay->second);
145
146 // For all following platform views that would cover this overlay,
147 // emulate the effect by adding a difference clip. This makes the
148 // overlays appear as if they are under the platform view, when in
149 // reality there is only a single layer.
150 for (size_t j = i + 1; j < composition_order_.size(); j++) {
151 DlRect view_rect = GetViewRect(composition_order_[j], view_params_);
152 overlay_canvas->ClipRect(view_rect, DlClipOp::kDifference);
153 }
154
155 slices_[view_id]->render_into(overlay_canvas);
156 overlay_canvas->RestoreToCount(restore_count);
157 }
158 }
159 bool overlay_layer_has_content_this_frame_;
160 if (overlay_frame != nullptr) {
161 overlay_frame->set_submit_info({.frame_boundary = false});
162 overlay_frame->Submit();
163 overlay_layer_has_content_this_frame_ = true;
164 } else {
165 overlay_layer_has_content_this_frame_ = false;
166 }
167
168 frame->Submit();
170 [&, composition_order = composition_order_, view_params = view_params_,
171 jni_facade = jni_facade_, device_pixel_ratio = device_pixel_ratio_,
172 slices = std::move(slices_),
173 views_visible_last_frame = views_visible_last_frame_,
174 overlay_layer_has_content_this_frame_]() mutable -> void {
175 if (overlay_layer_has_content_this_frame_) {
176 ShowOverlayLayerIfNeeded();
177 } else {
178 HideOverlayLayerIfNeeded();
179 }
180 jni_facade->swapTransaction();
181
182 for (int64_t view_id : composition_order) {
183 DlRect view_rect = GetViewRect(view_id, view_params);
184 const EmbeddedViewParams& params = view_params.at(view_id);
185 jni_facade->onDisplayPlatformView2(
186 view_id, //
187 view_rect.GetX(), //
188 view_rect.GetY(), //
189 view_rect.GetWidth(), //
190 view_rect.GetHeight(), //
191 params.sizePoints().width * device_pixel_ratio,
192 params.sizePoints().height * device_pixel_ratio,
193 params.mutatorsStack() //
194 );
195 // Remove from views visible last frame, so we can hide the rest.
196 views_visible_last_frame.erase(view_id);
197 }
198 // Hide views that were visible last frame, but not in this frame.
199 for (int64_t view_id : views_visible_last_frame) {
200 jni_facade->hidePlatformView2(view_id);
201 }
202
203 jni_facade_->onEndFrame2();
204 }));
205
206 views_visible_last_frame_.clear();
207 views_visible_last_frame_.insert(composition_order_.begin(),
208 composition_order_.end());
209}
210
211// |ExternalViewEmbedder|
216
217bool AndroidExternalViewEmbedder2::FrameHasPlatformLayers() {
218 return !composition_order_.empty();
219}
220
221// |ExternalViewEmbedder|
223 // On Android, the root surface is created from the on-screen render target.
224 return nullptr;
225}
226
227void AndroidExternalViewEmbedder2::Reset() {
228 composition_order_.clear();
229 slices_.clear();
230}
231
232// |ExternalViewEmbedder|
234 GrDirectContext* context,
235 const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {}
236
237// |ExternalViewEmbedder|
239 DlISize frame_size,
240 double device_pixel_ratio) {
241 Reset();
242
243 // The surface size changed. Therefore, destroy existing surfaces as
244 // the existing surfaces in the pool can't be recycled.
245 if (frame_size_ != frame_size) {
246 DestroySurfaces();
247
248 // This should not block to prevent deadlocks with
249 // setViewportMetrics.
251 [jni_facade = jni_facade_, frame_size = frame_size]() {
252 jni_facade->MaybeResizeSurfaceView(frame_size.width,
253 frame_size.height);
254 }));
255 }
256 surface_pool_->SetFrameSize(frame_size);
257
258 frame_size_ = frame_size;
259 device_pixel_ratio_ = device_pixel_ratio;
260}
261
262// |ExternalViewEmbedder|
266
267// |ExternalViewEmbedder|
269 bool should_resubmit_frame,
270 const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {}
271
272// |ExternalViewEmbedder|
276
277// |ExternalViewEmbedder|
279 DestroySurfaces();
280}
281
282// |ExternalViewEmbedder|
283void AndroidExternalViewEmbedder2::DestroySurfaces() {
284 if (!surface_pool_->HasLayers()) {
285 return;
286 }
289 [&]() {
290 surface_pool_->DestroyLayers(jni_facade_);
291 latch.Signal();
292 });
293 latch.Wait();
294 overlay_layer_is_shown_.store(false);
295}
296
297void AndroidExternalViewEmbedder2::ShowOverlayLayerIfNeeded() {
298 if (!overlay_layer_is_shown_.load()) {
299 jni_facade_->showOverlaySurface2();
300 overlay_layer_is_shown_.store(true);
301 }
302}
303
304void AndroidExternalViewEmbedder2::HideOverlayLayerIfNeeded() {
305 if (overlay_layer_is_shown_.load()) {
306 jni_facade_->hideOverlaySurface2();
307 overlay_layer_is_shown_.store(false);
308 }
309}
310
311} // namespace flutter
Holds state that is shared across Android surfaces.
DlCanvas * CompositeEmbeddedView(int64_t view_id) override
void SubmitFlutterView(int64_t flutter_view_id, GrDirectContext *context, const std::shared_ptr< impeller::AiksContext > &aiks_context, std::unique_ptr< SurfaceFrame > frame) override
PostPrerollResult PostPrerollAction(const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger) override
void EndFrame(bool should_resubmit_frame, const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger) override
AndroidExternalViewEmbedder2(const AndroidContext &android_context, std::shared_ptr< PlatformViewAndroidJNI > jni_facade, std::shared_ptr< AndroidSurfaceFactory > surface_factory, const TaskRunners &task_runners)
static DlRect GetViewRect(int64_t view_id, const std::unordered_map< int64_t, EmbeddedViewParams > &view_params)
void PrerollCompositeEmbeddedView(int64_t view_id, std::unique_ptr< flutter::EmbeddedViewParams > params) override
void BeginFrame(GrDirectContext *context, const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger) override
void PrepareFlutterView(DlISize frame_size, double device_pixel_ratio) override
Developer-facing API for rendering anything within the engine.
Definition dl_canvas.h:32
virtual void ClipRect(const DlRect &rect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false)=0
virtual int GetSaveCount() const =0
virtual void RestoreToCount(int restore_count)=0
virtual void Save()=0
const DlRect & finalBoundingRect() const
fml::RefPtr< fml::TaskRunner > GetPlatformTaskRunner() const
static void RunNowOrPostTask(const fml::RefPtr< fml::TaskRunner > &runner, const fml::closure &task)
virtual void PostTask(const fml::closure &task) override
const EmbeddedViewParams * params
TaskRunners task_runners_
FlView * view
G_BEGIN_DECLS FlutterViewId view_id
std::unordered_map< int64_t, DlRect > SliceViews(DlCanvas *background_canvas, const std::vector< int64_t > &composition_order, const std::unordered_map< int64_t, std::unique_ptr< EmbedderViewSlice > > &slices, const std::unordered_map< int64_t, DlRect > &view_rects, const std::unordered_set< int64_t > &views_with_underlay_preserved)
Compute the required overlay layers and clip the view slices according to the size and position of th...
internal::CopyableLambda< T > MakeCopyable(T lambda)
Definition ref_ptr.h:261
static constexpr DlColor kTransparent()
Definition dl_color.h:68
constexpr Type GetY() const
Returns the Y coordinate of the upper left corner, equivalent to |GetOrigin().y|.
Definition rect.h:371
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
Definition rect.h:381
constexpr Type GetX() const
Returns the X coordinate of the upper left corner, equivalent to |GetOrigin().x|.
Definition rect.h:367
static constexpr TRect MakeSize(const TSize< U > &size)
Definition rect.h:150
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
Definition rect.h:375
Type height
Definition size.h:29
Type width
Definition size.h:28
#define TRACE_EVENT0(category_group, name)