mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Rework GLContextSwitch, get rid of RendererContextManager (flutter/engine#18601)
This commit is contained in:
parent
ea849e7c04
commit
b842ba72a6
@ -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",
|
||||
]
|
||||
|
||||
|
||||
34
engine/src/flutter/shell/common/gl_context_switch.cc
Normal file
34
engine/src/flutter/shell/common/gl_context_switch.cc
Normal file
@ -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<SwitchableGLContext> context)
|
||||
: context_(std::move(context)) {
|
||||
FML_CHECK(context_ != nullptr);
|
||||
result_ = context_->SetCurrent();
|
||||
};
|
||||
|
||||
GLContextSwitch::~GLContextSwitch() {
|
||||
context_->RemoveCurrent();
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
117
engine/src/flutter/shell/common/gl_context_switch.h
Normal file
117
engine/src/flutter/shell/common/gl_context_switch.h
Normal file
@ -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 <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
|
||||
43
engine/src/flutter/shell/common/gl_context_switch_test.cc
Normal file
43
engine/src/flutter/shell/common/gl_context_switch_test.cc
Normal file
@ -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<int> 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
|
||||
@ -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
|
||||
@ -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 <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;
|
||||
}
|
||||
|
||||
|
||||
@ -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<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
|
||||
@ -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 <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
|
||||
@ -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 <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
|
||||
@ -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<int> 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
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
@ -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 <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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user