From 92eb845482116ca869ced8183d64f045e1ab3d38 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 25 Apr 2023 11:03:51 +0200 Subject: [PATCH] gltexture: Optionally take a sync object Add a new function to TextureBuilder that takes a GLsync that requires internal code to wait on before using the texture. Somewhat sneakily, we don't take the sync if syncs are not supported by the current GL context. As public API has no code to query the sync for the destroy notify, this is fine and it means we don't have to do the check every time we want to call gdk_texture_get_sync() internally. --- gdk/gdkgltexture.c | 9 +++++ gdk/gdkgltexturebuilder.c | 77 +++++++++++++++++++++++++++++++++++++-- gdk/gdkgltexturebuilder.h | 6 +++ gdk/gdkgltextureprivate.h | 3 +- 4 files changed, 91 insertions(+), 4 deletions(-) diff --git a/gdk/gdkgltexture.c b/gdk/gdkgltexture.c index e7818e9a07..3b6c20a637 100644 --- a/gdk/gdkgltexture.c +++ b/gdk/gdkgltexture.c @@ -39,6 +39,7 @@ struct _GdkGLTexture { GdkGLContext *context; guint id; gboolean has_mipmap; + gpointer sync; GdkTexture *saved; @@ -296,6 +297,12 @@ gdk_gl_texture_has_mipmap (GdkGLTexture *self) return self->has_mipmap; } +gpointer +gdk_gl_texture_get_sync (GdkGLTexture *self) +{ + return self->sync; +} + /** * gdk_gl_texture_release: * @self: a `GdkTexture` wrapping a GL texture @@ -337,6 +344,8 @@ gdk_gl_texture_new_from_builder (GdkGLTextureBuilder *builder, self->id = gdk_gl_texture_builder_get_id (builder); GDK_TEXTURE (self)->format = gdk_gl_texture_builder_get_format (builder); self->has_mipmap = gdk_gl_texture_builder_get_has_mipmap (builder); + if (gdk_gl_context_has_sync (self->context)) + self->sync = gdk_gl_texture_builder_get_sync (builder); self->destroy = destroy; self->data = data; diff --git a/gdk/gdkgltexturebuilder.c b/gdk/gdkgltexturebuilder.c index ca13fe6618..ceaf44a9c8 100644 --- a/gdk/gdkgltexturebuilder.c +++ b/gdk/gdkgltexturebuilder.c @@ -35,6 +35,7 @@ struct _GdkGLTextureBuilder int height; GdkMemoryFormat format; gboolean has_mipmap; + gpointer sync; }; struct _GdkGLTextureBuilderClass @@ -68,6 +69,7 @@ enum PROP_HAS_MIPMAP, PROP_HEIGHT, PROP_ID, + PROP_SYNC, PROP_WIDTH, N_PROPS @@ -117,6 +119,10 @@ gdk_gl_texture_builder_get_property (GObject *object, g_value_set_uint (value, self->id); break; + case PROP_SYNC: + g_value_set_pointer (value, self->sync); + break; + case PROP_WIDTH: g_value_set_int (value, self->width); break; @@ -157,6 +163,10 @@ gdk_gl_texture_builder_set_property (GObject *object, gdk_gl_texture_builder_set_id (self, g_value_get_uint (value)); break; + case PROP_SYNC: + gdk_gl_texture_builder_set_sync (self, g_value_get_pointer (value)); + break; + case PROP_WIDTH: gdk_gl_texture_builder_set_width (self, g_value_get_int (value)); break; @@ -237,6 +247,19 @@ gdk_gl_texture_builder_class_init (GdkGLTextureBuilderClass *klass) 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); + /** + * GdkGLTextureBuilder:sync: (attributes org.gdk.Property.get=gdk_gl_texture_builder_get_sync org.gdk.Property.set=gdk_gl_texture_builder_set_sync) + * + * An optional `GLSync` object. + * + * If this is set, GTK will wait on it before using the texture. + * + * Since: 4.12 + */ + properties[PROP_SYNC] = + g_param_spec_pointer ("sync", NULL, NULL, + G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); + /** * GdkGLTextureBuilder:width: (attributes org.gdk.Property.get=gdk_gl_texture_builder_get_width org.gdk.Property.set=gdk_gl_texture_builder_set_width) * @@ -494,6 +517,54 @@ gdk_gl_texture_builder_set_has_mipmap (GdkGLTextureBuilder *self, g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_HAS_MIPMAP]); } +/** + * gdk_gl_texture_builder_get_sync: (attributes org.gdk.Method.get_property=sync) + * @self: a `GdkGLTextureBuilder` + * + * Gets the `GLsync` previously set via gdk_gl_texture_builder_set_sync(). + * + * Returns: (nullable): the `GLSync` + * + * Since: 4.12 + */ +gpointer +gdk_gl_texture_builder_get_sync (GdkGLTextureBuilder *self) +{ + g_return_val_if_fail (GDK_IS_GL_TEXTURE_BUILDER (self), NULL); + + return self->sync; +} + +/** + * gdk_gl_texture_builder_set_sync: (attributes org.gdk.Method.set_property=sync) + * @self: a `GdkGLTextureBuilder` + * @sync: (nullable): the GLSync object + * + * Sets the GLSync object to use for the texture. + * + * GTK will wait on this object before using the created `GdkTexture`. + * + * The `destroy` function that is passed to [method@Gdk.GLTextureBuilder.build] + * is responsible for freeing the sync object when it is no longer needed. + * The texture builder does not destroy it and it is the callers + * responsibility to make sure it doesn't leak. + * + * Since: 4.12 + */ +void +gdk_gl_texture_builder_set_sync (GdkGLTextureBuilder *self, + gpointer sync) +{ + g_return_if_fail (GDK_IS_GL_TEXTURE_BUILDER (self)); + + if (self->sync == sync) + return; + + self->sync = sync; + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SYNC]); +} + /** * gdk_gl_texture_builder_get_format: (attributes org.gdk.Method.get_property=format) * @self: a `GdkGLTextureBuilder` @@ -553,9 +624,9 @@ gdk_gl_texture_builder_set_format (GdkGLTextureBuilder *self, * * The `destroy` function gets called when the returned texture gets released; * either when the texture is finalized or by an explicit call to - * [method@Gdk.GLTexture.release]. - * This function should release all GL resources associated with the texture, - * such as the [property@Gdk.GLTextureBuilder:id]. + * [method@Gdk.GLTexture.release]. It should release all GL resources associated + * with the texture, such as the [property@Gdk.GLTextureBuilder:id] and the + * [property@Gdk.GLTextureBuilder:sync]. * * Note that it is a programming error to call this function if any mandatory * property has not been set. diff --git a/gdk/gdkgltexturebuilder.h b/gdk/gdkgltexturebuilder.h index 1633bca1c2..03ee185e0c 100644 --- a/gdk/gdkgltexturebuilder.h +++ b/gdk/gdkgltexturebuilder.h @@ -72,6 +72,12 @@ GDK_AVAILABLE_IN_4_12 void gdk_gl_texture_builder_set_has_mipmap (GdkGLTextureBuilder *self, gboolean has_mipmap); +GDK_AVAILABLE_IN_4_12 +gpointer gdk_gl_texture_builder_get_sync (GdkGLTextureBuilder *self) G_GNUC_PURE; +GDK_AVAILABLE_IN_4_12 +void gdk_gl_texture_builder_set_sync (GdkGLTextureBuilder *self, + gpointer sync); + GDK_AVAILABLE_IN_4_12 GdkTexture * gdk_gl_texture_builder_build (GdkGLTextureBuilder *self, GDestroyNotify destroy, diff --git a/gdk/gdkgltextureprivate.h b/gdk/gdkgltextureprivate.h index eae09290a9..c2841fb55e 100644 --- a/gdk/gdkgltextureprivate.h +++ b/gdk/gdkgltextureprivate.h @@ -10,11 +10,12 @@ G_BEGIN_DECLS GdkTexture * gdk_gl_texture_new_from_builder (GdkGLTextureBuilder *builder, GDestroyNotify destroy, gpointer data); - + GdkGLContext * gdk_gl_texture_get_context (GdkGLTexture *self); guint gdk_gl_texture_get_id (GdkGLTexture *self); gboolean gdk_gl_texture_has_mipmap (GdkGLTexture *self); +gpointer gdk_gl_texture_get_sync (GdkGLTexture *self); G_END_DECLS