From 669e0b48d5e32d14677919a608c94bc4bc6f373e Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Thu, 11 Mar 2021 21:06:43 +0800 Subject: [PATCH 01/20] Linux texture support --- ci/licenses_golden/licenses_flutter | 8 + shell/platform/linux/BUILD.gn | 6 + shell/platform/linux/fl_engine.cc | 50 ++++++- shell/platform/linux/fl_engine_private.h | 36 +++++ shell/platform/linux/fl_plugin_registrar.cc | 18 ++- .../linux/fl_plugin_registrar_private.h | 7 +- shell/platform/linux/fl_texture.cc | 139 ++++++++++++++++++ shell/platform/linux/fl_texture_private.h | 42 ++++++ shell/platform/linux/fl_texture_registrar.cc | 101 +++++++++++++ .../linux/fl_texture_registrar_private.h | 57 +++++++ .../linux/fl_texture_registrar_test.cc | 65 ++++++++ shell/platform/linux/fl_texture_test.cc | 64 ++++++++ shell/platform/linux/fl_view.cc | 3 +- .../linux/public/flutter_linux/fl_engine.h | 11 ++ .../flutter_linux/fl_plugin_registrar.h | 12 ++ .../linux/public/flutter_linux/fl_texture.h | 95 ++++++++++++ .../flutter_linux/fl_texture_registrar.h | 67 +++++++++ .../public/flutter_linux/flutter_linux.h | 1 + shell/platform/linux/testing/mock_engine.cc | 38 ++++- shell/platform/linux/testing/mock_epoxy.cc | 6 + 20 files changed, 819 insertions(+), 7 deletions(-) create mode 100644 shell/platform/linux/fl_texture.cc create mode 100644 shell/platform/linux/fl_texture_private.h create mode 100644 shell/platform/linux/fl_texture_registrar.cc create mode 100644 shell/platform/linux/fl_texture_registrar_private.h create mode 100644 shell/platform/linux/fl_texture_registrar_test.cc create mode 100644 shell/platform/linux/fl_texture_test.cc create mode 100644 shell/platform/linux/public/flutter_linux/fl_texture.h create mode 100644 shell/platform/linux/public/flutter_linux/fl_texture_registrar.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index e968f9fd6854f..d334ce81368d7 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1448,6 +1448,12 @@ FILE: ../../../flutter/shell/platform/linux/fl_string_codec.cc FILE: ../../../flutter/shell/platform/linux/fl_string_codec_test.cc FILE: ../../../flutter/shell/platform/linux/fl_text_input_plugin.cc FILE: ../../../flutter/shell/platform/linux/fl_text_input_plugin.h +FILE: ../../../flutter/shell/platform/linux/fl_texture.cc +FILE: ../../../flutter/shell/platform/linux/fl_texture_private.h +FILE: ../../../flutter/shell/platform/linux/fl_texture_registrar.cc +FILE: ../../../flutter/shell/platform/linux/fl_texture_registrar_private.h +FILE: ../../../flutter/shell/platform/linux/fl_texture_registrar_test.cc +FILE: ../../../flutter/shell/platform/linux/fl_texture_test.cc FILE: ../../../flutter/shell/platform/linux/fl_value.cc FILE: ../../../flutter/shell/platform/linux/fl_value_test.cc FILE: ../../../flutter/shell/platform/linux/fl_view.cc @@ -1472,6 +1478,8 @@ FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_plugin_regis FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_standard_message_codec.h FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_string_codec.h +FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_texture.h +FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_value.h FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_view.h FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/flutter_linux.h diff --git a/shell/platform/linux/BUILD.gn b/shell/platform/linux/BUILD.gn index 038909683bc18..dab74d915cadd 100644 --- a/shell/platform/linux/BUILD.gn +++ b/shell/platform/linux/BUILD.gn @@ -60,6 +60,8 @@ _public_headers = [ "public/flutter_linux/fl_standard_message_codec.h", "public/flutter_linux/fl_standard_method_codec.h", "public/flutter_linux/fl_string_codec.h", + "public/flutter_linux/fl_texture.h", + "public/flutter_linux/fl_texture_registrar.h", "public/flutter_linux/fl_value.h", "public/flutter_linux/fl_view.h", "public/flutter_linux/flutter_linux.h", @@ -115,6 +117,8 @@ source_set("flutter_linux_sources") { "fl_standard_method_codec.cc", "fl_string_codec.cc", "fl_text_input_plugin.cc", + "fl_texture.cc", + "fl_texture_registrar.cc", "fl_value.cc", "fl_view.cc", "fl_view_accessible.cc", @@ -172,6 +176,8 @@ executable("flutter_linux_unittests") { "fl_standard_message_codec_test.cc", "fl_standard_method_codec_test.cc", "fl_string_codec_test.cc", + "fl_texture_registrar_test.cc", + "fl_texture_test.cc", "fl_value_test.cc", "testing/fl_test.cc", "testing/mock_engine.cc", diff --git a/shell/platform/linux/fl_engine.cc b/shell/platform/linux/fl_engine.cc index 2212b68ed6489..f51f6e8aac797 100644 --- a/shell/platform/linux/fl_engine.cc +++ b/shell/platform/linux/fl_engine.cc @@ -8,6 +8,7 @@ #include +#include "flutter/shell/platform/embedder/embedder.h" #include "flutter/shell/platform/linux/fl_binary_messenger_private.h" #include "flutter/shell/platform/linux/fl_dart_project_private.h" #include "flutter/shell/platform/linux/fl_engine_private.h" @@ -15,6 +16,7 @@ #include "flutter/shell/platform/linux/fl_renderer.h" #include "flutter/shell/platform/linux/fl_renderer_headless.h" #include "flutter/shell/platform/linux/fl_settings_plugin.h" +#include "flutter/shell/platform/linux/fl_texture_registrar_private.h" #include "flutter/shell/platform/linux/public/flutter_linux/fl_plugin_registry.h" static constexpr int kMicrosecondsPerNanosecond = 1000; @@ -32,6 +34,7 @@ struct _FlEngine { FlRenderer* renderer; FlBinaryMessenger* binary_messenger; FlSettingsPlugin* settings_plugin; + FlTextureRegistrar* texture_registrar; FlutterEngineAOTData aot_data; FLUTTER_API_SYMBOL(FlutterEngine) engine; FlutterEngineProcTable embedder_api; @@ -266,6 +269,21 @@ static bool fl_engine_gl_make_resource_current(void* user_data) { return result; } +// Called by the engine to retrieve an external texture. +static bool fl_engine_gl_external_texture_frame_callback( + void* user_data, + int64_t texture_id, + size_t width, + size_t height, + FlutterOpenGLTexture* texture) { + FlEngine* self = static_cast(user_data); + if (!self->texture_registrar) { + return false; + } + return fl_texture_registrar_populate_texture( + self->texture_registrar, texture_id, width, height, texture); +} + // Called by the engine to determine if it is on the GTK thread. static bool fl_engine_runs_task_on_current_thread(void* user_data) { FlEngine* self = static_cast(user_data); @@ -336,7 +354,8 @@ static FlPluginRegistrar* fl_engine_get_registrar_for_plugin( const gchar* name) { FlEngine* self = FL_ENGINE(registry); - return fl_plugin_registrar_new(nullptr, self->binary_messenger); + return fl_plugin_registrar_new(nullptr, self->binary_messenger, + self->texture_registrar); } static void fl_engine_plugin_registry_iface_init( @@ -359,6 +378,7 @@ static void fl_engine_dispose(GObject* object) { g_clear_object(&self->project); g_clear_object(&self->renderer); + g_clear_object(&self->texture_registrar); g_clear_object(&self->binary_messenger); g_clear_object(&self->settings_plugin); @@ -389,6 +409,7 @@ static void fl_engine_init(FlEngine* self) { self->embedder_api.struct_size = sizeof(FlutterEngineProcTable); FlutterEngineGetProcAddresses(&self->embedder_api); + self->texture_registrar = fl_texture_registrar_new(self); self->binary_messenger = fl_binary_messenger_new(self); } @@ -419,6 +440,8 @@ gboolean fl_engine_start(FlEngine* self, GError** error) { config.open_gl.fbo_callback = fl_engine_gl_get_fbo; config.open_gl.present = fl_engine_gl_present; config.open_gl.make_resource_current = fl_engine_gl_make_resource_current; + config.open_gl.gl_external_texture_frame_callback = + fl_engine_gl_external_texture_frame_callback; FlutterTaskRunnerDescription platform_task_runner = {}; platform_task_runner.struct_size = sizeof(FlutterTaskRunnerDescription); @@ -717,8 +740,33 @@ void fl_engine_dispatch_semantics_action(FlEngine* self, action_data, action_data_length); } +gboolean fl_engine_mark_texture_frame_available(FlEngine* self, + int64_t texture_id) { + g_return_val_if_fail(FL_IS_ENGINE(self), FALSE); + return self->embedder_api.MarkExternalTextureFrameAvailable( + self->engine, texture_id) == kSuccess; +} + +gboolean fl_engine_register_external_texture(FlEngine* self, + int64_t texture_id) { + g_return_val_if_fail(FL_IS_ENGINE(self), FALSE); + return self->embedder_api.RegisterExternalTexture(self->engine, texture_id) == + kSuccess; +} + +void fl_engine_unregister_external_texture(FlEngine* self, int64_t texture_id) { + g_return_if_fail(FL_IS_ENGINE(self)); + self->embedder_api.UnregisterExternalTexture(self->engine, texture_id); +} + G_MODULE_EXPORT FlBinaryMessenger* fl_engine_get_binary_messenger( FlEngine* self) { g_return_val_if_fail(FL_IS_ENGINE(self), nullptr); return self->binary_messenger; } + +G_MODULE_EXPORT FlTextureRegistrar* fl_engine_get_texture_registrar( + FlEngine* self) { + g_return_val_if_fail(FL_IS_ENGINE(self), nullptr); + return self->texture_registrar; +} diff --git a/shell/platform/linux/fl_engine_private.h b/shell/platform/linux/fl_engine_private.h index 23f186921fca6..c3b7fac0d7dcc 100644 --- a/shell/platform/linux/fl_engine_private.h +++ b/shell/platform/linux/fl_engine_private.h @@ -226,6 +226,42 @@ GBytes* fl_engine_send_platform_message_finish(FlEngine* engine, GAsyncResult* result, GError** error); +/** + * fl_engine_mark_texture_frame_available: + * @engine: an #FlEngine. + * @texture_id: the identifier of the texture whose frame has been updated. + * + * Tells the Flutter engine that a new texture frame is available for the given + * texture. + * + * Returns: %TRUE on success. + */ +gboolean fl_engine_mark_texture_frame_available(FlEngine* engine, + int64_t texture_id); + +/** + * fl_engine_register_external_texture: + * @engine: an #FlEngine. + * @texture_id: the identifier of the texture that is available. + * + * Tells the Flutter engine that a new external texture is available. + * + * Returns: %TRUE on success. + */ +gboolean fl_engine_register_external_texture(FlEngine* engine, + int64_t texture_id); + +/** + * fl_engine_unregister_external_texture: + * @engine: an #FlEngine. + * @texture_id: the identifier of the texture that is not available anymore. + * + * Tells the Flutter engine that an existing external texture is not available + * anymore. + */ +void fl_engine_unregister_external_texture(FlEngine* engine, + int64_t texture_id); + G_END_DECLS #endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_ENGINE_PRIVATE_H_ diff --git a/shell/platform/linux/fl_plugin_registrar.cc b/shell/platform/linux/fl_plugin_registrar.cc index 5207497b2fb30..d5cd4df9b640c 100644 --- a/shell/platform/linux/fl_plugin_registrar.cc +++ b/shell/platform/linux/fl_plugin_registrar.cc @@ -15,6 +15,8 @@ struct _FlPluginRegistrar { // Messenger to communicate on. FlBinaryMessenger* messenger; + + FlTextureRegistrar* texture_registrar; }; // Added here to stop the compiler from optimizing this function away. @@ -31,6 +33,7 @@ static void fl_plugin_registrar_dispose(GObject* object) { self->view = nullptr; } g_clear_object(&self->messenger); + g_clear_object(&self->texture_registrar); G_OBJECT_CLASS(fl_plugin_registrar_parent_class)->dispose(object); } @@ -41,8 +44,10 @@ static void fl_plugin_registrar_class_init(FlPluginRegistrarClass* klass) { static void fl_plugin_registrar_init(FlPluginRegistrar* self) {} -FlPluginRegistrar* fl_plugin_registrar_new(FlView* view, - FlBinaryMessenger* messenger) { +FlPluginRegistrar* fl_plugin_registrar_new( + FlView* view, + FlBinaryMessenger* messenger, + FlTextureRegistrar* texture_registrar) { g_return_val_if_fail(view == nullptr || FL_IS_VIEW(view), nullptr); g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr); @@ -55,6 +60,8 @@ FlPluginRegistrar* fl_plugin_registrar_new(FlView* view, reinterpret_cast(&(self->view))); } self->messenger = FL_BINARY_MESSENGER(g_object_ref(messenger)); + self->texture_registrar = + FL_TEXTURE_REGISTRAR(g_object_ref(texture_registrar)); return self; } @@ -66,6 +73,13 @@ G_MODULE_EXPORT FlBinaryMessenger* fl_plugin_registrar_get_messenger( return self->messenger; } +G_MODULE_EXPORT FlTextureRegistrar* fl_plugin_registrar_get_texture_registrar( + FlPluginRegistrar* self) { + g_return_val_if_fail(FL_IS_PLUGIN_REGISTRAR(self), nullptr); + + return self->texture_registrar; +} + G_MODULE_EXPORT FlView* fl_plugin_registrar_get_view(FlPluginRegistrar* self) { g_return_val_if_fail(FL_IS_PLUGIN_REGISTRAR(self), nullptr); diff --git a/shell/platform/linux/fl_plugin_registrar_private.h b/shell/platform/linux/fl_plugin_registrar_private.h index 712f32a3d98c3..52058c3ce930f 100644 --- a/shell/platform/linux/fl_plugin_registrar_private.h +++ b/shell/platform/linux/fl_plugin_registrar_private.h @@ -15,13 +15,16 @@ G_BEGIN_DECLS * @view: (allow-none): the #FlView that is being plugged into or %NULL for * headless mode. * @messenger: the #FlBinaryMessenger to communicate with. + * @texture_registrar: the #FlTextureRegistrar to communicate with. * * Creates a new #FlPluginRegistrar. * * Returns: a new #FlPluginRegistrar. */ -FlPluginRegistrar* fl_plugin_registrar_new(FlView* view, - FlBinaryMessenger* messenger); +FlPluginRegistrar* fl_plugin_registrar_new( + FlView* view, + FlBinaryMessenger* messenger, + FlTextureRegistrar* texture_registrar); G_END_DECLS diff --git a/shell/platform/linux/fl_texture.cc b/shell/platform/linux/fl_texture.cc new file mode 100644 index 0000000000000..19ebe1f7bd41f --- /dev/null +++ b/shell/platform/linux/fl_texture.cc @@ -0,0 +1,139 @@ +// 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/public/flutter_linux/fl_texture.h" +#include "flutter/shell/platform/linux/fl_texture_private.h" + +#include +#include +#include + +// Added here to stop the compiler from optimising this function away. +G_MODULE_EXPORT GType fl_texture_get_type(); + +G_DEFINE_TYPE(FlTexture, fl_texture, G_TYPE_OBJECT) + +#define GL_CALL(expr) \ + do { \ + expr; \ + GLenum err = glGetError(); \ + if (err) { \ + fprintf(stderr, "glGetError %x (%s:%d)\n", err, __FILE__, __LINE__); \ + } \ + } while (0); + +struct _FlPixelBufferTexture { + FlTexture parent_instance; + + GLuint texture_id; + + FlCopyPixelBufferCallback callback; + gpointer user_data; + GDestroyNotify destroy_notify; +}; + +G_DEFINE_TYPE(FlPixelBufferTexture, + fl_pixel_buffer_texture, + fl_texture_get_type()) + +static void fl_pixel_buffer_texture_dispose(GObject* object) { + FlPixelBufferTexture* self = FL_PIXEL_BUFFER_TEXTURE(object); + + if (self->destroy_notify) { + self->destroy_notify(self->user_data); + } + + if (self->texture_id) { + glDeleteTextures(1, &self->texture_id); + self->texture_id = 0; + } + + G_OBJECT_CLASS(fl_pixel_buffer_texture_parent_class)->dispose(object); +} + +static gboolean fl_pixel_buffer_texture_populate_texture(FlTexture* texture, + uint32_t* target, + uint32_t* name, + uint32_t* width, + uint32_t* height) { + FlPixelBufferTexture* self = FL_PIXEL_BUFFER_TEXTURE(texture); + uint32_t format = 0; + const uint8_t* buffer = nullptr; + if (!self->callback || + !self->callback(&buffer, &format, width, height, self->user_data)) { + return FALSE; + } + if (self->texture_id == 0) { + GL_CALL(glGenTextures(1, &self->texture_id)); + GL_CALL(glBindTexture(GL_TEXTURE_2D, self->texture_id)); + GL_CALL( + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)); + GL_CALL( + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)); + GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + } else { + GL_CALL(glBindTexture(GL_TEXTURE_2D, self->texture_id)); + } + *target = GL_TEXTURE_2D; + *name = self->texture_id; + GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, *width, *height, 0, format, + GL_UNSIGNED_BYTE, buffer)); + return TRUE; +} + +static void fl_pixel_buffer_texture_class_init( + FlPixelBufferTextureClass* klass) { + FL_TEXTURE_CLASS(klass)->populate_texture = + fl_pixel_buffer_texture_populate_texture; + + G_OBJECT_CLASS(klass)->dispose = fl_pixel_buffer_texture_dispose; +} + +static void fl_pixel_buffer_texture_init(FlPixelBufferTexture* self) {} + +G_MODULE_EXPORT FlPixelBufferTexture* fl_pixel_buffer_texture_new( + FlCopyPixelBufferCallback callback, + void* user_data, + GDestroyNotify destroy_notify) { + g_return_val_if_fail(callback != nullptr, nullptr); + + FlPixelBufferTexture* texture = reinterpret_cast( + g_object_new(fl_pixel_buffer_texture_get_type(), nullptr)); + texture->callback = callback; + texture->user_data = user_data; + texture->destroy_notify = destroy_notify; + return texture; +} + +static void fl_texture_class_init(FlTextureClass* klass) {} + +static void fl_texture_init(FlTexture* self) {} + +gboolean fl_texture_populate_texture(FlTexture* self, + uint32_t width, + uint32_t height, + FlutterOpenGLTexture* opengl_texture) { + uint32_t target = 0, name = 0; + bool populate_result = FL_TEXTURE_GET_CLASS(self)->populate_texture( + self, &target, &name, &width, &height); + if (!populate_result) { + return false; + } + + opengl_texture->target = target; + opengl_texture->name = name; + opengl_texture->format = GL_RGBA8; + opengl_texture->destruction_callback = nullptr; + opengl_texture->user_data = nullptr; + opengl_texture->width = width; + opengl_texture->height = height; + + return TRUE; +} + +int64_t fl_texture_get_texture_id(FlTexture* self) { + g_return_val_if_fail(FL_IS_TEXTURE(self), -1); + return reinterpret_cast(self); +} diff --git a/shell/platform/linux/fl_texture_private.h b/shell/platform/linux/fl_texture_private.h new file mode 100644 index 0000000000000..e1b75ec67a828 --- /dev/null +++ b/shell/platform/linux/fl_texture_private.h @@ -0,0 +1,42 @@ +// 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_TEXTURE_PRIVATE_H_ +#define FLUTTER_SHELL_PLATFORM_LINUX_FL_TEXTURE_PRIVATE_H_ + +#include "flutter/shell/platform/embedder/embedder.h" +#include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h" + +G_BEGIN_DECLS + +/** + * fl_texture_populate_texture: + * @texture: an #FlTexture. + * @width: width of the texture. + * @height: height of the texture. + * @opengl_texture: (out): return an #FlutterOpenGLTexture. + * + * Attempts to populate the specified @opengl_texture with texture details + * such as the name, width, height and the pixel format. + * + * Returns: %TRUE on success. + */ +gboolean fl_texture_populate_texture(FlTexture* texture, + uint32_t width, + uint32_t height, + FlutterOpenGLTexture* opengl_texture); + +/** + * fl_texture_get_texture_id: + * @texture: an #FlTexture. + * + * Retrieves the unique id of this texture. + * + * Returns: the unique id of this texture. + */ +int64_t fl_texture_get_texture_id(FlTexture* texture); + +G_END_DECLS + +#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_TEXTURE_PRIVATE_H_ diff --git a/shell/platform/linux/fl_texture_registrar.cc b/shell/platform/linux/fl_texture_registrar.cc new file mode 100644 index 0000000000000..816b0cd31e99d --- /dev/null +++ b/shell/platform/linux/fl_texture_registrar.cc @@ -0,0 +1,101 @@ +// 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/public/flutter_linux/fl_texture_registrar.h" + +#include + +#include "flutter/shell/platform/embedder/embedder.h" +#include "flutter/shell/platform/linux/fl_engine_private.h" +#include "flutter/shell/platform/linux/fl_texture_private.h" +#include "flutter/shell/platform/linux/fl_texture_registrar_private.h" + +struct _FlTextureRegistrar { + GObject parent_instance; + + FlEngine* engine; + + GHashTable* textures; +}; + +G_DEFINE_TYPE(FlTextureRegistrar, fl_texture_registrar, G_TYPE_OBJECT) + +static void fl_texture_registrar_dispose(GObject* object) { + FlTextureRegistrar* self = FL_TEXTURE_REGISTRAR(object); + + if (self->textures != nullptr) { + g_hash_table_destroy(self->textures); + self->textures = nullptr; + } + + g_clear_object(&self->engine); + + G_OBJECT_CLASS(fl_texture_registrar_parent_class)->dispose(object); +} + +static void fl_texture_registrar_class_init(FlTextureRegistrarClass* klass) { + G_OBJECT_CLASS(klass)->dispose = fl_texture_registrar_dispose; +} + +static void fl_texture_registrar_init(FlTextureRegistrar* self) { + self->textures = + g_hash_table_new_full(nullptr, nullptr, nullptr, g_object_unref); +} + +G_MODULE_EXPORT int64_t +fl_texture_registrar_register_texture(FlTextureRegistrar* self, + FlTexture* texture) { + g_return_val_if_fail(FL_IS_TEXTURE(texture), 0); + int64_t id = fl_texture_get_texture_id(texture); + g_hash_table_insert(self->textures, GINT_TO_POINTER(id), texture); + fl_engine_register_external_texture(self->engine, id); + return id; +} + +G_MODULE_EXPORT void fl_texture_registrar_mark_texture_frame_available( + FlTextureRegistrar* self, + int64_t texture_id) { + g_return_if_fail(FL_IS_TEXTURE_REGISTRAR(self)); + fl_engine_mark_texture_frame_available(self->engine, texture_id); +} + +bool fl_texture_registrar_populate_texture( + FlTextureRegistrar* self, + int64_t texture_id, + size_t width, + size_t height, + FlutterOpenGLTexture* opengl_texture) { + FlTexture* texture = FL_TEXTURE( + g_hash_table_lookup(self->textures, GINT_TO_POINTER(texture_id))); + if (texture == nullptr) { + return false; + } + return fl_texture_populate_texture(texture, width, height, opengl_texture); +} + +G_MODULE_EXPORT void fl_texture_registrar_unregister_texture( + FlTextureRegistrar* self, + int64_t texture_id) { + if (!g_hash_table_remove(self->textures, GINT_TO_POINTER(texture_id))) { + g_warning("Unregistering a non-existent texture %ld", texture_id); + return; + } + + fl_engine_unregister_external_texture(self->engine, texture_id); +} + +FlTexture* fl_texture_registrar_get_texture(FlTextureRegistrar* registrar, + int64_t texture_id) { + return reinterpret_cast( + g_hash_table_lookup(registrar->textures, GINT_TO_POINTER(texture_id))); +} + +FlTextureRegistrar* fl_texture_registrar_new(FlEngine* engine) { + FlTextureRegistrar* self = FL_TEXTURE_REGISTRAR( + g_object_new(fl_texture_registrar_get_type(), nullptr)); + + self->engine = FL_ENGINE(g_object_ref(engine)); + + return self; +} diff --git a/shell/platform/linux/fl_texture_registrar_private.h b/shell/platform/linux/fl_texture_registrar_private.h new file mode 100644 index 0000000000000..72dc788abd41e --- /dev/null +++ b/shell/platform/linux/fl_texture_registrar_private.h @@ -0,0 +1,57 @@ +// 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_TEXTURE_REGISTRAR_PRIVATE_H_ +#define FLUTTER_SHELL_PLATFORM_LINUX_FL_TEXTURE_REGISTRAR_PRIVATE_H_ + +#include "flutter/shell/platform/embedder/embedder.h" +#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h" +#include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h" + +G_BEGIN_DECLS + +/** + * fl_texture_registrar_new: + * @engine: an #FlEngine. + * + * Creates a new #FlTextureRegistrar. + * + * Returns: a new #FlTextureRegistrar. + */ +FlTextureRegistrar* fl_texture_registrar_new(FlEngine* engine); + +/** + * fl_texture_registrar_populate_texture: + * @registrar: an #FlTextureRegistrar. + * @texture_id: ID of texture. + * @width: width of the texture. + * @height: height of the texture. + * @opengl_texture: (out): return an #FlutterOpenGLTexture. + * + * Attempts to populate the given @texture_id. + * + * Returns: %TRUE on success. + */ +bool fl_texture_registrar_populate_texture( + FlTextureRegistrar* registrar, + int64_t texture_id, + size_t width, + size_t height, + FlutterOpenGLTexture* opengl_texture); + +/** + * fl_texture_registrar_get_texture: + * @registrar: an #FlTextureRegistrar. + * @texture_id: ID of texture. + * + * Gets a registered texture by @texture_id. + * + * Returns: an #FlTexture, or %NULL if not found. + */ +FlTexture* fl_texture_registrar_get_texture(FlTextureRegistrar* registrar, + int64_t texture_id); + +G_END_DECLS + +#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_TEXTURE_REGISTRAR_PRIVATE_H_ diff --git a/shell/platform/linux/fl_texture_registrar_test.cc b/shell/platform/linux/fl_texture_registrar_test.cc new file mode 100644 index 0000000000000..a5db0e5b85000 --- /dev/null +++ b/shell/platform/linux/fl_texture_registrar_test.cc @@ -0,0 +1,65 @@ +// 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/public/flutter_linux/fl_texture_registrar.h" +#include "flutter/shell/platform/linux/fl_texture_registrar_private.h" +#include "flutter/shell/platform/linux/testing/fl_test.h" +#include "gtest/gtest.h" + +#include + +#include + +// Test that registering a texture works. +TEST(FlTextureRegistrarTest, RegisterTexture) { + g_autoptr(FlEngine) engine = make_mock_engine(); + g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine); + FlTexture* texture = + FL_TEXTURE(fl_pixel_buffer_texture_new(nullptr, nullptr, nullptr)); + int64_t id = fl_texture_registrar_register_texture(registrar, texture); + + EXPECT_EQ(fl_texture_registrar_get_texture(registrar, id), texture); + + fl_texture_registrar_unregister_texture(registrar, id); + + EXPECT_EQ(fl_texture_registrar_get_texture(registrar, id), nullptr); +} + +// Test that marking a texture frame available works. +TEST(FlTextureRegistrarTest, MarkTextureFrameAvailable) { + g_autoptr(FlEngine) engine = make_mock_engine(); + g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine); + int64_t id = fl_texture_registrar_register_texture(registrar, nullptr); + fl_texture_registrar_mark_texture_frame_available(registrar, id); +} + +// Test that populating an OpenGL texture works. +TEST(FlTextureRegistrarTest, PopulateTexture) { + g_autoptr(FlEngine) engine = make_mock_engine(); + g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine); + static constexpr uint32_t BUFFER_WIDTH = 4u; + static constexpr uint32_t BUFFER_HEIGHT = 4u; + static constexpr uint32_t REAL_BUFFER_WIDTH = 2u; + static constexpr uint32_t REAL_BUFFER_HEIGHT = 2u; + FlCopyPixelBufferCallback callback = + [](const uint8_t** out_buffer, uint32_t* format, uint32_t* width, + uint32_t* height, gpointer user_data) -> gboolean { + const uint8_t buffer[] = {0x7a, 0x8a, 0x9a, 0xaa}; + EXPECT_EQ(*width, BUFFER_WIDTH); + EXPECT_EQ(*height, BUFFER_HEIGHT); + *out_buffer = buffer; + *format = GL_R8; + *width = REAL_BUFFER_WIDTH; + *height = REAL_BUFFER_HEIGHT; + return TRUE; + }; + FlTexture* texture = + FL_TEXTURE(fl_pixel_buffer_texture_new(callback, nullptr, nullptr)); + int64_t id = fl_texture_registrar_register_texture(registrar, texture); + FlutterOpenGLTexture opengl_texture; + EXPECT_TRUE(fl_texture_registrar_populate_texture( + registrar, id, BUFFER_WIDTH, BUFFER_HEIGHT, &opengl_texture)); + EXPECT_EQ(opengl_texture.width, REAL_BUFFER_WIDTH); + EXPECT_EQ(opengl_texture.height, REAL_BUFFER_HEIGHT); +} diff --git a/shell/platform/linux/fl_texture_test.cc b/shell/platform/linux/fl_texture_test.cc new file mode 100644 index 0000000000000..03b517138bab1 --- /dev/null +++ b/shell/platform/linux/fl_texture_test.cc @@ -0,0 +1,64 @@ +// 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/public/flutter_linux/fl_texture.h" +#include "flutter/shell/platform/linux/fl_texture_private.h" +#include "flutter/shell/platform/linux/fl_texture_registrar_private.h" +#include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h" +#include "flutter/shell/platform/linux/testing/fl_test.h" +#include "gtest/gtest.h" + +#include + +// Test that getting the texture ID works. +TEST(FlTextureTest, TextureID) { + // Texture ID is not assigned until the pixel buffer is copied once. + static constexpr uint32_t BUFFER_WIDTH = 4u; + static constexpr uint32_t BUFFER_HEIGHT = 4u; + static constexpr uint32_t REAL_BUFFER_WIDTH = 2u; + static constexpr uint32_t REAL_BUFFER_HEIGHT = 2u; + FlCopyPixelBufferCallback callback = + [](const uint8_t** out_buffer, uint32_t* format, uint32_t* width, + uint32_t* height, gpointer user_data) -> gboolean { + static const uint8_t buffer[] = {0xc9, 0xc8, 0xc7, 0xc6}; + EXPECT_EQ(*width, BUFFER_WIDTH); + EXPECT_EQ(*height, BUFFER_HEIGHT); + *out_buffer = buffer; + *format = GL_R8; + *width = REAL_BUFFER_WIDTH; + *height = REAL_BUFFER_HEIGHT; + return TRUE; + }; + g_autoptr(FlTexture) texture = + FL_TEXTURE(fl_pixel_buffer_texture_new(callback, nullptr, nullptr)); + EXPECT_EQ(fl_texture_get_texture_id(texture), + reinterpret_cast(texture)); +} + +// Test that populating an OpenGL texture works. +TEST(FlTextureTest, PopulateTexture) { + static constexpr uint32_t BUFFER_WIDTH = 4u; + static constexpr uint32_t BUFFER_HEIGHT = 4u; + static constexpr uint32_t REAL_BUFFER_WIDTH = 2u; + static constexpr uint32_t REAL_BUFFER_HEIGHT = 2u; + FlCopyPixelBufferCallback callback = + [](const uint8_t** out_buffer, uint32_t* format, uint32_t* width, + uint32_t* height, gpointer user_data) -> gboolean { + static const uint8_t buffer[] = {0x7a, 0x8a, 0x9a, 0xaa}; + EXPECT_EQ(*width, BUFFER_WIDTH); + EXPECT_EQ(*height, BUFFER_HEIGHT); + *out_buffer = buffer; + *format = GL_R8; + *width = REAL_BUFFER_WIDTH; + *height = REAL_BUFFER_HEIGHT; + return TRUE; + }; + g_autoptr(FlTexture) texture = + FL_TEXTURE(fl_pixel_buffer_texture_new(callback, nullptr, nullptr)); + FlutterOpenGLTexture opengl_texture = {0}; + EXPECT_TRUE(fl_texture_populate_texture(texture, BUFFER_WIDTH, BUFFER_HEIGHT, + &opengl_texture)); + EXPECT_EQ(opengl_texture.width, REAL_BUFFER_WIDTH); + EXPECT_EQ(opengl_texture.height, REAL_BUFFER_HEIGHT); +} diff --git a/shell/platform/linux/fl_view.cc b/shell/platform/linux/fl_view.cc index 2c18a4d0516f9..cc0d597c989d0 100644 --- a/shell/platform/linux/fl_view.cc +++ b/shell/platform/linux/fl_view.cc @@ -146,7 +146,8 @@ static FlPluginRegistrar* fl_view_get_registrar_for_plugin( FlView* self = FL_VIEW(registry); return fl_plugin_registrar_new(self, - fl_engine_get_binary_messenger(self->engine)); + fl_engine_get_binary_messenger(self->engine), + fl_engine_get_texture_registrar(self->engine)); } static void fl_view_plugin_registry_iface_init( diff --git a/shell/platform/linux/public/flutter_linux/fl_engine.h b/shell/platform/linux/public/flutter_linux/fl_engine.h index 201c38f4a06d2..6740c0bd8cd81 100644 --- a/shell/platform/linux/public/flutter_linux/fl_engine.h +++ b/shell/platform/linux/public/flutter_linux/fl_engine.h @@ -13,6 +13,7 @@ #include "fl_binary_messenger.h" #include "fl_dart_project.h" +#include "fl_texture_registrar.h" G_BEGIN_DECLS @@ -44,6 +45,16 @@ FlEngine* fl_engine_new_headless(FlDartProject* project); */ FlBinaryMessenger* fl_engine_get_binary_messenger(FlEngine* engine); +/** + * fl_engine_get_texture_registrar: + * @engine: an #FlEngine. + * + * Gets the texture registrar for registering textures. + * + * Returns: an #FlTextureRegistrar. + */ +FlTextureRegistrar* fl_engine_get_texture_registrar(FlEngine* engine); + G_END_DECLS #endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_ENGINE_H_ diff --git a/shell/platform/linux/public/flutter_linux/fl_plugin_registrar.h b/shell/platform/linux/public/flutter_linux/fl_plugin_registrar.h index 5ac073c1844ae..5ccd74752fa14 100644 --- a/shell/platform/linux/public/flutter_linux/fl_plugin_registrar.h +++ b/shell/platform/linux/public/flutter_linux/fl_plugin_registrar.h @@ -12,6 +12,7 @@ #include #include "fl_binary_messenger.h" +#include "fl_texture_registrar.h" #include "fl_view.h" G_BEGIN_DECLS @@ -39,6 +40,17 @@ G_DECLARE_FINAL_TYPE(FlPluginRegistrar, FlBinaryMessenger* fl_plugin_registrar_get_messenger( FlPluginRegistrar* registrar); +/** + * fl_plugin_registrar_get_texture_registrar: + * @registrar: an #FlPluginRegistrar. + * + * Gets the texture registrar this plugin can communicate with. + * + * Returns: an #FlTextureRegistrar. + */ +FlTextureRegistrar* fl_plugin_registrar_get_texture_registrar( + FlPluginRegistrar* registrar); + /** * fl_plugin_registrar_get_view: * @registrar: an #FlPluginRegistrar. diff --git a/shell/platform/linux/public/flutter_linux/fl_texture.h b/shell/platform/linux/public/flutter_linux/fl_texture.h new file mode 100644 index 0000000000000..a98c5ee213e06 --- /dev/null +++ b/shell/platform/linux/public/flutter_linux/fl_texture.h @@ -0,0 +1,95 @@ +// 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_TEXTURE_H_ +#define FLUTTER_SHELL_PLATFORM_LINUX_FL_TEXTURE_H_ + +#if !defined(__FLUTTER_LINUX_INSIDE__) && !defined(FLUTTER_LINUX_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +G_DECLARE_DERIVABLE_TYPE(FlTexture, fl_texture, FL, TEXTURE, GObject) + +/** + * FlTexture: + * + * #FlTexture is an abstract class that represents a texture. + */ + +struct _FlTextureClass { + GObjectClass parent_class; + + /** + * Virtual method called when Flutter populates this texture. + * @texture: an #FlTexture. + * @target: return texture target (example GL_TEXTURE_2D or + * GL_TEXTURE_RECTANGLE). + * @name: (out): return name of texture. + * @width: (inout): pointer to width of the texture. + * @height: (inout): pointer to height of the texture. + * + * Returns: %TRUE on success. + */ + gboolean (*populate_texture)(FlTexture* texture, + uint32_t* target, + uint32_t* name, + uint32_t* width, + uint32_t* height); +}; + +G_DECLARE_FINAL_TYPE(FlPixelBufferTexture, + fl_pixel_buffer_texture, + FL, + PIXEL_BUFFER_TEXTURE, + FlTexture) + +/** + * FlPixelBufferTexture: + * + * #FlPixelBufferTexture represents a pixel buffer texture. + */ + +/** + * FlCopyPixelBufferCallback: + * @buffer: (out): return callee-allocated pixel buffer. + * @format: (out): return pixel buffer format (example GL_RGBA). + * @width: (inout): pointer to width of the texture. + * @height: (inout): pointer to height of the texture. + * @user_data: (closure): data provided when populating texture at first time. + * + * Function called when Flutter wants to copy pixel buffer for populating + * texture. + * + * Returns: %TRUE on success. + */ +typedef gboolean (*FlCopyPixelBufferCallback)(const uint8_t** buffer, + uint32_t* format, + uint32_t* width, + uint32_t* height, + gpointer user_data); + +/** + * fl_pixel_buffer_texture_new: + * @callback: a callback to copy pixel buffer when populating texture. + * @user_data: (closure): user data to pass to @callback. + * @destroy_notify: (allow-none): a function which gets called to free + * @user_data, or %NULL. + * + * Creates a new #FlPixelBufferTexture. + * + * Returns: the newly created #FlPixelBufferTexture. + */ +FlPixelBufferTexture* fl_pixel_buffer_texture_new( + FlCopyPixelBufferCallback callback, + gpointer user_data, + GDestroyNotify destroy_notify); + +G_END_DECLS + +#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_TEXTURE_H_ diff --git a/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h b/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h new file mode 100644 index 0000000000000..b90c87325c861 --- /dev/null +++ b/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h @@ -0,0 +1,67 @@ +// 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_TEXTURE_REGISTRAR_H_ +#define FLUTTER_SHELL_PLATFORM_LINUX_FL_TEXTURE_REGISTRAR_H_ + +#if !defined(__FLUTTER_LINUX_INSIDE__) && !defined(FLUTTER_LINUX_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +#include "fl_texture.h" + +G_BEGIN_DECLS + +G_DECLARE_FINAL_TYPE(FlTextureRegistrar, + fl_texture_registrar, + FL, + TEXTURE_REGISTRAR, + GObject) + +/** + * FlTextureRegistrar: + * + * #FlTextureRegistrar is used when registering textures. + */ + +/** + * fl_texture_registrar_register_texture: + * @registrar: an #FlTextureRegistrar. + * @texture: (transfer-full): a #FlTexture for registration. + * + * Registers a texture and returns the unique ID for that texture. + * + * Returns: unique ID of the texture. + */ +int64_t fl_texture_registrar_register_texture(FlTextureRegistrar* registrar, + FlTexture* texture); + +/** + * fl_texture_registrar_mark_texture_frame_available: + * @registrar: an #FlTextureRegistrar. + * @texture_id: the ID of the texture that has a frame available. + * + * Notifies the flutter engine that the texture object corresponding + * to texture_id needs to render a new texture. + */ +void fl_texture_registrar_mark_texture_frame_available( + FlTextureRegistrar* registrar, + int64_t texture_id); + +/** + * fl_texture_registrar_unregister_texture: + * @registrar: an #FlTextureRegistrar. + * @texture_id: the ID of the texture that is being unregistered. + * + * Unregisters an existing texture object. + */ +void fl_texture_registrar_unregister_texture(FlTextureRegistrar* registrar, + int64_t texture_id); + +G_END_DECLS + +#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_TEXTURE_REGISTRAR_H_ diff --git a/shell/platform/linux/public/flutter_linux/flutter_linux.h b/shell/platform/linux/public/flutter_linux/flutter_linux.h index f80bef47d730b..fbce7e1c2a271 100644 --- a/shell/platform/linux/public/flutter_linux/flutter_linux.h +++ b/shell/platform/linux/public/flutter_linux/flutter_linux.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include diff --git a/shell/platform/linux/testing/mock_engine.cc b/shell/platform/linux/testing/mock_engine.cc index 516adae3c3345..f7029e60128d6 100644 --- a/shell/platform/linux/testing/mock_engine.cc +++ b/shell/platform/linux/testing/mock_engine.cc @@ -10,6 +10,7 @@ // Over time existing tests should be migrated and this file should be removed. #include +#include #include "flutter/shell/platform/embedder/embedder.h" #include "flutter/shell/platform/linux/fl_method_codec_private.h" @@ -20,11 +21,16 @@ const int32_t kFlutterSemanticsCustomActionIdBatchEnd = -1; +struct _FlutterEngineTexture { + bool has_new_frame; +}; + struct _FlutterEngine { bool running; FlutterPlatformMessageCallback platform_message_callback; FlutterTaskRunnerPostTaskCallback platform_post_task_callback; void* user_data; + std::unordered_map textures; _FlutterEngine(FlutterPlatformMessageCallback platform_message_callback, FlutterTaskRunnerPostTaskCallback platform_post_task_callback, @@ -461,6 +467,33 @@ FlutterEngineResult FlutterEngineDispatchSemanticsAction( return kSuccess; } +FlutterEngineResult FlutterEngineRegisterExternalTexture( + FLUTTER_API_SYMBOL(FlutterEngine) engine, + int64_t texture_identifier) { + _FlutterEngineTexture texture; + texture.has_new_frame = false; + engine->textures[texture_identifier] = texture; + return kSuccess; +} + +FlutterEngineResult FlutterEngineMarkExternalTextureFrameAvailable( + FLUTTER_API_SYMBOL(FlutterEngine) engine, + int64_t texture_identifier) { + auto val = engine->textures.find(texture_identifier); + if (val == std::end(engine->textures)) { + return kInvalidArguments; + } + val->second.has_new_frame = true; + return kSuccess; +} + +FlutterEngineResult FlutterEngineUnregisterExternalTexture( + FLUTTER_API_SYMBOL(FlutterEngine) engine, + int64_t texture_identifier) { + engine->textures.erase(texture_identifier); + return kSuccess; +} + } // namespace FlutterEngineResult FlutterEngineGetProcAddresses( @@ -493,6 +526,9 @@ FlutterEngineResult FlutterEngineGetProcAddresses( table->UpdateSemanticsEnabled = &FlutterEngineUpdateSemanticsEnabled; table->DispatchSemanticsAction = &FlutterEngineDispatchSemanticsAction; table->RunsAOTCompiledDartCode = &FlutterEngineRunsAOTCompiledDartCode; - + table->RegisterExternalTexture = &FlutterEngineRegisterExternalTexture; + table->MarkExternalTextureFrameAvailable = + &FlutterEngineMarkExternalTextureFrameAvailable; + table->UnregisterExternalTexture = &FlutterEngineUnregisterExternalTexture; return kSuccess; } diff --git a/shell/platform/linux/testing/mock_epoxy.cc b/shell/platform/linux/testing/mock_epoxy.cc index a8012cd9888ef..23dc72b250de4 100644 --- a/shell/platform/linux/testing/mock_epoxy.cc +++ b/shell/platform/linux/testing/mock_epoxy.cc @@ -374,6 +374,10 @@ static void _glTexImage2D(GLenum target, GLenum type, const void* pixels) {} +static GLenum _glGetError() { + return GL_NO_ERROR; +} + #ifdef __GNUC__ #define CONSTRUCT(_func) static void _func(void) __attribute__((constructor)); #define DESTRUCT(_func) static void _func(void) __attribute__((destructor)); @@ -446,6 +450,7 @@ void (*epoxy_glTexImage2D)(GLenum target, GLenum format, GLenum type, const void* pixels); +GLenum (*epoxy_glGetError)(); static void library_init() { epoxy_eglBindAPI = _eglBindAPI; @@ -471,4 +476,5 @@ static void library_init() { epoxy_glTexParameterf = _glTexParameterf; epoxy_glTexParameteri = _glTexParameteri; epoxy_glTexImage2D = _glTexImage2D; + epoxy_glGetError = _glGetError; } From 27744756a8712115cd93a0c013747508fa7ac0b2 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 12 Mar 2021 14:57:16 +0800 Subject: [PATCH 02/20] fix reference loop --- shell/platform/linux/fl_texture_registrar.cc | 50 ++++++++++++++++--- .../linux/fl_texture_registrar_private.h | 6 +-- 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/shell/platform/linux/fl_texture_registrar.cc b/shell/platform/linux/fl_texture_registrar.cc index 816b0cd31e99d..3cee2feba7d82 100644 --- a/shell/platform/linux/fl_texture_registrar.cc +++ b/shell/platform/linux/fl_texture_registrar.cc @@ -21,6 +21,18 @@ struct _FlTextureRegistrar { G_DEFINE_TYPE(FlTextureRegistrar, fl_texture_registrar, G_TYPE_OBJECT) +static void engine_weak_notify_cb(gpointer user_data, + GObject* where_the_object_was) { + FlTextureRegistrar* self = FL_TEXTURE_REGISTRAR(user_data); + self->engine = nullptr; + + // Unregister any textures. + g_autoptr(GHashTable) textures = self->textures; + self->textures = g_hash_table_new_full(g_direct_hash, g_direct_equal, nullptr, + g_object_unref); + g_hash_table_remove_all(textures); +} + static void fl_texture_registrar_dispose(GObject* object) { FlTextureRegistrar* self = FL_TEXTURE_REGISTRAR(object); @@ -29,7 +41,10 @@ static void fl_texture_registrar_dispose(GObject* object) { self->textures = nullptr; } - g_clear_object(&self->engine); + if (self->engine != nullptr) { + g_object_weak_unref(G_OBJECT(self->engine), engine_weak_notify_cb, self); + self->engine = nullptr; + } G_OBJECT_CLASS(fl_texture_registrar_parent_class)->dispose(object); } @@ -39,16 +54,23 @@ static void fl_texture_registrar_class_init(FlTextureRegistrarClass* klass) { } static void fl_texture_registrar_init(FlTextureRegistrar* self) { - self->textures = - g_hash_table_new_full(nullptr, nullptr, nullptr, g_object_unref); + self->textures = g_hash_table_new_full(g_direct_hash, g_direct_equal, nullptr, + g_object_unref); } G_MODULE_EXPORT int64_t fl_texture_registrar_register_texture(FlTextureRegistrar* self, FlTexture* texture) { + g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), 0); g_return_val_if_fail(FL_IS_TEXTURE(texture), 0); + int64_t id = fl_texture_get_texture_id(texture); g_hash_table_insert(self->textures, GINT_TO_POINTER(id), texture); + + if (self->engine == nullptr) { + return 0; + } + fl_engine_register_external_texture(self->engine, id); return id; } @@ -57,19 +79,24 @@ G_MODULE_EXPORT void fl_texture_registrar_mark_texture_frame_available( FlTextureRegistrar* self, int64_t texture_id) { g_return_if_fail(FL_IS_TEXTURE_REGISTRAR(self)); + + if (self->engine == nullptr) { + return; + } + fl_engine_mark_texture_frame_available(self->engine, texture_id); } -bool fl_texture_registrar_populate_texture( +gboolean fl_texture_registrar_populate_texture( FlTextureRegistrar* self, int64_t texture_id, - size_t width, - size_t height, + uint32_t width, + uint32_t height, FlutterOpenGLTexture* opengl_texture) { FlTexture* texture = FL_TEXTURE( g_hash_table_lookup(self->textures, GINT_TO_POINTER(texture_id))); if (texture == nullptr) { - return false; + return FALSE; } return fl_texture_populate_texture(texture, width, height, opengl_texture); } @@ -77,11 +104,17 @@ bool fl_texture_registrar_populate_texture( G_MODULE_EXPORT void fl_texture_registrar_unregister_texture( FlTextureRegistrar* self, int64_t texture_id) { + g_return_if_fail(FL_IS_TEXTURE_REGISTRAR(self)); + if (!g_hash_table_remove(self->textures, GINT_TO_POINTER(texture_id))) { g_warning("Unregistering a non-existent texture %ld", texture_id); return; } + if (self->engine == nullptr) { + return; + } + fl_engine_unregister_external_texture(self->engine, texture_id); } @@ -95,7 +128,8 @@ FlTextureRegistrar* fl_texture_registrar_new(FlEngine* engine) { FlTextureRegistrar* self = FL_TEXTURE_REGISTRAR( g_object_new(fl_texture_registrar_get_type(), nullptr)); - self->engine = FL_ENGINE(g_object_ref(engine)); + self->engine = engine; + g_object_weak_ref(G_OBJECT(engine), engine_weak_notify_cb, self); return self; } diff --git a/shell/platform/linux/fl_texture_registrar_private.h b/shell/platform/linux/fl_texture_registrar_private.h index 72dc788abd41e..8f2ca3b80d021 100644 --- a/shell/platform/linux/fl_texture_registrar_private.h +++ b/shell/platform/linux/fl_texture_registrar_private.h @@ -33,11 +33,11 @@ FlTextureRegistrar* fl_texture_registrar_new(FlEngine* engine); * * Returns: %TRUE on success. */ -bool fl_texture_registrar_populate_texture( +gboolean fl_texture_registrar_populate_texture( FlTextureRegistrar* registrar, int64_t texture_id, - size_t width, - size_t height, + uint32_t width, + uint32_t height, FlutterOpenGLTexture* opengl_texture); /** From 7e5599d763086fc69daea6b9814a288f59974c1a Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Thu, 6 May 2021 16:45:00 +1200 Subject: [PATCH 03/20] Use g_clear_pointer --- shell/platform/linux/fl_texture_registrar.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/shell/platform/linux/fl_texture_registrar.cc b/shell/platform/linux/fl_texture_registrar.cc index 3cee2feba7d82..aa4393395799a 100644 --- a/shell/platform/linux/fl_texture_registrar.cc +++ b/shell/platform/linux/fl_texture_registrar.cc @@ -36,10 +36,7 @@ static void engine_weak_notify_cb(gpointer user_data, static void fl_texture_registrar_dispose(GObject* object) { FlTextureRegistrar* self = FL_TEXTURE_REGISTRAR(object); - if (self->textures != nullptr) { - g_hash_table_destroy(self->textures); - self->textures = nullptr; - } + g_clear_pointer(&self->textures, g_hash_table_unref); if (self->engine != nullptr) { g_object_weak_unref(G_OBJECT(self->engine), engine_weak_notify_cb, self); From e603f73c07554b3e54c091e8bb495588ec6378a1 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Thu, 6 May 2021 16:46:14 +1200 Subject: [PATCH 04/20] Take a reference to the texture --- shell/platform/linux/fl_texture_registrar.cc | 2 +- .../platform/linux/public/flutter_linux/fl_texture_registrar.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/platform/linux/fl_texture_registrar.cc b/shell/platform/linux/fl_texture_registrar.cc index aa4393395799a..bc51e19877570 100644 --- a/shell/platform/linux/fl_texture_registrar.cc +++ b/shell/platform/linux/fl_texture_registrar.cc @@ -62,7 +62,7 @@ fl_texture_registrar_register_texture(FlTextureRegistrar* self, g_return_val_if_fail(FL_IS_TEXTURE(texture), 0); int64_t id = fl_texture_get_texture_id(texture); - g_hash_table_insert(self->textures, GINT_TO_POINTER(id), texture); + g_hash_table_insert(self->textures, GINT_TO_POINTER(id), g_object_ref(texture)); if (self->engine == nullptr) { return 0; diff --git a/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h b/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h index b90c87325c861..957532cf28ccb 100644 --- a/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h +++ b/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h @@ -31,7 +31,7 @@ G_DECLARE_FINAL_TYPE(FlTextureRegistrar, /** * fl_texture_registrar_register_texture: * @registrar: an #FlTextureRegistrar. - * @texture: (transfer-full): a #FlTexture for registration. + * @texture: an #FlTexture for registration. * * Registers a texture and returns the unique ID for that texture. * From 2b88a31f5756dff87f35ee2c437e9b252f0782f3 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Thu, 6 May 2021 16:52:24 +1200 Subject: [PATCH 05/20] Split FlPixelBufferTexture into its own module --- ci/licenses_golden/licenses_flutter | 1 + shell/platform/linux/BUILD.gn | 2 + shell/platform/linux/fl_texture.cc | 93 ------------------- .../flutter_linux/fl_pixel_buffer_texture.h | 65 +++++++++++++ .../public/flutter_linux/flutter_linux.h | 2 + 5 files changed, 70 insertions(+), 93 deletions(-) create mode 100644 shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index eb13342c97aee..8675f509cd28e 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1427,6 +1427,7 @@ FILE: ../../../flutter/shell/platform/linux/fl_method_response.cc FILE: ../../../flutter/shell/platform/linux/fl_method_response_test.cc FILE: ../../../flutter/shell/platform/linux/fl_mouse_cursor_plugin.cc FILE: ../../../flutter/shell/platform/linux/fl_mouse_cursor_plugin.h +FILE: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture.cc FILE: ../../../flutter/shell/platform/linux/fl_platform_plugin.cc FILE: ../../../flutter/shell/platform/linux/fl_platform_plugin.h FILE: ../../../flutter/shell/platform/linux/fl_plugin_registrar.cc diff --git a/shell/platform/linux/BUILD.gn b/shell/platform/linux/BUILD.gn index dab74d915cadd..53cb3a01b2370 100644 --- a/shell/platform/linux/BUILD.gn +++ b/shell/platform/linux/BUILD.gn @@ -55,6 +55,7 @@ _public_headers = [ "public/flutter_linux/fl_method_channel.h", "public/flutter_linux/fl_method_codec.h", "public/flutter_linux/fl_method_response.h", + "public/flutter_linux/fl_pixel_buffer_texture.h", "public/flutter_linux/fl_plugin_registrar.h", "public/flutter_linux/fl_plugin_registry.h", "public/flutter_linux/fl_standard_message_codec.h", @@ -106,6 +107,7 @@ source_set("flutter_linux_sources") { "fl_method_codec.cc", "fl_method_response.cc", "fl_mouse_cursor_plugin.cc", + "fl_pixel_buffer_texture.cc", "fl_platform_plugin.cc", "fl_plugin_registrar.cc", "fl_plugin_registry.cc", diff --git a/shell/platform/linux/fl_texture.cc b/shell/platform/linux/fl_texture.cc index 19ebe1f7bd41f..10edd4ff75d51 100644 --- a/shell/platform/linux/fl_texture.cc +++ b/shell/platform/linux/fl_texture.cc @@ -14,99 +14,6 @@ G_MODULE_EXPORT GType fl_texture_get_type(); G_DEFINE_TYPE(FlTexture, fl_texture, G_TYPE_OBJECT) -#define GL_CALL(expr) \ - do { \ - expr; \ - GLenum err = glGetError(); \ - if (err) { \ - fprintf(stderr, "glGetError %x (%s:%d)\n", err, __FILE__, __LINE__); \ - } \ - } while (0); - -struct _FlPixelBufferTexture { - FlTexture parent_instance; - - GLuint texture_id; - - FlCopyPixelBufferCallback callback; - gpointer user_data; - GDestroyNotify destroy_notify; -}; - -G_DEFINE_TYPE(FlPixelBufferTexture, - fl_pixel_buffer_texture, - fl_texture_get_type()) - -static void fl_pixel_buffer_texture_dispose(GObject* object) { - FlPixelBufferTexture* self = FL_PIXEL_BUFFER_TEXTURE(object); - - if (self->destroy_notify) { - self->destroy_notify(self->user_data); - } - - if (self->texture_id) { - glDeleteTextures(1, &self->texture_id); - self->texture_id = 0; - } - - G_OBJECT_CLASS(fl_pixel_buffer_texture_parent_class)->dispose(object); -} - -static gboolean fl_pixel_buffer_texture_populate_texture(FlTexture* texture, - uint32_t* target, - uint32_t* name, - uint32_t* width, - uint32_t* height) { - FlPixelBufferTexture* self = FL_PIXEL_BUFFER_TEXTURE(texture); - uint32_t format = 0; - const uint8_t* buffer = nullptr; - if (!self->callback || - !self->callback(&buffer, &format, width, height, self->user_data)) { - return FALSE; - } - if (self->texture_id == 0) { - GL_CALL(glGenTextures(1, &self->texture_id)); - GL_CALL(glBindTexture(GL_TEXTURE_2D, self->texture_id)); - GL_CALL( - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)); - GL_CALL( - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)); - GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - } else { - GL_CALL(glBindTexture(GL_TEXTURE_2D, self->texture_id)); - } - *target = GL_TEXTURE_2D; - *name = self->texture_id; - GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, *width, *height, 0, format, - GL_UNSIGNED_BYTE, buffer)); - return TRUE; -} - -static void fl_pixel_buffer_texture_class_init( - FlPixelBufferTextureClass* klass) { - FL_TEXTURE_CLASS(klass)->populate_texture = - fl_pixel_buffer_texture_populate_texture; - - G_OBJECT_CLASS(klass)->dispose = fl_pixel_buffer_texture_dispose; -} - -static void fl_pixel_buffer_texture_init(FlPixelBufferTexture* self) {} - -G_MODULE_EXPORT FlPixelBufferTexture* fl_pixel_buffer_texture_new( - FlCopyPixelBufferCallback callback, - void* user_data, - GDestroyNotify destroy_notify) { - g_return_val_if_fail(callback != nullptr, nullptr); - - FlPixelBufferTexture* texture = reinterpret_cast( - g_object_new(fl_pixel_buffer_texture_get_type(), nullptr)); - texture->callback = callback; - texture->user_data = user_data; - texture->destroy_notify = destroy_notify; - return texture; -} - static void fl_texture_class_init(FlTextureClass* klass) {} static void fl_texture_init(FlTexture* self) {} diff --git a/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h b/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h new file mode 100644 index 0000000000000..eecedcbf0e962 --- /dev/null +++ b/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h @@ -0,0 +1,65 @@ +// 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_PIXEL_BUFFER_TEXTURE_H_ +#define FLUTTER_SHELL_PLATFORM_LINUX_FL_PIXEL_BUFFER_TEXTURE_H_ + +#if !defined(__FLUTTER_LINUX_INSIDE__) && !defined(FLUTTER_LINUX_COMPILATION) +#error "Only can be included directly." +#endif + +#include "fl_texture.h" + +G_BEGIN_DECLS + +G_DECLARE_FINAL_TYPE(FlPixelBufferTexture, + fl_pixel_buffer_texture, + FL, + PIXEL_BUFFER_TEXTURE, + FlTexture) + +/** + * FlPixelBufferTexture: + * + * #FlPixelBufferTexture represents a pixel buffer texture. + */ + +/** + * FlCopyPixelBufferCallback: + * @buffer: (out): return callee-allocated pixel buffer. + * @format: (out): return pixel buffer format (example GL_RGBA). + * @width: (inout): pointer to width of the texture. + * @height: (inout): pointer to height of the texture. + * @user_data: (closure): data provided when populating texture at first time. + * + * Function called when Flutter wants to copy pixel buffer for populating + * texture. + * + * Returns: %TRUE on success. + */ +typedef gboolean (*FlCopyPixelBufferCallback)(const uint8_t** buffer, + uint32_t* format, + uint32_t* width, + uint32_t* height, + gpointer user_data); + +/** + * fl_pixel_buffer_texture_new: + * @callback: a callback to copy pixel buffer when populating texture. + * @user_data: (closure): user data to pass to @callback. + * @destroy_notify: (allow-none): a function which gets called to free + * @user_data, or %NULL. + * + * Creates a new #FlPixelBufferTexture. + * + * Returns: the newly created #FlPixelBufferTexture. + */ +FlPixelBufferTexture* fl_pixel_buffer_texture_new( + FlCopyPixelBufferCallback callback, + gpointer user_data, + GDestroyNotify destroy_notify); + +G_END_DECLS + +#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_PIXEL_BUFFER_TEXTURE_H_ diff --git a/shell/platform/linux/public/flutter_linux/flutter_linux.h b/shell/platform/linux/public/flutter_linux/flutter_linux.h index fbce7e1c2a271..550474887e547 100644 --- a/shell/platform/linux/public/flutter_linux/flutter_linux.h +++ b/shell/platform/linux/public/flutter_linux/flutter_linux.h @@ -20,11 +20,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include From eb9e75b47844374bee2cc5b68f11b0a1812fdc0c Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Thu, 6 May 2021 16:53:00 +1200 Subject: [PATCH 06/20] Add missing comment --- shell/platform/linux/fl_plugin_registrar.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/shell/platform/linux/fl_plugin_registrar.cc b/shell/platform/linux/fl_plugin_registrar.cc index d5cd4df9b640c..acf53f4db5bca 100644 --- a/shell/platform/linux/fl_plugin_registrar.cc +++ b/shell/platform/linux/fl_plugin_registrar.cc @@ -16,6 +16,7 @@ struct _FlPluginRegistrar { // Messenger to communicate on. FlBinaryMessenger* messenger; + // Texture registrar in use. FlTextureRegistrar* texture_registrar; }; From e137a943c2a2c1552cf78de1f79d446947645ff9 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Thu, 6 May 2021 16:53:54 +1200 Subject: [PATCH 07/20] Add missing param check --- shell/platform/linux/fl_plugin_registrar.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/shell/platform/linux/fl_plugin_registrar.cc b/shell/platform/linux/fl_plugin_registrar.cc index acf53f4db5bca..e9fe0318a65b9 100644 --- a/shell/platform/linux/fl_plugin_registrar.cc +++ b/shell/platform/linux/fl_plugin_registrar.cc @@ -51,6 +51,7 @@ FlPluginRegistrar* fl_plugin_registrar_new( FlTextureRegistrar* texture_registrar) { g_return_val_if_fail(view == nullptr || FL_IS_VIEW(view), nullptr); g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr); + g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(texture_registrar), nullptr); FlPluginRegistrar* self = FL_PLUGIN_REGISTRAR( g_object_new(fl_plugin_registrar_get_type(), nullptr)); From c62c6f1fa1451a102f1bfc3889244c4e31f068a3 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Fri, 7 May 2021 09:15:48 +1200 Subject: [PATCH 08/20] Fix memory management with texture registrar tests --- shell/platform/linux/fl_texture_registrar.cc | 3 ++- shell/platform/linux/fl_texture_registrar_test.cc | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/shell/platform/linux/fl_texture_registrar.cc b/shell/platform/linux/fl_texture_registrar.cc index bc51e19877570..d91d4ecc5c53f 100644 --- a/shell/platform/linux/fl_texture_registrar.cc +++ b/shell/platform/linux/fl_texture_registrar.cc @@ -62,7 +62,8 @@ fl_texture_registrar_register_texture(FlTextureRegistrar* self, g_return_val_if_fail(FL_IS_TEXTURE(texture), 0); int64_t id = fl_texture_get_texture_id(texture); - g_hash_table_insert(self->textures, GINT_TO_POINTER(id), g_object_ref(texture)); + g_hash_table_insert(self->textures, GINT_TO_POINTER(id), + g_object_ref(texture)); if (self->engine == nullptr) { return 0; diff --git a/shell/platform/linux/fl_texture_registrar_test.cc b/shell/platform/linux/fl_texture_registrar_test.cc index a5db0e5b85000..30e49b15f37d2 100644 --- a/shell/platform/linux/fl_texture_registrar_test.cc +++ b/shell/platform/linux/fl_texture_registrar_test.cc @@ -15,7 +15,7 @@ TEST(FlTextureRegistrarTest, RegisterTexture) { g_autoptr(FlEngine) engine = make_mock_engine(); g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine); - FlTexture* texture = + g_autoptr(FlTexture) texture = FL_TEXTURE(fl_pixel_buffer_texture_new(nullptr, nullptr, nullptr)); int64_t id = fl_texture_registrar_register_texture(registrar, texture); @@ -30,7 +30,9 @@ TEST(FlTextureRegistrarTest, RegisterTexture) { TEST(FlTextureRegistrarTest, MarkTextureFrameAvailable) { g_autoptr(FlEngine) engine = make_mock_engine(); g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine); - int64_t id = fl_texture_registrar_register_texture(registrar, nullptr); + g_autoptr(FlTexture) texture = + FL_TEXTURE(fl_pixel_buffer_texture_new(nullptr, nullptr, nullptr)); + int64_t id = fl_texture_registrar_register_texture(registrar, texture); fl_texture_registrar_mark_texture_frame_available(registrar, id); } @@ -54,7 +56,7 @@ TEST(FlTextureRegistrarTest, PopulateTexture) { *height = REAL_BUFFER_HEIGHT; return TRUE; }; - FlTexture* texture = + g_autoptr(FlTexture) texture = FL_TEXTURE(fl_pixel_buffer_texture_new(callback, nullptr, nullptr)); int64_t id = fl_texture_registrar_register_texture(registrar, texture); FlutterOpenGLTexture opengl_texture; From 6adb093fe660421829f34a81fbcadf931f9cc922 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Fri, 7 May 2021 10:28:32 +1200 Subject: [PATCH 09/20] Remove callback and make FlPixelBufferTexture derivable --- ci/licenses_golden/licenses_flutter | 1 + shell/platform/linux/BUILD.gn | 1 + shell/platform/linux/fl_engine.cc | 9 +- .../platform/linux/fl_pixel_buffer_texture.cc | 88 ++++++++++++++++++ .../linux/fl_pixel_buffer_texture_test.cc | 85 +++++++++++++++++ shell/platform/linux/fl_texture.cc | 14 +-- shell/platform/linux/fl_texture_private.h | 13 ++- shell/platform/linux/fl_texture_registrar.cc | 7 +- .../linux/fl_texture_registrar_private.h | 5 +- .../linux/fl_texture_registrar_test.cc | 80 +++++++++++----- shell/platform/linux/fl_texture_test.cc | 92 +++++++++++-------- .../flutter_linux/fl_pixel_buffer_texture.h | 72 +++++++-------- .../linux/public/flutter_linux/fl_texture.h | 71 +++----------- 13 files changed, 360 insertions(+), 178 deletions(-) create mode 100644 shell/platform/linux/fl_pixel_buffer_texture.cc create mode 100644 shell/platform/linux/fl_pixel_buffer_texture_test.cc diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 8675f509cd28e..ad65359d614e3 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1428,6 +1428,7 @@ FILE: ../../../flutter/shell/platform/linux/fl_method_response_test.cc FILE: ../../../flutter/shell/platform/linux/fl_mouse_cursor_plugin.cc FILE: ../../../flutter/shell/platform/linux/fl_mouse_cursor_plugin.h FILE: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture.cc +FILE: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture_test.cc FILE: ../../../flutter/shell/platform/linux/fl_platform_plugin.cc FILE: ../../../flutter/shell/platform/linux/fl_platform_plugin.h FILE: ../../../flutter/shell/platform/linux/fl_plugin_registrar.cc diff --git a/shell/platform/linux/BUILD.gn b/shell/platform/linux/BUILD.gn index 53cb3a01b2370..1c720f80c2b98 100644 --- a/shell/platform/linux/BUILD.gn +++ b/shell/platform/linux/BUILD.gn @@ -171,6 +171,7 @@ executable("flutter_linux_unittests") { "fl_json_message_codec_test.cc", "fl_json_method_codec_test.cc", "fl_key_event_plugin_test.cc", + "fl_pixel_buffer_texture_test.cc", "fl_message_codec_test.cc", "fl_method_channel_test.cc", "fl_method_codec_test.cc", diff --git a/shell/platform/linux/fl_engine.cc b/shell/platform/linux/fl_engine.cc index f51f6e8aac797..07d14c8e8141a 100644 --- a/shell/platform/linux/fl_engine.cc +++ b/shell/platform/linux/fl_engine.cc @@ -280,8 +280,13 @@ static bool fl_engine_gl_external_texture_frame_callback( if (!self->texture_registrar) { return false; } - return fl_texture_registrar_populate_texture( - self->texture_registrar, texture_id, width, height, texture); + g_autoptr(GError) error = nullptr; + gboolean result = fl_texture_registrar_populate_texture( + self->texture_registrar, texture_id, width, height, texture, &error); + if (!result) { + g_warning("%s", error->message); + } + return result; } // Called by the engine to determine if it is on the GTK thread. diff --git a/shell/platform/linux/fl_pixel_buffer_texture.cc b/shell/platform/linux/fl_pixel_buffer_texture.cc new file mode 100644 index 0000000000000..dafc654374c9a --- /dev/null +++ b/shell/platform/linux/fl_pixel_buffer_texture.cc @@ -0,0 +1,88 @@ +// 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/public/flutter_linux/fl_pixel_buffer_texture.h" + +#include +#include +#include + +#define GL_CALL(expr) \ + do { \ + expr; \ + GLenum err = glGetError(); \ + if (err) { \ + fprintf(stderr, "glGetError %x (%s:%d)\n", err, __FILE__, __LINE__); \ + } \ + } while (0); + +typedef struct { + GLuint texture_id; +} FlPixelBufferTexturePrivate; + +// Added here to stop the compiler from optimising this function away. +G_MODULE_EXPORT GType fl_pixel_buffer_texture_get_type(); + +G_DEFINE_TYPE_WITH_PRIVATE(FlPixelBufferTexture, + fl_pixel_buffer_texture, + fl_texture_get_type()) + +static void fl_pixel_buffer_texture_dispose(GObject* object) { + FlPixelBufferTexture* self = FL_PIXEL_BUFFER_TEXTURE(object); + FlPixelBufferTexturePrivate* priv = + reinterpret_cast( + fl_pixel_buffer_texture_get_instance_private(self)); + + if (priv->texture_id) { + glDeleteTextures(1, &priv->texture_id); + priv->texture_id = 0; + } + + G_OBJECT_CLASS(fl_pixel_buffer_texture_parent_class)->dispose(object); +} + +static gboolean fl_pixel_buffer_texture_populate(FlTexture* texture, + uint32_t* target, + uint32_t* name, + uint32_t* width, + uint32_t* height, + GError** error) { + FlPixelBufferTexture* self = FL_PIXEL_BUFFER_TEXTURE(texture); + FlPixelBufferTexturePrivate* priv = + reinterpret_cast( + fl_pixel_buffer_texture_get_instance_private(self)); + + uint32_t format = 0; + const uint8_t* buffer = nullptr; + if (!FL_PIXEL_BUFFER_TEXTURE_GET_CLASS(self)->copy_pixels( + self, &buffer, &format, width, height, error)) { + return FALSE; + } + if (priv->texture_id == 0) { + GL_CALL(glGenTextures(1, &priv->texture_id)); + GL_CALL(glBindTexture(GL_TEXTURE_2D, priv->texture_id)); + GL_CALL( + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)); + GL_CALL( + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)); + GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + } else { + GL_CALL(glBindTexture(GL_TEXTURE_2D, priv->texture_id)); + } + *target = GL_TEXTURE_2D; + *name = priv->texture_id; + GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, *width, *height, 0, format, + GL_UNSIGNED_BYTE, buffer)); + return TRUE; +} + +static void fl_pixel_buffer_texture_class_init( + FlPixelBufferTextureClass* klass) { + FL_TEXTURE_CLASS(klass)->populate = fl_pixel_buffer_texture_populate; + + G_OBJECT_CLASS(klass)->dispose = fl_pixel_buffer_texture_dispose; +} + +static void fl_pixel_buffer_texture_init(FlPixelBufferTexture* self) {} diff --git a/shell/platform/linux/fl_pixel_buffer_texture_test.cc b/shell/platform/linux/fl_pixel_buffer_texture_test.cc new file mode 100644 index 0000000000000..2da689ac6e159 --- /dev/null +++ b/shell/platform/linux/fl_pixel_buffer_texture_test.cc @@ -0,0 +1,85 @@ +// 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/public/flutter_linux/fl_pixel_buffer_texture.h" +#include "flutter/shell/platform/linux/fl_texture_private.h" +#include "flutter/shell/platform/linux/fl_texture_registrar_private.h" +#include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h" +#include "flutter/shell/platform/linux/testing/fl_test.h" +#include "gtest/gtest.h" + +#include + +static constexpr uint32_t BUFFER_WIDTH = 4u; +static constexpr uint32_t BUFFER_HEIGHT = 4u; +static constexpr uint32_t REAL_BUFFER_WIDTH = 2u; +static constexpr uint32_t REAL_BUFFER_HEIGHT = 2u; + +G_DECLARE_FINAL_TYPE(FlTestPixelBufferTexture, + fl_test_pixel_buffer_texture, + FL, + TEST_PIXEL_BUFFER_TEXTURE, + FlPixelBufferTexture) + +/// A simple texture with fixed contents. +struct _FlTestPixelBufferTexture { + FlPixelBufferTexture parent_instance; +}; + +G_DEFINE_TYPE(FlTestPixelBufferTexture, + fl_test_pixel_buffer_texture, + fl_pixel_buffer_texture_get_type()) + +static gboolean fl_test_pixel_buffer_texture_copy_pixels( + FlPixelBufferTexture* texture, + const uint8_t** out_buffer, + uint32_t* format, + uint32_t* width, + uint32_t* height, + GError** error) { + EXPECT_TRUE(FL_IS_TEST_PIXEL_BUFFER_TEXTURE(texture)); + + static const uint8_t buffer[] = {0x7a, 0x8a, 0x9a, 0xaa}; + EXPECT_EQ(*width, BUFFER_WIDTH); + EXPECT_EQ(*height, BUFFER_HEIGHT); + *out_buffer = buffer; + *format = GL_R8; + *width = REAL_BUFFER_WIDTH; + *height = REAL_BUFFER_HEIGHT; + + return TRUE; +} + +static void fl_test_pixel_buffer_texture_class_init( + FlTestPixelBufferTextureClass* klass) { + FL_PIXEL_BUFFER_TEXTURE_CLASS(klass)->copy_pixels = + fl_test_pixel_buffer_texture_copy_pixels; +} + +static void fl_test_pixel_buffer_texture_init(FlTestPixelBufferTexture* self) {} + +static FlTestPixelBufferTexture* fl_test_pixel_buffer_texture_new() { + return FL_TEST_PIXEL_BUFFER_TEXTURE( + g_object_new(fl_test_pixel_buffer_texture_get_type(), nullptr)); +} + +// Test that getting the texture ID works. +TEST(FlPixelBufferTextureTest, TextureID) { + // Texture ID is not assigned until the pixel buffer is copied once. + g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_pixel_buffer_texture_new()); + EXPECT_EQ(fl_texture_get_texture_id(texture), + reinterpret_cast(texture)); +} + +// Test that populating an OpenGL texture works. +TEST(FlPixelBufferTextureTest, PopulateTexture) { + g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_pixel_buffer_texture_new()); + FlutterOpenGLTexture opengl_texture = {0}; + g_autoptr(GError) error = nullptr; + EXPECT_TRUE(fl_texture_populate(texture, BUFFER_WIDTH, BUFFER_HEIGHT, + &opengl_texture, &error)); + EXPECT_EQ(error, nullptr); + EXPECT_EQ(opengl_texture.width, REAL_BUFFER_WIDTH); + EXPECT_EQ(opengl_texture.height, REAL_BUFFER_HEIGHT); +} diff --git a/shell/platform/linux/fl_texture.cc b/shell/platform/linux/fl_texture.cc index 10edd4ff75d51..a0f5176ae27e6 100644 --- a/shell/platform/linux/fl_texture.cc +++ b/shell/platform/linux/fl_texture.cc @@ -18,14 +18,14 @@ static void fl_texture_class_init(FlTextureClass* klass) {} static void fl_texture_init(FlTexture* self) {} -gboolean fl_texture_populate_texture(FlTexture* self, - uint32_t width, - uint32_t height, - FlutterOpenGLTexture* opengl_texture) { +gboolean fl_texture_populate(FlTexture* self, + uint32_t width, + uint32_t height, + FlutterOpenGLTexture* opengl_texture, + GError** error) { uint32_t target = 0, name = 0; - bool populate_result = FL_TEXTURE_GET_CLASS(self)->populate_texture( - self, &target, &name, &width, &height); - if (!populate_result) { + if (!FL_TEXTURE_GET_CLASS(self)->populate(self, &target, &name, &width, + &height, error)) { return false; } diff --git a/shell/platform/linux/fl_texture_private.h b/shell/platform/linux/fl_texture_private.h index e1b75ec67a828..25127c9a3e85c 100644 --- a/shell/platform/linux/fl_texture_private.h +++ b/shell/platform/linux/fl_texture_private.h @@ -11,21 +11,24 @@ G_BEGIN_DECLS /** - * fl_texture_populate_texture: + * fl_texture_populate: * @texture: an #FlTexture. * @width: width of the texture. * @height: height of the texture. * @opengl_texture: (out): return an #FlutterOpenGLTexture. + * @error: (allow-none): #GError location to store the error occurring, or + * %NULL to ignore. * * Attempts to populate the specified @opengl_texture with texture details * such as the name, width, height and the pixel format. * * Returns: %TRUE on success. */ -gboolean fl_texture_populate_texture(FlTexture* texture, - uint32_t width, - uint32_t height, - FlutterOpenGLTexture* opengl_texture); +gboolean fl_texture_populate(FlTexture* texture, + uint32_t width, + uint32_t height, + FlutterOpenGLTexture* opengl_texture, + GError** error); /** * fl_texture_get_texture_id: diff --git a/shell/platform/linux/fl_texture_registrar.cc b/shell/platform/linux/fl_texture_registrar.cc index d91d4ecc5c53f..436b6fc5299d2 100644 --- a/shell/platform/linux/fl_texture_registrar.cc +++ b/shell/platform/linux/fl_texture_registrar.cc @@ -90,13 +90,16 @@ gboolean fl_texture_registrar_populate_texture( int64_t texture_id, uint32_t width, uint32_t height, - FlutterOpenGLTexture* opengl_texture) { + FlutterOpenGLTexture* opengl_texture, + GError** error) { FlTexture* texture = FL_TEXTURE( g_hash_table_lookup(self->textures, GINT_TO_POINTER(texture_id))); if (texture == nullptr) { + g_set_error(error, fl_engine_error_quark(), FL_ENGINE_ERROR_FAILED, + "Unable to find texture %" G_GINT64_FORMAT, texture_id); return FALSE; } - return fl_texture_populate_texture(texture, width, height, opengl_texture); + return fl_texture_populate(texture, width, height, opengl_texture, error); } G_MODULE_EXPORT void fl_texture_registrar_unregister_texture( diff --git a/shell/platform/linux/fl_texture_registrar_private.h b/shell/platform/linux/fl_texture_registrar_private.h index 8f2ca3b80d021..954215ef9761a 100644 --- a/shell/platform/linux/fl_texture_registrar_private.h +++ b/shell/platform/linux/fl_texture_registrar_private.h @@ -28,6 +28,8 @@ FlTextureRegistrar* fl_texture_registrar_new(FlEngine* engine); * @width: width of the texture. * @height: height of the texture. * @opengl_texture: (out): return an #FlutterOpenGLTexture. + * @error: (allow-none): #GError location to store the error occurring, or + * %NULL to ignore. * * Attempts to populate the given @texture_id. * @@ -38,7 +40,8 @@ gboolean fl_texture_registrar_populate_texture( int64_t texture_id, uint32_t width, uint32_t height, - FlutterOpenGLTexture* opengl_texture); + FlutterOpenGLTexture* opengl_texture, + GError** error); /** * fl_texture_registrar_get_texture: diff --git a/shell/platform/linux/fl_texture_registrar_test.cc b/shell/platform/linux/fl_texture_registrar_test.cc index 30e49b15f37d2..a03f4ff41b328 100644 --- a/shell/platform/linux/fl_texture_registrar_test.cc +++ b/shell/platform/linux/fl_texture_registrar_test.cc @@ -4,6 +4,7 @@ #include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h" #include "flutter/shell/platform/linux/fl_texture_registrar_private.h" +#include "flutter/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h" #include "flutter/shell/platform/linux/testing/fl_test.h" #include "gtest/gtest.h" @@ -11,12 +12,61 @@ #include +static constexpr uint32_t BUFFER_WIDTH = 4u; +static constexpr uint32_t BUFFER_HEIGHT = 4u; +static constexpr uint32_t REAL_BUFFER_WIDTH = 2u; +static constexpr uint32_t REAL_BUFFER_HEIGHT = 2u; + +G_DECLARE_FINAL_TYPE(FlTestRegistrarTexture, + fl_test_registrar_texture, + FL, + TEST_REGISTRAR_TEXTURE, + FlTexture) + +/// A simple texture. +struct _FlTestRegistrarTexture { + FlTexture parent_instance; +}; + +G_DEFINE_TYPE(FlTestRegistrarTexture, + fl_test_registrar_texture, + fl_texture_get_type()) + +static gboolean fl_test_registrar_texture_populate(FlTexture* texture, + uint32_t* target, + uint32_t* format, + uint32_t* width, + uint32_t* height, + GError** error) { + EXPECT_TRUE(FL_IS_TEST_REGISTRAR_TEXTURE(texture)); + + EXPECT_EQ(*width, BUFFER_WIDTH); + EXPECT_EQ(*height, BUFFER_HEIGHT); + *target = GL_TEXTURE_2D; + *format = GL_R8; + *width = REAL_BUFFER_WIDTH; + *height = REAL_BUFFER_HEIGHT; + + return TRUE; +} + +static void fl_test_registrar_texture_class_init( + FlTestRegistrarTextureClass* klass) { + FL_TEXTURE_CLASS(klass)->populate = fl_test_registrar_texture_populate; +} + +static void fl_test_registrar_texture_init(FlTestRegistrarTexture* self) {} + +static FlTestRegistrarTexture* fl_test_registrar_texture_new() { + return FL_TEST_REGISTRAR_TEXTURE( + g_object_new(fl_test_registrar_texture_get_type(), nullptr)); +} + // Test that registering a texture works. TEST(FlTextureRegistrarTest, RegisterTexture) { g_autoptr(FlEngine) engine = make_mock_engine(); g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine); - g_autoptr(FlTexture) texture = - FL_TEXTURE(fl_pixel_buffer_texture_new(nullptr, nullptr, nullptr)); + g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_registrar_texture_new()); int64_t id = fl_texture_registrar_register_texture(registrar, texture); EXPECT_EQ(fl_texture_registrar_get_texture(registrar, id), texture); @@ -30,8 +80,7 @@ TEST(FlTextureRegistrarTest, RegisterTexture) { TEST(FlTextureRegistrarTest, MarkTextureFrameAvailable) { g_autoptr(FlEngine) engine = make_mock_engine(); g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine); - g_autoptr(FlTexture) texture = - FL_TEXTURE(fl_pixel_buffer_texture_new(nullptr, nullptr, nullptr)); + g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_registrar_texture_new()); int64_t id = fl_texture_registrar_register_texture(registrar, texture); fl_texture_registrar_mark_texture_frame_available(registrar, id); } @@ -40,28 +89,13 @@ TEST(FlTextureRegistrarTest, MarkTextureFrameAvailable) { TEST(FlTextureRegistrarTest, PopulateTexture) { g_autoptr(FlEngine) engine = make_mock_engine(); g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine); - static constexpr uint32_t BUFFER_WIDTH = 4u; - static constexpr uint32_t BUFFER_HEIGHT = 4u; - static constexpr uint32_t REAL_BUFFER_WIDTH = 2u; - static constexpr uint32_t REAL_BUFFER_HEIGHT = 2u; - FlCopyPixelBufferCallback callback = - [](const uint8_t** out_buffer, uint32_t* format, uint32_t* width, - uint32_t* height, gpointer user_data) -> gboolean { - const uint8_t buffer[] = {0x7a, 0x8a, 0x9a, 0xaa}; - EXPECT_EQ(*width, BUFFER_WIDTH); - EXPECT_EQ(*height, BUFFER_HEIGHT); - *out_buffer = buffer; - *format = GL_R8; - *width = REAL_BUFFER_WIDTH; - *height = REAL_BUFFER_HEIGHT; - return TRUE; - }; - g_autoptr(FlTexture) texture = - FL_TEXTURE(fl_pixel_buffer_texture_new(callback, nullptr, nullptr)); + g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_registrar_texture_new()); int64_t id = fl_texture_registrar_register_texture(registrar, texture); FlutterOpenGLTexture opengl_texture; + g_autoptr(GError) error = nullptr; EXPECT_TRUE(fl_texture_registrar_populate_texture( - registrar, id, BUFFER_WIDTH, BUFFER_HEIGHT, &opengl_texture)); + registrar, id, BUFFER_WIDTH, BUFFER_HEIGHT, &opengl_texture, &error)); + EXPECT_EQ(error, nullptr); EXPECT_EQ(opengl_texture.width, REAL_BUFFER_WIDTH); EXPECT_EQ(opengl_texture.height, REAL_BUFFER_HEIGHT); } diff --git a/shell/platform/linux/fl_texture_test.cc b/shell/platform/linux/fl_texture_test.cc index 03b517138bab1..9a4d2341bc95f 100644 --- a/shell/platform/linux/fl_texture_test.cc +++ b/shell/platform/linux/fl_texture_test.cc @@ -11,54 +11,68 @@ #include +static constexpr uint32_t BUFFER_WIDTH = 4u; +static constexpr uint32_t BUFFER_HEIGHT = 4u; +static constexpr uint32_t REAL_BUFFER_WIDTH = 2u; +static constexpr uint32_t REAL_BUFFER_HEIGHT = 2u; + +G_DECLARE_FINAL_TYPE(FlTestTexture, + fl_test_texture, + FL, + TEST_TEXTURE, + FlTexture) + +/// A simple texture. +struct _FlTestTexture { + FlTexture parent_instance; +}; + +G_DEFINE_TYPE(FlTestTexture, fl_test_texture, fl_texture_get_type()) + +static gboolean fl_test_texture_populate(FlTexture* texture, + uint32_t* target, + uint32_t* format, + uint32_t* width, + uint32_t* height, + GError** error) { + EXPECT_TRUE(FL_IS_TEST_TEXTURE(texture)); + + EXPECT_EQ(*width, BUFFER_WIDTH); + EXPECT_EQ(*height, BUFFER_HEIGHT); + *target = GL_TEXTURE_2D; + *format = GL_R8; + *width = REAL_BUFFER_WIDTH; + *height = REAL_BUFFER_HEIGHT; + + return TRUE; +} + +static void fl_test_texture_class_init(FlTestTextureClass* klass) { + FL_TEXTURE_CLASS(klass)->populate = fl_test_texture_populate; +} + +static void fl_test_texture_init(FlTestTexture* self) {} + +static FlTestTexture* fl_test_texture_new() { + return FL_TEST_TEXTURE(g_object_new(fl_test_texture_get_type(), nullptr)); +} + // Test that getting the texture ID works. TEST(FlTextureTest, TextureID) { - // Texture ID is not assigned until the pixel buffer is copied once. - static constexpr uint32_t BUFFER_WIDTH = 4u; - static constexpr uint32_t BUFFER_HEIGHT = 4u; - static constexpr uint32_t REAL_BUFFER_WIDTH = 2u; - static constexpr uint32_t REAL_BUFFER_HEIGHT = 2u; - FlCopyPixelBufferCallback callback = - [](const uint8_t** out_buffer, uint32_t* format, uint32_t* width, - uint32_t* height, gpointer user_data) -> gboolean { - static const uint8_t buffer[] = {0xc9, 0xc8, 0xc7, 0xc6}; - EXPECT_EQ(*width, BUFFER_WIDTH); - EXPECT_EQ(*height, BUFFER_HEIGHT); - *out_buffer = buffer; - *format = GL_R8; - *width = REAL_BUFFER_WIDTH; - *height = REAL_BUFFER_HEIGHT; - return TRUE; - }; - g_autoptr(FlTexture) texture = - FL_TEXTURE(fl_pixel_buffer_texture_new(callback, nullptr, nullptr)); + // Texture ID is not assigned until the testure is populated. + g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_texture_new()); EXPECT_EQ(fl_texture_get_texture_id(texture), reinterpret_cast(texture)); } // Test that populating an OpenGL texture works. TEST(FlTextureTest, PopulateTexture) { - static constexpr uint32_t BUFFER_WIDTH = 4u; - static constexpr uint32_t BUFFER_HEIGHT = 4u; - static constexpr uint32_t REAL_BUFFER_WIDTH = 2u; - static constexpr uint32_t REAL_BUFFER_HEIGHT = 2u; - FlCopyPixelBufferCallback callback = - [](const uint8_t** out_buffer, uint32_t* format, uint32_t* width, - uint32_t* height, gpointer user_data) -> gboolean { - static const uint8_t buffer[] = {0x7a, 0x8a, 0x9a, 0xaa}; - EXPECT_EQ(*width, BUFFER_WIDTH); - EXPECT_EQ(*height, BUFFER_HEIGHT); - *out_buffer = buffer; - *format = GL_R8; - *width = REAL_BUFFER_WIDTH; - *height = REAL_BUFFER_HEIGHT; - return TRUE; - }; - g_autoptr(FlTexture) texture = - FL_TEXTURE(fl_pixel_buffer_texture_new(callback, nullptr, nullptr)); + g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_texture_new()); FlutterOpenGLTexture opengl_texture = {0}; - EXPECT_TRUE(fl_texture_populate_texture(texture, BUFFER_WIDTH, BUFFER_HEIGHT, - &opengl_texture)); + g_autoptr(GError) error = nullptr; + EXPECT_TRUE(fl_texture_populate(texture, BUFFER_WIDTH, BUFFER_HEIGHT, + &opengl_texture, &error)); + EXPECT_EQ(error, nullptr); EXPECT_EQ(opengl_texture.width, REAL_BUFFER_WIDTH); EXPECT_EQ(opengl_texture.height, REAL_BUFFER_HEIGHT); } diff --git a/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h b/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h index eecedcbf0e962..e0ddb8fd87a87 100644 --- a/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h +++ b/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h @@ -13,53 +13,43 @@ G_BEGIN_DECLS -G_DECLARE_FINAL_TYPE(FlPixelBufferTexture, - fl_pixel_buffer_texture, - FL, - PIXEL_BUFFER_TEXTURE, - FlTexture) +G_DECLARE_DERIVABLE_TYPE(FlPixelBufferTexture, + fl_pixel_buffer_texture, + FL, + PIXEL_BUFFER_TEXTURE, + FlTexture) + +struct _FlPixelBufferTextureClass { + FlTextureClass parent_class; + + /** + * Virtual method called when Flutter wants to copy pixel buffer for + * populating this texture. + * @texture: an #FlPixelBufferTexture. + * @buffer: (out): pixel data. + * @format: (out): pixel buffer format (example GL_RGBA). + * @width: (inout): width of the texture in pixels. + * @height: (inout): height of the texture in pixels. + * @error: (allow-none): #GError location to store the error occurring, or + * %NULL to ignore. + * + * Returns: %TRUE on success. + */ + gboolean (*copy_pixels)(FlPixelBufferTexture* texture, + const uint8_t** buffer, + uint32_t* format, + uint32_t* width, + uint32_t* height, + GError** error); +}; /** * FlPixelBufferTexture: * - * #FlPixelBufferTexture represents a pixel buffer texture. + * #FlPixelBufferTexture represents an OpenGL texture generated from a pixel + * buffer. */ -/** - * FlCopyPixelBufferCallback: - * @buffer: (out): return callee-allocated pixel buffer. - * @format: (out): return pixel buffer format (example GL_RGBA). - * @width: (inout): pointer to width of the texture. - * @height: (inout): pointer to height of the texture. - * @user_data: (closure): data provided when populating texture at first time. - * - * Function called when Flutter wants to copy pixel buffer for populating - * texture. - * - * Returns: %TRUE on success. - */ -typedef gboolean (*FlCopyPixelBufferCallback)(const uint8_t** buffer, - uint32_t* format, - uint32_t* width, - uint32_t* height, - gpointer user_data); - -/** - * fl_pixel_buffer_texture_new: - * @callback: a callback to copy pixel buffer when populating texture. - * @user_data: (closure): user data to pass to @callback. - * @destroy_notify: (allow-none): a function which gets called to free - * @user_data, or %NULL. - * - * Creates a new #FlPixelBufferTexture. - * - * Returns: the newly created #FlPixelBufferTexture. - */ -FlPixelBufferTexture* fl_pixel_buffer_texture_new( - FlCopyPixelBufferCallback callback, - gpointer user_data, - GDestroyNotify destroy_notify); - G_END_DECLS #endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_PIXEL_BUFFER_TEXTURE_H_ diff --git a/shell/platform/linux/public/flutter_linux/fl_texture.h b/shell/platform/linux/public/flutter_linux/fl_texture.h index a98c5ee213e06..56a934ba2d2c5 100644 --- a/shell/platform/linux/public/flutter_linux/fl_texture.h +++ b/shell/platform/linux/public/flutter_linux/fl_texture.h @@ -19,7 +19,7 @@ G_DECLARE_DERIVABLE_TYPE(FlTexture, fl_texture, FL, TEXTURE, GObject) /** * FlTexture: * - * #FlTexture is an abstract class that represents a texture. + * #FlTexture is an abstract class that represents an OpenGL texture. */ struct _FlTextureClass { @@ -28,68 +28,23 @@ struct _FlTextureClass { /** * Virtual method called when Flutter populates this texture. * @texture: an #FlTexture. - * @target: return texture target (example GL_TEXTURE_2D or - * GL_TEXTURE_RECTANGLE). - * @name: (out): return name of texture. - * @width: (inout): pointer to width of the texture. - * @height: (inout): pointer to height of the texture. + * @target: texture target (example GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE). + * @name: (out): name of texture. + * @width: (inout): width of the texture in pixels. + * @height: (inout): height of the texture in pixels. + * @error: (allow-none): #GError location to store the error occurring, or + * %NULL to ignore. * * Returns: %TRUE on success. */ - gboolean (*populate_texture)(FlTexture* texture, - uint32_t* target, - uint32_t* name, - uint32_t* width, - uint32_t* height); + gboolean (*populate)(FlTexture* texture, + uint32_t* target, + uint32_t* name, + uint32_t* width, + uint32_t* height, + GError** error); }; -G_DECLARE_FINAL_TYPE(FlPixelBufferTexture, - fl_pixel_buffer_texture, - FL, - PIXEL_BUFFER_TEXTURE, - FlTexture) - -/** - * FlPixelBufferTexture: - * - * #FlPixelBufferTexture represents a pixel buffer texture. - */ - -/** - * FlCopyPixelBufferCallback: - * @buffer: (out): return callee-allocated pixel buffer. - * @format: (out): return pixel buffer format (example GL_RGBA). - * @width: (inout): pointer to width of the texture. - * @height: (inout): pointer to height of the texture. - * @user_data: (closure): data provided when populating texture at first time. - * - * Function called when Flutter wants to copy pixel buffer for populating - * texture. - * - * Returns: %TRUE on success. - */ -typedef gboolean (*FlCopyPixelBufferCallback)(const uint8_t** buffer, - uint32_t* format, - uint32_t* width, - uint32_t* height, - gpointer user_data); - -/** - * fl_pixel_buffer_texture_new: - * @callback: a callback to copy pixel buffer when populating texture. - * @user_data: (closure): user data to pass to @callback. - * @destroy_notify: (allow-none): a function which gets called to free - * @user_data, or %NULL. - * - * Creates a new #FlPixelBufferTexture. - * - * Returns: the newly created #FlPixelBufferTexture. - */ -FlPixelBufferTexture* fl_pixel_buffer_texture_new( - FlCopyPixelBufferCallback callback, - gpointer user_data, - GDestroyNotify destroy_notify); - G_END_DECLS #endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_TEXTURE_H_ From c4c78225c4e927c9e4c421f08fdd5e0d2b107ba4 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 7 May 2021 14:55:51 +0800 Subject: [PATCH 10/20] Add some comments --- shell/platform/linux/public/flutter_linux/fl_texture.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/shell/platform/linux/public/flutter_linux/fl_texture.h b/shell/platform/linux/public/flutter_linux/fl_texture.h index 56a934ba2d2c5..46138124608cc 100644 --- a/shell/platform/linux/public/flutter_linux/fl_texture.h +++ b/shell/platform/linux/public/flutter_linux/fl_texture.h @@ -20,13 +20,18 @@ G_DECLARE_DERIVABLE_TYPE(FlTexture, fl_texture, FL, TEXTURE, GObject) * FlTexture: * * #FlTexture is an abstract class that represents an OpenGL texture. + * + * If you want to render textures in other OpenGL context, create and use the + * #GdkGLContext by calling gdk_window_create_gl_context () with the #GdkWindow + * of #FlView. The context will be shared with the one used by Flutter. */ struct _FlTextureClass { GObjectClass parent_class; /** - * Virtual method called when Flutter populates this texture. + * Virtual method called when Flutter populates this texture. The OpenGL + * context used by Flutter has been already set. * @texture: an #FlTexture. * @target: texture target (example GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE). * @name: (out): name of texture. From d545cc3d07772fd8d2ff860ef91e70bcbe5f54ee Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 7 May 2021 22:03:28 +0800 Subject: [PATCH 11/20] fix: format --- shell/platform/linux/BUILD.gn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/linux/BUILD.gn b/shell/platform/linux/BUILD.gn index 1c720f80c2b98..f187742f79fd0 100644 --- a/shell/platform/linux/BUILD.gn +++ b/shell/platform/linux/BUILD.gn @@ -171,11 +171,11 @@ executable("flutter_linux_unittests") { "fl_json_message_codec_test.cc", "fl_json_method_codec_test.cc", "fl_key_event_plugin_test.cc", - "fl_pixel_buffer_texture_test.cc", "fl_message_codec_test.cc", "fl_method_channel_test.cc", "fl_method_codec_test.cc", "fl_method_response_test.cc", + "fl_pixel_buffer_texture_test.cc", "fl_standard_message_codec_test.cc", "fl_standard_method_codec_test.cc", "fl_string_codec_test.cc", From 50fd4efb31a7b20586bfa49573092560ebba713c Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Wed, 12 May 2021 15:33:11 +1200 Subject: [PATCH 12/20] Add new file to licenses --- ci/licenses_golden/licenses_flutter | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 1657857b6826a..53dbc0ffa358f 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1515,6 +1515,7 @@ FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_method_call. FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_method_channel.h FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_method_codec.h FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_method_response.h +FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_plugin_registrar.h FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_plugin_registry.h FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_standard_message_codec.h From 150f012268baa0adb1c089f9bde4a9ccea6de612 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Wed, 12 May 2021 15:33:39 +1200 Subject: [PATCH 13/20] Return correct texture ID --- shell/platform/linux/fl_texture_registrar.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/linux/fl_texture_registrar.cc b/shell/platform/linux/fl_texture_registrar.cc index 436b6fc5299d2..03864d7170a43 100644 --- a/shell/platform/linux/fl_texture_registrar.cc +++ b/shell/platform/linux/fl_texture_registrar.cc @@ -66,7 +66,7 @@ fl_texture_registrar_register_texture(FlTextureRegistrar* self, g_object_ref(texture)); if (self->engine == nullptr) { - return 0; + return id; } fl_engine_register_external_texture(self->engine, id); From e31dfdd22d0abe02da1eb41aca29eb98df1c4f58 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Wed, 12 May 2021 15:33:59 +1200 Subject: [PATCH 14/20] Consistent boolean values --- shell/platform/linux/fl_texture.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/linux/fl_texture.cc b/shell/platform/linux/fl_texture.cc index a0f5176ae27e6..f371e9b9dc664 100644 --- a/shell/platform/linux/fl_texture.cc +++ b/shell/platform/linux/fl_texture.cc @@ -26,7 +26,7 @@ gboolean fl_texture_populate(FlTexture* self, uint32_t target = 0, name = 0; if (!FL_TEXTURE_GET_CLASS(self)->populate(self, &target, &name, &width, &height, error)) { - return false; + return FALSE; } opengl_texture->target = target; From 02e56b6c1c90c751a36e4eae7e74fc8d6e3066c3 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 7 Jul 2021 21:30:13 +0800 Subject: [PATCH 15/20] Make FlTexture more general --- ci/licenses_golden/licenses_flutter | 6 +- shell/platform/linux/BUILD.gn | 4 +- shell/platform/linux/fl_engine.cc | 2 +- .../platform/linux/fl_pixel_buffer_texture.cc | 72 +++++++++++-------- .../linux/fl_pixel_buffer_texture_private.h | 36 ++++++++++ .../linux/fl_pixel_buffer_texture_test.cc | 8 ++- shell/platform/linux/fl_texture.cc | 23 ------ shell/platform/linux/fl_texture_gl.cc | 41 +++++++++++ shell/platform/linux/fl_texture_gl_private.h | 36 ++++++++++ ..._texture_test.cc => fl_texture_gl_test.cc} | 17 ++--- shell/platform/linux/fl_texture_private.h | 22 +----- shell/platform/linux/fl_texture_registrar.cc | 35 ++++++--- .../linux/fl_texture_registrar_private.h | 4 +- .../linux/fl_texture_registrar_test.cc | 13 ++-- .../linux/public/flutter_linux/fl_texture.h | 28 ++------ .../public/flutter_linux/fl_texture_gl.h | 56 +++++++++++++++ 16 files changed, 273 insertions(+), 130 deletions(-) create mode 100644 shell/platform/linux/fl_pixel_buffer_texture_private.h create mode 100644 shell/platform/linux/fl_texture_gl.cc create mode 100644 shell/platform/linux/fl_texture_gl_private.h rename shell/platform/linux/{fl_texture_test.cc => fl_texture_gl_test.cc} (83%) create mode 100644 shell/platform/linux/public/flutter_linux/fl_texture_gl.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index d75b6769aedd5..a27d4b8250a5c 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1509,6 +1509,7 @@ FILE: ../../../flutter/shell/platform/linux/fl_method_response_test.cc FILE: ../../../flutter/shell/platform/linux/fl_mouse_cursor_plugin.cc FILE: ../../../flutter/shell/platform/linux/fl_mouse_cursor_plugin.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 FILE: ../../../flutter/shell/platform/linux/fl_platform_plugin.cc FILE: ../../../flutter/shell/platform/linux/fl_platform_plugin.h @@ -1535,11 +1536,13 @@ FILE: ../../../flutter/shell/platform/linux/fl_task_runner.h FILE: ../../../flutter/shell/platform/linux/fl_text_input_plugin.cc FILE: ../../../flutter/shell/platform/linux/fl_text_input_plugin.h FILE: ../../../flutter/shell/platform/linux/fl_texture.cc +FILE: ../../../flutter/shell/platform/linux/fl_texture_gl.cc +FILE: ../../../flutter/shell/platform/linux/fl_texture_gl_private.h +FILE: ../../../flutter/shell/platform/linux/fl_texture_gl_test.cc FILE: ../../../flutter/shell/platform/linux/fl_texture_private.h FILE: ../../../flutter/shell/platform/linux/fl_texture_registrar.cc FILE: ../../../flutter/shell/platform/linux/fl_texture_registrar_private.h FILE: ../../../flutter/shell/platform/linux/fl_texture_registrar_test.cc -FILE: ../../../flutter/shell/platform/linux/fl_texture_test.cc FILE: ../../../flutter/shell/platform/linux/fl_value.cc FILE: ../../../flutter/shell/platform/linux/fl_value_test.cc FILE: ../../../flutter/shell/platform/linux/fl_view.cc @@ -1568,6 +1571,7 @@ FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_standard_mes FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_string_codec.h FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_texture.h +FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_texture_gl.h FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_value.h FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_view.h diff --git a/shell/platform/linux/BUILD.gn b/shell/platform/linux/BUILD.gn index edd6f76e11ca7..f19057d635e44 100644 --- a/shell/platform/linux/BUILD.gn +++ b/shell/platform/linux/BUILD.gn @@ -62,6 +62,7 @@ _public_headers = [ "public/flutter_linux/fl_standard_method_codec.h", "public/flutter_linux/fl_string_codec.h", "public/flutter_linux/fl_texture.h", + "public/flutter_linux/fl_texture_gl.h", "public/flutter_linux/fl_texture_registrar.h", "public/flutter_linux/fl_value.h", "public/flutter_linux/fl_view.h", @@ -132,6 +133,7 @@ source_set("flutter_linux_sources") { "fl_task_runner.h", "fl_text_input_plugin.cc", "fl_texture.cc", + "fl_texture_gl.cc", "fl_texture_registrar.cc", "fl_value.cc", "fl_view.cc", @@ -194,8 +196,8 @@ executable("flutter_linux_unittests") { "fl_standard_message_codec_test.cc", "fl_standard_method_codec_test.cc", "fl_string_codec_test.cc", + "fl_texture_gl_test.cc", "fl_texture_registrar_test.cc", - "fl_texture_test.cc", "fl_value_test.cc", "testing/fl_test.cc", "testing/mock_engine.cc", diff --git a/shell/platform/linux/fl_engine.cc b/shell/platform/linux/fl_engine.cc index 36314e932df0f..b575e2c975437 100644 --- a/shell/platform/linux/fl_engine.cc +++ b/shell/platform/linux/fl_engine.cc @@ -229,7 +229,7 @@ static bool fl_engine_gl_external_texture_frame_callback( return false; } g_autoptr(GError) error = nullptr; - gboolean result = fl_texture_registrar_populate_texture( + gboolean result = fl_texture_registrar_populate_gl_external_texture( self->texture_registrar, texture_id, width, height, texture, &error); if (!result) { g_warning("%s", error->message); diff --git a/shell/platform/linux/fl_pixel_buffer_texture.cc b/shell/platform/linux/fl_pixel_buffer_texture.cc index dafc654374c9a..a4ee86f7c16f2 100644 --- a/shell/platform/linux/fl_pixel_buffer_texture.cc +++ b/shell/platform/linux/fl_pixel_buffer_texture.cc @@ -6,16 +6,8 @@ #include #include -#include -#define GL_CALL(expr) \ - do { \ - expr; \ - GLenum err = glGetError(); \ - if (err) { \ - fprintf(stderr, "glGetError %x (%s:%d)\n", err, __FILE__, __LINE__); \ - } \ - } while (0); +#include "flutter/shell/platform/linux/fl_pixel_buffer_texture_private.h" typedef struct { GLuint texture_id; @@ -42,12 +34,18 @@ static void fl_pixel_buffer_texture_dispose(GObject* object) { G_OBJECT_CLASS(fl_pixel_buffer_texture_parent_class)->dispose(object); } -static gboolean fl_pixel_buffer_texture_populate(FlTexture* texture, - uint32_t* target, - uint32_t* name, - uint32_t* width, - uint32_t* height, - GError** error) { +static void check_gl_error(int line) { + GLenum err = glGetError(); + if (err) { + g_warning("glGetError %x (%s:%d)\n", err, __FILE__, __LINE__); + } +} + +gboolean fl_pixel_buffer_texture_populate(FlPixelBufferTexture* texture, + uint32_t width, + uint32_t height, + FlutterOpenGLTexture* opengl_texture, + GError** error) { FlPixelBufferTexture* self = FL_PIXEL_BUFFER_TEXTURE(texture); FlPixelBufferTexturePrivate* priv = reinterpret_cast( @@ -56,32 +54,44 @@ static gboolean fl_pixel_buffer_texture_populate(FlTexture* texture, uint32_t format = 0; const uint8_t* buffer = nullptr; if (!FL_PIXEL_BUFFER_TEXTURE_GET_CLASS(self)->copy_pixels( - self, &buffer, &format, width, height, error)) { + self, &buffer, &format, &width, &height, error)) { return FALSE; } + if (priv->texture_id == 0) { - GL_CALL(glGenTextures(1, &priv->texture_id)); - GL_CALL(glBindTexture(GL_TEXTURE_2D, priv->texture_id)); - GL_CALL( - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)); - GL_CALL( - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)); - GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + glGenTextures(1, &priv->texture_id); + check_gl_error(__LINE__); + glBindTexture(GL_TEXTURE_2D, priv->texture_id); + check_gl_error(__LINE__); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + check_gl_error(__LINE__); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + check_gl_error(__LINE__); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + check_gl_error(__LINE__); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + check_gl_error(__LINE__); } else { - GL_CALL(glBindTexture(GL_TEXTURE_2D, priv->texture_id)); + glBindTexture(GL_TEXTURE_2D, priv->texture_id); + check_gl_error(__LINE__); } - *target = GL_TEXTURE_2D; - *name = priv->texture_id; - GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, *width, *height, 0, format, - GL_UNSIGNED_BYTE, buffer)); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, format, + GL_UNSIGNED_BYTE, buffer); + check_gl_error(__LINE__); + + opengl_texture->target = GL_TEXTURE_2D; + opengl_texture->name = priv->texture_id; + opengl_texture->format = GL_RGBA8; + opengl_texture->destruction_callback = nullptr; + opengl_texture->user_data = nullptr; + opengl_texture->width = width; + opengl_texture->height = height; + return TRUE; } static void fl_pixel_buffer_texture_class_init( FlPixelBufferTextureClass* klass) { - FL_TEXTURE_CLASS(klass)->populate = fl_pixel_buffer_texture_populate; - G_OBJECT_CLASS(klass)->dispose = fl_pixel_buffer_texture_dispose; } diff --git a/shell/platform/linux/fl_pixel_buffer_texture_private.h b/shell/platform/linux/fl_pixel_buffer_texture_private.h new file mode 100644 index 0000000000000..bea9d60472962 --- /dev/null +++ b/shell/platform/linux/fl_pixel_buffer_texture_private.h @@ -0,0 +1,36 @@ +// 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_PIXEL_BUFFER_TEXTURE_PRIVATE_H_ +#define FLUTTER_SHELL_PLATFORM_LINUX_FL_PIXEL_BUFFER_TEXTURE_PRIVATE_H_ + +#include "flutter/shell/platform/embedder/embedder.h" +#include "flutter/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h" +#include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h" + +G_BEGIN_DECLS + +/** + * fl_pixel_buffer_texture_populate: + * @texture: an #FlPixelBufferTexture. + * @width: width of the texture. + * @height: height of the texture. + * @opengl_texture: (out): return an #FlutterOpenGLTexture. + * @error: (allow-none): #GError location to store the error occurring, or + * %NULL to ignore. + * + * Attempts to populate the specified @opengl_texture with texture details + * such as the name, width, height and the pixel format. + * + * Returns: %TRUE on success. + */ +gboolean fl_pixel_buffer_texture_populate(FlPixelBufferTexture* texture, + uint32_t width, + uint32_t height, + FlutterOpenGLTexture* opengl_texture, + GError** error); + +G_END_DECLS + +#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_PIXEL_BUFFER_TEXTURE_PRIVATE_H_ diff --git a/shell/platform/linux/fl_pixel_buffer_texture_test.cc b/shell/platform/linux/fl_pixel_buffer_texture_test.cc index 2da689ac6e159..79796a3605fdc 100644 --- a/shell/platform/linux/fl_pixel_buffer_texture_test.cc +++ b/shell/platform/linux/fl_pixel_buffer_texture_test.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "flutter/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h" +#include "flutter/shell/platform/linux/fl_pixel_buffer_texture_private.h" #include "flutter/shell/platform/linux/fl_texture_private.h" #include "flutter/shell/platform/linux/fl_texture_registrar_private.h" #include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h" @@ -74,11 +75,12 @@ TEST(FlPixelBufferTextureTest, TextureID) { // Test that populating an OpenGL texture works. TEST(FlPixelBufferTextureTest, PopulateTexture) { - g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_pixel_buffer_texture_new()); + g_autoptr(FlPixelBufferTexture) texture = + FL_PIXEL_BUFFER_TEXTURE(fl_test_pixel_buffer_texture_new()); FlutterOpenGLTexture opengl_texture = {0}; g_autoptr(GError) error = nullptr; - EXPECT_TRUE(fl_texture_populate(texture, BUFFER_WIDTH, BUFFER_HEIGHT, - &opengl_texture, &error)); + EXPECT_TRUE(fl_pixel_buffer_texture_populate( + texture, BUFFER_WIDTH, BUFFER_HEIGHT, &opengl_texture, &error)); EXPECT_EQ(error, nullptr); EXPECT_EQ(opengl_texture.width, REAL_BUFFER_WIDTH); EXPECT_EQ(opengl_texture.height, REAL_BUFFER_HEIGHT); diff --git a/shell/platform/linux/fl_texture.cc b/shell/platform/linux/fl_texture.cc index f371e9b9dc664..bd8b68a6bfd65 100644 --- a/shell/platform/linux/fl_texture.cc +++ b/shell/platform/linux/fl_texture.cc @@ -5,7 +5,6 @@ #include "flutter/shell/platform/linux/public/flutter_linux/fl_texture.h" #include "flutter/shell/platform/linux/fl_texture_private.h" -#include #include #include @@ -18,28 +17,6 @@ static void fl_texture_class_init(FlTextureClass* klass) {} static void fl_texture_init(FlTexture* self) {} -gboolean fl_texture_populate(FlTexture* self, - uint32_t width, - uint32_t height, - FlutterOpenGLTexture* opengl_texture, - GError** error) { - uint32_t target = 0, name = 0; - if (!FL_TEXTURE_GET_CLASS(self)->populate(self, &target, &name, &width, - &height, error)) { - return FALSE; - } - - opengl_texture->target = target; - opengl_texture->name = name; - opengl_texture->format = GL_RGBA8; - opengl_texture->destruction_callback = nullptr; - opengl_texture->user_data = nullptr; - opengl_texture->width = width; - opengl_texture->height = height; - - return TRUE; -} - int64_t fl_texture_get_texture_id(FlTexture* self) { g_return_val_if_fail(FL_IS_TEXTURE(self), -1); return reinterpret_cast(self); diff --git a/shell/platform/linux/fl_texture_gl.cc b/shell/platform/linux/fl_texture_gl.cc new file mode 100644 index 0000000000000..2099d7300baa1 --- /dev/null +++ b/shell/platform/linux/fl_texture_gl.cc @@ -0,0 +1,41 @@ +// 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/public/flutter_linux/fl_texture_gl.h" +#include "flutter/shell/platform/linux/fl_texture_gl_private.h" + +#include +#include +#include + +// Added here to stop the compiler from optimising this function away. +G_MODULE_EXPORT GType fl_texture_gl_get_type(); + +G_DEFINE_TYPE(FlTextureGL, fl_texture_gl, fl_texture_get_type()) + +static void fl_texture_gl_class_init(FlTextureGLClass* klass) {} + +static void fl_texture_gl_init(FlTextureGL* self) {} + +gboolean fl_texture_gl_populate(FlTextureGL* self, + uint32_t width, + uint32_t height, + FlutterOpenGLTexture* opengl_texture, + GError** error) { + uint32_t target = 0, name = 0; + if (!FL_TEXTURE_GL_GET_CLASS(self)->populate(self, &target, &name, &width, + &height, error)) { + return FALSE; + } + + opengl_texture->target = target; + opengl_texture->name = name; + opengl_texture->format = GL_RGBA8; + opengl_texture->destruction_callback = nullptr; + opengl_texture->user_data = nullptr; + opengl_texture->width = width; + opengl_texture->height = height; + + return TRUE; +} diff --git a/shell/platform/linux/fl_texture_gl_private.h b/shell/platform/linux/fl_texture_gl_private.h new file mode 100644 index 0000000000000..42ac7fcda91a2 --- /dev/null +++ b/shell/platform/linux/fl_texture_gl_private.h @@ -0,0 +1,36 @@ +// 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_TEXTURE_GL_PRIVATE_H_ +#define FLUTTER_SHELL_PLATFORM_LINUX_FL_TEXTURE_GL_PRIVATE_H_ + +#include "flutter/shell/platform/embedder/embedder.h" +#include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_gl.h" +#include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h" + +G_BEGIN_DECLS + +/** + * fl_texture_gl_populate: + * @texture: an #FlTextureGL. + * @width: width of the texture. + * @height: height of the texture. + * @opengl_texture: (out): return an #FlutterOpenGLTexture. + * @error: (allow-none): #GError location to store the error occurring, or + * %NULL to ignore. + * + * Attempts to populate the specified @opengl_texture with texture details + * such as the name, width, height and the pixel format. + * + * Returns: %TRUE on success. + */ +gboolean fl_texture_gl_populate(FlTextureGL* texture, + uint32_t width, + uint32_t height, + FlutterOpenGLTexture* opengl_texture, + GError** error); + +G_END_DECLS + +#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_TEXTURE_GL_PRIVATE_H_ diff --git a/shell/platform/linux/fl_texture_test.cc b/shell/platform/linux/fl_texture_gl_test.cc similarity index 83% rename from shell/platform/linux/fl_texture_test.cc rename to shell/platform/linux/fl_texture_gl_test.cc index 9a4d2341bc95f..18d3507986547 100644 --- a/shell/platform/linux/fl_texture_test.cc +++ b/shell/platform/linux/fl_texture_gl_test.cc @@ -2,9 +2,10 @@ // 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/public/flutter_linux/fl_texture.h" +#include "flutter/shell/platform/linux/fl_texture_gl_private.h" #include "flutter/shell/platform/linux/fl_texture_private.h" #include "flutter/shell/platform/linux/fl_texture_registrar_private.h" +#include "flutter/shell/platform/linux/public/flutter_linux/fl_texture.h" #include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h" #include "flutter/shell/platform/linux/testing/fl_test.h" #include "gtest/gtest.h" @@ -20,16 +21,16 @@ G_DECLARE_FINAL_TYPE(FlTestTexture, fl_test_texture, FL, TEST_TEXTURE, - FlTexture) + FlTextureGL) /// A simple texture. struct _FlTestTexture { - FlTexture parent_instance; + FlTextureGL parent_instance; }; G_DEFINE_TYPE(FlTestTexture, fl_test_texture, fl_texture_get_type()) -static gboolean fl_test_texture_populate(FlTexture* texture, +static gboolean fl_test_texture_populate(FlTextureGL* texture, uint32_t* target, uint32_t* format, uint32_t* width, @@ -48,7 +49,7 @@ static gboolean fl_test_texture_populate(FlTexture* texture, } static void fl_test_texture_class_init(FlTestTextureClass* klass) { - FL_TEXTURE_CLASS(klass)->populate = fl_test_texture_populate; + FL_TEXTURE_GL_CLASS(klass)->populate = fl_test_texture_populate; } static void fl_test_texture_init(FlTestTexture* self) {} @@ -67,11 +68,11 @@ TEST(FlTextureTest, TextureID) { // Test that populating an OpenGL texture works. TEST(FlTextureTest, PopulateTexture) { - g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_texture_new()); + g_autoptr(FlTextureGL) texture = FL_TEXTURE_GL(fl_test_texture_new()); FlutterOpenGLTexture opengl_texture = {0}; g_autoptr(GError) error = nullptr; - EXPECT_TRUE(fl_texture_populate(texture, BUFFER_WIDTH, BUFFER_HEIGHT, - &opengl_texture, &error)); + EXPECT_TRUE(fl_texture_gl_populate(texture, BUFFER_WIDTH, BUFFER_HEIGHT, + &opengl_texture, &error)); EXPECT_EQ(error, nullptr); EXPECT_EQ(opengl_texture.width, REAL_BUFFER_WIDTH); EXPECT_EQ(opengl_texture.height, REAL_BUFFER_HEIGHT); diff --git a/shell/platform/linux/fl_texture_private.h b/shell/platform/linux/fl_texture_private.h index 25127c9a3e85c..0bf304eb524d7 100644 --- a/shell/platform/linux/fl_texture_private.h +++ b/shell/platform/linux/fl_texture_private.h @@ -6,30 +6,10 @@ #define FLUTTER_SHELL_PLATFORM_LINUX_FL_TEXTURE_PRIVATE_H_ #include "flutter/shell/platform/embedder/embedder.h" -#include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h" +#include "flutter/shell/platform/linux/public/flutter_linux/fl_texture.h" G_BEGIN_DECLS -/** - * fl_texture_populate: - * @texture: an #FlTexture. - * @width: width of the texture. - * @height: height of the texture. - * @opengl_texture: (out): return an #FlutterOpenGLTexture. - * @error: (allow-none): #GError location to store the error occurring, or - * %NULL to ignore. - * - * Attempts to populate the specified @opengl_texture with texture details - * such as the name, width, height and the pixel format. - * - * Returns: %TRUE on success. - */ -gboolean fl_texture_populate(FlTexture* texture, - uint32_t width, - uint32_t height, - FlutterOpenGLTexture* opengl_texture, - GError** error); - /** * fl_texture_get_texture_id: * @texture: an #FlTexture. diff --git a/shell/platform/linux/fl_texture_registrar.cc b/shell/platform/linux/fl_texture_registrar.cc index 03864d7170a43..339e7ef91b5da 100644 --- a/shell/platform/linux/fl_texture_registrar.cc +++ b/shell/platform/linux/fl_texture_registrar.cc @@ -8,6 +8,8 @@ #include "flutter/shell/platform/embedder/embedder.h" #include "flutter/shell/platform/linux/fl_engine_private.h" +#include "flutter/shell/platform/linux/fl_pixel_buffer_texture_private.h" +#include "flutter/shell/platform/linux/fl_texture_gl_private.h" #include "flutter/shell/platform/linux/fl_texture_private.h" #include "flutter/shell/platform/linux/fl_texture_registrar_private.h" @@ -61,16 +63,21 @@ fl_texture_registrar_register_texture(FlTextureRegistrar* self, g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), 0); g_return_val_if_fail(FL_IS_TEXTURE(texture), 0); - int64_t id = fl_texture_get_texture_id(texture); - g_hash_table_insert(self->textures, GINT_TO_POINTER(id), - g_object_ref(texture)); + if (FL_IS_TEXTURE_GL(texture) || FL_IS_PIXEL_BUFFER_TEXTURE(texture)) { + int64_t id = fl_texture_get_texture_id(texture); + g_hash_table_insert(self->textures, GINT_TO_POINTER(id), + g_object_ref(texture)); - if (self->engine == nullptr) { + if (self->engine == nullptr) { + return id; + } + + fl_engine_register_external_texture(self->engine, id); return id; + } else { + // We currently only support #FlTextureGL and #FlPixelBufferTexture. + return 0; } - - fl_engine_register_external_texture(self->engine, id); - return id; } G_MODULE_EXPORT void fl_texture_registrar_mark_texture_frame_available( @@ -85,7 +92,7 @@ G_MODULE_EXPORT void fl_texture_registrar_mark_texture_frame_available( fl_engine_mark_texture_frame_available(self->engine, texture_id); } -gboolean fl_texture_registrar_populate_texture( +gboolean fl_texture_registrar_populate_gl_external_texture( FlTextureRegistrar* self, int64_t texture_id, uint32_t width, @@ -99,7 +106,17 @@ gboolean fl_texture_registrar_populate_texture( "Unable to find texture %" G_GINT64_FORMAT, texture_id); return FALSE; } - return fl_texture_populate(texture, width, height, opengl_texture, error); + if (FL_IS_TEXTURE_GL(texture)) { + return fl_texture_gl_populate(FL_TEXTURE_GL(texture), width, height, + opengl_texture, error); + } else if (FL_IS_PIXEL_BUFFER_TEXTURE(texture)) { + return fl_pixel_buffer_texture_populate( + FL_PIXEL_BUFFER_TEXTURE(texture), width, height, opengl_texture, error); + } else { + g_set_error(error, fl_engine_error_quark(), FL_ENGINE_ERROR_FAILED, + "Unsupported texture type %" G_GINT64_FORMAT, texture_id); + return FALSE; + } } G_MODULE_EXPORT void fl_texture_registrar_unregister_texture( diff --git a/shell/platform/linux/fl_texture_registrar_private.h b/shell/platform/linux/fl_texture_registrar_private.h index 954215ef9761a..b4ea9b2119219 100644 --- a/shell/platform/linux/fl_texture_registrar_private.h +++ b/shell/platform/linux/fl_texture_registrar_private.h @@ -22,7 +22,7 @@ G_BEGIN_DECLS FlTextureRegistrar* fl_texture_registrar_new(FlEngine* engine); /** - * fl_texture_registrar_populate_texture: + * fl_texture_registrar_populate_gl_external_texture: * @registrar: an #FlTextureRegistrar. * @texture_id: ID of texture. * @width: width of the texture. @@ -35,7 +35,7 @@ FlTextureRegistrar* fl_texture_registrar_new(FlEngine* engine); * * Returns: %TRUE on success. */ -gboolean fl_texture_registrar_populate_texture( +gboolean fl_texture_registrar_populate_gl_external_texture( FlTextureRegistrar* registrar, int64_t texture_id, uint32_t width, diff --git a/shell/platform/linux/fl_texture_registrar_test.cc b/shell/platform/linux/fl_texture_registrar_test.cc index a03f4ff41b328..05c02b938ec1f 100644 --- a/shell/platform/linux/fl_texture_registrar_test.cc +++ b/shell/platform/linux/fl_texture_registrar_test.cc @@ -5,6 +5,7 @@ #include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h" #include "flutter/shell/platform/linux/fl_texture_registrar_private.h" #include "flutter/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h" +#include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_gl.h" #include "flutter/shell/platform/linux/testing/fl_test.h" #include "gtest/gtest.h" @@ -21,18 +22,18 @@ G_DECLARE_FINAL_TYPE(FlTestRegistrarTexture, fl_test_registrar_texture, FL, TEST_REGISTRAR_TEXTURE, - FlTexture) + FlTextureGL) /// A simple texture. struct _FlTestRegistrarTexture { - FlTexture parent_instance; + FlTextureGL parent_instance; }; G_DEFINE_TYPE(FlTestRegistrarTexture, fl_test_registrar_texture, - fl_texture_get_type()) + fl_texture_gl_get_type()) -static gboolean fl_test_registrar_texture_populate(FlTexture* texture, +static gboolean fl_test_registrar_texture_populate(FlTextureGL* texture, uint32_t* target, uint32_t* format, uint32_t* width, @@ -52,7 +53,7 @@ static gboolean fl_test_registrar_texture_populate(FlTexture* texture, static void fl_test_registrar_texture_class_init( FlTestRegistrarTextureClass* klass) { - FL_TEXTURE_CLASS(klass)->populate = fl_test_registrar_texture_populate; + FL_TEXTURE_GL_CLASS(klass)->populate = fl_test_registrar_texture_populate; } static void fl_test_registrar_texture_init(FlTestRegistrarTexture* self) {} @@ -93,7 +94,7 @@ TEST(FlTextureRegistrarTest, PopulateTexture) { int64_t id = fl_texture_registrar_register_texture(registrar, texture); FlutterOpenGLTexture opengl_texture; g_autoptr(GError) error = nullptr; - EXPECT_TRUE(fl_texture_registrar_populate_texture( + EXPECT_TRUE(fl_texture_registrar_populate_gl_external_texture( registrar, id, BUFFER_WIDTH, BUFFER_HEIGHT, &opengl_texture, &error)); EXPECT_EQ(error, nullptr); EXPECT_EQ(opengl_texture.width, REAL_BUFFER_WIDTH); diff --git a/shell/platform/linux/public/flutter_linux/fl_texture.h b/shell/platform/linux/public/flutter_linux/fl_texture.h index 46138124608cc..82f5d668f7d49 100644 --- a/shell/platform/linux/public/flutter_linux/fl_texture.h +++ b/shell/platform/linux/public/flutter_linux/fl_texture.h @@ -19,35 +19,15 @@ G_DECLARE_DERIVABLE_TYPE(FlTexture, fl_texture, FL, TEXTURE, GObject) /** * FlTexture: * - * #FlTexture is an abstract class that represents an OpenGL texture. + * #FlTexture is an abstract class that represents a texture. * - * If you want to render textures in other OpenGL context, create and use the - * #GdkGLContext by calling gdk_window_create_gl_context () with the #GdkWindow - * of #FlView. The context will be shared with the one used by Flutter. + * You can derive #FlTextureGL for populating hardware-accelerated textures or + * instantiate #FlPixelBufferTexture for populating pixel buffers. Do NOT + * directly derive this class. */ struct _FlTextureClass { GObjectClass parent_class; - - /** - * Virtual method called when Flutter populates this texture. The OpenGL - * context used by Flutter has been already set. - * @texture: an #FlTexture. - * @target: texture target (example GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE). - * @name: (out): name of texture. - * @width: (inout): width of the texture in pixels. - * @height: (inout): height of the texture in pixels. - * @error: (allow-none): #GError location to store the error occurring, or - * %NULL to ignore. - * - * Returns: %TRUE on success. - */ - gboolean (*populate)(FlTexture* texture, - uint32_t* target, - uint32_t* name, - uint32_t* width, - uint32_t* height, - GError** error); }; G_END_DECLS diff --git a/shell/platform/linux/public/flutter_linux/fl_texture_gl.h b/shell/platform/linux/public/flutter_linux/fl_texture_gl.h new file mode 100644 index 0000000000000..87f59f8079a20 --- /dev/null +++ b/shell/platform/linux/public/flutter_linux/fl_texture_gl.h @@ -0,0 +1,56 @@ +// 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_TEXTURE_GL_H_ +#define FLUTTER_SHELL_PLATFORM_LINUX_FL_TEXTURE_GL_H_ + +#if !defined(__FLUTTER_LINUX_INSIDE__) && !defined(FLUTTER_LINUX_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include +#include "fl_texture.h" + +G_BEGIN_DECLS + +G_DECLARE_DERIVABLE_TYPE(FlTextureGL, fl_texture_gl, FL, TEXTURE_GL, FlTexture) + +/** + * FlTextureGL: + * + * #FlTextureGL is an abstract class that represents an OpenGL texture. + * + * If you want to render textures in other OpenGL context, create and use the + * #GdkGLContext by calling gdk_window_create_gl_context () with the #GdkWindow + * of #FlView. The context will be shared with the one used by Flutter. + */ + +struct _FlTextureGLClass { + FlTextureClass parent_class; + + /** + * Virtual method called when Flutter populates this texture. The OpenGL + * context used by Flutter has been already set. + * @texture: an #FlTexture. + * @target: texture target (example GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE). + * @name: (out): name of texture. + * @width: (inout): width of the texture in pixels. + * @height: (inout): height of the texture in pixels. + * @error: (allow-none): #GError location to store the error occurring, or + * %NULL to ignore. + * + * Returns: %TRUE on success. + */ + gboolean (*populate)(FlTextureGL* texture, + uint32_t* target, + uint32_t* name, + uint32_t* width, + uint32_t* height, + GError** error); +}; + +G_END_DECLS + +#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_TEXTURE_H_ From 3fbd0c38df2f50318108f66e19d37faa77f6dafe Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Fri, 20 Aug 2021 15:05:38 +0800 Subject: [PATCH 16/20] Fix: It should be assumed that the format of pixel buffer is RGBA. --- shell/platform/linux/fl_pixel_buffer_texture.cc | 7 +++---- shell/platform/linux/fl_pixel_buffer_texture_test.cc | 7 ++++--- .../public/flutter_linux/fl_pixel_buffer_texture.h | 11 +++++++---- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/shell/platform/linux/fl_pixel_buffer_texture.cc b/shell/platform/linux/fl_pixel_buffer_texture.cc index a4ee86f7c16f2..bd2b8230398c5 100644 --- a/shell/platform/linux/fl_pixel_buffer_texture.cc +++ b/shell/platform/linux/fl_pixel_buffer_texture.cc @@ -37,7 +37,7 @@ static void fl_pixel_buffer_texture_dispose(GObject* object) { static void check_gl_error(int line) { GLenum err = glGetError(); if (err) { - g_warning("glGetError %x (%s:%d)\n", err, __FILE__, __LINE__); + g_warning("glGetError %x (%s:%d)\n", err, __FILE__, line); } } @@ -51,10 +51,9 @@ gboolean fl_pixel_buffer_texture_populate(FlPixelBufferTexture* texture, reinterpret_cast( fl_pixel_buffer_texture_get_instance_private(self)); - uint32_t format = 0; const uint8_t* buffer = nullptr; if (!FL_PIXEL_BUFFER_TEXTURE_GET_CLASS(self)->copy_pixels( - self, &buffer, &format, &width, &height, error)) { + self, &buffer, &width, &height, error)) { return FALSE; } @@ -75,7 +74,7 @@ gboolean fl_pixel_buffer_texture_populate(FlPixelBufferTexture* texture, glBindTexture(GL_TEXTURE_2D, priv->texture_id); check_gl_error(__LINE__); } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, format, + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); check_gl_error(__LINE__); diff --git a/shell/platform/linux/fl_pixel_buffer_texture_test.cc b/shell/platform/linux/fl_pixel_buffer_texture_test.cc index 79796a3605fdc..ff844f65a233e 100644 --- a/shell/platform/linux/fl_pixel_buffer_texture_test.cc +++ b/shell/platform/linux/fl_pixel_buffer_texture_test.cc @@ -35,17 +35,18 @@ G_DEFINE_TYPE(FlTestPixelBufferTexture, static gboolean fl_test_pixel_buffer_texture_copy_pixels( FlPixelBufferTexture* texture, const uint8_t** out_buffer, - uint32_t* format, uint32_t* width, uint32_t* height, GError** error) { EXPECT_TRUE(FL_IS_TEST_PIXEL_BUFFER_TEXTURE(texture)); - static const uint8_t buffer[] = {0x7a, 0x8a, 0x9a, 0xaa}; + // RGBA + static const uint8_t buffer[] = {0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a, + 0x6a, 0x7a, 0x8a, 0x9a, 0xaa, 0xba, + 0xca, 0xda, 0xea, 0xfa}; EXPECT_EQ(*width, BUFFER_WIDTH); EXPECT_EQ(*height, BUFFER_HEIGHT); *out_buffer = buffer; - *format = GL_R8; *width = REAL_BUFFER_WIDTH; *height = REAL_BUFFER_HEIGHT; diff --git a/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h b/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h index e0ddb8fd87a87..cbf387d82f670 100644 --- a/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h +++ b/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h @@ -23,21 +23,24 @@ struct _FlPixelBufferTextureClass { FlTextureClass parent_class; /** - * Virtual method called when Flutter wants to copy pixel buffer for - * populating this texture. + * FlPixelBufferTexture::copy_pixels: * @texture: an #FlPixelBufferTexture. * @buffer: (out): pixel data. - * @format: (out): pixel buffer format (example GL_RGBA). * @width: (inout): width of the texture in pixels. * @height: (inout): height of the texture in pixels. * @error: (allow-none): #GError location to store the error occurring, or * %NULL to ignore. * + * Retrieve pixel buffer in RGBA format. + * + * As this method is usually invoked from the render thread, you must + * take care of proper synchronization. It also needs to be ensured that + * the returned buffer is not released prior to unregistering this texture. + * * Returns: %TRUE on success. */ gboolean (*copy_pixels)(FlPixelBufferTexture* texture, const uint8_t** buffer, - uint32_t* format, uint32_t* width, uint32_t* height, GError** error); From d0923e78eb59a8b71313ceea3dbfa363b5cc54be Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 23 Aug 2021 17:34:16 +0800 Subject: [PATCH 17/20] Include fl_texture_gl.h --- shell/platform/linux/public/flutter_linux/flutter_linux.h | 1 + 1 file changed, 1 insertion(+) diff --git a/shell/platform/linux/public/flutter_linux/flutter_linux.h b/shell/platform/linux/public/flutter_linux/flutter_linux.h index 550474887e547..2d9317ddf5342 100644 --- a/shell/platform/linux/public/flutter_linux/flutter_linux.h +++ b/shell/platform/linux/public/flutter_linux/flutter_linux.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include From 9ed4178a4a2d152e3c35d9e6f153f9334aeff723 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 6 Sep 2021 17:25:18 +0800 Subject: [PATCH 18/20] Add more detailed documentation --- shell/platform/linux/fl_texture_gl_test.cc | 4 +- .../flutter_linux/fl_pixel_buffer_texture.h | 63 ++++++++++++++++--- .../public/flutter_linux/fl_texture_gl.h | 47 ++++++++++++++ .../flutter_linux/fl_texture_registrar.h | 5 ++ 4 files changed, 110 insertions(+), 9 deletions(-) diff --git a/shell/platform/linux/fl_texture_gl_test.cc b/shell/platform/linux/fl_texture_gl_test.cc index 18d3507986547..2ac7e181b3996 100644 --- a/shell/platform/linux/fl_texture_gl_test.cc +++ b/shell/platform/linux/fl_texture_gl_test.cc @@ -32,7 +32,7 @@ G_DEFINE_TYPE(FlTestTexture, fl_test_texture, fl_texture_get_type()) static gboolean fl_test_texture_populate(FlTextureGL* texture, uint32_t* target, - uint32_t* format, + uint32_t* name, uint32_t* width, uint32_t* height, GError** error) { @@ -41,7 +41,7 @@ static gboolean fl_test_texture_populate(FlTextureGL* texture, EXPECT_EQ(*width, BUFFER_WIDTH); EXPECT_EQ(*height, BUFFER_HEIGHT); *target = GL_TEXTURE_2D; - *format = GL_R8; + *name = 1; *width = REAL_BUFFER_WIDTH; *height = REAL_BUFFER_HEIGHT; diff --git a/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h b/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h index cbf387d82f670..a6c490d41c9d9 100644 --- a/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h +++ b/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h @@ -19,6 +19,62 @@ G_DECLARE_DERIVABLE_TYPE(FlPixelBufferTexture, PIXEL_BUFFER_TEXTURE, FlTexture) +/** + * FlPixelBufferTexture: + * + * #FlPixelBufferTexture represents an OpenGL texture generated from a pixel + * buffer. + * + * The following example shows how to implement an #FlPixelBufferTexture. + * ![ + * // Type definition, constructor, init, destructor and class_init are + * // omitted. + * struct _VideoPixelBufferTexture { // extends FlPixelBufferTexture + * FlPixelBufferTexture parent_instance; + * + * uint8_t *buffer; // your pixel buffer. + * } + * + * G_DEFINE_TYPE(VideoTexture, + * video_texture, + * fl_pixel_buffer_texture_get_type ()) + * + * static gboolean + * video_texture_copy_pixels (FlPixelBufferTexture* texture, + * const uint8_t** out_buffer, + * uint32_t* width, + * uint32_t* height, + * GError** error) { + * // This method is called on Render Thread. Be careful with your + * // cross-thread operation. + * + * // @width and @height are initially stored the canvas size in Flutter. + * + * // You must prepare your pixel buffer in RGBA format. + * // So you may do some format conversion first if your original pixel + * // buffer is not in RGBA format. + * manage_your_pixel_buffer_here (); + * + * if (your_operations_are_successfully_finished) { + * // Directly return pointer to your pixel buffer here. + * // Flutter takes content of your pixel buffer after this function + * // is finished. So you must make the buffer live long enough until + * // next tick of Render Thread. + * // If it is hard to manage lifetime of your pixel buffer, you should + * // take look into #FlTextureGL. + * + * *out_buffer = buffer; + * *width = real_width_of_buffer; + * *height = real_height_of_buffer; + * return TRUE; + * } else { + * // set @error to report failure. + * return FALSE; + * } + * } + * ]| + */ + struct _FlPixelBufferTextureClass { FlTextureClass parent_class; @@ -46,13 +102,6 @@ struct _FlPixelBufferTextureClass { GError** error); }; -/** - * FlPixelBufferTexture: - * - * #FlPixelBufferTexture represents an OpenGL texture generated from a pixel - * buffer. - */ - G_END_DECLS #endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_PIXEL_BUFFER_TEXTURE_H_ diff --git a/shell/platform/linux/public/flutter_linux/fl_texture_gl.h b/shell/platform/linux/public/flutter_linux/fl_texture_gl.h index 87f59f8079a20..6cf3260801f25 100644 --- a/shell/platform/linux/public/flutter_linux/fl_texture_gl.h +++ b/shell/platform/linux/public/flutter_linux/fl_texture_gl.h @@ -25,6 +25,53 @@ G_DECLARE_DERIVABLE_TYPE(FlTextureGL, fl_texture_gl, FL, TEXTURE_GL, FlTexture) * If you want to render textures in other OpenGL context, create and use the * #GdkGLContext by calling gdk_window_create_gl_context () with the #GdkWindow * of #FlView. The context will be shared with the one used by Flutter. + * + * The following example shows how to implement an #FlTextureGL. + * ![ + * #include + * + * // Type definition, constructor, init, destructor, and class_init are + * // omitted. + * struct _VideoTextureGL { // extends FlTextureGL + * FlTextureGL parent_instance; + * + * GLuint texture_id; + * }; + * + * G_DEFINE_TYPE(VideoTexture, + * video_texture, + * fl_texture_gl_get_type ()) + * + * static gboolean + * video_texture_populate (FlTextureGL *texture, + * uint32_t *target, + * uint32_t *name, + * uint32_t *width, + * uint32_t *height, + * GError **error) { + * VideoTextureGL *self = VIDEO_TEXTURE_GL (texture); + * if (self->texture_id == 0) { + * glGenTextures (1, &self->texture_id); + * glBindTexture (GL_TEXTURE_2D, self->texture_id); + * // further configuration here. + * } else { + * glBindTexture (GL_TEXTURE_2D, self->texture_id); + * } + * + * // For example, we render pixel buffer here. + * // Note that Flutter only accepts textures in GL_RGBA8 format. + * static char buffer[] = { 0x1f, 0x2f, 0x3f, 0x4f }; // 1x1 pixel. + * glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, + * GL_UNSIGNED_BYTE, buffer); + * + * *target = GL_TEXTURE_2D; + * *name = self->texture_id; + * *width = 1; + * *height = 1; + * + * return TRUE; + * } + * ]| */ struct _FlTextureGLClass { diff --git a/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h b/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h index 957532cf28ccb..3e0fe42236c2c 100644 --- a/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h +++ b/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h @@ -26,6 +26,11 @@ G_DECLARE_FINAL_TYPE(FlTextureRegistrar, * FlTextureRegistrar: * * #FlTextureRegistrar is used when registering textures. + * + * Flutter Framework accesses your texture by the related unique texture ID. To + * draw your texture in Dart, you should add Texture widget in your widget tree + * with the same texture ID. Use platform channels to send this unique texture + * ID to the Dart side. */ /** From e8016521db69ed19dcd0f7eed6eed4b3b008d8c4 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 13 Sep 2021 16:18:27 +0800 Subject: [PATCH 19/20] Remove concept of texture ID in the API. --- shell/platform/linux/fl_engine.cc | 8 ++- shell/platform/linux/fl_engine_private.h | 6 +- shell/platform/linux/fl_texture_gl_test.cc | 2 +- shell/platform/linux/fl_texture_registrar.cc | 67 ++++++++++++------- .../linux/fl_texture_registrar_test.cc | 23 ++++--- .../flutter_linux/fl_texture_registrar.h | 28 ++++---- 6 files changed, 80 insertions(+), 54 deletions(-) diff --git a/shell/platform/linux/fl_engine.cc b/shell/platform/linux/fl_engine.cc index b575e2c975437..05e3d084e3e9f 100644 --- a/shell/platform/linux/fl_engine.cc +++ b/shell/platform/linux/fl_engine.cc @@ -715,9 +715,11 @@ gboolean fl_engine_register_external_texture(FlEngine* self, kSuccess; } -void fl_engine_unregister_external_texture(FlEngine* self, int64_t texture_id) { - g_return_if_fail(FL_IS_ENGINE(self)); - self->embedder_api.UnregisterExternalTexture(self->engine, texture_id); +gboolean fl_engine_unregister_external_texture(FlEngine* self, + int64_t texture_id) { + g_return_val_if_fail(FL_IS_ENGINE(self), FALSE); + return self->embedder_api.UnregisterExternalTexture(self->engine, + texture_id) == kSuccess; } G_MODULE_EXPORT FlBinaryMessenger* fl_engine_get_binary_messenger( diff --git a/shell/platform/linux/fl_engine_private.h b/shell/platform/linux/fl_engine_private.h index 93fd5c1f033be..fdc35ac54b5c4 100644 --- a/shell/platform/linux/fl_engine_private.h +++ b/shell/platform/linux/fl_engine_private.h @@ -285,9 +285,11 @@ gboolean fl_engine_register_external_texture(FlEngine* engine, * * Tells the Flutter engine that an existing external texture is not available * anymore. + * + * Returns: %TRUE on success. */ -void fl_engine_unregister_external_texture(FlEngine* engine, - int64_t texture_id); +gboolean fl_engine_unregister_external_texture(FlEngine* engine, + int64_t texture_id); G_END_DECLS diff --git a/shell/platform/linux/fl_texture_gl_test.cc b/shell/platform/linux/fl_texture_gl_test.cc index 2ac7e181b3996..a1edc88b0ad63 100644 --- a/shell/platform/linux/fl_texture_gl_test.cc +++ b/shell/platform/linux/fl_texture_gl_test.cc @@ -28,7 +28,7 @@ struct _FlTestTexture { FlTextureGL parent_instance; }; -G_DEFINE_TYPE(FlTestTexture, fl_test_texture, fl_texture_get_type()) +G_DEFINE_TYPE(FlTestTexture, fl_test_texture, fl_texture_gl_get_type()) static gboolean fl_test_texture_populate(FlTextureGL* texture, uint32_t* target, diff --git a/shell/platform/linux/fl_texture_registrar.cc b/shell/platform/linux/fl_texture_registrar.cc index 339e7ef91b5da..70c6e59cbd198 100644 --- a/shell/platform/linux/fl_texture_registrar.cc +++ b/shell/platform/linux/fl_texture_registrar.cc @@ -16,8 +16,14 @@ struct _FlTextureRegistrar { GObject parent_instance; + // Weak reference to the engine this texture registrar is created for. FlEngine* engine; + // Internal record for registered textures. + // + // It is a map from Flutter texture ID to #FlTexture instance created by + // plugins. The keys are directly stored int64s. The values are stored + // pointer to #FlTexture. This table is freed by the responder. GHashTable* textures; }; @@ -57,39 +63,46 @@ static void fl_texture_registrar_init(FlTextureRegistrar* self) { g_object_unref); } -G_MODULE_EXPORT int64_t +G_MODULE_EXPORT gboolean fl_texture_registrar_register_texture(FlTextureRegistrar* self, FlTexture* texture) { - g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), 0); - g_return_val_if_fail(FL_IS_TEXTURE(texture), 0); + g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), FALSE); + g_return_val_if_fail(FL_IS_TEXTURE(texture), FALSE); if (FL_IS_TEXTURE_GL(texture) || FL_IS_PIXEL_BUFFER_TEXTURE(texture)) { - int64_t id = fl_texture_get_texture_id(texture); - g_hash_table_insert(self->textures, GINT_TO_POINTER(id), + g_hash_table_insert(self->textures, + GINT_TO_POINTER(fl_texture_get_texture_id(texture)), g_object_ref(texture)); if (self->engine == nullptr) { - return id; + return FALSE; } - fl_engine_register_external_texture(self->engine, id); - return id; + return fl_engine_register_external_texture( + self->engine, fl_texture_get_texture_id(texture)); } else { // We currently only support #FlTextureGL and #FlPixelBufferTexture. - return 0; + return FALSE; } } -G_MODULE_EXPORT void fl_texture_registrar_mark_texture_frame_available( - FlTextureRegistrar* self, - int64_t texture_id) { - g_return_if_fail(FL_IS_TEXTURE_REGISTRAR(self)); +G_MODULE_EXPORT gboolean +fl_texture_registrar_mark_texture_frame_available(FlTextureRegistrar* self, + FlTexture* texture) { + g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), FALSE); if (self->engine == nullptr) { - return; + return FALSE; } - fl_engine_mark_texture_frame_available(self->engine, texture_id); + if (fl_texture_registrar_get_texture( + self, fl_texture_get_texture_id(texture)) == nullptr) { + g_warning("Unregistered texture %p", texture); + return FALSE; + } + + return fl_engine_mark_texture_frame_available( + self->engine, fl_texture_get_texture_id(texture)); } gboolean fl_texture_registrar_populate_gl_external_texture( @@ -99,8 +112,7 @@ gboolean fl_texture_registrar_populate_gl_external_texture( uint32_t height, FlutterOpenGLTexture* opengl_texture, GError** error) { - FlTexture* texture = FL_TEXTURE( - g_hash_table_lookup(self->textures, GINT_TO_POINTER(texture_id))); + FlTexture* texture = fl_texture_registrar_get_texture(self, texture_id); if (texture == nullptr) { g_set_error(error, fl_engine_error_quark(), FL_ENGINE_ERROR_FAILED, "Unable to find texture %" G_GINT64_FORMAT, texture_id); @@ -119,21 +131,24 @@ gboolean fl_texture_registrar_populate_gl_external_texture( } } -G_MODULE_EXPORT void fl_texture_registrar_unregister_texture( - FlTextureRegistrar* self, - int64_t texture_id) { - g_return_if_fail(FL_IS_TEXTURE_REGISTRAR(self)); +G_MODULE_EXPORT gboolean +fl_texture_registrar_unregister_texture(FlTextureRegistrar* self, + FlTexture* texture) { + g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), FALSE); - if (!g_hash_table_remove(self->textures, GINT_TO_POINTER(texture_id))) { - g_warning("Unregistering a non-existent texture %ld", texture_id); - return; + if (!g_hash_table_remove( + self->textures, + GINT_TO_POINTER(fl_texture_get_texture_id(texture)))) { + g_warning("Unregistering a non-existent texture %p", texture); + return FALSE; } if (self->engine == nullptr) { - return; + return FALSE; } - fl_engine_unregister_external_texture(self->engine, texture_id); + return fl_engine_unregister_external_texture( + self->engine, fl_texture_get_texture_id(texture)); } FlTexture* fl_texture_registrar_get_texture(FlTextureRegistrar* registrar, diff --git a/shell/platform/linux/fl_texture_registrar_test.cc b/shell/platform/linux/fl_texture_registrar_test.cc index 05c02b938ec1f..6d9845ee59602 100644 --- a/shell/platform/linux/fl_texture_registrar_test.cc +++ b/shell/platform/linux/fl_texture_registrar_test.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h" +#include "flutter/shell/platform/linux/fl_texture_private.h" #include "flutter/shell/platform/linux/fl_texture_registrar_private.h" #include "flutter/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h" #include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_gl.h" @@ -68,13 +69,10 @@ TEST(FlTextureRegistrarTest, RegisterTexture) { g_autoptr(FlEngine) engine = make_mock_engine(); g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine); g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_registrar_texture_new()); - int64_t id = fl_texture_registrar_register_texture(registrar, texture); - EXPECT_EQ(fl_texture_registrar_get_texture(registrar, id), texture); - - fl_texture_registrar_unregister_texture(registrar, id); - - EXPECT_EQ(fl_texture_registrar_get_texture(registrar, id), nullptr); + EXPECT_FALSE(fl_texture_registrar_unregister_texture(registrar, texture)); + EXPECT_TRUE(fl_texture_registrar_register_texture(registrar, texture)); + EXPECT_TRUE(fl_texture_registrar_unregister_texture(registrar, texture)); } // Test that marking a texture frame available works. @@ -82,8 +80,12 @@ TEST(FlTextureRegistrarTest, MarkTextureFrameAvailable) { g_autoptr(FlEngine) engine = make_mock_engine(); g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine); g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_registrar_texture_new()); - int64_t id = fl_texture_registrar_register_texture(registrar, texture); - fl_texture_registrar_mark_texture_frame_available(registrar, id); + + EXPECT_FALSE( + fl_texture_registrar_mark_texture_frame_available(registrar, texture)); + EXPECT_TRUE(fl_texture_registrar_register_texture(registrar, texture)); + EXPECT_TRUE( + fl_texture_registrar_mark_texture_frame_available(registrar, texture)); } // Test that populating an OpenGL texture works. @@ -91,11 +93,12 @@ TEST(FlTextureRegistrarTest, PopulateTexture) { g_autoptr(FlEngine) engine = make_mock_engine(); g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine); g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_registrar_texture_new()); - int64_t id = fl_texture_registrar_register_texture(registrar, texture); + EXPECT_TRUE(fl_texture_registrar_register_texture(registrar, texture)); FlutterOpenGLTexture opengl_texture; g_autoptr(GError) error = nullptr; EXPECT_TRUE(fl_texture_registrar_populate_gl_external_texture( - registrar, id, BUFFER_WIDTH, BUFFER_HEIGHT, &opengl_texture, &error)); + registrar, fl_texture_get_texture_id(texture), BUFFER_WIDTH, + BUFFER_HEIGHT, &opengl_texture, &error)); EXPECT_EQ(error, nullptr); EXPECT_EQ(opengl_texture.width, REAL_BUFFER_WIDTH); EXPECT_EQ(opengl_texture.height, REAL_BUFFER_HEIGHT); diff --git a/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h b/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h index 3e0fe42236c2c..b978559a80b38 100644 --- a/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h +++ b/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h @@ -38,34 +38,38 @@ G_DECLARE_FINAL_TYPE(FlTextureRegistrar, * @registrar: an #FlTextureRegistrar. * @texture: an #FlTexture for registration. * - * Registers a texture and returns the unique ID for that texture. + * Registers a texture. * - * Returns: unique ID of the texture. + * Returns: %TRUE on success. */ -int64_t fl_texture_registrar_register_texture(FlTextureRegistrar* registrar, - FlTexture* texture); +gboolean fl_texture_registrar_register_texture(FlTextureRegistrar* registrar, + FlTexture* texture); /** * fl_texture_registrar_mark_texture_frame_available: * @registrar: an #FlTextureRegistrar. - * @texture_id: the ID of the texture that has a frame available. + * @texture: the texture that has a frame available. * - * Notifies the flutter engine that the texture object corresponding - * to texture_id needs to render a new texture. + * Notifies the flutter engine that the texture object has updated and needs to + * be rerendered. + * + * Returns: %TRUE on success. */ -void fl_texture_registrar_mark_texture_frame_available( +gboolean fl_texture_registrar_mark_texture_frame_available( FlTextureRegistrar* registrar, - int64_t texture_id); + FlTexture* texture); /** * fl_texture_registrar_unregister_texture: * @registrar: an #FlTextureRegistrar. - * @texture_id: the ID of the texture that is being unregistered. + * @texture: the texture being unregistered. * * Unregisters an existing texture object. + * + * Returns: %TRUE on success. */ -void fl_texture_registrar_unregister_texture(FlTextureRegistrar* registrar, - int64_t texture_id); +gboolean fl_texture_registrar_unregister_texture(FlTextureRegistrar* registrar, + FlTexture* texture); G_END_DECLS From 84184ae412eb35dafebc4920e603a163d286dc0f Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 13 Sep 2021 16:56:31 +0800 Subject: [PATCH 20/20] FlTexture should an interface --- shell/platform/linux/fl_pixel_buffer_texture.cc | 12 +++++++++--- shell/platform/linux/fl_texture.cc | 6 ++---- shell/platform/linux/fl_texture_gl.cc | 8 +++++++- .../public/flutter_linux/fl_pixel_buffer_texture.h | 4 ++-- .../platform/linux/public/flutter_linux/fl_texture.h | 10 +++++----- .../linux/public/flutter_linux/fl_texture_gl.h | 4 ++-- 6 files changed, 27 insertions(+), 17 deletions(-) diff --git a/shell/platform/linux/fl_pixel_buffer_texture.cc b/shell/platform/linux/fl_pixel_buffer_texture.cc index bd2b8230398c5..f0f75bef1146f 100644 --- a/shell/platform/linux/fl_pixel_buffer_texture.cc +++ b/shell/platform/linux/fl_pixel_buffer_texture.cc @@ -16,9 +16,15 @@ typedef struct { // Added here to stop the compiler from optimising this function away. G_MODULE_EXPORT GType fl_pixel_buffer_texture_get_type(); -G_DEFINE_TYPE_WITH_PRIVATE(FlPixelBufferTexture, - fl_pixel_buffer_texture, - fl_texture_get_type()) +static void fl_pixel_buffer_texture_iface_init(FlTextureInterface* iface) {} + +G_DEFINE_TYPE_WITH_CODE( + FlPixelBufferTexture, + fl_pixel_buffer_texture, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(fl_texture_get_type(), + fl_pixel_buffer_texture_iface_init); + G_ADD_PRIVATE(FlPixelBufferTexture)) static void fl_pixel_buffer_texture_dispose(GObject* object) { FlPixelBufferTexture* self = FL_PIXEL_BUFFER_TEXTURE(object); diff --git a/shell/platform/linux/fl_texture.cc b/shell/platform/linux/fl_texture.cc index bd8b68a6bfd65..ff26adc31bda3 100644 --- a/shell/platform/linux/fl_texture.cc +++ b/shell/platform/linux/fl_texture.cc @@ -11,11 +11,9 @@ // Added here to stop the compiler from optimising this function away. G_MODULE_EXPORT GType fl_texture_get_type(); -G_DEFINE_TYPE(FlTexture, fl_texture, G_TYPE_OBJECT) +G_DEFINE_INTERFACE(FlTexture, fl_texture, G_TYPE_OBJECT) -static void fl_texture_class_init(FlTextureClass* klass) {} - -static void fl_texture_init(FlTexture* self) {} +static void fl_texture_default_init(FlTextureInterface* self) {} int64_t fl_texture_get_texture_id(FlTexture* self) { g_return_val_if_fail(FL_IS_TEXTURE(self), -1); diff --git a/shell/platform/linux/fl_texture_gl.cc b/shell/platform/linux/fl_texture_gl.cc index 2099d7300baa1..c447ccc7eb9f1 100644 --- a/shell/platform/linux/fl_texture_gl.cc +++ b/shell/platform/linux/fl_texture_gl.cc @@ -12,7 +12,13 @@ // Added here to stop the compiler from optimising this function away. G_MODULE_EXPORT GType fl_texture_gl_get_type(); -G_DEFINE_TYPE(FlTextureGL, fl_texture_gl, fl_texture_get_type()) +static void fl_texture_gl_texture_iface_init(FlTextureInterface* iface) {} + +G_DEFINE_TYPE_WITH_CODE(FlTextureGL, + fl_texture_gl, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(fl_texture_get_type(), + fl_texture_gl_texture_iface_init)) static void fl_texture_gl_class_init(FlTextureGLClass* klass) {} diff --git a/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h b/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h index a6c490d41c9d9..adddd7728c5d4 100644 --- a/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h +++ b/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h @@ -17,7 +17,7 @@ G_DECLARE_DERIVABLE_TYPE(FlPixelBufferTexture, fl_pixel_buffer_texture, FL, PIXEL_BUFFER_TEXTURE, - FlTexture) + GObject) /** * FlPixelBufferTexture: @@ -76,7 +76,7 @@ G_DECLARE_DERIVABLE_TYPE(FlPixelBufferTexture, */ struct _FlPixelBufferTextureClass { - FlTextureClass parent_class; + GObjectClass parent_class; /** * FlPixelBufferTexture::copy_pixels: diff --git a/shell/platform/linux/public/flutter_linux/fl_texture.h b/shell/platform/linux/public/flutter_linux/fl_texture.h index 82f5d668f7d49..45ceb514785ba 100644 --- a/shell/platform/linux/public/flutter_linux/fl_texture.h +++ b/shell/platform/linux/public/flutter_linux/fl_texture.h @@ -14,20 +14,20 @@ G_BEGIN_DECLS -G_DECLARE_DERIVABLE_TYPE(FlTexture, fl_texture, FL, TEXTURE, GObject) +G_DECLARE_INTERFACE(FlTexture, fl_texture, FL, TEXTURE, GObject) /** * FlTexture: * - * #FlTexture is an abstract class that represents a texture. + * #FlTexture represents a texture. * * You can derive #FlTextureGL for populating hardware-accelerated textures or * instantiate #FlPixelBufferTexture for populating pixel buffers. Do NOT - * directly derive this class. + * directly implement this interface. */ -struct _FlTextureClass { - GObjectClass parent_class; +struct _FlTextureInterface { + GTypeInterface g_iface; }; G_END_DECLS diff --git a/shell/platform/linux/public/flutter_linux/fl_texture_gl.h b/shell/platform/linux/public/flutter_linux/fl_texture_gl.h index 6cf3260801f25..949f4afba5ac1 100644 --- a/shell/platform/linux/public/flutter_linux/fl_texture_gl.h +++ b/shell/platform/linux/public/flutter_linux/fl_texture_gl.h @@ -15,7 +15,7 @@ G_BEGIN_DECLS -G_DECLARE_DERIVABLE_TYPE(FlTextureGL, fl_texture_gl, FL, TEXTURE_GL, FlTexture) +G_DECLARE_DERIVABLE_TYPE(FlTextureGL, fl_texture_gl, FL, TEXTURE_GL, GObject) /** * FlTextureGL: @@ -75,7 +75,7 @@ G_DECLARE_DERIVABLE_TYPE(FlTextureGL, fl_texture_gl, FL, TEXTURE_GL, FlTexture) */ struct _FlTextureGLClass { - FlTextureClass parent_class; + GObjectClass parent_class; /** * Virtual method called when Flutter populates this texture. The OpenGL