From 79d2a14061d29538675f8ba7fd7c94c4a9798a00 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 17 Oct 2021 18:46:01 +0200 Subject: [PATCH 1/7] glcontext: reinstate another missing "!" A leftover from aa0c22b64813a406da9854fd079579d87181a97b. --- gdk/gdkglcontext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c index 640c8bf1fc..32bb0cdbed 100644 --- a/gdk/gdkglcontext.c +++ b/gdk/gdkglcontext.c @@ -954,7 +954,7 @@ gdk_gl_context_set_required_version (GdkGLContext *context, #endif g_return_if_fail (GDK_IS_GL_CONTEXT (context)); - g_return_if_fail (gdk_gl_context_is_realized (context)); + g_return_if_fail (!gdk_gl_context_is_realized (context)); /* this will take care of the default */ if (major == 0 && minor == 0) From c7e36bcf226643fc37b7de37cf9f00138b255384 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 17 Oct 2021 06:54:38 +0200 Subject: [PATCH 2/7] gltexture: Fix conditions for glGetTexImage() call The conditions were inverted, plus we failed to limit this call to non-GLES. --- gdk/gdkgltexture.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gdk/gdkgltexture.c b/gdk/gdkgltexture.c index b20534801a..867fd538cd 100644 --- a/gdk/gdkgltexture.c +++ b/gdk/gdkgltexture.c @@ -155,8 +155,9 @@ gdk_gl_texture_do_download (gpointer texture_, expected_stride = texture->width * gdk_memory_format_bytes_per_pixel (download->format); - if (download->stride != expected_stride && - !gdk_memory_format_gl_format (download->format, gdk_gl_context_get_use_es (self->context), &gl_internal_format, &gl_format, &gl_type)) + if (download->stride == expected_stride && + !gdk_gl_context_get_use_es (self->context) && + gdk_memory_format_gl_format (download->format, TRUE, &gl_internal_format, &gl_format, &gl_type)) { glGetTexImage (GL_TEXTURE_2D, 0, From 800246402f7c65d052fab812fe363e56a28d98e8 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 17 Oct 2021 14:27:03 +0200 Subject: [PATCH 3/7] tiff: Refactor Now we support all the formats. --- gdk/loaders/gdktiff.c | 153 ++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 94 deletions(-) diff --git a/gdk/loaders/gdktiff.c b/gdk/loaders/gdktiff.c index 994f50e353..2652aeacc4 100644 --- a/gdk/loaders/gdktiff.c +++ b/gdk/loaders/gdktiff.c @@ -220,129 +220,89 @@ tiff_open_write (GBytes **result) NULL, NULL); } -/* }}} */ -/* {{{ Format conversion */ - -static void -flip_02 (guchar *data, - int width, - int height, - int stride) -{ - gsize x, y; - - for (y = 0; y < height; y++) - { - for (x = 0; x < width; x++) - { - guchar tmp; - tmp = data[x * 4]; - data[x * 4] = data[x * 4 + 2]; - data[x * 4 + 2] = tmp; - } - data += stride; - } -} - /* }}} */ /* {{{ Public API */ -static struct { +typedef struct _FormatData FormatData; +struct _FormatData { GdkMemoryFormat format; guint16 bits_per_sample; guint16 samples_per_pixel; guint16 sample_format; -} format_data[] = { - { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, 8, 4, SAMPLEFORMAT_UINT }, - { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT }, - { GDK_MEMORY_R16G16B16, 16, 3, SAMPLEFORMAT_UINT }, - { GDK_MEMORY_R16G16B16A16_PREMULTIPLIED, 16, 4, SAMPLEFORMAT_UINT }, - { GDK_MEMORY_R16G16B16_FLOAT, 16, 3, SAMPLEFORMAT_IEEEFP }, - { GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED, 16, 4, SAMPLEFORMAT_IEEEFP }, - { GDK_MEMORY_R32G32B32_FLOAT, 32, 3, SAMPLEFORMAT_IEEEFP }, - { GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED, 32, 4, SAMPLEFORMAT_IEEEFP }, + guint16 alpha_samples; }; +static const FormatData format_data[] = { + [GDK_MEMORY_B8G8R8A8_PREMULTIPLIED] = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA }, + [GDK_MEMORY_A8R8G8B8_PREMULTIPLIED] = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA }, + [GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA }, + [GDK_MEMORY_B8G8R8A8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA }, + [GDK_MEMORY_A8R8G8B8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA }, + [GDK_MEMORY_R8G8B8A8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA }, + [GDK_MEMORY_A8B8G8R8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA }, + [GDK_MEMORY_R8G8B8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0 }, + [GDK_MEMORY_B8G8R8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0 }, + [GDK_MEMORY_R16G16B16] = { GDK_MEMORY_R16G16B16, 16, 3, SAMPLEFORMAT_UINT, 0 }, + [GDK_MEMORY_R16G16B16A16_PREMULTIPLIED] = { GDK_MEMORY_R16G16B16A16_PREMULTIPLIED, 16, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA }, + [GDK_MEMORY_R16G16B16A16] = { GDK_MEMORY_R16G16B16A16, 16, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA }, + [GDK_MEMORY_R16G16B16_FLOAT] = { GDK_MEMORY_R16G16B16_FLOAT, 16, 3, SAMPLEFORMAT_IEEEFP, 0 }, + [GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] = { GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED, 16, 4, SAMPLEFORMAT_IEEEFP, EXTRASAMPLE_ASSOCALPHA }, + [GDK_MEMORY_R16G16B16A16_FLOAT] = { GDK_MEMORY_R16G16B16A16_FLOAT, 16, 4, SAMPLEFORMAT_IEEEFP, EXTRASAMPLE_UNASSALPHA }, + [GDK_MEMORY_R32G32B32_FLOAT] = { GDK_MEMORY_R32G32B32_FLOAT, 32, 3, SAMPLEFORMAT_IEEEFP, 0 }, + [GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] = { GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED, 32, 4, SAMPLEFORMAT_IEEEFP, EXTRASAMPLE_ASSOCALPHA }, + [GDK_MEMORY_R32G32B32A32_FLOAT] = { GDK_MEMORY_R32G32B32A32_FLOAT, 32, 4, SAMPLEFORMAT_IEEEFP, EXTRASAMPLE_UNASSALPHA }, +}; + +/* if this fails, somebody forgot to add formats above */ +G_STATIC_ASSERT (G_N_ELEMENTS (format_data) == GDK_MEMORY_N_FORMATS); + GBytes * gdk_save_tiff (GdkTexture *texture) { TIFF *tif; int width, height, stride; - guint16 bits_per_sample = 0; - guint16 samples_per_pixel = 0; - guint16 sample_format = 0; const guchar *line; const guchar *data; - guchar *new_data = NULL; GBytes *result = NULL; - GdkTexture *memory_texture; + GdkMemoryTexture *memtex; GdkMemoryFormat format; + const FormatData *fdata = NULL; tif = tiff_open_write (&result); width = gdk_texture_get_width (texture); height = gdk_texture_get_height (texture); - format = gdk_texture_get_format (texture); - memory_texture = GDK_TEXTURE (gdk_memory_texture_from_texture (texture, format)); + fdata = &format_data[format]; - for (int i = 0; i < G_N_ELEMENTS (format_data); i++) - { - if (format == format_data[i].format) - { - data = gdk_memory_texture_get_data (GDK_MEMORY_TEXTURE (memory_texture)); - stride = gdk_memory_texture_get_stride (GDK_MEMORY_TEXTURE (memory_texture)); - bits_per_sample = format_data[i].bits_per_sample; - samples_per_pixel = format_data[i].samples_per_pixel; - sample_format = format_data[i].sample_format; - break; - } - } - - if (bits_per_sample == 0) - { - /* An 8-bit format we don't have in the table, handle - * it by converting to R8G8B8A8_PREMULTIPLIED - */ - stride = width * 4; - new_data = g_malloc (stride * height); - gdk_texture_download (memory_texture, new_data, stride); -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - flip_02 (new_data, width, height, stride); -#endif - data = new_data; - bits_per_sample = 8; - samples_per_pixel = 4; - sample_format = SAMPLEFORMAT_UINT; - } + if (fdata == NULL) + fdata = &format_data[0]; TIFFSetField (tif, TIFFTAG_SOFTWARE, "GTK"); TIFFSetField (tif, TIFFTAG_IMAGEWIDTH, width); TIFFSetField (tif, TIFFTAG_IMAGELENGTH, height); - TIFFSetField (tif, TIFFTAG_BITSPERSAMPLE, bits_per_sample); - TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel); - TIFFSetField (tif, TIFFTAG_SAMPLEFORMAT, sample_format); + TIFFSetField (tif, TIFFTAG_BITSPERSAMPLE, fdata->bits_per_sample); + TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, fdata->samples_per_pixel); + TIFFSetField (tif, TIFFTAG_SAMPLEFORMAT, fdata->sample_format); TIFFSetField (tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField (tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); - // TODO: save gamma / colorspace - - if (samples_per_pixel > 3) - { - guint16 extra_samples[] = { EXTRASAMPLE_ASSOCALPHA }; - TIFFSetField (tif, TIFFTAG_EXTRASAMPLES, 1, extra_samples); - } + if (fdata->alpha_samples) + TIFFSetField (tif, TIFFTAG_EXTRASAMPLES, 1, &fdata->alpha_samples); TIFFSetField (tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); TIFFSetField (tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + memtex = gdk_memory_texture_from_texture (texture, fdata->format); + data = gdk_memory_texture_get_data (memtex); + stride = gdk_memory_texture_get_stride (memtex); + line = (const guchar *)data; for (int y = 0; y < height; y++) { if (TIFFWriteScanline (tif, (void *)line, y, 0) == -1) { TIFFClose (tif); - g_free (new_data); - g_object_unref (memory_texture); + g_object_unref (memtex); return NULL; } @@ -354,8 +314,7 @@ gdk_save_tiff (GdkTexture *texture) g_assert (result); - g_free (new_data); - g_object_unref (memory_texture); + g_object_unref (memtex); return result; } @@ -407,6 +366,7 @@ gdk_load_tiff (GBytes *input_bytes, guint16 sample_format; guint16 orientation; guint32 width, height; + guint16 alpha_samples; GdkMemoryFormat format; guchar *data, *line; gsize stride; @@ -434,30 +394,35 @@ gdk_load_tiff (GBytes *input_bytes, guint16 *extra_types; if (!TIFFGetField (tif, TIFFTAG_EXTRASAMPLES, &extra, &extra_types)) - extra = 0; + alpha_samples = 0; - if (extra == 0 || extra_types[0] != EXTRASAMPLE_ASSOCALPHA) + alpha_samples = extra_types[0]; + if (alpha_samples != 0 && alpha_samples != EXTRASAMPLE_ASSOCALPHA && alpha_samples != EXTRASAMPLE_UNASSALPHA) { texture = load_fallback (tif, error); TIFFClose (tif); return texture; } } + else + alpha_samples = 0; - format = 0; - - for (int i = 0; i < G_N_ELEMENTS (format_data); i++) + for (format = 0; format < G_N_ELEMENTS (format_data); format++) { - if (format_data[i].sample_format == sample_format && - format_data[i].bits_per_sample == bits_per_sample && - format_data[i].samples_per_pixel == samples_per_pixel) + /* not a native format */ + if (format_data[format].format != format) + continue; + + if (format_data[format].sample_format == sample_format && + format_data[format].bits_per_sample == bits_per_sample && + format_data[format].samples_per_pixel == samples_per_pixel && + format_data[format].alpha_samples == alpha_samples) { - format = format_data[i].format; break; } } - if (format == 0 || + if (format == G_N_ELEMENTS(format_data) || photometric != PHOTOMETRIC_RGB || planarconfig != PLANARCONFIG_CONTIG || TIFFIsTiled (tif) || From 7eceed8d4d542af2deadeb961a96e65c56ef125c Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 17 Oct 2021 22:15:53 +0200 Subject: [PATCH 4/7] jpeg: Use gdk_memory_texture_from_texture() --- gdk/loaders/gdkjpeg.c | 51 ++++++++++--------------------------------- 1 file changed, 12 insertions(+), 39 deletions(-) diff --git a/gdk/loaders/gdkjpeg.c b/gdk/loaders/gdkjpeg.c index b7c3bbacd5..8cbb0438a4 100644 --- a/gdk/loaders/gdkjpeg.c +++ b/gdk/loaders/gdkjpeg.c @@ -74,38 +74,6 @@ output_message_handler (j_common_ptr cinfo) /* }}} */ /* {{{ Format conversion */ -static void -convert_rgba_to_rgb (guchar *data, - int width, - int height, - int stride) -{ - gsize x, y; - guchar *src, *dest; - - for (y = 0; y < height; y++) - { - src = data; - dest = data; - - for (x = 0; x < width; x++) - { - guint32 pixel; - - memcpy (&pixel, src, sizeof (guint32)); - - dest[0] = (pixel & 0x00ff0000) >> 16; - dest[1] = (pixel & 0x0000ff00) >> 8; - dest[2] = (pixel & 0x000000ff) >> 0; - - dest += 3; - src += 4; - } - - data += stride; - } -} - static void convert_grayscale_to_rgb (guchar *data, int width, @@ -274,11 +242,14 @@ gdk_save_jpeg (GdkTexture *texture) struct jpeg_compress_struct info; struct error_handler_data jerr; struct jpeg_error_mgr err; - guchar *data = NULL; + guchar *data; gulong size = 0; guchar *input = NULL; + GdkMemoryTexture *memtex = NULL; + const guchar *texdata; + gsize texstride; guchar *row; - int width, height, stride; + int width, height; width = gdk_texture_get_width (texture); height = gdk_texture_get_height (texture); @@ -293,6 +264,7 @@ gdk_save_jpeg (GdkTexture *texture) free (data); g_free (input); jpeg_destroy_compress (&info); + g_clear_object (&memtex); return NULL; } @@ -308,21 +280,22 @@ gdk_save_jpeg (GdkTexture *texture) jpeg_mem_dest (&info, &data, &size); - stride = width * 4; - input = g_malloc (stride * height); - gdk_texture_download (texture, input, stride); - convert_rgba_to_rgb (data, width, height, stride); + memtex = gdk_memory_texture_from_texture (texture, + GDK_MEMORY_R8G8B8); + texdata = gdk_memory_texture_get_data (memtex); + texstride = gdk_memory_texture_get_stride (memtex); jpeg_start_compress (&info, TRUE); while (info.next_scanline < info.image_height) { - row = &input[info.next_scanline * stride]; + row = (guchar *) texdata + info.next_scanline * texstride; jpeg_write_scanlines (&info, &row, 1); } jpeg_finish_compress (&info); + g_object_unref (memtex); g_free (input); jpeg_destroy_compress (&info); From dcba78338949d2e1edaf30cd580ddf348d39f181 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 26 Sep 2021 00:22:20 +0200 Subject: [PATCH 5/7] gdk: Rework gdk_pixbuf_get_from_texture() Make it use gdk_memory_texture_from_texture(). Also make gdk_memory_format_alpha() privately available so that we can detect if an image contains an alpha channel. --- gdk/gdkcontentserializer.c | 6 +----- gdk/gdkmemoryformat.c | 12 ++++++------ gdk/gdkmemoryformatprivate.h | 7 +++++++ gdk/gdkpixbuf-drawable.c | 34 ++++++++++++++++++++++++---------- 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/gdk/gdkcontentserializer.c b/gdk/gdkcontentserializer.c index 6faaa0121a..d359c558f8 100644 --- a/gdk/gdkcontentserializer.c +++ b/gdk/gdkcontentserializer.c @@ -641,11 +641,7 @@ pixbuf_serializer (GdkContentSerializer *serializer) else if (G_VALUE_HOLDS (value, GDK_TYPE_TEXTURE)) { GdkTexture *texture = g_value_get_object (value); - cairo_surface_t *surface = gdk_texture_download_surface (texture); - pixbuf = gdk_pixbuf_get_from_surface (surface, - 0, 0, - gdk_texture_get_width (texture), gdk_texture_get_height (texture)); - cairo_surface_destroy (surface); + pixbuf = gdk_pixbuf_get_from_texture (texture); } else { diff --git a/gdk/gdkmemoryformat.c b/gdk/gdkmemoryformat.c index 940e9cea17..60c3317bc8 100644 --- a/gdk/gdkmemoryformat.c +++ b/gdk/gdkmemoryformat.c @@ -27,12 +27,6 @@ typedef struct _GdkMemoryFormatDescription GdkMemoryFormatDescription; -typedef enum { - GDK_MEMORY_ALPHA_PREMULTIPLIED, - GDK_MEMORY_ALPHA_STRAIGHT, - GDK_MEMORY_ALPHA_OPAQUE -} GdkMemoryAlpha; - #define TYPED_FUNCS(name, T, R, G, B, A, bpp, scale) \ static void \ name ## _to_float (float *dest, \ @@ -386,6 +380,12 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format) return memory_formats[format].bytes_per_pixel; } +GdkMemoryAlpha +gdk_memory_format_alpha (GdkMemoryFormat format) +{ + return memory_formats[format].alpha; +} + gsize gdk_memory_format_alignment (GdkMemoryFormat format) { diff --git a/gdk/gdkmemoryformatprivate.h b/gdk/gdkmemoryformatprivate.h index bdcb2265e6..bd75192dfe 100644 --- a/gdk/gdkmemoryformatprivate.h +++ b/gdk/gdkmemoryformatprivate.h @@ -24,7 +24,14 @@ G_BEGIN_DECLS +typedef enum { + GDK_MEMORY_ALPHA_PREMULTIPLIED, + GDK_MEMORY_ALPHA_STRAIGHT, + GDK_MEMORY_ALPHA_OPAQUE +} GdkMemoryAlpha; + gsize gdk_memory_format_alignment (GdkMemoryFormat format) G_GNUC_CONST; +GdkMemoryAlpha gdk_memory_format_alpha (GdkMemoryFormat format) G_GNUC_CONST; gsize gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format) G_GNUC_CONST; gboolean gdk_memory_format_prefers_high_depth(GdkMemoryFormat format) G_GNUC_CONST; gboolean gdk_memory_format_gl_format (GdkMemoryFormat format, diff --git a/gdk/gdkpixbuf-drawable.c b/gdk/gdkpixbuf-drawable.c index 8cf98feeaf..15b886357e 100644 --- a/gdk/gdkpixbuf-drawable.c +++ b/gdk/gdkpixbuf-drawable.c @@ -24,6 +24,8 @@ #include "gdkpixbuf.h" +#include "gdkmemoryformatprivate.h" +#include "gdkmemorytextureprivate.h" #include "gdksurface.h" #include "gdktextureprivate.h" @@ -214,6 +216,13 @@ gdk_pixbuf_get_from_surface (cairo_surface_t *surface, return dest; } +static void +pixbuf_texture_unref_cb (guchar *pixels, + gpointer texture) +{ + g_object_unref (texture); +} + /** * gdk_pixbuf_get_from_texture: * @texture: a `GdkTexture` @@ -229,17 +238,22 @@ gdk_pixbuf_get_from_surface (cairo_surface_t *surface, GdkPixbuf * gdk_pixbuf_get_from_texture (GdkTexture *texture) { - GdkPixbuf *pixbuf; - cairo_surface_t *surface; - int width, height; + GdkMemoryTexture *memtex; + gboolean alpha; - g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL); + alpha = gdk_memory_format_alpha (gdk_texture_get_format (texture)) != GDK_MEMORY_ALPHA_OPAQUE; - width = gdk_texture_get_width (texture); - height = gdk_texture_get_height (texture); - surface = gdk_texture_download_surface (texture); - pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, width, height); - cairo_surface_destroy (surface); + memtex = gdk_memory_texture_from_texture (texture, + alpha ? GDK_MEMORY_GDK_PIXBUF_ALPHA + : GDK_MEMORY_GDK_PIXBUF_OPAQUE); - return pixbuf; + return gdk_pixbuf_new_from_data (gdk_memory_texture_get_data (memtex), + GDK_COLORSPACE_RGB, + alpha, + 8, + gdk_texture_get_width (GDK_TEXTURE (memtex)), + gdk_texture_get_height (GDK_TEXTURE (memtex)), + gdk_memory_texture_get_stride (memtex), + pixbuf_texture_unref_cb, + memtex); } From 5b473911627f3e2d6c6ced90665922743b7286be Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 26 Sep 2021 00:32:27 +0200 Subject: [PATCH 6/7] broadway: Use gdk_texture_save_to_png_bytes() Instead of using Cairo, save the texture directly. --- gdk/broadway/gdkbroadway-server.c | 57 +++++++++++-------------------- 1 file changed, 20 insertions(+), 37 deletions(-) diff --git a/gdk/broadway/gdkbroadway-server.c b/gdk/broadway/gdkbroadway-server.c index e6b96ff0b9..4ce17727cd 100644 --- a/gdk/broadway/gdkbroadway-server.c +++ b/gdk/broadway/gdkbroadway-server.c @@ -609,56 +609,39 @@ open_shared_memory (void) return ret; } -typedef struct { - int fd; - gsize size; -} PngData; - -static cairo_status_t -write_png_cb (void *closure, - const guchar *data, - unsigned int length) -{ - PngData *png_data = closure; - int fd = png_data->fd; - - while (length) - { - gssize ret = write (fd, data, length); - - if (ret <= 0) - return CAIRO_STATUS_WRITE_ERROR; - - png_data->size += ret; - length -= ret; - data += ret; - } - - return CAIRO_STATUS_SUCCESS; -} - guint32 gdk_broadway_server_upload_texture (GdkBroadwayServer *server, GdkTexture *texture) { guint32 id; - cairo_surface_t *surface = gdk_texture_download_surface (texture); BroadwayRequestUploadTexture msg; - PngData data; + GBytes *bytes; + const guchar *data; + gsize size; + int fd; id = server->next_texture_id++; - data.fd = open_shared_memory (); - data.size = 0; - cairo_surface_write_to_png_stream (surface, write_png_cb, &data); + bytes = gdk_texture_save_to_png_bytes (texture); + fd = open_shared_memory (); + data = g_bytes_get_data (bytes, &size); - msg.id = id; - msg.offset = 0; - msg.size = data.size; + while (size) + { + gssize ret = write (fd, data, size); + + if (ret <= 0) + break; + + size -= ret; + data += ret; + } + + g_bytes_unref (bytes); /* This passes ownership of fd */ gdk_broadway_server_send_fd_message (server, msg, - BROADWAY_REQUEST_UPLOAD_TEXTURE, data.fd); + BROADWAY_REQUEST_UPLOAD_TEXTURE, fd); return id; } From a85947196051ef6c3aef6c9e85821bc4443f4214 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Mon, 18 Oct 2021 13:38:35 +0200 Subject: [PATCH 7/7] testsuite: Add workarounds for non-gl backends read: Fix tests for broadway --- testsuite/gdk/memorytexture.c | 3 ++- testsuite/gdk/texture-threads.c | 11 ++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/testsuite/gdk/memorytexture.c b/testsuite/gdk/memorytexture.c index 806f7f1d0a..03f8634c3f 100644 --- a/testsuite/gdk/memorytexture.c +++ b/testsuite/gdk/memorytexture.c @@ -526,7 +526,8 @@ create_texture (GdkMemoryFormat format, case TEXTURE_METHOD_GL_RELEASED: texture = upload_to_gl (texture); - gdk_gl_texture_release (GDK_GL_TEXTURE (texture)); + if (GDK_IS_GL_TEXTURE (texture)) + gdk_gl_texture_release (GDK_GL_TEXTURE (texture)); break; case TEXTURE_METHOD_PNG: diff --git a/testsuite/gdk/texture-threads.c b/testsuite/gdk/texture-threads.c index 11598812bf..5ca16e0ec5 100644 --- a/testsuite/gdk/texture-threads.c +++ b/testsuite/gdk/texture-threads.c @@ -70,11 +70,20 @@ texture_threads (void) GMainLoop *loop; GdkTexture *texture; GTask *task; + GError *error = NULL; /* 1. Get a GL renderer */ surface = gdk_surface_new_toplevel (gdk_display_get_default()); gl_renderer = gsk_gl_renderer_new (); - g_assert_true (gsk_renderer_realize (gl_renderer, surface, NULL)); + if (!gsk_renderer_realize (gl_renderer, surface, &error)) + { + g_test_skip (error->message); + + g_clear_error (&error); + g_clear_object (&gl_renderer); + g_clear_object (&surface); + return; + } /* 2. Get a GL texture */ node = gsk_color_node_new (&(GdkRGBA) { 1, 0, 0, 1 }, &GRAPHENE_RECT_INIT(0, 0, 1, 1));