From 496059a8565c2d5eed672c2e5bc5e1edd14b3de8 Mon Sep 17 00:00:00 2001 From: MithicSpirit Date: Fri, 29 Dec 2023 12:49:17 -0500 Subject: [PATCH] Only rescale background images once This greatly improves performance as rescaling it for every frame is very expensive. Resolves jirutka#59. --- background-image.c | 16 +++++++++++++--- include/background-image.h | 5 +++-- include/swaylock.h | 2 ++ render.c | 24 ++++++++++++++++++------ 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/background-image.c b/background-image.c index 97cb85e4..30dbcdec 100644 --- a/background-image.c +++ b/background-image.c @@ -367,12 +367,13 @@ cairo_surface_t *load_background_image(const char *path) { return image; } -void render_background_image(cairo_t *cairo, cairo_surface_t *image, - enum background_mode mode, int buffer_width, int buffer_height, double alpha) { +cairo_surface_t *scale_background_image(cairo_surface_t *image, + enum background_mode mode, int buffer_width, int buffer_height) { + cairo_surface_t *target = cairo_image_surface_create(CAIRO_FORMAT_RGB24, buffer_width, buffer_height); + cairo_t *cairo = cairo_create(target); double width = cairo_image_surface_get_width(image); double height = cairo_image_surface_get_height(image); - cairo_save(cairo); switch (mode) { case BACKGROUND_MODE_STRETCH: cairo_scale(cairo, @@ -435,7 +436,16 @@ void render_background_image(cairo_t *cairo, cairo_surface_t *image, assert(0); break; } + cairo_pattern_set_filter(cairo_get_source(cairo), CAIRO_FILTER_BILINEAR); + cairo_paint(cairo); + cairo_destroy(cairo); + return target; +} + +void render_background_image(cairo_t *cairo, cairo_surface_t *image, double alpha) { + cairo_save(cairo); + cairo_set_source_surface(cairo, image, 0, 0); cairo_paint_with_alpha(cairo, alpha); cairo_restore(cairo); } diff --git a/include/background-image.h b/include/background-image.h index ad38272e..0a10dd45 100644 --- a/include/background-image.h +++ b/include/background-image.h @@ -19,7 +19,8 @@ enum background_mode parse_background_mode(const char *mode); cairo_surface_t *load_background_image(const char *path); cairo_surface_t *load_background_from_buffer(void *buf, uint32_t format, uint32_t width, uint32_t height, uint32_t stride, enum wl_output_transform transform); -void render_background_image(cairo_t *cairo, cairo_surface_t *image, - enum background_mode mode, int buffer_width, int buffer_height, double alpha); +cairo_surface_t *scale_background_image(cairo_surface_t *image, + enum background_mode mode, int buffer_width, int buffer_height); +void render_background_image(cairo_t *cairo, cairo_surface_t *image, double alpha); #endif diff --git a/include/swaylock.h b/include/swaylock.h index de09ce85..daa6f754 100644 --- a/include/swaylock.h +++ b/include/swaylock.h @@ -123,11 +123,13 @@ struct swaylock_state { struct swaylock_surface { cairo_surface_t *image; + cairo_surface_t *scaled_image; struct { uint32_t format, width, height, stride; enum wl_output_transform transform; void *data; cairo_surface_t *original_image; + cairo_surface_t *scaled_image; struct swaylock_image *image; } screencopy; struct swaylock_state *state; diff --git a/render.c b/render.c index 368a4bca..f92b3c1f 100644 --- a/render.c +++ b/render.c @@ -95,13 +95,25 @@ void render_frame_background(struct swaylock_surface *surface, bool commit) { if (surface->image && state->args.mode != BACKGROUND_MODE_SOLID_COLOR) { cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); if (fade_is_complete(&surface->fade)) { - render_background_image(cairo, surface->image, - state->args.mode, buffer_width, buffer_height, 1); + if (!surface->scaled_image) { + surface->scaled_image = + scale_background_image(surface->image, state->args.mode, + buffer_width, buffer_height); + } + render_background_image(cairo, surface->scaled_image, 1); } else { - render_background_image(cairo, surface->screencopy.original_image, - state->args.mode, buffer_width, buffer_height, 1); - render_background_image(cairo, surface->image, - state->args.mode, buffer_width, buffer_height, surface->fade.alpha); + if (!surface->screencopy.scaled_image) { + surface->screencopy.scaled_image = + scale_background_image(surface->screencopy.original_image, + state->args.mode, buffer_width, buffer_height); + } + render_background_image(cairo, surface->screencopy.scaled_image, 1); + if (!surface->scaled_image) { + surface->scaled_image = + scale_background_image(surface->image, state->args.mode, + buffer_width, buffer_height); + } + render_background_image(cairo, surface->scaled_image, surface->fade.alpha); } } cairo_restore(cairo);