Flutter Engine
The Flutter Engine
fl_texture_registrar.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h"
6
7#include <gmodule.h>
8
9#include "flutter/shell/platform/embedder/embedder.h"
10#include "flutter/shell/platform/linux/fl_engine_private.h"
11#include "flutter/shell/platform/linux/fl_pixel_buffer_texture_private.h"
12#include "flutter/shell/platform/linux/fl_texture_gl_private.h"
13#include "flutter/shell/platform/linux/fl_texture_private.h"
14#include "flutter/shell/platform/linux/fl_texture_registrar_private.h"
15
16G_DECLARE_FINAL_TYPE(FlTextureRegistrarImpl,
17 fl_texture_registrar_impl,
18 FL,
19 TEXTURE_REGISTRAR_IMPL,
20 GObject)
21
22struct _FlTextureRegistrarImpl {
23 GObject parent_instance;
24
25 // Weak reference to the engine this texture registrar is created for.
26 FlEngine* engine;
27
28 // ID to assign to the next new texture.
29 int64_t next_id;
30
31 // Internal record for registered textures.
32 //
33 // It is a map from Flutter texture ID to #FlTexture instance created by
34 // plugins. The keys are directly stored int64s. The values are stored
35 // pointer to #FlTexture. This table is freed by the responder.
36 GHashTable* textures;
37
38 // The mutex guard to make `textures` thread-safe.
39 GMutex textures_mutex;
40};
41
43 FlTextureRegistrarInterface* iface);
44
45G_DEFINE_INTERFACE(FlTextureRegistrar, fl_texture_registrar, G_TYPE_OBJECT)
46
48 FlTextureRegistrarImpl,
49 fl_texture_registrar_impl,
50 G_TYPE_OBJECT,
51 G_IMPLEMENT_INTERFACE(fl_texture_registrar_get_type(),
53
54static void fl_texture_registrar_default_init(
55 FlTextureRegistrarInterface* iface) {}
56
57static void engine_weak_notify_cb(gpointer user_data,
58 GObject* where_the_object_was) {
59 FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(user_data);
60 self->engine = nullptr;
61
62 // Unregister any textures.
63 g_mutex_lock(&self->textures_mutex);
64 g_autoptr(GHashTable) textures = self->textures;
65 self->textures = g_hash_table_new_full(g_direct_hash, g_direct_equal, nullptr,
66 g_object_unref);
67 g_hash_table_remove_all(textures);
68 g_mutex_unlock(&self->textures_mutex);
69}
70
71static void fl_texture_registrar_impl_dispose(GObject* object) {
72 FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(object);
73
74 g_mutex_lock(&self->textures_mutex);
75 g_clear_pointer(&self->textures, g_hash_table_unref);
76 g_mutex_unlock(&self->textures_mutex);
77
78 if (self->engine != nullptr) {
79 g_object_weak_unref(G_OBJECT(self->engine), engine_weak_notify_cb, self);
80 self->engine = nullptr;
81 }
82 g_mutex_clear(&self->textures_mutex);
83
84 G_OBJECT_CLASS(fl_texture_registrar_impl_parent_class)->dispose(object);
85}
86
88 FlTextureRegistrarImplClass* klass) {
89 G_OBJECT_CLASS(klass)->dispose = fl_texture_registrar_impl_dispose;
90}
91
92static gboolean register_texture(FlTextureRegistrar* registrar,
93 FlTexture* texture) {
94 FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(registrar);
95
96 if (FL_IS_TEXTURE_GL(texture) || FL_IS_PIXEL_BUFFER_TEXTURE(texture)) {
97 if (self->engine == nullptr) {
98 return FALSE;
99 }
100
101 // We ideally would use numeric IDs, but for backwards compatibility with
102 // existing code use the address of the texture. Once all code uses
103 // fl_texture_get_id we can re-enable this method. See
104 // https://github.com/flutter/flutter/issues/124009 int64_t id =
105 // self->next_id++;
106 int64_t id = reinterpret_cast<int64_t>(texture);
107 if (fl_engine_register_external_texture(self->engine, id)) {
109 g_mutex_lock(&self->textures_mutex);
110 g_hash_table_insert(self->textures, GINT_TO_POINTER(id),
111 g_object_ref(texture));
112 g_mutex_unlock(&self->textures_mutex);
113 return TRUE;
114 } else {
115 return FALSE;
116 }
117 } else {
118 // We currently only support #FlTextureGL and #FlPixelBufferTexture.
119 return FALSE;
120 }
121}
122
123static FlTexture* lookup_texture(FlTextureRegistrar* registrar,
124 int64_t texture_id) {
125 FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(registrar);
126 g_mutex_lock(&self->textures_mutex);
127 FlTexture* texture = reinterpret_cast<FlTexture*>(
128 g_hash_table_lookup(self->textures, GINT_TO_POINTER(texture_id)));
129 g_mutex_unlock(&self->textures_mutex);
130 return texture;
131}
132
133static gboolean mark_texture_frame_available(FlTextureRegistrar* registrar,
134 FlTexture* texture) {
135 FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(registrar);
136
137 if (self->engine == nullptr) {
138 return FALSE;
139 }
140
143}
144
145static gboolean unregister_texture(FlTextureRegistrar* registrar,
146 FlTexture* texture) {
147 FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(registrar);
148
149 if (self->engine == nullptr) {
150 return FALSE;
151 }
152
154 self->engine, fl_texture_get_id(texture));
155
156 g_mutex_lock(&self->textures_mutex);
157 if (!g_hash_table_remove(self->textures,
158 GINT_TO_POINTER(fl_texture_get_id(texture)))) {
159 g_warning("Unregistering a non-existent texture %p", texture);
160 }
161 g_mutex_unlock(&self->textures_mutex);
162
163 return result;
164}
165
167 FlTextureRegistrarInterface* iface) {
168 iface->register_texture = register_texture;
169 iface->lookup_texture = lookup_texture;
170 iface->mark_texture_frame_available = mark_texture_frame_available;
171 iface->unregister_texture = unregister_texture;
172}
173
174static void fl_texture_registrar_impl_init(FlTextureRegistrarImpl* self) {
175 self->next_id = 1;
176 self->textures = g_hash_table_new_full(g_direct_hash, g_direct_equal, nullptr,
177 g_object_unref);
178 // Initialize the mutex for textures.
179 g_mutex_init(&self->textures_mutex);
180}
181
183 FlTextureRegistrar* self,
184 FlTexture* texture) {
185 g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), FALSE);
186 g_return_val_if_fail(FL_IS_TEXTURE(texture), FALSE);
187
188 return FL_TEXTURE_REGISTRAR_GET_IFACE(self)->register_texture(self, texture);
189}
190
191FlTexture* fl_texture_registrar_lookup_texture(FlTextureRegistrar* self,
192 int64_t texture_id) {
193 g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), NULL);
194
195 return FL_TEXTURE_REGISTRAR_GET_IFACE(self)->lookup_texture(self, texture_id);
196}
197
199 FlTextureRegistrar* self,
200 FlTexture* texture) {
201 g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), FALSE);
202
203 return FL_TEXTURE_REGISTRAR_GET_IFACE(self)->mark_texture_frame_available(
204 self, texture);
205}
206
208 FlTextureRegistrar* self,
209 FlTexture* texture) {
210 g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), FALSE);
211
212 return FL_TEXTURE_REGISTRAR_GET_IFACE(self)->unregister_texture(self,
213 texture);
214}
215
216FlTextureRegistrar* fl_texture_registrar_new(FlEngine* engine) {
217 FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(
218 g_object_new(fl_texture_registrar_impl_get_type(), nullptr));
219
220 // Added to stop compiler complaining about an unused function.
221 FL_IS_TEXTURE_REGISTRAR_IMPL(self);
222
223 self->engine = engine;
224 g_object_weak_ref(G_OBJECT(engine), engine_weak_notify_cb, self);
225
226 return FL_TEXTURE_REGISTRAR(self);
227}
static uint32_t next_id()
Definition: SkTextBlob.cpp:146
FlutterEngine engine
Definition: main.cc:68
gboolean fl_engine_mark_texture_frame_available(FlEngine *self, int64_t texture_id)
Definition: fl_engine.cc:894
gboolean fl_engine_unregister_external_texture(FlEngine *self, int64_t texture_id)
Definition: fl_engine.cc:908
gboolean fl_engine_register_external_texture(FlEngine *self, int64_t texture_id)
Definition: fl_engine.cc:901
G_DEFINE_INTERFACE(FlKeyboardViewDelegate, fl_keyboard_view_delegate, G_TYPE_OBJECT) static void fl_keyboard_view_delegate_default_init(FlKeyboardViewDelegateInterface *iface)
GAsyncResult * result
G_MODULE_EXPORT int64_t fl_texture_get_id(FlTexture *self)
Definition: fl_texture.cc:20
void fl_texture_set_id(FlTexture *self, int64_t id)
Definition: fl_texture.cc:15
static gboolean register_texture(FlTextureRegistrar *registrar, FlTexture *texture)
static gboolean mark_texture_frame_available(FlTextureRegistrar *registrar, FlTexture *texture)
G_MODULE_EXPORT gboolean fl_texture_registrar_register_texture(FlTextureRegistrar *self, FlTexture *texture)
static void engine_weak_notify_cb(gpointer user_data, GObject *where_the_object_was)
G_DEFINE_TYPE_WITH_CODE(FlTextureRegistrarImpl, fl_texture_registrar_impl, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(fl_texture_registrar_get_type(), fl_texture_registrar_impl_iface_init)) static void fl_texture_registrar_default_init(FlTextureRegistrarInterface *iface)
static void fl_texture_registrar_impl_init(FlTextureRegistrarImpl *self)
G_DECLARE_FINAL_TYPE(FlTextureRegistrarImpl, fl_texture_registrar_impl, FL, TEXTURE_REGISTRAR_IMPL, GObject) struct _FlTextureRegistrarImpl
G_MODULE_EXPORT gboolean fl_texture_registrar_unregister_texture(FlTextureRegistrar *self, FlTexture *texture)
G_MODULE_EXPORT gboolean fl_texture_registrar_mark_texture_frame_available(FlTextureRegistrar *self, FlTexture *texture)
FlTexture * fl_texture_registrar_lookup_texture(FlTextureRegistrar *self, int64_t texture_id)
static FlTexture * lookup_texture(FlTextureRegistrar *registrar, int64_t texture_id)
static void fl_texture_registrar_impl_dispose(GObject *object)
static gboolean unregister_texture(FlTextureRegistrar *registrar, FlTexture *texture)
FlTextureRegistrar * fl_texture_registrar_new(FlEngine *engine)
static void fl_texture_registrar_impl_class_init(FlTextureRegistrarImplClass *klass)
static void fl_texture_registrar_impl_iface_init(FlTextureRegistrarInterface *iface)
return FALSE
FlTexture * texture
void * user_data
int64_t texture_id