[gtk/matthiasc/color-profile-rebased: 16/46] gsk: Avoid cairo in icon upload
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/matthiasc/color-profile-rebased: 16/46] gsk: Avoid cairo in icon upload
- Date: Tue, 10 May 2022 13:15:49 +0000 (UTC)
commit 73bed6adc377794d1f18afaa62ef7097920e0e78
Author: Matthias Clasen <mclasen redhat com>
Date: Sun May 8 09:34:35 2022 -0400
gsk: Avoid cairo in icon upload
Use the new memory texture magic
gsk/gl/gskgliconlibrary.c | 265 +++++++++++++++++++++++++++++++---------------
1 file changed, 178 insertions(+), 87 deletions(-)
---
diff --git a/gsk/gl/gskgliconlibrary.c b/gsk/gl/gskgliconlibrary.c
index 51e44a4384..28fea92e6f 100644
--- a/gsk/gl/gskgliconlibrary.c
+++ b/gsk/gl/gskgliconlibrary.c
@@ -24,6 +24,7 @@
#include <gdk/gdkmemoryformatprivate.h>
#include <gdk/gdkprofilerprivate.h>
#include <gdk/gdktextureprivate.h>
+#include <gdk/gdkmemorytextureprivate.h>
#include "gskglcommandqueueprivate.h"
#include "gskgldriverprivate.h"
@@ -71,25 +72,108 @@ gsk_gl_icon_library_init (GskGLIconLibrary *self)
gsk_gl_icon_data_free);
}
+static GdkMemoryTexture *
+gsk_ngl_texture_prepare_upload (GdkGLContext *context,
+ GdkTexture *texture,
+ GLenum *gl_internalformat,
+ GLenum *gl_format,
+ GLenum *gl_type)
+{
+ GdkMemoryTexture *memtex;
+ GdkColorProfile *profile;
+ GdkMemoryFormat format;
+
+ format = gdk_texture_get_format (texture);
+ profile = gdk_texture_get_color_profile (texture);
+
+ memtex = gdk_memory_texture_from_texture (texture, format, profile);
+
+ if (!gdk_memory_format_gl_format (format,
+ gdk_gl_context_get_use_es (context),
+ gl_internalformat,
+ gl_format,
+ gl_type))
+ {
+ g_object_unref (memtex);
+
+ format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
+ profile = gdk_color_profile_get_srgb ();
+ if (!gdk_memory_format_gl_format (format,
+ gdk_gl_context_get_use_es (context),
+ gl_internalformat,
+ gl_format,
+ gl_type))
+ {
+ g_assert_not_reached ();
+ }
+ }
+
+ return gdk_memory_texture_from_texture (texture, format, profile);
+}
+
+static void
+straightTexSubImage2D (int tex,
+ int level,
+ int x,
+ int y,
+ int width,
+ int height,
+ GLenum gl_format,
+ GLenum gl_type,
+ const guchar *data,
+ gsize stride)
+{
+ glTexSubImage2D (tex, level,
+ x, y,
+ width, height,
+ gl_format, gl_type,
+ data);
+}
+
+static void
+strideTexSubImage2D (int tex,
+ int level,
+ int x,
+ int y,
+ int width,
+ int height,
+ GLenum gl_format,
+ GLenum gl_type,
+ const guchar *data,
+ gsize stride)
+{
+ for (int i = 0; i < height; i++)
+ {
+ glTexSubImage2D (tex, level,
+ x, y + i,
+ width, height,
+ gl_format, gl_type,
+ data + i * stride);
+ }
+}
+
void
gsk_gl_icon_library_add (GskGLIconLibrary *self,
GdkTexture *key,
const GskGLIconData **out_value)
{
GskGLTextureLibrary *tl = (GskGLTextureLibrary *)self;
+ GdkGLContext *context = gdk_gl_context_get_current ();
G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
- cairo_surface_t *surface;
+ GdkMemoryTexture *memtex;
GskGLIconData *icon_data;
- guint8 *pixel_data;
- guint8 *surface_data;
- guint8 *free_data = NULL;
- guint gl_format;
- guint gl_type;
+ const guchar *pixel_data;
+ gsize stride, bpp;
+ GdkMemoryFormat format;
+ GLenum gl_internalformat;
+ GLenum gl_format;
+ GLenum gl_type;
guint packed_x;
guint packed_y;
int width;
int height;
guint texture_id;
+ void (* upload_func) (int, int, int, int, int, int, GLenum, GLenum, const guchar *, gsize);
g_assert (GSK_IS_GL_ICON_LIBRARY (self));
g_assert (GDK_IS_TEXTURE (key));
@@ -106,107 +190,114 @@ gsk_gl_icon_library_add (GskGLIconLibrary *self,
icon_data->source_texture = g_object_ref (key);
/* actually upload the texture */
- surface = gdk_texture_download_surface (key, NULL);
- surface_data = cairo_image_surface_get_data (surface);
- gdk_gl_context_push_debug_group_printf (gdk_gl_context_get_current (),
- "Uploading texture");
+ gdk_gl_context_push_debug_group_printf (context, "Uploading texture");
+ memtex = gsk_ngl_texture_prepare_upload (context,
+ key,
+ &gl_internalformat,
+ &gl_format,
+ &gl_type);
+
+ pixel_data = gdk_memory_texture_get_data (memtex);
+ stride = gdk_memory_texture_get_stride (memtex);
+ format = gdk_texture_get_format (GDK_TEXTURE (memtex));
+ bpp = gdk_memory_format_bytes_per_pixel (format);
+
+ texture_id = GSK_GL_TEXTURE_ATLAS_ENTRY_TEXTURE (icon_data);
+
+ glBindTexture (GL_TEXTURE_2D, texture_id);
- if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+ /* GL_UNPACK_ROW_LENGTH is available on desktop GL, OpenGL ES >= 3.0, or if
+ * the GL_EXT_unpack_subimage extension for OpenGL ES 2.0 is available
+ */
+ if ((stride % bpp == 0) &&
+ (gdk_gl_context_get_api (context) == GDK_GL_API_GL ||
+ gdk_gl_context_check_version (context, 3, 0, 3, 0) ||
+ gdk_gl_context_has_unpack_subimage (context)))
{
- pixel_data = free_data = g_malloc (width * height * 4);
- gdk_memory_convert (pixel_data, width * 4,
- GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
- gdk_color_profile_get_srgb (),
- surface_data, cairo_image_surface_get_stride (surface),
- GDK_MEMORY_DEFAULT,
- gdk_color_profile_get_srgb (),
- width, height);
- gl_format = GL_RGBA;
- gl_type = GL_UNSIGNED_BYTE;
+ upload_func = straightTexSubImage2D;
+ glPixelStorei (GL_UNPACK_ROW_LENGTH, stride / bpp);
}
else
{
- pixel_data = surface_data;
- gl_format = GL_BGRA;
- gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ upload_func = strideTexSubImage2D;
}
- texture_id = GSK_GL_TEXTURE_ATLAS_ENTRY_TEXTURE (icon_data);
-
- glBindTexture (GL_TEXTURE_2D, texture_id);
-
- glTexSubImage2D (GL_TEXTURE_2D, 0,
- packed_x + 1, packed_y + 1,
- width, height,
- gl_format, gl_type,
- pixel_data);
+ upload_func (GL_TEXTURE_2D, 0,
+ packed_x + 1, packed_y + 1,
+ width, height,
+ gl_format, gl_type,
+ pixel_data,
+ stride);
/* Padding top */
- glTexSubImage2D (GL_TEXTURE_2D, 0,
- packed_x + 1, packed_y,
- width, 1,
- gl_format, gl_type,
- pixel_data);
+ upload_func (GL_TEXTURE_2D, 0,
+ packed_x + 1, packed_y,
+ width, 1,
+ gl_format, gl_type,
+ pixel_data,
+ stride);
/* Padding left */
- glTexSubImage2D (GL_TEXTURE_2D, 0,
- packed_x, packed_y + 1,
- 1, height,
- gl_format, gl_type,
- pixel_data);
+ upload_func (GL_TEXTURE_2D, 0,
+ packed_x, packed_y + 1,
+ 1, height,
+ gl_format, gl_type,
+ pixel_data,
+ stride);
/* Padding top left */
- glTexSubImage2D (GL_TEXTURE_2D, 0,
- packed_x, packed_y,
- 1, 1,
- gl_format, gl_type,
- pixel_data);
-
+ upload_func (GL_TEXTURE_2D, 0,
+ packed_x, packed_y,
+ 1, 1,
+ gl_format, gl_type,
+ pixel_data,
+ stride);
/* Padding right */
- glPixelStorei (GL_UNPACK_ROW_LENGTH, width);
- glPixelStorei (GL_UNPACK_SKIP_PIXELS, width - 1);
- glTexSubImage2D (GL_TEXTURE_2D, 0,
- packed_x + width + 1, packed_y + 1,
- 1, height,
- gl_format, gl_type,
- pixel_data);
+ upload_func (GL_TEXTURE_2D, 0,
+ packed_x + width + 1, packed_y + 1,
+ 1, height,
+ gl_format, gl_type,
+ pixel_data + (width - 1) * bpp,
+ stride);
/* Padding top right */
- glTexSubImage2D (GL_TEXTURE_2D, 0,
- packed_x + width + 1, packed_y,
- 1, 1,
- gl_format, gl_type,
- pixel_data);
+ upload_func (GL_TEXTURE_2D, 0,
+ packed_x + width + 1, packed_y,
+ 1, 1,
+ gl_format, gl_type,
+ pixel_data + (width - 1) * bpp,
+ stride);
/* Padding bottom */
- glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
- glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
- glPixelStorei (GL_UNPACK_SKIP_ROWS, height - 1);
- glTexSubImage2D (GL_TEXTURE_2D, 0,
- packed_x + 1, packed_y + 1 + height,
- width, 1,
- gl_format, gl_type,
- pixel_data);
+ upload_func (GL_TEXTURE_2D, 0,
+ packed_x + 1, packed_y + 1 + height,
+ width, 1,
+ gl_format, gl_type,
+ pixel_data + (height - 1) * stride,
+ stride);
/* Padding bottom left */
- glTexSubImage2D (GL_TEXTURE_2D, 0,
- packed_x, packed_y + 1 + height,
- 1, 1,
- gl_format, gl_type,
- pixel_data);
+ upload_func (GL_TEXTURE_2D, 0,
+ packed_x, packed_y + 1 + height,
+ 1, 1,
+ gl_format, gl_type,
+ pixel_data + (height - 1) * stride,
+ stride);
/* Padding bottom right */
- glPixelStorei (GL_UNPACK_ROW_LENGTH, width);
- glPixelStorei (GL_UNPACK_SKIP_PIXELS, width - 1);
- glTexSubImage2D (GL_TEXTURE_2D, 0,
- packed_x + 1 + width, packed_y + 1 + height,
- 1, 1,
- gl_format, gl_type,
- pixel_data);
+ upload_func (GL_TEXTURE_2D, 0,
+ packed_x + 1 + width, packed_y + 1 + height,
+ 1, 1,
+ gl_format, gl_type,
+ pixel_data + (width - 1) * bpp + (height - 1) * stride,
+ stride);
/* Reset this */
- glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
- glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
- glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
+ if ((stride % bpp == 0) &&
+ (gdk_gl_context_get_api (context) == GDK_GL_API_GL ||
+ gdk_gl_context_check_version (context, 3, 0, 3, 0) ||
+ gdk_gl_context_has_unpack_subimage (context)))
+ glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
- gdk_gl_context_pop_debug_group (gdk_gl_context_get_current ());
+ gdk_gl_context_pop_debug_group (context);
*out_value = icon_data;
- cairo_surface_destroy (surface);
- g_free (free_data);
+ g_object_unref (memtex);
tl->driver->command_queue->n_uploads++;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]