未验证 提交 892b505d 编写于 作者: S stuartmorgan 提交者: GitHub

Provide a resource context in the GLFW shell (#8895)

Uses an invisible GLFW window to provide a background resource context
for the Flutter engine to upload textures.

Fixes #31941
上级 edff0aa1
......@@ -34,14 +34,20 @@
#define GLFW_FALSE 0
#endif
using UniqueGLFWwindowPtr = std::unique_ptr<GLFWwindow, void (*)(GLFWwindow*)>;
static_assert(FLUTTER_ENGINE_VERSION == 1, "");
static constexpr double kDpPerInch = 160.0;
// Struct for storing state within an instance of the GLFW Window.
struct FlutterDesktopWindowControllerState {
// The GLFW window that owns this state object.
GLFWwindow* window;
// The GLFW window that is bound to this state object.
UniqueGLFWwindowPtr window = UniqueGLFWwindowPtr(nullptr, glfwDestroyWindow);
// The invisible GLFW window used to upload resources in the background.
UniqueGLFWwindowPtr resource_window =
UniqueGLFWwindowPtr(nullptr, glfwDestroyWindow);
// The handle to the Flutter engine instance.
FlutterEngine engine;
......@@ -116,6 +122,16 @@ static FlutterDesktopWindowControllerState* GetSavedWindowState(
glfwGetWindowUserPointer(window));
}
// Creates and returns an invisible GLFW window that shares |window|'s resource
// context.
static UniqueGLFWwindowPtr CreateShareWindowForWindow(GLFWwindow* window) {
glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
GLFWwindow* share_window = glfwCreateWindow(1, 1, "", NULL, window);
glfwDefaultWindowHints();
return UniqueGLFWwindowPtr(share_window, glfwDestroyWindow);
}
// Converts a FlutterPlatformMessage to an equivalent FlutterDesktopMessage.
static FlutterDesktopMessage ConvertToDesktopMessage(
const FlutterPlatformMessage& engine_message) {
......@@ -379,6 +395,12 @@ static bool GLFWMakeContextCurrent(void* user_data) {
return true;
}
static bool GLFWMakeResourceContextCurrent(void* user_data) {
GLFWwindow* window = reinterpret_cast<GLFWwindow*>(user_data);
glfwMakeContextCurrent(GetSavedWindowState(window)->resource_window.get());
return true;
}
static bool GLFWClearContext(void* user_data) {
glfwMakeContextCurrent(nullptr);
return true;
......@@ -458,6 +480,7 @@ static FlutterEngine RunFlutterEngine(GLFWwindow* window,
config.open_gl.clear_current = GLFWClearContext;
config.open_gl.present = GLFWPresent;
config.open_gl.fbo_callback = GLFWGetActiveFbo;
config.open_gl.make_resource_current = GLFWMakeResourceContextCurrent;
config.open_gl.gl_proc_resolver = GLFWProcResolver;
}
FlutterProjectArgs args = {};
......@@ -499,34 +522,37 @@ FlutterDesktopWindowControllerRef FlutterDesktopCreateWindow(
#ifdef __linux__
gtk_init(0, nullptr);
#endif
// Create the window.
auto* window =
glfwCreateWindow(initial_width, initial_height, title, NULL, NULL);
auto state = std::make_unique<FlutterDesktopWindowControllerState>();
// Create the window, and set the state as its user data.
state->window = UniqueGLFWwindowPtr(
glfwCreateWindow(initial_width, initial_height, title, NULL, NULL),
glfwDestroyWindow);
GLFWwindow* window = state->window.get();
if (window == nullptr) {
return nullptr;
}
GLFWClearCanvas(window);
glfwSetWindowUserPointer(window, state.get());
// Create the share window before starting the engine, since it may call
// GLFWMakeResourceContextCurrent immediately.
state->resource_window = CreateShareWindowForWindow(window);
// Start the engine.
auto engine = RunFlutterEngine(window, assets_path, icu_data_path, arguments,
argument_count);
if (engine == nullptr) {
glfwDestroyWindow(window);
state->engine = RunFlutterEngine(window, assets_path, icu_data_path,
arguments, argument_count);
if (state->engine == nullptr) {
return nullptr;
}
// Create a state object attached to the window.
auto* state = new FlutterDesktopWindowControllerState();
state->window = window;
glfwSetWindowUserPointer(window, state);
state->engine = engine;
// TODO: Restructure the internals to follow the structure of the C++ API, so
// that this isn't a tangle of references.
auto messenger = std::make_unique<FlutterDesktopMessenger>();
state->message_dispatcher =
std::make_unique<flutter::IncomingMessageDispatcher>(messenger.get());
messenger->engine = engine;
messenger->engine = state->engine;
messenger->dispatcher = state->message_dispatcher.get();
state->window_wrapper = std::make_unique<FlutterDesktopWindow>();
......@@ -557,12 +583,11 @@ FlutterDesktopWindowControllerRef FlutterDesktopCreateWindow(
glfwSetFramebufferSizeCallback(window, GLFWFramebufferSizeCallback);
GLFWAssignEventCallbacks(window);
return state;
return state.release();
}
void FlutterDesktopDestroyWindow(FlutterDesktopWindowControllerRef controller) {
FlutterEngineShutdown(controller->engine);
glfwDestroyWindow(controller->window);
delete controller;
}
......@@ -633,7 +658,7 @@ double FlutterDesktopWindowGetScaleFactor(
}
void FlutterDesktopRunWindowLoop(FlutterDesktopWindowControllerRef controller) {
GLFWwindow* window = controller->window;
GLFWwindow* window = controller->window.get();
#ifdef __linux__
// Necessary for GTK thread safety.
XInitThreads();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册