drawcontext: Make begin_frame() set colorstate + depth

Make begin_frame() set a rendering colorstate and depth, and provide it
to the renderers via gdk_draw_context_get_depth() and
gdk_draw_context_get_color_state().

This allows the draw contexts to define their own values, so that ie the
Cairo and GL renderer can choose different settings for rendering (in
particular, GL can choose GL_SRGB and do the srgb conversion; while
Cairo relies on the renderer).
This commit is contained in:
Benjamin Otte 2024-06-30 04:06:48 +02:00
parent 5a7d7cc9f5
commit 1b1e7f4296
17 changed files with 183 additions and 68 deletions

View File

@ -33,9 +33,11 @@ gdk_broadway_cairo_context_dispose (GObject *object)
}
static void
gdk_broadway_cairo_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region)
gdk_broadway_cairo_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region,
GdkColorState **out_color_state,
GdkMemoryDepth *out_depth)
{
GdkBroadwayCairoContext *self = GDK_BROADWAY_CAIRO_CONTEXT (draw_context);
GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self));
@ -59,6 +61,9 @@ gdk_broadway_cairo_context_begin_frame (GdkDrawContext *draw_context,
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
cairo_fill (cr);
cairo_destroy (cr);
*out_color_state = GDK_COLOR_STATE_SRGB;
*out_depth = gdk_color_state_get_depth (GDK_COLOR_STATE_SRGB);
}
static void

View File

@ -33,9 +33,11 @@ gdk_broadway_draw_context_dispose (GObject *object)
}
static void
gdk_broadway_draw_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region)
gdk_broadway_draw_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region,
GdkColorState **out_color_state,
GdkMemoryDepth *out_depth)
{
GdkBroadwayDrawContext *self = GDK_BROADWAY_DRAW_CONTEXT (draw_context);
GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self));
@ -52,6 +54,9 @@ gdk_broadway_draw_context_begin_frame (GdkDrawContext *draw_context,
self->nodes = g_array_new (FALSE, FALSE, sizeof(guint32));
self->node_textures = g_ptr_array_new_with_free_func (g_object_unref);
*out_color_state = GDK_COLOR_STATE_SRGB;
*out_depth = gdk_color_state_get_depth (GDK_COLOR_STATE_SRGB);
}
static void

View File

