Recycle failed capture buffers, release when off

This commit is contained in:
Mars-Wave
2025-11-23 22:05:32 +01:00
parent 63479fc178
commit 294642363f
3 changed files with 37 additions and 8 deletions
+1
View File
@@ -183,6 +183,7 @@ static void update_tick_callback(struct wd_state *state) {
if (state->capture_timeout != -1) {
g_source_remove(state->capture_timeout);
state->capture_timeout = -1;
wd_capture_release(state);
}
} else if (state->capture_timeout == -1) {
state->capture_due = true;
+31 -8
View File
@@ -252,6 +252,21 @@ static void capture_flags(void *data,
frame->y_invert = !!(flags & ZWLR_SCREENCOPY_FRAME_V1_FLAGS_Y_INVERT);
}
static void keep_as_spare(struct wd_frame *frame) {
struct wd_output *output = frame->output;
if (output->spare != NULL) {
wd_frame_destroy(frame);
return;
}
if (frame->wlr_frame != NULL) {
zwlr_screencopy_frame_v1_destroy(frame->wlr_frame);
frame->wlr_frame = NULL;
}
wl_list_remove(&frame->link);
wl_list_init(&frame->link);
output->spare = frame;
}
static void capture_ready(void *data,
struct zwlr_screencopy_frame_v1 *wlr_frame,
uint32_t tv_sec_hi, uint32_t tv_sec_lo, uint32_t tv_nsec) {
@@ -268,13 +283,7 @@ static void capture_ready(void *data,
struct wd_frame *frame_iter, *frame_tmp;
wl_list_for_each_safe(frame_iter, frame_tmp, &output->frames, link) {
if (frame != frame_iter) {
if (output->spare == NULL) {
wl_list_remove(&frame_iter->link);
wl_list_init(&frame_iter->link);
output->spare = frame_iter;
} else {
wd_frame_destroy(frame_iter);
}
keep_as_spare(frame_iter);
}
}
}
@@ -282,7 +291,7 @@ static void capture_ready(void *data,
static void capture_failed(void *data,
struct zwlr_screencopy_frame_v1 *wlr_frame) {
struct wd_frame *frame = data;
wd_frame_destroy(frame);
keep_as_spare(frame);
}
struct zwlr_screencopy_frame_v1_listener capture_listener = {
@@ -330,6 +339,20 @@ void wd_capture_frame(struct wd_state *state) {
}
}
void wd_capture_release(struct wd_state *state) {
struct wd_output *output;
wl_list_for_each(output, &state->outputs, link) {
struct wd_frame *frame, *frame_tmp;
wl_list_for_each_safe(frame, frame_tmp, &output->frames, link) {
wd_frame_destroy(frame);
}
if (output->spare != NULL) {
wd_frame_destroy(output->spare);
output->spare = NULL;
}
}
}
static void wd_output_destroy(struct wd_output *output) {
struct wd_frame *frame, *frame_tmp;
wl_list_for_each_safe(frame, frame_tmp, &output->frames, link) {
+5
View File
@@ -285,6 +285,11 @@ void wd_capture_frame(struct wd_state *state);
*/
void wd_capture_wait(struct wd_state *state, struct wl_display *display);
/*
* Frees all captured frames and their buffers.
*/
void wd_capture_release(struct wd_state *state);
/*
* Updates the UI stack of all heads. Does not update individual head forms.
* Useful for when a display is plugged/unplugged and we want to add/remove