diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm index 05e999777b097..ec44e2af421b5 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm @@ -3388,4 +3388,84 @@ - (void)testLayerPool { XCTAssertEqual(pool.size(), 1u); } +- (void)testFlutterPlatformViewControllerSubmitFramePreservingFrameDamage { + flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate; + + flutter::TaskRunners runners(/*label=*/self.name.UTF8String, + /*platform=*/GetDefaultTaskRunner(), + /*raster=*/GetDefaultTaskRunner(), + /*ui=*/GetDefaultTaskRunner(), + /*io=*/GetDefaultTaskRunner()); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + auto platform_view = std::make_unique( + /*delegate=*/mock_delegate, + /*rendering_api=*/mock_delegate.settings_.enable_impeller + ? flutter::IOSRenderingAPI::kMetal + : flutter::IOSRenderingAPI::kSoftware, + /*platform_views_controller=*/flutterPlatformViewsController, + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_jsync_switch=*/std::make_shared()); + + UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; + flutterPlatformViewsController->SetFlutterView(flutterView); + + FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = + [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + FlutterResult result = ^(id result) { + }; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @0, @"viewType" : @"MockFlutterPlatformView"}], + result); + + // This overwrites `gMockPlatformView` to another view. + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}], + result); + + flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300)); + flutter::MutatorsStack stack; + SkMatrix finalMatrix; + auto embeddedViewParams1 = + std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); + flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams1)); + + auto embeddedViewParams2 = + std::make_unique(finalMatrix, SkSize::Make(500, 500), stack); + flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams2)); + + // SKSurface is required if the root FlutterView is present. + const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000); + sk_sp mock_sk_surface = SkSurfaces::Raster(image_info); + flutter::SurfaceFrame::FramebufferInfo framebuffer_info; + std::optional submit_info; + auto mock_surface = std::make_unique( + std::move(mock_sk_surface), framebuffer_info, + [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; }, + [&](const flutter::SurfaceFrame& surface_frame) { + submit_info = surface_frame.submit_info(); + return true; + }, + /*frame_size=*/SkISize::Make(800, 600)); + mock_surface->set_submit_info({ + .frame_damage = SkIRect::MakeWH(800, 600), + .buffer_damage = SkIRect::MakeWH(400, 600), + }); + + XCTAssertTrue( + flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface))); + + XCTAssertTrue(submit_info.has_value()); + XCTAssertEqual(*submit_info->frame_damage, SkIRect::MakeWH(800, 600)); + XCTAssertEqual(*submit_info->buffer_damage, SkIRect::MakeWH(400, 600)); +} + @end diff --git a/shell/platform/darwin/ios/framework/Source/platform_views_controller.mm b/shell/platform/darwin/ios/framework/Source/platform_views_controller.mm index 806d9510011d9..0ad4ad6ff5517 100644 --- a/shell/platform/darwin/ios/framework/Source/platform_views_controller.mm +++ b/shell/platform/darwin/ios/framework/Source/platform_views_controller.mm @@ -679,7 +679,12 @@ bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, overlay_id++; } - background_frame->set_submit_info({.present_with_transaction = true}); + auto previous_submit_info = background_frame->submit_info(); + background_frame->set_submit_info({ + .frame_damage = previous_submit_info.frame_damage, + .buffer_damage = previous_submit_info.buffer_damage, + .present_with_transaction = true, + }); background_frame->Encode(); surface_frames.push_back(std::move(background_frame));