Skip to content
This repository has been archived by the owner on Nov 1, 2021. It is now read-only.

Commit

Permalink
screencopy: Handle shm copy in commit event handler
Browse files Browse the repository at this point in the history
This simplifies the implementation considerably.
  • Loading branch information
any1 committed Aug 14, 2021
1 parent fa20c20 commit 405dbe3
Showing 1 changed file with 35 additions and 70 deletions.
105 changes: 35 additions & 70 deletions types/wlr_screencopy_v1.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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(
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -200,38 +189,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;

Expand All @@ -244,23 +208,15 @@ 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;
wlr_renderer_begin_with_buffer(renderer, output->front_buffer);
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 ?
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,
Expand Down Expand Up @@ -298,21 +254,45 @@ static bool blit_dmabuf(struct wlr_renderer *renderer,
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) {
zwlr_screencopy_frame_v1_send_failed(frame->resource);
frame_destroy(frame);
return false;
}

bool ok = output->front_buffer && 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 =
wl_container_of(listener, frame, output_commit);
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;
}

Expand All @@ -327,20 +307,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);
Expand Down Expand Up @@ -468,9 +436,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;

Expand Down

0 comments on commit 405dbe3

Please sign in to comment.