未验证 提交 8997f348 编写于 作者: A Amir Hardon 提交者: GitHub

Fix stale platform view gr context on iOS (#13469)

When gr context is changed (this happens when sending the app to the background and then to the foreground) we need to update it for all the platform view overlay surfaces.

The update logic was caching the previous gr context to figure if it had to be updated, but after updating it for a given overlay we were updating the cached context. In apps with multiple platform views this will result in overlays with a stale gr context.

This fixes flutter/flutter#36437
And I believe it should fix flutter/flutter#36999 as well (though I don't have repro code to verify).
上级 55e8ef90
......@@ -476,8 +476,9 @@ void FlutterPlatformViewsController::EnsureOverlayInitialized(
}
if (overlay_it != overlays_.end()) {
if (gr_context != overlays_gr_context_) {
overlays_gr_context_ = gr_context;
FlutterPlatformViewLayer* overlay = overlay_it->second.get();
if (gr_context != overlay->gr_context) {
overlay->gr_context = gr_context;
// The overlay already exists, but the GrContext was changed so we need to recreate
// the rendering surface with the new GrContext.
IOSSurface* ios_surface = overlay_it->second->ios_surface.get();
......@@ -497,7 +498,7 @@ void FlutterPlatformViewsController::EnsureOverlayInitialized(
std::unique_ptr<Surface> surface = ios_surface->CreateGPUSurface(gr_context);
overlays_[overlay_id] = std::make_unique<FlutterPlatformViewLayer>(
std::move(overlay_view), std::move(ios_surface), std::move(surface));
overlays_gr_context_ = gr_context;
overlays_[overlay_id]->gr_context = gr_context;
}
} // namespace flutter
......
......@@ -63,6 +63,11 @@ struct FlutterPlatformViewLayer {
fml::scoped_nsobject<UIView> overlay_view;
std::unique_ptr<IOSSurface> ios_surface;
std::unique_ptr<Surface> surface;
// The GrContext that is currently used by the overlay surfaces.
// We track this to know when the GrContext for the Flutter app has changed
// so we can update the overlay with the new context.
GrContext* gr_context;
};
class FlutterPlatformViewsController {
......@@ -123,10 +128,6 @@ class FlutterPlatformViewsController {
// platform view last time it was composited.
std::map<int64_t, int64_t> clip_count_;
std::map<int64_t, std::unique_ptr<FlutterPlatformViewLayer>> overlays_;
// The GrContext that is currently used by all of the overlay surfaces.
// We track this to know when the GrContext for the Flutter app has changed
// so we can update the overlays with the new context.
GrContext* overlays_gr_context_;
SkISize frame_size_;
// This is the number of frames the task runners will stay
......
......@@ -31,6 +31,7 @@
24D47D1D230CA2700069DD5E /* golden_platform_view_iPhone SE_simulator.png in Resources */ = {isa = PBXBuildFile; fileRef = 24D47D1C230CA2700069DD5E /* golden_platform_view_iPhone SE_simulator.png */; };
24F1FB89230B4579005ACE7C /* TextPlatformView.m in Sources */ = {isa = PBXBuildFile; fileRef = 24F1FB87230B4579005ACE7C /* TextPlatformView.m */; };
59A97FD8236A49D300B4C066 /* golden_platform_view_multiple_iPhone SE_simulator.png in Resources */ = {isa = PBXBuildFile; fileRef = 59A97FD7236A49D300B4C066 /* golden_platform_view_multiple_iPhone SE_simulator.png */; };
59A97FDA236B984300B4C066 /* golden_platform_view_multiple_background_foreground_iPhone SE_simulator.png in Resources */ = {isa = PBXBuildFile; fileRef = 59A97FD9236B984300B4C066 /* golden_platform_view_multiple_background_foreground_iPhone SE_simulator.png */; };
6816DB9E231750ED00A51400 /* GoldenPlatformViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6816DB9D231750ED00A51400 /* GoldenPlatformViewTests.m */; };
6816DBA12317573300A51400 /* GoldenImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 6816DBA02317573300A51400 /* GoldenImage.m */; };
6816DBA42318358200A51400 /* PlatformViewGoldenTestManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 6816DBA32318358200A51400 /* PlatformViewGoldenTestManager.m */; };
......@@ -123,6 +124,7 @@
24F1FB87230B4579005ACE7C /* TextPlatformView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TextPlatformView.m; sourceTree = "<group>"; };
24F1FB88230B4579005ACE7C /* TextPlatformView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextPlatformView.h; sourceTree = "<group>"; };
59A97FD7236A49D300B4C066 /* golden_platform_view_multiple_iPhone SE_simulator.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "golden_platform_view_multiple_iPhone SE_simulator.png"; sourceTree = "<group>"; };
59A97FD9236B984300B4C066 /* golden_platform_view_multiple_background_foreground_iPhone SE_simulator.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "golden_platform_view_multiple_background_foreground_iPhone SE_simulator.png"; sourceTree = "<group>"; };
6816DB9C231750ED00A51400 /* GoldenPlatformViewTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GoldenPlatformViewTests.h; sourceTree = "<group>"; };
6816DB9D231750ED00A51400 /* GoldenPlatformViewTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GoldenPlatformViewTests.m; sourceTree = "<group>"; };
6816DB9F2317573300A51400 /* GoldenImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GoldenImage.h; sourceTree = "<group>"; };
......@@ -218,6 +220,7 @@
248D76ED22E388380012F0C1 /* ScenariosUITests */ = {
isa = PBXGroup;
children = (
59A97FD9236B984300B4C066 /* golden_platform_view_multiple_background_foreground_iPhone SE_simulator.png */,
59A97FD7236A49D300B4C066 /* golden_platform_view_multiple_iPhone SE_simulator.png */,
244EA6CF230DBE8900B2D26E /* golden_platform_view_D21AP.png */,
24D47D1C230CA2700069DD5E /* golden_platform_view_iPhone SE_simulator.png */,
......@@ -375,6 +378,7 @@
files = (
6816DBAE2318696600A51400 /* golden_platform_view_cliprrect_iPhone SE_simulator.png in Resources */,
6816DBAB2318696600A51400 /* golden_platform_view_transform_iPhone SE_simulator.png in Resources */,
59A97FDA236B984300B4C066 /* golden_platform_view_multiple_background_foreground_iPhone SE_simulator.png in Resources */,
6816DBAA2318696600A51400 /* golden_platform_view_clippath_iPhone SE_simulator.png in Resources */,
6816DBAD2318696600A51400 /* golden_platform_view_cliprect_iPhone SE_simulator.png in Resources */,
24D47D1B230C79840069DD5E /* golden_platform_view_D211AP.png in Resources */,
......
......@@ -29,6 +29,8 @@
NSDictionary<NSString*, NSString*>* launchArgsMap = @{
@"--platform-view" : @"platform_view",
@"--platform-view-multiple" : @"platform_view_multiple",
@"--platform-view-multiple-background-foreground" :
@"platform_view_multiple_background_foreground",
@"--platform-view-cliprect" : @"platform_view_cliprect",
@"--platform-view-cliprrect" : @"platform_view_cliprrect",
@"--platform-view-clippath" : @"platform_view_clippath",
......
......@@ -17,6 +17,8 @@ NS_ASSUME_NONNULL_BEGIN
// This base class doesn't run any test case on its own.
@interface GoldenPlatformViewTests : XCTestCase
@property(nonatomic, strong) XCUIApplication* application;
// Initialize with a `PlatformViewGoldenTestManager`.
- (instancetype)initWithManager:(PlatformViewGoldenTestManager*)manager
invocation:(NSInvocation*)invocation;
......
......@@ -11,7 +11,6 @@ static const NSInteger kSecondsToWaitForPlatformView = 30;
@interface GoldenPlatformViewTests ()
@property(nonatomic, copy) NSString* goldenName;
@property(nonatomic, strong) XCUIApplication* application;
@property(nonatomic, strong) PlatformViewGoldenTestManager* manager;
......
......@@ -24,6 +24,8 @@ NSDictionary* launchArgsMap;
launchArgsMap = @{
@"--platform-view" : @"platform_view",
@"--platform-view-multiple" : @"platform_view_multiple",
@"--platform-view-multiple-background-foreground" :
@"platform_view_multiple_background_foreground",
@"--platform-view-cliprect" : @"platform_view_cliprect",
@"--platform-view-cliprrect" : @"platform_view_cliprrect",
@"--platform-view-clippath" : @"platform_view_clippath",
......
......@@ -35,6 +35,29 @@
}
- (void)testPlatformView {
//[self checkGolden];
[[XCUIDevice sharedDevice] pressButton:XCUIDeviceButtonHome];
[self.application activate];
[self checkGolden];
}
@end
@interface MultiplePlatformViewsBackgroundForegroundTest : GoldenPlatformViewTests
@end
@implementation MultiplePlatformViewsBackgroundForegroundTest
- (instancetype)initWithInvocation:(NSInvocation*)invocation {
PlatformViewGoldenTestManager* manager = [[PlatformViewGoldenTestManager alloc]
initWithLaunchArg:@"--platform-view-multiple-background-foreground"];
return [super initWithManager:manager invocation:invocation];
}
- (void)testPlatformView {
[[XCUIDevice sharedDevice] pressButton:XCUIDeviceButtonHome];
[self.application activate];
[self checkGolden];
}
......
......@@ -23,6 +23,7 @@ Map<String, Scenario> _scenarios = <String, Scenario>{
'platform_view_transform': PlatformViewTransformScenario(window, 'PlatformViewTransform', id: 4),
'platform_view_opacity': PlatformViewOpacityScenario(window, 'PlatformViewOpacity', id: 5),
'platform_view_multiple': MultiPlatformViewScenario(window, firstId: 6, secondId: 7),
'platform_view_multiple_background_foreground': MultiPlatformViewBackgroundForegroundScenario(window, firstId: 8, secondId: 9),
'poppable_screen': PoppableScreenScenario(window),
};
......
......@@ -79,6 +79,98 @@ class MultiPlatformViewScenario extends Scenario with _BasePlatformViewScenarioM
}
}
/// Scenario for verifying platform views after background and foregrounding the app.
///
/// Renders a frame with 2 platform views covered by a flutter drawn rectangle,
/// when the app goes to the background and comes back to the foreground renders a new frame
/// with the 2 platform views but without the flutter drawn rectangle.
class MultiPlatformViewBackgroundForegroundScenario extends Scenario with _BasePlatformViewScenarioMixin {
/// Creates the PlatformView scenario.
///
/// The [window] parameter must not be null.
MultiPlatformViewBackgroundForegroundScenario(Window window, {this.firstId, this.secondId})
: assert(window != null),
super(window) {
createPlatformView(window, 'platform view 1', firstId);
createPlatformView(window, 'platform view 2', secondId);
_nextFrame = _firstFrame;
}
/// The platform view identifier to use for the first platform view.
final int firstId;
/// The platform view identifier to use for the second platform view.
final int secondId;
@override
void onBeginFrame(Duration duration) {
_nextFrame();
}
VoidCallback _nextFrame;
void _firstFrame() {
final SceneBuilder builder = SceneBuilder();
builder.pushOffset(0, 0);
builder.pushOffset(0, 600);
_addPlatformViewtoScene(builder, firstId, 500, 500);
builder.pop();
_addPlatformViewtoScene(builder, secondId, 500, 500);
final PictureRecorder recorder = PictureRecorder();
final Canvas canvas = Canvas(recorder);
canvas.drawRect(
const Rect.fromLTRB(0, 0, 500, 1000),
Paint()..color = const Color(0xFFFF0000),
);
final Picture picture = recorder.endRecording();
builder.addPicture(const Offset(0, 0), picture);
builder.pop();
final Scene scene = builder.build();
window.render(scene);
scene.dispose();
}
void _secondFrame() {
final SceneBuilder builder = SceneBuilder();
builder.pushOffset(0, 0);
builder.pushOffset(0, 600);
_addPlatformViewtoScene(builder, firstId, 500, 500);
builder.pop();
_addPlatformViewtoScene(builder, secondId, 500, 500);
final Scene scene = builder.build();
window.render(scene);
scene.dispose();
}
String _lastLifecycleState = '';
@override
void onPlatformMessage(
String name,
ByteData data,
PlatformMessageResponseCallback callback,
) {
if (name != 'flutter/lifecycle') {
return;
}
final String message = utf8.decode(data.buffer.asUint8List());
if (_lastLifecycleState == 'AppLifecycleState.inactive' && message == 'AppLifecycleState.resumed') {
_nextFrame = _secondFrame;
window.scheduleFrame();
}
_lastLifecycleState = message;
}
}
/// Platform view with clip rect.
class PlatformViewClipRectScenario extends Scenario with _BasePlatformViewScenarioMixin {
/// Constructs a platform view with clip rect scenario.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册