Add color states to gdk_memory_convert

This lets us perform color space conversions at the same time
as memory format changes.
This commit is contained in:
Matthias Clasen
2024-06-07 21:25:21 -04:00
parent 1c1d52cc59
commit b5e4bf7a70
8 changed files with 66 additions and 12 deletions

View File

@@ -24,6 +24,7 @@
#include "gdkdmabuffourccprivate.h"
#include "gdkdmabuftextureprivate.h"
#include "gdkmemoryformatprivate.h"
#include "gdkcolorstate.h"
#ifdef HAVE_DMABUF
#include <sys/mman.h>
@@ -2066,8 +2067,10 @@ gdk_dmabuf_download_mmap (GdkTexture *texture,
gsize stride)
{
GdkMemoryFormat src_format = gdk_texture_get_format (texture);
GdkColorState *src_color_state = gdk_texture_get_color_state (texture);
if (format == src_format)
if (format == src_format &&
gdk_color_state_equal (gdk_color_state_get_srgb (), src_color_state))
gdk_dmabuf_do_download_mmap (texture, data, stride);
else
{
@@ -2083,8 +2086,10 @@ 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, gdk_color_state_get_srgb (),
src_data, src_stride,
src_format, src_color_state,
width, height);
g_free (src_data);

View File

@@ -24,6 +24,7 @@
#include "gdkglcontextprivate.h"
#include "gdkmemoryformatprivate.h"
#include "gdkmemorytextureprivate.h"
#include "gdkcolorstate.h"
#include <epoxy/gl.h>
@@ -185,13 +186,15 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
{
GdkTexture *texture = GDK_TEXTURE (self);
GdkMemoryFormat format;
GdkColorState *color_state;
gsize expected_stride;
Download *download = download_;
GLint gl_internal_format;
GLenum gl_format, gl_type;
GLint gl_swizzle[4];
format = gdk_texture_get_format (texture),
format = gdk_texture_get_format (texture);
color_state = gdk_texture_get_color_state (texture);
expected_stride = texture->width * gdk_memory_format_bytes_per_pixel (download->format);
if (!gdk_gl_context_get_use_es (context) &&
@@ -225,9 +228,11 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
gdk_memory_convert (download->data,
download->stride,
download->format,
gdk_color_state_get_srgb (),
pixels,
stride,
format,
color_state,
texture->width,
texture->height);
@@ -377,9 +382,11 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
gdk_memory_convert (download->data,
download->stride,
download->format,
gdk_color_state_get_srgb (),
pixels,
stride,
actual_format,
color_state,
texture->width,
texture->height);

View File

@@ -23,8 +23,9 @@
#include "gdkdmabuffourccprivate.h"
#include "gdkglcontextprivate.h"
#include "gdkcolorstateprivate.h"
#include "gsk/gl/fp16private.h"
#include "gtk/gtkcolorutilsprivate.h"
#include <epoxy/gl.h>
@@ -1734,14 +1735,18 @@ void
gdk_memory_convert (guchar *dest_data,
gsize dest_stride,
GdkMemoryFormat dest_format,
GdkColorState *dest_color_state,
const guchar *src_data,
gsize src_stride,
GdkMemoryFormat src_format,
GdkColorState *src_color_state,
gsize width,
gsize height)
{
const GdkMemoryFormatDescription *dest_desc = &memory_formats[dest_format];
const GdkMemoryFormatDescription *src_desc = &memory_formats[src_format];
GdkColorStateTransform transform;
gboolean has_transform;
float *tmp;
gsize y;
void (*func) (guchar *, const guchar *, gsize) = NULL;
@@ -1749,7 +1754,8 @@ gdk_memory_convert (guchar *dest_data,
g_assert (dest_format < GDK_MEMORY_N_FORMATS);
g_assert (src_format < GDK_MEMORY_N_FORMATS);
if (src_format == dest_format)
if (gdk_color_state_equal (src_color_state, dest_color_state) &&
src_format == dest_format)
{
gsize bytes_per_row = src_desc->bytes_per_pixel * width;
@@ -1769,7 +1775,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 (src_color_state, dest_color_state))
func = NULL;
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;
@@ -1817,19 +1825,43 @@ gdk_memory_convert (guchar *dest_data,
return;
}
if (!gdk_color_state_equal (src_color_state, dest_color_state))
{
gdk_color_state_transform_init (&transform, src_color_state, dest_color_state, TRUE);
has_transform = TRUE;
}
else
{
has_transform = FALSE;
}
tmp = g_new (float, width * 4);
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)
unpremultiply (tmp, width);
else if (src_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT && dest_desc->alpha != GDK_MEMORY_ALPHA_STRAIGHT)
premultiply (tmp, width);
if (has_transform)
{
if (src_desc->alpha == GDK_MEMORY_ALPHA_PREMULTIPLIED)
unpremultiply (tmp, width);
gdk_color_state_transform (&transform, tmp, tmp, width);
if (dest_desc->alpha != GDK_MEMORY_ALPHA_STRAIGHT)
premultiply (tmp, width);
}
else
{
if (src_desc->alpha == GDK_MEMORY_ALPHA_PREMULTIPLIED && dest_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT)
unpremultiply (tmp, width);
else if (src_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT && dest_desc->alpha != GDK_MEMORY_ALPHA_STRAIGHT)
premultiply (tmp, width);
}
dest_desc->from_float (dest_data, tmp, width);
src_data += src_stride;
dest_data += dest_stride;
}
if (has_transform)
gdk_color_state_transform_finish (&transform);
g_free (tmp);
}

View File

@@ -80,9 +80,11 @@ const char * gdk_memory_format_get_name (GdkMemoryFormat
void gdk_memory_convert (guchar *dest_data,
gsize dest_stride,
GdkMemoryFormat dest_format,
GdkColorState *dest_color_state,
const guchar *src_data,
gsize src_stride,
GdkMemoryFormat src_format,
GdkColorState *src_color_state,
gsize width,
gsize height);

View File

@@ -66,9 +66,11 @@ gdk_memory_texture_download (GdkTexture *texture,
gdk_memory_convert (data, stride,
format,
gdk_color_state_get_srgb (),
(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));
}

View File

@@ -805,6 +805,7 @@ gdk_texture_get_color_state (GdkTexture *texture)
return texture->color_state;
}
void
gdk_texture_do_download (GdkTexture *texture,
GdkMemoryFormat format,

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_get_srgb (),
cairo_image_surface_get_data (surface),
stride,
GDK_MEMORY_DEFAULT,
gdk_color_state_get_srgb (),
width, height);
stride = width * 4;
gl_format = GL_RGBA;

View File

@@ -116,8 +116,11 @@ gsk_gl_icon_library_add (GskGLIconLibrary *self,
pixel_data = free_data = g_malloc (width * height * 4);
gdk_memory_convert (pixel_data, width * 4,
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
gdk_color_state_get_srgb (),
surface_data, cairo_image_surface_get_stride (surface),
GDK_MEMORY_DEFAULT, width, height);
GDK_MEMORY_DEFAULT,
gdk_texture_get_color_state (key),
width, height);
gl_format = GL_RGBA;
gl_type = GL_UNSIGNED_BYTE;
}