summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorManuel Stoeckl <code@mstoeckl.com>2023-02-19 17:56:53 -0500
committerSimon Ser <contact@emersion.fr>2024-04-29 17:18:13 +0200
commitcde38d5e876e2f6192e83073eedcca4348141a09 (patch)
tree640031ec01be390d81058708ccddbc6c2901eb7d /main.c
parenta48604c871e197423969059cb233428de79a9fbb (diff)
downloadswaybg-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.c122
1 files changed, 74 insertions, 48 deletions
diff --git a/main.c b/main.c
index 9dcf6b7..af314f1 100644
--- a/main.c
+++ b/main.c
@@ -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;
}