Compare commits

...

18 Commits

Author SHA1 Message Date
Matthias Clasen ec271b47fb wip 2024-08-07 19:18:35 -04:00
Matthias Clasen 80bee35ab7 download op: wip 2024-08-07 18:13:34 -04:00
Matthias Clasen 4be4e53bdd memory convert: debug spew 2024-08-07 18:13:34 -04:00
Matthias Clasen d10c55c748 node processor: spew 2024-08-07 18:13:34 -04:00
Matthias Clasen 60d9d79bcc renderer: debug spew 2024-08-07 18:13:33 -04:00
Matthias Clasen d0fbe1db5a download op: debug spew 2024-08-07 18:13:33 -04:00
Matthias Clasen 44aca0cecf Add a test for render_texture 2024-08-07 18:13:33 -04:00
Matthias Clasen f8afc60c9b Some more color tests 2024-08-07 18:11:35 -04:00
Matthias Clasen 2f26bd9842 colorstate: Change the rendering color state api
Pass an extra boolean that tells whether the target image is GL_SRGB,
in which case, the rendering color state must be srgb-linear.

Update all callers to pass FALSE, except for the one call in
the node processor, where we want to take GL_LINEAR into account.
2024-08-07 18:11:35 -04:00
Matthias Clasen 449fc749e6 Add a compare test for handling of pq colors
The node file here has a pq color that is far out of range for
sRGB, and will produce widely different result if we don't clamp
things properly.
2024-08-07 13:34:45 -04:00
Matthias Clasen 56ea1754bf gsk: Pass color state to download op
This lets us create a texture in the desired color state.
2024-08-07 13:34:45 -04:00
Matthias Clasen cd18bb9fd1 renderer: Make hdr textures if necessary
Take the preferred color state of the content into account
when deciding what color state to use for the texture we
generate.
2024-08-07 13:34:45 -04:00
Matthias Clasen 9f3927e7a7 gsk: Adapt to new rendering colorstate api
Since we now handle the GL_SRGB case when the  node processor calls
get_rendering_color_state, we can just pass SRGB as input here.
2024-08-07 13:34:45 -04:00
Matthias Clasen df18749d6d colorstate: Change the rendering color state api
Pass an extra boolean that tells whether the target image is GL_SRGB,
in which case, the rendering color state must be srgb-linear.

Update all callers to pass FALSE, except for the one call in
the node processor, where we want to take GL_LINEAR into account.
2024-08-07 13:34:45 -04:00
Matthias Clasen 50c19a6534 Merge branch 'hdr-content' into 'main'
gsk: Track whether nodes require wide gamut

See merge request GNOME/gtk!7575
2024-08-07 17:34:02 +00:00
Matthias Clasen 6edb526561 Merge branch 'plug-gtask-leaks' into 'main'
Plug GTask leaks

See merge request GNOME/gtk!7551
2024-08-07 16:26:52 +00:00
Matthias Clasen ee18156675 gsk: Add gsk_render_node_is_hdr
Add a function that tracks whether a render node's content is
in a wide gamut color state (in practice, that means non-sRGB).

