diff options
author | Manuel Stoeckl <code@mstoeckl.com> | 2023-02-19 17:56:53 -0500 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2024-04-29 17:18:13 +0200 |
commit | cde38d5e876e2f6192e83073eedcca4348141a09 (patch) | |
tree | 640031ec01be390d81058708ccddbc6c2901eb7d /main.c | |
parent | a48604c871e197423969059cb233428de79a9fbb (diff) | |
download | swaybg-cde38d5e876e2f6192e83073eedcca4348141a09.tar.gz swaybg-cde38d5e876e2f6192e83073eedcca4348141a09.tar.bz2 |
Decouple wl_buffer creation and wl_surface config
This commit introduces a new `draw_buffer` function which handles both
the creation of single-pixel and wl_shm buffers, and a `get_buffer_size`
to give the required buffer size in both cases. This reorganization
will it easier in the future to support shm buffers in conjunction
with wp_viewport, for use with wp_fractional_scale_v1.
Diffstat (limited to '')
-rw-r--r-- | main.c | 122 |
1 files changed, 74 insertions, 48 deletions
@@ -79,37 +79,26 @@ struct swaybg_output { struct wl_surface *surface; struct zwlr_layer_surface_v1 *layer_surface; + struct wp_viewport *viewport; uint32_t width, height; int32_t scale; uint32_t configure_serial; bool dirty, needs_ack; - int32_t committed_width, committed_height, committed_scale; + // dimensions of the wl_buffer attached to the wl_surface + uint32_t buffer_width, buffer_height; struct wl_list link; }; -static void render_frame(struct swaybg_output *output, cairo_surface_t *surface) { - int buffer_width = output->width * output->scale, - buffer_height = output->height * output->scale; - - // If the last committed buffer has the same size as this one would, do - // not render a new buffer, because it will be identical to the old one - if (output->committed_width == buffer_width && - output->committed_height == buffer_height) { - if (output->committed_scale != output->scale) { - wl_surface_set_buffer_scale(output->surface, output->scale); - wl_surface_commit(output->surface); - - output->committed_scale = output->scale; - } - return; - } - - if (output->config->mode == BACKGROUND_MODE_SOLID_COLOR && - output->state->viewporter && +// Create a wl_buffer with the specified dimensions and content +static struct wl_buffer *draw_buffer(const struct swaybg_output *output, + cairo_surface_t *surface, uint32_t buffer_width, uint32_t buffer_height) { + if (buffer_width == 1 && buffer_height == 1 && + output->config->mode == BACKGROUND_MODE_SOLID_COLOR && output->state->single_pixel_buffer_manager) { + // create and return single pixel buffer uint8_t r8 = (output->config->color >> 24) & 0xFF; uint8_t g8 = (output->config->color >> 16) & 0xFF; uint8_t b8 = (output->config->color >> 8) & 0xFF; @@ -119,26 +108,15 @@ static void render_frame(struct swaybg_output *output, cairo_surface_t *surface) uint32_t g32 = g8 * f; uint32_t b32 = b8 * f; uint32_t a32 = a8 * f; - struct wl_buffer *buffer = wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer( + return wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer( output->state->single_pixel_buffer_manager, r32, g32, b32, a32); - wl_surface_attach(output->surface, buffer, 0, 0); - wl_surface_damage_buffer(output->surface, 0, 0, INT32_MAX, INT32_MAX); - - struct wp_viewport *viewport = wp_viewporter_get_viewport( - output->state->viewporter, output->surface); - wp_viewport_set_destination(viewport, output->width, output->height); - - wl_surface_commit(output->surface); - - wp_viewport_destroy(viewport); - wl_buffer_destroy(buffer); - return; } + struct pool_buffer buffer; if (!create_buffer(&buffer, output->state->shm, buffer_width, buffer_height, WL_SHM_FORMAT_ARGB8888)) { - return; + return NULL; } cairo_t *cairo = buffer.cairo; @@ -161,17 +139,57 @@ static void render_frame(struct swaybg_output *output, cairo_surface_t *surface) } } - wl_surface_set_buffer_scale(output->surface, output->scale); - wl_surface_attach(output->surface, buffer.buffer, 0, 0); - wl_surface_damage_buffer(output->surface, 0, 0, INT32_MAX, INT32_MAX); - wl_surface_commit(output->surface); + // return wl_buffer for caller to use and destroy + struct wl_buffer *wl_buf = buffer.buffer; + buffer.buffer = NULL; + destroy_buffer(&buffer); + return wl_buf; +} + +// Return the size of the buffer that should be attached to this output +static void get_buffer_size(const struct swaybg_output *output, + uint32_t *buffer_width, uint32_t *buffer_height) { + if (output->config->mode == BACKGROUND_MODE_SOLID_COLOR && + output->state->viewporter) { + *buffer_width = 1; + *buffer_height = 1; + } else { + *buffer_width = output->width * output->scale; + *buffer_height = output->height * output->scale; + } +} - output->committed_width = buffer_width; - output->committed_height = buffer_height; - output->committed_scale = output->scale; +static void render_frame(struct swaybg_output *output, cairo_surface_t *surface) { + uint32_t buffer_width, buffer_height; + get_buffer_size(output, &buffer_width, &buffer_height); + + // Attach a new buffer if the desired size has changed + struct wl_buffer *buf = NULL; + if (buffer_width != output->buffer_width || + buffer_height != output->buffer_height) { + buf = draw_buffer(output, surface, + buffer_width, buffer_height); + if (!buf) { + return; + } - // we will not reuse the buffer, so destroy it immediately - destroy_buffer(&buffer); + wl_surface_attach(output->surface, buf, 0, 0); + wl_surface_damage_buffer(output->surface, 0, 0, + buffer_width, buffer_height); + + output->buffer_width = buffer_width; + output->buffer_height = buffer_height; + } + + if (output->viewport) { + wp_viewport_set_destination(output->viewport, output->width, output->height); + } else { + wl_surface_set_buffer_scale(output->surface, output->scale); + } + wl_surface_commit(output->surface); + if (buf) { + wl_buffer_destroy(buf); + } } static void destroy_swaybg_image(struct swaybg_image *image) { @@ -202,6 +220,9 @@ static void destroy_swaybg_output(struct swaybg_output *output) { if (output->surface != NULL) { wl_surface_destroy(output->surface); } + if (output->viewport != NULL) { + wp_viewport_destroy(output->viewport); + } wl_output_destroy(output->wl_output); free(output->name); free(output->identifier); @@ -254,6 +275,12 @@ static void create_layer_surface(struct swaybg_output *output) { wl_surface_set_input_region(output->surface, input_region); wl_region_destroy(input_region); + if (output->state->viewporter && + output->config->mode == BACKGROUND_MODE_SOLID_COLOR) { + output->viewport = wp_viewporter_get_viewport( + output->state->viewporter, output->surface); + } + output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( output->state->layer_shell, output->surface, output->wl_output, ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "wallpaper"); @@ -588,11 +615,10 @@ int main(int argc, char **argv) { output->configure_serial); } - int buffer_width = output->width * output->scale, - buffer_height = output->height * output->scale; - bool buffer_change = - output->committed_height != buffer_height || - output->committed_width != buffer_width; + uint32_t buffer_width, buffer_height; + get_buffer_size(output, &buffer_width, &buffer_height); + bool buffer_change = output->buffer_width != buffer_width || + output->buffer_height != buffer_height; if (output->dirty && output->config->image && buffer_change) { output->config->image->load_required = true; } |