diff --git a/engine/src/flutter/ci/licenses_golden/licenses_flutter b/engine/src/flutter/ci/licenses_golden/licenses_flutter index ae492384075..15d16e9c87d 100755 --- a/engine/src/flutter/ci/licenses_golden/licenses_flutter +++ b/engine/src/flutter/ci/licenses_golden/licenses_flutter @@ -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 diff --git a/engine/src/flutter/flow/BUILD.gn b/engine/src/flutter/flow/BUILD.gn index c21ba807803..d1fd1a5e740 100644 --- a/engine/src/flutter/flow/BUILD.gn +++ b/engine/src/flutter/flow/BUILD.gn @@ -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", ] diff --git a/engine/src/flutter/shell/common/BUILD.gn b/engine/src/flutter/shell/common/BUILD.gn index cd1e40608b9..37fa98cb1f7 100644 --- a/engine/src/flutter/shell/common/BUILD.gn +++ b/engine/src/flutter/shell/common/BUILD.gn @@ -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", ] diff --git a/engine/src/flutter/shell/common/gl_context_switch.cc b/engine/src/flutter/shell/common/gl_context_switch.cc new file mode 100644 index 00000000000..dae9c310811 --- /dev/null +++ b/engine/src/flutter/shell/common/gl_context_switch.cc @@ -0,0 +1,34 @@ +// 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 context) + : context_(std::move(context)) { + FML_CHECK(context_ != nullptr); + result_ = context_->SetCurrent(); +}; + +GLContextSwitch::~GLContextSwitch() { + context_->RemoveCurrent(); +}; + +} // namespace flutter diff --git a/engine/src/flutter/shell/common/gl_context_switch.h b/engine/src/flutter/shell/common/gl_context_switch.h new file mode 100644 index 00000000000..daec16fdbc0 --- /dev/null +++ b/engine/src/flutter/shell/common/gl_context_switch.h @@ -0,0 +1,117 @@ +// 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 +#include +#include + +#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 context); + + ~GLContextSwitch() override; + + private: + std::unique_ptr context_; + + FML_DISALLOW_COPY_AND_ASSIGN(GLContextSwitch); +}; + +} // namespace flutter + +#endif diff --git a/engine/src/flutter/shell/common/gl_context_switch_test.cc b/engine/src/flutter/shell/common/gl_context_switch_test.cc new file mode 100644 index 00000000000..0fd02f82332 --- /dev/null +++ b/engine/src/flutter/shell/common/gl_context_switch_test.cc @@ -0,0 +1,43 @@ +// 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_test.h" + +#include "flutter/fml/thread_local.h" + +namespace flutter { +namespace testing { + +FML_THREAD_LOCAL fml::ThreadLocalUniquePtr current_context; + +GLContextSwitchTest::GLContextSwitchTest() = default; + +TestSwitchableGLContext::TestSwitchableGLContext(int context) + : context_(context){}; + +TestSwitchableGLContext::~TestSwitchableGLContext() = default; + +bool TestSwitchableGLContext::SetCurrent() { + SetCurrentContext(context_); + return true; +}; + +bool TestSwitchableGLContext::RemoveCurrent() { + SetCurrentContext(-1); + return true; +}; + +int TestSwitchableGLContext::GetContext() { + return context_; +}; + +int TestSwitchableGLContext::GetCurrentContext() { + return *(current_context.get()); +}; + +void TestSwitchableGLContext::SetCurrentContext(int context) { + current_context.reset(new int(context)); +}; +} // namespace testing +} // namespace flutter diff --git a/engine/src/flutter/shell/common/renderer_context_test.h b/engine/src/flutter/shell/common/gl_context_switch_test.h similarity index 66% rename from engine/src/flutter/shell/common/renderer_context_test.h rename to engine/src/flutter/shell/common/gl_context_switch_test.h index 7225c8a237e..38b4fb7cd10 100644 --- a/engine/src/flutter/shell/common/renderer_context_test.h +++ b/engine/src/flutter/shell/common/gl_context_switch_test.h @@ -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 diff --git a/engine/src/flutter/shell/common/gl_context_switch_unittests.cc b/engine/src/flutter/shell/common/gl_context_switch_unittests.cc new file mode 100644 index 00000000000..bb5f761b868 --- /dev/null +++ b/engine/src/flutter/shell/common/gl_context_switch_unittests.cc @@ -0,0 +1,27 @@ +// 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 +#include +#include + +#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(0); + auto context_switch = GLContextSwitch(std::move(test_gl_context)); + ASSERT_EQ(TestSwitchableGLContext::GetCurrentContext(), 0); + } + ASSERT_EQ(TestSwitchableGLContext::GetCurrentContext(), -1); +} + +} // namespace testing +} // namespace flutter diff --git a/engine/src/flutter/shell/common/rasterizer.cc b/engine/src/flutter/shell/common/rasterizer.cc index e992f801d1f..4bf5139f333 100644 --- a/engine/src/flutter/shell/common/rasterizer.cc +++ b/engine/src/flutter/shell/common/rasterizer.cc @@ -228,7 +228,8 @@ sk_sp Rasterizer::DoMakeRasterSnapshot( result = DrawSnapshot(surface, draw_callback); }) .SetIfFalse([&] { - if (!surface_->MakeRenderContextCurrent()) { + auto context_switch = surface_->MakeRenderContextCurrent(); + if (!context_switch->GetResult()) { return; } diff --git a/engine/src/flutter/shell/common/renderer_context_manager.cc b/engine/src/flutter/shell/common/renderer_context_manager.cc deleted file mode 100644 index a544df5cbf5..00000000000 --- a/engine/src/flutter/shell/common/renderer_context_manager.cc +++ /dev/null @@ -1,74 +0,0 @@ -// 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 context, - std::unique_ptr resource_context) - : context_(std::move(context)), - resource_context_(std::move(resource_context)){}; - -RendererContextManager::~RendererContextManager() = default; - -RendererContextManager::RendererContextSwitch -RendererContextManager::MakeCurrent(std::unique_ptr 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 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 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 diff --git a/engine/src/flutter/shell/common/renderer_context_manager.h b/engine/src/flutter/shell/common/renderer_context_manager.h deleted file mode 100644 index bfdc8e543f4..00000000000 --- a/engine/src/flutter/shell/common/renderer_context_manager.h +++ /dev/null @@ -1,131 +0,0 @@ -// 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 -#include -#include - -#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 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 context, - std::unique_ptr 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 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 context_; - std::unique_ptr resource_context_; - - std::unique_ptr current_; - - std::vector> stored_; - - bool PushContext(std::unique_ptr context); - void PopContext(); - - FML_DISALLOW_COPY_AND_ASSIGN(RendererContextManager); -}; - -} // namespace flutter - -#endif diff --git a/engine/src/flutter/shell/common/renderer_context_manager_unittests.cc b/engine/src/flutter/shell/common/renderer_context_manager_unittests.cc deleted file mode 100644 index b3c695a8e9b..00000000000 --- a/engine/src/flutter/shell/common/renderer_context_manager_unittests.cc +++ /dev/null @@ -1,119 +0,0 @@ -// 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 -#include -#include - -#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(0); - auto flutter_resource_context = std::make_unique(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(0); - auto flutter_resource_context = std::make_unique(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(0); - auto flutter_resource_context = std::make_unique(1); - auto some_context = std::make_unique(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(0); - auto flutter_resource_context = std::make_unique(1); - auto some_context = std::make_unique(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(0); - auto flutter_resource_context = std::make_unique(1); - auto some_context = std::make_unique(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 diff --git a/engine/src/flutter/shell/common/renderer_context_test.cc b/engine/src/flutter/shell/common/renderer_context_test.cc deleted file mode 100644 index 9cfb2b39e58..00000000000 --- a/engine/src/flutter/shell/common/renderer_context_test.cc +++ /dev/null @@ -1,39 +0,0 @@ -// 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_test.h" - -namespace flutter { -namespace testing { - -FML_THREAD_LOCAL fml::ThreadLocalUniquePtr current_context; - -RendererContextTest::RendererContextTest() = default; - -TestRendererContext::TestRendererContext(int context) : context_(context){}; - -TestRendererContext::~TestRendererContext() = default; - -bool TestRendererContext::SetCurrent() { - SetCurrentContext(context_); - return true; -}; - -void TestRendererContext::RemoveCurrent() { - SetCurrentContext(-1); -}; - -int TestRendererContext::GetContext() { - return context_; -}; - -int TestRendererContext::GetCurrentContext() { - return *(current_context.get()); -}; - -void TestRendererContext::SetCurrentContext(int context) { - current_context.reset(new int(context)); -}; -} // namespace testing -} // namespace flutter diff --git a/engine/src/flutter/shell/common/shell_test_platform_view_gl.cc b/engine/src/flutter/shell/common/shell_test_platform_view_gl.cc index c980c531686..0b7b1f588c7 100644 --- a/engine/src/flutter/shell/common/shell_test_platform_view_gl.cc +++ b/engine/src/flutter/shell/common/shell_test_platform_view_gl.cc @@ -44,8 +44,9 @@ PointerDataDispatcherMaker ShellTestPlatformViewGL::GetDispatcherMaker() { } // |GPUSurfaceGLDelegate| -bool ShellTestPlatformViewGL::GLContextMakeCurrent() { - return gl_surface_.MakeCurrent(); +std::unique_ptr +ShellTestPlatformViewGL::GLContextMakeCurrent() { + return std::make_unique(gl_surface_.MakeCurrent()); } // |GPUSurfaceGLDelegate| diff --git a/engine/src/flutter/shell/common/shell_test_platform_view_gl.h b/engine/src/flutter/shell/common/shell_test_platform_view_gl.h index cac2fdc6497..e33b84fed78 100644 --- a/engine/src/flutter/shell/common/shell_test_platform_view_gl.h +++ b/engine/src/flutter/shell/common/shell_test_platform_view_gl.h @@ -47,7 +47,7 @@ class ShellTestPlatformViewGL : public ShellTestPlatformView, PointerDataDispatcherMaker GetDispatcherMaker() override; // |GPUSurfaceGLDelegate| - bool GLContextMakeCurrent() override; + std::unique_ptr GLContextMakeCurrent() override; // |GPUSurfaceGLDelegate| bool GLContextClearCurrent() override; diff --git a/engine/src/flutter/shell/common/shell_test_platform_view_vulkan.cc b/engine/src/flutter/shell/common/shell_test_platform_view_vulkan.cc index 7c916567897..7d92053de6d 100644 --- a/engine/src/flutter/shell/common/shell_test_platform_view_vulkan.cc +++ b/engine/src/flutter/shell/common/shell_test_platform_view_vulkan.cc @@ -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 { diff --git a/engine/src/flutter/shell/common/surface.cc b/engine/src/flutter/shell/common/surface.cc index c12a35ba070..95ed2afbdf5 100644 --- a/engine/src/flutter/shell/common/surface.cc +++ b/engine/src/flutter/shell/common/surface.cc @@ -14,8 +14,8 @@ flutter::ExternalViewEmbedder* Surface::GetExternalViewEmbedder() { return nullptr; } -bool Surface::MakeRenderContextCurrent() { - return true; +std::unique_ptr Surface::MakeRenderContextCurrent() { + return std::make_unique(true); } } // namespace flutter diff --git a/engine/src/flutter/shell/common/surface.h b/engine/src/flutter/shell/common/surface.h index 2703fb83a26..708a35595e7 100644 --- a/engine/src/flutter/shell/common/surface.h +++ b/engine/src/flutter/shell/common/surface.h @@ -31,7 +31,7 @@ class Surface { virtual flutter::ExternalViewEmbedder* GetExternalViewEmbedder(); - virtual bool MakeRenderContextCurrent(); + virtual std::unique_ptr MakeRenderContextCurrent(); private: FML_DISALLOW_COPY_AND_ASSIGN(Surface); diff --git a/engine/src/flutter/shell/common/surface_frame.cc b/engine/src/flutter/shell/common/surface_frame.cc index a99c8a88259..b08fae0eb3e 100644 --- a/engine/src/flutter/shell/common/surface_frame.cc +++ b/engine/src/flutter/shell/common/surface_frame.cc @@ -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 surface, FML_DCHECK(submit_callback_); } +SurfaceFrame::SurfaceFrame(sk_sp surface, + bool supports_readback, + const SubmitCallback& submit_callback, + std::unique_ptr 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. diff --git a/engine/src/flutter/shell/common/surface_frame.h b/engine/src/flutter/shell/common/surface_frame.h index b3ac64fb5d0..8e5e56bd9e7 100644 --- a/engine/src/flutter/shell/common/surface_frame.h +++ b/engine/src/flutter/shell/common/surface_frame.h @@ -8,6 +8,7 @@ #include #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 surface, + bool supports_readback, + const SubmitCallback& submit_callback, + std::unique_ptr context_result); + ~SurfaceFrame(); bool Submit(); @@ -41,6 +47,7 @@ class SurfaceFrame { sk_sp surface_; bool supports_readback_; SubmitCallback submit_callback_; + std::unique_ptr context_result_; bool PerformSubmit(); diff --git a/engine/src/flutter/shell/gpu/BUILD.gn b/engine/src/flutter/shell/gpu/BUILD.gn index 2f91e20b43a..1e5b0d1f398 100644 --- a/engine/src/flutter/shell/gpu/BUILD.gn +++ b/engine/src/flutter/shell/gpu/BUILD.gn @@ -11,6 +11,7 @@ gpu_common_deps = [ "//flutter/flow", "//flutter/fml", "//flutter/shell/common", + "//flutter/shell/common:common_standalone", "//third_party/skia", ] diff --git a/engine/src/flutter/shell/gpu/gpu_surface_gl.cc b/engine/src/flutter/shell/gpu/gpu_surface_gl.cc index e5fbf00a247..cf895df4613 100644 --- a/engine/src/flutter/shell/gpu/gpu_surface_gl.cc +++ b/engine/src/flutter/shell/gpu/gpu_surface_gl.cc @@ -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 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 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 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 GPUSurfaceGL::AcquireFrame(const SkISize& size) { }; return std::make_unique( - 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 GPUSurfaceGL::MakeRenderContextCurrent() { return delegate_->GLContextMakeCurrent(); } diff --git a/engine/src/flutter/shell/gpu/gpu_surface_gl.h b/engine/src/flutter/shell/gpu/gpu_surface_gl.h index d299e572f45..b5bd4a1bf19 100644 --- a/engine/src/flutter/shell/gpu/gpu_surface_gl.h +++ b/engine/src/flutter/shell/gpu/gpu_surface_gl.h @@ -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 MakeRenderContextCurrent() override; private: GPUSurfaceGLDelegate* delegate_; diff --git a/engine/src/flutter/shell/gpu/gpu_surface_gl_delegate.h b/engine/src/flutter/shell/gpu/gpu_surface_gl_delegate.h index cf0600aea4d..aaca9269a14 100644 --- a/engine/src/flutter/shell/gpu/gpu_surface_gl_delegate.h +++ b/engine/src/flutter/shell/gpu/gpu_surface_gl_delegate.h @@ -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 GLContextMakeCurrent() = 0; // Called to clear the current GL context on the thread. This may be called on // either the GPU or IO threads. diff --git a/engine/src/flutter/shell/gpu/gpu_surface_metal.h b/engine/src/flutter/shell/gpu/gpu_surface_metal.h index 3332dca6585..86715960a05 100644 --- a/engine/src/flutter/shell/gpu/gpu_surface_metal.h +++ b/engine/src/flutter/shell/gpu/gpu_surface_metal.h @@ -50,7 +50,7 @@ class GPUSurfaceMetal : public Surface { flutter::ExternalViewEmbedder* GetExternalViewEmbedder() override; // |Surface| - bool MakeRenderContextCurrent() override; + std::unique_ptr MakeRenderContextCurrent() override; void ReleaseUnusedDrawableIfNecessary(); diff --git a/engine/src/flutter/shell/gpu/gpu_surface_metal.mm b/engine/src/flutter/shell/gpu/gpu_surface_metal.mm index fa2efce0fc4..69faa872923 100644 --- a/engine/src/flutter/shell/gpu/gpu_surface_metal.mm +++ b/engine/src/flutter/shell/gpu/gpu_surface_metal.mm @@ -127,9 +127,9 @@ flutter::ExternalViewEmbedder* GPUSurfaceMetal::GetExternalViewEmbedder() { } // |Surface| -bool GPUSurfaceMetal::MakeRenderContextCurrent() { +std::unique_ptr GPUSurfaceMetal::MakeRenderContextCurrent() { // This backend has no such concept. - return true; + return std::make_unique(true); } void GPUSurfaceMetal::ReleaseUnusedDrawableIfNecessary() { diff --git a/engine/src/flutter/shell/platform/android/android_surface_gl.cc b/engine/src/flutter/shell/platform/android/android_surface_gl.cc index e27756c3b6a..dae803fb6b8 100644 --- a/engine/src/flutter/shell/platform/android/android_surface_gl.cc +++ b/engine/src/flutter/shell/platform/android/android_surface_gl.cc @@ -106,9 +106,11 @@ bool AndroidSurfaceGL::SetNativeWindow( return true; } -bool AndroidSurfaceGL::GLContextMakeCurrent() { +std::unique_ptr AndroidSurfaceGL::GLContextMakeCurrent() { FML_DCHECK(onscreen_context_ && onscreen_context_->IsValid()); - return onscreen_context_->MakeCurrent(); + auto default_context_result = std::make_unique( + onscreen_context_->MakeCurrent()); + return std::move(default_context_result); } bool AndroidSurfaceGL::GLContextClearCurrent() { diff --git a/engine/src/flutter/shell/platform/android/android_surface_gl.h b/engine/src/flutter/shell/platform/android/android_surface_gl.h index bed05bd60b5..a13156a7734 100644 --- a/engine/src/flutter/shell/platform/android/android_surface_gl.h +++ b/engine/src/flutter/shell/platform/android/android_surface_gl.h @@ -48,7 +48,7 @@ class AndroidSurfaceGL final : public GPUSurfaceGLDelegate, bool SetNativeWindow(fml::RefPtr window) override; // |GPUSurfaceGLDelegate| - bool GLContextMakeCurrent() override; + std::unique_ptr GLContextMakeCurrent() override; // |GPUSurfaceGLDelegate| bool GLContextClearCurrent() override; diff --git a/engine/src/flutter/shell/platform/darwin/ios/BUILD.gn b/engine/src/flutter/shell/platform/darwin/ios/BUILD.gn index 9166eba9d85..9bdc12115a7 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/BUILD.gn +++ b/engine/src/flutter/shell/platform/darwin/ios/BUILD.gn @@ -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", diff --git a/engine/src/flutter/shell/platform/darwin/ios/ios_context.h b/engine/src/flutter/shell/platform/darwin/ios/ios_context.h index 8d030a75297..ca834c1660f 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/ios_context.h +++ b/engine/src/flutter/shell/platform/darwin/ios/ios_context.h @@ -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 MakeCurrent() = 0; //---------------------------------------------------------------------------- /// @brief Creates an external texture proxy of the appropriate client diff --git a/engine/src/flutter/shell/platform/darwin/ios/ios_context_gl.h b/engine/src/flutter/shell/platform/darwin/ios/ios_context_gl.h index a0d330eac6f..126fda48c3f 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/ios_context_gl.h +++ b/engine/src/flutter/shell/platform/darwin/ios/ios_context_gl.h @@ -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 CreateResourceContext() override; // |IOSContext| - bool MakeCurrent() override; + std::unique_ptr MakeCurrent() override; // |IOSContext| std::unique_ptr CreateExternalTexture( diff --git a/engine/src/flutter/shell/platform/darwin/ios/ios_context_gl.mm b/engine/src/flutter/shell/platform/darwin/ios/ios_context_gl.mm index 5eaac6ca51f..282f8eda2fc 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/ios_context_gl.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/ios_context_gl.mm @@ -28,7 +28,7 @@ IOSContextGL::~IOSContextGL() = default; std::unique_ptr IOSContextGL::CreateRenderTarget( fml::scoped_nsobject layer) { - return std::make_unique(std::move(layer), context_, resource_context_); + return std::make_unique(std::move(layer), context_); } // |IOSContext| @@ -44,8 +44,9 @@ sk_sp IOSContextGL::CreateResourceContext() { } // |IOSContext| -bool IOSContextGL::MakeCurrent() { - return [EAGLContext setCurrentContext:context_.get()]; +std::unique_ptr IOSContextGL::MakeCurrent() { + return std::make_unique( + std::make_unique(context_.get())); } // |IOSContext| diff --git a/engine/src/flutter/shell/platform/darwin/ios/ios_context_metal.h b/engine/src/flutter/shell/platform/darwin/ios/ios_context_metal.h index c91d742fffd..644b4f5d3c3 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/ios_context_metal.h +++ b/engine/src/flutter/shell/platform/darwin/ios/ios_context_metal.h @@ -43,7 +43,7 @@ class IOSContextMetal final : public IOSContext { sk_sp CreateResourceContext() override; // |IOSContext| - bool MakeCurrent() override; + std::unique_ptr MakeCurrent() override; // |IOSContext| std::unique_ptr CreateExternalTexture( diff --git a/engine/src/flutter/shell/platform/darwin/ios/ios_context_metal.mm b/engine/src/flutter/shell/platform/darwin/ios/ios_context_metal.mm index 9bf665c316d..9d0a3cad623 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/ios_context_metal.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/ios_context_metal.mm @@ -96,9 +96,9 @@ sk_sp IOSContextMetal::CreateResourceContext() { } // |IOSContext| -bool IOSContextMetal::MakeCurrent() { +std::unique_ptr IOSContextMetal::MakeCurrent() { // This only makes sense for context that need to be bound to a specific thread. - return true; + return std::make_unique(true); } // |IOSContext| diff --git a/engine/src/flutter/shell/platform/darwin/ios/ios_context_software.h b/engine/src/flutter/shell/platform/darwin/ios/ios_context_software.h index 1d0e961d4aa..9f98d8eb7c6 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/ios_context_software.h +++ b/engine/src/flutter/shell/platform/darwin/ios/ios_context_software.h @@ -21,7 +21,7 @@ class IOSContextSoftware final : public IOSContext { sk_sp CreateResourceContext() override; // |IOSContext| - bool MakeCurrent() override; + std::unique_ptr MakeCurrent() override; // |IOSContext| std::unique_ptr CreateExternalTexture( diff --git a/engine/src/flutter/shell/platform/darwin/ios/ios_context_software.mm b/engine/src/flutter/shell/platform/darwin/ios/ios_context_software.mm index 5d2006e2dd4..4bec84f4b2c 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/ios_context_software.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/ios_context_software.mm @@ -17,8 +17,9 @@ sk_sp IOSContextSoftware::CreateResourceContext() { } // |IOSContext| -bool IOSContextSoftware::MakeCurrent() { - return false; +std::unique_ptr IOSContextSoftware::MakeCurrent() { + // This only makes sense for context that need to be bound to a specific thread. + return std::make_unique(false); } // |IOSContext| diff --git a/engine/src/flutter/shell/platform/darwin/ios/ios_render_target_gl.h b/engine/src/flutter/shell/platform/darwin/ios/ios_render_target_gl.h index f83679f29bc..dc0b0a2fad8 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/ios_render_target_gl.h +++ b/engine/src/flutter/shell/platform/darwin/ios/ios_render_target_gl.h @@ -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 layer, - fml::scoped_nsobject context, - fml::scoped_nsobject resource_context); + fml::scoped_nsobject context_); ~IOSRenderTargetGL(); @@ -35,7 +35,6 @@ class IOSRenderTargetGL { private: fml::scoped_nsobject layer_; fml::scoped_nsobject context_; - fml::scoped_nsobject resource_context_; GLuint framebuffer_ = GL_NONE; GLuint colorbuffer_ = GL_NONE; GLint storage_size_width_ = GL_NONE; diff --git a/engine/src/flutter/shell/platform/darwin/ios/ios_render_target_gl.mm b/engine/src/flutter/shell/platform/darwin/ios/ios_render_target_gl.mm index 7f58a7d7fa2..a8972822f1e 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/ios_render_target_gl.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/ios_render_target_gl.mm @@ -13,20 +13,16 @@ namespace flutter { IOSRenderTargetGL::IOSRenderTargetGL(fml::scoped_nsobject layer, - fml::scoped_nsobject context, - fml::scoped_nsobject resource_context) - : layer_(std::move(layer)), - context_(std::move(context)), - resource_context_(std::move(resource_context)) { + fml::scoped_nsobject 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(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 layer, } IOSRenderTargetGL::~IOSRenderTargetGL() { - EAGLContext* context = EAGLContext.currentContext; - [EAGLContext setCurrentContext:context_]; + auto context_switch = GLContextSwitch(std::make_unique(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(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; } diff --git a/engine/src/flutter/shell/platform/darwin/ios/ios_surface_gl.h b/engine/src/flutter/shell/platform/darwin/ios/ios_surface_gl.h index 3cbc6ebd047..42e8fcd4b75 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/ios_surface_gl.h +++ b/engine/src/flutter/shell/platform/darwin/ios/ios_surface_gl.h @@ -34,7 +34,7 @@ class IOSSurfaceGL final : public IOSSurface, public GPUSurfaceGLDelegate { std::unique_ptr CreateGPUSurface(GrContext* gr_context) override; // |GPUSurfaceGLDelegate| - bool GLContextMakeCurrent() override; + std::unique_ptr GLContextMakeCurrent() override; // |GPUSurfaceGLDelegate| bool GLContextClearCurrent() override; diff --git a/engine/src/flutter/shell/platform/darwin/ios/ios_surface_gl.mm b/engine/src/flutter/shell/platform/darwin/ios/ios_surface_gl.mm index b3aa25a4e66..cf685d4f79a 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/ios_surface_gl.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/ios_surface_gl.mm @@ -59,16 +59,20 @@ bool IOSSurfaceGL::SurfaceSupportsReadback() const { } // |GPUSurfaceGLDelegate| -bool IOSSurfaceGL::GLContextMakeCurrent() { +std::unique_ptr IOSSurfaceGL::GLContextMakeCurrent() { if (!IsValid()) { - return false; + return std::make_unique(false); } - return render_target_->UpdateStorageSizeIfNecessary() && GetContext()->MakeCurrent(); + bool update_if_necessary = render_target_->UpdateStorageSizeIfNecessary(); + if (!update_if_necessary) { + return std::make_unique(false); + } + return GetContext()->MakeCurrent(); } // |GPUSurfaceGLDelegate| bool IOSSurfaceGL::GLContextClearCurrent() { - [EAGLContext setCurrentContext:nil]; + // |GLContextMakeCurrent| should handle the scope of the gl context. return true; } diff --git a/engine/src/flutter/shell/platform/darwin/ios/ios_switchable_gl_context.h b/engine/src/flutter/shell/platform/darwin/ios/ios_switchable_gl_context.h new file mode 100644 index 00000000000..8f1aed11ddf --- /dev/null +++ b/engine/src/flutter/shell/platform/darwin/ios/ios_switchable_gl_context.h @@ -0,0 +1,49 @@ +// 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 diff --git a/engine/src/flutter/shell/platform/darwin/ios/ios_switchable_gl_context.mm b/engine/src/flutter/shell/platform/darwin/ios/ios_switchable_gl_context.mm new file mode 100644 index 00000000000..279db9c0e1a --- /dev/null +++ b/engine/src/flutter/shell/platform/darwin/ios/ios_switchable_gl_context.mm @@ -0,0 +1,24 @@ +// 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 + +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_]; +}; +} diff --git a/engine/src/flutter/shell/platform/embedder/embedder_surface_gl.cc b/engine/src/flutter/shell/platform/embedder/embedder_surface_gl.cc index d37b03aae8d..527fbdd9b75 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder_surface_gl.cc +++ b/engine/src/flutter/shell/platform/embedder/embedder_surface_gl.cc @@ -34,8 +34,9 @@ bool EmbedderSurfaceGL::IsValid() const { } // |GPUSurfaceGLDelegate| -bool EmbedderSurfaceGL::GLContextMakeCurrent() { - return gl_dispatch_table_.gl_make_current_callback(); +std::unique_ptr EmbedderSurfaceGL::GLContextMakeCurrent() { + return std::make_unique( + gl_dispatch_table_.gl_make_current_callback()); } // |GPUSurfaceGLDelegate| diff --git a/engine/src/flutter/shell/platform/embedder/embedder_surface_gl.h b/engine/src/flutter/shell/platform/embedder/embedder_surface_gl.h index a01fa05d4e6..b3c4e094f9e 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder_surface_gl.h +++ b/engine/src/flutter/shell/platform/embedder/embedder_surface_gl.h @@ -50,7 +50,7 @@ class EmbedderSurfaceGL final : public EmbedderSurface, sk_sp CreateResourceContext() const override; // |GPUSurfaceGLDelegate| - bool GLContextMakeCurrent() override; + std::unique_ptr GLContextMakeCurrent() override; // |GPUSurfaceGLDelegate| bool GLContextClearCurrent() override;