This will be used in render_texture to determine the color
state to use when creating a texture.
2024-08-07 11:14:21 -04:00
Sergey Bugaev 85830c059e Plug GTask leaks
The error-prone pattern seems to be:

  GTask *task = g_task_new (...);

  if (condition)
    {
      g_task_return_... (task, ...);
      /* need g_object_unref (task) here! */
      return;
    }

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
2024-08-05 14:38:23 +03:00
28 changed files with 532 additions and 33 deletions
+8 -1
View File
@@ -78,8 +78,15 @@ GdkColorState * gdk_color_state_new_for_cicp (const GdkCicp
GError **error);
static inline GdkColorState *
gdk_color_state_get_rendering_color_state (GdkColorState *self)
gdk_color_state_get_rendering_color_state (GdkColorState *self,
gboolean srgb)
{
if (srgb)
{
self = gdk_color_state_get_no_srgb_tf (self);
g_assert (self);
}
if (GDK_DEBUG_CHECK (HDR))
self = GDK_COLOR_STATE_REC2100_PQ;
+1 -4
View File
@@ -637,10 +637,7 @@ gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
else
*out_depth = GDK_MEMORY_U8;
if (*out_depth == GDK_MEMORY_U8_SRGB)
*out_color_state = gdk_color_state_get_no_srgb_tf (color_state);
else
*out_color_state = color_state;
*out_color_state = color_state;
#else
*out_color_state = gdk_color_state_get_srgb ();
*out_depth = GDK_MEMORY_U8;
+14
View File
@@ -1879,6 +1879,12 @@ 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);
g_print ("memory convert %s %s -> %s %s\n",
gdk_memory_format_get_name (src_format),
gdk_color_state_get_name (src_cs),
gdk_memory_format_get_name (dest_format),
gdk_color_state_get_name (dest_cs));
if (src_format == dest_format && gdk_color_state_equal (dest_cs, src_cs))
{
gsize bytes_per_row = src_desc->bytes_per_pixel * width;
@@ -1952,6 +1958,7 @@ gdk_memory_convert (guchar *dest_data,
if (func != NULL)
{
g_print ("convert format\n");
for (y = 0; y < height; y++)
{
func (dest_data, src_data, width);
@@ -1974,10 +1981,13 @@ gdk_memory_convert (guchar *dest_data,
needs_premultiply = src_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT && dest_desc->alpha != GDK_MEMORY_ALPHA_STRAIGHT;
}
g_print ("convert color %lu %lu\n", width, height);
for (y = 0; y < height; y++)
{
src_desc->to_float (tmp, src_data, width);
g_print ("after to_float: %f %f %f %f\n", tmp[0][0], tmp[0][1], tmp[0][2], tmp[0][3]);
if (needs_unpremultiply)
unpremultiply (tmp, width);
@@ -2159,6 +2169,10 @@ gdk_memory_convert_color_state (guchar *data,
if (gdk_color_state_equal (src_cs, dest_cs))
return;
g_print ("memory convert color state %s -> %s\n",
gdk_color_state_get_name (src_cs),
gdk_color_state_get_name (dest_cs));
if (format == GDK_MEMORY_B8G8R8A8_PREMULTIPLIED &&
src_cs == GDK_COLOR_STATE_SRGB &&
dest_cs == GDK_COLOR_STATE_SRGB_LINEAR)
+1 -4
View File
@@ -678,10 +678,7 @@ gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context,
cairo_region_union (region, priv->regions[priv->draw_index]);
if (priv->current_depth == GDK_MEMORY_U8_SRGB)
*out_color_state = gdk_color_state_get_no_srgb_tf (color_state);
else
*out_color_state = color_state;
*out_color_state = color_state;
*out_depth = priv->current_depth;
}
+3
View File
@@ -236,6 +236,7 @@ gdk_wayland_clipboard_read_async (GdkClipboard *clipboard,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("No compatible transfer format found"));
g_object_unref (task);
return;
}
/* offer formats should be empty if we have no offer */
@@ -246,6 +247,7 @@ gdk_wayland_clipboard_read_async (GdkClipboard *clipboard,
if (!g_unix_open_pipe (pipe_fd, O_CLOEXEC, &error))
{
g_task_return_error (task, error);
g_object_unref (task);
return;
}
@@ -253,6 +255,7 @@ gdk_wayland_clipboard_read_async (GdkClipboard *clipboard,
stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
close (pipe_fd[1]);
g_task_return_pointer (task, stream, g_object_unref);
g_object_unref (task);
}
static GInputStream *
+3
View File
@@ -203,6 +203,7 @@ gdk_wayland_drop_read_async (GdkDrop *drop,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("No compatible transfer format found"));
g_object_unref (task);
return;
}
@@ -211,6 +212,7 @@ gdk_wayland_drop_read_async (GdkDrop *drop,
if (!g_unix_open_pipe (pipe_fd, O_CLOEXEC, &error))
{
g_task_return_error (task, error);
g_object_unref (task);
return;
}
@@ -218,6 +220,7 @@ gdk_wayland_drop_read_async (GdkDrop *drop,
stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
close (pipe_fd[1]);
g_task_return_pointer (task, stream, g_object_unref);
g_object_unref (task);
}
static GInputStream *
+3
View File
@@ -335,6 +335,7 @@ gdk_wayland_primary_read_async (GdkClipboard *clipboard,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("No compatible transfer format found"));
g_object_unref (task);
return;
}
/* offer formats should be empty if we have no offer */
@@ -345,6 +346,7 @@ gdk_wayland_primary_read_async (GdkClipboard *clipboard,
if (!g_unix_open_pipe (pipe_fd, O_CLOEXEC, &error))
{
g_task_return_error (task, error);
g_object_unref (task);
return;
}
@@ -352,6 +354,7 @@ gdk_wayland_primary_read_async (GdkClipboard *clipboard,
stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
close (pipe_fd[1]);
g_task_return_pointer (task, stream, g_object_unref);
g_object_unref (task);
}
static GInputStream *
+9
View File
@@ -1016,6 +1016,7 @@ gdk_win32_drop_read_async (GdkDrop *drop,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("No compatible transfer format found"));
g_object_unref (task);
g_clear_pointer (&drop_win32->dropfiles_list, g_free);
return;
@@ -1025,6 +1026,7 @@ gdk_win32_drop_read_async (GdkDrop *drop,
drop_win32->dropfiles_list = NULL;
g_object_set_data (G_OBJECT (stream), "gdk-dnd-stream-contenttype", (gpointer) "text/uri-list");
g_task_return_pointer (task, stream, g_object_unref);
g_object_unref (task);
return;
}
@@ -1035,6 +1037,7 @@ gdk_win32_drop_read_async (GdkDrop *drop,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
_("GDK surface 0x%p is not registered as a drop target"), gdk_drop_get_surface (drop));
g_object_unref (task);
return;
}
@@ -1042,6 +1045,7 @@ gdk_win32_drop_read_async (GdkDrop *drop,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Target context record 0x%p has no data object"), tctx);
g_object_unref (task);
return;
}
@@ -1061,6 +1065,7 @@ gdk_win32_drop_read_async (GdkDrop *drop,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("No compatible transfer format found"));
g_object_unref (task);
return;
}
@@ -1080,6 +1085,7 @@ gdk_win32_drop_read_async (GdkDrop *drop,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
_("IDataObject_GetData (0x%x) failed, returning 0x%lx"), fmt.cfFormat, hr);
g_object_unref (task);
return;
}
@@ -1092,6 +1098,7 @@ gdk_win32_drop_read_async (GdkDrop *drop,
if (data == NULL)
{
ReleaseStgMedium (&storage);
g_object_unref (task);
return;
}
@@ -1112,12 +1119,14 @@ gdk_win32_drop_read_async (GdkDrop *drop,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Failed to transmute DnD data W32 format 0x%x to %p (%s)"), pair->w32format, pair->contentformat, pair->contentformat);
g_object_unref (task);
return;
}
stream = g_memory_input_stream_new_from_data (data, data_len, g_free);
g_object_set_data (G_OBJECT (stream), "gdk-dnd-stream-contenttype", (gpointer) pair->contentformat);
g_task_return_pointer (task, stream, g_object_unref);
g_object_unref (task);
}
static GInputStream *
+1
View File
@@ -797,6 +797,7 @@ gdk_x11_clipboard_read_async (GdkClipboard *clipboard,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("No compatible transfer format found"));
g_object_unref (task);
return;
}
+1
View File
@@ -233,6 +233,7 @@ gdk_x11_drop_read_async (GdkDrop *drop,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("No compatible transfer format found"));
g_object_unref (task);
return;
}
+101 -7
View File
@@ -33,6 +33,8 @@ struct _GskGpuDownloadOp
GskGpuOp op;
GskGpuImage *image;
GdkColorState *image_cs;
GdkColorState *download_cs;
gboolean allow_dmabuf;
GdkGpuDownloadOpCreateFunc create_func;
GskGpuDownloadFunc func;
@@ -53,8 +55,60 @@ gsk_gpu_download_op_finish (GskGpuOp *op)
if (self->create_func)
self->create_func (self);
g_print ("downloaded texture: %s %.4s depth %s format %s color state %s\n",
GDK_IS_DMABUF_TEXTURE (self->texture)
? "dmabuf"
: (GDK_IS_GL_TEXTURE (self->texture)
? "gl"
: "memory"),
GDK_IS_DMABUF_TEXTURE (self->texture)
? (char *) &gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (self->texture))->fourcc
: "",
gdk_memory_depth_get_name (gdk_memory_format_get_depth (gdk_texture_get_format (self->texture), FALSE)),
gdk_memory_format_get_name (gdk_texture_get_format (self->texture)),
gdk_color_state_get_name (gdk_texture_get_color_state (self->texture)));
if (!gdk_color_state_equal (gdk_texture_get_color_state (self->texture), self->download_cs))
{
GdkTextureDownloader *downloader;
GdkMemoryTextureBuilder *builder;
GBytes *bytes;
gsize stride;
GdkTexture *texture;
g_print ("converting rendered %s texture after download: %s -> %s\n",
GDK_IS_DMABUF_TEXTURE (self->texture) ? "dmabuf" :
(GDK_IS_GL_TEXTURE (self->texture) ? "gl" : "memory"),
gdk_color_state_get_name (gdk_texture_get_color_state (self->texture)),
gdk_color_state_get_name (self->download_cs));
downloader = gdk_texture_downloader_new (self->texture);
gdk_texture_downloader_set_format (downloader, gdk_texture_get_format (self->texture));
gdk_texture_downloader_set_color_state (downloader, self->download_cs);
bytes = gdk_texture_downloader_download_bytes (downloader, &stride);
gdk_texture_downloader_free (downloader);
builder = gdk_memory_texture_builder_new ();
gdk_memory_texture_builder_set_bytes (builder, bytes);
gdk_memory_texture_builder_set_stride (builder, stride);
gdk_memory_texture_builder_set_width (builder, gdk_texture_get_width (self->texture));
gdk_memory_texture_builder_set_height (builder, gdk_texture_get_height (self->texture));
gdk_memory_texture_builder_set_format (builder, gdk_texture_get_format (self->texture));
gdk_memory_texture_builder_set_color_state (builder, self->download_cs);
texture = gdk_memory_texture_builder_build (builder);
g_object_unref (builder);
g_set_object (&self->texture, texture);
g_bytes_unref (bytes);
g_object_unref (texture);
}
self->func (self->user_data, self->texture);
gdk_color_state_unref (self->image_cs);
gdk_color_state_unref (self->download_cs);
g_object_unref (self->texture);
g_object_unref (self->image);
g_clear_object (&self->buffer);
@@ -70,6 +124,7 @@ gsk_gpu_download_op_print (GskGpuOp *op,
gsk_gpu_print_op (string, indent, "download");
gsk_gpu_print_image (string, self->image);
gsk_gpu_print_string (string, gdk_color_state_get_name (self->download_cs));
gsk_gpu_print_newline (string);
}
@@ -118,6 +173,7 @@ gsk_gpu_download_op_vk_create (GskGpuDownloadOp *self)
guchar *data;
gsize width, height, stride;
GdkMemoryFormat format;
GdkMemoryTextureBuilder *builder;
data = gsk_gpu_buffer_map (self->buffer);
width = gsk_gpu_image_get_width (self->image);
@@ -125,11 +181,18 @@ gsk_gpu_download_op_vk_create (GskGpuDownloadOp *self)
format = gsk_gpu_image_get_format (self->image);
stride = width * gdk_memory_format_bytes_per_pixel (format);
bytes = g_bytes_new (data, stride * height);
self->texture = gdk_memory_texture_new (width,
height,
format,
bytes,
stride);
builder = gdk_memory_texture_builder_new ();
gdk_memory_texture_builder_set_bytes (builder, bytes);
gdk_memory_texture_builder_set_stride (builder, stride);
gdk_memory_texture_builder_set_width (builder, width);
gdk_memory_texture_builder_set_height (builder, height);
gdk_memory_texture_builder_set_format (builder, format);
gdk_memory_texture_builder_set_color_state (builder, self->image_cs);
self->texture = gdk_memory_texture_builder_build (builder);
g_object_unref (builder);
g_bytes_unref (bytes);
gsk_gpu_buffer_unmap (self->buffer, 0);
}
@@ -144,7 +207,17 @@ gsk_gpu_download_op_vk_command (GskGpuOp *op,
#ifdef HAVE_DMABUF
if (self->allow_dmabuf)
self->texture = gsk_vulkan_image_to_dmabuf_texture (GSK_VULKAN_IMAGE (self->image));
{
GdkColorState *cs;
if (gsk_gpu_image_get_flags (self->image) & GSK_GPU_IMAGE_SRGB)
cs = GDK_COLOR_STATE_SRGB;
else
cs = self->image_cs;
self->texture = gsk_vulkan_image_to_dmabuf_texture (GSK_VULKAN_IMAGE (self->image), cs);
}
if (self->texture)
{
GskGpuDevice *device = gsk_gpu_frame_get_device (frame);
@@ -295,10 +368,16 @@ gsk_gpu_download_op_gl_command (GskGpuOp *op,
GskGLTextureData *data;
GdkGLContext *context;
guint texture_id;
GdkColorState *cs;
context = GDK_GL_CONTEXT (gsk_gpu_frame_get_context (frame));
texture_id = gsk_gl_image_steal_texture (GSK_GL_IMAGE (self->image));
if (gsk_gpu_image_get_flags (self->image) & GSK_GPU_IMAGE_SRGB)
cs = GDK_COLOR_STATE_SRGB_LINEAR;
else
cs = self->image_cs;
#ifdef HAVE_DMABUF
if (self->allow_dmabuf)
{
@@ -317,12 +396,20 @@ gsk_gpu_download_op_gl_command (GskGpuOp *op,
gdk_dmabuf_texture_builder_set_width (db, gsk_gpu_image_get_width (self->image));
gdk_dmabuf_texture_builder_set_height (db, gsk_gpu_image_get_height (self->image));
self->texture = gdk_dmabuf_texture_builder_build (db, release_dmabuf_texture, texture, NULL);
gdk_dmabuf_texture_builder_set_color_state (db, cs);
g_print ("dmabuf downloader color state: %s\n", gdk_color_state_get_name (gdk_dmabuf_texture_builder_get_color_state (db)));
self->texture = gdk_dmabuf_texture_builder_build (db,
release_dmabuf_texture,
texture,
NULL);
g_object_unref (db);
if (self->texture)
return op->next;
else
g_print ("failed to build dmabuf texture\n");
}
g_free (texture);
@@ -343,6 +430,7 @@ gsk_gpu_download_op_gl_command (GskGpuOp *op,
gdk_gl_texture_builder_set_width (builder, gsk_gpu_image_get_width (self->image));
gdk_gl_texture_builder_set_height (builder, gsk_gpu_image_get_height (self->image));
gdk_gl_texture_builder_set_sync (builder, data->sync);
gdk_gl_texture_builder_set_color_state (builder, cs);
self->texture = gdk_gl_texture_builder_build (builder,
gsk_gl_texture_data_free,
@@ -367,6 +455,8 @@ static const GskGpuOpClass GSK_GPU_DOWNLOAD_OP_CLASS = {
void
gsk_gpu_download_op (GskGpuFrame *frame,
GskGpuImage *image,
GdkColorState *image_cs,
GdkColorState *download_cs,
gboolean allow_dmabuf,
GskGpuDownloadFunc func,
gpointer user_data)
@@ -377,6 +467,10 @@ gsk_gpu_download_op (GskGpuFrame *frame,
self->image = g_object_ref (image);
self->allow_dmabuf = allow_dmabuf;
self->image_cs = gdk_color_state_ref (image_cs);
self->download_cs = gdk_color_state_ref (download_cs);
self->func = func,
self->user_data = user_data;
}
+2
View File
@@ -9,6 +9,8 @@ typedef void (* GskGpuDownloadFunc) (gpointe
void gsk_gpu_download_op (GskGpuFrame *frame,
GskGpuImage *image,
GdkColorState *image_cs,
GdkColorState *download_cs,
gboolean allow_dmabuf,
GskGpuDownloadFunc func,
gpointer user_data);
+16 -1
View File
@@ -671,7 +671,20 @@ gsk_gpu_frame_record (GskGpuFrame *self,
}
if (texture)
gsk_gpu_download_op (self, target, TRUE, copy_texture, texture);
{
GdkColorState *image_cs;
GdkColorState *download_cs;
image_cs = gdk_color_state_get_rendering_color_state (target_color_state,
gsk_gpu_image_get_flags (target) & GSK_GPU_IMAGE_SRGB);
if (image_cs == GDK_COLOR_STATE_SRGB_LINEAR)
download_cs = GDK_COLOR_STATE_SRGB;
else
download_cs = image_cs;
gsk_gpu_download_op (self, target, target_color_state, download_cs, TRUE, copy_texture, texture);
}
}
static void
@@ -778,6 +791,8 @@ gsk_gpu_frame_download_texture (GskGpuFrame *self,
gsk_gpu_download_op (self,
image,
gdk_texture_get_color_state (texture),
color_state,
FALSE,
do_download,
g_memdup (&(Download) {
+15 -1
View File
@@ -1584,10 +1584,18 @@ gsk_gpu_node_processor_add_color_node (GskGpuNodeProcessor *self,
}
gdk_color_to_float (gsk_color_node_get_color2 (node), self->ccs, clear_color);
g_print ("node processor: add color via clear %s -> %s %f %f %f %f\n",
gdk_color_to_string (gsk_color_node_get_color2 (node)),
gdk_color_state_get_name (self->ccs),
clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
gsk_gpu_clear_op (self->frame, &int_clipped, clear_color);
return;
}
g_print ("node processor: add color %s -> %s\n",
gdk_color_to_string (gsk_color_node_get_color2 (node)),
gdk_color_state_get_name (self->ccs));
gsk_gpu_color_op (self->frame,
gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds),
self->ccs,
@@ -1615,6 +1623,10 @@ gsk_gpu_node_processor_add_first_color_node (GskGpuNodeProcessor *self,
return FALSE;
gdk_color_to_float (gsk_color_node_get_color2 (node), self->ccs, clear_color);
g_print ("node processor: add first color %s -> %s %f %f %f %f\n",
gdk_color_to_string (gsk_color_node_get_color2 (node)),
gdk_color_state_get_name (self->ccs),
clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
gsk_gpu_render_pass_begin_op (self->frame,
target,
clip,
@@ -3905,7 +3917,9 @@ gsk_gpu_node_processor_process (GskGpuFrame *frame,
clip,
viewport);
ccs = gdk_color_state_get_rendering_color_state (target_color_state);
ccs = gdk_color_state_get_rendering_color_state (target_color_state, gsk_gpu_image_get_flags (target) & GSK_GPU_IMAGE_SRGB);
g_print ("node processor: rendering color state %s\n", gdk_color_state_get_name (ccs));
if (gdk_color_state_equal (ccs, target_color_state))
{
+14 -9
View File
@@ -299,10 +299,7 @@ gsk_gpu_renderer_fallback_render_texture (GskGpuRenderer *self,
MIN (image_width, width - x),
MIN (image_height, height - y));
if (gsk_gpu_image_get_flags (image) & GSK_GPU_IMAGE_SRGB)
color_state = GDK_COLOR_STATE_SRGB_LINEAR;
else
color_state = GDK_COLOR_STATE_SRGB;
color_state = GDK_COLOR_STATE_SRGB;
frame = gsk_gpu_renderer_create_frame (self);
gsk_gpu_frame_render (frame,
@@ -352,6 +349,7 @@ gsk_gpu_renderer_render_texture (GskRenderer *renderer,
GdkTexture *texture;
graphene_rect_t rounded_viewport;
GdkColorState *color_state;
GdkMemoryDepth depth;
gsk_gpu_device_maybe_gc (priv->device);
@@ -361,18 +359,25 @@ gsk_gpu_renderer_render_texture (GskRenderer *renderer,
viewport->origin.y,
ceil (viewport->size.width),
ceil (viewport->size.height));
if (gsk_render_node_is_hdr (root))
color_state = GDK_COLOR_STATE_REC2100_PQ;
else
color_state = GDK_COLOR_STATE_SRGB;
depth = gdk_memory_depth_merge (gsk_render_node_get_preferred_depth (root),
gdk_color_state_get_depth (color_state));
image = gsk_gpu_device_create_download_image (priv->device,
gsk_render_node_get_preferred_depth (root),
depth,
rounded_viewport.size.width,
rounded_viewport.size.height);
if (image == NULL)
return gsk_gpu_renderer_fallback_render_texture (self, root, &rounded_viewport);
if (gsk_gpu_image_get_flags (image) & GSK_GPU_IMAGE_SRGB)
color_state = GDK_COLOR_STATE_SRGB_LINEAR;
else
color_state = GDK_COLOR_STATE_SRGB;
g_print ("render_texture: image depth %s, target color state %s\n",
gdk_memory_depth_get_name (depth), gdk_color_state_get_name (color_state));
frame = gsk_gpu_renderer_create_frame (self);
+3 -1
View File
@@ -1176,7 +1176,8 @@ gsk_vulkan_image_get_n_planes (GskVulkanImage *self,
}
GdkTexture *
gsk_vulkan_image_to_dmabuf_texture (GskVulkanImage *self)
gsk_vulkan_image_to_dmabuf_texture (GskVulkanImage *self,
GdkColorState *color_state)
{
GskGpuImage *image = GSK_GPU_IMAGE (self);
GdkDmabufTextureBuilder *builder;
@@ -1226,6 +1227,7 @@ gsk_vulkan_image_to_dmabuf_texture (GskVulkanImage *self)
gdk_dmabuf_texture_builder_set_display (builder, gsk_gpu_device_get_display (GSK_GPU_DEVICE (self->device)));
gdk_dmabuf_texture_builder_set_width (builder, gsk_gpu_image_get_width (image));
gdk_dmabuf_texture_builder_set_height (builder, gsk_gpu_image_get_height (image));
gdk_dmabuf_texture_builder_set_color_state (builder, color_state);
gdk_dmabuf_texture_builder_set_fourcc (builder, fourcc);
gdk_dmabuf_texture_builder_set_modifier (builder, properties.drmFormatModifier);
gdk_dmabuf_texture_builder_set_premultiplied (builder, !(gsk_gpu_image_get_flags (image) & GSK_GPU_IMAGE_STRAIGHT_ALPHA));
+2 -1
View File
@@ -44,7 +44,8 @@ GskGpuImage * gsk_vulkan_image_new_for_dmabuf (GskVulk
gsize height,
const GdkDmabuf *dmabuf,
gboolean premultiplied);
GdkTexture * gsk_vulkan_image_to_dmabuf_texture (GskVulkanImage *self);
GdkTexture * gsk_vulkan_image_to_dmabuf_texture (GskVulkanImage *self,
GdkColorState *color_state);
#endif
guchar * gsk_vulkan_image_get_data (GskVulkanImage *self,
+8 -2
View File
@@ -380,7 +380,7 @@ gsk_render_node_draw_ccs (GskRenderNode *node,
GdkColorState *ccs)
{
/* Check that the calling function did pass a correct color state */
g_assert (ccs == gdk_color_state_get_rendering_color_state (ccs));
g_assert (ccs == gdk_color_state_get_rendering_color_state (ccs, FALSE));
cairo_save (cr);
@@ -413,7 +413,7 @@ gsk_render_node_draw_with_color_state (GskRenderNode *node,
{
GdkColorState *ccs;
ccs = gdk_color_state_get_rendering_color_state (color_state);
ccs = gdk_color_state_get_rendering_color_state (color_state, FALSE);
if (gdk_color_state_equal (color_state, ccs))
{
@@ -827,6 +827,12 @@ gsk_render_node_get_preferred_depth (const GskRenderNode *node)
return node->preferred_depth;
}
gboolean
gsk_render_node_is_hdr (const GskRenderNode *node)
{
return node->is_hdr;
}
/* Whether we need an offscreen to handle opacity correctly for this node.
* We don't if there is only one drawing node inside (could be child
* node, or grandchild, or...).
+38 -1
View File
@@ -91,6 +91,17 @@ my_color_stops_get_depth (const GskColorStop *stops,
return gdk_color_state_get_depth (GDK_COLOR_STATE_SRGB);
}
static inline gboolean
color_state_is_hdr (GdkColorState *color_state)
{
GdkColorState *rendering_cs;
rendering_cs = gdk_color_state_get_rendering_color_state (color_state, FALSE);
return rendering_cs != GDK_COLOR_STATE_SRGB &&
rendering_cs != GDK_COLOR_STATE_SRGB_LINEAR;
}
/* apply a rectangle that bounds @rect in
* pixel-aligned device coordinates.
*
@@ -316,6 +327,7 @@ gsk_color_node_new2 (const GdkColor *color,
node->offscreen_for_opacity = FALSE;
node->fully_opaque = gdk_color_is_opaque (color);
node->preferred_depth = gdk_color_get_depth (color);
node->is_hdr = color_state_is_hdr (color->color_state);
gdk_color_init_copy (&self->color, color);
@@ -1978,6 +1990,7 @@ gsk_texture_node_new (GdkTexture *texture,
node = (GskRenderNode *) self;
node->offscreen_for_opacity = FALSE;
node->fully_opaque = gdk_memory_format_alpha (gdk_texture_get_format (texture)) == GDK_MEMORY_ALPHA_OPAQUE;
node->is_hdr = color_state_is_hdr (gdk_texture_get_color_state (texture));
self->texture = g_object_ref (texture);
gsk_rect_init_from_rect (&node->bounds, bounds);
@@ -2200,6 +2213,7 @@ gsk_texture_scale_node_new (GdkTexture *texture,
node->fully_opaque = gdk_memory_format_alpha (gdk_texture_get_format (texture)) == GDK_MEMORY_ALPHA_OPAQUE &&
bounds->size.width == floor (bounds->size.width) &&
bounds->size.height == floor (bounds->size.height);
node->is_hdr = color_state_is_hdr (gdk_texture_get_color_state (texture));
self->texture = g_object_ref (texture);
gsk_rect_init_from_rect (&node->bounds, bounds);
@@ -3481,6 +3495,7 @@ gsk_container_node_new (GskRenderNode **children,
{
graphene_rect_t child_opaque;
gboolean have_opaque;
gboolean is_hdr;
self->children = g_malloc_n (n_children, sizeof (GskRenderNode *));
@@ -3489,6 +3504,7 @@ gsk_container_node_new (GskRenderNode **children,
node->preferred_depth = children[0]->preferred_depth;
gsk_rect_init_from_rect (&node->bounds, &(children[0]->bounds));
have_opaque = gsk_render_node_get_opaque_rect (self->children[0], &self->opaque);
is_hdr = gsk_render_node_is_hdr (self->children[0]);
for (guint i = 1; i < n_children; i++)
{
@@ -3507,10 +3523,13 @@ gsk_container_node_new (GskRenderNode **children,
have_opaque = TRUE;
}
}
is_hdr |= gsk_render_node_is_hdr (self->children[i]);
}
node->offscreen_for_opacity = node->offscreen_for_opacity || !self->disjoint;
}
node->is_hdr = is_hdr;
}
return node;
}
@@ -3805,6 +3824,7 @@ gsk_transform_node_new (GskRenderNode *child,
&node->bounds);
node->preferred_depth = gsk_render_node_get_preferred_depth (child);
node->is_hdr = gsk_render_node_is_hdr (child);
return node;
}
@@ -3957,6 +3977,7 @@ gsk_opacity_node_new (GskRenderNode *child,
gsk_rect_init_from_rect (&node->bounds, &child->bounds);
node->preferred_depth = gsk_render_node_get_preferred_depth (child);
node->is_hdr = gsk_render_node_is_hdr (child);
return node;
}
@@ -4190,6 +4211,7 @@ gsk_color_matrix_node_new (GskRenderNode *child,
gsk_rect_init_from_rect (&node->bounds, &child->bounds);
node->preferred_depth = gsk_render_node_get_preferred_depth (child);
node->is_hdr = gsk_render_node_is_hdr (child);
return node;
}
@@ -4497,6 +4519,7 @@ gsk_repeat_node_new (const graphene_rect_t *bounds,
}
node->preferred_depth = gsk_render_node_get_preferred_depth (child);
node->is_hdr = gsk_render_node_is_hdr (child);
node->fully_opaque = child->fully_opaque && gsk_rect_contains_rect (&child->bounds, &self->child_bounds);
return node;
@@ -4664,6 +4687,7 @@ gsk_clip_node_new (GskRenderNode *child,
gsk_rect_intersection (&self->clip, &child->bounds, &node->bounds);
node->preferred_depth = gsk_render_node_get_preferred_depth (child);
node->is_hdr = gsk_render_node_is_hdr (child);
return node;
}
@@ -4847,6 +4871,7 @@ gsk_rounded_clip_node_new (GskRenderNode *child,
gsk_rect_intersection (&self->clip.bounds, &child->bounds, &node->bounds);
node->preferred_depth = gsk_render_node_get_preferred_depth (child);
node->is_hdr = gsk_render_node_is_hdr (child);
return node;
}
@@ -5017,6 +5042,7 @@ gsk_fill_node_new (GskRenderNode *child,
node = (GskRenderNode *) self;
node->offscreen_for_opacity = child->offscreen_for_opacity;
node->preferred_depth = gsk_render_node_get_preferred_depth (child);
node->is_hdr = gsk_render_node_is_hdr (child);
self->child = gsk_render_node_ref (child);
self->path = gsk_path_ref (path);
@@ -5227,6 +5253,7 @@ gsk_stroke_node_new (GskRenderNode *child,
node = (GskRenderNode *) self;
node->offscreen_for_opacity = child->offscreen_for_opacity;
node->preferred_depth = gsk_render_node_get_preferred_depth (child);
node->is_hdr = gsk_render_node_is_hdr (child);
self->child = gsk_render_node_ref (child);
self->path = gsk_path_ref (path);
@@ -5504,6 +5531,7 @@ gsk_shadow_node_new (GskRenderNode *child,
gsk_shadow_node_get_bounds (self, &node->bounds);
node->preferred_depth = gsk_render_node_get_preferred_depth (child);
node->is_hdr = gsk_render_node_is_hdr (child);
for (i = 0; i < n_shadows; i++)
{
node->preferred_depth = gdk_memory_depth_merge (node->preferred_depth,
@@ -5727,6 +5755,8 @@ gsk_blend_node_new (GskRenderNode *bottom,
node->preferred_depth = gdk_memory_depth_merge (gsk_render_node_get_preferred_depth (bottom),
gsk_render_node_get_preferred_depth (top));
node->is_hdr = gsk_render_node_is_hdr (bottom) ||
gsk_render_node_is_hdr (top);
return node;
}
@@ -5914,6 +5944,8 @@ gsk_cross_fade_node_new (GskRenderNode *start,
node->preferred_depth = gdk_memory_depth_merge (gsk_render_node_get_preferred_depth (start),
gsk_render_node_get_preferred_depth (end));
node->is_hdr = gsk_render_node_is_hdr (start) ||
gsk_render_node_is_hdr (end);
return node;
}
@@ -6566,6 +6598,7 @@ gsk_blur_node_new (GskRenderNode *child,
graphene_rect_inset (&self->render_node.bounds, - clip_radius, - clip_radius);
node->preferred_depth = gsk_render_node_get_preferred_depth (child);
node->is_hdr = gsk_render_node_is_hdr (child);
return node;
}
@@ -6802,6 +6835,8 @@ gsk_mask_node_new (GskRenderNode *source,
self->render_node.bounds = *graphene_rect_zero ();
self->render_node.preferred_depth = gsk_render_node_get_preferred_depth (source);
self->render_node.is_hdr = gsk_render_node_is_hdr (source) ||
gsk_render_node_is_hdr (mask);
return &self->render_node;
}
@@ -6980,6 +7015,7 @@ gsk_debug_node_new (GskRenderNode *child,
gsk_rect_init_from_rect (&node->bounds, &child->bounds);
node->preferred_depth = gsk_render_node_get_preferred_depth (child);
self->render_node.is_hdr = gsk_render_node_is_hdr (child);
return node;
}
@@ -7402,6 +7438,7 @@ gsk_subsurface_node_new (GskRenderNode *child,
gsk_rect_init_from_rect (&node->bounds, &child->bounds);
node->preferred_depth = gsk_render_node_get_preferred_depth (child);
node->is_hdr = gsk_render_node_is_hdr (child);
return node;
}
+2
View File
@@ -36,6 +36,7 @@ struct _GskRenderNode
guint preferred_depth : GDK_MEMORY_DEPTH_BITS;
guint offscreen_for_opacity : 1;
guint fully_opaque : 1;
guint is_hdr : 1;
};
typedef struct
@@ -106,6 +107,7 @@ void gsk_transform_node_get_translate (const GskRenderNode
float *dx,
float *dy);
GdkMemoryDepth gsk_render_node_get_preferred_depth (const GskRenderNode *node) G_GNUC_PURE;
gboolean gsk_render_node_is_hdr (const GskRenderNode *node) G_GNUC_PURE;
gboolean gsk_container_node_is_disjoint (const GskRenderNode *node) G_GNUC_PURE;
+1
View File
@@ -222,6 +222,7 @@ gtk_color_picker_win32_pick (GtkColorPicker *cp,
G_IO_ERROR,
G_IO_ERROR_FAILED,
"Cannot capture the mouse pointer");
g_object_unref (picker->task);
return;
}
+3
View File
@@ -485,6 +485,7 @@ gtk_file_launcher_launch (GtkFileLauncher *self,
g_task_return_new_error (task,
GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_FAILED,
"No file to launch");
g_object_unref (task);
return;
}
@@ -576,6 +577,7 @@ gtk_file_launcher_open_containing_folder (GtkFileLauncher *self,
g_task_return_new_error (task,
GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_FAILED,
"No file to open");
g_object_unref (task);
return;
}
@@ -584,6 +586,7 @@ gtk_file_launcher_open_containing_folder (GtkFileLauncher *self,
g_task_return_new_error (task,
GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_FAILED,
"Operation not supported on non-native files");
g_object_unref (task);
return;
}
+2
View File
@@ -292,6 +292,7 @@ gtk_uri_launcher_launch (GtkUriLauncher *self,
g_task_return_new_error (task,
GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_FAILED,
"No uri to launch");
g_object_unref (task);
return;
}
@@ -301,6 +302,7 @@ gtk_uri_launcher_launch (GtkUriLauncher *self,
GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_FAILED,
"%s is not a valid uri: %s", self->uri, error->message);
g_error_free (error);
g_object_unref (task);
return;
}
+84 -1
View File
@@ -1,6 +1,7 @@
#include <gdk/gdk.h>
#include <gtk.h>
#include "gdkcolorstateprivate.h"
#include "gdkcolorprivate.h"
#include "gdkdebugprivate.h"
#include <math.h>
#include "gdkcolordefs.h"
@@ -158,9 +159,88 @@ test_color_mislabel (void)
g_assert_true (red1 != red2);
}
static void
test_rendering_colorstate (void)
{
struct {
GdkColorState *surface;
gboolean srgb;
GdkColorState *rendering;
} tests[] = {
{ GDK_COLOR_STATE_SRGB, 0, GDK_COLOR_STATE_SRGB },
{ GDK_COLOR_STATE_SRGB, 1, GDK_COLOR_STATE_SRGB_LINEAR },
{ GDK_COLOR_STATE_SRGB_LINEAR, 0, GDK_COLOR_STATE_SRGB_LINEAR },
{ GDK_COLOR_STATE_SRGB_LINEAR, 1, GDK_COLOR_STATE_SRGB_LINEAR },
{ GDK_COLOR_STATE_REC2100_PQ, 0, GDK_COLOR_STATE_REC2100_PQ },
{ GDK_COLOR_STATE_REC2100_PQ, 1, GDK_COLOR_STATE_SRGB_LINEAR },
{ GDK_COLOR_STATE_REC2100_LINEAR, 0, GDK_COLOR_STATE_REC2100_LINEAR },
{ GDK_COLOR_STATE_REC2100_LINEAR, 1, GDK_COLOR_STATE_SRGB_LINEAR },
};
if (GDK_DEBUG_CHECK (HDR) || GDK_DEBUG_CHECK (LINEAR))
{
g_test_skip ("Skip because GDK_DEBUG flags hdr or linear are set");
return;
}
for (int i = 0; i < G_N_ELEMENTS (tests); i++)
{
GdkColorState *res = gdk_color_state_get_rendering_color_state (tests[i].surface, tests[i].srgb);
g_assert_true (gdk_color_state_equal (res, tests[i].rendering));
}
}
static void
test_color_conversion (void)
{
GdkColor color;
GdkColor color2;
GdkColor color3;
gdk_color_init (&color, GDK_COLOR_STATE_REC2100_PQ, (float[4]) { 0, 0.5, 1, 1 });
gdk_color_convert (&color2, GDK_COLOR_STATE_REC2100_LINEAR, &color);
g_assert_cmpfloat_with_epsilon (0, color2.values[0], 0.005);
g_assert_cmpfloat_with_epsilon (0.45, color2.values[1], 0.005);
g_assert_cmpfloat_with_epsilon (49.26, color2.values[2], 0.005);
g_assert_cmpfloat_with_epsilon (1, color2.values[3], 0.005);
gdk_color_convert (&color3, GDK_COLOR_STATE_REC2100_PQ, &color2);
g_assert_cmpfloat_with_epsilon (color3.values[0], color.values[0], 0.005);
g_assert_cmpfloat_with_epsilon (color3.values[1], color.values[1], 0.005);
g_assert_cmpfloat_with_epsilon (color3.values[2], color.values[2], 0.005);
g_assert_cmpfloat_with_epsilon (color3.values[3], color.values[3], 0.005);
gdk_color_finish (&color);
gdk_color_finish (&color2);
gdk_color_finish (&color3);
gdk_color_init (&color, GDK_COLOR_STATE_SRGB, (float[4]) { 0, 0.5, 1, 1 });
gdk_color_convert (&color2, GDK_COLOR_STATE_REC2100_LINEAR, &color);
g_assert_cmpfloat_with_epsilon (0.114, color2.values[0], 0.005);
g_assert_cmpfloat_with_epsilon (0.208, color2.values[1], 0.005);
g_assert_cmpfloat_with_epsilon (0.914, color2.values[2], 0.005);
g_assert_cmpfloat_with_epsilon (1, color2.values[3], 0.005);
gdk_color_convert (&color3, GDK_COLOR_STATE_SRGB, &color2);
g_assert_cmpfloat_with_epsilon (color3.values[0], color.values[0], 0.005);
g_assert_cmpfloat_with_epsilon (color3.values[1], color.values[1], 0.005);
g_assert_cmpfloat_with_epsilon (color3.values[2], color.values[2], 0.005);
g_assert_cmpfloat_with_epsilon (color3.values[3], color.values[3], 0.005);
gdk_color_finish (&color);
gdk_color_finish (&color2);
gdk_color_finish (&color3);
}
int
main (int argc, char *argv[])
{
gtk_init ();
(g_test_init) (&argc, &argv, NULL);
for (guint i = 0; i < G_N_ELEMENTS (transfers); i++)
@@ -181,7 +261,10 @@ main (int argc, char *argv[])
g_test_add_func ("/colorstate/matrix/srgb_to_rec2020", test_srgb_to_rec2020);
g_test_add_func ("/colorstate/matrix/rec2020_to_srgb", test_rec2020_to_srgb);
g_test_add_func ("/colorstate/rendering", test_rendering_colorstate);
g_test_add_func ("/color/mislabel", test_color_mislabel);
g_test_add_func ("/color/conversion", test_color_conversion);
return g_test_run ();
}
@@ -0,0 +1,4 @@
color {
bounds: 0 0 50 50;
color: color(rec2100-pq 1 0 0 / 0.2);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

+2
View File
@@ -46,6 +46,7 @@ compare_render_tests = [
'color-matrix-identity',
'color-matrix-merge',
'color-matrix-parsing',
'color-pq-transparency',
'color-states',
'conic-gradient-with-64-colorstops',
'container-single-child-offscreen-for-opacity',
@@ -530,6 +531,7 @@ tests = [
[ 'path', [ 'path-utils.c' ], [ 'flaky'] ],
[ 'path-special-cases' ],
[ 'scaling' ],
[ 'rendertexture' ],
]
test_cargs = []
+191
View File
@@ -0,0 +1,191 @@
#include <gtk/gtk.h>
enum {
GDK_COLOR_STATE_SRGB,
GDK_COLOR_STATE_SRGB_LINEAR,
GDK_COLOR_STATE_REC2100_PQ,
GDK_COLOR_STATE_REC2100_LINEAR,
};
typedef struct {
const char *renderer;
const char *debug;
gboolean hdr_content;
guint expected;
} TextureTest;
static TextureTest tests[] = {
{ "ngl", "", 0, GDK_COLOR_STATE_SRGB },
{ "ngl", "", 1, GDK_COLOR_STATE_REC2100_PQ },
{ "ngl", "linear", 0, GDK_COLOR_STATE_SRGB },
{ "ngl", "linear", 1, GDK_COLOR_STATE_REC2100_LINEAR },
{ "ngl", "hdr", 0, GDK_COLOR_STATE_REC2100_PQ },
{ "ngl", "hdr", 1, GDK_COLOR_STATE_REC2100_PQ },
{ "ngl", "hdr:linear", 0, GDK_COLOR_STATE_REC2100_LINEAR },
{ "ngl", "hdr:linear", 1, GDK_COLOR_STATE_REC2100_LINEAR },
{ "vulkan", "", 0, GDK_COLOR_STATE_SRGB },
{ "vulkan", "", 1, GDK_COLOR_STATE_REC2100_PQ },
{ "vulkan", "linear", 0, GDK_COLOR_STATE_SRGB },
{ "vulkan", "linear", 1, GDK_COLOR_STATE_REC2100_LINEAR },
{ "vulkan", "hdr", 0, GDK_COLOR_STATE_REC2100_PQ },
{ "vulkan", "hdr", 1, GDK_COLOR_STATE_REC2100_PQ },
{ "vulkan", "hdr:linear", 0, GDK_COLOR_STATE_REC2100_LINEAR },
{ "vulkan", "hdr:linear", 1, GDK_COLOR_STATE_REC2100_LINEAR },
};
static GdkColorState *
get_color_state (guint id)
{
switch (id)
{
case GDK_COLOR_STATE_SRGB: return gdk_color_state_get_srgb ();
case GDK_COLOR_STATE_SRGB_LINEAR: return gdk_color_state_get_srgb_linear ();
case GDK_COLOR_STATE_REC2100_PQ: return gdk_color_state_get_rec2100_pq ();
case GDK_COLOR_STATE_REC2100_LINEAR: return gdk_color_state_get_rec2100_linear ();
default: g_assert_not_reached ();
}
}
static const char *
color_state_name (GdkColorState *cs)
{
if (cs == gdk_color_state_get_srgb ())
return "srgb";
else if (cs == gdk_color_state_get_srgb_linear ())
return "srgb-linear";
else if (cs == gdk_color_state_get_rec2100_pq ())
return "rec2100-pq";
else if (cs == gdk_color_state_get_rec2100_linear ())
return "rec2100-linear";
else
return "???";
}
static void
test_render_texture (gconstpointer testdata)
{
const TextureTest *test = testdata;
if (g_test_subprocess ())
{
GError *error = NULL;
const char *text;
GBytes *bytes;
GskRenderNode *node;
GskRenderer *renderer;
GdkTexture *texture;
GdkTextureDownloader *downloader;
GdkColorState *expected = get_color_state (test->expected);
gtk_init ();
text = test->hdr_content
? "color { color: color(rec2100-pq 1 0.5 0); }"
: "color { color: color(srgb 0 0.5 1); }";
bytes = g_bytes_new_static (text, strlen (text));
node = gsk_render_node_deserialize (bytes, NULL, NULL);
g_bytes_unref (bytes);
g_assert_nonnull (node);
if (strcmp (test->renderer, "ngl") == 0)
renderer = gsk_ngl_renderer_new ();
else if (strcmp (test->renderer, "vulkan") == 0)
renderer = gsk_vulkan_renderer_new ();
else
g_assert_not_reached ();
gsk_renderer_realize_for_display (renderer, gdk_display_get_default (), &error);
g_assert_no_error (error);
texture = gsk_renderer_render_texture (renderer, node, &GRAPHENE_RECT_INIT (0, 0, 1, 1));
if (!gdk_color_state_equal (expected, gdk_texture_get_color_state (texture)))
{
g_print ("test: expected %s, got %s\n",
color_state_name (expected),
color_state_name (gdk_texture_get_color_state (texture)));
exit (1);
}
else
{
g_print ("test: got color state %s\n",
color_state_name (gdk_texture_get_color_state (texture)));
}
g_assert_true (gdk_texture_get_width (texture) == 1);
g_assert_true (gdk_texture_get_height (texture) == 1);
downloader = gdk_texture_downloader_new (texture);
gdk_texture_downloader_set_format (downloader, GDK_MEMORY_R32G32B32A32_FLOAT);
/* Convert the data to the colorstate we used in the node */
if (test->hdr_content)
gdk_texture_downloader_set_color_state (downloader, gdk_color_state_get_rec2100_pq ());
else
gdk_texture_downloader_set_color_state (downloader, gdk_color_state_get_srgb ());
float data[4];
gdk_texture_downloader_download_into (downloader, (guchar *) data, 4 * sizeof (float));
gdk_texture_downloader_free (downloader);
g_print ("test: got %s content: %f %f %f %f\n",
test->hdr_content ? "rec2100-pq" : "srgb",
data[0], data[1], data[2], data[3]);
if (test->hdr_content)
{
g_assert_cmpfloat_with_epsilon (data[0], 1, 0.005);
g_assert_cmpfloat_with_epsilon (data[1], 0.5, 0.005);
g_assert_cmpfloat_with_epsilon (data[2], 0, 0.005);
g_assert_cmpfloat_with_epsilon (data[3], 1, 0.005);
}
else
{
g_assert_cmpfloat_with_epsilon (data[0], 0, 0.005);
g_assert_cmpfloat_with_epsilon (data[1], 0.5, 0.005);
g_assert_cmpfloat_with_epsilon (data[2], 1, 0.005);
g_assert_cmpfloat_with_epsilon (data[3], 1, 0.005);
}
gsk_render_node_unref (node);
gsk_renderer_unrealize (renderer);
g_object_unref (renderer);
return;
}
char **envp = g_get_environ ();
const char *str = g_getenv ("GDK_DEBUG") ? g_getenv ("GDK_DEBUG") : "";
char *str2 = g_strconcat (test->debug, test->debug[0] && str[0] ? ":" : "", str, NULL);
envp = g_environ_setenv (g_steal_pointer (&envp), "GDK_DEBUG", str2, TRUE);
g_free (str2);
g_test_trap_subprocess_with_envp (NULL, (const char * const *) envp, 0, G_TEST_SUBPROCESS_INHERIT_STDOUT | G_TEST_SUBPROCESS_INHERIT_STDERR);
if (!g_test_trap_has_passed ())
g_test_fail ();
}
int
main (int argc, char *argv[])
{
gtk_init ();
g_test_init (&argc, &argv, NULL);
for (int i = 0; i < G_N_ELEMENTS (tests); i++)
{
TextureTest *test = &tests[i];
char *path;
path = g_strconcat ("/rendertexture",
"/renderer:", test->renderer,
"/content:", test->hdr_content ? "hdr" : "sdr",
"/flags:", test->debug[0] ? test->debug : "none", NULL);
g_test_add_data_func (path, test, test_render_texture);
g_free (path);
}
return g_test_run ();
}