aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndri Yngvason <andri@yngvason.is>2021-08-14 22:33:53 +0000
committerSimon Ser <contact@emersion.fr>2021-09-10 10:37:18 +0200
commit105fdecd0cd893c4ae1e21f78c67404f70859af8 (patch)
tree56b7ce5ce5b85a55139b9d922c0d635e37105ba9
parent04d234bac1fe1b8d8e96e727d5ac7e4a41e9e6a7 (diff)
screencopy: Handle shm copy in commit event handler
This simplifies the implementation considerably.
-rw-r--r--include/wlr/types/wlr_screencopy_v1.h1
-rw-r--r--types/wlr_screencopy_v1.c112
2 files changed, 36 insertions, 77 deletions
diff --git a/include/wlr/types/wlr_screencopy_v1.h b/include/wlr/types/wlr_screencopy_v1.h
index aaa300b3..9947b015 100644
--- a/include/wlr/types/wlr_screencopy_v1.h
+++ b/include/wlr/types/wlr_screencopy_v1.h
@@ -52,7 +52,6 @@ struct wlr_screencopy_frame_v1 {
struct wl_listener buffer_destroy;
struct wlr_output *output;
- struct wl_listener output_precommit;
struct wl_listener output_commit;
struct wl_listener output_destroy;
struct wl_listener output_enable;
diff --git a/types/wlr_screencopy_v1.c b/types/wlr_screencopy_v1.c
index ba06f87f..5ef9d269 100644
--- a/types/wlr_screencopy_v1.c
+++ b/types/wlr_screencopy_v1.c
@@ -21,7 +21,6 @@ struct screencopy_damage {
struct pixman_region32 damage;
struct wl_listener output_precommit;
struct wl_listener output_destroy;
- uint32_t last_commit_seq;
};
static const struct zwlr_screencopy_frame_v1_interface frame_impl;
@@ -44,13 +43,6 @@ static void screencopy_damage_accumulate(struct screencopy_damage *damage) {
struct pixman_region32 *region = &damage->damage;
struct wlr_output *output = damage->output;
- /* This check is done so damage that has been added and cleared in the
- * frame precommit handler is not added again after it has been handled.
- */
- if (damage->last_commit_seq == output->commit_seq) {
- return;
- }
-
if (output->pending.committed & WLR_OUTPUT_STATE_DAMAGE) {
// If the compositor submitted damage, copy it over
pixman_region32_union(region, region, &output->pending.damage);
@@ -62,8 +54,6 @@ static void screencopy_damage_accumulate(struct screencopy_damage *damage) {
pixman_region32_union_rect(region, region, 0, 0,
output->width, output->height);
}
-
- damage->last_commit_seq = output->commit_seq;
}
static void screencopy_damage_handle_output_precommit(
@@ -98,7 +88,6 @@ static struct screencopy_damage *screencopy_damage_create(
}
damage->output = output;
- damage->last_commit_seq = output->commit_seq - 1;
pixman_region32_init_rect(&damage->damage, 0, 0, output->width,
output->height);
wl_list_insert(&client->damages, &damage->link);
@@ -154,7 +143,6 @@ static void frame_destroy(struct wlr_screencopy_frame_v1 *frame) {
}
}
wl_list_remove(&frame->link);
- wl_list_remove(&frame->output_precommit.link);
wl_list_remove(&frame->output_commit.link);
wl_list_remove(&frame->output_destroy.link);
wl_list_remove(&frame->output_enable.link);
@@ -200,38 +188,13 @@ static void frame_send_ready(struct wlr_screencopy_frame_v1 *frame,
tv_sec_hi, tv_sec_lo, when->tv_nsec);
}
-static void frame_handle_output_precommit(struct wl_listener *listener,
- void *_data) {
- struct wlr_screencopy_frame_v1 *frame =
- wl_container_of(listener, frame, output_precommit);
- struct wlr_output_event_precommit *event = _data;
+static bool frame_shm_copy(struct wlr_screencopy_frame_v1 *frame,
+ uint32_t *flags) {
+ struct wl_shm_buffer *shm_buffer = frame->shm_buffer;
struct wlr_output *output = frame->output;
struct wlr_renderer *renderer = wlr_backend_get_renderer(output->backend);
assert(renderer);
- if (!(output->pending.committed & WLR_OUTPUT_STATE_BUFFER)) {
- return;
- }
-
- struct wl_shm_buffer *shm_buffer = frame->shm_buffer;
- if (shm_buffer == NULL) {
- return;
- }
-
- if (frame->with_damage) {
- struct screencopy_damage *damage =
- screencopy_damage_get_or_create(frame->client, output);
- if (damage) {
- screencopy_damage_accumulate(damage);
- if (!pixman_region32_not_empty(&damage->damage)) {
- return;
- }
- }
- }
-
- wl_list_remove(&frame->output_precommit.link);
- wl_list_init(&frame->output_precommit.link);
-
int x = frame->box.x;
int y = frame->box.y;
@@ -244,23 +207,16 @@ static void frame_handle_output_precommit(struct wl_listener *listener,
wl_shm_buffer_begin_access(shm_buffer);
void *data = wl_shm_buffer_get_data(shm_buffer);
uint32_t renderer_flags = 0;
- bool ok = wlr_renderer_read_pixels(renderer, drm_format, &renderer_flags,
- stride, width, height, x, y, 0, 0, data);
- uint32_t flags = renderer_flags & WLR_RENDERER_READ_PIXELS_Y_INVERT ?
+ bool ok;
+ ok = wlr_renderer_begin_with_buffer(renderer, output->front_buffer);
+ ok = ok && wlr_renderer_read_pixels(renderer, drm_format,
+ &renderer_flags, stride, width, height, x, y, 0, 0, data);
+ wlr_renderer_end(renderer);
+ *flags = renderer_flags & WLR_RENDERER_READ_PIXELS_Y_INVERT ?
ZWLR_SCREENCOPY_FRAME_V1_FLAGS_Y_INVERT : 0;
wl_shm_buffer_end_access(shm_buffer);
- if (!ok) {
- wlr_log(WLR_ERROR, "Failed to read pixels from renderer");
- zwlr_screencopy_frame_v1_send_failed(frame->resource);
- frame_destroy(frame);
- return;
- }
-
- zwlr_screencopy_frame_v1_send_flags(frame->resource, flags);
- frame_send_damage(frame);
- frame_send_ready(frame, event->when);
- frame_destroy(frame);
+ return ok;
}
static bool blit_dmabuf(struct wlr_renderer *renderer,
@@ -298,6 +254,27 @@ error_src_tex:
return false;
}
+static bool frame_dma_copy(struct wlr_screencopy_frame_v1 *frame,
+ uint32_t *flags) {
+ struct wlr_dmabuf_v1_buffer *dma_buffer = frame->dma_buffer;
+ struct wlr_output *output = frame->output;
+ struct wlr_renderer *renderer = wlr_backend_get_renderer(output->backend);
+ assert(renderer);
+
+ // TODO: add support for copying regions with DMA-BUFs
+ if (frame->box.x != 0 || frame->box.y != 0 ||
+ output->width != frame->box.width ||
+ output->height != frame->box.height) {
+ return false;
+ }
+
+ bool ok = blit_dmabuf(renderer, dma_buffer, output->front_buffer);
+ *flags = dma_buffer->attributes.flags & WLR_DMABUF_ATTRIBUTES_FLAGS_Y_INVERT ?
+ ZWLR_SCREENCOPY_FRAME_V1_FLAGS_Y_INVERT : 0;
+
+ return ok;
+}
+
static void frame_handle_output_commit(struct wl_listener *listener,
void *data) {
struct wlr_screencopy_frame_v1 *frame =
@@ -305,14 +282,14 @@ static void frame_handle_output_commit(struct wl_listener *listener,
struct wlr_output_event_commit *event = data;
struct wlr_output *output = frame->output;
struct wlr_renderer *renderer = wlr_backend_get_renderer(output->backend);
+ uint32_t flags;
assert(renderer);
if (!(event->committed & WLR_OUTPUT_STATE_BUFFER)) {
return;
}
- struct wlr_dmabuf_v1_buffer *dma_buffer = frame->dma_buffer;
- if (dma_buffer == NULL) {
+ if (!frame->shm_buffer && !frame->dma_buffer) {
return;
}
@@ -327,20 +304,8 @@ static void frame_handle_output_commit(struct wl_listener *listener,
wl_list_remove(&frame->output_commit.link);
wl_list_init(&frame->output_commit.link);
- // TODO: add support for copying regions with DMA-BUFs
- if (frame->box.x != 0 || frame->box.y != 0 ||
- output->width != frame->box.width ||
- output->height != frame->box.height) {
- zwlr_screencopy_frame_v1_send_failed(frame->resource);
- frame_destroy(frame);
- return;
- }
-
- bool ok = output->front_buffer && blit_dmabuf(renderer, dma_buffer,
- output->front_buffer);
- uint32_t flags = dma_buffer->attributes.flags & WLR_DMABUF_ATTRIBUTES_FLAGS_Y_INVERT ?
- ZWLR_SCREENCOPY_FRAME_V1_FLAGS_Y_INVERT : 0;
-
+ bool ok = frame->shm_buffer ?
+ frame_shm_copy(frame, &flags) : frame_dma_copy(frame, &flags);
if (!ok) {
zwlr_screencopy_frame_v1_send_failed(frame->resource);
frame_destroy(frame);
@@ -457,8 +422,7 @@ static void frame_handle_copy(struct wl_client *wl_client,
return;
}
- if (!wl_list_empty(&frame->output_precommit.link) ||
- frame->shm_buffer != NULL || frame->dma_buffer != NULL) {
+ if (frame->shm_buffer != NULL || frame->dma_buffer != NULL) {
wl_resource_post_error(frame->resource,
ZWLR_SCREENCOPY_FRAME_V1_ERROR_ALREADY_USED,
"frame already used");
@@ -468,9 +432,6 @@ static void frame_handle_copy(struct wl_client *wl_client,
frame->shm_buffer = shm_buffer;
frame->dma_buffer = dma_buffer;
- wl_signal_add(&output->events.precommit, &frame->output_precommit);
- frame->output_precommit.notify = frame_handle_output_precommit;
-
wl_signal_add(&output->events.commit, &frame->output_commit);
frame->output_commit.notify = frame_handle_output_commit;
@@ -575,7 +536,6 @@ static void capture_output(struct wl_client *wl_client,
wl_list_insert(&client->manager->frames, &frame->link);
- wl_list_init(&frame->output_precommit.link);
wl_list_init(&frame->output_commit.link);
wl_list_init(&frame->output_enable.link);
wl_list_init(&frame->output_destroy.link);