texturedownloader: Add color state

... and plumb the color state through the downloading machinery, where
no matter what path it takes it ends up in
gdk_memory_convert_color_state() or gdk_memory_convert().

The 2nd of those has been expanded to optionally do colorstate
conversion when the 2 colorstates are different.
This commit is contained in:
Benjamin Otte 2024-07-14 00:51:05 +02:00
parent fee4ad0174
commit 11543a229a
19 changed files with 144 additions and 18 deletions

View File

@ -2062,13 +2062,21 @@ out:
void
gdk_dmabuf_download_mmap (GdkTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
guchar *data,
gsize stride)
{
GdkMemoryFormat src_format = gdk_texture_get_format (texture);
GdkColorState *src_color_state = gdk_texture_get_color_state (texture);
if (format == src_format)
gdk_dmabuf_do_download_mmap (texture, data, stride);
{
gdk_dmabuf_do_download_mmap (texture, data, stride);
gdk_memory_convert_color_state (data, stride, format,
src_color_state, color_state,
gdk_texture_get_width (texture),
gdk_texture_get_height (texture));
}
else
{
unsigned int width, height;
@ -2083,8 +2091,8 @@ gdk_dmabuf_download_mmap (GdkTexture *texture,
gdk_dmabuf_do_download_mmap (texture, src_data, src_stride);
gdk_memory_convert (data, stride, format,
src_data, src_stride, src_format,
gdk_memory_convert (data, stride, format, color_state,
src_data, src_stride, src_format, src_color_state,
width, height);
g_free (src_data);

View File

@ -35,6 +35,7 @@ void
gdk_dmabuf_downloader_download (GdkDmabufDownloader *self,
GdkDmabufTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
guchar *data,
gsize stride)
{
@ -43,6 +44,6 @@ gdk_dmabuf_downloader_download (GdkDmabufDownloader *self,
g_return_if_fail (GDK_IS_DMABUF_DOWNLOADER (self));
iface = GDK_DMABUF_DOWNLOADER_GET_IFACE (self);
iface->download (self, texture, format, data, stride);
iface->download (self, texture, format, color_state, data, stride);
}

View File

@ -20,6 +20,7 @@ struct _GdkDmabufDownloaderInterface
void (* download) (GdkDmabufDownloader *downloader,
GdkDmabufTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
guchar *data,
gsize stride);
};
@ -31,6 +32,7 @@ gboolean gdk_dmabuf_downloader_supports (GdkDmabufDownlo
void gdk_dmabuf_downloader_download (GdkDmabufDownloader *downloader,
GdkDmabufTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
guchar *data,
gsize stride);

View File

@ -29,6 +29,7 @@ void gdk_dmabuf_close_fds (GdkDmabuf
GdkDmabufFormats * gdk_dmabuf_get_mmap_formats (void) G_GNUC_CONST;
void gdk_dmabuf_download_mmap (GdkTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
guchar *data,
gsize stride);

View File

@ -97,6 +97,7 @@ struct _Download
{
GdkDmabufTexture *texture;
GdkMemoryFormat format;
GdkColorState *color_state;
guchar *data;
gsize stride;
volatile int spinlock;
@ -110,6 +111,7 @@ gdk_dmabuf_texture_invoke_callback (gpointer data)
gdk_dmabuf_downloader_download (download->texture->downloader,
download->texture,
download->format,
download->color_state,
download->data,
download->stride);
@ -121,16 +123,17 @@ gdk_dmabuf_texture_invoke_callback (gpointer data)
static void
gdk_dmabuf_texture_download (GdkTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
guchar *data,
gsize stride)
{
GdkDmabufTexture *self = GDK_DMABUF_TEXTURE (texture);
Download download = { self, format, data, stride, 0 };
Download download = { self, format, color_state, data, stride, 0 };
if (self->downloader == NULL)
{
#ifdef HAVE_DMABUF
gdk_dmabuf_download_mmap (texture, format, data, stride);
gdk_dmabuf_download_mmap (texture, format, color_state, data, stride);
#endif
return;
}

View File

@ -137,6 +137,7 @@ typedef struct _Download Download;
struct _Download
{
GdkMemoryFormat format;
GdkColorState *color_state;
guchar *data;
gsize stride;
};
@ -211,6 +212,14 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
gl_format,
gl_type,
download->data);
gdk_memory_convert_color_state (download->data,
download->stride,
download->format,
download->color_state,
texture->color_state,
texture->width,
texture->height);
}
else
{
@ -227,14 +236,15 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
gdk_memory_convert (download->data,
download->stride,
download->format,
download->color_state,
pixels,
stride,
format,
texture->color_state,
texture->width,
texture->height);
g_free (pixels);
}
}
else
@ -288,6 +298,14 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
gl_read_format,
gl_read_type,
download->data);
gdk_memory_convert_color_state (download->data,
download->stride,
download->format,
download->color_state,
texture->color_state,
texture->width,
texture->height);
}
else
{
@ -379,9 +397,11 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
gdk_memory_convert (download->data,
download->stride,
download->format,
download->color_state,
pixels,
stride,
actual_format,
texture->color_state,
texture->width,
texture->height);
@ -395,6 +415,7 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
static void
gdk_gl_texture_download (GdkTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
guchar *data,
gsize stride)
{
@ -403,11 +424,12 @@ gdk_gl_texture_download (GdkTexture *texture,
if (self->saved)
{
gdk_texture_do_download (self->saved, format, data, stride);
gdk_texture_do_download (self->saved, format, color_state, data, stride);
return;
}
download.format = format;
download.color_state = color_state;
download.data = data;
download.stride = stride;

View File

@ -1846,9 +1846,11 @@ void
gdk_memory_convert (guchar *dest_data,
gsize dest_stride,
GdkMemoryFormat dest_format,
GdkColorState *dest_cs,
const guchar *src_data,
gsize src_stride,
GdkMemoryFormat src_format,
GdkColorState *src_cs,
gsize width,
gsize height)
{
@ -1856,7 +1858,9 @@ gdk_memory_convert (guchar *dest_data,
const GdkMemoryFormatDescription *src_desc = &memory_formats[src_format];
float (*tmp)[4];
gsize y;
GdkFloatColorConvert convert_func = NULL;
void (*func) (guchar *, const guchar *, gsize) = NULL;
gboolean needs_premultiply, needs_unpremultiply;
g_assert (dest_format < GDK_MEMORY_N_FORMATS);
g_assert (src_format < GDK_MEMORY_N_FORMATS);
@ -1866,7 +1870,7 @@ gdk_memory_convert (guchar *dest_data,
g_assert (dest_data + gdk_memory_format_min_buffer_size (dest_format, dest_stride, width, height) <= src_data ||
src_data + gdk_memory_format_min_buffer_size (src_format, src_stride, width, height) <= dest_data);
if (src_format == dest_format)
if (src_format == dest_format && gdk_color_state_equal (dest_cs, src_cs))
{
gsize bytes_per_row = src_desc->bytes_per_pixel * width;
@ -1886,7 +1890,9 @@ gdk_memory_convert (guchar *dest_data,
return;
}
if (src_format == GDK_MEMORY_R8G8B8A8 && dest_format == GDK_MEMORY_R8G8B8A8_PREMULTIPLIED)
if (!gdk_color_state_equal (dest_cs, src_cs))
convert_func = gdk_color_state_get_convert_to (src_cs, dest_cs);
else if (src_format == GDK_MEMORY_R8G8B8A8 && dest_format == GDK_MEMORY_R8G8B8A8_PREMULTIPLIED)
func = r8g8b8a8_to_r8g8b8a8_premultiplied;
else if (src_format == GDK_MEMORY_B8G8R8A8 && dest_format == GDK_MEMORY_R8G8B8A8_PREMULTIPLIED)
func = r8g8b8a8_to_b8g8r8a8_premultiplied;
@ -1936,12 +1942,25 @@ gdk_memory_convert (guchar *dest_data,
tmp = g_malloc (sizeof (*tmp) * width);
if (convert_func)
{
needs_unpremultiply = src_desc->alpha == GDK_MEMORY_ALPHA_PREMULTIPLIED;
needs_premultiply = src_desc->alpha != GDK_MEMORY_ALPHA_OPAQUE && dest_desc->alpha != GDK_MEMORY_ALPHA_STRAIGHT;
}
else
{
needs_unpremultiply = src_desc->alpha == GDK_MEMORY_ALPHA_PREMULTIPLIED && dest_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT;
needs_premultiply = src_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT && dest_desc->alpha != GDK_MEMORY_ALPHA_STRAIGHT;
}
for (y = 0; y < height; y++)
{
src_desc->to_float (tmp, src_data, width);
if (src_desc->alpha == GDK_MEMORY_ALPHA_PREMULTIPLIED && dest_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT)
if (needs_unpremultiply)
unpremultiply (tmp, width);
else if (src_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT && dest_desc->alpha != GDK_MEMORY_ALPHA_STRAIGHT)
if (convert_func)
convert_func (src_cs, tmp, width);
if (needs_premultiply)
premultiply (tmp, width);
dest_desc->from_float (dest_data, tmp, width);
src_data += src_stride;

View File

@ -95,9 +95,11 @@ const char * gdk_memory_format_get_name (GdkMemoryFormat
void gdk_memory_convert (guchar *dest_data,
gsize dest_stride,
GdkMemoryFormat dest_format,
GdkColorState *src_cs,
const guchar *src_data,
gsize src_stride,
GdkMemoryFormat src_format,
GdkColorState *dest_cs,
gsize width,
gsize height);
void gdk_memory_convert_color_state (guchar *data,

View File

@ -58,6 +58,7 @@ gdk_memory_texture_dispose (GObject *object)
static void
gdk_memory_texture_download (GdkTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
guchar *data,
gsize stride)
{
@ -65,9 +66,11 @@ gdk_memory_texture_download (GdkTexture *texture,
gdk_memory_convert (data, stride,
format,
color_state,
(guchar *) g_bytes_get_data (self->bytes, NULL),
self->stride,
texture->format,
texture->color_state,
gdk_texture_get_width (texture),
gdk_texture_get_height (texture));
}
@ -217,7 +220,7 @@ gdk_memory_texture_from_texture (GdkTexture *texture)
stride = texture->width * gdk_memory_format_bytes_per_pixel (texture->format);
data = g_malloc_n (stride, texture->height);
gdk_texture_do_download (texture, texture->format, data, stride);
gdk_texture_do_download (texture, texture->format, texture->color_state, data, stride);
bytes = g_bytes_new_take (data, stride * texture->height);
result = gdk_memory_texture_new (texture->width,
texture->height,

View File

@ -262,6 +262,7 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GdkTexture, gdk_texture, G_TYPE_OBJECT,
static void
gdk_texture_default_download (GdkTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
guchar *data,
gsize stride)
{
@ -821,10 +822,11 @@ gdk_texture_get_color_state (GdkTexture *self)
void
gdk_texture_do_download (GdkTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
guchar *data,
gsize stride)
{
GDK_TEXTURE_GET_CLASS (texture)->download (texture, format, data, stride);
GDK_TEXTURE_GET_CLASS (texture)->download (texture, format, color_state, data, stride);
}
static gboolean
@ -1006,6 +1008,7 @@ gdk_texture_download (GdkTexture *texture,
gdk_texture_do_download (texture,
GDK_MEMORY_DEFAULT,
GDK_COLOR_STATE_SRGB,
data,
stride);
}

View File

@ -36,6 +36,7 @@
#include "gdktexturedownloaderprivate.h"
#include "gdkcolorstateprivate.h"
#include "gdkmemoryformatprivate.h"
#include "gdkmemorytextureprivate.h"
#include "gdktextureprivate.h"
@ -51,12 +52,14 @@ gdk_texture_downloader_init (GdkTextureDownloader *self,
{
self->texture = g_object_ref (texture);
self->format = GDK_MEMORY_DEFAULT;
self->color_state = gdk_color_state_ref (GDK_COLOR_STATE_SRGB);
}
void
gdk_texture_downloader_finish (GdkTextureDownloader *self)
{
g_object_unref (self->texture);
gdk_color_state_unref (self->color_state);
}
/**
@ -199,6 +202,45 @@ gdk_texture_downloader_get_format (const GdkTextureDownloader *self)
return self->format;
}
/**
* gdk_texture_downloader_set_color_state:
* @self: a texture downloader
* @color_state: the color state to use
*
* Sets the color state the downloader will convert the data to.
*
* By default, the sRGB colorstate returned by [func@ColorState.get_srgb]
* is used.
*
* Since: 4.16
*/
void
gdk_texture_downloader_set_color_state (GdkTextureDownloader *self,
GdkColorState *color_state)
{
if (self->color_state == color_state)
return;
gdk_color_state_unref (self->color_state);
self->color_state = gdk_color_state_ref (color_state);
}
/**
* gdk_texture_downloader_get_color_state:
* @self: a texture downloader
*
* Gets the color state that the data will be downloaded in.
*
* Returns: The color state of the download
*
* Since: 4.16
**/
GdkColorState *
gdk_texture_downloader_get_color_state (const GdkTextureDownloader *self)
{
return self->color_state;
}
/**
* gdk_texture_downloader_download_into:
* @self: a texture downloader
@ -219,7 +261,7 @@ gdk_texture_downloader_download_into (const GdkTextureDownloader *self,
g_return_if_fail (data != NULL);
g_return_if_fail (stride >= gdk_texture_get_width (self->texture) * gdk_memory_format_bytes_per_pixel (self->format));
gdk_texture_do_download (self->texture, self->format, data, stride);
gdk_texture_do_download (self->texture, self->format, self->color_state, data, stride);
}
/**
@ -250,7 +292,8 @@ gdk_texture_downloader_download_bytes (const GdkTextureDownloader *self,
g_return_val_if_fail (out_stride != NULL, NULL);
if (GDK_IS_MEMORY_TEXTURE (self->texture) &&
gdk_texture_get_format (self->texture) == self->format)
gdk_texture_get_format (self->texture) == self->format &&
gdk_color_state_equal (gdk_texture_get_color_state (self->texture), self->color_state))
{
GdkMemoryTexture *memtex = GDK_MEMORY_TEXTURE (self->texture);
@ -260,7 +303,7 @@ gdk_texture_downloader_download_bytes (const GdkTextureDownloader *self,
stride = self->texture->width * gdk_memory_format_bytes_per_pixel (self->format);
data = g_malloc_n (stride, self->texture->height);
gdk_texture_do_download (self->texture, self->format, data, stride);
gdk_texture_do_download (self->texture, self->format, self->color_state, data, stride);
*out_stride = stride;
return g_bytes_new_take (data, stride * self->texture->height);

View File

@ -30,7 +30,7 @@ G_BEGIN_DECLS
GDK_AVAILABLE_IN_4_10
GType gdk_texture_downloader_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_4_10
GdkTextureDownloader * gdk_texture_downloader_new (GdkTexture *texture);
GdkTextureDownloader * gdk_texture_downloader_new (GdkTexture *texture);
GDK_AVAILABLE_IN_4_10
GdkTextureDownloader * gdk_texture_downloader_copy (const GdkTextureDownloader *self);
@ -48,6 +48,11 @@ void gdk_texture_downloader_set_format (GdkTextureDownl
GdkMemoryFormat format);
GDK_AVAILABLE_IN_4_10
GdkMemoryFormat gdk_texture_downloader_get_format (const GdkTextureDownloader *self);
GDK_AVAILABLE_IN_4_16
void gdk_texture_downloader_set_color_state (GdkTextureDownloader *self,
GdkColorState *color_state);
GDK_AVAILABLE_IN_4_16
GdkColorState * gdk_texture_downloader_get_color_state (const GdkTextureDownloader *self);
GDK_AVAILABLE_IN_4_10

View File

@ -28,6 +28,7 @@ struct _GdkTextureDownloader
/*< private >*/
GdkTexture *texture;
GdkMemoryFormat format;
GdkColorState *color_state;
};
void gdk_texture_downloader_init (GdkTextureDownloader *self,

View File

@ -48,6 +48,7 @@ struct _GdkTextureClass {
/* mandatory: Download in the given format into data */
void (* download) (GdkTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
guchar *data,
gsize stride);
};
@ -62,6 +63,7 @@ GdkMemoryDepth gdk_texture_get_depth (GdkTexture
void gdk_texture_do_download (GdkTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
guchar *data,
gsize stride);
void gdk_texture_diff (GdkTexture *self,

View File

@ -281,9 +281,11 @@ gsk_gl_glyph_library_upload_glyph (GskGLGlyphLibrary *self,
pixel_data = free_data = g_malloc (width * height * 4);
gdk_memory_convert (pixel_data, width * 4,
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
GDK_COLOR_STATE_SRGB,
cairo_image_surface_get_data (surface),
stride,
GDK_MEMORY_DEFAULT,
GDK_COLOR_STATE_SRGB,
width, height);
stride = width * 4;
gl_format = GL_RGBA;

View File

@ -104,6 +104,7 @@ static void
gsk_gl_renderer_dmabuf_downloader_download (GdkDmabufDownloader *downloader_,
GdkDmabufTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
guchar *data,
gsize stride)
{
@ -125,6 +126,7 @@ gsk_gl_renderer_dmabuf_downloader_download (GdkDmabufDownloader *downloader_,
downloader = gdk_texture_downloader_new (native);
gdk_texture_downloader_set_format (downloader, format);
gdk_texture_downloader_set_color_state (downloader, color_state);
gdk_texture_downloader_download_into (downloader, data, stride);
gdk_texture_downloader_free (downloader);

View File

@ -653,6 +653,7 @@ typedef struct _Download Download;
struct _Download
{
GdkMemoryFormat format;
GdkColorState *color_state;
guchar *data;
gsize stride;
};
@ -666,6 +667,7 @@ do_download (gpointer user_data,
gdk_texture_downloader_init (&downloader, texture);
gdk_texture_downloader_set_format (&downloader, download->format);
gdk_texture_downloader_set_color_state (&downloader, download->color_state);
gdk_texture_downloader_download_into (&downloader, download->data, download->stride);
gdk_texture_downloader_finish (&downloader);
@ -677,6 +679,7 @@ gsk_gpu_frame_download_texture (GskGpuFrame *self,
gint64 timestamp,
GdkTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
guchar *data,
gsize stride)
{
@ -702,6 +705,7 @@ gsk_gpu_frame_download_texture (GskGpuFrame *self,
do_download,
g_memdup (&(Download) {
.format = format,
.color_state = color_state,
.data = data,
.stride = stride
}, sizeof (Download)));

View File

@ -84,6 +84,7 @@ void gsk_gpu_frame_download_texture (GskGpuF
gint64 timestamp,
GdkTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
guchar *data,
gsize stride);
GskGpuOp *gsk_gpu_frame_get_last_op (GskGpuFrame *self);

View File

@ -107,6 +107,7 @@ static void
gsk_gpu_renderer_dmabuf_downloader_download (GdkDmabufDownloader *downloader,
GdkDmabufTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
guchar *data,
gsize stride)
{
@ -121,6 +122,7 @@ gsk_gpu_renderer_dmabuf_downloader_download (GdkDmabufDownloader *downloader,
g_get_monotonic_time (),
GDK_TEXTURE (texture),
format,
color_state,
data,
stride);