Move OpenGL context management to FlOpenGLManager (#166025)

This helps to make a non-OpenGL FlRenderer
This commit is contained in:
Robert Ancell
2025-03-28 13:37:05 +13:00
committed by GitHub
parent d6ec7d4dc0
commit bfe95d3819
19 changed files with 322 additions and 592 deletions

View File

@@ -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

View File

@@ -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",

View File

@@ -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;

View File

@@ -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.

View File

@@ -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)

View 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();
}

View 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_

View File

@@ -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);
}
}

View File

@@ -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:

View File

@@ -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;
}

View File

@@ -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_

View File

@@ -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));
}

View File

@@ -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_

View File

@@ -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,

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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(

View File

@@ -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_