diff --git a/shell/platform/darwin/macos/framework/Source/FlutterCompositor.h b/shell/platform/darwin/macos/framework/Source/FlutterCompositor.h index 8e3bcff066a8d..aca395edacf48 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterCompositor.h +++ b/shell/platform/darwin/macos/framework/Source/FlutterCompositor.h @@ -46,7 +46,7 @@ class FlutterCompositor { // Present sets frame_started_ to false. virtual bool Present(const FlutterLayer** layers, size_t layers_count) = 0; - using PresentCallback = std::function; + using PresentCallback = std::function; // PresentCallback is called at the end of the Present function. void SetPresentCallback(const PresentCallback& present_callback); @@ -73,7 +73,7 @@ class FlutterCompositor { // Calls the present callback and ensures the frame status is updated // to frame ended, returning whether the present was successful or not. - bool EndFrame(); + bool EndFrame(bool has_flutter_content); // Creates a CALayer object which is backed by the supplied IOSurface, and // adds it to the root CALayer for this FlutterViewController's view. diff --git a/shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm b/shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm index 487cc41b762b8..3015a716c6ca6 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm @@ -29,8 +29,8 @@ SetFrameStatus(FrameStatus::kStarted); } -bool FlutterCompositor::EndFrame() { - bool status = present_callback_(); +bool FlutterCompositor::EndFrame(bool has_flutter_content) { + bool status = present_callback_(has_flutter_content); SetFrameStatus(FrameStatus::kEnded); return status; } diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm index 66b5fa88f4f19..ab196fa2f7aca 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm @@ -340,10 +340,14 @@ - (FlutterCompositor*)createFlutterCompositor { FlutterMetalRenderer* metalRenderer = reinterpret_cast(_renderer); _macOSCompositor = std::make_unique(_viewController, metalRenderer.device); - _macOSCompositor->SetPresentCallback([weakSelf]() { - FlutterMetalRenderer* metalRenderer = - reinterpret_cast(weakSelf.renderer); - return [metalRenderer present:0 /*=textureID*/]; + _macOSCompositor->SetPresentCallback([weakSelf](bool has_flutter_content) { + if (has_flutter_content) { + FlutterMetalRenderer* metalRenderer = + reinterpret_cast(weakSelf.renderer); + return [metalRenderer present:0 /*=textureID*/] == YES; + } else { + return true; + } }); } else { FlutterOpenGLRenderer* openGLRenderer = reinterpret_cast(_renderer); @@ -351,10 +355,14 @@ - (FlutterCompositor*)createFlutterCompositor { _macOSCompositor = std::make_unique(_viewController, openGLRenderer.openGLContext); - _macOSCompositor->SetPresentCallback([weakSelf]() { - FlutterOpenGLRenderer* openGLRenderer = - reinterpret_cast(weakSelf.renderer); - return [openGLRenderer glPresent]; + _macOSCompositor->SetPresentCallback([weakSelf](bool has_flutter_content) { + if (has_flutter_content) { + FlutterOpenGLRenderer* openGLRenderer = + reinterpret_cast(weakSelf.renderer); + return [openGLRenderer glPresent] == YES; + } else { + return true; + } }); } diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm index 3414daa48b46a..56d6a62072617 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm @@ -355,7 +355,7 @@ @interface FlutterEngine (Test) // Latch to ensure the entire layer tree has been generated and presented. fml::AutoResetWaitableEvent latch; auto compositor = engine.macOSCompositor; - compositor->SetPresentCallback([&]() { + compositor->SetPresentCallback([&](bool has_flutter_content) { latch.Signal(); return true; }); diff --git a/shell/platform/darwin/macos/framework/Source/FlutterGLCompositor.mm b/shell/platform/darwin/macos/framework/Source/FlutterGLCompositor.mm index 89f9b55b32111..c8c6ce7f93056 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterGLCompositor.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterGLCompositor.mm @@ -77,6 +77,8 @@ bool FlutterGLCompositor::Present(const FlutterLayer** layers, size_t layers_count) { SetFrameStatus(FrameStatus::kPresenting); + bool has_flutter_content = false; + for (size_t i = 0; i < layers_count; ++i) { const auto* layer = layers[i]; FlutterBackingStore* backing_store = const_cast(layer->backing_store); @@ -93,6 +95,7 @@ // and needs to be flipped vertically InsertCALayerForIOSurface(io_surface, CATransform3DMakeScale(1, -1, 1)); } + has_flutter_content = true; break; } case kFlutterLayerContentTypePlatformView: @@ -102,7 +105,7 @@ }; } - return EndFrame(); + return EndFrame(has_flutter_content); } } // namespace flutter diff --git a/shell/platform/darwin/macos/framework/Source/FlutterGLCompositorUnittests.mm b/shell/platform/darwin/macos/framework/Source/FlutterGLCompositorUnittests.mm index 25fc35575176f..049c3ed7cd7dd 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterGLCompositorUnittests.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterGLCompositorUnittests.mm @@ -17,7 +17,7 @@ std::make_unique(mockViewController, nullptr); bool flag = false; - macos_compositor->SetPresentCallback([f = &flag]() { + macos_compositor->SetPresentCallback([f = &flag](bool has_flutter_content) { *f = true; return true; }); diff --git a/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositor.mm b/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositor.mm index aa36b4ae292e4..101df075dbb5b 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositor.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositor.mm @@ -76,6 +76,8 @@ bool FlutterMetalCompositor::Present(const FlutterLayer** layers, size_t layers_count) { SetFrameStatus(FrameStatus::kPresenting); + bool has_flutter_content = false; + for (size_t i = 0; i < layers_count; ++i) { const auto* layer = layers[i]; FlutterBackingStore* backing_store = const_cast(layer->backing_store); @@ -88,6 +90,7 @@ IOSurfaceRef io_surface = [io_surface_holder ioSurface]; InsertCALayerForIOSurface(io_surface); } + has_flutter_content = true; break; } case kFlutterLayerContentTypePlatformView: @@ -97,7 +100,7 @@ }; } - return EndFrame(); + return EndFrame(has_flutter_content); } } // namespace flutter diff --git a/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositorUnittests.mm b/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositorUnittests.mm index 0f4dc409fbd0d..766acc6255b50 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositorUnittests.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositorUnittests.mm @@ -17,7 +17,7 @@ std::make_unique(mockViewController, nullptr); bool flag = false; - macos_compositor->SetPresentCallback([f = &flag]() { + macos_compositor->SetPresentCallback([f = &flag](bool has_flutter_content) { *f = true; return true; }); diff --git a/shell/platform/darwin/macos/framework/Source/FlutterMetalSurfaceManagerTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterMetalSurfaceManagerTest.mm index 7a739e753528f..77760776383b7 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterMetalSurfaceManagerTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterMetalSurfaceManagerTest.mm @@ -53,6 +53,7 @@ - (instancetype)init { FlutterMetalSurfaceManager* surfaceManager = CreateSurfaceManager(); CGSize size = CGSizeMake(100, 50); [surfaceManager ensureSurfaceSize:size]; + [surfaceManager renderBuffer]; // make sure we have back buffer [surfaceManager swapBuffers]; id texture = (reinterpret_cast([surfaceManager renderBuffer])).texture; diff --git a/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm b/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm index 054aaa22ff618..9c212ba10431b 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm @@ -58,6 +58,13 @@ - (void)ensureSurfaceSize:(CGSize)size { } - (void)swapBuffers { +#ifndef NDEBUG + // swapBuffers should not be called unless a frame was drawn + @synchronized(self) { + assert(_frameInProgress); + } +#endif + _contentLayer.frame = _containingLayer.bounds; _contentLayer.transform = _contentTransform; IOSurfaceRef contentIOSurface = [_ioSurfaces[kFlutterSurfaceManagerBackBuffer] ioSurface];