-
Notifications
You must be signed in to change notification settings - Fork 6k
[iOS] Supported rendering platform views without merging the raster thread. #53826
Changes from 1 commit
02556ae
b3f6670
b31aae6
75f931a
4525bd8
6ce3aa0
be03cf8
6770376
912cd40
1f65cc3
53adc81
870b950
f8267bd
80565d5
2b9a825
0a7dc5a
2745e88
6002aa0
e7a832f
f099d74
e2e6a2a
44d5b5b
b53063a
9a84539
65a5210
735ce22
a4f523b
b6c3345
a4b771e
cd8e1de
6603d18
27c0daa
d794211
2f4314b
25a4e06
ea2e66d
d220885
9b534cd
970e13a
63ebe66
ff4802a
e3fc731
c0fab3b
d73671e
7285907
bcd8519
b25a742
5f6a8d4
be7853d
b19b4d8
ab08739
6e6e5a2
355ab30
8cd1c74
30e7b97
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,8 +21,10 @@ | |
| FLUTTER_ASSERT_ARC | ||
|
|
||
| #ifdef FML_OS_IOS_SIMULATOR | ||
| // Note: this is an arbitrary number that attempts to account for cases | ||
| // where the platform view might be momentarily off the screen. | ||
| // The number of frames the rasterizer task runner will continue | ||
| // to run on the platform thread after no platform view is rendered. | ||
| // | ||
| // Note: this is an arbitrary number. | ||
| static const int kDefaultMergedLeaseDuration = 10; | ||
| #endif // FML_OS_IOS_SIMULATOR | ||
|
|
||
|
|
@@ -105,6 +107,7 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, | |
| void FlutterPlatformViewLayerPool::CreateLayer(GrDirectContext* gr_context, | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is probably the biggest PITA. Because I can only construct these on the platform thread, right now frame 0 with platform views will skip some number of overlay layers. Its possible that the FlutterMetalLayer solves this partially
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we move away from On macOS surfaces are allocated on raster thread and the overlay sublayers are crated here. Here are relevant files: |
||
| const std::shared_ptr<IOSContext>& ios_context, | ||
| MTLPixelFormat pixel_format) { | ||
cbracken marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| FML_DCHECK([[NSThread currentThread] isMainThread]); | ||
| std::shared_ptr<FlutterPlatformViewLayer> layer; | ||
| fml::scoped_nsobject<UIView> overlay_view; | ||
| fml::scoped_nsobject<UIView> overlay_view_wrapper; | ||
|
|
@@ -266,12 +269,13 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, | |
| ChildClippingView* clipping_view = [[ChildClippingView alloc] initWithFrame:CGRectZero]; | ||
| [clipping_view addSubview:touch_interceptor]; | ||
|
|
||
| platform_views_[viewId] = PlatformViewData{ | ||
| .view = fml::scoped_nsobject<NSObject<FlutterPlatformView>>(embedded_view), // | ||
| .touch_interceptor = | ||
| fml::scoped_nsobject<FlutterTouchInterceptingView>(touch_interceptor), // | ||
| .root_view = fml::scoped_nsobject<UIView>(clipping_view) // | ||
| }; | ||
| platform_views_.emplace( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice clean up with the struct |
||
| viewId, PlatformViewData{ | ||
| .view = fml::scoped_nsobject<NSObject<FlutterPlatformView>>(embedded_view), // | ||
| .touch_interceptor = | ||
| fml::scoped_nsobject<FlutterTouchInterceptingView>(touch_interceptor), // | ||
| .root_view = fml::scoped_nsobject<UIView>(clipping_view) // | ||
| }); | ||
|
|
||
| result(nil); | ||
| } | ||
|
|
@@ -643,6 +647,9 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, | |
| } | ||
|
|
||
| void FlutterPlatformViewsController::Reset() { | ||
| // Reset will only be called from the raster thread or a merged raster/platform thread. | ||
| // platform_views_ must only be modified on the platform thread, and any operations that | ||
| // read or modify platform views should occur there. | ||
| fml::TaskRunner::RunNowOrPostTask( | ||
cbracken marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| platform_task_runner_, [&, composition_order = composition_order_]() { | ||
| for (int64_t view_id : composition_order_) { | ||
|
|
@@ -664,6 +671,7 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, | |
| std::unique_ptr<SurfaceFrame> background_frame) { | ||
| TRACE_EVENT0("flutter", "FlutterPlatformViewsController::SubmitFrame"); | ||
|
|
||
| // No platform views to render; we're done. | ||
| if (flutter_view_ == nullptr || (composition_order_.empty() && !had_platform_views_)) { | ||
cbracken marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| had_platform_views_ = false; | ||
| return background_frame->Submit(); | ||
|
|
@@ -673,6 +681,7 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, | |
| bool did_encode = true; | ||
| LayersMap platform_view_layers; | ||
| std::vector<std::unique_ptr<SurfaceFrame>> surface_frames; | ||
cbracken marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| surface_frames.reserve(composition_order_.size()); | ||
| std::unordered_map<int64_t, SkRect> view_rects; | ||
|
|
||
| for (int64_t view_id : composition_order_) { | ||
|
|
@@ -694,9 +703,7 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, | |
| // If there are not sufficient overlay layers, we must construct them on the platform | ||
| // thread, at least until we've refactored iOS surface creation to use IOSurfaces | ||
| // instead of CALayers. | ||
| if (required_overlay_layers > layer_pool_->size()) { | ||
| CreateMissingOverlays(gr_context, ios_context, required_overlay_layers); | ||
| } | ||
| CreateMissingOverlays(gr_context, ios_context, required_overlay_layers); | ||
|
|
||
| int64_t overlay_id = 0; | ||
| for (int64_t view_id : composition_order_) { | ||
|
|
@@ -775,24 +782,15 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, | |
| size_t required_overlay_layers) { | ||
| TRACE_EVENT0("flutter", "FlutterPlatformViewsController::CreateMissingLayers"); | ||
|
|
||
| auto missing_layer_count = required_overlay_layers - layer_pool_->size(); | ||
|
|
||
| // If raster thread is merged because we're in a unit test or running on simulator, then | ||
| // we don't need to post a task to create an overlay layer. | ||
| if ([[NSThread currentThread] isMainThread]) { | ||
| // Create Missing Layers | ||
| for (auto i = 0u; i < missing_layer_count; i++) { | ||
| CreateLayer(gr_context, // | ||
| ios_context, // | ||
| ((FlutterView*)flutter_view_.get()).pixelFormat // | ||
| ); | ||
| } | ||
| if (required_overlay_layers <= layer_pool_->size()) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it looks like the layer_pool is accessed here on raster thread, but mutated below in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because we block the raster thread on completion via a latch, there is no race |
||
| return; | ||
| } | ||
| auto missing_layer_count = required_overlay_layers - layer_pool_->size(); | ||
|
|
||
| // If the raster thread isn't merged, create layers on the platform thread and block until | ||
| // complete. | ||
| auto latch = std::make_shared<fml::CountDownLatch>(1u); | ||
| platform_task_runner_->PostTask([&]() { | ||
| // Create Missing Layers | ||
| fml::TaskRunner::RunNowOrPostTask(platform_task_runner_, [&]() { | ||
| for (auto i = 0u; i < missing_layer_count; i++) { | ||
| CreateLayer(gr_context, // | ||
| ios_context, // | ||
|
|
@@ -801,7 +799,9 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, | |
| } | ||
| latch->CountDown(); | ||
| }); | ||
| latch->Wait(); | ||
| if (![[NSThread currentThread] isMainThread]) { | ||
| latch->Wait(); | ||
| } | ||
| } | ||
|
|
||
| /// Update the buffers and mutate the platform views in CATransaction on the platform thread. | ||
|
|
@@ -848,9 +848,6 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, | |
| // Organize the layers by their z indexes. | ||
| BringLayersIntoView(platform_view_layers, composition_order); | ||
|
|
||
| // If the frame is submitted with embedded platform views, | ||
| // there should be a |[CATransaction begin]| call in this frame prior to all the drawing. | ||
| // If that case, we need to commit the transaction. | ||
| [CATransaction commit]; | ||
| } | ||
|
|
||
|
|
@@ -862,8 +859,7 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, | |
|
|
||
| previous_composition_order_.clear(); | ||
| NSMutableArray* desired_platform_subviews = [NSMutableArray array]; | ||
| for (size_t i = 0; i < composition_order.size(); i++) { | ||
| int64_t platform_view_id = composition_order[i]; | ||
| for (int64_t platform_view_id : composition_order) { | ||
| UIView* platform_view_root = platform_views_[platform_view_id].root_view.get(); | ||
| [desired_platform_subviews addObject:platform_view_root]; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ask to learn - are we still merging the thread (given this variable name?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are merging threads on the iOS simulator (technically we only need to when using the software backend but that is a harder condition to test). Once we remove skia and the software backend we can remove this condition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May I ask what's the difference between the simulator and device that we have to merge the thread on simulator?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its not the simulator, its the software backend. The software backend surfaces cannot be used from multiple threads, which this change requires.