| Flutter Linux Embedder |

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
16 G_DECLARE_FINAL_TYPE(FlTextureRegistrarImpl,
17 fl_texture_registrar_impl,
18 FL,
19 TEXTURE_REGISTRAR_IMPL,
20 GObject)
21
22 struct _FlTextureRegistrarImpl {
23 GObject parent_instance;
24
25 // Weak reference to the engine this texture registrar is created for.
26 GWeakRef 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
42 static void fl_texture_registrar_impl_iface_init(
43 FlTextureRegistrarInterface* iface);
44
45 G_DEFINE_INTERFACE(FlTextureRegistrar, fl_texture_registrar, G_TYPE_OBJECT)
46
47 G_DEFINE_TYPE_WITH_CODE(
48 FlTextureRegistrarImpl,
49 fl_texture_registrar_impl,
50 G_TYPE_OBJECT,
51 G_IMPLEMENT_INTERFACE(fl_texture_registrar_get_type(),
52 fl_texture_registrar_impl_iface_init))
53
54 static void fl_texture_registrar_default_init(
55 FlTextureRegistrarInterface* iface) {}
56
57 static void fl_texture_registrar_impl_dispose(GObject* object) {
58 FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(object);
59
60 g_mutex_lock(&self->textures_mutex);
61 g_clear_pointer(&self->textures, g_hash_table_unref);
62 g_mutex_unlock(&self->textures_mutex);
63
64 g_weak_ref_clear(&self->engine);
65 g_mutex_clear(&self->textures_mutex);
66
67 G_OBJECT_CLASS(fl_texture_registrar_impl_parent_class)->dispose(object);
68 }
69
70 static void fl_texture_registrar_impl_class_init(
71 FlTextureRegistrarImplClass* klass) {
72 G_OBJECT_CLASS(klass)->dispose = fl_texture_registrar_impl_dispose;
73 }
74
75 static gboolean register_texture(FlTextureRegistrar* registrar,
76 FlTexture* texture) {
77 FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(registrar);
78
79 if (FL_IS_TEXTURE_GL(texture) || FL_IS_PIXEL_BUFFER_TEXTURE(texture)) {
80 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
81 if (engine == nullptr) {
82 return FALSE;
83 }
84
85 // We ideally would use numeric IDs, but for backwards compatibility with
86 // existing code use the address of the texture. Once all code uses
87 // fl_texture_get_id we can re-enable this method. See
88 // https://github.com/flutter/flutter/issues/124009 int64_t id =
89 // self->next_id++;
90 int64_t id = reinterpret_cast<int64_t>(texture);
91 if (fl_engine_register_external_texture(engine, id)) {
92 fl_texture_set_id(texture, id);
93 g_mutex_lock(&self->textures_mutex);
94 g_hash_table_insert(self->textures, GINT_TO_POINTER(id),
95 g_object_ref(texture));
96 g_mutex_unlock(&self->textures_mutex);
97 return TRUE;
98 } else {
99 return FALSE;
100 }
101 } else {
102 // We currently only support #FlTextureGL and #FlPixelBufferTexture.
103 return FALSE;
104 }
105 }
106
107 static FlTexture* lookup_texture(FlTextureRegistrar* registrar,
108 int64_t texture_id) {
109 FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(registrar);
110 g_mutex_lock(&self->textures_mutex);
111 FlTexture* texture = reinterpret_cast<FlTexture*>(
112 g_hash_table_lookup(self->textures, GINT_TO_POINTER(texture_id)));
113 g_mutex_unlock(&self->textures_mutex);
114 return texture;
115 }
116
117 static gboolean mark_texture_frame_available(FlTextureRegistrar* registrar,
118 FlTexture* texture) {
119 FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(registrar);
120
121 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
122 if (engine == nullptr) {
123 return FALSE;
124 }
125
126 return fl_engine_mark_texture_frame_available(engine,
127 fl_texture_get_id(texture));
128 }
129
130 static gboolean unregister_texture(FlTextureRegistrar* registrar,
131 FlTexture* texture) {
132 FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(registrar);
133
134 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
135 if (engine == nullptr) {
136 return FALSE;
137 }
138
139 gboolean result =
140 fl_engine_unregister_external_texture(engine, fl_texture_get_id(texture));
141
142 g_mutex_lock(&self->textures_mutex);
143 if (!g_hash_table_remove(self->textures,
144 GINT_TO_POINTER(fl_texture_get_id(texture)))) {
145 g_warning("Unregistering a non-existent texture %p", texture);
146 }
147 g_mutex_unlock(&self->textures_mutex);
148
149 return result;
150 }
151
152 static void shutdown(FlTextureRegistrar* registrar) {
153 FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(registrar);
154
155 // Unregister any textures.
156 g_mutex_lock(&self->textures_mutex);
157 g_autoptr(GHashTable) textures = self->textures;
158 self->textures = g_hash_table_new_full(g_direct_hash, g_direct_equal, nullptr,
159 g_object_unref);
160 g_hash_table_remove_all(textures);
161 g_mutex_unlock(&self->textures_mutex);
162 }
163
164 static void fl_texture_registrar_impl_iface_init(
165 FlTextureRegistrarInterface* iface) {
166 iface->register_texture = register_texture;
167 iface->lookup_texture = lookup_texture;
168 iface->mark_texture_frame_available = mark_texture_frame_available;
169 iface->unregister_texture = unregister_texture;
170 iface->shutdown = shutdown;
171 }
172
173 static void fl_texture_registrar_impl_init(FlTextureRegistrarImpl* self) {
174 self->next_id = 1;
175 self->textures = g_hash_table_new_full(g_direct_hash, g_direct_equal, nullptr,
176 g_object_unref);
177 // Initialize the mutex for textures.
178 g_mutex_init(&self->textures_mutex);
179 }
180
181 G_MODULE_EXPORT gboolean fl_texture_registrar_register_texture(
182 FlTextureRegistrar* self,
183 FlTexture* texture) {
184 g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), FALSE);
185 g_return_val_if_fail(FL_IS_TEXTURE(texture), FALSE);
186
187 return FL_TEXTURE_REGISTRAR_GET_IFACE(self)->register_texture(self, texture);
188 }
189
190 FlTexture* fl_texture_registrar_lookup_texture(FlTextureRegistrar* self,
191 int64_t texture_id) {
192 g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), NULL);
193
194 return FL_TEXTURE_REGISTRAR_GET_IFACE(self)->lookup_texture(self, texture_id);
195 }
196
197 G_MODULE_EXPORT gboolean fl_texture_registrar_mark_texture_frame_available(
198 FlTextureRegistrar* self,
199 FlTexture* texture) {
200 g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), FALSE);
201
202 return FL_TEXTURE_REGISTRAR_GET_IFACE(self)->mark_texture_frame_available(
203 self, texture);
204 }
205
206 G_MODULE_EXPORT gboolean fl_texture_registrar_unregister_texture(
207 FlTextureRegistrar* self,
208 FlTexture* texture) {
209 g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), FALSE);
210
211 return FL_TEXTURE_REGISTRAR_GET_IFACE(self)->unregister_texture(self,
212 texture);
213 }
214
215 void fl_texture_registrar_shutdown(FlTextureRegistrar* self) {
216 g_return_if_fail(FL_IS_TEXTURE_REGISTRAR(self));
217
218 return FL_TEXTURE_REGISTRAR_GET_IFACE(self)->shutdown(self);
219 }
220
221 FlTextureRegistrar* fl_texture_registrar_new(FlEngine* engine) {
222 FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(
223 g_object_new(fl_texture_registrar_impl_get_type(), nullptr));
224
225 // Added to stop compiler complaining about an unused function.
226 FL_IS_TEXTURE_REGISTRAR_IMPL(self);
227
228 g_weak_ref_init(&self->engine, G_OBJECT(engine));
229
230 return FL_TEXTURE_REGISTRAR(self);
231 }
FL
FL
Definition: fl_binary_messenger.cc:27
fl_engine_mark_texture_frame_available
gboolean fl_engine_mark_texture_frame_available(FlEngine *self, int64_t texture_id)
Definition: fl_engine.cc:1260
fl_engine_unregister_external_texture
gboolean fl_engine_unregister_external_texture(FlEngine *self, int64_t texture_id)
Definition: fl_engine.cc:1274
fl_engine_register_external_texture
gboolean fl_engine_register_external_texture(FlEngine *self, int64_t texture_id)
Definition: fl_engine.cc:1267
fl_engine_private.h
fl_pixel_buffer_texture_private.h
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
fl_texture_get_id
G_MODULE_EXPORT int64_t fl_texture_get_id(FlTexture *self)
Definition: fl_texture.cc:20
fl_texture_set_id
void fl_texture_set_id(FlTexture *self, int64_t id)
Definition: fl_texture.cc:15
fl_texture_gl_private.h
fl_texture_private.h
register_texture
static gboolean register_texture(FlTextureRegistrar *registrar, FlTexture *texture)
Definition: fl_texture_registrar.cc:75
mark_texture_frame_available
static gboolean mark_texture_frame_available(FlTextureRegistrar *registrar, FlTexture *texture)
Definition: fl_texture_registrar.cc:117
fl_texture_registrar_register_texture
G_MODULE_EXPORT gboolean fl_texture_registrar_register_texture(FlTextureRegistrar *self, FlTexture *texture)
Definition: fl_texture_registrar.cc:181
fl_texture_registrar_shutdown
void fl_texture_registrar_shutdown(FlTextureRegistrar *self)
Definition: fl_texture_registrar.cc:215
G_DEFINE_TYPE_WITH_CODE
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)
Definition: fl_texture_registrar.cc:47
fl_texture_registrar_impl_init
static void fl_texture_registrar_impl_init(FlTextureRegistrarImpl *self)
Definition: fl_texture_registrar.cc:173
G_DECLARE_FINAL_TYPE
G_DECLARE_FINAL_TYPE(FlTextureRegistrarImpl, fl_texture_registrar_impl, FL, TEXTURE_REGISTRAR_IMPL, GObject) struct _FlTextureRegistrarImpl
Definition: fl_texture_registrar.cc:16
fl_texture_registrar_unregister_texture
G_MODULE_EXPORT gboolean fl_texture_registrar_unregister_texture(FlTextureRegistrar *self, FlTexture *texture)
Definition: fl_texture_registrar.cc:206
fl_texture_registrar_mark_texture_frame_available
G_MODULE_EXPORT gboolean fl_texture_registrar_mark_texture_frame_available(FlTextureRegistrar *self, FlTexture *texture)
Definition: fl_texture_registrar.cc:197
fl_texture_registrar_new
FlTextureRegistrar * fl_texture_registrar_new(FlEngine *engine)
Definition: fl_texture_registrar.cc:221
lookup_texture
static FlTexture * lookup_texture(FlTextureRegistrar *registrar, int64_t texture_id)
Definition: fl_texture_registrar.cc:107
shutdown
static void shutdown(FlTextureRegistrar *registrar)
Definition: fl_texture_registrar.cc:152
fl_texture_registrar_lookup_texture
FlTexture * fl_texture_registrar_lookup_texture(FlTextureRegistrar *self, int64_t texture_id)
Definition: fl_texture_registrar.cc:190
fl_texture_registrar_impl_dispose
static void fl_texture_registrar_impl_dispose(GObject *object)
Definition: fl_texture_registrar.cc:57
unregister_texture
static gboolean unregister_texture(FlTextureRegistrar *registrar, FlTexture *texture)
Definition: fl_texture_registrar.cc:130
fl_texture_registrar_impl_class_init
static void fl_texture_registrar_impl_class_init(FlTextureRegistrarImplClass *klass)
Definition: fl_texture_registrar.cc:70
fl_texture_registrar_impl_iface_init
static void fl_texture_registrar_impl_iface_init(FlTextureRegistrarInterface *iface)
Definition: fl_texture_registrar.cc:164
fl_texture_registrar.h
fl_texture_registrar_private.h
texture_id
int64_t texture_id
Definition: texture_registrar_unittests.cc:24