gpu: Pass compositing color states around

Make the node processor and the pattern writer track the current
compositing color state. Color state nodes change it. We pass
the surface color state down via the frame apis.
This commit is contained in:
Matthias Clasen
2024-06-08 21:33:56 -04:00
parent 5ab831215e
commit 6b76c13bcc
5 changed files with 88 additions and 12 deletions

View File

@@ -561,6 +561,7 @@ copy_texture (gpointer user_data,
static void
gsk_gpu_frame_record_rect (GskGpuFrame *self,
GskGpuImage *target,
GdkColorState *target_color_state,
const cairo_rectangle_int_t *clip,
GskRenderNode *node,
const graphene_rect_t *viewport)
@@ -572,6 +573,7 @@ gsk_gpu_frame_record_rect (GskGpuFrame *self,
gsk_gpu_node_processor_process (self,
target,
target_color_state,
clip,
node,
viewport);
@@ -585,6 +587,7 @@ static void
gsk_gpu_frame_record (GskGpuFrame *self,
gint64 timestamp,
GskGpuImage *target,
GdkColorState *target_color_state,
const cairo_region_t *clip,
GskRenderNode *node,
const graphene_rect_t *viewport,
@@ -603,13 +606,14 @@ gsk_gpu_frame_record (GskGpuFrame *self,
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (clip, i, &rect);
gsk_gpu_frame_record_rect (self, target, &rect, node, viewport);
gsk_gpu_frame_record_rect (self, target, target_color_state, &rect, node, viewport);
}
}
else
{
gsk_gpu_frame_record_rect (self,
target,
target_color_state,
&(cairo_rectangle_int_t) {
0, 0,
gsk_gpu_image_get_width (target),
@@ -656,6 +660,7 @@ void
gsk_gpu_frame_render (GskGpuFrame *self,
gint64 timestamp,
GskGpuImage *target,
GdkColorState *target_color_state,
const cairo_region_t *region,
GskRenderNode *node,
const graphene_rect_t *viewport,
@@ -663,7 +668,7 @@ gsk_gpu_frame_render (GskGpuFrame *self,
{
gsk_gpu_frame_cleanup (self);
gsk_gpu_frame_record (self, timestamp, target, region, node, viewport, texture);
gsk_gpu_frame_record (self, timestamp, target, target_color_state, region, node, viewport, texture);
gsk_gpu_frame_submit (self);
}

View File

@@ -75,6 +75,7 @@ void gsk_gpu_frame_wait (GskGpuF
void gsk_gpu_frame_render (GskGpuFrame *self,
gint64 timestamp,
GskGpuImage *target,
GdkColorState *target_color_state,
const cairo_region_t *region,
GskRenderNode *node,
const graphene_rect_t *viewport,

View File

@@ -120,6 +120,7 @@ struct _GskGpuNodeProcessor
float opacity;
GskGpuGlobals pending_globals;
GdkColorState *color_state;
};
#define GDK_ARRAY_NAME pattern_buffer
@@ -141,6 +142,7 @@ struct _GskGpuPatternWriter
guint stack;
PatternBuffer buffer;
GdkColorState *color_state;
};
static void gsk_gpu_node_processor_add_node (GskGpuNodeProcessor *self,
@@ -153,6 +155,7 @@ gsk_gpu_node_processor_finish (GskGpuNodeProcessor *self)
{
g_clear_pointer (&self->modelview, gsk_transform_unref);
g_clear_object (&self->desc);
g_clear_pointer (&self->color_state, gdk_color_state_unref);
}
static void
@@ -160,6 +163,7 @@ gsk_gpu_node_processor_init (GskGpuNodeProcessor *self,
GskGpuFrame *frame,
GskGpuDescriptors *desc,
GskGpuImage *target,
GdkColorState *color_state,
const cairo_rectangle_int_t *clip,
const graphene_rect_t *viewport)
{
@@ -202,6 +206,8 @@ gsk_gpu_node_processor_init (GskGpuNodeProcessor *self,
-viewport->origin.y);
self->opacity = 1.0;
self->pending_globals = GSK_GPU_GLOBAL_MATRIX | GSK_GPU_GLOBAL_SCALE | GSK_GPU_GLOBAL_CLIP | GSK_GPU_GLOBAL_SCISSOR | GSK_GPU_GLOBAL_BLEND;
self->color_state = gdk_color_state_ref (color_state);
}
static void
@@ -338,6 +344,7 @@ gsk_gpu_node_processor_init_draw (GskGpuNodeProcessor *self,
GskGpuFrame *frame,
GdkMemoryDepth depth,
const graphene_vec2_t *scale,
GdkColorState *color_state,
const graphene_rect_t *viewport)
{
GskGpuImage *image;
@@ -359,6 +366,7 @@ gsk_gpu_node_processor_init_draw (GskGpuNodeProcessor *self,
frame,
NULL,
image,
color_state,
&area,
viewport);
@@ -384,6 +392,7 @@ gsk_gpu_node_processor_finish_draw (GskGpuNodeProcessor *self,
void
gsk_gpu_node_processor_process (GskGpuFrame *frame,
GskGpuImage *target,
GdkColorState *target_color_state,
const cairo_rectangle_int_t *clip,
GskRenderNode *node,
const graphene_rect_t *viewport)
@@ -394,6 +403,7 @@ gsk_gpu_node_processor_process (GskGpuFrame *frame,
frame,
NULL,
target,
target_color_state,
clip,
viewport);
@@ -406,6 +416,7 @@ static void
gsk_gpu_pattern_writer_init (GskGpuPatternWriter *self,
GskGpuFrame *frame,
const graphene_vec2_t *scale,
GdkColorState *color_state,
const graphene_point_t *offset,
const graphene_rect_t *bounds)
{
@@ -419,6 +430,8 @@ gsk_gpu_pattern_writer_init (GskGpuPatternWriter *self,
self->scale = *scale;
self->stack = 0;
self->color_state = gdk_color_state_ref (color_state);
pattern_buffer_init (&self->buffer);
}
@@ -546,6 +559,7 @@ gsk_gpu_pattern_writer_finish (GskGpuPatternWriter *self)
pattern_buffer_clear (&self->buffer);
g_assert (self->stack == 0);
g_clear_object (&self->desc);
g_clear_pointer (&self->color_state, gdk_color_state_unref);
}
static gboolean
@@ -742,6 +756,7 @@ gsk_gpu_node_processor_image_op (GskGpuNodeProcessor *self,
static GskGpuImage *
gsk_gpu_node_processor_create_offscreen (GskGpuFrame *frame,
const graphene_vec2_t *scale,
GdkColorState *color_state,
const graphene_rect_t *viewport,
GskRenderNode *node)
{
@@ -752,6 +767,7 @@ gsk_gpu_node_processor_create_offscreen (GskGpuFrame *frame,
frame,
gsk_render_node_get_preferred_depth (node),
scale,
color_state,
viewport);
if (image == NULL)
return NULL;
@@ -789,6 +805,7 @@ static GskGpuImage *
gsk_gpu_get_node_as_image (GskGpuFrame *frame,
const graphene_rect_t *clip_bounds,
const graphene_vec2_t *scale,
GdkColorState *color_state,
GskRenderNode *node,
graphene_rect_t *out_bounds)
{
@@ -833,6 +850,7 @@ gsk_gpu_get_node_as_image (GskGpuFrame *frame,
GSK_DEBUG (FALLBACK, "Offscreening node '%s'", g_type_name_from_instance ((GTypeInstance *) node));
result = gsk_gpu_node_processor_create_offscreen (frame,
scale,
color_state,
clip_bounds,
node);
@@ -843,6 +861,7 @@ gsk_gpu_get_node_as_image (GskGpuFrame *frame,
static GskGpuImage *
gsk_gpu_node_processor_ensure_image (GskGpuFrame *frame,
GskGpuImage *image,
GdkColorState *color_state,
GskGpuImageFlags required_flags,
GskGpuImageFlags disallowed_flags)
{
@@ -895,6 +914,7 @@ gsk_gpu_node_processor_ensure_image (GskGpuFrame *frame,
frame,
NULL,
copy,
color_state,
&(cairo_rectangle_int_t) { 0, 0, width, height },
&rect);
@@ -968,6 +988,7 @@ gsk_gpu_node_processor_get_node_as_image (GskGpuNodeProcessor *self,
image = gsk_gpu_get_node_as_image (self->frame,
&clip,
&self->scale,
self->color_state,
node,
out_bounds);
if (image == NULL)
@@ -975,6 +996,7 @@ gsk_gpu_node_processor_get_node_as_image (GskGpuNodeProcessor *self,
ensure = gsk_gpu_node_processor_ensure_image (self->frame,
image,
self->color_state,
required_flags,
disallowed_flags);
@@ -1026,6 +1048,7 @@ gsk_gpu_node_processor_blur_op (GskGpuNodeProcessor *self,
self->frame,
source_depth,
&self->scale,
self->color_state,
&intermediate_rect);
gsk_gpu_node_processor_sync_globals (&other, 0);
@@ -1206,6 +1229,7 @@ gsk_gpu_node_processor_try_node_as_pattern (GskGpuNodeProcessor *self,
gsk_gpu_pattern_writer_init (&writer,
self->frame,
&self->scale,
self->color_state,
&self->offset,
&clipped);
@@ -1455,6 +1479,7 @@ gsk_gpu_node_processor_add_rounded_clip_node_with_mask (GskGpuNodeProcessor *sel
self->frame,
gsk_render_node_get_preferred_depth (node),
&self->scale,
self->color_state,
&clip_bounds);
gsk_gpu_node_processor_sync_globals (&other, 0);
gsk_gpu_rounded_color_op (other.frame,
@@ -1956,6 +1981,7 @@ gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self,
image = gsk_gpu_node_processor_ensure_image (self->frame,
image,
self->color_state,
GSK_GPU_IMAGE_MIPMAP,
GSK_GPU_IMAGE_STRAIGHT_ALPHA);
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_MIPMAP_DEFAULT);
@@ -2021,6 +2047,7 @@ gsk_gpu_node_processor_create_texture_pattern (GskGpuPatternWriter *self,
{
image = gsk_gpu_node_processor_ensure_image (self->frame,
image,
self->color_state,
GSK_GPU_IMAGE_MIPMAP,
GSK_GPU_IMAGE_STRAIGHT_ALPHA);
sampler = GSK_GPU_SAMPLER_MIPMAP_DEFAULT;
@@ -2082,6 +2109,7 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self,
clip_bounds.size.height = ceilf (clip_bounds.size.height);
offscreen = gsk_gpu_node_processor_create_offscreen (self->frame,
graphene_vec2_one (),
self->color_state,
&clip_bounds,
node);
descriptor = gsk_gpu_node_processor_add_image (self, offscreen, GSK_GPU_SAMPLER_DEFAULT);
@@ -2119,6 +2147,7 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self,
image = gsk_gpu_node_processor_ensure_image (self->frame,
image,
self->color_state,
need_mipmap ? (GSK_GPU_IMAGE_CAN_MIPMAP | GSK_GPU_IMAGE_MIPMAP) : 0,
GSK_GPU_IMAGE_STRAIGHT_ALPHA);
@@ -2283,6 +2312,7 @@ gsk_gpu_node_processor_add_gradient_node (GskGpuNodeProcessor *self,
self->frame,
gsk_render_node_get_preferred_depth (node),
&self->scale,
self->color_state,
&bounds);
other.blend = GSK_GPU_BLEND_ADD;
@@ -3332,6 +3362,7 @@ gsk_gpu_node_processor_repeat_tile (GskGpuNodeProcessor *self,
GSK_DEBUG (FALLBACK, "Offscreening node '%s' for tiling", g_type_name_from_instance ((GTypeInstance *) child));
image = gsk_gpu_node_processor_create_offscreen (self->frame,
&self->scale,
self->color_state,
&clipped_child_bounds,
child);
@@ -3806,17 +3837,31 @@ static void
gsk_gpu_node_processor_add_color_state_node (GskGpuNodeProcessor *self,
GskRenderNode *node)
{
GskGpuImage *image;
GskRenderNode *child;
GdkColorState *color_state;
child = gsk_color_state_node_get_child (node);
color_state = gsk_color_state_node_get_color_state (node);
image = gsk_gpu_node_processor_create_offscreen (self->frame,
&self->scale,
&node->bounds,
child);
if (gdk_color_state_equal (color_state, self->color_state))
{
gsk_gpu_node_processor_add_node (self, child);
return;
}
else
{
GskGpuImage *offscreen;
gsk_gpu_node_processor_image_op (self, image, &node->bounds, &node->bounds);
offscreen = gsk_gpu_node_processor_create_offscreen (self->frame,
&self->scale,
color_state,
&node->bounds,
child);
gsk_gpu_node_processor_image_op (self, offscreen, &node->bounds, &node->bounds);
g_object_unref (offscreen);
}
}
static void
@@ -4147,6 +4192,7 @@ gsk_gpu_node_processor_create_node_pattern (GskGpuPatternWriter *self,
image = gsk_gpu_get_node_as_image (self->frame,
&bounds,
&self->scale,
self->color_state,
node,
&bounds);
if (image == NULL)

View File

@@ -7,6 +7,7 @@ G_BEGIN_DECLS
void gsk_gpu_node_processor_process (GskGpuFrame *frame,
GskGpuImage *target,
GdkColorState *target_color_state,
const cairo_rectangle_int_t *clip,
GskRenderNode *node,
const graphene_rect_t *viewport);

View File

@@ -18,6 +18,7 @@
#include "gdk/gdktextureprivate.h"
#include "gdk/gdktexturedownloaderprivate.h"
#include "gdk/gdkdrawcontextprivate.h"
#include "gdk/gdkcolorstateprivate.h"
#include <graphene.h>
@@ -261,6 +262,7 @@ gsk_gpu_renderer_fallback_render_texture (GskGpuRenderer *self,
GdkTexture *texture;
GdkTextureDownloader downloader;
GskGpuFrame *frame;
GdkColorState *color_state;
max_size = gsk_gpu_device_get_max_image_size (priv->device);
depth = gsk_render_node_get_preferred_depth (root);
@@ -283,6 +285,7 @@ gsk_gpu_renderer_fallback_render_texture (GskGpuRenderer *self,
stride = width * bpp;
size = stride * height;
data = g_malloc_n (stride, height);
color_state = gdk_color_state_get_srgb ();
for (y = 0; y < height; y += image_height)
{
@@ -299,6 +302,7 @@ gsk_gpu_renderer_fallback_render_texture (GskGpuRenderer *self,
gsk_gpu_frame_render (frame,
g_get_monotonic_time (),
image,
color_state,
NULL,
root,
&GRAPHENE_RECT_INIT (rounded_viewport->origin.x + x,
@@ -338,6 +342,7 @@ gsk_gpu_renderer_render_texture (GskRenderer *renderer,
GskGpuImage *image;
GdkTexture *texture;
graphene_rect_t rounded_viewport;
GdkColorState *color_state;
gsk_gpu_device_maybe_gc (priv->device);
@@ -351,6 +356,7 @@ gsk_gpu_renderer_render_texture (GskRenderer *renderer,
gsk_render_node_get_preferred_depth (root),
rounded_viewport.size.width,
rounded_viewport.size.height);
color_state = gdk_color_state_get_srgb ();
if (image == NULL)
return gsk_gpu_renderer_fallback_render_texture (self, root, &rounded_viewport);
@@ -361,6 +367,7 @@ gsk_gpu_renderer_render_texture (GskRenderer *renderer,
gsk_gpu_frame_render (frame,
g_get_monotonic_time (),
image,
color_state,
NULL,
root,
&rounded_viewport,
@@ -388,6 +395,10 @@ gsk_gpu_renderer_render (GskRenderer *renderer,
GskGpuImage *backbuffer;
cairo_region_t *render_region;
double scale;
GdkSurface *surface;
GdkColorState *color_state;
GskRenderNode *node;
GdkMemoryDepth depth;
if (cairo_region_is_empty (region))
{
@@ -395,9 +406,13 @@ gsk_gpu_renderer_render (GskRenderer *renderer,
return;
}
gdk_draw_context_begin_frame_full (priv->context,
gsk_render_node_get_preferred_depth (root),
region);
surface = gdk_draw_context_get_surface (priv->context);
depth = gsk_render_node_get_preferred_depth (root);
color_state = gdk_surface_get_color_state (surface);
depth = gdk_memory_depth_merge (depth, gdk_color_state_get_min_depth (color_state));
gdk_draw_context_begin_frame_full (priv->context, depth, region);
gsk_gpu_device_maybe_gc (priv->device);
@@ -409,11 +424,17 @@ gsk_gpu_renderer_render (GskRenderer *renderer,
render_region = get_render_region (self);
scale = gsk_gpu_renderer_get_scale (self);
if (!gdk_color_state_is_linear (color_state))
node = gsk_color_state_node_new (root, gdk_color_state_get_srgb_linear ());
else
node = gsk_render_node_ref (root);
gsk_gpu_frame_render (frame,
g_get_monotonic_time (),
backbuffer,
color_state,
render_region,
root,
node,
&GRAPHENE_RECT_INIT (
0, 0,
gsk_gpu_image_get_width (backbuffer) / scale,
@@ -421,6 +442,8 @@ gsk_gpu_renderer_render (GskRenderer *renderer,
),
NULL);
gsk_render_node_unref (node);
gsk_gpu_device_queue_gc (priv->device);
gdk_draw_context_end_frame (priv->context);