diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index c6e5047eaa2bbb516c47f8c311a19b8e6ae9f1ef..aea08acb9b27b819f07680513e73608171310caa 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1016,6 +1016,8 @@ FILE: ../../../flutter/shell/platform/darwin/ios/ios_render_target_gl.h FILE: ../../../flutter/shell/platform/darwin/ios/ios_render_target_gl.mm FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface.h FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface.mm +FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_factory.h +FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_factory.mm FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_gl.h FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_gl.mm FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_metal.h diff --git a/shell/platform/darwin/ios/BUILD.gn b/shell/platform/darwin/ios/BUILD.gn index c0caf9f94d58835cf8168ad9e8a82a72d0b80ed4..99acf3960c825fd0fe2c8bb24d3fadfaae8e0024 100644 --- a/shell/platform/darwin/ios/BUILD.gn +++ b/shell/platform/darwin/ios/BUILD.gn @@ -99,6 +99,8 @@ source_set("flutter_framework_source") { "ios_render_target_gl.mm", "ios_surface.h", "ios_surface.mm", + "ios_surface_factory.h", + "ios_surface_factory.mm", "ios_surface_gl.h", "ios_surface_gl.mm", "ios_surface_software.h", @@ -219,6 +221,7 @@ shared_library("ios_test_flutter") { deps = [ ":flutter_framework_source", ":ios_test_flutter_mrc", + "//flutter/common:common", "//flutter/shell/platform/darwin/common:framework_shared", "//flutter/third_party/tonic", "//flutter/third_party/txt", diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm index b87fde573c3efc2f7fcf27d4a7a1c60a3b27beb5..d22a9684f3b2a3b540adb5efb21f726e6e41edce 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm @@ -27,7 +27,7 @@ extern const intptr_t kPlatformStrongDillSize; static const char* kApplicationKernelSnapshotFileName = "kernel_blob.bin"; -static flutter::Settings DefaultSettingsForProcess(NSBundle* bundle = nil) { +flutter::Settings FLTDefaultSettingsForBundle(NSBundle* bundle) { auto command_line = flutter::CommandLineFromNSProcessInfo(); // Precedence: @@ -181,7 +181,17 @@ static flutter::Settings DefaultSettingsForProcess(NSBundle* bundle = nil) { self = [super init]; if (self) { - _settings = DefaultSettingsForProcess(bundle); + _settings = FLTDefaultSettingsForBundle(bundle); + } + + return self; +} + +- (instancetype)initWithSettings:(const flutter::Settings&)settings { + self = [self initWithPrecompiledDartBundle:nil]; + + if (self) { + _settings = settings; } return self; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h index b5570a321458d151373ca2eb6e6a2489444c7da1..1efdf75880281aef9e610c05c2fc0f20afa77411 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h @@ -12,8 +12,14 @@ NS_ASSUME_NONNULL_BEGIN +flutter::Settings FLTDefaultSettingsForBundle(NSBundle* bundle = nil); + @interface FlutterDartProject () +/** + * This is currently used for *only for tests* to override settings. + */ +- (instancetype)initWithSettings:(const flutter::Settings&)settings; - (const flutter::Settings&)settings; - (const flutter::PlatformData)defaultPlatformData; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm index 8a0de614f10ec9d808122f2ded1e204513e5348a..acac834082fffd57d2160e8377baf259004fbd15 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm @@ -28,7 +28,9 @@ #import "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h" #import "flutter/shell/platform/darwin/ios/framework/Source/profiler_metrics_ios.h" #import "flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h" +#import "flutter/shell/platform/darwin/ios/ios_context.h" #import "flutter/shell/platform/darwin/ios/ios_surface.h" +#import "flutter/shell/platform/darwin/ios/ios_surface_factory.h" #import "flutter/shell/platform/darwin/ios/platform_view_ios.h" #import "flutter/shell/platform/darwin/ios/rendering_api_selection.h" #include "flutter/shell/profiling/sampling_profiler.h" @@ -64,6 +66,8 @@ static constexpr int kNumProfilerSamplesPerSec = 5; fml::scoped_nsobject _publisher; std::shared_ptr _platformViewsController; + flutter::IOSRenderingAPI _renderingApi; + std::shared_ptr _surfaceFactory; std::unique_ptr _profiler_metrics; std::unique_ptr _profiler; @@ -128,7 +132,7 @@ static constexpr int kNumProfilerSamplesPerSec = 5; _pluginPublications = [NSMutableDictionary new]; _registrars = [[NSMutableDictionary alloc] init]; - _platformViewsController.reset(new flutter::FlutterPlatformViewsController()); + [self recreatePlatformViewController]; _binaryMessenger = [[FlutterBinaryMessengerRelay alloc] initWithParent:self]; _connections.reset(new flutter::ConnectionCollection()); @@ -162,6 +166,17 @@ static constexpr int kNumProfilerSamplesPerSec = 5; return self; } +- (void)recreatePlatformViewController { + _renderingApi = flutter::GetRenderingAPIForProcess(FlutterView.forceSoftwareRendering); + _surfaceFactory = flutter::IOSSurfaceFactory::Create(_renderingApi); + _platformViewsController.reset(new flutter::FlutterPlatformViewsController(_surfaceFactory)); + _surfaceFactory->SetPlatformViewsController(_platformViewsController); +} + +- (flutter::IOSRenderingAPI)platformViewsRenderingAPI { + return _renderingApi; +} + - (void)dealloc { /// Notify plugins of dealloc. This should happen first in dealloc since the /// plugins may be talking to things like the binaryMessenger. @@ -520,13 +535,12 @@ static constexpr int kNumProfilerSamplesPerSec = 5; threadHostType}; // Lambda captures by pointers to ObjC objects are fine here because the - // create call is - // synchronous. + // create call is synchronous. flutter::Shell::CreateCallback on_create_platform_view = - [](flutter::Shell& shell) { + [self](flutter::Shell& shell) { + [self recreatePlatformViewController]; return std::make_unique( - shell, flutter::GetRenderingAPIForProcess(FlutterView.forceSoftwareRendering), - shell.GetTaskRunners()); + shell, self->_renderingApi, self->_surfaceFactory, shell.GetTaskRunners()); }; flutter::Shell::CreateCallback on_create_rasterizer = @@ -554,9 +568,6 @@ static constexpr int kNumProfilerSamplesPerSec = 5; [self setupChannels]; [self onLocaleUpdated:nil]; [self initializeDisplays]; - if (!_platformViewsController) { - _platformViewsController.reset(new flutter::FlutterPlatformViewsController()); - } _publisher.reset([[FlutterObservatoryPublisher alloc] initWithEnableObservatoryPublication:settings.enable_observatory_publication]); [self maybeSetupPlatformViewChannels]; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEnginePlatformViewTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterEnginePlatformViewTest.mm index a202eba4d8d8d01d3803575e95db2358ace5deb7..3e002e2aa78ee06ab1ef8f733e1defb9b6628da4 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEnginePlatformViewTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEnginePlatformViewTest.mm @@ -67,6 +67,7 @@ class MockDelegate : public PlatformView::Delegate { auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware), /*task_runners=*/runners); id project = OCMClassMock([FlutterDartProject class]); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngineTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngineTest.mm index cfbb8cbdb87b3c060fc3080ec323cc2f030bf030..9e56ca45a753da4e05f7009ff3bb8618c75290c3 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngineTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngineTest.mm @@ -5,8 +5,10 @@ #import #import +#import "flutter/common/settings.h" #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterBinaryMessengerRelay.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Test.h" FLUTTER_ASSERT_ARC @@ -113,4 +115,23 @@ FLUTTER_ASSERT_ARC [self waitForExpectationsWithTimeout:1 handler:nil]; } +- (void)testPlatformViewsControllerRenderingMetalBackend { + FlutterEngine* engine = [[FlutterEngine alloc] init]; + [engine run]; + flutter::IOSRenderingAPI renderingApi = [engine platformViewsRenderingAPI]; + + XCTAssertEqual(renderingApi, flutter::IOSRenderingAPI::kMetal); +} + +- (void)testPlatformViewsControllerRenderingSoftware { + auto settings = FLTDefaultSettingsForBundle(); + settings.enable_software_rendering = true; + FlutterDartProject* project = [[FlutterDartProject alloc] initWithSettings:settings]; + FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"foobar" project:project]; + [engine run]; + flutter::IOSRenderingAPI renderingApi = [engine platformViewsRenderingAPI]; + + XCTAssertEqual(renderingApi, flutter::IOSRenderingAPI::kSoftware); +} + @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine_Test.h b/shell/platform/darwin/ios/framework/Source/FlutterEngine_Test.h index 748cc8c642d8b1fd7e4f568a578e02526b7c326c..a458ea167b1f88cfbff02db204fe62cf51237ef3 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngine_Test.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine_Test.h @@ -3,6 +3,7 @@ // found in the LICENSE file. #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h" +#include "shell/platform/darwin/ios/rendering_api_selection.h" @class FlutterBinaryMessengerRelay; @@ -10,4 +11,5 @@ @interface FlutterEngine (Test) - (void)setBinaryMessenger:(FlutterBinaryMessengerRelay*)binaryMessenger; - (void)waitForFirstFrame:(NSTimeInterval)timeout callback:(void (^)(BOOL didTimeout))callback; +- (flutter::IOSRenderingAPI)platformViewsRenderingAPI; @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h b/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h index cb56163c6c5c2ae4e4de1c2a372c5e8caa43f91e..b77ac7181853f1daed1852623e4ecfe7deecb43a 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h @@ -35,8 +35,6 @@ - (instancetype)init NS_DESIGNATED_INITIALIZER; - (instancetype)initWithContentsScale:(CGFloat)contentsScale; -- (std::unique_ptr)createSurface: - (std::shared_ptr)ios_context; @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm b/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm index f6a0cd823975675e409decc7d644f6a70ace3c2f..345d3a36798cbe3db13ecf9fb0148d59a6204598 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm @@ -62,14 +62,6 @@ return [FlutterView layerClass]; } -- (std::unique_ptr)createSurface: - (std::shared_ptr)ios_context { - return flutter::IOSSurface::Create(std::move(ios_context), // context - fml::scoped_nsobject{[self.layer retain]}, // layer - nullptr // platform views controller - ); -} - // TODO(amirh): implement drawLayer to support snapshotting. @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 2d14282d096ad55dee6fddff10e783227517e07c..ef1860037eeb13e88419de824540811180a7d3eb 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -16,6 +16,7 @@ #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h" #import "flutter/shell/platform/darwin/ios/ios_surface.h" +#import "flutter/shell/platform/darwin/ios/ios_surface_factory.h" #import "flutter/shell/platform/darwin/ios/ios_surface_gl.h" namespace flutter { @@ -32,8 +33,8 @@ std::shared_ptr FlutterPlatformViewLayerPool::GetLayer overlay_view.reset([[FlutterOverlayView alloc] init]); overlay_view_wrapper.reset([[FlutterOverlayView alloc] init]); - std::unique_ptr ios_surface = - [overlay_view.get() createSurface:std::move(ios_context)]; + auto ca_layer = fml::scoped_nsobject{[[overlay_view.get() layer] retain]}; + std::unique_ptr ios_surface = ios_surface_factory_->CreateSurface(ca_layer); std::unique_ptr surface = ios_surface->CreateGPUSurface(); layer = std::make_shared( @@ -44,8 +45,8 @@ std::shared_ptr FlutterPlatformViewLayerPool::GetLayer overlay_view.reset([[FlutterOverlayView alloc] initWithContentsScale:screenScale]); overlay_view_wrapper.reset([[FlutterOverlayView alloc] initWithContentsScale:screenScale]); - std::unique_ptr ios_surface = - [overlay_view.get() createSurface:std::move(ios_context)]; + auto ca_layer = fml::scoped_nsobject{[[overlay_view.get() layer] retain]}; + std::unique_ptr ios_surface = ios_surface_factory_->CreateSurface(ca_layer); std::unique_ptr surface = ios_surface->CreateGPUSurface(gr_context); layer = std::make_shared( @@ -436,6 +437,12 @@ void FlutterPlatformViewsController::Reset() { for (UIView* sub_view in [flutter_view subviews]) { [sub_view removeFromSuperview]; } + // See: https://github.com/flutter/flutter/issues/69305 + for (auto it = touch_interceptors_.begin(); it != touch_interceptors_.end(); it++) { + FlutterTouchInterceptingView* view = it->second.get(); + [view removeFromSuperview]; + } + touch_interceptors_.clear(); views_.clear(); composition_order_.clear(); active_composition_order_.clear(); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm index 283a86cf2ae463b01cab58ed3c9ebb1fd28a057c..b71b603bc379e33db1b281bdcd0eace1196df713 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm @@ -121,12 +121,16 @@ fml::RefPtr CreateNewThread(std::string name) { /*raster=*/thread_task_runner, /*ui=*/thread_task_runner, /*io=*/thread_task_runner); + auto surface_factory = flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + /*ios_surface_factory=*/surface_factory, /*task_runners=*/runners); - auto flutterPlatformViewsController = std::make_unique(); + auto flutterPlatformViewsController = + std::make_shared(surface_factory); + surface_factory->SetPlatformViewsController(flutterPlatformViewsController); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -175,12 +179,16 @@ fml::RefPtr CreateNewThread(std::string name) { /*raster=*/thread_task_runner, /*ui=*/thread_task_runner, /*io=*/thread_task_runner); + auto surface_factory = flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + /*ios_surface_factory=*/surface_factory, /*task_runners=*/runners); - auto flutterPlatformViewsController = std::make_unique(); + auto flutterPlatformViewsController = + std::make_shared(surface_factory); + surface_factory->SetPlatformViewsController(flutterPlatformViewsController); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -230,12 +238,16 @@ fml::RefPtr CreateNewThread(std::string name) { /*raster=*/thread_task_runner, /*ui=*/thread_task_runner, /*io=*/thread_task_runner); + auto surface_factory = flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + /*ios_surface_factory=*/surface_factory, /*task_runners=*/runners); - auto flutterPlatformViewsController = std::make_unique(); + auto flutterPlatformViewsController = + std::make_shared(surface_factory); + surface_factory->SetPlatformViewsController(flutterPlatformViewsController); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -301,12 +313,16 @@ fml::RefPtr CreateNewThread(std::string name) { /*raster=*/thread_task_runner, /*ui=*/thread_task_runner, /*io=*/thread_task_runner); + auto surface_factory = flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + /*ios_surface_factory=*/surface_factory, /*task_runners=*/runners); - auto flutterPlatformViewsController = std::make_unique(); + auto flutterPlatformViewsController = + std::make_shared(surface_factory); + surface_factory->SetPlatformViewsController(flutterPlatformViewsController); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -373,12 +389,16 @@ fml::RefPtr CreateNewThread(std::string name) { /*raster=*/thread_task_runner, /*ui=*/thread_task_runner, /*io=*/thread_task_runner); + auto surface_factory = flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + /*ios_surface_factory=*/surface_factory, /*task_runners=*/runners); - auto flutterPlatformViewsController = std::make_unique(); + auto flutterPlatformViewsController = + std::make_shared(surface_factory); + surface_factory->SetPlatformViewsController(flutterPlatformViewsController); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -445,12 +465,16 @@ fml::RefPtr CreateNewThread(std::string name) { /*raster=*/thread_task_runner, /*ui=*/thread_task_runner, /*io=*/thread_task_runner); + auto surface_factory = flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + /*ios_surface_factory=*/surface_factory, /*task_runners=*/runners); - auto flutterPlatformViewsController = std::make_unique(); + auto flutterPlatformViewsController = + std::make_shared(surface_factory); + surface_factory->SetPlatformViewsController(flutterPlatformViewsController); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -518,12 +542,16 @@ fml::RefPtr CreateNewThread(std::string name) { /*raster=*/thread_task_runner, /*ui=*/thread_task_runner, /*io=*/thread_task_runner); + auto surface_factory = flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + /*ios_surface_factory=*/surface_factory, /*task_runners=*/runners); - auto flutterPlatformViewsController = std::make_unique(); + auto flutterPlatformViewsController = + std::make_shared(surface_factory); + surface_factory->SetPlatformViewsController(flutterPlatformViewsController); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 4fcaaf387421222f62e54a6c501a1a0390498c19..d9638d75b6b15d10cdf9b637042d542f368b4448 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -61,6 +61,7 @@ void ResetAnchor(CALayer* layer); class IOSContextGL; class IOSSurface; +class IOSSurfaceFactory; struct FlutterPlatformViewLayer { FlutterPlatformViewLayer(fml::scoped_nsobject overlay_view, @@ -87,7 +88,9 @@ struct FlutterPlatformViewLayer { // This class isn't thread safe. class FlutterPlatformViewLayerPool { public: - FlutterPlatformViewLayerPool() = default; + FlutterPlatformViewLayerPool(std::shared_ptr ios_surface_factory) + : ios_surface_factory_(ios_surface_factory) {} + ~FlutterPlatformViewLayerPool() = default; // Gets a layer from the pool if available, or allocates a new one. @@ -118,12 +121,14 @@ class FlutterPlatformViewLayerPool { size_t available_layer_index_ = 0; std::vector> layers_; + const std::shared_ptr ios_surface_factory_; + FML_DISALLOW_COPY_AND_ASSIGN(FlutterPlatformViewLayerPool); }; class FlutterPlatformViewsController { public: - FlutterPlatformViewsController(); + FlutterPlatformViewsController(std::shared_ptr surface_factory); ~FlutterPlatformViewsController(); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm index a6d3d03653b1786b0dcb1b2f8b61f6d696691abc..a46684ccb10645cd135d8fba444382d854a0515c 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm @@ -23,8 +23,9 @@ FlutterPlatformViewLayer::FlutterPlatformViewLayer( FlutterPlatformViewLayer::~FlutterPlatformViewLayer() = default; -FlutterPlatformViewsController::FlutterPlatformViewsController() - : layer_pool_(std::make_unique()), +FlutterPlatformViewsController::FlutterPlatformViewsController( + std::shared_ptr surface_factory) + : layer_pool_(std::make_unique(surface_factory)), weak_factory_(std::make_unique>(this)){}; FlutterPlatformViewsController::~FlutterPlatformViewsController() = default; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterView.h b/shell/platform/darwin/ios/framework/Source/FlutterView.h index b874bbc8636ffee3236a256a46299831fcfb7b98..0cdd56d2cfbdcb6a43d0ba81a7b4dc9ae36ff50d 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterView.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterView.h @@ -32,7 +32,6 @@ - (instancetype)initWithDelegate:(id)delegate opaque:(BOOL)opaque NS_DESIGNATED_INITIALIZER; -- (std::unique_ptr)createSurface:(std::shared_ptr)context; // Set by FlutterEngine or FlutterViewController to override software rendering. @property(class, nonatomic) BOOL forceSoftwareRendering; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterView.mm b/shell/platform/darwin/ios/framework/Source/FlutterView.mm index 3f6b19decdac37ab89bc12e7deabe3ae85b30ec1..73a9b8b529088a5bd73b2beb7ccb7a6ba35226d5 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterView.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterView.mm @@ -83,15 +83,6 @@ static BOOL _forceSoftwareRendering; flutter::GetRenderingAPIForProcess(FlutterView.forceSoftwareRendering)); } -- (std::unique_ptr)createSurface: - (std::shared_ptr)ios_context { - return flutter::IOSSurface::Create( - std::move(ios_context), // context - fml::scoped_nsobject{[self.layer retain]}, // layer - [_delegate platformViewsController] // platform views controller - ); -} - - (void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context { TRACE_EVENT0("flutter", "SnapshotFlutterView"); diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm b/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm index fea18becd87b6510bbf23289a56d7c1dc0514029..7596578bd5e645154a154d9585a6a1c5c263b77e 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm +++ b/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm @@ -137,6 +137,7 @@ fml::RefPtr CreateNewThread(std::string name) { auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware), /*task_runners=*/runners); auto bridge = std::make_unique(/*view=*/nil, @@ -156,6 +157,7 @@ fml::RefPtr CreateNewThread(std::string name) { auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware), /*task_runners=*/runners); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); @@ -182,6 +184,7 @@ fml::RefPtr CreateNewThread(std::string name) { auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware), /*task_runners=*/runners); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); @@ -224,9 +227,12 @@ fml::RefPtr CreateNewThread(std::string name) { /*raster=*/thread_task_runner, /*ui=*/thread_task_runner, /*io=*/thread_task_runner); + + auto surfaceFactory = flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware); auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + /*ios_surface_factory=*/surfaceFactory, /*task_runners=*/runners); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); @@ -234,8 +240,9 @@ fml::RefPtr CreateNewThread(std::string name) { std::string label = "some label"; auto flutterPlatformViewsController = - std::make_shared(); + std::make_shared(surfaceFactory); flutterPlatformViewsController->SetFlutterView(mockFlutterView); + surfaceFactory->SetPlatformViewsController(flutterPlatformViewsController); MockFlutterPlatformFactory* factory = [[MockFlutterPlatformFactory new] autorelease]; flutterPlatformViewsController->RegisterViewFactory( @@ -279,6 +286,7 @@ fml::RefPtr CreateNewThread(std::string name) { auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware), /*task_runners=*/runners); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); @@ -344,6 +352,7 @@ fml::RefPtr CreateNewThread(std::string name) { auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware), /*task_runners=*/runners); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); @@ -427,6 +436,7 @@ fml::RefPtr CreateNewThread(std::string name) { auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware), /*task_runners=*/runners); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); @@ -516,6 +526,7 @@ fml::RefPtr CreateNewThread(std::string name) { auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware), /*task_runners=*/runners); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); @@ -583,6 +594,7 @@ fml::RefPtr CreateNewThread(std::string name) { auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware), /*task_runners=*/runners); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); id mockFlutterView = OCMClassMock([FlutterView class]); @@ -649,6 +661,7 @@ fml::RefPtr CreateNewThread(std::string name) { auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware), /*task_runners=*/runners); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); id mockFlutterView = OCMClassMock([FlutterView class]); @@ -721,6 +734,7 @@ fml::RefPtr CreateNewThread(std::string name) { auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware), /*task_runners=*/runners); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); id mockFlutterView = OCMClassMock([FlutterView class]); @@ -795,6 +809,7 @@ fml::RefPtr CreateNewThread(std::string name) { auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware), /*task_runners=*/runners); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); id mockFlutterView = OCMClassMock([FlutterView class]); @@ -865,6 +880,7 @@ fml::RefPtr CreateNewThread(std::string name) { auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware), /*task_runners=*/runners); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); @@ -932,6 +948,7 @@ fml::RefPtr CreateNewThread(std::string name) { auto platform_view = std::make_unique( /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + flutter::IOSSurfaceFactory::Create(flutter::IOSRenderingAPI::kSoftware), /*task_runners=*/runners); fml::AutoResetWaitableEvent latch; thread_task_runner->PostTask([&] { diff --git a/shell/platform/darwin/ios/ios_surface_factory.h b/shell/platform/darwin/ios/ios_surface_factory.h new file mode 100644 index 0000000000000000000000000000000000000000..8184918114c78c9b07f1e813762eec780dc546ef --- /dev/null +++ b/shell/platform/darwin/ios/ios_surface_factory.h @@ -0,0 +1,40 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS__SURFACE_FACTORY_H_ +#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS__SURFACE_FACTORY_H_ + +#include + +#import "flutter/shell/platform/darwin/ios/ios_surface.h" +#import "flutter/shell/platform/darwin/ios/rendering_api_selection.h" + +namespace flutter { + +class IOSSurfaceFactory { + public: + static std::shared_ptr Create( + IOSRenderingAPI rendering_api); + + explicit IOSSurfaceFactory(std::shared_ptr ios_context); + + ~IOSSurfaceFactory(); + + void SetPlatformViewsController( + const std::shared_ptr& + platform_views_controller); + + std::unique_ptr CreateSurface( + fml::scoped_nsobject ca_layer); + + private: + std::shared_ptr platform_views_controller_; + std::shared_ptr ios_context_; + + FML_DISALLOW_COPY_AND_ASSIGN(IOSSurfaceFactory); +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS__SURFACE_FACTORY_H_ diff --git a/shell/platform/darwin/ios/ios_surface_factory.mm b/shell/platform/darwin/ios/ios_surface_factory.mm new file mode 100644 index 0000000000000000000000000000000000000000..2c228bc074e921dff6e84ab744cbe9957a865a17 --- /dev/null +++ b/shell/platform/darwin/ios/ios_surface_factory.mm @@ -0,0 +1,30 @@ +// 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/ios/ios_surface_factory.h" +#import "flutter/shell/platform/darwin/ios/ios_context.h" + +namespace flutter { + +IOSSurfaceFactory::IOSSurfaceFactory(std::shared_ptr ios_context) + : ios_context_(ios_context) {} + +std::shared_ptr IOSSurfaceFactory::Create(IOSRenderingAPI rendering_api) { + std::shared_ptr ios_context = IOSContext::Create(rendering_api); + return std::make_shared(ios_context); +} + +IOSSurfaceFactory::~IOSSurfaceFactory() = default; + +void IOSSurfaceFactory::SetPlatformViewsController( + const std::shared_ptr& platform_views_controller) { + platform_views_controller_ = platform_views_controller; +} + +std::unique_ptr IOSSurfaceFactory::CreateSurface( + fml::scoped_nsobject ca_layer) { + return flutter::IOSSurface::Create(ios_context_, ca_layer, platform_views_controller_); +} + +} // namespace flutter diff --git a/shell/platform/darwin/ios/platform_view_ios.h b/shell/platform/darwin/ios/platform_view_ios.h index 8e63bbda2f132de8db5fc0bef96159189da1ec01..661d5e57f5b854317d0c46bdbaacfd178bd8776d 100644 --- a/shell/platform/darwin/ios/platform_view_ios.h +++ b/shell/platform/darwin/ios/platform_view_ios.h @@ -19,6 +19,7 @@ #import "flutter/shell/platform/darwin/ios/framework/Source/platform_message_router.h" #import "flutter/shell/platform/darwin/ios/ios_context.h" #import "flutter/shell/platform/darwin/ios/ios_surface.h" +#import "flutter/shell/platform/darwin/ios/ios_surface_factory.h" #import "flutter/shell/platform/darwin/ios/rendering_api_selection.h" @class FlutterViewController; @@ -41,6 +42,7 @@ class PlatformViewIOS final : public PlatformView { public: explicit PlatformViewIOS(PlatformView::Delegate& delegate, IOSRenderingAPI rendering_api, + std::shared_ptr surface_factory, flutter::TaskRunners task_runners); ~PlatformViewIOS() override; @@ -124,6 +126,7 @@ class PlatformViewIOS final : public PlatformView { std::mutex ios_surface_mutex_; std::unique_ptr ios_surface_; std::shared_ptr ios_context_; + std::shared_ptr ios_surface_factory_; PlatformMessageRouter platform_message_router_; AccessibilityBridgePtr accessibility_bridge_; fml::scoped_nsprotocol text_input_plugin_; diff --git a/shell/platform/darwin/ios/platform_view_ios.mm b/shell/platform/darwin/ios/platform_view_ios.mm index faf764be7cb0cf2f7538c3484c3bd6fdb2e5069e..43543c1e2fcdeb37b47c3544d7f521c376aa3fd9 100644 --- a/shell/platform/darwin/ios/platform_view_ios.mm +++ b/shell/platform/darwin/ios/platform_view_ios.mm @@ -3,6 +3,7 @@ // found in the LICENSE file. #import "flutter/shell/platform/darwin/ios/platform_view_ios.h" +#include #include @@ -46,9 +47,11 @@ void PlatformViewIOS::AccessibilityBridgePtr::reset(AccessibilityBridge* bridge) PlatformViewIOS::PlatformViewIOS(PlatformView::Delegate& delegate, IOSRenderingAPI rendering_api, + std::shared_ptr surface_factory, flutter::TaskRunners task_runners) : PlatformView(delegate, std::move(task_runners)), ios_context_(IOSContext::Create(rendering_api)), + ios_surface_factory_(surface_factory), accessibility_bridge_([this](bool enabled) { PlatformView::SetSemanticsEnabled(enabled); }) {} PlatformViewIOS::~PlatformViewIOS() = default; @@ -102,8 +105,9 @@ void PlatformViewIOS::attachView() { FML_DCHECK(owner_controller_.get().isViewLoaded) << "FlutterViewController's view should be loaded " "before attaching to PlatformViewIOS."; - ios_surface_ = - [static_cast(owner_controller_.get().view) createSurface:ios_context_]; + auto flutter_view = static_cast(owner_controller_.get().view); + auto ca_layer = fml::scoped_nsobject{[[flutter_view layer] retain]}; + ios_surface_ = ios_surface_factory_->CreateSurface(ca_layer); FML_DCHECK(ios_surface_ != nullptr); if (accessibility_bridge_) { diff --git a/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj b/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj index dde07daccd170dbc18f08b942a2a63b757e154fd..ea69e52363610219896342877bdb1324881b8f46 100644 --- a/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj +++ b/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj @@ -332,6 +332,7 @@ /* Begin XCBuildConfiguration section */ 0D6AB6D022BB05E200EEE540 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 0D6AB73E22BD8F0200EEE540 /* FlutterEngineConfig.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -391,6 +392,7 @@ }; 0D6AB6D122BB05E200EEE540 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 0D6AB73E22BD8F0200EEE540 /* FlutterEngineConfig.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -484,7 +486,6 @@ }; 0D6AB6D622BB05E200EEE540 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 0D6AB73E22BD8F0200EEE540 /* FlutterEngineConfig.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; @@ -528,7 +529,6 @@ }; 0D6AB6D722BB05E200EEE540 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 0D6AB73E22BD8F0200EEE540 /* FlutterEngineConfig.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; diff --git a/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/xcshareddata/xcschemes/IosUnitTests.xcscheme b/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/xcshareddata/xcschemes/IosUnitTests.xcscheme index 503fa272ca433204e0b4c2e20946955684527702..0394976e2de6d76612aac2b46761c313f2c6f4ea 100644 --- a/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/xcshareddata/xcschemes/IosUnitTests.xcscheme +++ b/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/xcshareddata/xcschemes/IosUnitTests.xcscheme @@ -28,6 +28,13 @@ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES" systemAttachmentLifetime = "keepNever"> + + + + diff --git a/testing/ios/IosUnitTests/README.md b/testing/ios/IosUnitTests/README.md index 096f66875f5ebcd3c9cb6ad41a4f2b445d38e795..4e22fb8d29258555b59a13e1f009680f2ef81684 100644 --- a/testing/ios/IosUnitTests/README.md +++ b/testing/ios/IosUnitTests/README.md @@ -9,7 +9,7 @@ also run in LUCI builds. testing/run_tests.py [--type=objc] ``` -After the `ios_flutter_test` target is built you can also run the tests inside +After the `ios_test_flutter` target is built you can also run the tests inside of Xcode with `testing/ios/IosUnitTests/IosUnitTests.xcodeproj`. If you modify the test or under-test files, you'll have to run `run_tests.py` again. @@ -17,5 +17,5 @@ modify the test or under-test files, you'll have to run `run_tests.py` again. When you add a new unit test file, also add a reference to that file in shell/platform/darwin/ios/BUILD.gn, under the `sources` list of the -`ios_flutter_test` target. Once it's there, it will execute with the other +`ios_test_flutter` target. Once it's there, it will execute with the other tests.