@ -48,6 +48,8 @@ struct _GdkDrawContextPrivate {
GdkSurface *surface;
cairo_region_t *frame_region;
GdkColorState *color_state;
GdkMemoryDepth depth;
};
enum {
@ -201,8 +203,12 @@ static guint pixels_counter;
static void
gdk_draw_context_init (GdkDrawContext *self)
{
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (self);
if (pixels_counter == 0)
pixels_counter = gdk_profiler_define_int_counter ("frame pixels", "Pixels drawn per frame");
priv->depth = GDK_N_DEPTHS;
}
/**
@ -378,7 +384,15 @@ gdk_draw_context_begin_frame_full (GdkDrawContext *context,
priv->frame_region = cairo_region_copy (region);
priv->surface->paint_context = g_object_ref (context);
GDK_DRAW_CONTEXT_GET_CLASS (context)->begin_frame (context, depth, priv->frame_region);
GDK_DRAW_CONTEXT_GET_CLASS (context)->begin_frame (context,
depth,
priv->frame_region,
&priv->color_state,
&priv->depth);
/* the callback is meant to set them */
g_assert (priv->color_state != NULL);
g_assert (priv->depth < GDK_N_DEPTHS);
cairo_region_intersect_rectangle (priv->frame_region,
&(cairo_rectangle_int_t) {
@ -449,8 +463,10 @@ gdk_draw_context_end_frame (GdkDrawContext *context)
gdk_profiler_set_int_counter (pixels_counter, region_get_pixels (priv->frame_region));
g_clear_pointer (&priv->color_state, gdk_color_state_unref);
g_clear_pointer (&priv->frame_region, cairo_region_destroy);
g_clear_object (&priv->surface->paint_context);
priv->depth = GDK_N_DEPTHS;
}
/**
@ -478,6 +494,38 @@ gdk_draw_context_get_frame_region (GdkDrawContext *context)
return priv->frame_region;
}
/*<private>
* gdk_draw_context_get_color_state:
* @self: a `GdkDrawContext`
*
* Gets the target color state while rendering. If no rendering is going on, %NULL is returned.
*
* Returns: (transfer none) (nullable): the target color state
**/
GdkColorState *
gdk_draw_context_get_color_state (GdkDrawContext *self)
{
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (self);
return priv->color_state;
}
/*<private>
* gdk_draw_context_get_depth:
* @self: a `GdkDrawContext`
*
* Gets the target depth while rendering. If no rendering is going on, the return value is undefined.
*
* Returns: the target depth
**/
GdkMemoryDepth
gdk_draw_context_get_depth (GdkDrawContext *self)
{
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (self);
return priv->depth;
}
void
gdk_draw_context_empty_frame (GdkDrawContext *context)
{

View File

@ -22,6 +22,7 @@
#include "gdkdrawcontext.h"
#include "gdkcolorstateprivate.h"
#include "gdkmemoryformatprivate.h"
G_BEGIN_DECLS
@ -43,7 +44,9 @@ struct _GdkDrawContextClass
void (* begin_frame) (GdkDrawContext *context,
GdkMemoryDepth depth,
cairo_region_t *update_area);
cairo_region_t *update_area,
GdkColorState **out_color_state,
GdkMemoryDepth *out_depth);
void (* end_frame) (GdkDrawContext *context,
cairo_region_t *painted);
void (* empty_frame) (GdkDrawContext *context);
@ -58,6 +61,9 @@ void gdk_draw_context_begin_frame_full (GdkDrawContext
void gdk_draw_context_empty_frame (GdkDrawContext *context);
GdkColorState * gdk_draw_context_get_color_state (GdkDrawContext *self);
GdkMemoryDepth gdk_draw_context_get_depth (GdkDrawContext *self);
G_END_DECLS

View File

@ -609,9 +609,11 @@ gdk_gl_context_get_scale (GdkGLContext *self)
}
static void
gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region)
gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region,
GdkColorState **out_color_state,
GdkMemoryDepth *out_depth)
{
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
G_GNUC_UNUSED GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
@ -626,7 +628,16 @@ gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
#ifdef HAVE_EGL
if (priv->egl_context)
gdk_surface_ensure_egl_surface (surface, depth);
*out_depth = gdk_surface_ensure_egl_surface (surface, depth);
else
*out_depth = gdk_color_state_get_depth (GDK_COLOR_STATE_SRGB);
if (*out_depth == GDK_MEMORY_U8_SRGB)
*out_color_state = GDK_COLOR_STATE_SRGB_LINEAR;
else
*out_color_state = GDK_COLOR_STATE_SRGB;
#else
*out_color_state = GDK_COLOR_STATE_SRGB;
*out_depth = gdk_color_state_get_depth (GDK_COLOR_STATE_SRGB);
#endif
damage = GDK_GL_CONTEXT_GET_CLASS (context)->get_damage (context);

View File

@ -1139,14 +1139,14 @@ gdk_surface_get_egl_surface (GdkSurface *self)
return priv->egl_surface;
}
void
GdkMemoryDepth
gdk_surface_ensure_egl_surface (GdkSurface *self,
GdkMemoryDepth depth)
{
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (self);
GdkDisplay *display = gdk_surface_get_display (self);
g_return_if_fail (priv->egl_native_window != NULL);
g_return_val_if_fail (priv->egl_native_window != NULL, depth);
if (priv->egl_surface_depth != depth &&
priv->egl_surface != NULL &&
@ -1187,6 +1187,8 @@ gdk_surface_ensure_egl_surface (GdkSurface *self,
}
priv->egl_surface_depth = depth;
}
return priv->egl_surface_depth;
#endif
}

View File

