未验证 提交 1482d9b0 编写于 作者: C Chris Yang 提交者: GitHub

Rework GLContextSwitch, get rid of RendererContextManager (#18601)

上级 4ce831e4
......@@ -575,6 +575,11 @@ FILE: ../../../flutter/shell/common/engine.cc
FILE: ../../../flutter/shell/common/engine.h
FILE: ../../../flutter/shell/common/fixtures/shell_test.dart
FILE: ../../../flutter/shell/common/fixtures/shelltest_screenshot.png
FILE: ../../../flutter/shell/common/gl_context_switch.cc
FILE: ../../../flutter/shell/common/gl_context_switch.h
FILE: ../../../flutter/shell/common/gl_context_switch_test.cc
FILE: ../../../flutter/shell/common/gl_context_switch_test.h
FILE: ../../../flutter/shell/common/gl_context_switch_unittests.cc
FILE: ../../../flutter/shell/common/input_events_unittests.cc
FILE: ../../../flutter/shell/common/isolate_configuration.cc
FILE: ../../../flutter/shell/common/isolate_configuration.h
......@@ -590,11 +595,6 @@ FILE: ../../../flutter/shell/common/pointer_data_dispatcher.cc
FILE: ../../../flutter/shell/common/pointer_data_dispatcher.h
FILE: ../../../flutter/shell/common/rasterizer.cc
FILE: ../../../flutter/shell/common/rasterizer.h
FILE: ../../../flutter/shell/common/renderer_context_manager.cc
FILE: ../../../flutter/shell/common/renderer_context_manager.h
FILE: ../../../flutter/shell/common/renderer_context_manager_unittests.cc
FILE: ../../../flutter/shell/common/renderer_context_test.cc
FILE: ../../../flutter/shell/common/renderer_context_test.h
FILE: ../../../flutter/shell/common/run_configuration.cc
FILE: ../../../flutter/shell/common/run_configuration.h
FILE: ../../../flutter/shell/common/shell.cc
......@@ -942,6 +942,8 @@ FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_metal.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_metal.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_software.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_software.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_switchable_gl_context.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_switchable_gl_context.mm
FILE: ../../../flutter/shell/platform/darwin/ios/platform_view_ios.h
FILE: ../../../flutter/shell/platform/darwin/ios/platform_view_ios.mm
FILE: ../../../flutter/shell/platform/darwin/ios/rendering_api_selection.h
......
......@@ -73,7 +73,7 @@ source_set("flow") {
deps = [
"//flutter/common",
"//flutter/fml",
"//flutter/shell/common:surface_frame",
"//flutter/shell/common:common_standalone",
"//third_party/skia",
]
......
......@@ -97,8 +97,6 @@ source_set("common") {
"pointer_data_dispatcher.h",
"rasterizer.cc",
"rasterizer.h",
"renderer_context_manager.cc",
"renderer_context_manager.h",
"run_configuration.cc",
"run_configuration.h",
"shell.cc",
......@@ -120,7 +118,7 @@ source_set("common") {
]
deps = [
":surface_frame",
":common_standalone",
"//flutter/assets",
"//flutter/common",
"//flutter/flow",
......@@ -142,8 +140,10 @@ source_set("common") {
public_configs = [ "//flutter:config" ]
}
source_set("surface_frame") {
source_set("common_standalone") {
sources = [
"gl_context_switch.cc",
"gl_context_switch.h",
"surface_frame.cc",
"surface_frame.h",
]
......@@ -203,8 +203,9 @@ if (enable_unittests) {
testonly = true
sources = [
"renderer_context_test.cc",
"renderer_context_test.h",
"gl_context_switch_test.cc",
"gl_context_switch_test.h",
"gl_context_switch_unittests.cc",
"shell_test.cc",
"shell_test.h",
"shell_test_external_view_embedder.cc",
......@@ -216,6 +217,7 @@ if (enable_unittests) {
]
public_deps = [
":common_standalone",
"//flutter/flow",
"//flutter/fml/dart",
"//flutter/lib/ui",
......@@ -267,7 +269,6 @@ if (enable_unittests) {
"input_events_unittests.cc",
"persistent_cache_unittests.cc",
"pipeline_unittests.cc",
"renderer_context_manager_unittests.cc",
"shell_unittests.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.h"
namespace flutter {
SwitchableGLContext::SwitchableGLContext() = default;
SwitchableGLContext::~SwitchableGLContext() = default;
GLContextResult::GLContextResult() = default;
GLContextResult::~GLContextResult() = default;
GLContextResult::GLContextResult(bool static_result) : result_(static_result){};
bool GLContextResult::GetResult() {
return result_;
};
GLContextDefaultResult::~GLContextDefaultResult() = default;
GLContextDefaultResult::GLContextDefaultResult(bool static_result)
: GLContextResult(static_result){};
GLContextSwitch::GLContextSwitch(std::unique_ptr<SwitchableGLContext> context)
: context_(std::move(context)) {
FML_CHECK(context_ != nullptr);
result_ = context_->SetCurrent();
};
GLContextSwitch::~GLContextSwitch() {
context_->RemoveCurrent();
};
} // 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_H_
#define FLUTTER_SHELL_COMMON_GL_CONTEXT_SWITCH_H_
#include <functional>
#include <memory>
#include <vector>
#include "flutter/fml/logging.h"
#include "flutter/fml/macros.h"
namespace flutter {
//------------------------------------------------------------------------------
/// An abstract class represents a gl context that can be switched by
/// GLContextSwitch
///
/// The subclass should wrap a "Context" object inside this class. For example,
/// in iOS while using GL rendering surface, the subclass should wrap an
/// |EAGLContext|.
class SwitchableGLContext {
public:
//------------------------------------------------------------------------------
/// Implement this to set the context wrapped by this |SwitchableGLContext|
/// object to the current context.
virtual bool SetCurrent() = 0;
//------------------------------------------------------------------------------
/// Implement this to remove the context wrapped by this |SwitchableGLContext|
/// object from current context;
virtual bool RemoveCurrent() = 0;
SwitchableGLContext();
virtual ~SwitchableGLContext();
FML_DISALLOW_COPY_AND_ASSIGN(SwitchableGLContext);
};
//------------------------------------------------------------------------------
/// Represents the result of setting a gl context.
/// This class exists because context results are used in places applies to all
/// the platforms. On certain platforms(for example lower end iOS devices that
/// uses gl), a |GLContextSwitch| is required to protect flutter's gl contect
/// from being polluted by other programs(embedded platform views). A
/// |GLContextSwitch| is a subclass of |GLContextResult|, which can be returned
/// on platforms that requires context switching. A |GLContextDefaultResult| is
/// also a subclass of |GLContextResult|, which can be returned on platforms
/// that doesn't require context switching.
class GLContextResult {
public:
GLContextResult();
virtual ~GLContextResult();
//----------------------------------------------------------------------------
// Returns true if the gl context is set successfully.
bool GetResult();
protected:
GLContextResult(bool static_result);
bool result_;
FML_DISALLOW_COPY_AND_ASSIGN(GLContextResult);
};
//------------------------------------------------------------------------------
/// The default implementation of |GLContextResult|.
///
/// Use this class on platforms that doesn't require gl context switching.
/// * See also |GLContextSwitch| if the platform requires gl context switching.
class GLContextDefaultResult : public GLContextResult {
public:
//----------------------------------------------------------------------------
/// Constructs a |GLContextDefaultResult| with a static result.
///
/// Used this on platforms that doesn't require gl context switching. (For
/// example, metal on iOS)
///
/// @param static_result a static value that will be returned from
/// |GetResult|
GLContextDefaultResult(bool static_result);
~GLContextDefaultResult() override;
FML_DISALLOW_COPY_AND_ASSIGN(GLContextDefaultResult);
};
//------------------------------------------------------------------------------
/// Switches the gl context to the a context that is passed in the
/// constructor.
///
/// In destruction, it should restore the current context to what was
/// before the construction of this switch.
class GLContextSwitch final : public GLContextResult {
public:
//----------------------------------------------------------------------------
/// Constructs a |GLContextSwitch|.
///
/// @param context The context that is going to be set as the current
/// context. The |GLContextSwitch| should not outlive the owner of the gl
/// context wrapped inside the `context`.
GLContextSwitch(std::unique_ptr<SwitchableGLContext> context);
~GLContextSwitch() override;
private:
std::unique_ptr<SwitchableGLContext> context_;
FML_DISALLOW_COPY_AND_ASSIGN(GLContextSwitch);
};
} // namespace flutter
#endif
......@@ -2,37 +2,41 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "renderer_context_test.h"
#include "gl_context_switch_test.h"
#include "flutter/fml/thread_local.h"
namespace flutter {
namespace testing {
FML_THREAD_LOCAL fml::ThreadLocalUniquePtr<int> current_context;
RendererContextTest::RendererContextTest() = default;
GLContextSwitchTest::GLContextSwitchTest() = default;
TestRendererContext::TestRendererContext(int context) : context_(context){};
TestSwitchableGLContext::TestSwitchableGLContext(int context)
: context_(context){};
TestRendererContext::~TestRendererContext() = default;
TestSwitchableGLContext::~TestSwitchableGLContext() = default;
bool TestRendererContext::SetCurrent() {
bool TestSwitchableGLContext::SetCurrent() {
SetCurrentContext(context_);
return true;
};
void TestRendererContext::RemoveCurrent() {
bool TestSwitchableGLContext::RemoveCurrent() {
SetCurrentContext(-1);
return true;
};
int TestRendererContext::GetContext() {
int TestSwitchableGLContext::GetContext() {
return context_;
};
int TestRendererContext::GetCurrentContext() {
int TestSwitchableGLContext::GetCurrentContext() {
return *(current_context.get());
};
void TestRendererContext::SetCurrentContext(int context) {
void TestSwitchableGLContext::SetCurrentContext(int context) {
current_context.reset(new int(context));
};
} // namespace testing
......
......@@ -5,37 +5,35 @@
#ifndef FLUTTER_SHELL_RENDERER_CONTEXT_TEST_H_
#define FLUTTER_SHELL_RENDERER_CONTEXT_TEST_H_
#include "flutter/fml/thread_local.h"
#include "gl_context_switch.h"
#include "gtest/gtest.h"
#include "renderer_context_manager.h"
namespace flutter {
namespace testing {
class RendererContextTest : public ::testing::Test {
class GLContextSwitchTest : public ::testing::Test {
public:
RendererContextTest();
GLContextSwitchTest();
};
//------------------------------------------------------------------------------
/// The renderer context used for testing
class TestRendererContext : public RendererContext {
class TestSwitchableGLContext : public SwitchableGLContext {
public:
TestRendererContext(int context);
TestSwitchableGLContext(int context);
~TestRendererContext() override;
~TestSwitchableGLContext() override;
bool SetCurrent() override;
void RemoveCurrent() override;
bool RemoveCurrent() override;
int GetContext();
static int GetCurrentContext();
//------------------------------------------------------------------------------
/// Set the current context without going through the
/// |RendererContextManager|.
/// Set the current context
///
/// This is to mimic how other programs outside flutter sets the context.
static void SetCurrentContext(int context);
......@@ -43,7 +41,7 @@ class TestRendererContext : public RendererContext {
private:
int context_;
FML_DISALLOW_COPY_AND_ASSIGN(TestRendererContext);
FML_DISALLOW_COPY_AND_ASSIGN(TestSwitchableGLContext);
};
} // namespace testing
} // 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.
#define FML_USED_ON_EMBEDDER
#include <functional>
#include <future>
#include <memory>
#include "flutter/shell/common/gl_context_switch.h"
#include "gl_context_switch_test.h"
#include "gtest/gtest.h"
namespace flutter {
namespace testing {
TEST_F(GLContextSwitchTest, SwitchKeepsContextCurrentWhileInScope) {
{
auto test_gl_context = std::make_unique<TestSwitchableGLContext>(0);
auto context_switch = GLContextSwitch(std::move(test_gl_context));
ASSERT_EQ(TestSwitchableGLContext::GetCurrentContext(), 0);
}
ASSERT_EQ(TestSwitchableGLContext::GetCurrentContext(), -1);
}
} // namespace testing
} // namespace flutter
......@@ -228,7 +228,8 @@ sk_sp<SkImage> Rasterizer::DoMakeRasterSnapshot(
result = DrawSnapshot(surface, draw_callback);
})
.SetIfFalse([&] {
if (!surface_->MakeRenderContextCurrent()) {
auto context_switch = surface_->MakeRenderContextCurrent();
if (!context_switch->GetResult()) {
return;
}
......
// 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 "renderer_context_manager.h"
namespace flutter {
RendererContext::RendererContext() = default;
RendererContext::~RendererContext() = default;
RendererContextManager::RendererContextManager(
std::unique_ptr<RendererContext> context,
std::unique_ptr<RendererContext> resource_context)
: context_(std::move(context)),
resource_context_(std::move(resource_context)){};
RendererContextManager::~RendererContextManager() = default;
RendererContextManager::RendererContextSwitch
RendererContextManager::MakeCurrent(std::unique_ptr<RendererContext> context) {
return RendererContextManager::RendererContextSwitch(*this,
std::move(context));
};
RendererContextManager::RendererContextSwitch
RendererContextManager::FlutterMakeCurrent() {
return MakeCurrent(std::move(context_));
};
RendererContextManager::RendererContextSwitch
RendererContextManager::FlutterResourceMakeCurrent() {
return MakeCurrent(std::move(resource_context_));
};
bool RendererContextManager::PushContext(
std::unique_ptr<RendererContext> context) {
if (current_ == nullptr) {
current_ = std::move(context);
return current_->SetCurrent();
}
stored_.push_back(std::move(current_));
bool result = context->SetCurrent();
current_ = std::move(context);
return result;
};
void RendererContextManager::PopContext() {
if (stored_.empty()) {
current_->RemoveCurrent();
return;
}
current_ = std::move(stored_.back());
current_->SetCurrent();
stored_.pop_back();
};
RendererContextManager::RendererContextSwitch::RendererContextSwitch(
RendererContextManager& manager,
std::unique_ptr<RendererContext> context)
: manager_(manager) {
bool result = manager_.PushContext(std::move(context));
result_ = result;
};
RendererContextManager::RendererContextSwitch::~RendererContextSwitch() {
manager_.PopContext();
};
bool RendererContextManager::RendererContextSwitch::GetResult() {
return 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_RENDERER_CONTEXT_MANAGER_H_
#define FLUTTER_SHELL_COMMON_RENDERER_CONTEXT_MANAGER_H_
#include <functional>
#include <memory>
#include <vector>
#include "flutter/fml/logging.h"
#include "flutter/fml/macros.h"
namespace flutter {
//------------------------------------------------------------------------------
/// An abstract class represents a renderer context
///
/// The subclass should wrap a "Context" object inside this class. For example,
/// in iOS while using GL rendering surface, the subclass should wrap an
/// |EAGLContext|.
class RendererContext {
public:
//------------------------------------------------------------------------------
/// Implement this to set the context wrapped by this |RendererContext| object
/// to the current context.
virtual bool SetCurrent() = 0;
//------------------------------------------------------------------------------
/// Implement this to remove the context wrapped by this |RendererContext|
/// object from current context;
virtual void RemoveCurrent() = 0;
RendererContext();
virtual ~RendererContext();
FML_DISALLOW_COPY_AND_ASSIGN(RendererContext);
};
//------------------------------------------------------------------------------
/// Manages the renderer context.
///
/// Initially, the |RendererContextManager| doesn't know any context that is set
/// by other programs (e.g. a plugin). To make sure not to pollute the other
/// context, use `MakeCurrent` to set other context, so |RendererContextManager|
/// has a reference of the other context. Ideally, this process has to be done
/// everytime before a context used by Flutter is set, if the current context at
/// the moment is not null or used by Flutter.
class RendererContextManager {
public:
//------------------------------------------------------------------------------
/// Switches the renderer context to the a context that is passed in the
/// constructor.
///
/// In destruction, it should reset the current context back to what was
/// before the construction of this switch.
///
class RendererContextSwitch {
public:
//----------------------------------------------------------------------------
/// Constructs a |RendererContextSwitch|.
///
/// @param manager A reference to the manager.
/// @param context The context that is going to be set as the current
/// context.
RendererContextSwitch(RendererContextManager& manager,
std::unique_ptr<RendererContext> context);
~RendererContextSwitch();
//----------------------------------------------------------------------------
// Returns true if the context switching was successful.
bool GetResult();
private:
RendererContextManager& manager_;
bool result_;
FML_DISALLOW_COPY_AND_ASSIGN(RendererContextSwitch);
};
RendererContextManager(std::unique_ptr<RendererContext> context,
std::unique_ptr<RendererContext> resource_context);
~RendererContextManager();
//----------------------------------------------------------------------------
/// @brief Make the `context` to be the current context. It can be used
/// to set a context set by other programs to be the current context in
/// |RendererContextManager|. Which make sure Flutter doesn't pollute other
/// contexts.
///
/// @return A `RendererContextSwitch` which ensures the `context` is the
/// current context.
RendererContextSwitch MakeCurrent(std::unique_ptr<RendererContext> context);
//----------------------------------------------------------------------------
/// @brief Make the context Flutter uses on the raster thread for
/// onscreen rendering to be the current context.
///
/// @return A `RendererContextSwitch` which ensures the current context is
/// the `context` that used in the constructor.
RendererContextSwitch FlutterMakeCurrent();
//----------------------------------------------------------------------------
/// @brief Make the context Flutter uses for performing texture upload on
/// the IO thread to be the current context.
///
/// @return A `RendererContextSwitch` which ensures the current context is
/// the `resource_context` that used in the constructor.
RendererContextSwitch FlutterResourceMakeCurrent();
private:
std::unique_ptr<RendererContext> context_;
std::unique_ptr<RendererContext> resource_context_;
std::unique_ptr<RendererContext> current_;
std::vector<std::unique_ptr<RendererContext>> stored_;
bool PushContext(std::unique_ptr<RendererContext> context);
void PopContext();
FML_DISALLOW_COPY_AND_ASSIGN(RendererContextManager);
};
} // namespace flutter
#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.
#define FML_USED_ON_EMBEDDER
#include <functional>
#include <future>
#include <memory>
#include "flutter/shell/common/renderer_context_manager.h"
#include "gtest/gtest.h"
#include "renderer_context_test.h"
namespace flutter {
namespace testing {
TEST_F(RendererContextTest, StartWithNoContextFlutterMakeCurrent) {
auto flutter_context = std::make_unique<TestRendererContext>(0);
auto flutter_resource_context = std::make_unique<TestRendererContext>(1);
RendererContextManager manager(std::move(flutter_context),
std::move(flutter_resource_context));
// started with current_context as -1
TestRendererContext::SetCurrentContext(-1);
ASSERT_EQ(TestRendererContext::GetCurrentContext(), -1);
{
// made flutter context to be the current
auto context_switch = manager.FlutterMakeCurrent();
ASSERT_EQ(TestRendererContext::GetCurrentContext(), 0);
}
// flutter context is popped
ASSERT_EQ(TestRendererContext::GetCurrentContext(), -1);
}
TEST_F(RendererContextTest, StartWithNoContextFlutterResourceMakeCurrent) {
auto flutter_context = std::make_unique<TestRendererContext>(0);
auto flutter_resource_context = std::make_unique<TestRendererContext>(1);
RendererContextManager manager(std::move(flutter_context),
std::move(flutter_resource_context));
// started with current_context as -1
TestRendererContext::SetCurrentContext(-1);
ASSERT_EQ(TestRendererContext::GetCurrentContext(), -1);
{
// made resource context to be the current
auto context_switch = manager.FlutterResourceMakeCurrent();
ASSERT_EQ(TestRendererContext::GetCurrentContext(), 1);
}
// flutter context is popped
ASSERT_EQ(TestRendererContext::GetCurrentContext(), -1);
}
TEST_F(RendererContextTest, StartWithSomeContextFlutterMakeCurrent) {
auto flutter_context = std::make_unique<TestRendererContext>(0);
auto flutter_resource_context = std::make_unique<TestRendererContext>(1);
auto some_context = std::make_unique<TestRendererContext>(2);
RendererContextManager manager(std::move(flutter_context),
std::move(flutter_resource_context));
// started with some_context
auto context_switch = manager.MakeCurrent(std::move(some_context));
ASSERT_EQ(TestRendererContext::GetCurrentContext(), 2);
{
// made flutter context to be the current
auto context_switch2 = manager.FlutterMakeCurrent();
ASSERT_EQ(TestRendererContext::GetCurrentContext(), 0);
}
// flutter context is popped
ASSERT_EQ(TestRendererContext::GetCurrentContext(), 2);
}
TEST_F(RendererContextTest, StartWithSomeContextFlutterResourceMakeCurrent) {
auto flutter_context = std::make_unique<TestRendererContext>(0);
auto flutter_resource_context = std::make_unique<TestRendererContext>(1);
auto some_context = std::make_unique<TestRendererContext>(2);
RendererContextManager manager(std::move(flutter_context),
std::move(flutter_resource_context));
// started with some_context
auto context_switch = manager.MakeCurrent(std::move(some_context));
ASSERT_EQ(TestRendererContext::GetCurrentContext(), 2);
{
// made resource context to be the current
auto context_switch2 = manager.FlutterResourceMakeCurrent();
ASSERT_EQ(TestRendererContext::GetCurrentContext(), 1);
}
// flutter context is popped
ASSERT_EQ(TestRendererContext::GetCurrentContext(), 2);
}
TEST_F(RendererContextTest, Nested) {
auto flutter_context = std::make_unique<TestRendererContext>(0);
auto flutter_resource_context = std::make_unique<TestRendererContext>(1);
auto some_context = std::make_unique<TestRendererContext>(2);
RendererContextManager manager(std::move(flutter_context),
std::move(flutter_resource_context));
// started with some_context
auto context_switch = manager.MakeCurrent(std::move(some_context));
ASSERT_EQ(TestRendererContext::GetCurrentContext(), 2);
{
// made flutter context to be the current
auto context_switch2 = manager.FlutterMakeCurrent();
ASSERT_EQ(TestRendererContext::GetCurrentContext(), 0);
{
// made resource context to be the current
auto context_switch2 = manager.FlutterResourceMakeCurrent();
ASSERT_EQ(TestRendererContext::GetCurrentContext(), 1);
}
// resource context is popped
ASSERT_EQ(TestRendererContext::GetCurrentContext(), 0);
}
// flutter context is popped
ASSERT_EQ(TestRendererContext::GetCurrentContext(), 2);
}
} // namespace testing
} // namespace flutter
......@@ -44,8 +44,9 @@ PointerDataDispatcherMaker ShellTestPlatformViewGL::GetDispatcherMaker() {
}
// |GPUSurfaceGLDelegate|
bool ShellTestPlatformViewGL::GLContextMakeCurrent() {
return gl_surface_.MakeCurrent();
std::unique_ptr<GLContextResult>
ShellTestPlatformViewGL::GLContextMakeCurrent() {
return std::make_unique<GLContextDefaultResult>(gl_surface_.MakeCurrent());
}
// |GPUSurfaceGLDelegate|
......
......@@ -47,7 +47,7 @@ class ShellTestPlatformViewGL : public ShellTestPlatformView,
PointerDataDispatcherMaker GetDispatcherMaker() override;
// |GPUSurfaceGLDelegate|
bool GLContextMakeCurrent() override;
std::unique_ptr<GLContextResult> GLContextMakeCurrent() override;
// |GPUSurfaceGLDelegate|
bool GLContextClearCurrent() override;
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "flutter/shell/common/shell_test_platform_view_vulkan.h"
#include "flutter/shell/common/gl_context_switch.h"
#include "flutter/vulkan/vulkan_utilities.h"
namespace flutter {
......
......@@ -14,8 +14,8 @@ flutter::ExternalViewEmbedder* Surface::GetExternalViewEmbedder() {
return nullptr;
}
bool Surface::MakeRenderContextCurrent() {
return true;
std::unique_ptr<GLContextResult> Surface::MakeRenderContextCurrent() {
return std::make_unique<GLContextDefaultResult>(true);
}
} // namespace flutter
......@@ -31,7 +31,7 @@ class Surface {
virtual flutter::ExternalViewEmbedder* GetExternalViewEmbedder();
virtual bool MakeRenderContextCurrent();
virtual std::unique_ptr<GLContextResult> MakeRenderContextCurrent();
private:
FML_DISALLOW_COPY_AND_ASSIGN(Surface);
......
......@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "flutter/shell/common/surface_frame.h"
#include "flutter/fml/logging.h"
namespace flutter {
......@@ -17,6 +16,18 @@ SurfaceFrame::SurfaceFrame(sk_sp<SkSurface> surface,
FML_DCHECK(submit_callback_);
}
SurfaceFrame::SurfaceFrame(sk_sp<SkSurface> surface,
bool supports_readback,
const SubmitCallback& submit_callback,
std::unique_ptr<GLContextResult> context_result)
: submitted_(false),
surface_(surface),
supports_readback_(supports_readback),
submit_callback_(submit_callback),
context_result_(std::move(context_result)) {
FML_DCHECK(submit_callback_);
}
SurfaceFrame::~SurfaceFrame() {
if (submit_callback_ && !submitted_) {
// Dropping without a Submit.
......
......@@ -8,6 +8,7 @@
#include <memory>
#include "flutter/fml/macros.h"
#include "flutter/shell/common/gl_context_switch.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkSurface.h"
......@@ -24,6 +25,11 @@ class SurfaceFrame {
bool supports_readback,
const SubmitCallback& submit_callback);
SurfaceFrame(sk_sp<SkSurface> surface,
bool supports_readback,
const SubmitCallback& submit_callback,
std::unique_ptr<GLContextResult> context_result);
~SurfaceFrame();
bool Submit();
......@@ -41,6 +47,7 @@ class SurfaceFrame {
sk_sp<SkSurface> surface_;
bool supports_readback_;
SubmitCallback submit_callback_;
std::unique_ptr<GLContextResult> context_result_;
bool PerformSubmit();
......
......@@ -11,6 +11,7 @@ gpu_common_deps = [
"//flutter/flow",
"//flutter/fml",
"//flutter/shell/common",
"//flutter/shell/common:common_standalone",
"//third_party/skia",
]
......
......@@ -39,7 +39,8 @@ GPUSurfaceGL::GPUSurfaceGL(GPUSurfaceGLDelegate* delegate,
: delegate_(delegate),
render_to_surface_(render_to_surface),
weak_factory_(this) {
if (!delegate_->GLContextMakeCurrent()) {
auto context_switch = delegate_->GLContextMakeCurrent();
if (!context_switch->GetResult()) {
FML_LOG(ERROR)
<< "Could not make the context current to setup the gr context.";
return;
......@@ -98,7 +99,8 @@ GPUSurfaceGL::GPUSurfaceGL(sk_sp<GrContext> gr_context,
context_(gr_context),
render_to_surface_(render_to_surface),
weak_factory_(this) {
if (!delegate_->GLContextMakeCurrent()) {
auto context_switch = delegate_->GLContextMakeCurrent();
if (!context_switch->GetResult()) {
FML_LOG(ERROR)
<< "Could not make the context current to setup the gr context.";
return;
......@@ -114,8 +116,8 @@ GPUSurfaceGL::~GPUSurfaceGL() {
if (!valid_) {
return;
}
if (!delegate_->GLContextMakeCurrent()) {
auto context_switch = delegate_->GLContextMakeCurrent();
if (!context_switch->GetResult()) {
FML_LOG(ERROR) << "Could not make the context current to destroy the "
"GrContext resources.";
return;
......@@ -229,8 +231,8 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceGL::AcquireFrame(const SkISize& size) {
if (delegate_ == nullptr) {
return nullptr;
}
if (!delegate_->GLContextMakeCurrent()) {
auto context_switch = delegate_->GLContextMakeCurrent();
if (!context_switch->GetResult()) {
FML_LOG(ERROR)
<< "Could not make the context current to acquire the frame.";
return nullptr;
......@@ -255,7 +257,6 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceGL::AcquireFrame(const SkISize& size) {
}
surface->getCanvas()->setMatrix(root_surface_transformation);
SurfaceFrame::SubmitCallback submit_callback =
[weak = weak_factory_.GetWeakPtr()](const SurfaceFrame& surface_frame,
SkCanvas* canvas) {
......@@ -263,7 +264,8 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceGL::AcquireFrame(const SkISize& size) {
};
return std::make_unique<SurfaceFrame>(
surface, delegate_->SurfaceSupportsReadback(), submit_callback);
surface, delegate_->SurfaceSupportsReadback(), submit_callback,
std::move(context_switch));
}
bool GPUSurfaceGL::PresentSurface(SkCanvas* canvas) {
......@@ -329,7 +331,7 @@ flutter::ExternalViewEmbedder* GPUSurfaceGL::GetExternalViewEmbedder() {
}
// |Surface|
bool GPUSurfaceGL::MakeRenderContextCurrent() {
std::unique_ptr<GLContextResult> GPUSurfaceGL::MakeRenderContextCurrent() {
return delegate_->GLContextMakeCurrent();
}
......
......@@ -11,6 +11,7 @@
#include "flutter/flow/embedded_views.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/shell/common/gl_context_switch.h"
#include "flutter/shell/common/surface.h"
#include "flutter/shell/gpu/gpu_surface_gl_delegate.h"
#include "third_party/skia/include/gpu/GrContext.h"
......@@ -45,7 +46,7 @@ class GPUSurfaceGL : public Surface {
flutter::ExternalViewEmbedder* GetExternalViewEmbedder() override;
// |Surface|
bool MakeRenderContextCurrent() override;
std::unique_ptr<GLContextResult> 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.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"
......@@ -21,7 +22,7 @@ class GPUSurfaceGLDelegate : public GPUSurfaceDelegate {
ExternalViewEmbedder* GetExternalViewEmbedder() override;
// Called to make the main GL context current on the current thread.
virtual bool GLContextMakeCurrent() = 0;
virtual std::unique_ptr<GLContextResult> GLContextMakeCurrent() = 0;
// Called to clear the current GL context on the thread. This may be called on
// either the GPU or IO threads.
......
......@@ -50,7 +50,7 @@ class GPUSurfaceMetal : public Surface {
flutter::ExternalViewEmbedder* GetExternalViewEmbedder() override;
// |Surface|
bool MakeRenderContextCurrent() override;
std::unique_ptr<GLContextResult> MakeRenderContextCurrent() override;
void ReleaseUnusedDrawableIfNecessary();
......
......@@ -127,9 +127,9 @@ flutter::ExternalViewEmbedder* GPUSurfaceMetal::GetExternalViewEmbedder() {
}
// |Surface|
bool GPUSurfaceMetal::MakeRenderContextCurrent() {
std::unique_ptr<GLContextResult> GPUSurfaceMetal::MakeRenderContextCurrent() {
// This backend has no such concept.
return true;
return std::make_unique<GLContextDefaultResult>(true);
}
void GPUSurfaceMetal::ReleaseUnusedDrawableIfNecessary() {
......
......@@ -106,9 +106,11 @@ bool AndroidSurfaceGL::SetNativeWindow(
return true;
}
bool AndroidSurfaceGL::GLContextMakeCurrent() {
std::unique_ptr<GLContextResult> AndroidSurfaceGL::GLContextMakeCurrent() {
FML_DCHECK(onscreen_context_ && onscreen_context_->IsValid());
return onscreen_context_->MakeCurrent();
auto default_context_result = std::make_unique<GLContextDefaultResult>(
onscreen_context_->MakeCurrent());
return std::move(default_context_result);
}
bool AndroidSurfaceGL::GLContextClearCurrent() {
......
......@@ -48,7 +48,7 @@ class AndroidSurfaceGL final : public GPUSurfaceGLDelegate,
bool SetNativeWindow(fml::RefPtr<AndroidNativeWindow> window) override;
// |GPUSurfaceGLDelegate|
bool GLContextMakeCurrent() override;
std::unique_ptr<GLContextResult> GLContextMakeCurrent() override;
// |GPUSurfaceGLDelegate|
bool GLContextClearCurrent() override;
......
......@@ -98,6 +98,8 @@ source_set("flutter_framework_source") {
"ios_surface_gl.mm",
"ios_surface_software.h",
"ios_surface_software.mm",
"ios_switchable_gl_context.h",
"ios_switchable_gl_context.mm",
"platform_view_ios.h",
"platform_view_ios.mm",
"rendering_api_selection.h",
......@@ -130,6 +132,7 @@ source_set("flutter_framework_source") {
"//flutter/runtime",
"//flutter/runtime:libdart",
"//flutter/shell/common",
"//flutter/shell/common:common_standalone",
"//flutter/shell/platform/darwin/common",
"//flutter/shell/platform/darwin/common:framework_shared",
"//flutter/shell/profiling:profiling",
......
......@@ -10,6 +10,7 @@
#include "flutter/flow/texture.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/common/gl_context_switch.h"
#include "flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h"
#include "flutter/shell/platform/darwin/ios/rendering_api_selection.h"
#include "third_party/skia/include/gpu/GrContext.h"
......@@ -84,9 +85,12 @@ class IOSContext {
/// @attention Only one context may be bound to a thread at any given time.
/// Making a binding on a thread, clears the old binding.
///
/// @return If the on-screen context could be bound to the current thread.
/// @return A GLContextResult that represents the result of the method.
/// The GetResult() returns a bool that indicates If the on-screen context could be
/// bound to the current
/// thread.
///
virtual bool MakeCurrent() = 0;
virtual std::unique_ptr<GLContextResult> MakeCurrent() = 0;
//----------------------------------------------------------------------------
/// @brief Creates an external texture proxy of the appropriate client
......
......@@ -9,6 +9,7 @@
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/platform/darwin/ios/ios_context.h"
#include "flutter/shell/platform/darwin/ios/ios_context_gl.h"
#include "flutter/shell/platform/darwin/ios/ios_render_target_gl.h"
@class CAEAGLLayer;
......@@ -32,7 +33,7 @@ class IOSContextGL final : public IOSContext {
sk_sp<GrContext> CreateResourceContext() override;
// |IOSContext|
bool MakeCurrent() override;
std::unique_ptr<GLContextResult> MakeCurrent() override;
// |IOSContext|
std::unique_ptr<Texture> CreateExternalTexture(
......
......@@ -28,7 +28,7 @@ IOSContextGL::~IOSContextGL() = default;
std::unique_ptr<IOSRenderTargetGL> IOSContextGL::CreateRenderTarget(
fml::scoped_nsobject<CAEAGLLayer> layer) {
return std::make_unique<IOSRenderTargetGL>(std::move(layer), context_, resource_context_);
return std::make_unique<IOSRenderTargetGL>(std::move(layer), context_);
}
// |IOSContext|
......@@ -44,8 +44,9 @@ sk_sp<GrContext> IOSContextGL::CreateResourceContext() {
}
// |IOSContext|
bool IOSContextGL::MakeCurrent() {
return [EAGLContext setCurrentContext:context_.get()];
std::unique_ptr<GLContextResult> IOSContextGL::MakeCurrent() {
return std::make_unique<GLContextSwitch>(
std::make_unique<IOSSwitchableGLContext>(context_.get()));
}
// |IOSContext|
......
......@@ -43,7 +43,7 @@ class IOSContextMetal final : public IOSContext {
sk_sp<GrContext> CreateResourceContext() override;
// |IOSContext|
bool MakeCurrent() override;
std::unique_ptr<GLContextResult> MakeCurrent() override;
// |IOSContext|
std::unique_ptr<Texture> CreateExternalTexture(
......
......@@ -96,9 +96,9 @@ sk_sp<GrContext> IOSContextMetal::CreateResourceContext() {
}
// |IOSContext|
bool IOSContextMetal::MakeCurrent() {
std::unique_ptr<GLContextResult> IOSContextMetal::MakeCurrent() {
// This only makes sense for context that need to be bound to a specific thread.
return true;
return std::make_unique<GLContextDefaultResult>(true);
}
// |IOSContext|
......
......@@ -21,7 +21,7 @@ class IOSContextSoftware final : public IOSContext {
sk_sp<GrContext> CreateResourceContext() override;
// |IOSContext|
bool MakeCurrent() override;
std::unique_ptr<GLContextResult> MakeCurrent() override;
// |IOSContext|
std::unique_ptr<Texture> CreateExternalTexture(
......
......@@ -17,8 +17,9 @@ sk_sp<GrContext> IOSContextSoftware::CreateResourceContext() {
}
// |IOSContext|
bool IOSContextSoftware::MakeCurrent() {
return false;
std::unique_ptr<GLContextResult> IOSContextSoftware::MakeCurrent() {
// This only makes sense for context that need to be bound to a specific thread.
return std::make_unique<GLContextDefaultResult>(false);
}
// |IOSContext|
......
......@@ -13,14 +13,14 @@
#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_switchable_gl_context.h"
namespace flutter {
class IOSRenderTargetGL {
public:
IOSRenderTargetGL(fml::scoped_nsobject<CAEAGLLayer> layer,
fml::scoped_nsobject<EAGLContext> context,
fml::scoped_nsobject<EAGLContext> resource_context);
fml::scoped_nsobject<EAGLContext> context_);
~IOSRenderTargetGL();
......@@ -35,7 +35,6 @@ class IOSRenderTargetGL {
private:
fml::scoped_nsobject<CAEAGLLayer> layer_;
fml::scoped_nsobject<EAGLContext> context_;
fml::scoped_nsobject<EAGLContext> resource_context_;
GLuint framebuffer_ = GL_NONE;
GLuint colorbuffer_ = GL_NONE;
GLint storage_size_width_ = GL_NONE;
......
......@@ -13,20 +13,16 @@
namespace flutter {
IOSRenderTargetGL::IOSRenderTargetGL(fml::scoped_nsobject<CAEAGLLayer> layer,
fml::scoped_nsobject<EAGLContext> context,
fml::scoped_nsobject<EAGLContext> resource_context)
: layer_(std::move(layer)),
context_(std::move(context)),
resource_context_(std::move(resource_context)) {
fml::scoped_nsobject<EAGLContext> context)
: layer_(std::move(layer)), context_(context) {
FML_DCHECK(layer_ != nullptr);
FML_DCHECK(context_ != nullptr);
FML_DCHECK(resource_context_ != nullptr);
if (@available(iOS 9.0, *)) {
[layer_ setPresentsWithTransaction:YES];
}
bool context_current = [EAGLContext setCurrentContext:context_];
auto context_switch = GLContextSwitch(std::make_unique<IOSSwitchableGLContext>(context_.get()));
bool context_current = context_switch.GetResult();
FML_DCHECK(context_current);
FML_DCHECK(glGetError() == GL_NO_ERROR);
......@@ -61,8 +57,7 @@ IOSRenderTargetGL::IOSRenderTargetGL(fml::scoped_nsobject<CAEAGLLayer> layer,
}
IOSRenderTargetGL::~IOSRenderTargetGL() {
EAGLContext* context = EAGLContext.currentContext;
[EAGLContext setCurrentContext:context_];
auto context_switch = GLContextSwitch(std::make_unique<IOSSwitchableGLContext>(context_.get()));
FML_DCHECK(glGetError() == GL_NO_ERROR);
// Deletes on GL_NONEs are ignored
......@@ -70,11 +65,6 @@ IOSRenderTargetGL::~IOSRenderTargetGL() {
glDeleteRenderbuffers(1, &colorbuffer_);
FML_DCHECK(glGetError() == GL_NO_ERROR);
if (context == context_.get()) {
[EAGLContext setCurrentContext:nil];
} else {
[EAGLContext setCurrentContext:context];
}
}
// |IOSRenderTarget|
......@@ -118,7 +108,8 @@ bool IOSRenderTargetGL::UpdateStorageSizeIfNecessary() {
FML_DCHECK(glGetError() == GL_NO_ERROR);
if (![EAGLContext setCurrentContext:context_]) {
auto context_switch = GLContextSwitch(std::make_unique<IOSSwitchableGLContext>(context_.get()));
if (!context_switch.GetResult()) {
return false;
}
......@@ -129,7 +120,8 @@ bool IOSRenderTargetGL::UpdateStorageSizeIfNecessary() {
glBindRenderbuffer(GL_RENDERBUFFER, colorbuffer_);
FML_DCHECK(glGetError() == GL_NO_ERROR);
if (![context_.get() renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer_.get()]) {
auto current_context = [EAGLContext currentContext];
if (![current_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer_.get()]) {
return false;
}
......
......@@ -34,7 +34,7 @@ class IOSSurfaceGL final : public IOSSurface, public GPUSurfaceGLDelegate {
std::unique_ptr<Surface> CreateGPUSurface(GrContext* gr_context) override;
// |GPUSurfaceGLDelegate|
bool GLContextMakeCurrent() override;
std::unique_ptr<GLContextResult> GLContextMakeCurrent() override;
// |GPUSurfaceGLDelegate|
bool GLContextClearCurrent() override;
......
......@@ -59,16 +59,20 @@ bool IOSSurfaceGL::SurfaceSupportsReadback() const {
}
// |GPUSurfaceGLDelegate|
bool IOSSurfaceGL::GLContextMakeCurrent() {
std::unique_ptr<GLContextResult> IOSSurfaceGL::GLContextMakeCurrent() {
if (!IsValid()) {
return false;
return std::make_unique<GLContextDefaultResult>(false);
}
return render_target_->UpdateStorageSizeIfNecessary() && GetContext()->MakeCurrent();
bool update_if_necessary = render_target_->UpdateStorageSizeIfNecessary();
if (!update_if_necessary) {
return std::make_unique<GLContextDefaultResult>(false);
}
return GetContext()->MakeCurrent();
}
// |GPUSurfaceGLDelegate|
bool IOSSurfaceGL::GLContextClearCurrent() {
[EAGLContext setCurrentContext:nil];
// |GLContextMakeCurrent| should handle the scope of the gl context.
return true;
}
......
// 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_SWITCHABLE_GL_CONTEXT_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_SWITCHABLE_GL_CONTEXT_H_
#include "flutter/fml/macros.h"
#include "flutter/fml/memory/thread_checker.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/shell/common/gl_context_switch.h"
@class EAGLContext;
namespace flutter {
//------------------------------------------------------------------------------
/// The iOS implementation of a |SwitchableGLContext|.
///
/// It wraps a pointer to an EAGLContext. When passed in the constructor of the |GLContextSwitch|,
/// this EAGLContext is set to current. When the |GLContextSwitch| destroys, the current context
/// will be restored to the context before setting this EAGLContext to current.
///
/// Note: An |IOSSwitchableGLContext| doesn't retain the EAGLContext. Someone else must retain the
/// pointer and outlive all the |IOSSwitchableGLContext|. This object is meant to be only owned by a
/// |GLContextSwitch| and should be destroyed when The |GLContectSwitch| destroys.
class IOSSwitchableGLContext final : public SwitchableGLContext {
public:
IOSSwitchableGLContext(EAGLContext* context);
bool SetCurrent() override;
bool RemoveCurrent() override;
private:
// These pointers are managed by IOSRendererTarget/IOSContextGL or a 3rd party
// plugin that uses gl context. |IOSSwitchableGLContext| should never outlive
// those objects. Never release this pointer within this object.
EAGLContext* context_;
EAGLContext* previous_context_;
FML_DECLARE_THREAD_CHECKER(checker);
FML_DISALLOW_COPY_AND_ASSIGN(IOSSwitchableGLContext);
};
} // namespace flutter
#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 "flutter/shell/platform/darwin/ios/ios_switchable_gl_context.h"
#import <OpenGLES/EAGL.h>
namespace flutter {
IOSSwitchableGLContext::IOSSwitchableGLContext(EAGLContext* context) : context_(context){};
bool IOSSwitchableGLContext::SetCurrent() {
FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker);
FML_DCHECK(context_ != nullptr);
EAGLContext* current_context = EAGLContext.currentContext;
previous_context_ = current_context;
return [EAGLContext setCurrentContext:context_];
};
bool IOSSwitchableGLContext::RemoveCurrent() {
FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker);
return [EAGLContext setCurrentContext:previous_context_];
};
}
......@@ -34,8 +34,9 @@ bool EmbedderSurfaceGL::IsValid() const {
}
// |GPUSurfaceGLDelegate|
bool EmbedderSurfaceGL::GLContextMakeCurrent() {
return gl_dispatch_table_.gl_make_current_callback();
std::unique_ptr<GLContextResult> EmbedderSurfaceGL::GLContextMakeCurrent() {
return std::make_unique<GLContextDefaultResult>(
gl_dispatch_table_.gl_make_current_callback());
}
// |GPUSurfaceGLDelegate|
......
......@@ -50,7 +50,7 @@ class EmbedderSurfaceGL final : public EmbedderSurface,
sk_sp<GrContext> CreateResourceContext() const override;
// |GPUSurfaceGLDelegate|
bool GLContextMakeCurrent() override;
std::unique_ptr<GLContextResult> GLContextMakeCurrent() override;
// |GPUSurfaceGLDelegate|
bool GLContextClearCurrent() override;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册