Skip to content

Commit

Permalink
Manage iOS contexts separately (flutter#12078)
Browse files Browse the repository at this point in the history
Manage resource and onscreen contexts using separate IOSGLContext objects. FlutterView owns the onscreen context, and PlatformViewIOS owns the resource context.
  • Loading branch information
gw280 authored Sep 11, 2019
1 parent 28d7900 commit 4ac0663
Show file tree
Hide file tree
Showing 15 changed files with 125 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@

- (instancetype)init NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithContentsScale:(CGFloat)contentsScale;
- (std::unique_ptr<flutter::IOSSurface>)createSurface:
(std::shared_ptr<flutter::IOSGLContext>)gl_context;
- (std::unique_ptr<flutter::IOSSurface>)
createSurfaceWithOnscreenGLContext:(fml::WeakPtr<flutter::IOSGLContext>)onscreenGLContext
resourceGLContext:(fml::WeakPtr<flutter::IOSGLContext>)resourceGLContext;

@end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,17 @@ + (Class)layerClass {
#endif // TARGET_IPHONE_SIMULATOR
}

- (std::unique_ptr<flutter::IOSSurface>)createSurface:
(std::shared_ptr<flutter::IOSGLContext>)gl_context {
- (std::unique_ptr<flutter::IOSSurface>)
createSurfaceWithOnscreenGLContext:(fml::WeakPtr<flutter::IOSGLContext>)onscreenGLContext
resourceGLContext:(fml::WeakPtr<flutter::IOSGLContext>)resourceGLContext {
if ([self.layer isKindOfClass:[CAEAGLLayer class]]) {
fml::scoped_nsobject<CAEAGLLayer> eagl_layer(
reinterpret_cast<CAEAGLLayer*>([self.layer retain]));
if (@available(iOS 9.0, *)) {
eagl_layer.get().presentsWithTransaction = YES;
}
return std::make_unique<flutter::IOSSurfaceGL>(std::move(eagl_layer), gl_context);
return std::make_unique<flutter::IOSSurfaceGL>(std::move(eagl_layer), onscreenGLContext,
resourceGLContext);
#if FLUTTER_SHELL_ENABLE_METAL
} else if ([self.layer isKindOfClass:[CAMetalLayer class]]) {
fml::scoped_nsobject<CAMetalLayer> metalLayer(
Expand Down
15 changes: 10 additions & 5 deletions shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
Original file line number Diff line number Diff line change
Expand Up @@ -362,12 +362,13 @@
}

bool FlutterPlatformViewsController::SubmitFrame(GrContext* gr_context,
std::shared_ptr<IOSGLContext> gl_context) {
fml::WeakPtr<IOSGLContext> onscreen_gl_context,
fml::WeakPtr<IOSGLContext> 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());
Expand Down Expand Up @@ -451,7 +452,8 @@

void FlutterPlatformViewsController::EnsureOverlayInitialized(
int64_t overlay_id,
std::shared_ptr<IOSGLContext> gl_context,
fml::WeakPtr<IOSGLContext> onscreen_gl_context,
fml::WeakPtr<IOSGLContext> resource_gl_context,
GrContext* gr_context) {
FML_DCHECK(flutter_view_);

Expand All @@ -467,7 +469,9 @@
overlay_view.get().frame = flutter_view_.get().bounds;
overlay_view.get().autoresizingMask =
(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
std::unique_ptr<IOSSurface> ios_surface = [overlay_view.get() createSurface:nil];
std::unique_ptr<IOSSurface> ios_surface = [overlay_view.get()
createSurfaceWithOnscreenGLContext:fml::WeakPtr<flutter::IOSGLContext>()
resourceGLContext:fml::WeakPtr<flutter::IOSGLContext>()];
std::unique_ptr<Surface> surface = ios_surface->CreateGPUSurface();
overlays_[overlay_id] = std::make_unique<FlutterPlatformViewLayer>(
std::move(overlay_view), std::move(ios_surface), std::move(surface));
Expand All @@ -492,7 +496,8 @@
overlay_view.get().autoresizingMask =
(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
std::unique_ptr<IOSSurface> 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> surface = ios_surface->CreateGPUSurface(gr_context);
overlays_[overlay_id] = std::make_unique<FlutterPlatformViewLayer>(
std::move(overlay_view), std::move(ios_surface), std::move(surface));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ class FlutterPlatformViewsController {
// Discards all platform views instances and auxiliary resources.
void Reset();

bool SubmitFrame(GrContext* gr_context, std::shared_ptr<IOSGLContext> gl_context);
bool SubmitFrame(GrContext* gr_context,
fml::WeakPtr<IOSGLContext> onscreen_gl_context,
fml::WeakPtr<IOSGLContext> resource_gl_context);

void OnMethodCall(FlutterMethodCall* call, FlutterResult& result);

Expand Down Expand Up @@ -162,7 +164,8 @@ class FlutterPlatformViewsController {
// Dispose the views in `views_to_dispose_`.
void DisposeViews();
void EnsureOverlayInitialized(int64_t overlay_id,
std::shared_ptr<IOSGLContext> gl_context,
fml::WeakPtr<IOSGLContext> onscreen_gl_context,
fml::WeakPtr<IOSGLContext> resource_gl_context,
GrContext* gr_context);

// This will return true after pre-roll if any of the embedded views
Expand Down
4 changes: 2 additions & 2 deletions shell/platform/darwin/ios/framework/Source/FlutterView.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@

- (instancetype)initWithDelegate:(id<FlutterViewEngineDelegate>)delegate
opaque:(BOOL)opaque NS_DESIGNATED_INITIALIZER;
- (std::unique_ptr<flutter::IOSSurface>)createSurface:
(std::shared_ptr<flutter::IOSGLContext>)context;
- (std::unique_ptr<flutter::IOSSurface>)createSurfaceWithResourceGLContext:
(fml::WeakPtr<flutter::IOSGLContext>)resourceGLContext;

@end

Expand Down
23 changes: 16 additions & 7 deletions shell/platform/darwin/ios/framework/Source/FlutterView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -21,9 +22,10 @@
#include "flutter/shell/platform/darwin/ios/ios_surface_metal.h"
#endif // FLUTTER_SHELL_ENABLE_METAL

@implementation FlutterView

id<FlutterViewEngineDelegate> _delegate;
@implementation FlutterView {
id<FlutterViewEngineDelegate> _delegate;
std::unique_ptr<flutter::IOSGLContext> _onscreenGLContext;
}

- (instancetype)init {
@throw([NSException exceptionWithName:@"FlutterView must initWithDelegate"
Expand Down Expand Up @@ -93,8 +95,14 @@ + (Class)layerClass {
#endif // TARGET_IPHONE_SIMULATOR
}

- (std::unique_ptr<flutter::IOSSurface>)createSurface:
(std::shared_ptr<flutter::IOSGLContext>)context {
- (std::unique_ptr<flutter::IOSSurface>)createSurfaceWithResourceGLContext:
(fml::WeakPtr<flutter::IOSGLContext>)resourceGLContext {
#if !TARGET_IPHONE_SIMULATOR
if (!_onscreenGLContext) {
_onscreenGLContext = resourceGLContext->MakeSharedContext();
}
#endif // !TARGET_IPHONE_SIMULATOR

if ([self.layer isKindOfClass:[CAEAGLLayer class]]) {
fml::scoped_nsobject<CAEAGLLayer> eagl_layer(
reinterpret_cast<CAEAGLLayer*>([self.layer retain]));
Expand All @@ -105,8 +113,9 @@ + (Class)layerClass {
eagl_layer.get().presentsWithTransaction = YES;
}
}
return std::make_unique<flutter::IOSSurfaceGL>(context, std::move(eagl_layer),
[_delegate platformViewsController]);
return std::make_unique<flutter::IOSSurfaceGL>(
_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<CAMetalLayer> metalLayer(
Expand Down
14 changes: 8 additions & 6 deletions shell/platform/darwin/ios/ios_gl_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<IOSGLRenderTarget> CreateRenderTarget(
fml::scoped_nsobject<CAEAGLLayer> layer);

bool MakeCurrent();

bool ResourceMakeCurrent();
bool BindRenderbufferStorage(fml::scoped_nsobject<CAEAGLLayer> layer);

sk_sp<SkColorSpace> ColorSpace() const { return color_space_; }

std::unique_ptr<IOSGLContext> MakeSharedContext();

fml::WeakPtr<IOSGLContext> GetWeakPtr();

private:
fml::scoped_nsobject<EAGLContext> context_;
fml::scoped_nsobject<EAGLContext> resource_context_;
sk_sp<SkColorSpace> color_space_;

std::unique_ptr<fml::WeakPtrFactory<IOSGLContext>> weak_factory_;

FML_DISALLOW_COPY_AND_ASSIGN(IOSGLContext);
};

Expand Down
33 changes: 18 additions & 15 deletions shell/platform/darwin/ios/ios_gl_context.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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<fml::WeakPtrFactory<IOSGLContext>>(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:
Expand All @@ -44,20 +45,22 @@
}
}

IOSGLContext::~IOSGLContext() = default;
fml::WeakPtr<IOSGLContext> IOSGLContext::GetWeakPtr() {
return weak_factory_->GetWeakPtr();
}

std::unique_ptr<IOSGLRenderTarget> IOSGLContext::CreateRenderTarget(
fml::scoped_nsobject<CAEAGLLayer> layer) {
return std::make_unique<IOSGLRenderTarget>(std::move(layer), context_.get(),
resource_context_.get());
bool IOSGLContext::BindRenderbufferStorage(fml::scoped_nsobject<CAEAGLLayer> 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> IOSGLContext::MakeSharedContext() {
return std::make_unique<IOSGLContext>(context_.get().sharegroup);
}

} // namespace flutter
9 changes: 5 additions & 4 deletions shell/platform/darwin/ios/ios_gl_render_target.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<CAEAGLLayer> layer,
EAGLContext* context,
EAGLContext* resource_context);
fml::WeakPtr<IOSGLContext> onscreen_context,
fml::WeakPtr<IOSGLContext> resource_context);

~IOSGLRenderTarget();

Expand All @@ -40,8 +41,8 @@ class IOSGLRenderTarget {

private:
fml::scoped_nsobject<CAEAGLLayer> layer_;
fml::scoped_nsobject<EAGLContext> context_;
fml::scoped_nsobject<EAGLContext> resource_context_;
fml::WeakPtr<IOSGLContext> onscreen_gl_context_;
fml::WeakPtr<IOSGLContext> resource_gl_context_;
GLuint framebuffer_;
GLuint colorbuffer_;
GLint storage_size_width_;
Expand Down
25 changes: 12 additions & 13 deletions shell/platform/darwin/ios/ios_gl_render_target.mm
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,22 @@
#include "third_party/skia/include/gpu/gl/GrGLInterface.h"

namespace flutter {

IOSGLRenderTarget::IOSGLRenderTarget(fml::scoped_nsobject<CAEAGLLayer> layer,
EAGLContext* context,
EAGLContext* resource_context)
fml::WeakPtr<IOSGLContext> onscreen_gl_context,
fml::WeakPtr<IOSGLContext> 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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -105,7 +104,7 @@

FML_DCHECK(glGetError() == GL_NO_ERROR);

if (![EAGLContext setCurrentContext:context_]) {
if (!onscreen_gl_context_->MakeCurrent()) {
return false;
}

Expand All @@ -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;
}

Expand All @@ -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
12 changes: 9 additions & 3 deletions shell/platform/darwin/ios/ios_surface_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@ class IOSSurfaceGL final : public IOSSurface,
public GPUSurfaceGLDelegate,
public ExternalViewEmbedder {
public:
IOSSurfaceGL(std::shared_ptr<IOSGLContext> context,
IOSSurfaceGL(fml::WeakPtr<IOSGLContext> onscreen_gl_context,
fml::WeakPtr<IOSGLContext> resource_gl_context,
fml::scoped_nsobject<CAEAGLLayer> layer,
FlutterPlatformViewsController* platform_views_controller);

IOSSurfaceGL(fml::scoped_nsobject<CAEAGLLayer> layer, std::shared_ptr<IOSGLContext> context);
IOSSurfaceGL(fml::scoped_nsobject<CAEAGLLayer> layer,
fml::WeakPtr<IOSGLContext> onscreen_gl_context,
fml::WeakPtr<IOSGLContext> resource_gl_context);

~IOSSurfaceGL() override;

Expand Down Expand Up @@ -79,7 +82,10 @@ class IOSSurfaceGL final : public IOSSurface,
bool SubmitFrame(GrContext* context) override;

private:
std::shared_ptr<IOSGLContext> context_;
fml::WeakPtr<IOSGLContext> onscreen_gl_context_;

fml::WeakPtr<IOSGLContext> resource_gl_context_;

std::unique_ptr<IOSGLRenderTarget> render_target_;

FML_DISALLOW_COPY_AND_ASSIGN(IOSSurfaceGL);
Expand Down
Loading

0 comments on commit 4ac0663

Please sign in to comment.