@ -300,7 +300,7 @@ void gdk_surface_set_frame_clock (GdkSurface
GdkFrameClock *clock);
void gdk_surface_set_egl_native_window (GdkSurface *self,
gpointer native_window);
void gdk_surface_ensure_egl_surface (GdkSurface *self,
GdkMemoryDepth gdk_surface_ensure_egl_surface (GdkSurface *self,
GdkMemoryDepth depth);
gpointer /*EGLSurface*/ gdk_surface_get_egl_surface (GdkSurface *self);

View File

@ -634,9 +634,11 @@ physical_device_check_features (VkPhysicalDevice device)
}
static void
gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region)
gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region,
GdkColorState **out_color_state,
GdkMemoryDepth *out_depth)
{
GdkVulkanContext *context = GDK_VULKAN_CONTEXT (draw_context);
GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
@ -656,7 +658,6 @@ gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context,
g_warning ("%s", error->message);
g_error_free (error);
priv->current_depth = old_depth;
return;
}
}
}
@ -665,31 +666,38 @@ gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context,
cairo_region_union (priv->regions[i], region);
}
acquire_next_image:
acquire_result = GDK_VK_CHECK (vkAcquireNextImageKHR, gdk_vulkan_context_get_device (context),
priv->swapchain,
UINT64_MAX,
priv->draw_semaphore,
VK_NULL_HANDLE,
&priv->draw_index);
if ((acquire_result == VK_ERROR_OUT_OF_DATE_KHR) ||
(acquire_result == VK_SUBOPTIMAL_KHR))
while (TRUE)
{
GError *error = NULL;
GDK_DEBUG (VULKAN, "Recreating the swapchain");
if (!gdk_vulkan_context_check_swapchain (context, &error))
acquire_result = GDK_VK_CHECK (vkAcquireNextImageKHR, gdk_vulkan_context_get_device (context),
priv->swapchain,
UINT64_MAX,
priv->draw_semaphore,
VK_NULL_HANDLE,
&priv->draw_index);
if ((acquire_result == VK_ERROR_OUT_OF_DATE_KHR) ||
(acquire_result == VK_SUBOPTIMAL_KHR))
{
GError *error = NULL;
GDK_DEBUG (VULKAN, "Recreating the swapchain");
if (gdk_vulkan_context_check_swapchain (context, &error))
continue;
g_warning ("%s", error->message);
g_error_free (error);
return;
}
goto acquire_next_image;
}
break;
}
cairo_region_union (region, priv->regions[priv->draw_index]);
if (priv->current_depth == GDK_MEMORY_U8_SRGB)
*out_color_state = GDK_COLOR_STATE_SRGB_LINEAR;
else
*out_color_state = GDK_COLOR_STATE_SRGB;
*out_depth = priv->current_depth;
}
static void

View File

@ -197,9 +197,11 @@ clamp_region_to_surface (cairo_region_t *region,
}
static void
_gdk_macos_cairo_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region)
_gdk_macos_cairo_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region,
GdkColorState **out_color_state,
GdkMemoryDepth *out_depth)
{
GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
GdkMacosBuffer *buffer;
@ -249,6 +251,9 @@ _gdk_macos_cairo_context_begin_frame (GdkDrawContext *draw_context,
cairo_region_destroy (copy);
}
}
*out_color_state = GDK_COLOR_STATE_SRGB;
*out_depth = gdk_color_state_get_depth (GDK_COLOR_STATE_SRGB);
}
static void

View File

@ -478,9 +478,11 @@ gdk_macos_gl_context_real_realize (GdkGLContext *context,
}
static void
gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
GdkMemoryDepth depth,
cairo_region_t *region)
gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
GdkMemoryDepth depth,
cairo_region_t *region,
GdkColorState **out_color_state,
GdkMemoryDepth *out_depth)
{
GdkMacosGLContext *self = (GdkMacosGLContext *)context;
GdkMacosBuffer *buffer;
@ -498,7 +500,7 @@ gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
gdk_gl_context_make_current (GDK_GL_CONTEXT (self));
gdk_macos_gl_context_allocate (self);
GDK_DRAW_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->begin_frame (context, depth, region);
GDK_DRAW_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->begin_frame (context, depth, region, out_color_state, out_depth);
gdk_gl_context_make_current (GDK_GL_CONTEXT (self));
CHECK_GL (NULL, glBindFramebuffer (GL_FRAMEBUFFER, self->fbo));

View File

@ -144,9 +144,11 @@ gdk_wayland_cairo_context_create_surface (GdkWaylandCairoContext *self)
}
static void
gdk_wayland_cairo_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region)
gdk_wayland_cairo_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region,
GdkColorState **out_color_state,
GdkMemoryDepth *out_depth)
{
GdkWaylandCairoContext *self = GDK_WAYLAND_CAIRO_CONTEXT (draw_context);
const cairo_region_t *surface_region;
@ -173,6 +175,9 @@ gdk_wayland_cairo_context_begin_frame (GdkDrawContext *draw_context,
gdk_cairo_region (cr, region);
cairo_fill (cr);
cairo_destroy (cr);
*out_color_state = GDK_COLOR_STATE_SRGB;
*out_depth = gdk_color_state_get_depth (GDK_COLOR_STATE_SRGB);
}
static void

View File

@ -47,13 +47,15 @@
G_DEFINE_TYPE (GdkWaylandGLContext, gdk_wayland_gl_context, GDK_TYPE_GL_CONTEXT)
static void
gdk_wayland_gl_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region)
gdk_wayland_gl_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region,
GdkColorState **out_color_state,
GdkMemoryDepth *out_depth)
{
gdk_wayland_surface_ensure_wl_egl_window (gdk_draw_context_get_surface (draw_context));
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->begin_frame (draw_context, depth, region);
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->begin_frame (draw_context, depth, region, out_color_state, out_depth);
}
static void

