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 
6 
7 #include <gmodule.h>
8 
9 #include "flutter/shell/platform/embedder/embedder.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  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 
45 G_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 
54 static void fl_texture_registrar_default_init(
55  FlTextureRegistrarInterface* iface) {}
56 
57 static 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 
71 static 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 
92 static 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)) {
108  fl_texture_set_id(texture, 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 
123 static 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 
133 static 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 
141  return fl_engine_mark_texture_frame_available(self->engine,
142  fl_texture_get_id(texture));
143 }
144 
145 static 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 
174 static 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 
182 G_MODULE_EXPORT gboolean fl_texture_registrar_register_texture(
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 
191 FlTexture* 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 
216 FlTextureRegistrar* 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 }
fl_texture_gl_private.h
fl_texture_registrar_lookup_texture
FlTexture * fl_texture_registrar_lookup_texture(FlTextureRegistrar *self, int64_t texture_id)
Definition: fl_texture_registrar.cc:191
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_engine_mark_texture_frame_available
gboolean fl_engine_mark_texture_frame_available(FlEngine *self, int64_t texture_id)
Definition: fl_engine.cc:873
user_data
FlKeyEvent uint64_t FlKeyResponderAsyncCallback gpointer user_data
Definition: fl_key_channel_responder.cc:121
mark_texture_frame_available
static gboolean mark_texture_frame_available(FlTextureRegistrar *registrar, FlTexture *texture)
Definition: fl_texture_registrar.cc:133
fl_texture_registrar_new
FlTextureRegistrar * fl_texture_registrar_new(FlEngine *engine)
Definition: fl_texture_registrar.cc:216
unregister_texture
static gboolean unregister_texture(FlTextureRegistrar *registrar, FlTexture *texture)
Definition: fl_texture_registrar.cc:145
fl_texture_set_id
void fl_texture_set_id(FlTexture *self, int64_t id)
Definition: fl_texture.cc:15
fl_texture_registrar_unregister_texture
G_MODULE_EXPORT gboolean fl_texture_registrar_unregister_texture(FlTextureRegistrar *self, FlTexture *texture)
Definition: fl_texture_registrar.cc:207
G_DEFINE_INTERFACE
G_DEFINE_INTERFACE(FlKeyboardViewDelegate, fl_keyboard_view_delegate, G_TYPE_OBJECT) static void fl_keyboard_view_delegate_default_init(FlKeyboardViewDelegateInterface *iface)
Definition: fl_keyboard_view_delegate.cc:7
fl_texture_registrar_register_texture
G_MODULE_EXPORT gboolean fl_texture_registrar_register_texture(FlTextureRegistrar *self, FlTexture *texture)
Definition: fl_texture_registrar.cc:182
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_engine_private.h
fl_texture_registrar.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
lookup_texture
static FlTexture * lookup_texture(FlTextureRegistrar *registrar, int64_t texture_id)
Definition: fl_texture_registrar.cc:123
FL
FL
Definition: fl_binary_messenger.cc:27
engine_weak_notify_cb
static void engine_weak_notify_cb(gpointer user_data, GObject *where_the_object_was)
Definition: fl_texture_registrar.cc:57
fl_texture_registrar_impl_class_init
static void fl_texture_registrar_impl_class_init(FlTextureRegistrarImplClass *klass)
Definition: fl_texture_registrar.cc:87
result
GAsyncResult * result
Definition: fl_text_input_plugin.cc:106
fl_pixel_buffer_texture_private.h
register_texture
static gboolean register_texture(FlTextureRegistrar *registrar, FlTexture *texture)
Definition: fl_texture_registrar.cc:92
fl_texture_private.h
fl_texture_registrar_private.h
fl_texture_registrar_impl_init
static void fl_texture_registrar_impl_init(FlTextureRegistrarImpl *self)
Definition: fl_texture_registrar.cc:174
fl_texture_registrar_impl_dispose
static void fl_texture_registrar_impl_dispose(GObject *object)
Definition: fl_texture_registrar.cc:71
fl_engine_register_external_texture
gboolean fl_engine_register_external_texture(FlEngine *self, int64_t texture_id)
Definition: fl_engine.cc:880
engine
FlEngine * engine
Definition: fl_view_accessible.cc:26
fl_texture_registrar_impl_iface_init
static void fl_texture_registrar_impl_iface_init(FlTextureRegistrarInterface *iface)
Definition: fl_texture_registrar.cc:166
fl_engine_unregister_external_texture
gboolean fl_engine_unregister_external_texture(FlEngine *self, int64_t texture_id)
Definition: fl_engine.cc:887
texture_id
int64_t texture_id
Definition: texture_registrar_unittests.cc:24
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:198