forked from firka/flutter
Move OpenGL context management to FlOpenGLManager (#166025)
This helps to make a non-OpenGL FlRenderer
This commit is contained in:
@@ -53264,6 +53264,8 @@ ORIGIN: ../../../flutter/shell/platform/linux/fl_mouse_cursor_channel.cc + ../..
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_mouse_cursor_channel.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_mouse_cursor_handler.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_mouse_cursor_handler.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_opengl_manager.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_opengl_manager.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture_private.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture_test.cc + ../../../flutter/LICENSE
|
||||
@@ -53284,10 +53286,6 @@ ORIGIN: ../../../flutter/shell/platform/linux/fl_renderable.cc + ../../../flutte
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_renderable.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_gdk.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_gdk.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_headless.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_headless.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_test.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_scrolling_manager.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_scrolling_manager.h + ../../../flutter/LICENSE
|
||||
@@ -56281,6 +56279,8 @@ FILE: ../../../flutter/shell/platform/linux/fl_mouse_cursor_channel.cc
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_mouse_cursor_channel.h
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_mouse_cursor_handler.cc
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_mouse_cursor_handler.h
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_opengl_manager.cc
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_opengl_manager.h
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture.cc
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture_private.h
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture_test.cc
|
||||
@@ -56301,10 +56301,6 @@ FILE: ../../../flutter/shell/platform/linux/fl_renderable.cc
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_renderable.h
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_renderer.cc
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_renderer.h
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_renderer_gdk.cc
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_renderer_gdk.h
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_renderer_headless.cc
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_renderer_headless.h
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_renderer_test.cc
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_scrolling_manager.cc
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_scrolling_manager.h
|
||||
|
||||
@@ -128,6 +128,7 @@ source_set("flutter_linux_sources") {
|
||||
"fl_method_response.cc",
|
||||
"fl_mouse_cursor_channel.cc",
|
||||
"fl_mouse_cursor_handler.cc",
|
||||
"fl_opengl_manager.cc",
|
||||
"fl_pixel_buffer_texture.cc",
|
||||
"fl_platform_channel.cc",
|
||||
"fl_platform_handler.cc",
|
||||
@@ -136,8 +137,6 @@ source_set("flutter_linux_sources") {
|
||||
"fl_pointer_manager.cc",
|
||||
"fl_renderable.cc",
|
||||
"fl_renderer.cc",
|
||||
"fl_renderer_gdk.cc",
|
||||
"fl_renderer_headless.cc",
|
||||
"fl_scrolling_manager.cc",
|
||||
"fl_settings.cc",
|
||||
"fl_settings_channel.cc",
|
||||
@@ -261,7 +260,7 @@ executable("flutter_linux_unittests") {
|
||||
"testing/mock_epoxy.cc",
|
||||
"testing/mock_gtk.cc",
|
||||
"testing/mock_plugin_registrar.cc",
|
||||
"testing/mock_renderer.cc",
|
||||
"testing/mock_renderable.cc",
|
||||
"testing/mock_settings.cc",
|
||||
"testing/mock_signal_handler.cc",
|
||||
"testing/mock_texture_registrar.cc",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
|
||||
|
||||
#include <epoxy/egl.h>
|
||||
#include <gmodule.h>
|
||||
|
||||
#include <cstring>
|
||||
@@ -16,12 +17,11 @@
|
||||
#include "flutter/shell/platform/linux/fl_display_monitor.h"
|
||||
#include "flutter/shell/platform/linux/fl_engine_private.h"
|
||||
#include "flutter/shell/platform/linux/fl_keyboard_handler.h"
|
||||
#include "flutter/shell/platform/linux/fl_opengl_manager.h"
|
||||
#include "flutter/shell/platform/linux/fl_pixel_buffer_texture_private.h"
|
||||
#include "flutter/shell/platform/linux/fl_platform_handler.h"
|
||||
#include "flutter/shell/platform/linux/fl_plugin_registrar_private.h"
|
||||
#include "flutter/shell/platform/linux/fl_renderer.h"
|
||||
#include "flutter/shell/platform/linux/fl_renderer_gdk.h"
|
||||
#include "flutter/shell/platform/linux/fl_renderer_headless.h"
|
||||
#include "flutter/shell/platform/linux/fl_settings_handler.h"
|
||||
#include "flutter/shell/platform/linux/fl_texture_gl_private.h"
|
||||
#include "flutter/shell/platform/linux/fl_texture_registrar_private.h"
|
||||
@@ -51,6 +51,9 @@ struct _FlEngine {
|
||||
// Renders the Flutter app.
|
||||
FlRenderer* renderer;
|
||||
|
||||
// Manages OpenGL contexts.
|
||||
FlOpenGLManager* opengl_manager;
|
||||
|
||||
// Messenger used to send and receive platform messages.
|
||||
FlBinaryMessenger* binary_messenger;
|
||||
|
||||
@@ -274,25 +277,24 @@ static bool compositor_present_view_callback(
|
||||
// Flutter engine rendering callbacks.
|
||||
|
||||
static void* fl_engine_gl_proc_resolver(void* user_data, const char* name) {
|
||||
FlEngine* self = static_cast<FlEngine*>(user_data);
|
||||
return fl_renderer_get_proc_address(self->renderer, name);
|
||||
return reinterpret_cast<void*>(eglGetProcAddress(name));
|
||||
}
|
||||
|
||||
static bool fl_engine_gl_make_current(void* user_data) {
|
||||
FlEngine* self = static_cast<FlEngine*>(user_data);
|
||||
fl_renderer_make_current(self->renderer);
|
||||
fl_opengl_manager_make_current(self->opengl_manager);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool fl_engine_gl_clear_current(void* user_data) {
|
||||
FlEngine* self = static_cast<FlEngine*>(user_data);
|
||||
fl_renderer_clear_current(self->renderer);
|
||||
fl_opengl_manager_clear_current(self->opengl_manager);
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t fl_engine_gl_get_fbo(void* user_data) {
|
||||
FlEngine* self = static_cast<FlEngine*>(user_data);
|
||||
return fl_renderer_get_fbo(self->renderer);
|
||||
// There is only one frame buffer object - always return that.
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool fl_engine_gl_present(void* user_data) {
|
||||
@@ -303,7 +305,7 @@ static bool fl_engine_gl_present(void* user_data) {
|
||||
|
||||
static bool fl_engine_gl_make_resource_current(void* user_data) {
|
||||
FlEngine* self = static_cast<FlEngine*>(user_data);
|
||||
fl_renderer_make_resource_current(self->renderer);
|
||||
fl_opengl_manager_make_resource_current(self->opengl_manager);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -483,6 +485,7 @@ static void fl_engine_dispose(GObject* object) {
|
||||
g_clear_object(&self->project);
|
||||
g_clear_object(&self->display_monitor);
|
||||
g_clear_object(&self->renderer);
|
||||
g_clear_object(&self->opengl_manager);
|
||||
g_clear_object(&self->texture_registrar);
|
||||
g_clear_object(&self->binary_messenger);
|
||||
g_clear_object(&self->settings_handler);
|
||||
@@ -533,6 +536,8 @@ static void fl_engine_init(FlEngine* self) {
|
||||
g_warning("Failed get get engine function pointers");
|
||||
}
|
||||
|
||||
self->opengl_manager = fl_opengl_manager_new();
|
||||
|
||||
self->display_monitor =
|
||||
fl_display_monitor_new(self, gdk_display_get_default());
|
||||
self->task_runner = fl_task_runner_new(self);
|
||||
@@ -550,15 +555,13 @@ static void fl_engine_init(FlEngine* self) {
|
||||
}
|
||||
|
||||
static FlEngine* fl_engine_new_full(FlDartProject* project,
|
||||
FlRenderer* renderer,
|
||||
FlBinaryMessenger* binary_messenger) {
|
||||
g_return_val_if_fail(FL_IS_DART_PROJECT(project), nullptr);
|
||||
g_return_val_if_fail(FL_IS_RENDERER(renderer), nullptr);
|
||||
|
||||
FlEngine* self = FL_ENGINE(g_object_new(fl_engine_get_type(), nullptr));
|
||||
|
||||
self->project = FL_DART_PROJECT(g_object_ref(project));
|
||||
self->renderer = FL_RENDERER(g_object_ref(renderer));
|
||||
self->renderer = fl_renderer_new(self);
|
||||
if (binary_messenger != nullptr) {
|
||||
self->binary_messenger =
|
||||
FL_BINARY_MESSENGER(g_object_ref(binary_messenger));
|
||||
@@ -570,8 +573,6 @@ static FlEngine* fl_engine_new_full(FlDartProject* project,
|
||||
fl_mouse_cursor_handler_new(self->binary_messenger);
|
||||
self->windowing_handler = fl_windowing_handler_new(self);
|
||||
|
||||
fl_renderer_set_engine(self->renderer, self);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -581,28 +582,18 @@ FlEngine* fl_engine_for_id(int64_t id) {
|
||||
return FL_ENGINE(engine);
|
||||
}
|
||||
|
||||
FlEngine* fl_engine_new_with_renderer(FlDartProject* project,
|
||||
FlRenderer* renderer) {
|
||||
g_return_val_if_fail(FL_IS_DART_PROJECT(project), nullptr);
|
||||
g_return_val_if_fail(FL_IS_RENDERER(renderer), nullptr);
|
||||
return fl_engine_new_full(project, renderer, nullptr);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT FlEngine* fl_engine_new(FlDartProject* project) {
|
||||
g_autoptr(FlRendererGdk) renderer = fl_renderer_gdk_new();
|
||||
return fl_engine_new_with_renderer(project, FL_RENDERER(renderer));
|
||||
return fl_engine_new_full(project, nullptr);
|
||||
}
|
||||
|
||||
FlEngine* fl_engine_new_with_binary_messenger(
|
||||
FlBinaryMessenger* binary_messenger) {
|
||||
g_autoptr(FlDartProject) project = fl_dart_project_new();
|
||||
g_autoptr(FlRendererGdk) renderer = fl_renderer_gdk_new();
|
||||
return fl_engine_new_full(project, FL_RENDERER(renderer), binary_messenger);
|
||||
return fl_engine_new_full(project, binary_messenger);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT FlEngine* fl_engine_new_headless(FlDartProject* project) {
|
||||
g_autoptr(FlRendererHeadless) renderer = fl_renderer_headless_new();
|
||||
return fl_engine_new_with_renderer(project, FL_RENDERER(renderer));
|
||||
return fl_engine_new(project);
|
||||
}
|
||||
|
||||
FlRenderer* fl_engine_get_renderer(FlEngine* self) {
|
||||
@@ -610,6 +601,11 @@ FlRenderer* fl_engine_get_renderer(FlEngine* self) {
|
||||
return self->renderer;
|
||||
}
|
||||
|
||||
FlOpenGLManager* fl_engine_get_opengl_manager(FlEngine* self) {
|
||||
g_return_val_if_fail(FL_IS_ENGINE(self), nullptr);
|
||||
return self->opengl_manager;
|
||||
}
|
||||
|
||||
FlDisplayMonitor* fl_engine_get_display_monitor(FlEngine* self) {
|
||||
g_return_val_if_fail(FL_IS_ENGINE(self), nullptr);
|
||||
return self->display_monitor;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "flutter/shell/platform/linux/fl_display_monitor.h"
|
||||
#include "flutter/shell/platform/linux/fl_keyboard_manager.h"
|
||||
#include "flutter/shell/platform/linux/fl_mouse_cursor_handler.h"
|
||||
#include "flutter/shell/platform/linux/fl_opengl_manager.h"
|
||||
#include "flutter/shell/platform/linux/fl_renderable.h"
|
||||
#include "flutter/shell/platform/linux/fl_renderer.h"
|
||||
#include "flutter/shell/platform/linux/fl_task_runner.h"
|
||||
@@ -62,18 +63,6 @@ typedef gboolean (*FlEnginePlatformMessageHandler)(
|
||||
FlEngine* fl_engine_new_with_binary_messenger(
|
||||
FlBinaryMessenger* binary_messenger);
|
||||
|
||||
/**
|
||||
* fl_engine_new_with_renderer:
|
||||
* @project: an #FlDartProject.
|
||||
* @renderer: an #FlRenderer.
|
||||
*
|
||||
* Creates new Flutter engine.
|
||||
*
|
||||
* Returns: a new #FlEngine.
|
||||
*/
|
||||
FlEngine* fl_engine_new_with_renderer(FlDartProject* project,
|
||||
FlRenderer* renderer);
|
||||
|
||||
/**
|
||||
* fl_engine_get_renderer:
|
||||
* @engine: an #FlEngine.
|
||||
@@ -84,6 +73,16 @@ FlEngine* fl_engine_new_with_renderer(FlDartProject* project,
|
||||
*/
|
||||
FlRenderer* fl_engine_get_renderer(FlEngine* engine);
|
||||
|
||||
/**
|
||||
* fl_engine_get_opengl_manager:
|
||||
* @engine: an #FlEngine.
|
||||
*
|
||||
* Gets the OpenGL manager used by this engine.
|
||||
*
|
||||
* Returns: an #FlOpenGLManager.
|
||||
*/
|
||||
FlOpenGLManager* fl_engine_get_opengl_manager(FlEngine* engine);
|
||||
|
||||
/**
|
||||
* fl_engine_get_display_monitor:
|
||||
* @engine: an #FlEngine.
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
|
||||
#include "flutter/shell/platform/linux/public/flutter_linux/fl_json_message_codec.h"
|
||||
#include "flutter/shell/platform/linux/public/flutter_linux/fl_string_codec.h"
|
||||
#include "flutter/shell/platform/linux/testing/mock_renderer.h"
|
||||
#include "flutter/shell/platform/linux/testing/mock_renderable.h"
|
||||
|
||||
// MOCK_ENGINE_PROC is leaky by design
|
||||
// NOLINTBEGIN(clang-analyzer-core.StackAddressEscape)
|
||||
|
||||
92
engine/src/flutter/shell/platform/linux/fl_opengl_manager.cc
Normal file
92
engine/src/flutter/shell/platform/linux/fl_opengl_manager.cc
Normal file
@@ -0,0 +1,92 @@
|
||||
// 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/linux/fl_opengl_manager.h"
|
||||
|
||||
struct _FlOpenGLManager {
|
||||
GObject parent_instance;
|
||||
|
||||
// OpenGL rendering context used by GDK.
|
||||
GdkGLContext* gdk_context;
|
||||
|
||||
// Main OpenGL rendering context used by Flutter.
|
||||
GdkGLContext* main_context;
|
||||
|
||||
// OpenGL rendering context used by a Flutter background thread for
|
||||
// asynchronous texture uploads.
|
||||
GdkGLContext* resource_context;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(FlOpenGLManager, fl_opengl_manager, G_TYPE_OBJECT)
|
||||
|
||||
static void fl_opengl_manager_dispose(GObject* object) {
|
||||
FlOpenGLManager* self = FL_OPENGL_MANAGER(object);
|
||||
|
||||
g_clear_object(&self->gdk_context);
|
||||
g_clear_object(&self->main_context);
|
||||
g_clear_object(&self->resource_context);
|
||||
|
||||
G_OBJECT_CLASS(fl_opengl_manager_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void fl_opengl_manager_class_init(FlOpenGLManagerClass* klass) {
|
||||
G_OBJECT_CLASS(klass)->dispose = fl_opengl_manager_dispose;
|
||||
}
|
||||
|
||||
static void fl_opengl_manager_init(FlOpenGLManager* self) {}
|
||||
|
||||
FlOpenGLManager* fl_opengl_manager_new() {
|
||||
FlOpenGLManager* self =
|
||||
FL_OPENGL_MANAGER(g_object_new(fl_opengl_manager_get_type(), nullptr));
|
||||
return self;
|
||||
}
|
||||
|
||||
gboolean fl_opengl_manager_create_contexts(FlOpenGLManager* self,
|
||||
GdkWindow* window,
|
||||
GError** error) {
|
||||
g_return_val_if_fail(FL_IS_OPENGL_MANAGER(self), FALSE);
|
||||
|
||||
self->gdk_context = gdk_window_create_gl_context(window, error);
|
||||
if (self->gdk_context == nullptr) {
|
||||
return FALSE;
|
||||
}
|
||||
if (!gdk_gl_context_realize(self->gdk_context, error)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
self->main_context = gdk_window_create_gl_context(window, error);
|
||||
if (self->main_context == nullptr) {
|
||||
return FALSE;
|
||||
}
|
||||
if (!gdk_gl_context_realize(self->main_context, error)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
self->resource_context = gdk_window_create_gl_context(window, error);
|
||||
if (self->resource_context == nullptr) {
|
||||
return FALSE;
|
||||
}
|
||||
if (!gdk_gl_context_realize(self->resource_context, error)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GdkGLContext* fl_opengl_manager_get_context(FlOpenGLManager* self) {
|
||||
g_return_val_if_fail(FL_IS_OPENGL_MANAGER(self), nullptr);
|
||||
return self->gdk_context;
|
||||
}
|
||||
|
||||
void fl_opengl_manager_make_current(FlOpenGLManager* self) {
|
||||
gdk_gl_context_make_current(self->main_context);
|
||||
}
|
||||
|
||||
void fl_opengl_manager_make_resource_current(FlOpenGLManager* self) {
|
||||
gdk_gl_context_make_current(self->resource_context);
|
||||
}
|
||||
|
||||
void fl_opengl_manager_clear_current(FlOpenGLManager* self) {
|
||||
gdk_gl_context_clear_current();
|
||||
}
|
||||
76
engine/src/flutter/shell/platform/linux/fl_opengl_manager.h
Normal file
76
engine/src/flutter/shell/platform/linux/fl_opengl_manager.h
Normal file
@@ -0,0 +1,76 @@
|
||||
// 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_LINUX_FL_OPENGL_MANAGER_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_OPENGL_MANAGER_H_
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_DECLARE_FINAL_TYPE(FlOpenGLManager,
|
||||
fl_opengl_manager,
|
||||
FL,
|
||||
OPENGL_MANAGER,
|
||||
GObject)
|
||||
|
||||
/**
|
||||
* fl_opengl_manager_new:
|
||||
*
|
||||
* Creates an object that allows Flutter to render by OpenGL ES.
|
||||
*
|
||||
* Returns: a new #FlOpenGLManager.
|
||||
*/
|
||||
FlOpenGLManager* fl_opengl_manager_new();
|
||||
|
||||
/**
|
||||
* fl_opengl_manager_create_contexts:
|
||||
* @manager: an #FlOpenGLManager.
|
||||
* @window: the window that is being rendered on.
|
||||
* @error: (allow-none): #GError location to store the error occurring, or
|
||||
* %NULL to ignore.
|
||||
*
|
||||
* Create rendering contexts.
|
||||
*
|
||||
* Returns: %TRUE if contexts were created, %FALSE if there was an error.
|
||||
*/
|
||||
gboolean fl_opengl_manager_create_contexts(FlOpenGLManager* manager,
|
||||
GdkWindow* window,
|
||||
GError** error);
|
||||
|
||||
/**
|
||||
* fl_opengl_manager_get_context:
|
||||
* @manager: an #FlOpenGLManager.
|
||||
*
|
||||
* Returns: the main context used for rendering.
|
||||
*/
|
||||
GdkGLContext* fl_opengl_manager_get_context(FlOpenGLManager* manager);
|
||||
|
||||
/**
|
||||
* fl_opengl_manager_make_current:
|
||||
* @manager: an #FlOpenGLManager.
|
||||
*
|
||||
* Makes the rendering context current.
|
||||
*/
|
||||
void fl_opengl_manager_make_current(FlOpenGLManager* manager);
|
||||
|
||||
/**
|
||||
* fl_opengl_manager_make_resource_current:
|
||||
* @manager: an #FlOpenGLManager.
|
||||
*
|
||||
* Makes the resource rendering context current.
|
||||
*/
|
||||
void fl_opengl_manager_make_resource_current(FlOpenGLManager* manager);
|
||||
|
||||
/**
|
||||
* fl_opengl_manager_clear_current:
|
||||
* @manager: an #FlOpenGLManager.
|
||||
*
|
||||
* Clears the current rendering context.
|
||||
*/
|
||||
void fl_opengl_manager_clear_current(FlOpenGLManager* manager);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_OPENGL_MANAGER_H_
|
||||
@@ -38,10 +38,15 @@ static const char* fragment_shader_src =
|
||||
|
||||
G_DEFINE_QUARK(fl_renderer_error_quark, fl_renderer_error)
|
||||
|
||||
typedef struct {
|
||||
struct _FlRenderer {
|
||||
GObject parent_instance;
|
||||
|
||||
// Engine we are rendering.
|
||||
GWeakRef engine;
|
||||
|
||||
// OpenGL contexts.
|
||||
FlOpenGLManager* opengl_manager;
|
||||
|
||||
// Flag to track lazy initialization.
|
||||
gboolean initialized;
|
||||
|
||||
@@ -78,9 +83,9 @@ typedef struct {
|
||||
// Condition to unblock the raster thread after task is completed on platform
|
||||
// thread.
|
||||
GCond present_condition;
|
||||
} FlRendererPrivate;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE(FlRenderer, fl_renderer, G_TYPE_OBJECT)
|
||||
G_DEFINE_TYPE(FlRenderer, fl_renderer, G_TYPE_OBJECT)
|
||||
|
||||
// Check if running on an NVIDIA driver.
|
||||
static gboolean is_nvidia() {
|
||||
@@ -127,30 +132,25 @@ static GLfloat pixels_to_gl_coords(GLfloat position, GLfloat pixels) {
|
||||
|
||||
// Perform single run OpenGL initialization.
|
||||
static void initialize(FlRenderer* self) {
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
|
||||
if (priv->initialized) {
|
||||
if (self->initialized) {
|
||||
return;
|
||||
}
|
||||
priv->initialized = TRUE;
|
||||
self->initialized = TRUE;
|
||||
|
||||
if (epoxy_has_gl_extension("GL_EXT_texture_format_BGRA8888")) {
|
||||
priv->sized_format = GL_BGRA8_EXT;
|
||||
priv->general_format = GL_BGRA_EXT;
|
||||
self->sized_format = GL_BGRA8_EXT;
|
||||
self->general_format = GL_BGRA_EXT;
|
||||
} else {
|
||||
priv->sized_format = GL_RGBA8;
|
||||
priv->general_format = GL_RGBA;
|
||||
self->sized_format = GL_RGBA8;
|
||||
self->general_format = GL_RGBA;
|
||||
}
|
||||
}
|
||||
|
||||
static void fl_renderer_unblock_main_thread(FlRenderer* self) {
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
if (priv->blocking_main_thread) {
|
||||
priv->blocking_main_thread = false;
|
||||
if (self->blocking_main_thread) {
|
||||
self->blocking_main_thread = false;
|
||||
|
||||
g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&priv->engine));
|
||||
g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
|
||||
if (engine != nullptr) {
|
||||
fl_task_runner_release_main_thread(fl_engine_get_task_runner(engine));
|
||||
}
|
||||
@@ -158,9 +158,6 @@ static void fl_renderer_unblock_main_thread(FlRenderer* self) {
|
||||
}
|
||||
|
||||
static void setup_shader(FlRenderer* self) {
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
|
||||
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex_shader, 1, &vertex_shader_src, nullptr);
|
||||
glCompileShader(vertex_shader);
|
||||
@@ -181,15 +178,15 @@ static void setup_shader(FlRenderer* self) {
|
||||
g_warning("Failed to compile fragment shader: %s", shader_log);
|
||||
}
|
||||
|
||||
priv->program = glCreateProgram();
|
||||
glAttachShader(priv->program, vertex_shader);
|
||||
glAttachShader(priv->program, fragment_shader);
|
||||
glLinkProgram(priv->program);
|
||||
self->program = glCreateProgram();
|
||||
glAttachShader(self->program, vertex_shader);
|
||||
glAttachShader(self->program, fragment_shader);
|
||||
glLinkProgram(self->program);
|
||||
|
||||
GLint link_status;
|
||||
glGetProgramiv(priv->program, GL_LINK_STATUS, &link_status);
|
||||
glGetProgramiv(self->program, GL_LINK_STATUS, &link_status);
|
||||
if (link_status == GL_FALSE) {
|
||||
g_autofree gchar* program_log = get_program_log(priv->program);
|
||||
g_autofree gchar* program_log = get_program_log(self->program);
|
||||
g_warning("Failed to link program: %s", program_log);
|
||||
}
|
||||
|
||||
@@ -221,9 +218,6 @@ static void render_with_textures(FlRenderer* self,
|
||||
GPtrArray* framebuffers,
|
||||
int width,
|
||||
int height) {
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
|
||||
// Save bindings that are set by this function. All bindings must be restored
|
||||
// to their original values because Skia expects that its bindings have not
|
||||
// been altered.
|
||||
@@ -237,7 +231,7 @@ static void render_with_textures(FlRenderer* self,
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glUseProgram(priv->program);
|
||||
glUseProgram(self->program);
|
||||
|
||||
for (guint i = 0; i < framebuffers->len; i++) {
|
||||
FlFramebuffer* framebuffer =
|
||||
@@ -263,11 +257,11 @@ static void render_with_textures(FlRenderer* self,
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
|
||||
GL_STATIC_DRAW);
|
||||
GLint position_index = glGetAttribLocation(priv->program, "position");
|
||||
GLint position_index = glGetAttribLocation(self->program, "position");
|
||||
glEnableVertexAttribArray(position_index);
|
||||
glVertexAttribPointer(position_index, 2, GL_FLOAT, GL_FALSE,
|
||||
sizeof(GLfloat) * 4, 0);
|
||||
GLint texcoord_index = glGetAttribLocation(priv->program, "in_texcoord");
|
||||
GLint texcoord_index = glGetAttribLocation(self->program, "in_texcoord");
|
||||
glEnableVertexAttribArray(texcoord_index);
|
||||
glVertexAttribPointer(texcoord_index, 2, GL_FLOAT, GL_FALSE,
|
||||
sizeof(GLfloat) * 4,
|
||||
@@ -290,10 +284,7 @@ static void render(FlRenderer* self,
|
||||
GPtrArray* framebuffers,
|
||||
int width,
|
||||
int height) {
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
|
||||
if (priv->has_gl_framebuffer_blit) {
|
||||
if (self->has_gl_framebuffer_blit) {
|
||||
render_with_blit(self, framebuffers);
|
||||
} else {
|
||||
render_with_textures(self, framebuffers, width, height);
|
||||
@@ -304,21 +295,18 @@ static gboolean present_layers(FlRenderer* self,
|
||||
FlutterViewId view_id,
|
||||
const FlutterLayer** layers,
|
||||
size_t layers_count) {
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
|
||||
g_return_val_if_fail(FL_IS_RENDERER(self), FALSE);
|
||||
|
||||
// ignore incoming frame with wrong dimensions in trivial case with just one
|
||||
// layer
|
||||
if (priv->blocking_main_thread && layers_count == 1 &&
|
||||
if (self->blocking_main_thread && layers_count == 1 &&
|
||||
layers[0]->offset.x == 0 && layers[0]->offset.y == 0 &&
|
||||
(layers[0]->size.width != priv->target_width ||
|
||||
layers[0]->size.height != priv->target_height)) {
|
||||
(layers[0]->size.width != self->target_width ||
|
||||
layers[0]->size.height != self->target_height)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
priv->had_first_frame = true;
|
||||
self->had_first_frame = true;
|
||||
|
||||
fl_renderer_unblock_main_thread(self);
|
||||
|
||||
@@ -340,7 +328,7 @@ static gboolean present_layers(FlRenderer* self,
|
||||
}
|
||||
}
|
||||
|
||||
g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&priv->engine));
|
||||
g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
|
||||
if (engine == nullptr) {
|
||||
return TRUE;
|
||||
}
|
||||
@@ -352,7 +340,7 @@ static gboolean present_layers(FlRenderer* self,
|
||||
|
||||
if (view_id == flutter::kFlutterImplicitViewId) {
|
||||
// Store for rendering later
|
||||
g_hash_table_insert(priv->framebuffers_by_view_id, GINT_TO_POINTER(view_id),
|
||||
g_hash_table_insert(self->framebuffers_by_view_id, GINT_TO_POINTER(view_id),
|
||||
g_ptr_array_ref(framebuffers));
|
||||
} else {
|
||||
// Composite into a single framebuffer.
|
||||
@@ -374,7 +362,7 @@ static gboolean present_layers(FlRenderer* self,
|
||||
}
|
||||
|
||||
FlFramebuffer* view_framebuffer =
|
||||
fl_framebuffer_new(priv->general_format, width, height);
|
||||
fl_framebuffer_new(self->general_format, width, height);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
|
||||
fl_framebuffer_get_id(view_framebuffer));
|
||||
render(self, framebuffers, width, height);
|
||||
@@ -390,13 +378,13 @@ static gboolean present_layers(FlRenderer* self,
|
||||
size_t data_length = width * height * 4;
|
||||
g_autofree uint8_t* data = static_cast<uint8_t*>(malloc(data_length));
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fl_framebuffer_get_id(framebuffer));
|
||||
glReadPixels(0, 0, width, height, priv->general_format, GL_UNSIGNED_BYTE,
|
||||
glReadPixels(0, 0, width, height, self->general_format, GL_UNSIGNED_BYTE,
|
||||
data);
|
||||
|
||||
// Write into a texture in the views context.
|
||||
fl_renderable_make_current(renderable);
|
||||
FlFramebuffer* view_framebuffer =
|
||||
fl_framebuffer_new(priv->general_format, width, height);
|
||||
fl_framebuffer_new(self->general_format, width, height);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
|
||||
fl_framebuffer_get_id(view_framebuffer));
|
||||
glBindTexture(GL_TEXTURE_2D,
|
||||
@@ -407,7 +395,7 @@ static gboolean present_layers(FlRenderer* self,
|
||||
g_autoptr(GPtrArray) secondary_framebuffers =
|
||||
g_ptr_array_new_with_free_func(g_object_unref);
|
||||
g_ptr_array_add(secondary_framebuffers, g_object_ref(view_framebuffer));
|
||||
g_hash_table_insert(priv->framebuffers_by_view_id, GINT_TO_POINTER(view_id),
|
||||
g_hash_table_insert(self->framebuffers_by_view_id, GINT_TO_POINTER(view_id),
|
||||
g_ptr_array_ref(secondary_framebuffers));
|
||||
}
|
||||
|
||||
@@ -432,32 +420,30 @@ typedef struct {
|
||||
// Perform the present on the main thread.
|
||||
static void present_layers_task_cb(gpointer user_data) {
|
||||
PresentLayersData* data = static_cast<PresentLayersData*>(user_data);
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(data->self));
|
||||
FlRenderer* self = data->self;
|
||||
|
||||
// Perform the present.
|
||||
fl_renderer_make_current(data->self);
|
||||
data->result = present_layers(data->self, data->view_id, data->layers,
|
||||
data->layers_count);
|
||||
fl_renderer_clear_current(data->self);
|
||||
fl_opengl_manager_make_current(self->opengl_manager);
|
||||
data->result =
|
||||
present_layers(self, data->view_id, data->layers, data->layers_count);
|
||||
fl_opengl_manager_clear_current(self->opengl_manager);
|
||||
|
||||
// Complete fl_renderer_present_layers().
|
||||
g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&priv->present_mutex);
|
||||
g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->present_mutex);
|
||||
data->finished = TRUE;
|
||||
g_cond_signal(&priv->present_condition);
|
||||
g_cond_signal(&self->present_condition);
|
||||
}
|
||||
|
||||
static void fl_renderer_dispose(GObject* object) {
|
||||
FlRenderer* self = FL_RENDERER(object);
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
|
||||
fl_renderer_unblock_main_thread(self);
|
||||
|
||||
g_weak_ref_clear(&priv->engine);
|
||||
g_clear_pointer(&priv->framebuffers_by_view_id, g_hash_table_unref);
|
||||
g_mutex_clear(&priv->present_mutex);
|
||||
g_cond_clear(&priv->present_condition);
|
||||
g_weak_ref_clear(&self->engine);
|
||||
g_clear_object(&self->opengl_manager);
|
||||
g_clear_pointer(&self->framebuffers_by_view_id, g_hash_table_unref);
|
||||
g_mutex_clear(&self->present_mutex);
|
||||
g_cond_clear(&self->present_condition);
|
||||
|
||||
G_OBJECT_CLASS(fl_renderer_parent_class)->dispose(object);
|
||||
}
|
||||
@@ -467,65 +453,33 @@ static void fl_renderer_class_init(FlRendererClass* klass) {
|
||||
}
|
||||
|
||||
static void fl_renderer_init(FlRenderer* self) {
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
priv->framebuffers_by_view_id = g_hash_table_new_full(
|
||||
self->framebuffers_by_view_id = g_hash_table_new_full(
|
||||
g_direct_hash, g_direct_equal, nullptr,
|
||||
reinterpret_cast<GDestroyNotify>(g_ptr_array_unref));
|
||||
g_mutex_init(&priv->present_mutex);
|
||||
g_cond_init(&priv->present_condition);
|
||||
g_mutex_init(&self->present_mutex);
|
||||
g_cond_init(&self->present_condition);
|
||||
}
|
||||
|
||||
void fl_renderer_set_engine(FlRenderer* self, FlEngine* engine) {
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
FlRenderer* fl_renderer_new(FlEngine* engine) {
|
||||
FlRenderer* self = FL_RENDERER(g_object_new(fl_renderer_get_type(), nullptr));
|
||||
|
||||
g_return_if_fail(FL_IS_RENDERER(self));
|
||||
g_weak_ref_init(&self->engine, engine);
|
||||
self->opengl_manager =
|
||||
FL_OPENGL_MANAGER(g_object_ref(fl_engine_get_opengl_manager(engine)));
|
||||
|
||||
g_weak_ref_init(&priv->engine, engine);
|
||||
}
|
||||
|
||||
void* fl_renderer_get_proc_address(FlRenderer* self, const char* name) {
|
||||
g_return_val_if_fail(FL_IS_RENDERER(self), NULL);
|
||||
|
||||
return reinterpret_cast<void*>(eglGetProcAddress(name));
|
||||
}
|
||||
|
||||
void fl_renderer_make_current(FlRenderer* self) {
|
||||
g_return_if_fail(FL_IS_RENDERER(self));
|
||||
FL_RENDERER_GET_CLASS(self)->make_current(self);
|
||||
}
|
||||
|
||||
void fl_renderer_make_resource_current(FlRenderer* self) {
|
||||
g_return_if_fail(FL_IS_RENDERER(self));
|
||||
FL_RENDERER_GET_CLASS(self)->make_resource_current(self);
|
||||
}
|
||||
|
||||
void fl_renderer_clear_current(FlRenderer* self) {
|
||||
g_return_if_fail(FL_IS_RENDERER(self));
|
||||
FL_RENDERER_GET_CLASS(self)->clear_current(self);
|
||||
}
|
||||
|
||||
guint32 fl_renderer_get_fbo(FlRenderer* self) {
|
||||
g_return_val_if_fail(FL_IS_RENDERER(self), 0);
|
||||
|
||||
// There is only one frame buffer object - always return that.
|
||||
return 0;
|
||||
return self;
|
||||
}
|
||||
|
||||
gboolean fl_renderer_create_backing_store(
|
||||
FlRenderer* self,
|
||||
const FlutterBackingStoreConfig* config,
|
||||
FlutterBackingStore* backing_store_out) {
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
|
||||
fl_renderer_make_current(self);
|
||||
fl_opengl_manager_make_current(self->opengl_manager);
|
||||
|
||||
initialize(self);
|
||||
|
||||
FlFramebuffer* framebuffer = fl_framebuffer_new(
|
||||
priv->general_format, config->size.width, config->size.height);
|
||||
self->general_format, config->size.width, config->size.height);
|
||||
if (!framebuffer) {
|
||||
g_warning("Failed to create backing store");
|
||||
return FALSE;
|
||||
@@ -536,7 +490,7 @@ gboolean fl_renderer_create_backing_store(
|
||||
backing_store_out->open_gl.framebuffer.user_data = framebuffer;
|
||||
backing_store_out->open_gl.framebuffer.name =
|
||||
fl_framebuffer_get_id(framebuffer);
|
||||
backing_store_out->open_gl.framebuffer.target = priv->sized_format;
|
||||
backing_store_out->open_gl.framebuffer.target = self->sized_format;
|
||||
backing_store_out->open_gl.framebuffer.destruction_callback = [](void* p) {
|
||||
// Backing store destroyed in fl_renderer_collect_backing_store(), set
|
||||
// on FlutterCompositor.collect_backing_store_callback during engine start.
|
||||
@@ -548,7 +502,7 @@ gboolean fl_renderer_create_backing_store(
|
||||
gboolean fl_renderer_collect_backing_store(
|
||||
FlRenderer* self,
|
||||
const FlutterBackingStore* backing_store) {
|
||||
fl_renderer_make_current(self);
|
||||
fl_opengl_manager_make_current(self->opengl_manager);
|
||||
|
||||
// OpenGL context is required when destroying #FlFramebuffer.
|
||||
g_object_unref(backing_store->open_gl.framebuffer.user_data);
|
||||
@@ -558,17 +512,14 @@ gboolean fl_renderer_collect_backing_store(
|
||||
void fl_renderer_wait_for_frame(FlRenderer* self,
|
||||
int target_width,
|
||||
int target_height) {
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
|
||||
g_return_if_fail(FL_IS_RENDERER(self));
|
||||
|
||||
priv->target_width = target_width;
|
||||
priv->target_height = target_height;
|
||||
self->target_width = target_width;
|
||||
self->target_height = target_height;
|
||||
|
||||
if (priv->had_first_frame && !priv->blocking_main_thread) {
|
||||
priv->blocking_main_thread = true;
|
||||
g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&priv->engine));
|
||||
if (self->had_first_frame && !self->blocking_main_thread) {
|
||||
self->blocking_main_thread = true;
|
||||
g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
|
||||
if (engine != nullptr) {
|
||||
fl_task_runner_block_main_thread(fl_engine_get_task_runner(engine));
|
||||
}
|
||||
@@ -581,11 +532,9 @@ gboolean fl_renderer_present_layers(FlRenderer* self,
|
||||
size_t layers_count) {
|
||||
// Detach the context from raster thread. Needed because blitting
|
||||
// will be done on the main thread, which will make the context current.
|
||||
fl_renderer_clear_current(self);
|
||||
fl_opengl_manager_clear_current(self->opengl_manager);
|
||||
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&priv->engine));
|
||||
g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
|
||||
|
||||
// Schedule the present to run on the main thread.
|
||||
FlTaskRunner* task_runner = fl_engine_get_task_runner(engine);
|
||||
@@ -600,32 +549,29 @@ gboolean fl_renderer_present_layers(FlRenderer* self,
|
||||
fl_task_runner_post_callback(task_runner, present_layers_task_cb, &data);
|
||||
|
||||
// Block until present completes.
|
||||
g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&priv->present_mutex);
|
||||
g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->present_mutex);
|
||||
while (!data.finished) {
|
||||
g_cond_wait(&priv->present_condition, &priv->present_mutex);
|
||||
g_cond_wait(&self->present_condition, &self->present_mutex);
|
||||
}
|
||||
|
||||
// Restore the context to the raster thread in case the engine needs it
|
||||
// to do some cleanup.
|
||||
fl_renderer_make_current(self);
|
||||
fl_opengl_manager_make_current(self->opengl_manager);
|
||||
|
||||
return data.result;
|
||||
}
|
||||
|
||||
void fl_renderer_setup(FlRenderer* self) {
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
|
||||
g_return_if_fail(FL_IS_RENDERER(self));
|
||||
|
||||
// Note: NVIDIA and Vivante are temporarily disabled due to
|
||||
// https://github.com/flutter/flutter/issues/152099
|
||||
priv->has_gl_framebuffer_blit =
|
||||
self->has_gl_framebuffer_blit =
|
||||
!is_nvidia() && !is_vivante() &&
|
||||
(epoxy_gl_version() >= 30 ||
|
||||
epoxy_has_gl_extension("GL_EXT_framebuffer_blit"));
|
||||
|
||||
if (!priv->has_gl_framebuffer_blit) {
|
||||
if (!self->has_gl_framebuffer_blit) {
|
||||
setup_shader(self);
|
||||
}
|
||||
}
|
||||
@@ -635,9 +581,6 @@ void fl_renderer_render(FlRenderer* self,
|
||||
int width,
|
||||
int height,
|
||||
const GdkRGBA* background_color) {
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
|
||||
g_return_if_fail(FL_IS_RENDERER(self));
|
||||
|
||||
glClearColor(background_color->red, background_color->green,
|
||||
@@ -645,7 +588,7 @@ void fl_renderer_render(FlRenderer* self,
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
GPtrArray* framebuffers = reinterpret_cast<GPtrArray*>((g_hash_table_lookup(
|
||||
priv->framebuffers_by_view_id, GINT_TO_POINTER(view_id))));
|
||||
self->framebuffers_by_view_id, GINT_TO_POINTER(view_id))));
|
||||
if (framebuffers != nullptr) {
|
||||
render(self, framebuffers, width, height);
|
||||
}
|
||||
@@ -654,12 +597,9 @@ void fl_renderer_render(FlRenderer* self,
|
||||
}
|
||||
|
||||
void fl_renderer_cleanup(FlRenderer* self) {
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
|
||||
g_return_if_fail(FL_IS_RENDERER(self));
|
||||
|
||||
if (priv->program != 0) {
|
||||
glDeleteProgram(priv->program);
|
||||
if (self->program != 0) {
|
||||
glDeleteProgram(self->program);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ typedef enum {
|
||||
|
||||
GQuark fl_renderer_error_quark(void) G_GNUC_CONST;
|
||||
|
||||
G_DECLARE_DERIVABLE_TYPE(FlRenderer, fl_renderer, FL, RENDERER, GObject)
|
||||
G_DECLARE_FINAL_TYPE(FlRenderer, fl_renderer, FL, RENDERER, GObject)
|
||||
|
||||
/**
|
||||
* FlRenderer:
|
||||
@@ -33,83 +33,15 @@ G_DECLARE_DERIVABLE_TYPE(FlRenderer, fl_renderer, FL, RENDERER, GObject)
|
||||
* #FlRenderer is an abstract class that allows Flutter to draw pixels.
|
||||
*/
|
||||
|
||||
struct _FlRendererClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
/**
|
||||
* Virtual method called when Flutter needs to make the OpenGL context
|
||||
* current.
|
||||
* @renderer: an #FlRenderer.
|
||||
*/
|
||||
void (*make_current)(FlRenderer* renderer);
|
||||
|
||||
/**
|
||||
* Virtual method called when Flutter needs to make the OpenGL resource
|
||||
* context current.
|
||||
* @renderer: an #FlRenderer.
|
||||
*/
|
||||
void (*make_resource_current)(FlRenderer* renderer);
|
||||
|
||||
/**
|
||||
* Virtual method called when Flutter needs to clear the OpenGL context.
|
||||
* @renderer: an #FlRenderer.
|
||||
*/
|
||||
void (*clear_current)(FlRenderer* renderer);
|
||||
};
|
||||
|
||||
/**
|
||||
* fl_renderer_set_engine:
|
||||
* @renderer: an #FlRenderer.
|
||||
* fl_renderer_new:
|
||||
* @engine: an #FlEngine.
|
||||
*
|
||||
* Called when the renderer is connected to an engine.
|
||||
* Creates a new renderer.
|
||||
*
|
||||
* Returns: a new #FlRenderer.
|
||||
*/
|
||||
void fl_renderer_set_engine(FlRenderer* renderer, FlEngine* engine);
|
||||
|
||||
/**
|
||||
* fl_renderer_get_proc_address:
|
||||
* @renderer: an #FlRenderer.
|
||||
* @name: a function name.
|
||||
*
|
||||
* Gets the rendering API function that matches the given name.
|
||||
*
|
||||
* Returns: a function pointer.
|
||||
*/
|
||||
void* fl_renderer_get_proc_address(FlRenderer* renderer, const char* name);
|
||||
|
||||
/**
|
||||
* fl_renderer_make_current:
|
||||
* @renderer: an #FlRenderer.
|
||||
*
|
||||
* Makes the rendering context current.
|
||||
*/
|
||||
void fl_renderer_make_current(FlRenderer* renderer);
|
||||
|
||||
/**
|
||||
* fl_renderer_make_resource_current:
|
||||
* @renderer: an #FlRenderer.
|
||||
*
|
||||
* Makes the resource rendering context current.
|
||||
*/
|
||||
void fl_renderer_make_resource_current(FlRenderer* renderer);
|
||||
|
||||
/**
|
||||
* fl_renderer_clear_current:
|
||||
* @renderer: an #FlRenderer.
|
||||
*
|
||||
* Clears the current rendering context.
|
||||
*/
|
||||
void fl_renderer_clear_current(FlRenderer* renderer);
|
||||
|
||||
/**
|
||||
* fl_renderer_get_fbo:
|
||||
* @renderer: an #FlRenderer.
|
||||
*
|
||||
* Gets the frame buffer object to render to.
|
||||
*
|
||||
* Returns: a frame buffer object index.
|
||||
*/
|
||||
guint32 fl_renderer_get_fbo(FlRenderer* renderer);
|
||||
FlRenderer* fl_renderer_new(FlEngine* engine);
|
||||
|
||||
/**
|
||||
* fl_renderer_create_backing_store:
|
||||
|
||||
@@ -1,109 +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 "flutter/shell/platform/linux/fl_renderer_gdk.h"
|
||||
|
||||
struct _FlRendererGdk {
|
||||
FlRenderer parent_instance;
|
||||
|
||||
// Window being rendered on.
|
||||
GdkWindow* window;
|
||||
|
||||
// OpenGL rendering context used by GDK.
|
||||
GdkGLContext* gdk_context;
|
||||
|
||||
// Main OpenGL rendering context used by Flutter.
|
||||
GdkGLContext* main_context;
|
||||
|
||||
// Secondary OpenGL rendering context used by Flutter.
|
||||
GdkGLContext* resource_context;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(FlRendererGdk, fl_renderer_gdk, fl_renderer_get_type())
|
||||
|
||||
// Implements FlRenderer::make_current.
|
||||
static void fl_renderer_gdk_make_current(FlRenderer* renderer) {
|
||||
FlRendererGdk* self = FL_RENDERER_GDK(renderer);
|
||||
gdk_gl_context_make_current(self->main_context);
|
||||
}
|
||||
|
||||
// Implements FlRenderer::make_resource_current.
|
||||
static void fl_renderer_gdk_make_resource_current(FlRenderer* renderer) {
|
||||
FlRendererGdk* self = FL_RENDERER_GDK(renderer);
|
||||
gdk_gl_context_make_current(self->resource_context);
|
||||
}
|
||||
|
||||
// Implements FlRenderer::clear_current.
|
||||
static void fl_renderer_gdk_clear_current(FlRenderer* renderer) {
|
||||
gdk_gl_context_clear_current();
|
||||
}
|
||||
|
||||
static void fl_renderer_gdk_dispose(GObject* object) {
|
||||
FlRendererGdk* self = FL_RENDERER_GDK(object);
|
||||
|
||||
g_clear_object(&self->gdk_context);
|
||||
g_clear_object(&self->main_context);
|
||||
g_clear_object(&self->resource_context);
|
||||
|
||||
G_OBJECT_CLASS(fl_renderer_gdk_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void fl_renderer_gdk_class_init(FlRendererGdkClass* klass) {
|
||||
G_OBJECT_CLASS(klass)->dispose = fl_renderer_gdk_dispose;
|
||||
|
||||
FL_RENDERER_CLASS(klass)->make_current = fl_renderer_gdk_make_current;
|
||||
FL_RENDERER_CLASS(klass)->make_resource_current =
|
||||
fl_renderer_gdk_make_resource_current;
|
||||
FL_RENDERER_CLASS(klass)->clear_current = fl_renderer_gdk_clear_current;
|
||||
}
|
||||
|
||||
static void fl_renderer_gdk_init(FlRendererGdk* self) {}
|
||||
|
||||
FlRendererGdk* fl_renderer_gdk_new() {
|
||||
FlRendererGdk* self =
|
||||
FL_RENDERER_GDK(g_object_new(fl_renderer_gdk_get_type(), nullptr));
|
||||
return self;
|
||||
}
|
||||
|
||||
void fl_renderer_gdk_set_window(FlRendererGdk* self, GdkWindow* window) {
|
||||
g_return_if_fail(FL_IS_RENDERER_GDK(self));
|
||||
|
||||
g_assert(self->window == nullptr);
|
||||
self->window = window;
|
||||
}
|
||||
|
||||
gboolean fl_renderer_gdk_create_contexts(FlRendererGdk* self, GError** error) {
|
||||
g_return_val_if_fail(FL_IS_RENDERER_GDK(self), FALSE);
|
||||
|
||||
self->gdk_context = gdk_window_create_gl_context(self->window, error);
|
||||
if (self->gdk_context == nullptr) {
|
||||
return FALSE;
|
||||
}
|
||||
if (!gdk_gl_context_realize(self->gdk_context, error)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
self->main_context = gdk_window_create_gl_context(self->window, error);
|
||||
if (self->main_context == nullptr) {
|
||||
return FALSE;
|
||||
}
|
||||
if (!gdk_gl_context_realize(self->main_context, error)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
self->resource_context = gdk_window_create_gl_context(self->window, error);
|
||||
if (self->resource_context == nullptr) {
|
||||
return FALSE;
|
||||
}
|
||||
if (!gdk_gl_context_realize(self->resource_context, error)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GdkGLContext* fl_renderer_gdk_get_context(FlRendererGdk* self) {
|
||||
g_return_val_if_fail(FL_IS_RENDERER_GDK(self), nullptr);
|
||||
return self->gdk_context;
|
||||
}
|
||||
@@ -1,66 +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_PLATFORM_LINUX_FL_RENDERER_GDK_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_GDK_H_
|
||||
|
||||
#include "flutter/shell/platform/linux/fl_renderer.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_DECLARE_FINAL_TYPE(FlRendererGdk,
|
||||
fl_renderer_gdk,
|
||||
FL,
|
||||
RENDERER_GDK,
|
||||
FlRenderer)
|
||||
|
||||
/**
|
||||
* FlRendererGdk:
|
||||
*
|
||||
* #FlRendererGdk is an implementation of #FlRenderer that renders by OpenGL ES.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fl_renderer_gdk_new:
|
||||
*
|
||||
* Creates an object that allows Flutter to render by OpenGL ES.
|
||||
*
|
||||
* Returns: a new #FlRendererGdk.
|
||||
*/
|
||||
FlRendererGdk* fl_renderer_gdk_new();
|
||||
|
||||
/**
|
||||
* fl_renderer_gdk_set_window:
|
||||
* @renderer: an #FlRendererGdk.
|
||||
* @window: the window that is being rendered on.
|
||||
*
|
||||
* Set the window that is being rendered on. This is only called once when the
|
||||
* window is available.
|
||||
*/
|
||||
void fl_renderer_gdk_set_window(FlRendererGdk* renderer, GdkWindow* window);
|
||||
|
||||
/**
|
||||
* fl_renderer_gdk_create_contexts:
|
||||
* @renderer: an #FlRendererGdk.
|
||||
* @error: (allow-none): #GError location to store the error occurring, or
|
||||
* %NULL to ignore.
|
||||
*
|
||||
* Create rendering contexts.
|
||||
*
|
||||
* Returns: %TRUE if contexts were created, %FALSE if there was an error.
|
||||
*/
|
||||
gboolean fl_renderer_gdk_create_contexts(FlRendererGdk* renderer,
|
||||
GError** error);
|
||||
|
||||
/**
|
||||
* fl_renderer_gdk_get_context:
|
||||
* @renderer: an #FlRendererGdk.
|
||||
*
|
||||
* Returns: the main context used for rendering.
|
||||
*/
|
||||
GdkGLContext* fl_renderer_gdk_get_context(FlRendererGdk* renderer);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_GDK_H_
|
||||
@@ -1,34 +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 "fl_renderer_headless.h"
|
||||
|
||||
struct _FlRendererHeadless {
|
||||
FlRenderer parent_instance;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(FlRendererHeadless, fl_renderer_headless, fl_renderer_get_type())
|
||||
|
||||
// Implements FlRenderer::make_current.
|
||||
static void fl_renderer_headless_make_current(FlRenderer* renderer) {}
|
||||
|
||||
// Implements FlRenderer::make_resource_current.
|
||||
static void fl_renderer_headless_make_resource_current(FlRenderer* renderer) {}
|
||||
|
||||
// Implements FlRenderer::clear_current.
|
||||
static void fl_renderer_headless_clear_current(FlRenderer* renderer) {}
|
||||
|
||||
static void fl_renderer_headless_class_init(FlRendererHeadlessClass* klass) {
|
||||
FL_RENDERER_CLASS(klass)->make_current = fl_renderer_headless_make_current;
|
||||
FL_RENDERER_CLASS(klass)->make_resource_current =
|
||||
fl_renderer_headless_make_resource_current;
|
||||
FL_RENDERER_CLASS(klass)->clear_current = fl_renderer_headless_clear_current;
|
||||
}
|
||||
|
||||
static void fl_renderer_headless_init(FlRendererHeadless* self) {}
|
||||
|
||||
FlRendererHeadless* fl_renderer_headless_new() {
|
||||
return FL_RENDERER_HEADLESS(
|
||||
g_object_new(fl_renderer_headless_get_type(), nullptr));
|
||||
}
|
||||
@@ -1,36 +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_PLATFORM_LINUX_FL_RENDERER_HEADLESS_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_HEADLESS_H_
|
||||
|
||||
#include "flutter/shell/platform/linux/fl_renderer.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_DECLARE_FINAL_TYPE(FlRendererHeadless,
|
||||
fl_renderer_headless,
|
||||
FL,
|
||||
RENDERER_HEADLESS,
|
||||
FlRenderer)
|
||||
|
||||
/**
|
||||
* FlRendererHeadless:
|
||||
*
|
||||
* #FlRendererHeadless is an implementation of #FlRenderer that works without a
|
||||
* display.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fl_renderer_headless_new:
|
||||
*
|
||||
* Creates an object that allows Flutter to operate without a display.
|
||||
*
|
||||
* Returns: a new #FlRendererHeadless.
|
||||
*/
|
||||
FlRendererHeadless* fl_renderer_headless_new();
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_HEADLESS_H_
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "flutter/shell/platform/linux/fl_engine_private.h"
|
||||
#include "flutter/shell/platform/linux/fl_framebuffer.h"
|
||||
#include "flutter/shell/platform/linux/testing/mock_epoxy.h"
|
||||
#include "flutter/shell/platform/linux/testing/mock_renderer.h"
|
||||
#include "flutter/shell/platform/linux/testing/mock_renderable.h"
|
||||
|
||||
#include <epoxy/egl.h>
|
||||
|
||||
@@ -28,9 +28,8 @@ TEST(FlRendererTest, BackgroundColor) {
|
||||
EXPECT_CALL(epoxy, glClearColor(0.2, 0.3, 0.4, 0.5));
|
||||
|
||||
g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
|
||||
g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
|
||||
g_autoptr(FlRenderer) renderer = fl_renderer_new(engine);
|
||||
fl_renderer_setup(FL_RENDERER(renderer));
|
||||
fl_renderer_set_engine(FL_RENDERER(renderer), engine);
|
||||
fl_engine_set_implicit_view(engine, FL_RENDERABLE(renderable));
|
||||
fl_renderer_wait_for_frame(FL_RENDERER(renderer), 1024, 1024);
|
||||
FlutterBackingStoreConfig config = {
|
||||
@@ -78,8 +77,7 @@ TEST(FlRendererTest, RestoresGLState) {
|
||||
constexpr int kHeight = 100;
|
||||
|
||||
g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
|
||||
g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
|
||||
fl_renderer_set_engine(FL_RENDERER(renderer), engine);
|
||||
g_autoptr(FlRenderer) renderer = fl_renderer_new(engine);
|
||||
g_autoptr(FlFramebuffer) framebuffer =
|
||||
fl_framebuffer_new(GL_RGB, kWidth, kHeight);
|
||||
|
||||
@@ -145,9 +143,8 @@ TEST(FlRendererTest, BlitFramebuffer) {
|
||||
EXPECT_CALL(epoxy, glBlitFramebuffer);
|
||||
|
||||
g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
|
||||
g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
|
||||
g_autoptr(FlRenderer) renderer = fl_renderer_new(engine);
|
||||
fl_renderer_setup(FL_RENDERER(renderer));
|
||||
fl_renderer_set_engine(FL_RENDERER(renderer), engine);
|
||||
fl_engine_set_implicit_view(engine, FL_RENDERABLE(renderable));
|
||||
fl_renderer_wait_for_frame(FL_RENDERER(renderer), 1024, 1024);
|
||||
FlutterBackingStoreConfig config = {
|
||||
@@ -203,9 +200,8 @@ TEST(FlRendererTest, BlitFramebufferExtension) {
|
||||
EXPECT_CALL(epoxy, glBlitFramebuffer);
|
||||
|
||||
g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
|
||||
g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
|
||||
g_autoptr(FlRenderer) renderer = fl_renderer_new(engine);
|
||||
fl_renderer_setup(FL_RENDERER(renderer));
|
||||
fl_renderer_set_engine(FL_RENDERER(renderer), engine);
|
||||
fl_engine_set_implicit_view(engine, FL_RENDERABLE(renderable));
|
||||
fl_renderer_wait_for_frame(FL_RENDERER(renderer), 1024, 1024);
|
||||
FlutterBackingStoreConfig config = {
|
||||
@@ -254,9 +250,8 @@ TEST(FlRendererTest, NoBlitFramebuffer) {
|
||||
EXPECT_CALL(epoxy, epoxy_gl_version).WillRepeatedly(::testing::Return(20));
|
||||
|
||||
g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
|
||||
g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
|
||||
g_autoptr(FlRenderer) renderer = fl_renderer_new(engine);
|
||||
fl_renderer_setup(FL_RENDERER(renderer));
|
||||
fl_renderer_set_engine(FL_RENDERER(renderer), engine);
|
||||
fl_engine_set_implicit_view(engine, FL_RENDERABLE(renderable));
|
||||
fl_renderer_wait_for_frame(FL_RENDERER(renderer), 1024, 1024);
|
||||
FlutterBackingStoreConfig config = {
|
||||
@@ -308,9 +303,8 @@ TEST(FlRendererTest, BlitFramebufferNvidia) {
|
||||
EXPECT_CALL(epoxy, epoxy_gl_version).WillRepeatedly(::testing::Return(30));
|
||||
|
||||
g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
|
||||
g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
|
||||
g_autoptr(FlRenderer) renderer = fl_renderer_new(engine);
|
||||
fl_renderer_setup(FL_RENDERER(renderer));
|
||||
fl_renderer_set_engine(FL_RENDERER(renderer), engine);
|
||||
fl_engine_set_implicit_view(engine, FL_RENDERABLE(renderable));
|
||||
fl_renderer_wait_for_frame(FL_RENDERER(renderer), 1024, 1024);
|
||||
FlutterBackingStoreConfig config = {
|
||||
@@ -363,9 +357,8 @@ TEST(FlRendererTest, MultiView) {
|
||||
g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
|
||||
g_autoptr(FlMockRenderable) secondary_renderable = fl_mock_renderable_new();
|
||||
|
||||
g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
|
||||
g_autoptr(FlRenderer) renderer = fl_renderer_new(engine);
|
||||
fl_renderer_setup(FL_RENDERER(renderer));
|
||||
fl_renderer_set_engine(FL_RENDERER(renderer), engine);
|
||||
fl_engine_set_implicit_view(engine, FL_RENDERABLE(renderable));
|
||||
FlutterViewId view_id =
|
||||
fl_engine_add_view(engine, FL_RENDERABLE(secondary_renderable), 1024, 768,
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
#include "flutter/shell/platform/linux/fl_accessible_node.h"
|
||||
#include "flutter/shell/platform/linux/fl_engine_private.h"
|
||||
#include "flutter/shell/platform/linux/fl_key_event.h"
|
||||
#include "flutter/shell/platform/linux/fl_opengl_manager.h"
|
||||
#include "flutter/shell/platform/linux/fl_plugin_registrar_private.h"
|
||||
#include "flutter/shell/platform/linux/fl_pointer_manager.h"
|
||||
#include "flutter/shell/platform/linux/fl_renderer_gdk.h"
|
||||
#include "flutter/shell/platform/linux/fl_scrolling_manager.h"
|
||||
#include "flutter/shell/platform/linux/fl_socket_accessible.h"
|
||||
#include "flutter/shell/platform/linux/fl_touch_manager.h"
|
||||
@@ -43,9 +43,6 @@ struct _FlView {
|
||||
// ID for this view.
|
||||
FlutterViewId view_id;
|
||||
|
||||
// Object that performs the view rendering.
|
||||
FlRendererGdk* renderer;
|
||||
|
||||
// Background color.
|
||||
GdkRGBA* background_color;
|
||||
|
||||
@@ -197,7 +194,7 @@ static void handle_geometry_changed(FlView* self) {
|
||||
// Note: `gtk_widget_init()` initializes the size allocation to 1x1.
|
||||
if (allocation.width > 1 && allocation.height > 1 &&
|
||||
gtk_widget_get_realized(GTK_WIDGET(self))) {
|
||||
fl_renderer_wait_for_frame(FL_RENDERER(self->renderer),
|
||||
fl_renderer_wait_for_frame(fl_engine_get_renderer(self->engine),
|
||||
allocation.width * scale_factor,
|
||||
allocation.height * scale_factor);
|
||||
}
|
||||
@@ -440,26 +437,26 @@ static void gesture_zoom_end_cb(FlView* self) {
|
||||
}
|
||||
|
||||
static GdkGLContext* create_context_cb(FlView* self) {
|
||||
fl_renderer_gdk_set_window(self->renderer,
|
||||
gtk_widget_get_parent_window(GTK_WIDGET(self)));
|
||||
|
||||
init_scrolling(self);
|
||||
init_touch(self);
|
||||
|
||||
FlOpenGLManager* opengl_manager = fl_engine_get_opengl_manager(self->engine);
|
||||
g_autoptr(GError) error = nullptr;
|
||||
if (!fl_renderer_gdk_create_contexts(self->renderer, &error)) {
|
||||
if (!fl_opengl_manager_create_contexts(
|
||||
opengl_manager, gtk_widget_get_parent_window(GTK_WIDGET(self)),
|
||||
&error)) {
|
||||
gtk_gl_area_set_error(self->gl_area, error);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return GDK_GL_CONTEXT(
|
||||
g_object_ref(fl_renderer_gdk_get_context(self->renderer)));
|
||||
g_object_ref(fl_opengl_manager_get_context(opengl_manager)));
|
||||
}
|
||||
|
||||
static void realize_cb(FlView* self) {
|
||||
g_autoptr(GError) error = nullptr;
|
||||
|
||||
fl_renderer_make_current(FL_RENDERER(self->renderer));
|
||||
fl_opengl_manager_make_current(fl_engine_get_opengl_manager(self->engine));
|
||||
|
||||
GError* gl_error = gtk_gl_area_get_error(self->gl_area);
|
||||
if (gl_error != NULL) {
|
||||
@@ -467,7 +464,7 @@ static void realize_cb(FlView* self) {
|
||||
return;
|
||||
}
|
||||
|
||||
fl_renderer_setup(FL_RENDERER(self->renderer));
|
||||
fl_renderer_setup(fl_engine_get_renderer(self->engine));
|
||||
|
||||
GtkWidget* toplevel_window = gtk_widget_get_toplevel(GTK_WIDGET(self));
|
||||
|
||||
@@ -481,7 +478,7 @@ static void realize_cb(FlView* self) {
|
||||
|
||||
// Flutter engine will need to make the context current from raster thread
|
||||
// during initialization.
|
||||
fl_renderer_clear_current(FL_RENDERER(self->renderer));
|
||||
fl_opengl_manager_clear_current(fl_engine_get_opengl_manager(self->engine));
|
||||
|
||||
if (!fl_engine_start(self->engine, &error)) {
|
||||
g_warning("Failed to start Flutter engine: %s", error->message);
|
||||
@@ -505,7 +502,7 @@ static gboolean render_cb(FlView* self, GdkGLContext* context) {
|
||||
int width = gtk_widget_get_allocated_width(GTK_WIDGET(self->gl_area));
|
||||
int height = gtk_widget_get_allocated_height(GTK_WIDGET(self->gl_area));
|
||||
gint scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(self->gl_area));
|
||||
fl_renderer_render(FL_RENDERER(self->renderer), self->view_id,
|
||||
fl_renderer_render(fl_engine_get_renderer(self->engine), self->view_id,
|
||||
width * scale_factor, height * scale_factor,
|
||||
self->background_color);
|
||||
|
||||
@@ -515,7 +512,7 @@ static gboolean render_cb(FlView* self, GdkGLContext* context) {
|
||||
static void unrealize_cb(FlView* self) {
|
||||
g_autoptr(GError) error = nullptr;
|
||||
|
||||
fl_renderer_make_current(FL_RENDERER(self->renderer));
|
||||
fl_opengl_manager_make_current(fl_engine_get_opengl_manager(self->engine));
|
||||
|
||||
GError* gl_error = gtk_gl_area_get_error(self->gl_area);
|
||||
if (gl_error != NULL) {
|
||||
@@ -523,7 +520,7 @@ static void unrealize_cb(FlView* self) {
|
||||
return;
|
||||
}
|
||||
|
||||
fl_renderer_cleanup(FL_RENDERER(self->renderer));
|
||||
fl_renderer_cleanup(fl_engine_get_renderer(self->engine));
|
||||
}
|
||||
|
||||
static void size_allocate_cb(FlView* self) {
|
||||
@@ -572,7 +569,6 @@ static void fl_view_dispose(GObject* object) {
|
||||
}
|
||||
|
||||
g_clear_object(&self->engine);
|
||||
g_clear_object(&self->renderer);
|
||||
g_clear_pointer(&self->background_color, gdk_rgba_free);
|
||||
g_clear_object(&self->window_state_monitor);
|
||||
g_clear_object(&self->scrolling_manager);
|
||||
@@ -754,9 +750,6 @@ G_MODULE_EXPORT FlView* fl_view_new(FlDartProject* project) {
|
||||
|
||||
self->view_id = flutter::kFlutterImplicitViewId;
|
||||
self->engine = FL_ENGINE(g_object_ref(engine));
|
||||
FlRenderer* renderer = fl_engine_get_renderer(engine);
|
||||
g_assert(FL_IS_RENDERER_GDK(renderer));
|
||||
self->renderer = FL_RENDERER_GDK(g_object_ref(renderer));
|
||||
|
||||
setup_engine(self);
|
||||
|
||||
@@ -776,9 +769,6 @@ G_MODULE_EXPORT FlView* fl_view_new_for_engine(FlEngine* engine) {
|
||||
FlView* self = FL_VIEW(g_object_new(fl_view_get_type(), nullptr));
|
||||
|
||||
self->engine = FL_ENGINE(g_object_ref(engine));
|
||||
FlRenderer* renderer = fl_engine_get_renderer(engine);
|
||||
g_assert(FL_IS_RENDERER_GDK(renderer));
|
||||
self->renderer = FL_RENDERER_GDK(g_object_ref(renderer));
|
||||
|
||||
self->view_id = fl_engine_add_view(engine, FL_RENDERABLE(self), 1, 1, 1.0,
|
||||
self->cancellable, view_added_cb, self);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "flutter/shell/platform/linux/testing/fl_test.h"
|
||||
|
||||
#include "flutter/shell/platform/linux/fl_engine_private.h"
|
||||
#include "flutter/shell/platform/linux/testing/mock_renderer.h"
|
||||
#include "flutter/shell/platform/linux/testing/mock_renderable.h"
|
||||
|
||||
namespace {
|
||||
class ImModuleEnv : public ::testing::Environment {
|
||||
|
||||
@@ -79,6 +79,10 @@ GdkCursor* gdk_cursor_new_from_name(GdkDisplay* display, const gchar* name) {
|
||||
|
||||
void gdk_window_set_cursor(GdkWindow* window, GdkCursor* cursor) {}
|
||||
|
||||
void gdk_gl_context_make_current(GdkGLContext* context) {}
|
||||
|
||||
void gdk_gl_context_clear_current() {}
|
||||
|
||||
GtkWidget* gtk_window_new(GtkWindowType type) {
|
||||
GtkWindow* window = GTK_WINDOW(g_object_new(gtk_window_get_type(), nullptr));
|
||||
mock->gtk_window_new(window, type);
|
||||
|
||||
@@ -2,19 +2,13 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/shell/platform/linux/testing/mock_renderer.h"
|
||||
|
||||
struct _FlMockRenderer {
|
||||
FlRenderer parent_instance;
|
||||
};
|
||||
#include "flutter/shell/platform/linux/testing/mock_renderable.h"
|
||||
|
||||
struct _FlMockRenderable {
|
||||
GObject parent_instance;
|
||||
size_t redraw_count;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(FlMockRenderer, fl_mock_renderer, fl_renderer_get_type())
|
||||
|
||||
static void mock_renderable_iface_init(FlRenderableInterface* iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE(FlMockRenderable,
|
||||
@@ -23,24 +17,6 @@ G_DEFINE_TYPE_WITH_CODE(FlMockRenderable,
|
||||
G_IMPLEMENT_INTERFACE(fl_renderable_get_type(),
|
||||
mock_renderable_iface_init))
|
||||
|
||||
// Implements FlRenderer::make_current.
|
||||
static void fl_mock_renderer_make_current(FlRenderer* renderer) {}
|
||||
|
||||
// Implements FlRenderer::make_resource_current.
|
||||
static void fl_mock_renderer_make_resource_current(FlRenderer* renderer) {}
|
||||
|
||||
// Implements FlRenderer::clear_current.
|
||||
static void fl_mock_renderer_clear_current(FlRenderer* renderer) {}
|
||||
|
||||
static void fl_mock_renderer_class_init(FlMockRendererClass* klass) {
|
||||
FL_RENDERER_CLASS(klass)->make_current = fl_mock_renderer_make_current;
|
||||
FL_RENDERER_CLASS(klass)->make_resource_current =
|
||||
fl_mock_renderer_make_resource_current;
|
||||
FL_RENDERER_CLASS(klass)->clear_current = fl_mock_renderer_clear_current;
|
||||
}
|
||||
|
||||
static void fl_mock_renderer_init(FlMockRenderer* self) {}
|
||||
|
||||
static void mock_renderable_redraw(FlRenderable* renderable) {
|
||||
FlMockRenderable* self = FL_MOCK_RENDERABLE(renderable);
|
||||
self->redraw_count++;
|
||||
@@ -57,13 +33,6 @@ static void fl_mock_renderable_class_init(FlMockRenderableClass* klass) {}
|
||||
|
||||
static void fl_mock_renderable_init(FlMockRenderable* self) {}
|
||||
|
||||
// Creates a stub renderer
|
||||
FlMockRenderer* fl_mock_renderer_new() {
|
||||
FlMockRenderer* self =
|
||||
FL_MOCK_RENDERER(g_object_new(fl_mock_renderer_get_type(), nullptr));
|
||||
return self;
|
||||
}
|
||||
|
||||
// Creates a sub renderable.
|
||||
FlMockRenderable* fl_mock_renderable_new() {
|
||||
return FL_MOCK_RENDERABLE(
|
||||
@@ -2,34 +2,23 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_TESTING_MOCK_RENDERER_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_LINUX_TESTING_MOCK_RENDERER_H_
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_TESTING_MOCK_RENDERABLE_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_LINUX_TESTING_MOCK_RENDERABLE_H_
|
||||
|
||||
#include "flutter/shell/platform/linux/fl_renderable.h"
|
||||
#include "flutter/shell/platform/linux/fl_renderer.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_DECLARE_FINAL_TYPE(FlMockRenderer,
|
||||
fl_mock_renderer,
|
||||
FL,
|
||||
MOCK_RENDERER,
|
||||
FlRenderer)
|
||||
|
||||
G_DECLARE_FINAL_TYPE(FlMockRenderable,
|
||||
fl_mock_renderable,
|
||||
FL,
|
||||
MOCK_RENDERABLE,
|
||||
GObject)
|
||||
|
||||
typedef gdouble (*FlMockRendererGetRefreshRate)(FlRenderer* renderer);
|
||||
|
||||
FlMockRenderer* fl_mock_renderer_new();
|
||||
|
||||
FlMockRenderable* fl_mock_renderable_new();
|
||||
|
||||
size_t fl_mock_renderable_get_redraw_count(FlMockRenderable* renderable);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_LINUX_TESTING_MOCK_RENDERER_H_
|
||||
#endif // FLUTTER_SHELL_PLATFORM_LINUX_TESTING_MOCK_RENDERABLE_H_
|
||||
Reference in New Issue
Block a user