Preserve background frame damage (flutter/engine#54540)

Fixes https://github.com/flutter/flutter/issues/153335

When platform views are present, we always repaint entire frame. We must pass the buffer damage all the way to `GPUSurfaceMetalSkia/GPUSurfaceMetalImpeller` so that they know that the other two surfaces are lagging behind front surface and need to be repainted.

This is currently not being done with platform view present, that's why we miss full frame repaint when removing platform view.

With this merged in, it should be safe to reland https://github.com/flutter/engine/pull/54537 without any changes.

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This commit is contained in:
Matej Knopp 2024-08-13 22:55:36 +02:00 committed by GitHub
parent ed3b8da5e8
commit 7a1fd055b8
2 changed files with 86 additions and 1 deletions

View File

@ -3388,4 +3388,84 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
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<flutter::PlatformViewsController>();
flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner());
auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
/*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<fml::SyncSwitch>());
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<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack);
flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams1));
auto embeddedViewParams2 =
std::make_unique<flutter::EmbeddedViewParams>(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<SkSurface> mock_sk_surface = SkSurfaces::Raster(image_info);
flutter::SurfaceFrame::FramebufferInfo framebuffer_info;
std::optional<flutter::SurfaceFrame::SubmitInfo> submit_info;
auto mock_surface = std::make_unique<flutter::SurfaceFrame>(
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

View File

@ -679,7 +679,12 @@ bool PlatformViewsController::SubmitFrame(GrDirectContext* gr_context,
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));