diff --git a/include/pool-buffer.h b/include/pool-buffer.h index 0ebf787..38e8218 100644 --- a/include/pool-buffer.h +++ b/include/pool-buffer.h @@ -15,8 +15,10 @@ struct pool_buffer { bool busy; }; +struct pool_buffer *create_buffer(struct wl_shm *shm, struct pool_buffer *buf, + int32_t width, int32_t height, uint32_t format); struct pool_buffer *get_next_buffer(struct wl_shm *shm, - struct pool_buffer pool[static 2], uint32_t width, uint32_t height); + struct pool_buffer pool[static 2], uint32_t width, uint32_t height); void destroy_buffer(struct pool_buffer *buffer); #endif diff --git a/include/swaylock.h b/include/swaylock.h index 9de8ab6..bb71c8c 100644 --- a/include/swaylock.h +++ b/include/swaylock.h @@ -98,11 +98,10 @@ struct swaylock_surface { struct swaylock_state *state; struct wl_output *output; uint32_t output_global_name; - struct wl_surface *surface; - struct wl_surface *child; // surface made into subsurface + struct wl_surface *surface; // surface for background + struct wl_surface *child; // indicator surface made into subsurface struct wl_subsurface *subsurface; struct ext_session_lock_surface_v1 *ext_session_lock_surface_v1; - struct pool_buffer buffers[2]; struct pool_buffer indicator_buffers[2]; bool frame_pending, dirty; uint32_t width, height; @@ -110,6 +109,8 @@ struct swaylock_surface { enum wl_output_subpixel subpixel; char *output_name; struct wl_list link; + // Dimensions of last wl_buffer committed to background surface + int last_buffer_width, last_buffer_height; }; // There is exactly one swaylock_image for each -i argument diff --git a/main.c b/main.c index 26d30a5..ca89be7 100644 --- a/main.c +++ b/main.c @@ -100,8 +100,6 @@ static void destroy_surface(struct swaylock_surface *surface) { if (surface->surface != NULL) { wl_surface_destroy(surface->surface); } - destroy_buffer(&surface->buffers[0]); - destroy_buffer(&surface->buffers[1]); destroy_buffer(&surface->indicator_buffers[0]); destroy_buffer(&surface->indicator_buffers[1]); wl_output_destroy(surface->output); diff --git a/pool-buffer.c b/pool-buffer.c index 02884de..dfb4d0d 100644 --- a/pool-buffer.c +++ b/pool-buffer.c @@ -46,7 +46,7 @@ static const struct wl_buffer_listener buffer_listener = { .release = buffer_release }; -static struct pool_buffer *create_buffer(struct wl_shm *shm, +struct pool_buffer *create_buffer(struct wl_shm *shm, struct pool_buffer *buf, int32_t width, int32_t height, uint32_t format) { uint32_t stride = width * 4; diff --git a/render.c b/render.c index 3ce7a80..b7febc1 100644 --- a/render.c +++ b/render.c @@ -4,6 +4,7 @@ #include "cairo.h" #include "background-image.h" #include "swaylock.h" +#include "log.h" #define M_PI 3.14159265358979323846 const float TYPE_INDICATOR_RANGE = M_PI / 3.0f; @@ -41,30 +42,40 @@ void render_frame_background(struct swaylock_surface *surface) { return; // not yet configured } - struct pool_buffer *buffer = get_next_buffer(state->shm, - surface->buffers, buffer_width, buffer_height); - if (buffer == NULL) { - return; - } + if (buffer_width != surface->last_buffer_width || + buffer_height != surface->last_buffer_height) { + struct pool_buffer buffer; + if (!create_buffer(state->shm, &buffer, buffer_width, buffer_height, + WL_SHM_FORMAT_ARGB8888)) { + swaylock_log(LOG_ERROR, + "Failed to create new buffer for frame background."); + return; + } - cairo_t *cairo = buffer->cairo; - cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); + cairo_t *cairo = buffer.cairo; + cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); - cairo_save(cairo); - cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); - cairo_set_source_u32(cairo, state->args.colors.background); - cairo_paint(cairo); - if (surface->image && state->args.mode != BACKGROUND_MODE_SOLID_COLOR) { - cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); - render_background_image(cairo, surface->image, - state->args.mode, buffer_width, buffer_height); + cairo_save(cairo); + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); + cairo_set_source_u32(cairo, state->args.colors.background); + cairo_paint(cairo); + if (surface->image && state->args.mode != BACKGROUND_MODE_SOLID_COLOR) { + cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); + render_background_image(cairo, surface->image, + state->args.mode, buffer_width, buffer_height); + } + cairo_restore(cairo); + cairo_identity_matrix(cairo); + + wl_surface_attach(surface->surface, buffer.buffer, 0, 0); + wl_surface_damage_buffer(surface->surface, 0, 0, INT32_MAX, INT32_MAX); + destroy_buffer(&buffer); + + surface->last_buffer_width = buffer_width; + surface->last_buffer_height = buffer_height; } - cairo_restore(cairo); - cairo_identity_matrix(cairo); wl_surface_set_buffer_scale(surface->surface, surface->scale); - wl_surface_attach(surface->surface, buffer->buffer, 0, 0); - wl_surface_damage_buffer(surface->surface, 0, 0, INT32_MAX, INT32_MAX); wl_surface_commit(surface->surface); }