Compare commits

...

14 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
18 changed files with 461 additions and 33 deletions

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;

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;

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)

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;
}

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;
}

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);

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) {

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))
{

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);

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));

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,

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))
{

View File

@@ -96,7 +96,7 @@ color_state_is_hdr (GdkColorState *color_state)
{
GdkColorState *rendering_cs;
rendering_cs = gdk_color_state_get_rendering_color_state (color_state);
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;

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 ();
}

View File

@@ -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

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 = []

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 ();
}