View File

@ -52,9 +52,11 @@ create_cairo_surface_for_surface (GdkSurface *surface,
}
static void
gdk_win32_cairo_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region)
gdk_win32_cairo_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region,
GdkColorState **out_color_state,
GdkMemoryDepth *out_depth)
{
GdkWin32CairoContext *self = GDK_WIN32_CAIRO_CONTEXT (draw_context);
GdkSurface *surface;
@ -115,6 +117,9 @@ G_GNUC_END_IGNORE_DEPRECATIONS
cairo_clip (cr);
cairo_paint (cr);
cairo_destroy (cr);
*out_color_state = GDK_COLOR_STATE_SRGB;
*out_depth = gdk_color_state_get_depth (GDK_COLOR_STATE_SRGB);
}
static void

View File

@ -108,13 +108,15 @@ gdk_win32_gl_context_egl_end_frame (GdkDrawContext *draw_context,
}
static void
gdk_win32_gl_context_egl_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *update_area)
gdk_win32_gl_context_egl_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *update_area,
GdkColorState **out_color_state,
GdkMemoryDepth *out_depth)
{
gdk_win32_surface_handle_queued_move_resize (draw_context);
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_egl_parent_class)->begin_frame (draw_context, depth, update_area);
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_egl_parent_class)->begin_frame (draw_context, depth, update_area, out_color_state, out_depth);
}
static void

View File

@ -122,13 +122,15 @@ gdk_win32_gl_context_wgl_empty_frame (GdkDrawContext *draw_context)
}
static void
gdk_win32_gl_context_wgl_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *update_area)
gdk_win32_gl_context_wgl_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *update_area,
GdkColorState **out_color_state,
GdkMemoryDepth *out_depth)
{
gdk_win32_surface_handle_queued_move_resize (draw_context);
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_wgl_parent_class)->begin_frame (draw_context, depth, update_area);
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_wgl_parent_class)->begin_frame (draw_context, depth, update_area, out_color_state, out_depth);
}
#define PIXEL_ATTRIBUTES 21

View File

@ -64,13 +64,15 @@ gdk_win32_vulkan_context_create_surface (GdkVulkanContext *context,
}
static void
gdk_win32_vulkan_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *update_area)
gdk_win32_vulkan_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *update_area,
GdkColorState **out_color_state,
GdkMemoryDepth *out_depth)
{
gdk_win32_surface_handle_queued_move_resize (draw_context);
GDK_DRAW_CONTEXT_CLASS (gdk_win32_vulkan_context_parent_class)->begin_frame (draw_context, depth, update_area);
GDK_DRAW_CONTEXT_CLASS (gdk_win32_vulkan_context_parent_class)->begin_frame (draw_context, depth, update_area, out_color_state, out_depth);
}
static void

View File

@ -54,9 +54,11 @@ create_cairo_surface_for_surface (GdkSurface *surface)
}
static void
gdk_x11_cairo_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region)
gdk_x11_cairo_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region,
GdkColorState **out_color_state,
GdkMemoryDepth *out_depth)
{
GdkX11CairoContext *self = GDK_X11_CAIRO_CONTEXT (draw_context);
GdkRectangle clip_box;
@ -78,6 +80,9 @@ G_GNUC_END_IGNORE_DEPRECATIONS
sx = sy = 1;
cairo_surface_get_device_scale (self->paint_surface, &sx, &sy);
cairo_surface_set_device_offset (self->paint_surface, -clip_box.x*sx, -clip_box.y*sy);
*out_color_state = GDK_COLOR_STATE_SRGB;
*out_depth = gdk_color_state_get_depth (GDK_COLOR_STATE_SRGB);
}
static void