From 0177f9e6205cc0c4d972923806ea4e5b130726a5 Mon Sep 17 00:00:00 2001 From: RichardJCai Date: Tue, 27 Oct 2020 13:59:23 -0400 Subject: [PATCH 1/5] Refactor MacOS to use FlutterMacOSCompositor for creating backing stores using FlutterSurfaceManager. --- shell/platform/darwin/macos/BUILD.gn | 9 ++ .../macos/framework/Source/FlutterEngine.mm | 51 +++++++++- .../Source/FlutterMacOSGLCompositor.h | 57 +++++++++++ .../Source/FlutterMacOSGLCompositor.mm | 94 ++++++++++++++++++ .../FlutterMacOSGLCompositorUnittests.mm | 29 ++++++ .../framework/Source/FlutterSurfaceManager.h | 54 +++++++++-- .../framework/Source/FlutterSurfaceManager.mm | 96 ++++++++++++------- .../macos/framework/Source/FlutterView.mm | 1 + .../Source/FlutterViewControllerTest.mm | 26 +---- .../Source/FlutterViewControllerTestsUtils.h | 14 +++ .../Source/FlutterViewControllerTestsUtils.mm | 26 +++++ 11 files changed, 393 insertions(+), 64 deletions(-) create mode 100644 shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h create mode 100644 shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.mm create mode 100644 shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositorUnittests.mm create mode 100644 shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.h create mode 100644 shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.mm diff --git a/shell/platform/darwin/macos/BUILD.gn b/shell/platform/darwin/macos/BUILD.gn index 4c345a008c19c..aef31afad26a0 100644 --- a/shell/platform/darwin/macos/BUILD.gn +++ b/shell/platform/darwin/macos/BUILD.gn @@ -52,6 +52,8 @@ source_set("flutter_framework_source") { "framework/Source/FlutterEngine_Internal.h", "framework/Source/FlutterExternalTextureGL.h", "framework/Source/FlutterExternalTextureGL.mm", + "framework/Source/FlutterMacOSGLCompositor.h", + "framework/Source/FlutterMacOSGLCompositor.mm", "framework/Source/FlutterMouseCursorPlugin.h", "framework/Source/FlutterMouseCursorPlugin.mm", "framework/Source/FlutterResizeSynchronizer.h", @@ -73,9 +75,13 @@ source_set("flutter_framework_source") { sources += _flutter_framework_headers deps = [ + "//flutter/flow:flow", + "//flutter/fml", + "//flutter/fml:fml", "//flutter/shell/platform/common/cpp:common_cpp_switches", "//flutter/shell/platform/darwin/common:framework_shared", "//flutter/shell/platform/embedder:embedder_as_internal_library", + "//third_party/skia", ] public_configs = [ "//flutter:config" ] @@ -115,7 +121,10 @@ executable("flutter_desktop_darwin_unittests") { sources = [ "framework/Source/FlutterEngineTest.mm", + "framework/Source/FlutterMacOSGLCompositorUnittests.mm", "framework/Source/FlutterViewControllerTest.mm", + "framework/Source/FlutterViewControllerTestsUtils.h", + "framework/Source/FlutterViewControllerTestsUtils.mm", ] cflags_objcc = [ "-fobjc-arc" ] diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm index d9ebd55f0d7ec..2cb72d1745a46 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm @@ -10,7 +10,7 @@ #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.h" -#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h" #import "flutter/shell/platform/embedder/embedder.h" /** @@ -197,6 +197,11 @@ @implementation FlutterEngine { // Pointer to the Dart AOT snapshot and instruction data. _FlutterEngineAOTData* _aotData; + + // FlutterMacOSGLCompositor is created by the engine. + // This is only created when the engine has a FlutterViewController + // and used to support platform views. + std::unique_ptr _macOSCompositor; } - (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)project { @@ -306,6 +311,15 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint { flutterArguments.aot_data = _aotData; } + // Only create a Compositor if we have a ViewController. + if (_viewController) { + // Engine does not need to manage the life cycle of compositor + // since compositor is captured and copied in embedder.cc. + FlutterCompositor compositor = {}; + [self setupCompositor:&compositor]; + flutterArguments.compositor = &compositor; + } + FlutterEngineResult result = _embedderAPI.Initialize( FLUTTER_ENGINE_VERSION, &rendererConfig, &flutterArguments, (__bridge void*)(self), &_engine); if (result != kSuccess) { @@ -360,6 +374,41 @@ - (void)setViewController:(FlutterViewController*)controller { } } +- (void)setupCompositor:(FlutterCompositor*)compositor { + [_mainOpenGLContext makeCurrentContext]; + + _macOSCompositor = + std::make_unique(_viewController, _resourceContext); + + compositor->struct_size = sizeof(FlutterCompositor); + compositor->user_data = _macOSCompositor.get(); + + compositor->create_backing_store_callback = [](const FlutterBackingStoreConfig* config, // + FlutterBackingStore* backing_store_out, // + void* user_data // + ) { + return reinterpret_cast(user_data)->CreateBackingStore( + config, backing_store_out); + }; + + compositor->collect_backing_store_callback = [](const FlutterBackingStore* backing_store, // + void* user_data // + ) { + return reinterpret_cast(user_data)->CollectBackingStore( + backing_store); + }; + + compositor->present_layers_callback = [](const FlutterLayer** layers, // + size_t layers_count, // + void* user_data // + ) { + return reinterpret_cast(user_data)->Present(layers, + layers_count); + }; + + _macOSCompositor->SetPresentCallback([self]() { return [self engineCallbackOnPresent]; }); +} + - (id)binaryMessenger { // TODO(stuartmorgan): Switch to FlutterBinaryMessengerRelay to avoid plugins // keeping the engine alive. diff --git a/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h b/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h new file mode 100644 index 0000000000000..d7da3be7599d3 --- /dev/null +++ b/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h @@ -0,0 +1,57 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "flutter/fml/macros.h" +#include "flutter/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h" +#include "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h" +#include "flutter/shell/platform/embedder/embedder.h" +#include "third_party/skia/include/gpu/GrDirectContext.h" + +namespace flutter { + +/** + * FlutterMacOSGLCompositor creates and manages backing stores used for + * rendering Flutter content and presents Flutter content and Platform views. + */ +class FlutterMacOSGLCompositor { + public: + FlutterMacOSGLCompositor(FlutterViewController* view_controller, + NSOpenGLContext* open_gl_context); + + virtual ~FlutterMacOSGLCompositor(); + + // Creates a backing store according to FlutterBackingStoreConfig + // by modifying backing_store_out. + bool CreateBackingStore(const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out); + + // Releases the memory for any state used by the backing store. + bool CollectBackingStore(const FlutterBackingStore* backing_store); + + // Presents the FlutterLayers by updating FlutterView(s) using the + // layer content. + bool Present(const FlutterLayer** layers, size_t layers_count); + + using PresentCallback = std::function; + + // PresentCallback is called at the end of the Present function. + void SetPresentCallback(const PresentCallback& present_callback); + + protected: + FlutterViewController* view_controller_; + PresentCallback present_callback_; + NSOpenGLContext* open_gl_context_; + + // Creates a FlutterSurfaceManager and uses the FlutterSurfaceManager's + // underlying FBO and texture in the backing store. + bool CreateBackingStoreUsingSurfaceManager( + const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out); + + FML_DISALLOW_COPY_AND_ASSIGN(FlutterMacOSGLCompositor); +}; + +} // namespace flutter diff --git a/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.mm b/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.mm new file mode 100644 index 0000000000000..975532b791c94 --- /dev/null +++ b/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.mm @@ -0,0 +1,94 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h" + +#import +#import "flutter/fml/logging.h" +#import "flutter/fml/platform/darwin/cf_utils.h" +#import "third_party/skia/include/core/SkCanvas.h" +#import "third_party/skia/include/core/SkSurface.h" +#import "third_party/skia/include/gpu/gl/GrGLAssembleInterface.h" +#import "third_party/skia/include/utils/mac/SkCGUtils.h" + +#include + +namespace flutter { + +FlutterMacOSGLCompositor::FlutterMacOSGLCompositor(FlutterViewController* view_controller, + NSOpenGLContext* open_gl_context) + : view_controller_(view_controller), open_gl_context_(open_gl_context) {} + +FlutterMacOSGLCompositor::~FlutterMacOSGLCompositor() = default; + +bool FlutterMacOSGLCompositor::CreateBackingStore(const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out) { + return CreateBackingStoreUsingSurfaceManager(config, backing_store_out); +} + +bool FlutterMacOSGLCompositor::CollectBackingStore(const FlutterBackingStore* backing_store) { + // The memory for FlutterSurfaceManager is handled in the destruction callback. + // No other memory has to be collected. + return true; +} + +bool FlutterMacOSGLCompositor::Present(const FlutterLayer** layers, size_t layers_count) { + for (size_t i = 0; i < layers_count; ++i) { + const auto* layer = layers[i]; + FlutterBackingStore* backing_store = const_cast(layer->backing_store); + switch (layer->type) { + case kFlutterLayerContentTypeBackingStore: { + FlutterSurfaceManager* surfaceManager = + (__bridge FlutterSurfaceManager*)backing_store->user_data; + + CGSize size = CGSizeMake(layer->size.width, layer->size.height); + [view_controller_.flutterView frameBufferIDForSize:size]; + [surfaceManager setLayerContentWithIOSurface:[surfaceManager getIOSurface]]; + break; + } + case kFlutterLayerContentTypePlatformView: + // Add functionality in follow up PR. + FML_CHECK(false) << "Presenting PlatformViews not yet supported"; + break; + }; + } + return present_callback_(); +} + +bool FlutterMacOSGLCompositor::CreateBackingStoreUsingSurfaceManager( + const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out) { + FlutterSurfaceManager* surfaceManager = + [[FlutterSurfaceManager alloc] initWithLayer:view_controller_.flutterView.layer + openGLContext:open_gl_context_]; + + GLuint fbo = [surfaceManager getFramebuffer]; + GLuint texture = [surfaceManager getTexture]; + IOSurfaceRef* io_surface_ref = [surfaceManager getIOSurface]; + + CGSize size = CGSizeMake(config->size.width, config->size.height); + + [surfaceManager backTextureWithIOSurface:io_surface_ref size:size backingTexture:texture fbo:fbo]; + + backing_store_out->type = kFlutterBackingStoreTypeOpenGL; + backing_store_out->user_data = (__bridge_retained void*)surfaceManager; + backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer; + backing_store_out->open_gl.framebuffer.target = GL_RGBA8; + backing_store_out->open_gl.framebuffer.name = fbo; + backing_store_out->open_gl.framebuffer.user_data = backing_store_out->user_data; + backing_store_out->open_gl.framebuffer.destruction_callback = [](void* user_data) { + if (user_data != nullptr) { + CFRelease(user_data); + } + }; + + return true; +} + +void FlutterMacOSGLCompositor::SetPresentCallback( + const FlutterMacOSGLCompositor::PresentCallback& present_callback) { + present_callback_ = present_callback; +} + +} // namespace flutter diff --git a/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositorUnittests.mm b/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositorUnittests.mm new file mode 100644 index 0000000000000..6a5ffacbda140 --- /dev/null +++ b/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositorUnittests.mm @@ -0,0 +1,29 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.h" +#import "flutter/testing/testing.h" + +namespace flutter::testing { + +TEST(FlutterMacOSGLCompositorTest, TestPresent) { + id mockViewController = CreateMockViewController(nil); + + std::unique_ptr macos_compositor = + std::make_unique(mockViewController, nil); + + bool flag = false; + macos_compositor->SetPresentCallback([f = &flag]() { + *f = true; + return true; + }); + + ASSERT_TRUE(macos_compositor->Present(nil, 0)); + ASSERT_TRUE(flag); +} + +} // flutter::testing diff --git a/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h b/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h index afaeebb3ba8a3..133b85e969d55 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h +++ b/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h @@ -1,18 +1,60 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - #import // Manages the IOSurfaces for FlutterView @interface FlutterSurfaceManager : NSObject -- (nullable instancetype)initWithLayer:(nonnull CALayer*)containingLayer - openGLContext:(nonnull NSOpenGLContext*)opengLContext; +- (instancetype)initWithLayer:(CALayer*)layer openGLContext:(NSOpenGLContext*)opengLContext; - (void)ensureSurfaceSize:(CGSize)size; - (void)swapBuffers; - (uint32_t)glFrameBufferId; +/** + * Sets the CALayer content to the content of _ioSurface[kBack]. + */ +- (void)setLayerContent; + +/** + * Sets the CALayer content to the content of the provided ioSurface. + */ +- (void)setLayerContentWithIOSurface:(IOSurfaceRef*)ioSurface; + +/** + * Binds the IOSurface to the provided texture/framebuffer. + */ +- (void)backTextureWithIOSurface:(IOSurfaceRef*)ioSurface + size:(CGSize)size + backingTexture:(GLuint)texture + fbo:(GLuint)fbo; + +// Methods used by FlutterMacOSCompositor to render Flutter content +// using a single Framebuffer/Texture/IOSurface. + +/** + * Returns the kFront framebuffer. + * The framebuffer is used by FlutterMacOSCompositor to create a backing store. + * The framebuffer is collected when the backing store that uses the + * framebuffer is collected. + */ +- (uint32_t)getFramebuffer; + +/** + * Returns the kFront texture. + * The texture is used by FlutterMacOSCompositor to create a backing store. + * The texture is collected when the backing store that uses the + * texture is collected. + */ +- (uint32_t)getTexture; + +/** + * Returns the kFront IOSurfaceRef. + * The IOSurface is backed by the FBO provided by getFramebuffer + * and texture provided by getTexture. The IOSurface is used + * in FlutterMacOSCompositor's Present call. + * The IOSurface is collected when the backing store that uses the + * IOSurface is collected. + */ +- (IOSurfaceRef*)getIOSurface; + @end diff --git a/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm b/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm index c316d7359245f..6c44db2c5650b 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm @@ -69,49 +69,65 @@ - (void)ensureSurfaceSize:(CGSize)size { MacOSGLContextSwitch context_switch(_openGLContext); for (int i = 0; i < kFlutterSurfaceManagerBufferCount; ++i) { - if (_ioSurface[i]) { - CFRelease(_ioSurface[i]); - } - unsigned pixelFormat = 'BGRA'; - unsigned bytesPerElement = 4; - - size_t bytesPerRow = - IOSurfaceAlignProperty(kIOSurfaceBytesPerRow, size.width * bytesPerElement); - size_t totalBytes = IOSurfaceAlignProperty(kIOSurfaceAllocSize, size.height * bytesPerRow); - NSDictionary* options = @{ - (id)kIOSurfaceWidth : @(size.width), - (id)kIOSurfaceHeight : @(size.height), - (id)kIOSurfacePixelFormat : @(pixelFormat), - (id)kIOSurfaceBytesPerElement : @(bytesPerElement), - (id)kIOSurfaceBytesPerRow : @(bytesPerRow), - (id)kIOSurfaceAllocSize : @(totalBytes), - }; - _ioSurface[i] = IOSurfaceCreate((CFDictionaryRef)options); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _backingTexture[i]); - - CGLTexImageIOSurface2D(CGLGetCurrentContext(), GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, - int(size.width), int(size.height), GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, - _ioSurface[i], 0 /* plane */); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - - glBindFramebuffer(GL_FRAMEBUFFER, _frameBufferId[i]); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, - _backingTexture[i], 0); - - NSAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, - @"Framebuffer status check failed"); + [self backTextureWithIOSurface:&_ioSurface[i] + size:size + backingTexture:_backingTexture[i] + fbo:_frameBufferId[i]]; } } -- (void)swapBuffers { +- (void)backTextureWithIOSurface:(IOSurfaceRef*)ioSurface + size:(CGSize)size + backingTexture:(GLuint)texture + fbo:(GLuint)fbo { + if (ioSurface != nullptr && *ioSurface) { + CFRelease(*ioSurface); + } + + unsigned pixelFormat = 'BGRA'; + unsigned bytesPerElement = 4; + + size_t bytesPerRow = IOSurfaceAlignProperty(kIOSurfaceBytesPerRow, size.width * bytesPerElement); + size_t totalBytes = IOSurfaceAlignProperty(kIOSurfaceAllocSize, size.height * bytesPerRow); + NSDictionary* options = @{ + (id)kIOSurfaceWidth : @(size.width), + (id)kIOSurfaceHeight : @(size.height), + (id)kIOSurfacePixelFormat : @(pixelFormat), + (id)kIOSurfaceBytesPerElement : @(bytesPerElement), + (id)kIOSurfaceBytesPerRow : @(bytesPerRow), + (id)kIOSurfaceAllocSize : @(totalBytes), + }; + *ioSurface = IOSurfaceCreate((CFDictionaryRef)options); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture); + + CGLTexImageIOSurface2D(CGLGetCurrentContext(), GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, int(size.width), + int(size.height), GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, *ioSurface, + 0 /* plane */); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, texture, + 0); + + NSAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, + @"Framebuffer status check failed"); +} + +- (void)setLayerContent { + [self setLayerContentWithIOSurface:&_ioSurface[kFlutterSurfaceManagerBackBuffer]]; +} + +- (void)setLayerContentWithIOSurface:(IOSurfaceRef*)ioSurface { _contentLayer.frame = _containingLayer.bounds; // The surface is an OpenGL texture, which means it has origin in bottom left corner // and needs to be flipped vertically _contentLayer.transform = CATransform3DMakeScale(1, -1, 1); - [_contentLayer setContents:(__bridge id)_ioSurface[kFlutterSurfaceManagerBackBuffer]]; + [_contentLayer setContents:(__bridge id) * ioSurface]; +} +- (void)swapBuffers { std::swap(_ioSurface[kFlutterSurfaceManagerBackBuffer], _ioSurface[kFlutterSurfaceManagerFrontBuffer]); std::swap(_frameBufferId[kFlutterSurfaceManagerBackBuffer], @@ -124,6 +140,18 @@ - (uint32_t)glFrameBufferId { return _frameBufferId[kFlutterSurfaceManagerBackBuffer]; } +- (uint32_t)getFramebuffer { + return _frameBufferId[kFlutterSurfaceManagerFrontBuffer]; +} + +- (uint32_t)getTexture { + return _backingTexture[kFlutterSurfaceManagerFrontBuffer]; +} + +- (IOSurfaceRef*)getIOSurface { + return &_ioSurface[kFlutterSurfaceManagerFrontBuffer]; +} + - (void)dealloc { for (int i = 0; i < kFlutterSurfaceManagerBufferCount; ++i) { if (_ioSurface[i]) { diff --git a/shell/platform/darwin/macos/framework/Source/FlutterView.mm b/shell/platform/darwin/macos/framework/Source/FlutterView.mm index d6ce889f54e81..f39d48bd7caae 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterView.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterView.mm @@ -54,6 +54,7 @@ - (void)resizeSynchronizerCommit:(FlutterResizeSynchronizer*)synchronizer { [CATransaction begin]; [CATransaction setDisableActions:YES]; + [_surfaceManager setLayerContent]; [_surfaceManager swapBuffers]; [CATransaction commit]; diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm index ab73278d9c5bf..04816733f6a15 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm @@ -9,34 +9,14 @@ #import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.h" #include "flutter/testing/testing.h" namespace flutter::testing { -// Returns a mock FlutterViewController that is able to work in environments -// without a real pasteboard. -id mockViewController(NSString* pasteboardString) { - NSString* fixtures = @(testing::GetFixturesPath()); - FlutterDartProject* project = [[FlutterDartProject alloc] - initWithAssetsPath:fixtures - ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]]; - FlutterViewController* viewController = [[FlutterViewController alloc] initWithProject:project]; - - // Mock pasteboard so that this test will work in environments without a - // real pasteboard. - id pasteboardMock = OCMClassMock([NSPasteboard class]); - OCMExpect([pasteboardMock stringForType:[OCMArg any]]).andDo(^(NSInvocation* invocation) { - NSString* returnValue = pasteboardString.length > 0 ? pasteboardString : nil; - [invocation setReturnValue:&returnValue]; - }); - id viewControllerMock = OCMPartialMock(viewController); - OCMStub([viewControllerMock pasteboard]).andReturn(pasteboardMock); - return viewControllerMock; -} - TEST(FlutterViewController, HasStringsWhenPasteboardEmpty) { // Mock FlutterViewController so that it behaves like the pasteboard is empty. - id viewControllerMock = mockViewController(nil); + id viewControllerMock = CreateMockViewController(nil); // Call hasStrings and expect it to be false. __block bool calledAfterClear = false; @@ -56,7 +36,7 @@ id mockViewController(NSString* pasteboardString) { TEST(FlutterViewController, HasStringsWhenPasteboardFull) { // Mock FlutterViewController so that it behaves like the pasteboard has a // valid string. - id viewControllerMock = mockViewController(@"some string"); + id viewControllerMock = CreateMockViewController(@"some string"); // Call hasStrings and expect it to be true. __block bool called = false; diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.h b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.h new file mode 100644 index 0000000000000..92021ee44fe82 --- /dev/null +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.h @@ -0,0 +1,14 @@ +#import +#import + +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h" +#import "flutter/testing/testing.h" + +namespace flutter::testing { + +// Returns a mock FlutterViewController that is able to work in environments +// without a real pasteboard. +id CreateMockViewController(NSString* pasteboardString); + +} diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.mm new file mode 100644 index 0000000000000..656661e443ed9 --- /dev/null +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.mm @@ -0,0 +1,26 @@ +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.h" + +namespace flutter::testing { + +id CreateMockViewController(NSString* pasteboardString) { + { + NSString* fixtures = @(testing::GetFixturesPath()); + FlutterDartProject* project = [[FlutterDartProject alloc] + initWithAssetsPath:fixtures + ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]]; + FlutterViewController* viewController = [[FlutterViewController alloc] initWithProject:project]; + + // Mock pasteboard so that this test will work in environments without a + // real pasteboard. + id pasteboardMock = OCMClassMock([NSPasteboard class]); + OCMExpect([pasteboardMock stringForType:[OCMArg any]]).andDo(^(NSInvocation* invocation) { + NSString* returnValue = pasteboardString.length > 0 ? pasteboardString : nil; + [invocation setReturnValue:&returnValue]; + }); + id viewControllerMock = OCMPartialMock(viewController); + OCMStub([viewControllerMock pasteboard]).andReturn(pasteboardMock); + return viewControllerMock; + } +} + +} From 1a3a6d277d2aa979d08cf85b8dd9e10f58125916 Mon Sep 17 00:00:00 2001 From: richardjcai Date: Tue, 17 Nov 2020 12:17:07 -0500 Subject: [PATCH 2/5] Addressing PR comments --- shell/platform/darwin/macos/BUILD.gn | 5 +- .../macos/framework/Source/FlutterEngine.mm | 34 ++++----- .../Source/FlutterMacOSGLCompositor.h | 29 ++++---- .../Source/FlutterMacOSGLCompositor.mm | 71 +++++++++---------- .../FlutterMacOSGLCompositorUnittests.mm | 4 +- .../framework/Source/FlutterSurfaceManager.h | 21 ++---- .../framework/Source/FlutterSurfaceManager.mm | 39 +++++----- .../macos/framework/Source/FlutterView.mm | 3 +- .../Source/FlutterViewControllerTest.mm | 2 +- ...ils.h => FlutterViewControllerTestUtils.h} | 0 ...s.mm => FlutterViewControllerTestUtils.mm} | 2 +- 11 files changed, 97 insertions(+), 113 deletions(-) rename shell/platform/darwin/macos/framework/Source/{FlutterViewControllerTestsUtils.h => FlutterViewControllerTestUtils.h} (100%) rename shell/platform/darwin/macos/framework/Source/{FlutterViewControllerTestsUtils.mm => FlutterViewControllerTestUtils.mm} (96%) diff --git a/shell/platform/darwin/macos/BUILD.gn b/shell/platform/darwin/macos/BUILD.gn index aef31afad26a0..3ad09aa02bd78 100644 --- a/shell/platform/darwin/macos/BUILD.gn +++ b/shell/platform/darwin/macos/BUILD.gn @@ -77,7 +77,6 @@ source_set("flutter_framework_source") { deps = [ "//flutter/flow:flow", "//flutter/fml", - "//flutter/fml:fml", "//flutter/shell/platform/common/cpp:common_cpp_switches", "//flutter/shell/platform/darwin/common:framework_shared", "//flutter/shell/platform/embedder:embedder_as_internal_library", @@ -123,8 +122,8 @@ executable("flutter_desktop_darwin_unittests") { "framework/Source/FlutterEngineTest.mm", "framework/Source/FlutterMacOSGLCompositorUnittests.mm", "framework/Source/FlutterViewControllerTest.mm", - "framework/Source/FlutterViewControllerTestsUtils.h", - "framework/Source/FlutterViewControllerTestsUtils.mm", + "framework/Source/FlutterViewControllerTestUtils.h", + "framework/Source/FlutterViewControllerTestUtils.mm", ] cflags_objcc = [ "-fobjc-arc" ] diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm index 2cb72d1745a46..4c05d80ab49f6 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm @@ -201,7 +201,11 @@ @implementation FlutterEngine { // FlutterMacOSGLCompositor is created by the engine. // This is only created when the engine has a FlutterViewController // and used to support platform views. + // Creation / Destruction. std::unique_ptr _macOSCompositor; + + // FlutterCompositor is copied and used in embedder.cc. + FlutterCompositor _compositor; } - (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)project { @@ -311,14 +315,8 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint { flutterArguments.aot_data = _aotData; } - // Only create a Compositor if we have a ViewController. - if (_viewController) { - // Engine does not need to manage the life cycle of compositor - // since compositor is captured and copied in embedder.cc. - FlutterCompositor compositor = {}; - [self setupCompositor:&compositor]; - flutterArguments.compositor = &compositor; - } + [self setupCompositor]; + flutterArguments.compositor = &_compositor; FlutterEngineResult result = _embedderAPI.Initialize( FLUTTER_ENGINE_VERSION, &rendererConfig, &flutterArguments, (__bridge void*)(self), &_engine); @@ -374,16 +372,16 @@ - (void)setViewController:(FlutterViewController*)controller { } } -- (void)setupCompositor:(FlutterCompositor*)compositor { +- (void)setupCompositor { [_mainOpenGLContext makeCurrentContext]; - _macOSCompositor = - std::make_unique(_viewController, _resourceContext); + _macOSCompositor = std::make_unique(_viewController); - compositor->struct_size = sizeof(FlutterCompositor); - compositor->user_data = _macOSCompositor.get(); + _compositor = {}; + _compositor.struct_size = sizeof(FlutterCompositor); + _compositor.user_data = _macOSCompositor.get(); - compositor->create_backing_store_callback = [](const FlutterBackingStoreConfig* config, // + _compositor.create_backing_store_callback = [](const FlutterBackingStoreConfig* config, // FlutterBackingStore* backing_store_out, // void* user_data // ) { @@ -391,14 +389,14 @@ - (void)setupCompositor:(FlutterCompositor*)compositor { config, backing_store_out); }; - compositor->collect_backing_store_callback = [](const FlutterBackingStore* backing_store, // + _compositor.collect_backing_store_callback = [](const FlutterBackingStore* backing_store, // void* user_data // ) { return reinterpret_cast(user_data)->CollectBackingStore( backing_store); }; - compositor->present_layers_callback = [](const FlutterLayer** layers, // + _compositor.present_layers_callback = [](const FlutterLayer** layers, // size_t layers_count, // void* user_data // ) { @@ -406,7 +404,9 @@ - (void)setupCompositor:(FlutterCompositor*)compositor { layers_count); }; - _macOSCompositor->SetPresentCallback([self]() { return [self engineCallbackOnPresent]; }); + __weak FlutterEngine* weak_self = self; + _macOSCompositor->SetPresentCallback( + [weak_self]() { return [weak_self engineCallbackOnPresent]; }); } - (id)binaryMessenger { diff --git a/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h b/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h index d7da3be7599d3..ef1baba4408a6 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h +++ b/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h @@ -12,19 +12,20 @@ namespace flutter { -/** - * FlutterMacOSGLCompositor creates and manages backing stores used for - * rendering Flutter content and presents Flutter content and Platform views. - */ +// FlutterMacOSGLCompositor creates and manages the backing stores used for +// rendering Flutter content and presents Flutter content and Platform views. +// Platform views are not yet supported. +// FlutterMacOSGLCompositor is created and destroyed by FlutterEngine. class FlutterMacOSGLCompositor { public: - FlutterMacOSGLCompositor(FlutterViewController* view_controller, - NSOpenGLContext* open_gl_context); + FlutterMacOSGLCompositor(FlutterViewController* view_controller); - virtual ~FlutterMacOSGLCompositor(); - - // Creates a backing store according to FlutterBackingStoreConfig - // by modifying backing_store_out. + // Creates a FlutterSurfaceManager and uses the FlutterSurfaceManager's + // underlying FBO and texture in the backing store. + // Any additional state allocated for the backing store and + // saved as user_data in the backing store must be collected + // in the backing_store's desctruction_callback field which will + // be called when the embedder collects the backing store. bool CreateBackingStore(const FlutterBackingStoreConfig* config, FlutterBackingStore* backing_store_out); @@ -40,17 +41,11 @@ class FlutterMacOSGLCompositor { // PresentCallback is called at the end of the Present function. void SetPresentCallback(const PresentCallback& present_callback); - protected: + private: FlutterViewController* view_controller_; PresentCallback present_callback_; NSOpenGLContext* open_gl_context_; - // Creates a FlutterSurfaceManager and uses the FlutterSurfaceManager's - // underlying FBO and texture in the backing store. - bool CreateBackingStoreUsingSurfaceManager( - const FlutterBackingStoreConfig* config, - FlutterBackingStore* backing_store_out); - FML_DISALLOW_COPY_AND_ASSIGN(FlutterMacOSGLCompositor); }; diff --git a/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.mm b/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.mm index 975532b791c94..a8c795cdec798 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.mm @@ -16,15 +16,39 @@ namespace flutter { -FlutterMacOSGLCompositor::FlutterMacOSGLCompositor(FlutterViewController* view_controller, - NSOpenGLContext* open_gl_context) - : view_controller_(view_controller), open_gl_context_(open_gl_context) {} - -FlutterMacOSGLCompositor::~FlutterMacOSGLCompositor() = default; +FlutterMacOSGLCompositor::FlutterMacOSGLCompositor(FlutterViewController* view_controller) + : view_controller_(view_controller), + open_gl_context_(view_controller.flutterView.openGLContext) {} bool FlutterMacOSGLCompositor::CreateBackingStore(const FlutterBackingStoreConfig* config, FlutterBackingStore* backing_store_out) { - return CreateBackingStoreUsingSurfaceManager(config, backing_store_out); + FlutterSurfaceManager* surfaceManager = + [[FlutterSurfaceManager alloc] initWithLayer:view_controller_.flutterView.layer + openGLContext:open_gl_context_ + numFramebuffers:1]; + + GLuint fbo = [surfaceManager getFramebuffer]; + GLuint texture = [surfaceManager getTexture]; + + CGSize size = CGSizeMake(config->size.width, config->size.height); + size_t kFlutterSurfaceManagerFrontBuffer = 0; + [surfaceManager backTextureWithIOSurface:kFlutterSurfaceManagerFrontBuffer + size:size + backingTexture:texture + fbo:fbo]; + + backing_store_out->type = kFlutterBackingStoreTypeOpenGL; + backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer; + backing_store_out->open_gl.framebuffer.target = GL_RGBA8; + backing_store_out->open_gl.framebuffer.name = fbo; + backing_store_out->open_gl.framebuffer.user_data = (__bridge_retained void*)surfaceManager; + backing_store_out->open_gl.framebuffer.destruction_callback = [](void* user_data) { + if (user_data != nullptr) { + CFRelease(user_data); + } + }; + + return true; } bool FlutterMacOSGLCompositor::CollectBackingStore(const FlutterBackingStore* backing_store) { @@ -40,11 +64,12 @@ switch (layer->type) { case kFlutterLayerContentTypeBackingStore: { FlutterSurfaceManager* surfaceManager = - (__bridge FlutterSurfaceManager*)backing_store->user_data; + (__bridge FlutterSurfaceManager*)backing_store->open_gl.framebuffer.user_data; CGSize size = CGSizeMake(layer->size.width, layer->size.height); [view_controller_.flutterView frameBufferIDForSize:size]; - [surfaceManager setLayerContentWithIOSurface:[surfaceManager getIOSurface]]; + size_t kFlutterSurfaceManagerFrontBuffer = 0; + [surfaceManager setLayerContentWithIOSurface:kFlutterSurfaceManagerFrontBuffer]; break; } case kFlutterLayerContentTypePlatformView: @@ -56,36 +81,6 @@ return present_callback_(); } -bool FlutterMacOSGLCompositor::CreateBackingStoreUsingSurfaceManager( - const FlutterBackingStoreConfig* config, - FlutterBackingStore* backing_store_out) { - FlutterSurfaceManager* surfaceManager = - [[FlutterSurfaceManager alloc] initWithLayer:view_controller_.flutterView.layer - openGLContext:open_gl_context_]; - - GLuint fbo = [surfaceManager getFramebuffer]; - GLuint texture = [surfaceManager getTexture]; - IOSurfaceRef* io_surface_ref = [surfaceManager getIOSurface]; - - CGSize size = CGSizeMake(config->size.width, config->size.height); - - [surfaceManager backTextureWithIOSurface:io_surface_ref size:size backingTexture:texture fbo:fbo]; - - backing_store_out->type = kFlutterBackingStoreTypeOpenGL; - backing_store_out->user_data = (__bridge_retained void*)surfaceManager; - backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer; - backing_store_out->open_gl.framebuffer.target = GL_RGBA8; - backing_store_out->open_gl.framebuffer.name = fbo; - backing_store_out->open_gl.framebuffer.user_data = backing_store_out->user_data; - backing_store_out->open_gl.framebuffer.destruction_callback = [](void* user_data) { - if (user_data != nullptr) { - CFRelease(user_data); - } - }; - - return true; -} - void FlutterMacOSGLCompositor::SetPresentCallback( const FlutterMacOSGLCompositor::PresentCallback& present_callback) { present_callback_ = present_callback; diff --git a/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositorUnittests.mm b/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositorUnittests.mm index 6a5ffacbda140..6383a1cd2a6b5 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositorUnittests.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositorUnittests.mm @@ -5,7 +5,7 @@ #import #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h" -#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.h" #import "flutter/testing/testing.h" namespace flutter::testing { @@ -14,7 +14,7 @@ id mockViewController = CreateMockViewController(nil); std::unique_ptr macos_compositor = - std::make_unique(mockViewController, nil); + std::make_unique(mockViewController); bool flag = false; macos_compositor->SetPresentCallback([f = &flag]() { diff --git a/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h b/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h index 133b85e969d55..ef41f6a6ada2b 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h +++ b/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h @@ -3,7 +3,9 @@ // Manages the IOSurfaces for FlutterView @interface FlutterSurfaceManager : NSObject -- (instancetype)initWithLayer:(CALayer*)layer openGLContext:(NSOpenGLContext*)opengLContext; +- (instancetype)initWithLayer:(CALayer*)containingLayer + openGLContext:(NSOpenGLContext*)openGLContext + numFramebuffers:(int)numFramebuffers; - (void)ensureSurfaceSize:(CGSize)size; - (void)swapBuffers; @@ -16,14 +18,15 @@ - (void)setLayerContent; /** - * Sets the CALayer content to the content of the provided ioSurface. + * Sets the CALayer content to the content of ioSurface at ioSurfaceNum. */ -- (void)setLayerContentWithIOSurface:(IOSurfaceRef*)ioSurface; +// TODO(richardjcai): Fix this and remove setLayerContent. +- (void)setLayerContentWithIOSurface:(int)ioSurfaceNum; /** * Binds the IOSurface to the provided texture/framebuffer. */ -- (void)backTextureWithIOSurface:(IOSurfaceRef*)ioSurface +- (void)backTextureWithIOSurface:(int)ioSurfaceNum size:(CGSize)size backingTexture:(GLuint)texture fbo:(GLuint)fbo; @@ -47,14 +50,4 @@ */ - (uint32_t)getTexture; -/** - * Returns the kFront IOSurfaceRef. - * The IOSurface is backed by the FBO provided by getFramebuffer - * and texture provided by getTexture. The IOSurface is used - * in FlutterMacOSCompositor's Present call. - * The IOSurface is collected when the backing store that uses the - * IOSurface is collected. - */ -- (IOSurfaceRef*)getIOSurface; - @end diff --git a/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm b/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm index 6c44db2c5650b..0cb5fa054e45c 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm @@ -29,7 +29,8 @@ @interface FlutterSurfaceManager () { @implementation FlutterSurfaceManager - (instancetype)initWithLayer:(CALayer*)containingLayer - openGLContext:(NSOpenGLContext*)openGLContext { + openGLContext:(NSOpenGLContext*)openGLContext + numFramebuffers:(int)numFramebuffers { if (self = [super init]) { _containingLayer = containingLayer; _openGLContext = openGLContext; @@ -41,11 +42,12 @@ - (instancetype)initWithLayer:(CALayer*)containingLayer MacOSGLContextSwitch context_switch(openGLContext); - glGenFramebuffers(2, _frameBufferId); - glGenTextures(2, _backingTexture); + glGenFramebuffers(numFramebuffers, _frameBufferId); + glGenTextures(numFramebuffers, _backingTexture); - [self createFramebuffer:_frameBufferId[0] withBackingTexture:_backingTexture[0]]; - [self createFramebuffer:_frameBufferId[1] withBackingTexture:_backingTexture[1]]; + for (int i = 0; i < numFramebuffers; ++i) { + [self createFramebuffer:_frameBufferId[i] withBackingTexture:_backingTexture[1]]; + } } return self; } @@ -69,19 +71,19 @@ - (void)ensureSurfaceSize:(CGSize)size { MacOSGLContextSwitch context_switch(_openGLContext); for (int i = 0; i < kFlutterSurfaceManagerBufferCount; ++i) { - [self backTextureWithIOSurface:&_ioSurface[i] + [self backTextureWithIOSurface:i size:size backingTexture:_backingTexture[i] fbo:_frameBufferId[i]]; } } -- (void)backTextureWithIOSurface:(IOSurfaceRef*)ioSurface +- (void)backTextureWithIOSurface:(int)ioSurfaceNum size:(CGSize)size backingTexture:(GLuint)texture fbo:(GLuint)fbo { - if (ioSurface != nullptr && *ioSurface) { - CFRelease(*ioSurface); + if (_ioSurface[ioSurfaceNum]) { + CFRelease(_ioSurface[ioSurfaceNum]); } unsigned pixelFormat = 'BGRA'; @@ -97,13 +99,13 @@ - (void)backTextureWithIOSurface:(IOSurfaceRef*)ioSurface (id)kIOSurfaceBytesPerRow : @(bytesPerRow), (id)kIOSurfaceAllocSize : @(totalBytes), }; - *ioSurface = IOSurfaceCreate((CFDictionaryRef)options); + _ioSurface[ioSurfaceNum] = IOSurfaceCreate((CFDictionaryRef)options); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture); CGLTexImageIOSurface2D(CGLGetCurrentContext(), GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, int(size.width), - int(size.height), GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, *ioSurface, - 0 /* plane */); + int(size.height), GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, + _ioSurface[ioSurfaceNum], 0 /* plane */); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -115,16 +117,16 @@ - (void)backTextureWithIOSurface:(IOSurfaceRef*)ioSurface } - (void)setLayerContent { - [self setLayerContentWithIOSurface:&_ioSurface[kFlutterSurfaceManagerBackBuffer]]; + [self setLayerContentWithIOSurface:kFlutterSurfaceManagerBackBuffer]; } -- (void)setLayerContentWithIOSurface:(IOSurfaceRef*)ioSurface { +- (void)setLayerContentWithIOSurface:(int)ioSurfaceNum { _contentLayer.frame = _containingLayer.bounds; // The surface is an OpenGL texture, which means it has origin in bottom left corner // and needs to be flipped vertically _contentLayer.transform = CATransform3DMakeScale(1, -1, 1); - [_contentLayer setContents:(__bridge id) * ioSurface]; + [_contentLayer setContents:(__bridge id)_ioSurface[ioSurfaceNum]]; } - (void)swapBuffers { @@ -148,11 +150,10 @@ - (uint32_t)getTexture { return _backingTexture[kFlutterSurfaceManagerFrontBuffer]; } -- (IOSurfaceRef*)getIOSurface { - return &_ioSurface[kFlutterSurfaceManagerFrontBuffer]; -} - - (void)dealloc { + [_contentLayer removeFromSuperlayer]; + glDeleteFramebuffers(kFlutterSurfaceManagerBufferCount, _frameBufferId); + glDeleteTextures(kFlutterSurfaceManagerBufferCount, _backingTexture); for (int i = 0; i < kFlutterSurfaceManagerBufferCount; ++i) { if (_ioSurface[i]) { CFRelease(_ioSurface[i]); diff --git a/shell/platform/darwin/macos/framework/Source/FlutterView.mm b/shell/platform/darwin/macos/framework/Source/FlutterView.mm index f39d48bd7caae..9a5f9270cbfca 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterView.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterView.mm @@ -38,7 +38,8 @@ - (instancetype)initWithFrame:(NSRect)frame _resizeSynchronizer = [[FlutterResizeSynchronizer alloc] initWithDelegate:self]; _surfaceManager = [[FlutterSurfaceManager alloc] initWithLayer:self.layer - openGLContext:self.openGLContext]; + openGLContext:self.openGLContext + numFramebuffers:2]; _reshapeListener = reshapeListener; } diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm index 04816733f6a15..671520f494923 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm @@ -9,7 +9,7 @@ #import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h" -#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.h" #include "flutter/testing/testing.h" namespace flutter::testing { diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.h b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.h similarity index 100% rename from shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.h rename to shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.h diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.mm similarity index 96% rename from shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.mm rename to shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.mm index 656661e443ed9..04f320ba97030 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.mm @@ -1,4 +1,4 @@ -#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.h" namespace flutter::testing { From 48e436238ffc8514a7bd280a66b15af907ef610a Mon Sep 17 00:00:00 2001 From: richardjcai Date: Thu, 19 Nov 2020 12:05:55 -0500 Subject: [PATCH 3/5] For MacOS, rasterizer will only use the compositor if there is a platform view in the layer tree. Otherwise the current render path will be used. This is to avoid regression as Compositor currently doesn't fully support resizing. --- flow/layers/container_layer.cc | 13 ++++++ flow/layers/container_layer.h | 3 ++ flow/layers/layer.cc | 6 +++ flow/layers/layer.h | 4 ++ flow/layers/layer_tree.cc | 5 ++ flow/layers/layer_tree.h | 7 +++ flow/layers/platform_view_layer.cc | 6 +++ flow/layers/platform_view_layer.h | 3 ++ flow/surface.cc | 2 + flow/surface.h | 5 ++ shell/common/rasterizer.cc | 46 ++++++++++++++++--- shell/gpu/gpu_surface_gl.cc | 5 ++ shell/gpu/gpu_surface_gl.h | 5 +- shell/gpu/gpu_surface_software.h | 2 +- .../Source/FlutterMacOSGLCompositor.h | 4 +- 15 files changed, 105 insertions(+), 11 deletions(-) diff --git a/flow/layers/container_layer.cc b/flow/layers/container_layer.cc index 5bbbb438c9d79..1189b90d88f13 100644 --- a/flow/layers/container_layer.cc +++ b/flow/layers/container_layer.cc @@ -96,6 +96,19 @@ void ContainerLayer::TryToPrepareRasterCache(PrerollContext* context, } } +#if defined(OS_MACOSX) +bool ContainerLayer::HasPlatformView() { + bool hasPlatformView = false; + for (auto& layer : layers_) { + if (layer->HasPlatformView()) { + hasPlatformView = true; + } + } + + return hasPlatformView; +} +#endif + #if defined(LEGACY_FUCHSIA_EMBEDDER) void ContainerLayer::CheckForChildLayerBelow(PrerollContext* context) { diff --git a/flow/layers/container_layer.h b/flow/layers/container_layer.h index 11eae5f3fe123..ed86200aedba3 100644 --- a/flow/layers/container_layer.h +++ b/flow/layers/container_layer.h @@ -19,6 +19,9 @@ class ContainerLayer : public Layer { void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext& context) const override; +#if defined(OS_MACOSX) + bool HasPlatformView() override; +#endif #if defined(LEGACY_FUCHSIA_EMBEDDER) void CheckForChildLayerBelow(PrerollContext* context) override; void UpdateScene(std::shared_ptr context) override; diff --git a/flow/layers/layer.cc b/flow/layers/layer.cc index 006f5cb84e916..1fa10c5931142 100644 --- a/flow/layers/layer.cc +++ b/flow/layers/layer.cc @@ -27,6 +27,12 @@ uint64_t Layer::NextUniqueID() { void Layer::Preroll(PrerollContext* context, const SkMatrix& matrix) {} +#if defined(OS_MACOSX) +bool Layer::HasPlatformView() { + return false; +} +#endif + Layer::AutoPrerollSaveLayerState::AutoPrerollSaveLayerState( PrerollContext* preroll_context, bool save_layer_is_active, diff --git a/flow/layers/layer.h b/flow/layers/layer.h index 4ab93ce86903e..bea69375fe52b 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -75,6 +75,10 @@ class Layer { virtual void Preroll(PrerollContext* context, const SkMatrix& matrix); +#if defined(OS_MACOSX) + virtual bool HasPlatformView(); +#endif + // Used during Preroll by layers that employ a saveLayer to manage the // PrerollContext settings with values affected by the saveLayer mechanism. // This object must be created before calling Preroll on the children to diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index 8169e8bf6ba2e..15f9bdca0bcb4 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -60,6 +60,11 @@ bool LayerTree::Preroll(CompositorContext::ScopedFrame& frame, root_layer_->Preroll(&context, frame.root_surface_transformation()); return context.surface_needs_readback; } +#if defined(OS_MACOSX) +bool LayerTree::HasPlatformView() { + return root_layer_->HasPlatformView(); +} +#endif #if defined(LEGACY_FUCHSIA_EMBEDDER) void LayerTree::UpdateScene(std::shared_ptr context) { diff --git a/flow/layers/layer_tree.h b/flow/layers/layer_tree.h index b59f278296381..5f90343dc7edc 100644 --- a/flow/layers/layer_tree.h +++ b/flow/layers/layer_tree.h @@ -31,6 +31,13 @@ class LayerTree { bool Preroll(CompositorContext::ScopedFrame& frame, bool ignore_raster_cache = false); + // Used to check before Prerolling to see if the layer tree + // contains a platform view. + // Specifically used for MacOS to determine if the compositor + // should be used. +#if defined(OS_MACOSX) + bool HasPlatformView(); +#endif #if defined(LEGACY_FUCHSIA_EMBEDDER) void UpdateScene(std::shared_ptr context); #endif diff --git a/flow/layers/platform_view_layer.cc b/flow/layers/platform_view_layer.cc index 0971f93db777e..fcb1b1cc5243b 100644 --- a/flow/layers/platform_view_layer.cc +++ b/flow/layers/platform_view_layer.cc @@ -34,6 +34,12 @@ void PlatformViewLayer::Preroll(PrerollContext* context, std::move(params)); } +#if defined(OS_MACOSX) +bool PlatformViewLayer::HasPlatformView() { + return true; +} +#endif + void PlatformViewLayer::Paint(PaintContext& context) const { if (context.view_embedder == nullptr) { #if !defined(LEGACY_FUCHSIA_EMBEDDER) diff --git a/flow/layers/platform_view_layer.h b/flow/layers/platform_view_layer.h index e9d6fac42eb23..0d807a19d838c 100644 --- a/flow/layers/platform_view_layer.h +++ b/flow/layers/platform_view_layer.h @@ -17,6 +17,9 @@ class PlatformViewLayer : public Layer { void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext& context) const override; +#if defined(OS_MACOSX) + bool HasPlatformView() override; +#endif #if defined(LEGACY_FUCHSIA_EMBEDDER) // Updates the system composited scene. void UpdateScene(std::shared_ptr context) override; diff --git a/flow/surface.cc b/flow/surface.cc index 7dbe56c1e8e78..aa81de16c9319 100644 --- a/flow/surface.cc +++ b/flow/surface.cc @@ -18,4 +18,6 @@ bool Surface::ClearRenderContext() { return false; } +void Surface::SetRenderToSurface(bool render_to_surface) {} + } // namespace flutter diff --git a/flow/surface.h b/flow/surface.h index 21b248c074d4c..f407e4a98f22f 100644 --- a/flow/surface.h +++ b/flow/surface.h @@ -33,6 +33,11 @@ class Surface { virtual bool ClearRenderContext(); + // SetRenderToSurface sets whether or not the surface should be rendered to. + // This is needed for MacOS as we want to render scenes without platform views + // to the surface even in the existence of a external_view_embedder. + virtual void SetRenderToSurface(bool render_to_surface); + private: FML_DISALLOW_COPY_AND_ASSIGN(Surface); }; diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 1d326a7727166..b8fcefa7cc0a9 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -424,13 +424,30 @@ RasterStatus Rasterizer::DrawToSurface(flutter::LayerTree& layer_tree) { compositor_context_->ui_time().SetLapTime(layer_tree.build_time()); SkCanvas* embedder_root_canvas = nullptr; +#if defined(OS_MACOSX) + // For MacOS, we only want to use the external_view_embedder / compositor + // if there is a platform view in the layer tree. + // TODO(richardjcai): Remove branching logic for using external_view_embedder + // once the compositor supports smooth resizing. + // https://github.com/flutter/flutter/issues/70848. + bool hasPlatformView = layer_tree.HasPlatformView(); + if (external_view_embedder_ && hasPlatformView) { +#else if (external_view_embedder_) { +#endif external_view_embedder_->BeginFrame( layer_tree.frame_size(), surface_->GetContext(), layer_tree.device_pixel_ratio(), raster_thread_merger_); embedder_root_canvas = external_view_embedder_->GetRootCanvas(); } +#if defined(OS_MACOSX) + if (external_view_embedder_ && hasPlatformView) { + surface_->SetRenderToSurface(false); + } else { + surface_->SetRenderToSurface(true); + } +#endif // On Android, the external view embedder deletes surfaces in `BeginFrame`. // // Deleting a surface also clears the GL context. Therefore, acquire the @@ -450,14 +467,23 @@ RasterStatus Rasterizer::DrawToSurface(flutter::LayerTree& layer_tree) { auto root_surface_canvas = embedder_root_canvas ? embedder_root_canvas : frame->SkiaCanvas(); +#if defined(OS_MACOSX) + auto external_view_embedder = + hasPlatformView ? external_view_embedder_.get() : nullptr; + auto raster_thread_merger = hasPlatformView ? raster_thread_merger_ : nullptr; +#else + auto external_view_embedder = external_view_embedder_.get(); + auto raster_thread_merger = raster_thread_merger_; +#endif + auto compositor_frame = compositor_context_->AcquireFrame( - surface_->GetContext(), // skia GrContext - root_surface_canvas, // root surface canvas - external_view_embedder_.get(), // external view embedder - root_surface_transformation, // root surface transformation - true, // instrumentation enabled - frame->supports_readback(), // surface supports pixel reads - raster_thread_merger_ // thread merger + surface_->GetContext(), // skia GrContext + root_surface_canvas, // root surface canvas + external_view_embedder, // external view embedder + root_surface_transformation, // root surface transformation + true, // instrumentation enabled + frame->supports_readback(), // surface supports pixel reads + raster_thread_merger // thread merger ); if (compositor_frame) { @@ -466,8 +492,14 @@ RasterStatus Rasterizer::DrawToSurface(flutter::LayerTree& layer_tree) { raster_status == RasterStatus::kSkipAndRetry) { return raster_status; } +#if defined(OS_MACOSX) + if (external_view_embedder_ && + (!raster_thread_merger_ || raster_thread_merger_->IsMerged()) && + hasPlatformView) { +#else if (external_view_embedder_ && (!raster_thread_merger_ || raster_thread_merger_->IsMerged())) { +#endif FML_DCHECK(!frame->IsSubmitted()); external_view_embedder_->SubmitFrame(surface_->GetContext(), std::move(frame)); diff --git a/shell/gpu/gpu_surface_gl.cc b/shell/gpu/gpu_surface_gl.cc index 388a22e352dd5..9edd1b991c699 100644 --- a/shell/gpu/gpu_surface_gl.cc +++ b/shell/gpu/gpu_surface_gl.cc @@ -343,4 +343,9 @@ bool GPUSurfaceGL::ClearRenderContext() { return delegate_->GLContextClearCurrent(); } +// |Surface| +void GPUSurfaceGL::SetRenderToSurface(bool render_to_surface) { + render_to_surface_ = render_to_surface; +} + } // namespace flutter diff --git a/shell/gpu/gpu_surface_gl.h b/shell/gpu/gpu_surface_gl.h index e7fa001123e52..6ec7848c3efd5 100644 --- a/shell/gpu/gpu_surface_gl.h +++ b/shell/gpu/gpu_surface_gl.h @@ -48,6 +48,9 @@ class GPUSurfaceGL : public Surface { // |Surface| bool ClearRenderContext() override; + // |Surface| + void SetRenderToSurface(bool render_to_surface) override; + private: GPUSurfaceGLDelegate* delegate_; sk_sp context_; @@ -59,7 +62,7 @@ class GPUSurfaceGL : public Surface { // external view embedder may want to render to the root surface. This is a // hack to make avoid allocating resources for the root surface when an // external view embedder is present. - const bool render_to_surface_; + bool render_to_surface_; bool valid_ = false; fml::TaskRunnerAffineWeakPtrFactory weak_factory_; diff --git a/shell/gpu/gpu_surface_software.h b/shell/gpu/gpu_surface_software.h index 23d5cdedf8fed..1f51e8f6e2dc4 100644 --- a/shell/gpu/gpu_surface_software.h +++ b/shell/gpu/gpu_surface_software.h @@ -37,7 +37,7 @@ class GPUSurfaceSoftware : public Surface { // external view embedder may want to render to the root surface. This is a // hack to make avoid allocating resources for the root surface when an // external view embedder is present. - const bool render_to_surface_; + bool render_to_surface_; fml::TaskRunnerAffineWeakPtrFactory weak_factory_; FML_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceSoftware); diff --git a/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h b/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h index ef1baba4408a6..e840ba1ceab97 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h +++ b/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h @@ -15,14 +15,14 @@ namespace flutter { // FlutterMacOSGLCompositor creates and manages the backing stores used for // rendering Flutter content and presents Flutter content and Platform views. // Platform views are not yet supported. -// FlutterMacOSGLCompositor is created and destroyed by FlutterEngine. +// FlutterMacOSGLCompositor is created and destroyed by FlutterEngine. class FlutterMacOSGLCompositor { public: FlutterMacOSGLCompositor(FlutterViewController* view_controller); // Creates a FlutterSurfaceManager and uses the FlutterSurfaceManager's // underlying FBO and texture in the backing store. - // Any additional state allocated for the backing store and + // Any additional state allocated for the backing store and // saved as user_data in the backing store must be collected // in the backing_store's desctruction_callback field which will // be called when the embedder collects the backing store. From 3f3396efe011a43a3caccecd00df3fcf511b4658 Mon Sep 17 00:00:00 2001 From: richardjcai Date: Thu, 19 Nov 2020 15:56:29 -0500 Subject: [PATCH 4/5] Refactor FlutterSurfaceManager methods --- .../Source/FlutterMacOSGLCompositor.mm | 15 +++---- .../framework/Source/FlutterSurfaceManager.h | 36 +++++++---------- .../framework/Source/FlutterSurfaceManager.mm | 39 ++++++++----------- .../macos/framework/Source/FlutterView.mm | 2 +- 4 files changed, 37 insertions(+), 55 deletions(-) diff --git a/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.mm b/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.mm index a8c795cdec798..58d7224e35862 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.mm @@ -27,20 +27,15 @@ openGLContext:open_gl_context_ numFramebuffers:1]; - GLuint fbo = [surfaceManager getFramebuffer]; - GLuint texture = [surfaceManager getTexture]; - CGSize size = CGSizeMake(config->size.width, config->size.height); - size_t kFlutterSurfaceManagerFrontBuffer = 0; - [surfaceManager backTextureWithIOSurface:kFlutterSurfaceManagerFrontBuffer - size:size - backingTexture:texture - fbo:fbo]; + int kFlutterSurfaceManagerFrontBuffer = 0; + [surfaceManager recreateIOSurface:kFlutterSurfaceManagerFrontBuffer size:size]; + [surfaceManager backTextureWithIOSurface:kFlutterSurfaceManagerFrontBuffer size:size]; backing_store_out->type = kFlutterBackingStoreTypeOpenGL; backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer; backing_store_out->open_gl.framebuffer.target = GL_RGBA8; - backing_store_out->open_gl.framebuffer.name = fbo; + backing_store_out->open_gl.framebuffer.name = [surfaceManager glFrameBufferFrontId]; backing_store_out->open_gl.framebuffer.user_data = (__bridge_retained void*)surfaceManager; backing_store_out->open_gl.framebuffer.destruction_callback = [](void* user_data) { if (user_data != nullptr) { @@ -68,7 +63,7 @@ CGSize size = CGSizeMake(layer->size.width, layer->size.height); [view_controller_.flutterView frameBufferIDForSize:size]; - size_t kFlutterSurfaceManagerFrontBuffer = 0; + int kFlutterSurfaceManagerFrontBuffer = 0; [surfaceManager setLayerContentWithIOSurface:kFlutterSurfaceManagerFrontBuffer]; break; } diff --git a/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h b/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h index ef41f6a6ada2b..fd13089bd3de1 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h +++ b/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h @@ -10,29 +10,31 @@ - (void)ensureSurfaceSize:(CGSize)size; - (void)swapBuffers; -- (uint32_t)glFrameBufferId; - /** * Sets the CALayer content to the content of _ioSurface[kBack]. */ - (void)setLayerContent; /** - * Sets the CALayer content to the content of ioSurface at ioSurfaceNum. + * Sets the CALayer content to the content of _ioSurface[index]. */ -// TODO(richardjcai): Fix this and remove setLayerContent. -- (void)setLayerContentWithIOSurface:(int)ioSurfaceNum; +- (void)setLayerContentWithIOSurface:(int)index; /** - * Binds the IOSurface to the provided texture/framebuffer. + * Recreates the IOSurface _ioSurface[index] with specified size. */ -- (void)backTextureWithIOSurface:(int)ioSurfaceNum - size:(CGSize)size - backingTexture:(GLuint)texture - fbo:(GLuint)fbo; +- (void)recreateIOSurface:(int)index size:(CGSize)size; -// Methods used by FlutterMacOSCompositor to render Flutter content -// using a single Framebuffer/Texture/IOSurface. +/** + * Binds the IOSurface at _ioSurface[index] to the texture id at + * _backingTexture[index] and fbo at _frameBufferId[index]. + */ +- (void)backTextureWithIOSurface:(int)index size:(CGSize)size; + +/** + * Returns the kBack framebuffer. + */ +- (uint32_t)glFrameBufferBackId; /** * Returns the kFront framebuffer. @@ -40,14 +42,6 @@ * The framebuffer is collected when the backing store that uses the * framebuffer is collected. */ -- (uint32_t)getFramebuffer; - -/** - * Returns the kFront texture. - * The texture is used by FlutterMacOSCompositor to create a backing store. - * The texture is collected when the backing store that uses the - * texture is collected. - */ -- (uint32_t)getTexture; +- (uint32_t)glFrameBufferFrontId; @end diff --git a/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm b/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm index 0cb5fa054e45c..dfcdf0fd68e18 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm @@ -71,19 +71,14 @@ - (void)ensureSurfaceSize:(CGSize)size { MacOSGLContextSwitch context_switch(_openGLContext); for (int i = 0; i < kFlutterSurfaceManagerBufferCount; ++i) { - [self backTextureWithIOSurface:i - size:size - backingTexture:_backingTexture[i] - fbo:_frameBufferId[i]]; + [self recreateIOSurface:i size:size]; + [self backTextureWithIOSurface:i size:size]; } } -- (void)backTextureWithIOSurface:(int)ioSurfaceNum - size:(CGSize)size - backingTexture:(GLuint)texture - fbo:(GLuint)fbo { - if (_ioSurface[ioSurfaceNum]) { - CFRelease(_ioSurface[ioSurfaceNum]); +- (void)recreateIOSurface:(int)index size:(CGSize)size { + if (_ioSurface[index]) { + CFRelease(_ioSurface[index]); } unsigned pixelFormat = 'BGRA'; @@ -99,18 +94,20 @@ - (void)backTextureWithIOSurface:(int)ioSurfaceNum (id)kIOSurfaceBytesPerRow : @(bytesPerRow), (id)kIOSurfaceAllocSize : @(totalBytes), }; - _ioSurface[ioSurfaceNum] = IOSurfaceCreate((CFDictionaryRef)options); + _ioSurface[index] = IOSurfaceCreate((CFDictionaryRef)options); +} - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture); +- (void)backTextureWithIOSurface:(int)index size:(CGSize)size { + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _backingTexture[index]); CGLTexImageIOSurface2D(CGLGetCurrentContext(), GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, int(size.width), - int(size.height), GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, - _ioSurface[ioSurfaceNum], 0 /* plane */); + int(size.height), GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, _ioSurface[index], + 0 /* plane */); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, texture, - 0); + glBindFramebuffer(GL_FRAMEBUFFER, _frameBufferId[index]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, + _backingTexture[index], 0); NSAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, @"Framebuffer status check failed"); @@ -138,18 +135,14 @@ - (void)swapBuffers { _backingTexture[kFlutterSurfaceManagerFrontBuffer]); } -- (uint32_t)glFrameBufferId { +- (uint32_t)glFrameBufferBackId { return _frameBufferId[kFlutterSurfaceManagerBackBuffer]; } -- (uint32_t)getFramebuffer { +- (uint32_t)glFrameBufferFrontId { return _frameBufferId[kFlutterSurfaceManagerFrontBuffer]; } -- (uint32_t)getTexture { - return _backingTexture[kFlutterSurfaceManagerFrontBuffer]; -} - - (void)dealloc { [_contentLayer removeFromSuperlayer]; glDeleteFramebuffers(kFlutterSurfaceManagerBufferCount, _frameBufferId); diff --git a/shell/platform/darwin/macos/framework/Source/FlutterView.mm b/shell/platform/darwin/macos/framework/Source/FlutterView.mm index 9a5f9270cbfca..a5bfc58b86b7f 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterView.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterView.mm @@ -65,7 +65,7 @@ - (int)frameBufferIDForSize:(CGSize)size { if ([_resizeSynchronizer shouldEnsureSurfaceForSize:size]) { [_surfaceManager ensureSurfaceSize:size]; } - return [_surfaceManager glFrameBufferId]; + return [_surfaceManager glFrameBufferBackId]; } - (void)present { From 74a950a675579dff970977fac56f426349b4daf2 Mon Sep 17 00:00:00 2001 From: richardjcai Date: Thu, 19 Nov 2020 16:12:27 -0500 Subject: [PATCH 5/5] Add licenses to FlutterViewControllerTestUtils files --- .../macos/framework/Source/FlutterViewControllerTestUtils.h | 4 ++++ .../macos/framework/Source/FlutterViewControllerTestUtils.mm | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.h b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.h index 92021ee44fe82..cc3c7f2bcff17 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.h +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.h @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #import #import diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.mm index 04f320ba97030..972e3515283ed 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.mm @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.h" namespace flutter::testing {