From 4502d58eecb56b9aa79452fa2fee2fc68b50ce2d Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Thu, 28 Nov 2024 06:58:17 +0900 Subject: [PATCH] buffer: remove buffer->cairo It's more common for cairo_t to have a temporary lifetime and it will prevent accidentally reusing its previous state. --- include/buffer.h | 1 - src/buffer.c | 8 +++----- src/common/font.c | 5 +++-- src/common/scaled-rect-buffer.c | 4 +++- src/img/img-svg.c | 4 +++- src/osd.c | 3 ++- src/theme.c | 33 +++++++++++++++++++++++---------- src/workspaces.c | 3 ++- 8 files changed, 39 insertions(+), 22 deletions(-) diff --git a/include/buffer.h b/include/buffer.h index 7daa4643..52fa2573 100644 --- a/include/buffer.h +++ b/include/buffer.h @@ -34,7 +34,6 @@ struct lab_data_buffer { bool surface_owns_data; cairo_surface_t *surface; - cairo_t *cairo; void *data; uint32_t format; /* currently always DRM_FORMAT_ARGB8888 */ size_t stride; diff --git a/src/buffer.c b/src/buffer.c index 251f6930..7b626bc9 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -45,7 +45,6 @@ static void data_buffer_destroy(struct wlr_buffer *wlr_buffer) { struct lab_data_buffer *buffer = data_buffer_from_buffer(wlr_buffer); - cairo_destroy(buffer->cairo); /* this also frees buffer->data if surface_owns_data == true */ cairo_surface_destroy(buffer->surface); if (!buffer->surface_owns_data) { @@ -97,7 +96,6 @@ buffer_adopt_cairo_surface(cairo_surface_t *surface) buffer->stride = cairo_image_surface_get_stride(buffer->surface); buffer->logical_width = width; buffer->logical_height = height; - buffer->cairo = cairo_create(surface); buffer->surface_owns_data = true; return buffer; @@ -167,7 +165,7 @@ buffer_convert_cairo_surface_for_icon(cairo_surface_t *surface, buffer = buffer_create_cairo(logical.width, logical.height, scale); - cairo_t *cairo = buffer->cairo; + cairo_t *cairo = cairo_create(buffer->surface); cairo_scale(cairo, (double)logical.width / width, (double)logical.height / height); cairo_set_source_surface(cairo, surface, 0, 0); @@ -177,8 +175,9 @@ buffer_convert_cairo_surface_for_icon(cairo_surface_t *surface, /* ensure pixel data is updated */ cairo_surface_flush(buffer->surface); - /* destroy original surface */ + /* destroy original cairo surface & context */ cairo_surface_destroy(surface); + cairo_destroy(cairo); } return buffer; @@ -197,7 +196,6 @@ buffer_create_from_data(void *pixel_data, uint32_t width, uint32_t height, buffer->stride = stride; buffer->surface = cairo_image_surface_create_for_data( pixel_data, CAIRO_FORMAT_ARGB32, width, height, stride); - buffer->cairo = cairo_create(buffer->surface); buffer->surface_owns_data = false; return buffer; } diff --git a/src/common/font.c b/src/common/font.c index ff984ce4..f93e3e88 100644 --- a/src/common/font.c +++ b/src/common/font.c @@ -115,8 +115,8 @@ font_buffer_create(struct lab_data_buffer **buffer, int max_width, return; } - cairo_t *cairo = (*buffer)->cairo; - cairo_surface_t *surf = cairo_get_target(cairo); + cairo_surface_t *surf = (*buffer)->surface; + cairo_t *cairo = cairo_create(surf); /* * Fill with the background color first IF the background color @@ -171,6 +171,7 @@ font_buffer_create(struct lab_data_buffer **buffer, int max_width, g_object_unref(layout); cairo_surface_flush(surf); + cairo_destroy(cairo); } void diff --git a/src/common/scaled-rect-buffer.c b/src/common/scaled-rect-buffer.c index 43a81563..a6778d95 100644 --- a/src/common/scaled-rect-buffer.c +++ b/src/common/scaled-rect-buffer.c @@ -39,7 +39,7 @@ _create_buffer(struct scaled_scene_buffer *scaled_buffer, double scale) return NULL; } - cairo_t *cairo = buffer->cairo; + cairo_t *cairo = cairo_create(buffer->surface); /* Clear background */ cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); @@ -58,6 +58,8 @@ _create_buffer(struct scaled_scene_buffer *scaled_buffer, double scale) set_cairo_color(cairo, self->border_color); cairo_stroke(cairo); + cairo_destroy(cairo); + return buffer; } diff --git a/src/img/img-svg.c b/src/img/img-svg.c index 9480ce56..f217d72a 100644 --- a/src/img/img-svg.c +++ b/src/img/img-svg.c @@ -41,7 +41,7 @@ img_svg_load(const char *filename, struct lab_data_buffer **buffer, int size, *buffer = buffer_create_cairo(size, size, scale); cairo_surface_t *image = (*buffer)->surface; - cairo_t *cr = (*buffer)->cairo; + cairo_t *cr = cairo_create(image); rsvg_handle_render_document(svg, cr, &viewport, &err); if (err) { @@ -55,6 +55,7 @@ img_svg_load(const char *filename, struct lab_data_buffer **buffer, int size, goto error; } cairo_surface_flush(image); + cairo_destroy(cr); g_object_unref(svg); return; @@ -62,5 +63,6 @@ img_svg_load(const char *filename, struct lab_data_buffer **buffer, int size, error: wlr_buffer_drop(&(*buffer)->base); *buffer = NULL; + cairo_destroy(cr); g_object_unref(svg); } diff --git a/src/osd.c b/src/osd.c index ca5a7059..24365f60 100644 --- a/src/osd.c +++ b/src/osd.c @@ -354,8 +354,9 @@ display_osd(struct output *output, struct wl_array *views) } /* Render OSD image */ - cairo_t *cairo = buffer->cairo; + cairo_t *cairo = cairo_create(buffer->surface); render_osd(server, cairo, w, h, show_workspace, workspace_name, views); + cairo_destroy(cairo); struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_create( output->osd_tree, &buffer->base); diff --git a/src/theme.c b/src/theme.c index b49c6cc5..2a7111b2 100644 --- a/src/theme.c +++ b/src/theme.c @@ -80,7 +80,12 @@ zdrop(struct lab_data_buffer **buffer) } } -static struct lab_data_buffer * +struct icon_drawing_context { + struct lab_data_buffer *buffer; + cairo_t *cairo; +}; + +static struct icon_drawing_context copy_icon_buffer(struct theme *theme, struct lab_data_buffer *icon_buffer) { assert(icon_buffer); @@ -110,7 +115,7 @@ copy_icon_buffer(struct theme *theme, struct lab_data_buffer *icon_buffer) int buffer_height = (double)height * scale; struct lab_data_buffer *buffer = buffer_create_cairo( buffer_width, buffer_height, 1.0); - cairo_t *cairo = buffer->cairo; + cairo_t *cairo = cairo_create(buffer->surface); cairo_set_source_surface(cairo, surface, (buffer_width - icon_width) / 2, (buffer_height - icon_height) / 2); @@ -122,7 +127,10 @@ copy_icon_buffer(struct theme *theme, struct lab_data_buffer *icon_buffer) */ cairo_scale(cairo, scale, scale); - return buffer; + return (struct icon_drawing_context){ + .buffer = buffer, + .cairo = cairo, + }; } static void @@ -136,8 +144,9 @@ create_hover_fallback(struct theme *theme, int width = theme->window_button_width; int height = theme->window_button_height; - *hover_buffer = copy_icon_buffer(theme, icon_buffer); - cairo_t *cairo = (*hover_buffer)->cairo; + struct icon_drawing_context ctx = copy_icon_buffer(theme, icon_buffer); + *hover_buffer = ctx.buffer; + cairo_t *cairo = ctx.cairo; /* Overlay (pre-multiplied alpha) */ float overlay_color[4] = { 0.15f, 0.15f, 0.15f, 0.3f}; @@ -156,6 +165,7 @@ create_hover_fallback(struct theme *theme, cairo_fill(cairo); cairo_surface_flush(cairo_get_target(cairo)); + cairo_destroy(cairo); } static void @@ -163,8 +173,9 @@ create_rounded_buffer(struct theme *theme, enum corner corner, struct lab_data_buffer **rounded_buffer, struct lab_data_buffer *icon_buffer) { - *rounded_buffer = copy_icon_buffer(theme, icon_buffer); - cairo_t *cairo = (*rounded_buffer)->cairo; + struct icon_drawing_context ctx = copy_icon_buffer(theme, icon_buffer); + *rounded_buffer = ctx.buffer; + cairo_t *cairo = ctx.cairo; int width = theme->window_button_width; int height = theme->window_button_height; @@ -189,12 +200,13 @@ create_rounded_buffer(struct theme *theme, enum corner corner, }; struct lab_data_buffer *mask_buffer = rounded_rect(&rounded_ctx); cairo_set_operator(cairo, CAIRO_OPERATOR_DEST_IN); - cairo_set_source_surface(cairo, cairo_get_target(mask_buffer->cairo), + cairo_set_source_surface(cairo, mask_buffer->surface, (corner == LAB_CORNER_TOP_LEFT) ? -margin_x : 0, -margin_y); cairo_paint(cairo); cairo_surface_flush(cairo_get_target(cairo)); + cairo_destroy(cairo); wlr_buffer_drop(&mask_buffer->base); } @@ -1088,8 +1100,8 @@ rounded_rect(struct rounded_corner_ctx *ctx) /* TODO: scale */ buffer = buffer_create_cairo(w, h, 1); - cairo_t *cairo = buffer->cairo; - cairo_surface_t *surf = cairo_get_target(cairo); + cairo_surface_t *surf = buffer->surface; + cairo_t *cairo = cairo_create(surf); /* set transparent background */ cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); @@ -1231,6 +1243,7 @@ rounded_rect(struct rounded_corner_ctx *ctx) out: cairo_surface_flush(surf); + cairo_destroy(cairo); return buffer; } diff --git a/src/workspaces.c b/src/workspaces.c index 93bd0db6..806f250f 100644 --- a/src/workspaces.c +++ b/src/workspaces.c @@ -90,7 +90,7 @@ _osd_update(struct server *server) continue; } - cairo = buffer->cairo; + cairo = cairo_create(buffer->surface); /* Background */ set_cairo_color(cairo, theme->osd_bg_color); @@ -150,6 +150,7 @@ _osd_update(struct server *server) g_object_unref(layout); surface = cairo_get_target(cairo); cairo_surface_flush(surface); + cairo_destroy(cairo); if (!output->workspace_osd) { output->workspace_osd = wlr_scene_buffer_create(