gsk: Repurpose GSK_DEBUG=cairo

Use it to overlay an error pattern over all Cairo drawing done by
renderers.

This has 2 purposes:
1. It allows detecting fallbacks in GPU renderers.
2. Application code can use it to detect where it is using Cairo
   drawing.

As such, it is meant to trigger both with cairo nodes as well as when
renderers fallback for regular nodes.

The old use of the debug flag - which were 2 not very useful print
statements - was removed.
This commit is contained in:
Benjamin Otte 2023-12-26 04:53:09 +01:00
parent e93acc5762
commit 1385ffd2c2
6 changed files with 62 additions and 23 deletions

View File

@ -1212,7 +1212,7 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
cairo_save (cr); cairo_save (cr);
cairo_translate (cr, - floorf (node->bounds.origin.x), - floorf (node->bounds.origin.y)); cairo_translate (cr, - floorf (node->bounds.origin.x), - floorf (node->bounds.origin.y));
/* Render nodes don't modify state, so casting away the const is fine here */ /* Render nodes don't modify state, so casting away the const is fine here */
gsk_render_node_draw ((GskRenderNode *)node, cr); gsk_render_node_draw_fallback ((GskRenderNode *)node, cr);
cairo_restore (cr); cairo_restore (cr);
cairo_destroy (cr); cairo_destroy (cr);
} }

View File

