From: Benjamin Otte Date: Thu, 7 Oct 2021 04:19:41 +0000 (+0200) Subject: texture: Refactor downloading X-Git-Tag: archive/raspbian/4.6.5+ds-1+rpi1~1^2~19^2~5^2~239^2~8 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=b65b64628d0b5c883ba563eda412d88758c67b89;p=gtk4.git texture: Refactor downloading Pass a format do GdkTextureClass::download(). That way we can download data in any format. Also replace gdk_texture_download_texture() with gdk_memory_texture_from_texture() which again takes a format. The old functionality is still there for code that wants it: Just pass gdk_texture_get_format (texture) as the format argument. --- diff --git a/gdk/gdkgltexture.c b/gdk/gdkgltexture.c index e39fcd3fbb..a6d6d6e9b3 100644 --- a/gdk/gdkgltexture.c +++ b/gdk/gdkgltexture.c @@ -109,15 +109,27 @@ gdk_gl_texture_run (GdkGLTexture *self, while (g_atomic_int_get (&invoke.spinlock) == 0); } +typedef struct _Download Download; + +struct _Download +{ + guint gl_internalformat; + guint gl_format; + guint gl_type; + guchar *data; + gsize stride; +}; + static inline void -gdk_gl_texture_get_tex_image (GdkGLTexture *self, - GLenum gl_format, - GLenum gl_type, - GLvoid *data) +gdk_gl_texture_do_download (gpointer texture_, + gpointer download_) { + GdkGLTexture *self = texture_; + GdkTexture *texture = texture_; + Download *download = download_; + if (gdk_gl_context_get_use_es (self->context)) { - GdkTexture *texture = GDK_TEXTURE (self); GLuint fbo; glGenFramebuffers (1, &fbo); @@ -125,9 +137,9 @@ gdk_gl_texture_get_tex_image (GdkGLTexture *self, glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self->id, 0); glReadPixels (0, 0, texture->width, texture->height, - gl_format, - gl_type, - data); + download->gl_format, + download->gl_type, + download->data); glBindFramebuffer (GL_FRAMEBUFFER, 0); glDeleteFramebuffers (1, &fbo); } @@ -135,136 +147,48 @@ gdk_gl_texture_get_tex_image (GdkGLTexture *self, { glGetTexImage (GL_TEXTURE_2D, 0, - gl_format, - gl_type, - data); + download->gl_format, + download->gl_type, + download->data); } } static void -gdk_gl_texture_do_download_texture (gpointer texture_, - gpointer result_) -{ - GdkTexture *texture = texture_; - GdkTexture **result = result_; - guint gl_internalformat, gl_format, gl_type; - guchar *data; - gsize stride; - GBytes *bytes; - - if (!gdk_memory_format_gl_format (texture->format, - gdk_gl_context_get_use_es (gdk_gl_context_get_current ()), - &gl_internalformat, - &gl_format, - &gl_type)) - { - g_assert_not_reached (); - } - - stride = gdk_memory_format_bytes_per_pixel (texture->format) * texture->width; - data = g_malloc_n (stride, texture->height); - - gdk_gl_texture_get_tex_image (texture_, - gl_format, - gl_type, - data); - - bytes = g_bytes_new_take (data, stride * texture->height); - *result = gdk_memory_texture_new (texture->width, - texture->height, - texture->format, - bytes, - stride); - - g_bytes_unref (bytes); -} - -static GdkTexture * -gdk_gl_texture_download_texture (GdkTexture *texture) -{ - GdkGLTexture *self = GDK_GL_TEXTURE (texture); - GdkTexture *result; - - if (self->saved) - return g_object_ref (self->saved); - - gdk_gl_texture_run (self, gdk_gl_texture_do_download_texture, &result); - - return result; -} - -static void -gdk_gl_texture_do_download (gpointer texture, - gpointer data) -{ - glGetTexImage (GL_TEXTURE_2D, - 0, - GL_BGRA, -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - GL_UNSIGNED_INT_8_8_8_8_REV, -#elif G_BYTE_ORDER == G_BIG_ENDIAN - GL_UNSIGNED_BYTE, -#else -#error "Unknown byte order for gdk_gl_texture_download()" -#endif - data); -} - -static void -gdk_gl_texture_download (GdkTexture *texture, - guchar *data, - gsize stride) +gdk_gl_texture_download (GdkTexture *texture, + GdkMemoryFormat format, + guchar *data, + gsize stride) { GdkGLTexture *self = GDK_GL_TEXTURE (texture); + Download download; if (self->saved) { - gdk_texture_download (self->saved, data, stride); + gdk_texture_do_download (self->saved, format, data, stride); return; } - if (gdk_gl_context_get_use_es (self->context) || - stride != texture->width * 4) - { - GDK_TEXTURE_CLASS (gdk_gl_texture_parent_class)->download (texture, data, stride); - return; - } - - gdk_gl_texture_run (self, gdk_gl_texture_do_download, data); -} - -static void -gdk_gl_texture_do_download_float (gpointer texture, - gpointer data) -{ - glGetTexImage (GL_TEXTURE_2D, - 0, - GL_RGBA, - GL_FLOAT, - data); -} - -static void -gdk_gl_texture_download_float (GdkTexture *texture, - float *data, - gsize stride) -{ - GdkGLTexture *self = GDK_GL_TEXTURE (texture); + download.data = data; + download.stride = stride; - if (self->saved) + if (stride != texture->width * gdk_memory_format_bytes_per_pixel (format) || + !gdk_memory_format_gl_format (format, + gdk_gl_context_get_use_es (self->context), + &download.gl_internalformat, + &download.gl_format, + &download.gl_type)) { - gdk_texture_download_float (self->saved, data, stride); - return; - } + GdkMemoryTexture *memtex; - if (gdk_gl_context_get_use_es (self->context) || - stride != texture->width * 4) - { - GDK_TEXTURE_CLASS (gdk_gl_texture_parent_class)->download_float (texture, data, stride); + memtex = gdk_memory_texture_from_texture (texture, + format == texture->format ? GDK_MEMORY_R8G8B8A8_PREMULTIPLIED + : texture->format); + gdk_texture_do_download (GDK_TEXTURE (memtex), format, data, stride); + g_object_unref (memtex); return; } - gdk_gl_texture_run (self, gdk_gl_texture_do_download_float, data); + gdk_gl_texture_run (self, gdk_gl_texture_do_download, &download); } static void @@ -273,9 +197,8 @@ gdk_gl_texture_class_init (GdkGLTextureClass *klass) GdkTextureClass *texture_class = GDK_TEXTURE_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - texture_class->download_texture = gdk_gl_texture_download_texture; texture_class->download = gdk_gl_texture_download; - texture_class->download_float = gdk_gl_texture_download_float; + gobject_class->dispose = gdk_gl_texture_dispose; } @@ -309,10 +232,14 @@ gdk_gl_texture_get_id (GdkGLTexture *self) void gdk_gl_texture_release (GdkGLTexture *self) { + GdkTexture *texture; + g_return_if_fail (GDK_IS_GL_TEXTURE (self)); g_return_if_fail (self->saved == NULL); - self->saved = gdk_texture_download_texture (GDK_TEXTURE (self)); + texture = GDK_TEXTURE (self); + self->saved = GDK_TEXTURE (gdk_memory_texture_from_texture (texture, + gdk_texture_get_format (texture))); if (self->destroy) { diff --git a/gdk/gdkmemorytexture.c b/gdk/gdkmemorytexture.c index e658ad97ee..4402998ebb 100644 --- a/gdk/gdkmemorytexture.c +++ b/gdk/gdkmemorytexture.c @@ -55,38 +55,16 @@ gdk_memory_texture_dispose (GObject *object) G_OBJECT_CLASS (gdk_memory_texture_parent_class)->dispose (object); } -static GdkTexture * -gdk_memory_texture_download_texture (GdkTexture *texture) -{ - return g_object_ref (texture); -} - static void -gdk_memory_texture_download (GdkTexture *texture, - guchar *data, - gsize stride) +gdk_memory_texture_download (GdkTexture *texture, + GdkMemoryFormat format, + guchar *data, + gsize stride) { GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture); gdk_memory_convert (data, stride, - GDK_MEMORY_DEFAULT, - (guchar *) g_bytes_get_data (self->bytes, NULL), - self->stride, - texture->format, - gdk_texture_get_width (texture), - gdk_texture_get_height (texture)); -} - -static void -gdk_memory_texture_download_float (GdkTexture *texture, - float *data, - gsize stride) -{ - GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture); - - gdk_memory_convert ((guchar *) data, - stride * sizeof (float), - GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED, + format, (guchar *) g_bytes_get_data (self->bytes, NULL), self->stride, texture->format, @@ -100,9 +78,8 @@ gdk_memory_texture_class_init (GdkMemoryTextureClass *klass) GdkTextureClass *texture_class = GDK_TEXTURE_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - texture_class->download_texture = gdk_memory_texture_download_texture; texture_class->download = gdk_memory_texture_download; - texture_class->download_float = gdk_memory_texture_download_float; + gobject_class->dispose = gdk_memory_texture_dispose; } @@ -189,6 +166,40 @@ gdk_memory_texture_new (int width, return GDK_TEXTURE (self); } +GdkMemoryTexture * +gdk_memory_texture_from_texture (GdkTexture *texture, + GdkMemoryFormat format) +{ + GdkTexture *result; + GBytes *bytes; + guchar *data; + gsize stride; + + g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL); + + if (GDK_IS_MEMORY_TEXTURE (texture)) + { + GdkMemoryTexture *memtex = GDK_MEMORY_TEXTURE (texture); + + if (gdk_texture_get_format (texture) == format) + return g_object_ref (memtex); + } + + stride = texture->width * gdk_memory_format_bytes_per_pixel (format); + data = g_malloc_n (stride, texture->height); + + gdk_texture_do_download (texture, format, data, stride); + bytes = g_bytes_new_take (data, stride); + result = gdk_memory_texture_new (texture->width, + texture->height, + format, + bytes, + stride); + g_bytes_unref (bytes); + + return GDK_MEMORY_TEXTURE (result); +} + const guchar * gdk_memory_texture_get_data (GdkMemoryTexture *self) { diff --git a/gdk/gdkmemorytextureprivate.h b/gdk/gdkmemorytextureprivate.h index 0cd5e91f27..a71648a950 100644 --- a/gdk/gdkmemorytextureprivate.h +++ b/gdk/gdkmemorytextureprivate.h @@ -29,6 +29,9 @@ G_BEGIN_DECLS #define GDK_MEMORY_GDK_PIXBUF_OPAQUE GDK_MEMORY_R8G8B8 #define GDK_MEMORY_GDK_PIXBUF_ALPHA GDK_MEMORY_R8G8B8A8 +GdkMemoryTexture * gdk_memory_texture_from_texture (GdkTexture *texture, + GdkMemoryFormat format); + const guchar * gdk_memory_texture_get_data (GdkMemoryTexture *self); gsize gdk_memory_texture_get_stride (GdkMemoryTexture *self); diff --git a/gdk/gdktexture.c b/gdk/gdktexture.c index f4c5928c8d..b2213fd367 100644 --- a/gdk/gdktexture.c +++ b/gdk/gdktexture.c @@ -221,35 +221,13 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GdkTexture, gdk_texture, G_TYPE_OBJECT, #define GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD(obj,method) \ g_critical ("Texture of type '%s' does not implement GdkTexture::" # method, G_OBJECT_TYPE_NAME (obj)) -static GdkTexture * -gdk_texture_real_download_texture (GdkTexture *self) -{ - GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD (self, download_texture); - return NULL; -} - -static void -gdk_texture_real_download (GdkTexture *texture, - guchar *data, - gsize stride) -{ - GdkTexture *memory_texture; - - memory_texture = gdk_texture_download_texture (texture); - gdk_texture_download (memory_texture, data, stride); - g_object_unref (memory_texture); -} - static void -gdk_texture_real_download_float (GdkTexture *self, - float *data, - gsize stride) +gdk_texture_default_download (GdkTexture *texture, + GdkMemoryFormat format, + guchar *data, + gsize stride) { - GdkTexture *memory_texture; - - memory_texture = gdk_texture_download_texture (self); - gdk_texture_download_float (memory_texture, data, stride); - g_object_unref (memory_texture); + GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD (texture, download); } static void @@ -315,9 +293,7 @@ gdk_texture_class_init (GdkTextureClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - klass->download_texture = gdk_texture_real_download_texture; - klass->download = gdk_texture_real_download; - klass->download_float = gdk_texture_real_download_float; + klass->download = gdk_texture_default_download; gobject_class->set_property = gdk_texture_set_property; gobject_class->get_property = gdk_texture_get_property; @@ -692,6 +668,15 @@ gdk_texture_get_height (GdkTexture *texture) return texture->height; } +void +gdk_texture_do_download (GdkTexture *texture, + GdkMemoryFormat format, + guchar *data, + gsize stride) +{ + GDK_TEXTURE_GET_CLASS (texture)->download (texture, format, data,stride); +} + cairo_surface_t * gdk_texture_download_surface (GdkTexture *texture) { @@ -750,7 +735,10 @@ gdk_texture_download (GdkTexture *texture, g_return_if_fail (data != NULL); g_return_if_fail (stride >= gdk_texture_get_width (texture) * 4); - GDK_TEXTURE_GET_CLASS (texture)->download (texture, data, stride); + gdk_texture_do_download (texture, + GDK_MEMORY_DEFAULT, + data, + stride); } /** @@ -789,23 +777,10 @@ gdk_texture_download_float (GdkTexture *texture, g_return_if_fail (data != NULL); g_return_if_fail (stride >= gdk_texture_get_width (texture) * 4); - GDK_TEXTURE_GET_CLASS (texture)->download_float (texture, data, stride); -} - -GdkTexture * -gdk_texture_download_texture (GdkTexture *texture) -{ - g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL); - - g_object_ref (texture); - while (!GDK_IS_MEMORY_TEXTURE (texture)) - { - GdkTexture *downloaded = GDK_TEXTURE_GET_CLASS (texture)->download_texture (texture); - g_object_unref (texture); - texture = downloaded; - } - - return texture; + gdk_texture_do_download (texture, + GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED, + (guchar *) data, + stride); } GdkMemoryFormat diff --git a/gdk/gdktextureprivate.h b/gdk/gdktextureprivate.h index 994c9901f8..a9e6ac51a2 100644 --- a/gdk/gdktextureprivate.h +++ b/gdk/gdktextureprivate.h @@ -27,24 +27,22 @@ struct _GdkTexture struct _GdkTextureClass { GObjectClass parent_class; - /* mandatory: Download into a GdkMemoryTexture */ - GdkTexture * (* download_texture) (GdkTexture *texture); - /* optional */ + /* mandatory: Download in the given format into data */ void (* download) (GdkTexture *texture, + GdkMemoryFormat format, guchar *data, gsize stride); - void (* download_float) (GdkTexture *texture, - float *data, - gsize stride); }; gboolean gdk_texture_can_load (GBytes *bytes); GdkTexture * gdk_texture_new_for_surface (cairo_surface_t *surface); cairo_surface_t * gdk_texture_download_surface (GdkTexture *texture); -/* NB: GdkMemoryTexture */ -GdkTexture * gdk_texture_download_texture (GdkTexture *texture); +void gdk_texture_do_download (GdkTexture *texture, + GdkMemoryFormat format, + guchar *data, + gsize stride); GdkMemoryFormat gdk_texture_get_format (GdkTexture *self); gboolean gdk_texture_set_render_data (GdkTexture *self, gpointer key, diff --git a/gdk/loaders/gdkpng.c b/gdk/loaders/gdkpng.c index 69f85eaa98..6e2278386c 100644 --- a/gdk/loaders/gdkpng.c +++ b/gdk/loaders/gdkpng.c @@ -479,9 +479,9 @@ gdk_save_png (GdkTexture *texture) width = gdk_texture_get_width (texture); height = gdk_texture_get_height (texture); + format = gdk_texture_get_format (texture); - mtexture = gdk_texture_download_texture (texture); - format = gdk_texture_get_format (mtexture); + mtexture = GDK_TEXTURE (gdk_memory_texture_from_texture (texture, format)); switch (format) { diff --git a/gdk/loaders/gdktiff.c b/gdk/loaders/gdktiff.c index d2d8dfdbde..994f50e353 100644 --- a/gdk/loaders/gdktiff.c +++ b/gdk/loaders/gdktiff.c @@ -283,8 +283,8 @@ gdk_save_tiff (GdkTexture *texture) width = gdk_texture_get_width (texture); height = gdk_texture_get_height (texture); - memory_texture = gdk_texture_download_texture (texture); - format = gdk_texture_get_format (memory_texture); + format = gdk_texture_get_format (texture); + memory_texture = GDK_TEXTURE (gdk_memory_texture_from_texture (texture, format)); for (int i = 0; i < G_N_ELEMENTS (format_data); i++) { diff --git a/gsk/gl/gskgldriver.c b/gsk/gl/gskgldriver.c index a19522c8ca..61b8469d52 100644 --- a/gsk/gl/gskgldriver.c +++ b/gsk/gl/gskgldriver.c @@ -23,17 +23,14 @@ #include "config.h" -#include -#include -#include -#include +#include "gskngldriverprivate.h" + #include #include #include #include "gskglcommandqueueprivate.h" #include "gskglcompilerprivate.h" -#include "gskgldriverprivate.h" #include "gskglglyphlibraryprivate.h" #include "gskgliconlibraryprivate.h" #include "gskglprogramprivate.h" @@ -41,6 +38,12 @@ #include "gskgltextureprivate.h" #include "fp16private.h" +#include +#include +#include +#include +#include + #define ATLAS_SIZE 512 #define MAX_OLD_RATIO 0.5 @@ -746,7 +749,7 @@ gsk_gl_driver_load_texture (GskGLDriver *self, int mag_filter) { GdkGLContext *context; - GdkTexture *downloaded_texture; + GdkMemoryTexture *downloaded_texture; GskGLTexture *t; guint texture_id; int height; @@ -773,7 +776,7 @@ gsk_gl_driver_load_texture (GskGLDriver *self, } else { - downloaded_texture = gdk_texture_download_texture (texture); + downloaded_texture = gdk_memory_texture_from_texture (texture, gdk_texture_get_format (texture)); } } else @@ -784,7 +787,7 @@ gsk_gl_driver_load_texture (GskGLDriver *self, return t->texture_id; } - downloaded_texture = gdk_texture_download_texture (texture); + downloaded_texture = gdk_memory_texture_from_texture (texture, gdk_texture_get_format (texture)); } /* The download_texture() call may have switched the GL context. Make sure @@ -794,13 +797,13 @@ gsk_gl_driver_load_texture (GskGLDriver *self, width = gdk_texture_get_width (texture); height = gdk_texture_get_height (texture); texture_id = gsk_gl_command_queue_upload_texture (self->command_queue, - downloaded_texture, - 0, - 0, - width, - height, - min_filter, - mag_filter); + GDK_TEXTURE (downloaded_texture), + 0, + 0, + width, + height, + min_filter, + mag_filter); t = gsk_gl_texture_new (texture_id, width, height, format, min_filter, mag_filter,