未验证 提交 618e6666 编写于 作者: C Chris Yang 提交者: GitHub

Reland "Guarding EAGLContext used by Flutter #13314" (#13755)

上级 f7e73b62
......@@ -495,6 +495,8 @@ FILE: ../../../flutter/shell/common/canvas_spy_unittests.cc
FILE: ../../../flutter/shell/common/engine.cc
FILE: ../../../flutter/shell/common/engine.h
FILE: ../../../flutter/shell/common/fixtures/shell_test.dart
FILE: ../../../flutter/shell/common/gl_context_switch_manager.cc
FILE: ../../../flutter/shell/common/gl_context_switch_manager.h
FILE: ../../../flutter/shell/common/input_events_unittests.cc
FILE: ../../../flutter/shell/common/isolate_configuration.cc
FILE: ../../../flutter/shell/common/isolate_configuration.h
......@@ -799,6 +801,8 @@ FILE: ../../../flutter/shell/platform/darwin/ios/ios_external_texture_gl.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_external_texture_gl.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_gl_context.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_gl_context.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_gl_context_switch_manager.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_gl_context_switch_manager.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_gl_render_target.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_gl_render_target.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface.h
......
......@@ -66,6 +66,8 @@ source_set("common") {
"canvas_spy.h",
"engine.cc",
"engine.h",
"gl_context_switch_manager.cc",
"gl_context_switch_manager.h",
"isolate_configuration.cc",
"isolate_configuration.h",
"persistent_cache.cc",
......
// 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 "gl_context_switch_manager.h"
namespace flutter {
GLContextSwitchManager::GLContextSwitchManager() = default;
GLContextSwitchManager::~GLContextSwitchManager() = default;
GLContextSwitchManager::GLContextSwitch::GLContextSwitch() = default;
GLContextSwitchManager::GLContextSwitch::~GLContextSwitch(){};
GLContextSwitchManager::GLContextSwitchPureResult::GLContextSwitchPureResult(
bool switch_result)
: switch_result_(switch_result){};
GLContextSwitchManager::GLContextSwitchPureResult::
~GLContextSwitchPureResult() = default;
bool GLContextSwitchManager::GLContextSwitchPureResult::GetSwitchResult() {
return switch_result_;
}
} // namespace flutter
// 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_COMMON_GL_CONTEXT_SWITCH_MANAGER_H_
#define FLUTTER_SHELL_COMMON_GL_CONTEXT_SWITCH_MANAGER_H_
#include <memory>
#include "flutter/fml/macros.h"
namespace flutter {
//------------------------------------------------------------------------------
/// Manages `GLContextSwitch`.
///
/// Should be subclassed for platforms that uses GL and requires context
/// switching. Always use `MakeCurrent` and `ResourceMakeCurrent` in the
/// `GLContextSwitchManager` to set gl contexts.
///
class GLContextSwitchManager {
public:
//------------------------------------------------------------------------------
/// Switches the gl context to the flutter's contexts.
///
/// Should be subclassed for each platform embedder that uses GL.
/// In construction, it should set the current context to a flutter's context
/// In destruction, it should rest the current context.
///
class GLContextSwitch {
public:
GLContextSwitch();
virtual ~GLContextSwitch();
virtual bool GetSwitchResult() = 0;
FML_DISALLOW_COPY_AND_ASSIGN(GLContextSwitch);
};
GLContextSwitchManager();
~GLContextSwitchManager();
//----------------------------------------------------------------------------
/// @brief Creates a shell instance using the provided settings. The
/// callbacks to create the various shell subcomponents will be
/// called on the appropriate threads before this method returns.
/// If this is the first instance of a shell in the process, this
/// call also bootstraps the Dart VM.
///
/// @param[in] task_runners The task runners
/// @param[in] settings The settings
/// @param[in] on_create_platform_view The callback that must return a
/// platform view. This will be called on
/// the platform task runner before this
/// method returns.
/// @param[in] on_create_rasterizer That callback that must provide a
/// valid rasterizer. This will be called
/// on the render task runner before this
/// method returns.
///
/// @return A full initialized shell if the settings and callbacks are
/// valid. The root isolate has been created but not yet launched.
/// It may be launched by obtaining the engine weak pointer and
/// posting a task onto the UI task runner with a valid run
/// configuration to run the isolate. The embedder must always
/// check the validity of the shell (using the IsSetup call)
/// immediately after getting a pointer to it.
///
//----------------------------------------------------------------------------
/// @brief Make the flutter's context as current context.
///
/// @return A `GLContextSwitch` with `GetSwitchResult` returning true if
/// the setting process is succesful.
virtual std::unique_ptr<GLContextSwitch> MakeCurrent() = 0;
//----------------------------------------------------------------------------
/// @brief Make the flutter's resources context as current context.
///
/// @return A `GLContextSwitch` with `GetSwitchResult` returning true if
/// the setting process is succesful.
virtual std::unique_ptr<GLContextSwitch> ResourceMakeCurrent() = 0;
//------------------------------------------------------------------------------
/// A representation of a `GLContextSwitch` that doesn't require actual
/// context switching.
///
class GLContextSwitchPureResult final : public GLContextSwitch {
public:
// Constructor that creates an `GLContextSwitchPureResult`.
// The `GetSwitchResult` will return the same value as `switch_result`.
//----------------------------------------------------------------------------
/// @brief Constructs a `GLContextSwitchPureResult`.
///
/// @param[in] switch_result the switch result that will be returned
/// in `GetSwitchResult()`
///
GLContextSwitchPureResult(bool switch_result);
~GLContextSwitchPureResult();
bool GetSwitchResult() override;
private:
bool switch_result_;
FML_DISALLOW_COPY_AND_ASSIGN(GLContextSwitchPureResult);
};
FML_DISALLOW_COPY_AND_ASSIGN(GLContextSwitchManager);
};
} // namespace flutter
#endif
......@@ -355,8 +355,10 @@ PointerDataDispatcherMaker ShellTestPlatformView::GetDispatcherMaker() {
}
// |GPUSurfaceGLDelegate|
bool ShellTestPlatformView::GLContextMakeCurrent() {
return gl_surface_.MakeCurrent();
std::unique_ptr<GLContextSwitchManager::GLContextSwitch>
ShellTestPlatformView::GLContextMakeCurrent() {
return std::make_unique<GLContextSwitchManager::GLContextSwitchPureResult>(
gl_surface_.MakeCurrent());
}
// |GPUSurfaceGLDelegate|
......@@ -387,5 +389,10 @@ ExternalViewEmbedder* ShellTestPlatformView::GetExternalViewEmbedder() {
return nullptr;
}
std::shared_ptr<GLContextSwitchManager>
ShellTestPlatformView::GetGLContextSwitchManager() {
return nullptr;
}
} // namespace testing
} // namespace flutter
......@@ -144,7 +144,8 @@ class ShellTestPlatformView : public PlatformView, public GPUSurfaceGLDelegate {
PointerDataDispatcherMaker GetDispatcherMaker() override;
// |GPUSurfaceGLDelegate|
bool GLContextMakeCurrent() override;
std::unique_ptr<GLContextSwitchManager::GLContextSwitch>
GLContextMakeCurrent() override;
// |GPUSurfaceGLDelegate|
bool GLContextClearCurrent() override;
......@@ -161,6 +162,8 @@ class ShellTestPlatformView : public PlatformView, public GPUSurfaceGLDelegate {
// |GPUSurfaceGLDelegate|
ExternalViewEmbedder* GetExternalViewEmbedder() override;
std::shared_ptr<GLContextSwitchManager> GetGLContextSwitchManager() override;
FML_DISALLOW_COPY_AND_ASSIGN(ShellTestPlatformView);
};
......
......@@ -60,8 +60,10 @@ flutter::ExternalViewEmbedder* Surface::GetExternalViewEmbedder() {
return nullptr;
}
bool Surface::MakeRenderContextCurrent() {
return true;
std::unique_ptr<GLContextSwitchManager::GLContextSwitch>
Surface::MakeRenderContextCurrent() {
return std::make_unique<GLContextSwitchManager::GLContextSwitchPureResult>(
true);
}
} // namespace flutter
......@@ -10,6 +10,7 @@
#include "flutter/flow/compositor_context.h"
#include "flutter/flow/embedded_views.h"
#include "flutter/fml/macros.h"
#include "flutter/shell/common/gl_context_switch_manager.h"
#include "third_party/skia/include/core/SkCanvas.h"
namespace flutter {
......@@ -58,7 +59,8 @@ class Surface {
virtual flutter::ExternalViewEmbedder* GetExternalViewEmbedder();
virtual bool MakeRenderContextCurrent();
virtual std::unique_ptr<GLContextSwitchManager::GLContextSwitch>
MakeRenderContextCurrent();
private:
FML_DISALLOW_COPY_AND_ASSIGN(Surface);
......
......@@ -8,6 +8,7 @@
#include "flutter/fml/logging.h"
#include "flutter/fml/size.h"
#include "flutter/fml/trace_event.h"
#include "flutter/shell/common/gl_context_switch_manager.h"
#include "flutter/shell/common/persistent_cache.h"
#include "third_party/skia/include/core/SkColorFilter.h"
#include "third_party/skia/include/core/SkSurface.h"
......@@ -39,7 +40,10 @@ GPUSurfaceGL::GPUSurfaceGL(GPUSurfaceGLDelegate* delegate,
: delegate_(delegate),
render_to_surface_(render_to_surface),
weak_factory_(this) {
if (!delegate_->GLContextMakeCurrent()) {
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> context_switch =
delegate_->GLContextMakeCurrent();
if (!context_switch->GetSwitchResult()) {
FML_LOG(ERROR)
<< "Could not make the context current to setup the gr context.";
return;
......@@ -87,8 +91,6 @@ GPUSurfaceGL::GPUSurfaceGL(GPUSurfaceGLDelegate* delegate,
}
FML_LOG(INFO) << "Found " << caches.size() << " SkSL shaders; precompiled "
<< compiled_count;
delegate_->GLContextClearCurrent();
}
GPUSurfaceGL::GPUSurfaceGL(sk_sp<GrContext> gr_context,
......@@ -98,7 +100,9 @@ GPUSurfaceGL::GPUSurfaceGL(sk_sp<GrContext> gr_context,
context_(gr_context),
render_to_surface_(render_to_surface),
weak_factory_(this) {
if (!delegate_->GLContextMakeCurrent()) {
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> context_switch =
delegate_->GLContextMakeCurrent();
if (!context_switch->GetSwitchResult()) {
FML_LOG(ERROR)
<< "Could not make the context current to setup the gr context.";
return;
......@@ -114,8 +118,9 @@ GPUSurfaceGL::~GPUSurfaceGL() {
if (!valid_) {
return;
}
if (!delegate_->GLContextMakeCurrent()) {
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> context_switch =
delegate_->GLContextMakeCurrent();
if (!context_switch->GetSwitchResult()) {
FML_LOG(ERROR) << "Could not make the context current to destroy the "
"GrContext resources.";
return;
......@@ -126,8 +131,6 @@ GPUSurfaceGL::~GPUSurfaceGL() {
context_->releaseResourcesAndAbandonContext();
}
context_ = nullptr;
delegate_->GLContextClearCurrent();
}
// |Surface|
......@@ -253,7 +256,9 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceGL::AcquireFrame(const SkISize& size) {
return nullptr;
}
if (!delegate_->GLContextMakeCurrent()) {
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> context_switch =
delegate_->GLContextMakeCurrent();
if (!context_switch->GetSwitchResult()) {
FML_LOG(ERROR)
<< "Could not make the context current to acquire the frame.";
return nullptr;
......@@ -285,7 +290,9 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceGL::AcquireFrame(const SkISize& size) {
return weak ? weak->PresentSurface(canvas) : false;
};
return std::make_unique<SurfaceFrame>(surface, submit_callback);
std::unique_ptr<SurfaceFrame> result =
std::make_unique<SurfaceFrame>(surface, submit_callback);
return result;
}
bool GPUSurfaceGL::PresentSurface(SkCanvas* canvas) {
......@@ -293,6 +300,8 @@ bool GPUSurfaceGL::PresentSurface(SkCanvas* canvas) {
return false;
}
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> context_switch =
delegate_->GLContextMakeCurrent();
if (offscreen_surface_ != nullptr) {
TRACE_EVENT0("flutter", "CopyTextureOnscreen");
SkPaint paint;
......@@ -329,7 +338,6 @@ bool GPUSurfaceGL::PresentSurface(SkCanvas* canvas) {
onscreen_surface_ = std::move(new_onscreen_surface);
}
return true;
}
......@@ -360,7 +368,8 @@ flutter::ExternalViewEmbedder* GPUSurfaceGL::GetExternalViewEmbedder() {
}
// |Surface|
bool GPUSurfaceGL::MakeRenderContextCurrent() {
std::unique_ptr<GLContextSwitchManager::GLContextSwitch>
GPUSurfaceGL::MakeRenderContextCurrent() {
return delegate_->GLContextMakeCurrent();
}
......
......@@ -44,7 +44,8 @@ class GPUSurfaceGL : public Surface {
flutter::ExternalViewEmbedder* GetExternalViewEmbedder() override;
// |Surface|
bool MakeRenderContextCurrent() override;
std::unique_ptr<GLContextSwitchManager::GLContextSwitch>
MakeRenderContextCurrent() override;
private:
GPUSurfaceGLDelegate* delegate_;
......
......@@ -7,6 +7,7 @@
#include "flutter/flow/embedded_views.h"
#include "flutter/fml/macros.h"
#include "flutter/shell/common/gl_context_switch_manager.h"
#include "flutter/shell/gpu/gpu_surface_delegate.h"
#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
......@@ -16,7 +17,8 @@ namespace flutter {
class GPUSurfaceGLDelegate : public GPUSurfaceDelegate {
public:
// Called to make the main GL context current on the current thread.
virtual bool GLContextMakeCurrent() = 0;
virtual std::unique_ptr<GLContextSwitchManager::GLContextSwitch>
GLContextMakeCurrent() = 0;
// Called to clear the current GL context on the thread. This may be called on
// either the GPU or IO threads.
......@@ -59,6 +61,9 @@ class GPUSurfaceGLDelegate : public GPUSurfaceDelegate {
// instrumentation to specific GL calls can specify custom GL functions
// here.
virtual GLProcResolver GetGLProcResolver() const;
virtual std::shared_ptr<GLContextSwitchManager>
GetGLContextSwitchManager() = 0;
};
} // namespace flutter
......
......@@ -104,9 +104,11 @@ bool AndroidSurfaceGL::SetNativeWindow(
return true;
}
bool AndroidSurfaceGL::GLContextMakeCurrent() {
std::unique_ptr<GLContextSwitchManager::GLContextSwitch>
AndroidSurfaceGL::GLContextMakeCurrent() {
FML_DCHECK(onscreen_context_ && onscreen_context_->IsValid());
return onscreen_context_->MakeCurrent();
return std::make_unique<GLContextSwitchManager::GLContextSwitchPureResult>(
onscreen_context_->MakeCurrent());
}
bool AndroidSurfaceGL::GLContextClearCurrent() {
......@@ -130,4 +132,10 @@ ExternalViewEmbedder* AndroidSurfaceGL::GetExternalViewEmbedder() {
return nullptr;
}
// |GPUSurfaceGLDelegate|
std::shared_ptr<GLContextSwitchManager>
AndroidSurfaceGL::GetGLContextSwitchManager() {
return nullptr;
}
} // namespace flutter
......@@ -47,7 +47,8 @@ class AndroidSurfaceGL final : public GPUSurfaceGLDelegate,
bool SetNativeWindow(fml::RefPtr<AndroidNativeWindow> window) override;
// |GPUSurfaceGLDelegate|
bool GLContextMakeCurrent() override;
std::unique_ptr<GLContextSwitchManager::GLContextSwitch>
GLContextMakeCurrent() override;
// |GPUSurfaceGLDelegate|
bool GLContextClearCurrent() override;
......@@ -61,6 +62,9 @@ class AndroidSurfaceGL final : public GPUSurfaceGLDelegate,
// |GPUSurfaceGLDelegate|
ExternalViewEmbedder* GetExternalViewEmbedder() override;
// |GPUSurfaceGLDelegate|
std::shared_ptr<GLContextSwitchManager> GetGLContextSwitchManager() override;
private:
fml::RefPtr<AndroidContextGL> onscreen_context_;
fml::RefPtr<AndroidContextGL> offscreen_context_;
......
......@@ -86,6 +86,8 @@ shared_library("create_flutter_framework_dylib") {
"ios_external_texture_gl.mm",
"ios_gl_context.h",
"ios_gl_context.mm",
"ios_gl_context_switch_manager.h",
"ios_gl_context_switch_manager.mm",
"ios_gl_render_target.h",
"ios_gl_render_target.mm",
"ios_surface.h",
......
......@@ -160,6 +160,11 @@ void FlutterPlatformViewsController::SetFrameSize(SkISize frame_size) {
frame_size_ = frame_size;
}
void FlutterPlatformViewsController::SetGLContextSwitchManager(
std::shared_ptr<IOSGLContextSwitchManager> gl_context_guard_manager) {
gl_context_switch_manager_ = gl_context_guard_manager;
}
void FlutterPlatformViewsController::CancelFrame() {
composition_order_.clear();
}
......@@ -368,7 +373,12 @@ bool FlutterPlatformViewsController::SubmitFrame(GrContext* gr_context,
bool did_submit = true;
for (int64_t view_id : composition_order_) {
EnsureOverlayInitialized(view_id, gl_context, gr_context);
if (gl_context_switch_manager_ != nullptr) {
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> contextSwitch =
gl_context_switch_manager_->MakeCurrent();
}
EnsureOverlayInitialized(view_id, std::move(gl_context), gr_context);
auto frame = overlays_[view_id]->surface->AcquireFrame(frame_size_);
SkCanvas* canvas = frame->SkiaCanvas();
canvas->drawPicture(picture_recorders_[view_id]->finishRecordingAsPicture());
......@@ -455,6 +465,10 @@ void FlutterPlatformViewsController::EnsureOverlayInitialized(
std::shared_ptr<IOSGLContext> gl_context,
GrContext* gr_context) {
FML_DCHECK(flutter_view_);
if (gl_context_switch_manager_ != nullptr) {
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> contextSwitch =
gl_context_switch_manager_->MakeCurrent();
}
auto overlay_it = overlays_.find(overlay_id);
......
......@@ -11,6 +11,7 @@
#include "flutter/shell/platform/darwin/common/framework/Headers/FlutterBinaryMessenger.h"
#include "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h"
#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h"
#include "flutter/shell/platform/darwin/ios/ios_gl_context_switch_manager.h"
// A UIView that is used as the parent for embedded UIViews.
//
......@@ -80,6 +81,9 @@ class FlutterPlatformViewsController {
void SetFlutterViewController(UIViewController* flutter_view_controller);
void SetGLContextSwitchManager(
std::shared_ptr<IOSGLContextSwitchManager> gl_context_guard_manager);
void RegisterViewFactory(NSObject<FlutterPlatformViewFactory>* factory, NSString* factoryId);
void SetFrameSize(SkISize frame_size);
......@@ -204,6 +208,8 @@ class FlutterPlatformViewsController {
void ApplyMutators(const MutatorsStack& mutators_stack, UIView* embedded_view);
void CompositeWithParams(int view_id, const EmbeddedViewParams& params);
std::shared_ptr<IOSGLContextSwitchManager> gl_context_switch_manager_;
FML_DISALLOW_COPY_AND_ASSIGN(FlutterPlatformViewsController);
};
......
......@@ -26,16 +26,24 @@ class IOSGLContext {
std::unique_ptr<IOSGLRenderTarget> CreateRenderTarget(
fml::scoped_nsobject<CAEAGLLayer> layer);
bool MakeCurrent();
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> MakeCurrent();
bool ResourceMakeCurrent();
std::unique_ptr<GLContextSwitchManager::GLContextSwitch>
ResourceMakeCurrent();
std::shared_ptr<IOSGLContextSwitchManager> GetIOSGLContextSwitchManager() {
return gl_context_switch_manager_;
}
sk_sp<SkColorSpace> ColorSpace() const { return color_space_; }
fml::scoped_nsobject<EAGLContext> GetContext() const {
return gl_context_switch_manager_->GetContext();
}
private:
fml::scoped_nsobject<EAGLContext> context_;
fml::scoped_nsobject<EAGLContext> resource_context_;
sk_sp<SkColorSpace> color_space_;
std::shared_ptr<IOSGLContextSwitchManager> gl_context_switch_manager_;
FML_DISALLOW_COPY_AND_ASSIGN(IOSGLContext);
};
......
......@@ -13,15 +13,7 @@
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]);
context_.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2
sharegroup:resource_context_.get().sharegroup]);
}
gl_context_switch_manager_ = std::make_shared<IOSGLContextSwitchManager>();
// TODO:
// iOS displays are more variable than just P3 or sRGB. Reading the display
......@@ -48,16 +40,15 @@ IOSGLContext::~IOSGLContext() = default;
std::unique_ptr<IOSGLRenderTarget> IOSGLContext::CreateRenderTarget(
fml::scoped_nsobject<CAEAGLLayer> layer) {
return std::make_unique<IOSGLRenderTarget>(std::move(layer), context_.get(),
resource_context_.get());
return std::make_unique<IOSGLRenderTarget>(std::move(layer), gl_context_switch_manager_);
}
bool IOSGLContext::MakeCurrent() {
return [EAGLContext setCurrentContext:context_.get()];
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> IOSGLContext::MakeCurrent() {
return gl_context_switch_manager_->MakeCurrent();
}
bool IOSGLContext::ResourceMakeCurrent() {
return [EAGLContext setCurrentContext:resource_context_.get()];
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> IOSGLContext::ResourceMakeCurrent() {
return gl_context_switch_manager_->ResourceMakeCurrent();
}
} // namespace flutter
// 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_GL_CONTEXT_SWITCH_MANAGER_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_GL_CONTEXT_SWITCH_MANAGER_H_
#define GLES_SILENCE_DEPRECATION
#import <OpenGLES/EAGL.h>
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/common/gl_context_switch_manager.h"
namespace flutter {
//------------------------------------------------------------------------------
/// The iOS implementation of `GLContextSwitchManager`.
///
/// On `IOSGLContextSwitch`'s construction, it pushes the current EAGLContext to a stack and
/// sets the flutter's gl context as current.
/// On `IOSGLContextSwitch`'s desstruction, it pops a EAGLContext from the stack and set it to
/// current.
///
class IOSGLContextSwitchManager final : public GLContextSwitchManager {
public:
class IOSGLContextSwitch final : public GLContextSwitch {
public:
IOSGLContextSwitch(IOSGLContextSwitchManager& manager,
fml::scoped_nsobject<EAGLContext> context);
~IOSGLContextSwitch();
bool GetSwitchResult() override;
private:
IOSGLContextSwitchManager& manager_;
bool switch_result_;
bool has_pushed_context_;
FML_DISALLOW_COPY_AND_ASSIGN(IOSGLContextSwitch);
};
IOSGLContextSwitchManager();
~IOSGLContextSwitchManager();
std::unique_ptr<GLContextSwitch> MakeCurrent() override;
std::unique_ptr<GLContextSwitch> ResourceMakeCurrent() override;
fml::scoped_nsobject<EAGLContext> GetContext();
private:
fml::scoped_nsobject<EAGLContext> context_;
fml::scoped_nsobject<EAGLContext> resource_context_;
fml::scoped_nsobject<NSMutableArray> stored_;
bool PushContext(fml::scoped_nsobject<EAGLContext> context);
void PopContext();
FML_DISALLOW_COPY_AND_ASSIGN(IOSGLContextSwitchManager);
};
}
#endif
// 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 "ios_gl_context_switch_manager.h"
namespace flutter {
IOSGLContextSwitchManager::IOSGLContextSwitchManager() {
resource_context_.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]);
stored_ = fml::scoped_nsobject<NSMutableArray>([[NSMutableArray new] retain]);
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]);
context_.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2
sharegroup:resource_context_.get().sharegroup]);
}
};
IOSGLContextSwitchManager::~IOSGLContextSwitchManager() = default;
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> IOSGLContextSwitchManager::MakeCurrent() {
return std::make_unique<IOSGLContextSwitchManager::IOSGLContextSwitch>(*this, context_);
}
std::unique_ptr<GLContextSwitchManager::GLContextSwitch>
IOSGLContextSwitchManager::ResourceMakeCurrent() {
return std::make_unique<IOSGLContextSwitchManager::IOSGLContextSwitch>(*this, resource_context_);
}
fml::scoped_nsobject<EAGLContext> IOSGLContextSwitchManager::GetContext() {
return context_;
}
bool IOSGLContextSwitchManager::PushContext(fml::scoped_nsobject<EAGLContext> context) {
EAGLContext* current = [EAGLContext currentContext];
if (current == nil) {
[stored_.get() addObject:[NSNull null]];
} else {
[stored_.get() addObject:current];
}
bool result = [EAGLContext setCurrentContext:context.get()];
return result;
}
void IOSGLContextSwitchManager::PopContext() {
EAGLContext* last = [stored_.get() lastObject];
[stored_.get() removeLastObject];
if ([last isEqual:[NSNull null]]) {
[EAGLContext setCurrentContext:nil];
return;
}
[EAGLContext setCurrentContext:last];
}
IOSGLContextSwitchManager::IOSGLContextSwitch::IOSGLContextSwitch(
IOSGLContextSwitchManager& manager,
fml::scoped_nsobject<EAGLContext> context)
: manager_(manager) {
bool result = manager_.PushContext(context);
has_pushed_context_ = true;
switch_result_ = result;
}
IOSGLContextSwitchManager::IOSGLContextSwitch::~IOSGLContextSwitch() {
if (!has_pushed_context_) {
return;
}
manager_.PopContext();
}
bool IOSGLContextSwitchManager::IOSGLContextSwitch::GetSwitchResult() {
return switch_result_;
}
}
......@@ -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_switch_manager.h"
namespace flutter {
class IOSGLRenderTarget {
public:
IOSGLRenderTarget(fml::scoped_nsobject<CAEAGLLayer> layer,
EAGLContext* context,
EAGLContext* resource_context);
IOSGLRenderTarget(
fml::scoped_nsobject<CAEAGLLayer> layer,
std::shared_ptr<IOSGLContextSwitchManager> gl_context_guard_manager);
~IOSGLRenderTarget();
......@@ -32,16 +33,16 @@ class IOSGLRenderTarget {
bool UpdateStorageSizeIfNecessary();
bool MakeCurrent();
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> MakeCurrent();
bool ResourceMakeCurrent();
std::unique_ptr<GLContextSwitchManager::GLContextSwitch>
ResourceMakeCurrent();
sk_sp<SkColorSpace> ColorSpace() const { return color_space_; }
private:
fml::scoped_nsobject<CAEAGLLayer> layer_;
fml::scoped_nsobject<EAGLContext> context_;
fml::scoped_nsobject<EAGLContext> resource_context_;
std::shared_ptr<IOSGLContextSwitchManager> gl_context_switch_manager_;
GLuint framebuffer_;
GLuint colorbuffer_;
GLint storage_size_width_;
......
......@@ -12,22 +12,20 @@
namespace flutter {
IOSGLRenderTarget::IOSGLRenderTarget(fml::scoped_nsobject<CAEAGLLayer> layer,
EAGLContext* context,
EAGLContext* resource_context)
IOSGLRenderTarget::IOSGLRenderTarget(
fml::scoped_nsobject<CAEAGLLayer> layer,
std::shared_ptr<IOSGLContextSwitchManager> gl_context_guard_manager)
: layer_(std::move(layer)),
context_([context retain]),
resource_context_([resource_context retain]),
gl_context_switch_manager_(gl_context_guard_manager),
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);
bool context_current = [EAGLContext setCurrentContext:context_];
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> context_switch =
gl_context_switch_manager_->MakeCurrent();
bool context_current = context_switch->GetSwitchResult();
FML_DCHECK(context_current);
FML_DCHECK(glGetError() == GL_NO_ERROR);
......@@ -62,8 +60,8 @@ IOSGLRenderTarget::IOSGLRenderTarget(fml::scoped_nsobject<CAEAGLLayer> layer,
}
IOSGLRenderTarget::~IOSGLRenderTarget() {
EAGLContext* context = EAGLContext.currentContext;
[EAGLContext setCurrentContext:context_];
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> context_switch =
gl_context_switch_manager_->MakeCurrent();
FML_DCHECK(glGetError() == GL_NO_ERROR);
// Deletes on GL_NONEs are ignored
......@@ -71,7 +69,6 @@ IOSGLRenderTarget::~IOSGLRenderTarget() {
glDeleteRenderbuffers(1, &colorbuffer_);
FML_DCHECK(glGetError() == GL_NO_ERROR);
[EAGLContext setCurrentContext:context];
}
bool IOSGLRenderTarget::IsValid() const {
......@@ -104,8 +101,9 @@ bool IOSGLRenderTarget::UpdateStorageSizeIfNecessary() {
FML_DLOG(INFO) << "Updating render buffer storage size.";
FML_DCHECK(glGetError() == GL_NO_ERROR);
if (![EAGLContext setCurrentContext:context_]) {
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> context_switch =
gl_context_switch_manager_->MakeCurrent();
if (!context_switch->GetSwitchResult()) {
return false;
}
......@@ -116,7 +114,8 @@ bool IOSGLRenderTarget::UpdateStorageSizeIfNecessary() {
glBindRenderbuffer(GL_RENDERBUFFER, colorbuffer_);
FML_DCHECK(glGetError() == GL_NO_ERROR);
if (![context_.get() renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer_.get()]) {
if (![gl_context_switch_manager_->GetContext().get() renderbufferStorage:GL_RENDERBUFFER
fromDrawable:layer_.get()]) {
return false;
}
......@@ -132,12 +131,16 @@ bool IOSGLRenderTarget::UpdateStorageSizeIfNecessary() {
return true;
}
bool IOSGLRenderTarget::MakeCurrent() {
return UpdateStorageSizeIfNecessary() && [EAGLContext setCurrentContext:context_.get()];
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> IOSGLRenderTarget::MakeCurrent() {
bool isUpdateSuccessful = UpdateStorageSizeIfNecessary();
if (!isUpdateSuccessful) {
return std::make_unique<GLContextSwitchManager::GLContextSwitchPureResult>(false);
}
return gl_context_switch_manager_->MakeCurrent();
}
bool IOSGLRenderTarget::ResourceMakeCurrent() {
return [EAGLContext setCurrentContext:resource_context_.get()];
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> IOSGLRenderTarget::ResourceMakeCurrent() {
return gl_context_switch_manager_->ResourceMakeCurrent();
}
} // namespace flutter
......@@ -12,6 +12,7 @@
#include "flutter/fml/macros.h"
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/common/surface.h"
#include "flutter/shell/platform/darwin/ios/ios_gl_context_switch_manager.h"
namespace flutter {
......@@ -27,7 +28,8 @@ class IOSSurface {
virtual bool IsValid() const = 0;
virtual bool ResourceContextMakeCurrent() = 0;
virtual std::unique_ptr<GLContextSwitchManager::GLContextSwitch>
ResourceContextMakeCurrent() = 0;
virtual void UpdateStorageSizeIfNecessary() = 0;
......
......@@ -9,6 +9,7 @@
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/gpu/gpu_surface_gl.h"
#include "flutter/shell/platform/darwin/ios/ios_gl_context.h"
#include "flutter/shell/platform/darwin/ios/ios_gl_context_switch_manager.h"
#include "flutter/shell/platform/darwin/ios/ios_gl_render_target.h"
#include "flutter/shell/platform/darwin/ios/ios_surface.h"
......@@ -32,7 +33,7 @@ class IOSSurfaceGL final : public IOSSurface,
bool IsValid() const override;
// |IOSSurface|
bool ResourceContextMakeCurrent() override;
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> ResourceContextMakeCurrent() override;
// |IOSSurface|
void UpdateStorageSizeIfNecessary() override;
......@@ -40,7 +41,7 @@ class IOSSurfaceGL final : public IOSSurface,
// |IOSSurface|
std::unique_ptr<Surface> CreateGPUSurface(GrContext* gr_context = nullptr) override;
bool GLContextMakeCurrent() override;
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> GLContextMakeCurrent() override;
bool GLContextClearCurrent() override;
......@@ -53,6 +54,9 @@ class IOSSurfaceGL final : public IOSSurface,
// |GPUSurfaceGLDelegate|
ExternalViewEmbedder* GetExternalViewEmbedder() override;
// |GPUSurfaceGLDelegate|
std::shared_ptr<GLContextSwitchManager> GetGLContextSwitchManager() override;
// |ExternalViewEmbedder|
SkCanvas* GetRootCanvas() override;
......
......@@ -28,7 +28,8 @@ bool IOSSurfaceGL::IsValid() const {
return render_target_->IsValid();
}
bool IOSSurfaceGL::ResourceContextMakeCurrent() {
std::unique_ptr<GLContextSwitchManager::GLContextSwitch>
IOSSurfaceGL::ResourceContextMakeCurrent() {
return context_->ResourceMakeCurrent();
}
......@@ -56,11 +57,11 @@ bool IOSSurfaceGL::UseOffscreenSurface() const {
return true;
}
bool IOSSurfaceGL::GLContextMakeCurrent() {
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> IOSSurfaceGL::GLContextMakeCurrent() {
if (!IsValid()) {
return false;
return std::make_unique<GLContextSwitchManager::GLContextSwitchPureResult>(false);
}
return render_target_->UpdateStorageSizeIfNecessary() && context_->MakeCurrent();
return render_target_->MakeCurrent();
}
bool IOSSurfaceGL::GLContextClearCurrent() {
......@@ -73,6 +74,11 @@ bool IOSSurfaceGL::GLContextPresent() {
return IsValid() && render_target_->PresentRenderBuffer();
}
// |GPUSurfaceGLDelegate|
std::shared_ptr<GLContextSwitchManager> IOSSurfaceGL::GetGLContextSwitchManager() {
return context_->GetIOSGLContextSwitchManager();
}
// |ExternalViewEmbedder|
SkCanvas* IOSSurfaceGL::GetRootCanvas() {
// On iOS, the root surface is created from the on-screen render target. Only the surfaces for the
......@@ -144,7 +150,7 @@ bool IOSSurfaceGL::SubmitFrame(GrContext* context) {
if (platform_views_controller == nullptr) {
return true;
}
platform_views_controller->SetGLContextSwitchManager(context_->GetIOSGLContextSwitchManager());
bool submitted = platform_views_controller->SubmitFrame(std::move(context), context_);
[CATransaction commit];
return submitted;
......
......@@ -8,9 +8,9 @@
#include "flutter/flow/embedded_views.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/common/gl_context_switch_manager.h"
#include "flutter/shell/gpu/gpu_surface_software.h"
#include "flutter/shell/platform/darwin/ios/ios_surface.h"
@class CALayer;
namespace flutter {
......@@ -28,7 +28,7 @@ class IOSSurfaceSoftware final : public IOSSurface,
bool IsValid() const override;
// |IOSSurface|
bool ResourceContextMakeCurrent() override;
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> ResourceContextMakeCurrent() override;
// |IOSSurface|
void UpdateStorageSizeIfNecessary() override;
......
......@@ -27,8 +27,9 @@ bool IOSSurfaceSoftware::IsValid() const {
return layer_;
}
bool IOSSurfaceSoftware::ResourceContextMakeCurrent() {
return false;
std::unique_ptr<GLContextSwitchManager::GLContextSwitch>
IOSSurfaceSoftware::ResourceContextMakeCurrent() {
return std::make_unique<GLContextSwitchManager::GLContextSwitchPureResult>(false);
}
void IOSSurfaceSoftware::UpdateStorageSizeIfNecessary() {
......
......@@ -107,15 +107,18 @@ std::unique_ptr<Surface> PlatformViewIOS::CreateRenderingSurface() {
// |PlatformView|
sk_sp<GrContext> PlatformViewIOS::CreateResourceContext() const {
FML_DCHECK(task_runners_.GetIOTaskRunner()->RunsTasksOnCurrentThread());
if (!gl_context_ || !gl_context_->ResourceMakeCurrent()) {
FML_DLOG(INFO) << "Could not make resource context current on IO thread. "
"Async texture uploads will be disabled. On Simulators, "
"this is expected.";
return nullptr;
if (gl_context_ != nullptr) {
std::unique_ptr<GLContextSwitchManager::GLContextSwitch> context_switch =
gl_context_->ResourceMakeCurrent();
if (context_switch->GetSwitchResult()) {
return ShellIOManager::CreateCompatibleResourceLoadingContext(
GrBackend::kOpenGL_GrBackend, GPUSurfaceGLDelegate::GetDefaultPlatformGLInterface());
}
}
return ShellIOManager::CreateCompatibleResourceLoadingContext(
GrBackend::kOpenGL_GrBackend, GPUSurfaceGLDelegate::GetDefaultPlatformGLInterface());
FML_DLOG(INFO) << "Could not make resource context current on IO thread. "
"Async texture uploads will be disabled. On Simulators, "
"this is expected.";
return nullptr;
}
// |PlatformView|
......
......@@ -34,8 +34,10 @@ bool EmbedderSurfaceGL::IsValid() const {
}
// |GPUSurfaceGLDelegate|
bool EmbedderSurfaceGL::GLContextMakeCurrent() {
return gl_dispatch_table_.gl_make_current_callback();
std::unique_ptr<GLContextSwitchManager::GLContextSwitch>
EmbedderSurfaceGL::GLContextMakeCurrent() {
return std::make_unique<GLContextSwitchManager::GLContextSwitchPureResult>(
gl_dispatch_table_.gl_make_current_callback());
}
// |GPUSurfaceGLDelegate|
......@@ -79,6 +81,12 @@ EmbedderSurfaceGL::GLProcResolver EmbedderSurfaceGL::GetGLProcResolver() const {
return gl_dispatch_table_.gl_proc_resolver;
}
// |GPUSurfaceGLDelegate|
std::shared_ptr<GLContextSwitchManager>
EmbedderSurfaceGL::GetGLContextSwitchManager() {
return nullptr;
}
// |EmbedderSurface|
std::unique_ptr<Surface> EmbedderSurfaceGL::CreateGPUSurface() {
const bool render_to_surface = !external_view_embedder_;
......
......@@ -50,7 +50,8 @@ class EmbedderSurfaceGL final : public EmbedderSurface,
sk_sp<GrContext> CreateResourceContext() const override;
// |GPUSurfaceGLDelegate|
bool GLContextMakeCurrent() override;
std::unique_ptr<GLContextSwitchManager::GLContextSwitch>
GLContextMakeCurrent() override;
// |GPUSurfaceGLDelegate|
bool GLContextClearCurrent() override;
......@@ -73,6 +74,9 @@ class EmbedderSurfaceGL final : public EmbedderSurface,
// |GPUSurfaceGLDelegate|
GLProcResolver GetGLProcResolver() const override;
// |GPUSurfaceGLDelegate|
std::shared_ptr<GLContextSwitchManager> GetGLContextSwitchManager() override;
FML_DISALLOW_COPY_AND_ASSIGN(EmbedderSurfaceGL);
};
......
......@@ -40,6 +40,8 @@
6816DBAC2318696600A51400 /* golden_platform_view_opacity_iPhone SE_simulator.png in Resources */ = {isa = PBXBuildFile; fileRef = 6816DBA72318696600A51400 /* golden_platform_view_opacity_iPhone SE_simulator.png */; };
6816DBAD2318696600A51400 /* golden_platform_view_cliprect_iPhone SE_simulator.png in Resources */ = {isa = PBXBuildFile; fileRef = 6816DBA82318696600A51400 /* golden_platform_view_cliprect_iPhone SE_simulator.png */; };
6816DBAE2318696600A51400 /* golden_platform_view_cliprrect_iPhone SE_simulator.png in Resources */ = {isa = PBXBuildFile; fileRef = 6816DBA92318696600A51400 /* golden_platform_view_cliprrect_iPhone SE_simulator.png */; };
68396B28235FA0D700D5E655 /* GLTestPlatformView.m in Sources */ = {isa = PBXBuildFile; fileRef = 68396B27235FA0D700D5E655 /* GLTestPlatformView.m */; };
68396B2A235FBEA600D5E655 /* PlatformViewGLTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 68396B29235FBEA600D5E655 /* PlatformViewGLTests.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
......@@ -136,6 +138,9 @@
6816DBA72318696600A51400 /* golden_platform_view_opacity_iPhone SE_simulator.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "golden_platform_view_opacity_iPhone SE_simulator.png"; sourceTree = "<group>"; };
6816DBA82318696600A51400 /* golden_platform_view_cliprect_iPhone SE_simulator.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "golden_platform_view_cliprect_iPhone SE_simulator.png"; sourceTree = "<group>"; };
6816DBA92318696600A51400 /* golden_platform_view_cliprrect_iPhone SE_simulator.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "golden_platform_view_cliprrect_iPhone SE_simulator.png"; sourceTree = "<group>"; };
68396B26235FA0D700D5E655 /* GLTestPlatformView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GLTestPlatformView.h; sourceTree = "<group>"; };
68396B27235FA0D700D5E655 /* GLTestPlatformView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GLTestPlatformView.m; sourceTree = "<group>"; };
68396B29235FBEA600D5E655 /* PlatformViewGLTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PlatformViewGLTests.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
......@@ -202,6 +207,8 @@
0A57B3BC2323C4BD00DD9521 /* ScreenBeforeFlutter.m */,
0A57B3BE2323C74200DD9521 /* FlutterEngine+ScenariosTest.m */,
0A57B3C02323C74D00DD9521 /* FlutterEngine+ScenariosTest.h */,
68396B26235FA0D700D5E655 /* GLTestPlatformView.h */,
68396B27235FA0D700D5E655 /* GLTestPlatformView.m */,
);
path = Scenarios;
sourceTree = "<group>";
......@@ -239,6 +246,7 @@
6816DBA02317573300A51400 /* GoldenImage.m */,
6816DBA22318358200A51400 /* PlatformViewGoldenTestManager.h */,
6816DBA32318358200A51400 /* PlatformViewGoldenTestManager.m */,
68396B29235FBEA600D5E655 /* PlatformViewGLTests.m */,
);
path = ScenariosUITests;
sourceTree = "<group>";
......@@ -398,6 +406,7 @@
files = (
248D76DA22E388380012F0C1 /* main.m in Sources */,
24F1FB89230B4579005ACE7C /* TextPlatformView.m in Sources */,
68396B28235FA0D700D5E655 /* GLTestPlatformView.m in Sources */,
248D76CC22E388370012F0C1 /* AppDelegate.m in Sources */,
0A57B3BF2323C74200DD9521 /* FlutterEngine+ScenariosTest.m in Sources */,
0A57B3BD2323C4BD00DD9521 /* ScreenBeforeFlutter.m in Sources */,
......@@ -418,6 +427,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
68396B2A235FBEA600D5E655 /* PlatformViewGLTests.m in Sources */,
6816DBA12317573300A51400 /* GoldenImage.m in Sources */,
6816DB9E231750ED00A51400 /* GoldenPlatformViewTests.m in Sources */,
6816DBA42318358200A51400 /* PlatformViewGoldenTestManager.m in Sources */,
......@@ -492,7 +502,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
......@@ -545,7 +555,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
......@@ -561,6 +571,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = S8QB4VV633;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
......@@ -584,6 +595,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = S8QB4VV633;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
......
......@@ -27,6 +27,15 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "248D76C622E388370012F0C1"
BuildableName = "Scenarios.app"
BlueprintName = "Scenarios"
ReferencedContainer = "container:Scenarios.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
......@@ -51,17 +60,6 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "248D76C622E388370012F0C1"
BuildableName = "Scenarios.app"
BlueprintName = "Scenarios"
ReferencedContainer = "container:Scenarios.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
......@@ -93,8 +91,6 @@
isEnabled = "NO">
</CommandLineArgument>
</CommandLineArguments>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
......
......@@ -4,6 +4,7 @@
#include "AppDelegate.h"
#import "FlutterEngine+ScenariosTest.h"
#import "GLTestPlatformView.h"
#import "ScreenBeforeFlutter.h"
#import "TextPlatformView.h"
......@@ -50,6 +51,8 @@
[self readyContextForPlatformViewTests:goldenTestName];
} else if ([[[NSProcessInfo processInfo] arguments] containsObject:@"--screen-before-flutter"]) {
self.window.rootViewController = [[ScreenBeforeFlutter alloc] initWithEngineRunCompletion:nil];
} else if ([[[NSProcessInfo processInfo] arguments] containsObject:@"--platform-view-gl"]) {
[self readyContextForGLPlatformViewTests:@"platform_view_eaglcontext"];
} else {
self.window.rootViewController = [[UIViewController alloc] init];
}
......@@ -79,4 +82,25 @@
self.window.rootViewController = flutterViewController;
}
- (void)readyContextForGLPlatformViewTests:(NSString*)scenarioIdentifier {
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"PlatformViewTest" project:nil];
[engine runWithEntrypoint:nil];
FlutterViewController* flutterViewController =
[[NoStatusBarFlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil];
[engine.binaryMessenger
setMessageHandlerOnChannel:@"scenario_status"
binaryMessageHandler:^(NSData* _Nullable message, FlutterBinaryReply _Nonnull reply) {
[engine.binaryMessenger
sendOnChannel:@"set_scenario"
message:[scenarioIdentifier dataUsingEncoding:NSUTF8StringEncoding]];
}];
GLTestPlatformViewFactory* platformViewFactory =
[[GLTestPlatformViewFactory alloc] initWithMessenger:flutterViewController.binaryMessenger];
NSObject<FlutterPluginRegistrar>* registrar =
[flutterViewController.engine registrarForPlugin:@"scenarios/glTestPlatformViewPlugin"];
[registrar registerViewFactory:platformViewFactory withId:@"scenarios/glTestPlatformView"];
self.window.rootViewController = flutterViewController;
}
@end
// Copyright 2019 The Chromium 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/Flutter.h>
NS_ASSUME_NONNULL_BEGIN
@interface GLTestPlatformView : NSObject <FlutterPlatformView>
- (instancetype)initWithFrame:(CGRect)frame
viewIdentifier:(int64_t)viewId
arguments:(id _Nullable)args
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger;
- (UIView*)view;
@end
@interface GLTestPlatformViewFactory : NSObject <FlutterPlatformViewFactory>
- (instancetype)initWithMessenger:(NSObject<FlutterBinaryMessenger>*)messenger;
@end
@interface GLTestView : UIView
@end
NS_ASSUME_NONNULL_END
// Copyright 2019 The Chromium 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 "GLTestPlatformView.h"
#define GLES_SILENCE_DEPRECATION
@implementation GLTestPlatformView {
int64_t _viewId;
GLTestView* _view;
}
- (instancetype)initWithFrame:(CGRect)frame
viewIdentifier:(int64_t)viewId
arguments:(id)args
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger {
if ([super init]) {
_viewId = viewId;
_view = [[GLTestView alloc] initWithFrame:CGRectMake(50.0, 50.0, 250.0, 100.0)];
}
return self;
}
- (UIView*)view {
return _view;
}
@end
@implementation GLTestPlatformViewFactory {
NSObject<FlutterBinaryMessenger>* _messenger;
}
- (instancetype)initWithMessenger:(NSObject<FlutterBinaryMessenger>*)messenger {
self = [super init];
if (self) {
_messenger = messenger;
}
return self;
}
- (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame
viewIdentifier:(int64_t)viewId
arguments:(id _Nullable)args {
GLTestPlatformView* platformView = [[GLTestPlatformView alloc] initWithFrame:frame
viewIdentifier:viewId
arguments:args
binaryMessenger:_messenger];
return platformView;
}
- (NSObject<FlutterMessageCodec>*)createArgsCodec {
return [FlutterStringCodec sharedInstance];
}
@end
@interface GLTestView ()
@property(strong, nonatomic) EAGLContext* context;
@end
@implementation GLTestView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
_context.debugLabel = @"platform view context";
[EAGLContext setCurrentContext:_context];
self.backgroundColor = [UIColor redColor];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
[self checkEAGLContext];
});
}
return self;
}
- (void)checkEAGLContext {
if ([EAGLContext currentContext] != _context) {
self.accessibilityIdentifier = @"gl_platformview_wrong_context";
} else {
self.accessibilityIdentifier = @"gl_platformview_correct_context";
}
}
@end
// 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 <XCTest/XCTest.h>
@interface PlatformViewGLTests : XCTestCase
@property(nonatomic, strong) XCUIApplication* application;
@end
@implementation PlatformViewGLTests
- (void)setUp {
self.continueAfterFailure = NO;
self.application = [[XCUIApplication alloc] init];
self.application.launchArguments = @[ @"--platform-view-gl" ];
[self.application launch];
}
- (void)testExample {
NSPredicate* predicateToFindPlatformView =
[NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject,
NSDictionary<NSString*, id>* _Nullable bindings) {
XCUIElement* element = evaluatedObject;
return [element.identifier isEqualToString:@"gl_platformview_wrong_context"] ||
[element.identifier isEqualToString:@"gl_platformview_correct_context"];
}];
XCUIElement* firstElement =
[self.application.otherElements elementMatchingPredicate:predicateToFindPlatformView];
if (![firstElement waitForExistenceWithTimeout:30]) {
XCTFail(@"Failed due to not able to find platform view with 30 seconds");
}
XCTAssertEqualObjects(firstElement.identifier, @"gl_platformview_correct_context");
}
@end
......@@ -25,6 +25,7 @@ Map<String, Scenario> _scenarios = <String, Scenario>{
'platform_view_multiple': MultiPlatformViewScenario(window, firstId: 6, secondId: 7),
'platform_view_multiple_background_foreground': MultiPlatformViewBackgroundForegroundScenario(window, firstId: 8, secondId: 9),
'poppable_screen': PoppableScreenScenario(window),
'platform_view_eaglcontext': PlatformViewGLScenario(window, 'null', id:6),
};
Scenario _currentScenario = _scenarios['animated_color_square'];
......
......@@ -34,7 +34,7 @@ class PlatformViewScenario extends Scenario with _BasePlatformViewScenarioMixin
PlatformViewScenario(Window window, String text, {int id = 0})
: assert(window != null),
super(window) {
createPlatformView(window, text, id);
createPlatformView(window, text, id, 'scenarios/textPlatformView');
}
@override
......@@ -55,8 +55,8 @@ class MultiPlatformViewScenario extends Scenario with _BasePlatformViewScenarioM
MultiPlatformViewScenario(Window window, {this.firstId, this.secondId})
: assert(window != null),
super(window) {
createPlatformView(window, 'platform view 1', firstId);
createPlatformView(window, 'platform view 2', secondId);
createPlatformView(window, 'platform view 1', firstId, 'scenarios/textPlatformView');
createPlatformView(window, 'platform view 2', secondId, 'scenarios/textPlatformView');
}
/// The platform view identifier to use for the first platform view.
......@@ -91,8 +91,8 @@ class MultiPlatformViewBackgroundForegroundScenario extends Scenario with _BaseP
MultiPlatformViewBackgroundForegroundScenario(Window window, {this.firstId, this.secondId})
: assert(window != null),
super(window) {
createPlatformView(window, 'platform view 1', firstId);
createPlatformView(window, 'platform view 2', secondId);
createPlatformView(window, 'platform view 1', firstId, 'scenarios/textPlatformView');
createPlatformView(window, 'platform view 2', secondId, 'scenarios/textPlatformView');
_nextFrame = _firstFrame;
}
......@@ -177,7 +177,7 @@ class PlatformViewClipRectScenario extends Scenario with _BasePlatformViewScenar
PlatformViewClipRectScenario(Window window, String text, {int id = 0})
: assert(window != null),
super(window) {
createPlatformView(window, text, id);
createPlatformView(window, text, id, 'scenarios/textPlatformView');
}
@override
......@@ -281,6 +281,24 @@ class PlatformViewOpacityScenario extends PlatformViewScenario {
}
}
/// Platform view scenario for testing EAGLContext on iOS.
class PlatformViewGLScenario extends Scenario with _BasePlatformViewScenarioMixin {
/// Constructs a platform view to test EAGLContext on iOS.
PlatformViewGLScenario(Window window, String text, {int id = 0})
: assert(window != null),
super(window) {
createPlatformView(window, text, id, 'scenarios/glTestPlatformView');
}
@override
void onBeginFrame(Duration duration) {
final SceneBuilder builder = SceneBuilder();
builder.pushOffset(0, 0);
finishBuilderByAddingPlatformViewAndPicture(builder, 6);
}
}
mixin _BasePlatformViewScenarioMixin on Scenario {
int _textureId;
......@@ -289,7 +307,7 @@ mixin _BasePlatformViewScenarioMixin on Scenario {
/// It prepare a TextPlatformView so it can be added to the SceneBuilder in `onBeginFrame`.
/// Call this method in the constructor of the platform view related scenarios
/// to perform necessary set up.
void createPlatformView(Window window, String text, int id) {
void createPlatformView(Window window, String text, int id, String viewType) {
const int _valueInt32 = 3;
const int _valueFloat64 = 6;
const int _valueString = 7;
......@@ -313,8 +331,8 @@ mixin _BasePlatformViewScenarioMixin on Scenario {
'viewType'.length,
...utf8.encode('viewType'),
_valueString,
'scenarios/textPlatformView'.length,
...utf8.encode('scenarios/textPlatformView'),
viewType.length,
...utf8.encode(viewType),
if (Platform.isAndroid) ...<int>[
_valueString,
'width'.length,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册