@ -5,7 +5,6 @@
static const GdkDebugKey gsk_debug_keys[] = { static const GdkDebugKey gsk_debug_keys[] = {
{ "renderer", GSK_DEBUG_RENDERER, "General renderer information" }, { "renderer", GSK_DEBUG_RENDERER, "General renderer information" },
{ "cairo", GSK_DEBUG_CAIRO, "Cairo renderer information" },
{ "opengl", GSK_DEBUG_OPENGL, "OpenGL renderer information" }, { "opengl", GSK_DEBUG_OPENGL, "OpenGL renderer information" },
{ "vulkan", GSK_DEBUG_VULKAN, "Vulkan renderer information" }, { "vulkan", GSK_DEBUG_VULKAN, "Vulkan renderer information" },
{ "shaders", GSK_DEBUG_SHADERS, "Information about shaders" }, { "shaders", GSK_DEBUG_SHADERS, "Information about shaders" },
@ -18,6 +17,7 @@ static const GdkDebugKey gsk_debug_keys[] = {
{ "sync", GSK_DEBUG_SYNC, "Sync after each frame" }, { "sync", GSK_DEBUG_SYNC, "Sync after each frame" },
{ "staging", GSK_DEBUG_STAGING, "Use a staging image for texture upload (Vulkan only)" }, { "staging", GSK_DEBUG_STAGING, "Use a staging image for texture upload (Vulkan only)" },
{ "offload-disable", GSK_DEBUG_OFFLOAD_DISABLE, "Disable graphics offload" }, { "offload-disable", GSK_DEBUG_OFFLOAD_DISABLE, "Disable graphics offload" },
{ "cairo", GSK_DEBUG_CAIRO, "Overlay error pattern over Cairo drawing (finds fallbacks)" },
}; };
static guint gsk_debug_flags; static guint gsk_debug_flags;

View File

@ -7,20 +7,20 @@ G_BEGIN_DECLS
typedef enum { typedef enum {
GSK_DEBUG_RENDERER = 1 << 0, GSK_DEBUG_RENDERER = 1 << 0,
GSK_DEBUG_CAIRO = 1 << 1, GSK_DEBUG_OPENGL = 1 << 1,
GSK_DEBUG_OPENGL = 1 << 2, GSK_DEBUG_SHADERS = 1 << 2,
GSK_DEBUG_SHADERS = 1 << 3, GSK_DEBUG_SURFACE = 1 << 3,
GSK_DEBUG_SURFACE = 1 << 4, GSK_DEBUG_VULKAN = 1 << 4,
GSK_DEBUG_VULKAN = 1 << 5, GSK_DEBUG_FALLBACK = 1 << 5,
GSK_DEBUG_FALLBACK = 1 << 6, GSK_DEBUG_GLYPH_CACHE = 1 << 6,
GSK_DEBUG_GLYPH_CACHE = 1 << 7, GSK_DEBUG_VERBOSE = 1 << 7,
GSK_DEBUG_VERBOSE = 1 << 8,
/* flags below may affect behavior */ /* flags below may affect behavior */
GSK_DEBUG_GEOMETRY = 1 << 9, GSK_DEBUG_GEOMETRY = 1 << 8,
GSK_DEBUG_FULL_REDRAW = 1 << 10, GSK_DEBUG_FULL_REDRAW = 1 << 9,
GSK_DEBUG_SYNC = 1 << 11, GSK_DEBUG_SYNC = 1 << 10,
GSK_DEBUG_STAGING = 1 << 12, GSK_DEBUG_STAGING = 1 << 11,
GSK_DEBUG_OFFLOAD_DISABLE = 1 << 13, GSK_DEBUG_OFFLOAD_DISABLE = 1 << 12,
GSK_DEBUG_CAIRO = 1 << 13,
} GskDebugFlags; } GskDebugFlags;
#define GSK_DEBUG_ANY ((1 << 13) - 1) #define GSK_DEBUG_ANY ((1 << 13) - 1)

View File

@ -386,10 +386,6 @@ gsk_render_node_draw (GskRenderNode *node,
cairo_save (cr); cairo_save (cr);
GSK_DEBUG (CAIRO, "Rendering node %s[%p]",
g_type_name_from_instance ((GTypeInstance *) node),
node);
GSK_RENDER_NODE_GET_CLASS (node)->draw (node, cr); GSK_RENDER_NODE_GET_CLASS (node)->draw (node, cr);
if (GSK_DEBUG_CHECK (GEOMETRY)) if (GSK_DEBUG_CHECK (GEOMETRY))
@ -412,6 +408,51 @@ gsk_render_node_draw (GskRenderNode *node,
} }
} }
/*
* gsk_render_node_draw:
* @node: a `GskRenderNode`
* @cr: cairo context to draw to
*
* Like gsk_render_node_draw(), but will overlay an error pattern if
* GSK_DEBUG=cairo is enabled.
*
* This has 2 purposes:
* 1. It allows detecting fallbacks in GPU renderers.
* 2. Application code can use it to detect where it is using Cairo
* drawing.
*
* So use this function whenever either of those cases should be detected.
**/
void
gsk_render_node_draw_fallback (GskRenderNode *node,
cairo_t *cr)
{
gsk_render_node_draw (node, cr);
if (GSK_DEBUG_CHECK (CAIRO))
{
/* pink, black
* black, pink
*/
static const guint32 pixels[] = { 0xFFFF00CC, 0xFF000000,
0xFF000000, 0xFFFF00CC };
cairo_surface_t *surface;
cairo_save (cr);
surface = cairo_image_surface_create_for_data ((guchar *) pixels,
CAIRO_FORMAT_ARGB32,
2, 2,
2 * 4);
cairo_scale (cr, 10, 10);
cairo_set_source_surface (cr, surface, 0, 0);
cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
cairo_paint_with_alpha (cr, 0.6);
cairo_surface_destroy (surface);
cairo_restore (cr);
}
}
/* /*
* gsk_render_node_can_diff: * gsk_render_node_can_diff:
* @node1: a `GskRenderNode` * @node1: a `GskRenderNode`

View File

@ -3355,10 +3355,6 @@ gsk_transform_node_draw (GskRenderNode *node,
gsk_transform_to_2d (self->transform, &xx, &yx, &xy, &yy, &dx, &dy); gsk_transform_to_2d (self->transform, &xx, &yx, &xy, &yy, &dx, &dy);
cairo_matrix_init (&ctm, xx, yx, xy, yy, dx, dy); cairo_matrix_init (&ctm, xx, yx, xy, yy, dx, dy);
GSK_DEBUG (CAIRO, "CTM = { .xx = %g, .yx = %g, .xy = %g, .yy = %g, .x0 = %g, .y0 = %g }",
ctm.xx, ctm.yx,
ctm.xy, ctm.yy,
ctm.x0, ctm.y0);
if (xx * yy == xy * yx) if (xx * yy == xy * yx)
{ {
/* broken matrix here. This can happen during transitions /* broken matrix here. This can happen during transitions

View File

@ -84,6 +84,8 @@ void gsk_render_node_diff_impossible (GskRenderNode
void gsk_container_node_diff_with (GskRenderNode *container, void gsk_container_node_diff_with (GskRenderNode *container,
GskRenderNode *other, GskRenderNode *other,
GskDiffData *data); GskDiffData *data);
void gsk_render_node_draw_fallback (GskRenderNode *node,
cairo_t *cr);
bool gsk_border_node_get_uniform (const GskRenderNode *self); bool gsk_border_node_get_uniform (const GskRenderNode *self);
bool gsk_border_node_get_uniform_color (const GskRenderNode *self); bool gsk_border_node_get_uniform_color (const GskRenderNode *self);