diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h index 868d2176a309b..82d5fcc1d3a2e 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h @@ -36,6 +36,8 @@ - (fml::WeakPtr)platformView; +- (flutter::PlatformViewIOS*)iosPlatformView; + - (flutter::Rasterizer::Screenshot)screenshot:(flutter::Rasterizer::ScreenshotType)type base64Encode:(bool)base64Encode; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h b/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h index fac783f87f33f..903b9c02ca9a6 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h @@ -24,8 +24,9 @@ - (instancetype)init NS_DESIGNATED_INITIALIZER; - (instancetype)initWithContentsScale:(CGFloat)contentsScale; -- (std::unique_ptr)createSurface: - (std::shared_ptr)gl_context; +- (std::unique_ptr) + createSurfaceWithOnscreenGLContext:(fml::WeakPtr)onscreenGLContext + resourceGLContext:(fml::WeakPtr)resourceGLContext; @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm b/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm index 414029023061d..9cdf862c8c078 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm @@ -78,15 +78,17 @@ + (Class)layerClass { #endif // TARGET_IPHONE_SIMULATOR } -- (std::unique_ptr)createSurface: - (std::shared_ptr)gl_context { +- (std::unique_ptr) + createSurfaceWithOnscreenGLContext:(fml::WeakPtr)onscreenGLContext + resourceGLContext:(fml::WeakPtr)resourceGLContext { if ([self.layer isKindOfClass:[CAEAGLLayer class]]) { fml::scoped_nsobject eagl_layer( reinterpret_cast([self.layer retain])); if (@available(iOS 9.0, *)) { eagl_layer.get().presentsWithTransaction = YES; } - return std::make_unique(std::move(eagl_layer), gl_context); + return std::make_unique(std::move(eagl_layer), onscreenGLContext, + resourceGLContext); #if FLUTTER_SHELL_ENABLE_METAL } else if ([self.layer isKindOfClass:[CAMetalLayer class]]) { fml::scoped_nsobject metalLayer( diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 00a7c9ecda5bd..7cc3c44c04ff0 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -362,12 +362,13 @@ } bool FlutterPlatformViewsController::SubmitFrame(GrContext* gr_context, - std::shared_ptr gl_context) { + fml::WeakPtr onscreen_gl_context, + fml::WeakPtr resource_gl_context) { DisposeViews(); bool did_submit = true; for (int64_t view_id : composition_order_) { - EnsureOverlayInitialized(view_id, std::move(gl_context), gr_context); + EnsureOverlayInitialized(view_id, onscreen_gl_context, resource_gl_context, gr_context); auto frame = overlays_[view_id]->surface->AcquireFrame(frame_size_); SkCanvas* canvas = frame->SkiaCanvas(); canvas->drawPicture(picture_recorders_[view_id]->finishRecordingAsPicture()); @@ -451,7 +452,8 @@ void FlutterPlatformViewsController::EnsureOverlayInitialized( int64_t overlay_id, - std::shared_ptr gl_context, + fml::WeakPtr onscreen_gl_context, + fml::WeakPtr resource_gl_context, GrContext* gr_context) { FML_DCHECK(flutter_view_); @@ -467,7 +469,9 @@ overlay_view.get().frame = flutter_view_.get().bounds; overlay_view.get().autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); - std::unique_ptr ios_surface = [overlay_view.get() createSurface:nil]; + std::unique_ptr ios_surface = [overlay_view.get() + createSurfaceWithOnscreenGLContext:fml::WeakPtr() + resourceGLContext:fml::WeakPtr()]; std::unique_ptr surface = ios_surface->CreateGPUSurface(); overlays_[overlay_id] = std::make_unique( std::move(overlay_view), std::move(ios_surface), std::move(surface)); @@ -492,7 +496,8 @@ overlay_view.get().autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); std::unique_ptr ios_surface = - [overlay_view.get() createSurface:std::move(gl_context)]; + [overlay_view.get() createSurfaceWithOnscreenGLContext:std::move(onscreen_gl_context) + resourceGLContext:std::move(resource_gl_context)]; std::unique_ptr surface = ios_surface->CreateGPUSurface(gr_context); overlays_[overlay_id] = std::make_unique( std::move(overlay_view), std::move(ios_surface), std::move(surface)); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index f9f0eefece601..181723fd80286 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -100,7 +100,9 @@ class FlutterPlatformViewsController { // Discards all platform views instances and auxiliary resources. void Reset(); - bool SubmitFrame(GrContext* gr_context, std::shared_ptr gl_context); + bool SubmitFrame(GrContext* gr_context, + fml::WeakPtr onscreen_gl_context, + fml::WeakPtr resource_gl_context); void OnMethodCall(FlutterMethodCall* call, FlutterResult& result); @@ -162,7 +164,8 @@ class FlutterPlatformViewsController { // Dispose the views in `views_to_dispose_`. void DisposeViews(); void EnsureOverlayInitialized(int64_t overlay_id, - std::shared_ptr gl_context, + fml::WeakPtr onscreen_gl_context, + fml::WeakPtr resource_gl_context, GrContext* gr_context); // This will return true after pre-roll if any of the embedded views diff --git a/shell/platform/darwin/ios/framework/Source/FlutterView.h b/shell/platform/darwin/ios/framework/Source/FlutterView.h index 0da2d5b0bc71d..ad75d817f6800 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterView.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterView.h @@ -33,8 +33,8 @@ - (instancetype)initWithDelegate:(id)delegate opaque:(BOOL)opaque NS_DESIGNATED_INITIALIZER; -- (std::unique_ptr)createSurface: - (std::shared_ptr)context; +- (std::unique_ptr)createSurfaceWithResourceGLContext: + (fml::WeakPtr)resourceGLContext; @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterView.mm b/shell/platform/darwin/ios/framework/Source/FlutterView.mm index 4e4acdfc0438f..8891648da52f4 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterView.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterView.mm @@ -13,6 +13,7 @@ #include "flutter/shell/common/platform_view.h" #include "flutter/shell/common/rasterizer.h" #include "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h" +#include "flutter/shell/platform/darwin/ios/ios_gl_context.h" #include "flutter/shell/platform/darwin/ios/ios_surface_gl.h" #include "flutter/shell/platform/darwin/ios/ios_surface_software.h" #include "third_party/skia/include/utils/mac/SkCGUtils.h" @@ -21,9 +22,10 @@ #include "flutter/shell/platform/darwin/ios/ios_surface_metal.h" #endif // FLUTTER_SHELL_ENABLE_METAL -@implementation FlutterView - -id _delegate; +@implementation FlutterView { + id _delegate; + std::unique_ptr _onscreenGLContext; +} - (instancetype)init { @throw([NSException exceptionWithName:@"FlutterView must initWithDelegate" @@ -93,8 +95,14 @@ + (Class)layerClass { #endif // TARGET_IPHONE_SIMULATOR } -- (std::unique_ptr)createSurface: - (std::shared_ptr)context { +- (std::unique_ptr)createSurfaceWithResourceGLContext: + (fml::WeakPtr)resourceGLContext { +#if !TARGET_IPHONE_SIMULATOR + if (!_onscreenGLContext) { + _onscreenGLContext = resourceGLContext->MakeSharedContext(); + } +#endif // !TARGET_IPHONE_SIMULATOR + if ([self.layer isKindOfClass:[CAEAGLLayer class]]) { fml::scoped_nsobject eagl_layer( reinterpret_cast([self.layer retain])); @@ -105,8 +113,9 @@ + (Class)layerClass { eagl_layer.get().presentsWithTransaction = YES; } } - return std::make_unique(context, std::move(eagl_layer), - [_delegate platformViewsController]); + return std::make_unique( + _onscreenGLContext->GetWeakPtr(), std::move(resourceGLContext), std::move(eagl_layer), + [_delegate platformViewsController]); #if FLUTTER_SHELL_ENABLE_METAL } else if ([self.layer isKindOfClass:[CAMetalLayer class]]) { fml::scoped_nsobject metalLayer( diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 3cea602f86bad..05eac19d4a83b 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -1152,4 +1152,8 @@ - (NSObject*)valuePublishedByPlugin:(NSString*)pluginKey { return [_engine.get() valuePublishedByPlugin:pluginKey]; } +- (BOOL)hasOnscreenSurface { + return [_engine.get() iosPlatformView] -> HasOnscreenSurface(); +} + @end diff --git a/shell/platform/darwin/ios/ios_gl_context.h b/shell/platform/darwin/ios/ios_gl_context.h index 232645d9c8592..1f1bebcfb85a3 100644 --- a/shell/platform/darwin/ios/ios_gl_context.h +++ b/shell/platform/darwin/ios/ios_gl_context.h @@ -13,30 +13,32 @@ #include "flutter/fml/macros.h" #include "flutter/fml/platform/darwin/scoped_nsobject.h" #include "flutter/shell/common/platform_view.h" -#include "ios_gl_render_target.h" namespace flutter { class IOSGLContext { public: IOSGLContext(); + IOSGLContext(EAGLSharegroup* sharegroup); ~IOSGLContext(); - std::unique_ptr CreateRenderTarget( - fml::scoped_nsobject layer); - bool MakeCurrent(); - bool ResourceMakeCurrent(); + bool BindRenderbufferStorage(fml::scoped_nsobject layer); sk_sp ColorSpace() const { return color_space_; } + std::unique_ptr MakeSharedContext(); + + fml::WeakPtr GetWeakPtr(); + private: fml::scoped_nsobject context_; - fml::scoped_nsobject resource_context_; sk_sp color_space_; + std::unique_ptr> weak_factory_; + FML_DISALLOW_COPY_AND_ASSIGN(IOSGLContext); }; diff --git a/shell/platform/darwin/ios/ios_gl_context.mm b/shell/platform/darwin/ios/ios_gl_context.mm index 52fb85f8f19a9..8398ce0a5efd6 100644 --- a/shell/platform/darwin/ios/ios_gl_context.mm +++ b/shell/platform/darwin/ios/ios_gl_context.mm @@ -12,15 +12,16 @@ namespace flutter { -IOSGLContext::IOSGLContext() { - resource_context_.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]); - if (resource_context_ != nullptr) { - context_.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3 - sharegroup:resource_context_.get().sharegroup]); - } else { - resource_context_.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]); +IOSGLContext::IOSGLContext() : IOSGLContext(nullptr) {} + +IOSGLContext::IOSGLContext(EAGLSharegroup* sharegroup) + : weak_factory_(std::make_unique>(this)) { + context_.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3 + sharegroup:sharegroup]); + + if (!context_) { context_.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 - sharegroup:resource_context_.get().sharegroup]); + sharegroup:sharegroup]); } // TODO: @@ -44,20 +45,22 @@ } } -IOSGLContext::~IOSGLContext() = default; +fml::WeakPtr IOSGLContext::GetWeakPtr() { + return weak_factory_->GetWeakPtr(); +} -std::unique_ptr IOSGLContext::CreateRenderTarget( - fml::scoped_nsobject layer) { - return std::make_unique(std::move(layer), context_.get(), - resource_context_.get()); +bool IOSGLContext::BindRenderbufferStorage(fml::scoped_nsobject layer) { + return [context_.get() renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer.get()]; } +IOSGLContext::~IOSGLContext() = default; + bool IOSGLContext::MakeCurrent() { return [EAGLContext setCurrentContext:context_.get()]; } -bool IOSGLContext::ResourceMakeCurrent() { - return [EAGLContext setCurrentContext:resource_context_.get()]; +std::unique_ptr IOSGLContext::MakeSharedContext() { + return std::make_unique(context_.get().sharegroup); } } // namespace flutter diff --git a/shell/platform/darwin/ios/ios_gl_render_target.h b/shell/platform/darwin/ios/ios_gl_render_target.h index b2eafe16e0950..b26713e8ea707 100644 --- a/shell/platform/darwin/ios/ios_gl_render_target.h +++ b/shell/platform/darwin/ios/ios_gl_render_target.h @@ -13,14 +13,15 @@ #include "flutter/fml/macros.h" #include "flutter/fml/platform/darwin/scoped_nsobject.h" #include "flutter/shell/common/platform_view.h" +#include "flutter/shell/platform/darwin/ios/ios_gl_context.h" namespace flutter { class IOSGLRenderTarget { public: IOSGLRenderTarget(fml::scoped_nsobject layer, - EAGLContext* context, - EAGLContext* resource_context); + fml::WeakPtr onscreen_context, + fml::WeakPtr resource_context); ~IOSGLRenderTarget(); @@ -40,8 +41,8 @@ class IOSGLRenderTarget { private: fml::scoped_nsobject layer_; - fml::scoped_nsobject context_; - fml::scoped_nsobject resource_context_; + fml::WeakPtr onscreen_gl_context_; + fml::WeakPtr resource_gl_context_; GLuint framebuffer_; GLuint colorbuffer_; GLint storage_size_width_; diff --git a/shell/platform/darwin/ios/ios_gl_render_target.mm b/shell/platform/darwin/ios/ios_gl_render_target.mm index a57ba9c46b414..e0ce5e7bf8292 100644 --- a/shell/platform/darwin/ios/ios_gl_render_target.mm +++ b/shell/platform/darwin/ios/ios_gl_render_target.mm @@ -11,23 +11,22 @@ #include "third_party/skia/include/gpu/gl/GrGLInterface.h" namespace flutter { - IOSGLRenderTarget::IOSGLRenderTarget(fml::scoped_nsobject layer, - EAGLContext* context, - EAGLContext* resource_context) + fml::WeakPtr onscreen_gl_context, + fml::WeakPtr resource_gl_context) : layer_(std::move(layer)), - context_([context retain]), - resource_context_([resource_context retain]), + onscreen_gl_context_(std::move(onscreen_gl_context)), + resource_gl_context_(std::move(resource_gl_context)), framebuffer_(GL_NONE), colorbuffer_(GL_NONE), storage_size_width_(0), storage_size_height_(0), valid_(false) { FML_DCHECK(layer_ != nullptr); - FML_DCHECK(context_ != nullptr); - FML_DCHECK(resource_context_ != nullptr); + FML_DCHECK(onscreen_gl_context_); + FML_DCHECK(resource_gl_context_); - bool context_current = [EAGLContext setCurrentContext:context_]; + bool context_current = onscreen_gl_context_->MakeCurrent(); FML_DCHECK(context_current); FML_DCHECK(glGetError() == GL_NO_ERROR); @@ -63,7 +62,7 @@ IOSGLRenderTarget::~IOSGLRenderTarget() { EAGLContext* context = EAGLContext.currentContext; - [EAGLContext setCurrentContext:context_]; + onscreen_gl_context_->MakeCurrent(); FML_DCHECK(glGetError() == GL_NO_ERROR); // Deletes on GL_NONEs are ignored @@ -105,7 +104,7 @@ FML_DCHECK(glGetError() == GL_NO_ERROR); - if (![EAGLContext setCurrentContext:context_]) { + if (!onscreen_gl_context_->MakeCurrent()) { return false; } @@ -116,7 +115,7 @@ glBindRenderbuffer(GL_RENDERBUFFER, colorbuffer_); FML_DCHECK(glGetError() == GL_NO_ERROR); - if (![context_.get() renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer_.get()]) { + if (!onscreen_gl_context_->BindRenderbufferStorage(layer_)) { return false; } @@ -133,11 +132,11 @@ } bool IOSGLRenderTarget::MakeCurrent() { - return UpdateStorageSizeIfNecessary() && [EAGLContext setCurrentContext:context_.get()]; + return UpdateStorageSizeIfNecessary() && onscreen_gl_context_->MakeCurrent(); } bool IOSGLRenderTarget::ResourceMakeCurrent() { - return [EAGLContext setCurrentContext:resource_context_.get()]; + return resource_gl_context_->MakeCurrent(); } } // namespace flutter diff --git a/shell/platform/darwin/ios/ios_surface_gl.h b/shell/platform/darwin/ios/ios_surface_gl.h index 964cc7adb692e..7dc815dbba879 100644 --- a/shell/platform/darwin/ios/ios_surface_gl.h +++ b/shell/platform/darwin/ios/ios_surface_gl.h @@ -20,11 +20,14 @@ class IOSSurfaceGL final : public IOSSurface, public GPUSurfaceGLDelegate, public ExternalViewEmbedder { public: - IOSSurfaceGL(std::shared_ptr context, + IOSSurfaceGL(fml::WeakPtr onscreen_gl_context, + fml::WeakPtr resource_gl_context, fml::scoped_nsobject layer, FlutterPlatformViewsController* platform_views_controller); - IOSSurfaceGL(fml::scoped_nsobject layer, std::shared_ptr context); + IOSSurfaceGL(fml::scoped_nsobject layer, + fml::WeakPtr onscreen_gl_context, + fml::WeakPtr resource_gl_context); ~IOSSurfaceGL() override; @@ -79,7 +82,10 @@ class IOSSurfaceGL final : public IOSSurface, bool SubmitFrame(GrContext* context) override; private: - std::shared_ptr context_; + fml::WeakPtr onscreen_gl_context_; + + fml::WeakPtr resource_gl_context_; + std::unique_ptr render_target_; FML_DISALLOW_COPY_AND_ASSIGN(IOSSurfaceGL); diff --git a/shell/platform/darwin/ios/ios_surface_gl.mm b/shell/platform/darwin/ios/ios_surface_gl.mm index 9e838e200df34..b278e8170cd89 100644 --- a/shell/platform/darwin/ios/ios_surface_gl.mm +++ b/shell/platform/darwin/ios/ios_surface_gl.mm @@ -9,17 +9,25 @@ namespace flutter { -IOSSurfaceGL::IOSSurfaceGL(std::shared_ptr context, +IOSSurfaceGL::IOSSurfaceGL(fml::WeakPtr onscreen_gl_context, + fml::WeakPtr resource_gl_context, fml::scoped_nsobject layer, FlutterPlatformViewsController* platform_views_controller) - : IOSSurface(platform_views_controller), context_(context) { - render_target_ = context_->CreateRenderTarget(std::move(layer)); + : IOSSurface(platform_views_controller), + onscreen_gl_context_(std::move(onscreen_gl_context)), + resource_gl_context_(std::move(resource_gl_context)) { + render_target_ = std::make_unique(std::move(layer), onscreen_gl_context_, + resource_gl_context_); } IOSSurfaceGL::IOSSurfaceGL(fml::scoped_nsobject layer, - std::shared_ptr context) - : IOSSurface(nullptr), context_(context) { - render_target_ = context_->CreateRenderTarget(std::move(layer)); + fml::WeakPtr onscreen_gl_context, + fml::WeakPtr resource_gl_context) + : IOSSurface(nullptr), + onscreen_gl_context_(std::move(onscreen_gl_context)), + resource_gl_context_(std::move(resource_gl_context)) { + render_target_ = std::make_unique(std::move(layer), onscreen_gl_context_, + resource_gl_context_); } IOSSurfaceGL::~IOSSurfaceGL() = default; @@ -29,7 +37,7 @@ } bool IOSSurfaceGL::ResourceContextMakeCurrent() { - return context_->ResourceMakeCurrent(); + return resource_gl_context_->MakeCurrent(); } void IOSSurfaceGL::UpdateStorageSizeIfNecessary() { @@ -60,7 +68,7 @@ if (!IsValid()) { return false; } - return render_target_->UpdateStorageSizeIfNecessary() && context_->MakeCurrent(); + return render_target_->UpdateStorageSizeIfNecessary() && onscreen_gl_context_->MakeCurrent(); } bool IOSSurfaceGL::GLContextClearCurrent() { @@ -145,7 +153,8 @@ return true; } - bool submitted = platform_views_controller->SubmitFrame(std::move(context), context_); + bool submitted = platform_views_controller->SubmitFrame(std::move(context), onscreen_gl_context_, + resource_gl_context_); [CATransaction commit]; return submitted; } diff --git a/shell/platform/darwin/ios/ios_surface_software.mm b/shell/platform/darwin/ios/ios_surface_software.mm index 4566bbf3f3624..253c8645d2308 100644 --- a/shell/platform/darwin/ios/ios_surface_software.mm +++ b/shell/platform/darwin/ios/ios_surface_software.mm @@ -184,7 +184,8 @@ if (platform_views_controller == nullptr) { return true; } - return platform_views_controller->SubmitFrame(nullptr, nullptr); + return platform_views_controller->SubmitFrame(nullptr, fml::WeakPtr(), + fml::WeakPtr()); } } // namespace flutter diff --git a/shell/platform/darwin/ios/platform_view_ios.h b/shell/platform/darwin/ios/platform_view_ios.h index 38fc2a9f30b28..f9461719ba329 100644 --- a/shell/platform/darwin/ios/platform_view_ios.h +++ b/shell/platform/darwin/ios/platform_view_ios.h @@ -44,10 +44,12 @@ class PlatformViewIOS final : public PlatformView { // |PlatformView| void SetSemanticsEnabled(bool enabled) override; + bool HasOnscreenSurface() const; + private: fml::WeakPtr owner_controller_; std::unique_ptr ios_surface_; - std::shared_ptr gl_context_; + std::unique_ptr resource_gl_context_; PlatformMessageRouter platform_message_router_; std::unique_ptr accessibility_bridge_; fml::scoped_nsprotocol text_input_plugin_; @@ -75,6 +77,8 @@ class PlatformViewIOS final : public PlatformView { // |PlatformView| void OnPreEngineRestart() const override; + void NotifyDestroyed() override; + FML_DISALLOW_COPY_AND_ASSIGN(PlatformViewIOS); }; diff --git a/shell/platform/darwin/ios/platform_view_ios.mm b/shell/platform/darwin/ios/platform_view_ios.mm index c80ae377c03a1..34407de9aac30 100644 --- a/shell/platform/darwin/ios/platform_view_ios.mm +++ b/shell/platform/darwin/ios/platform_view_ios.mm @@ -23,7 +23,7 @@ flutter::TaskRunners task_runners) : PlatformView(delegate, std::move(task_runners)) { #if !TARGET_IPHONE_SIMULATOR - gl_context_ = std::make_shared(); + resource_gl_context_ = std::make_unique(); #endif // !TARGET_IPHONE_SIMULATOR } @@ -42,16 +42,24 @@ return owner_controller_; } +void PlatformViewIOS::NotifyDestroyed() { + PlatformView::NotifyDestroyed(); + ios_surface_.reset(); +} + +bool PlatformViewIOS::HasOnscreenSurface() const { + return !!ios_surface_; +} + void PlatformViewIOS::SetOwnerViewController(fml::WeakPtr owner_controller) { if (ios_surface_ || !owner_controller) { NotifyDestroyed(); - ios_surface_.reset(); accessibility_bridge_.reset(); } owner_controller_ = owner_controller; if (owner_controller_) { - ios_surface_ = - [static_cast(owner_controller.get().view) createSurface:gl_context_]; + ios_surface_ = [static_cast(owner_controller.get().view) + createSurfaceWithResourceGLContext:resource_gl_context_->GetWeakPtr()]; FML_DCHECK(ios_surface_ != nullptr); if (accessibility_bridge_) { @@ -83,7 +91,7 @@ new AccessibilityBridge(static_cast(owner_controller_.get().view), // |PlatformView| sk_sp PlatformViewIOS::CreateResourceContext() const { - if (!gl_context_ || !gl_context_->ResourceMakeCurrent()) { + if (!resource_gl_context_ || !resource_gl_context_->MakeCurrent()) { FML_DLOG(INFO) << "Could not make resource context current on IO thread. " "Async texture uploads will be disabled. On Simulators, " "this is expected."; diff --git a/testing/scenario_app/ios/Scenarios/Scenarios.xcodeproj/project.pbxproj b/testing/scenario_app/ios/Scenarios/Scenarios.xcodeproj/project.pbxproj index c7fe99847ea68..bf19f4e482c9e 100644 --- a/testing/scenario_app/ios/Scenarios/Scenarios.xcodeproj/project.pbxproj +++ b/testing/scenario_app/ios/Scenarios/Scenarios.xcodeproj/project.pbxproj @@ -27,6 +27,7 @@ 24D47D1B230C79840069DD5E /* golden_platform_view_D211AP.png in Resources */ = {isa = PBXBuildFile; fileRef = 24D47D1A230C79840069DD5E /* golden_platform_view_D211AP.png */; }; 24D47D1D230CA2700069DD5E /* golden_platform_view_iPhone SE_simulator.png in Resources */ = {isa = PBXBuildFile; fileRef = 24D47D1C230CA2700069DD5E /* golden_platform_view_iPhone SE_simulator.png */; }; 24F1FB89230B4579005ACE7C /* TextPlatformView.m in Sources */ = {isa = PBXBuildFile; fileRef = 24F1FB87230B4579005ACE7C /* TextPlatformView.m */; }; + D678B7C82322EFDA00792FDC /* FlutterViewTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D678B7C72322EFDA00792FDC /* FlutterViewTest.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -105,6 +106,7 @@ 24D47D1E230CA4480069DD5E /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 24F1FB87230B4579005ACE7C /* TextPlatformView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TextPlatformView.m; sourceTree = ""; }; 24F1FB88230B4579005ACE7C /* TextPlatformView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextPlatformView.h; sourceTree = ""; }; + D678B7C72322EFDA00792FDC /* FlutterViewTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FlutterViewTest.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -176,6 +178,7 @@ children = ( 248FDFC322FE7CD0009CC7CD /* FlutterEngineTest.m */, 0DB781FC22EA2C0300E9B371 /* FlutterViewControllerTest.m */, + D678B7C72322EFDA00792FDC /* FlutterViewTest.m */, 248D76E522E388380012F0C1 /* Info.plist */, ); path = ScenariosTests; @@ -349,6 +352,7 @@ files = ( 0DB7820222EA493B00E9B371 /* FlutterViewControllerTest.m in Sources */, 248FDFC422FE7CD0009CC7CD /* FlutterEngineTest.m in Sources */, + D678B7C82322EFDA00792FDC /* FlutterViewTest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/testing/scenario_app/ios/Scenarios/ScenariosTests/FlutterViewTest.m b/testing/scenario_app/ios/Scenarios/ScenariosTests/FlutterViewTest.m new file mode 100644 index 0000000000000..27c1f7702868e --- /dev/null +++ b/testing/scenario_app/ios/Scenarios/ScenariosTests/FlutterViewTest.m @@ -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. + +#import +#import +#import "AppDelegate.h" + +@interface FlutterViewGLContextTest : XCTestCase +@property(nonatomic, strong) FlutterViewController* flutterViewController; +@property(nonatomic, strong) FlutterEngine* flutterEngine; +@end + +@implementation FlutterViewGLContextTest + +- (void)setUp { + [super setUp]; + self.continueAfterFailure = NO; +} + +- (void)tearDown { + if (self.flutterViewController) { + [self.flutterViewController removeFromParentViewController]; + [self.flutterViewController release]; + } + if (self.flutterEngine) { + [self.flutterEngine release]; + } + [super tearDown]; +} + +- (void)testFlutterViewDestroyed { + self.flutterEngine = [[FlutterEngine alloc] initWithName:@"testGL" project:nil]; + [self.flutterEngine runWithEntrypoint:nil]; + self.flutterViewController = [[FlutterViewController alloc] initWithEngine:self.flutterEngine + nibName:nil + bundle:nil]; + + AppDelegate* appDelegate = (AppDelegate*)UIApplication.sharedApplication.delegate; + UIViewController* rootVC = appDelegate.window.rootViewController; + [rootVC presentViewController:self.flutterViewController animated:NO completion:nil]; + + // TODO: refactor this to not rely on private test-only APIs + __weak id flutterView = [self.flutterViewController flutterView]; + XCTAssertNotNil(flutterView); + XCTAssertTrue([self.flutterViewController hasOnscreenSurface]); + + [self.flutterViewController + dismissViewControllerAnimated:NO + completion:^{ + __weak id flutterView = [self.flutterViewController flutterView]; + XCTAssertNil(flutterView); + XCTAssertFalse([self.flutterViewController hasOnscreenSurface]); + }]; +} + +@end