diff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h index dd0c3ed76..c6cfa4f33 100644 --- a/libweston/backend-drm/drm-internal.h +++ b/libweston/backend-drm/drm-internal.h @@ -808,6 +808,11 @@ drm_fb_unref(struct drm_fb *fb); struct drm_fb * drm_fb_create_dumb(struct drm_device *device, int width, int height, uint32_t format); + +struct drm_fb * +drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf, + struct drm_device *device, bool is_opaque, + uint32_t *try_view_on_plane_failure_reasons); struct drm_fb * drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_device *device, bool is_opaque, enum drm_fb_type type); diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c index 39f96b7d7..ea12d761c 100644 --- a/libweston/backend-drm/drm.c +++ b/libweston/backend-drm/drm.c @@ -683,7 +683,7 @@ drm_output_pick_writeback_capture_task(struct drm_output *output) struct weston_capture_task *ct; struct weston_buffer *buffer; struct drm_writeback *wb; - const char *msg; + char *msg; int32_t width = output->base.current_mode->width; int32_t height = output->base.current_mode->height; const struct weston_drm_format_array *writeback_formats = @@ -698,14 +698,15 @@ drm_output_pick_writeback_capture_task(struct drm_output *output) return; if (output->base.disable_planes > 0) { - msg = "drm: KMS planes usage is disabled for now, so " \ - "writeback capture tasks are rejected"; + str_printf(&msg, "drm: KMS planes usage is disabled for now, " \ + "so writeback capture tasks are rejected"); goto err; } wb = drm_output_find_compatible_writeback(output); if (!wb) { - msg = "drm: could not find writeback connector for output"; + str_printf(&msg, + "drm: could not find writeback connector for output"); goto err; } @@ -715,14 +716,40 @@ drm_output_pick_writeback_capture_task(struct drm_output *output) output->wb_state = drm_writeback_state_alloc(); if (!output->wb_state) { - msg = "drm: failed to allocate memory for writeback state"; + str_printf(&msg, + "drm: failed to allocate memory for writeback state"); goto err; } - output->wb_state->fb = drm_fb_create_dumb(output->device, width, height, - buffer->pixel_format->format); - if (!output->wb_state->fb) { - msg = "drm: failed to create dumb buffer for writeback state"; + if (buffer->type == WESTON_BUFFER_SHM) { + output->wb_state->fb = drm_fb_create_dumb(output->device, width, + height, + buffer->pixel_format->format); + if (!output->wb_state->fb) { + str_printf(&msg, + "drm: failed to create dumb buffer for " \ + "writeback state"); + goto err_fb; + } + } +#ifdef BUILD_DRM_GBM + else if (buffer->type == WESTON_BUFFER_DMABUF) { + uint32_t failure_reasons = 0; + output->wb_state->fb = drm_fb_get_from_dmabuf(buffer->dmabuf, + output->device, + false, + &failure_reasons); + if (!output->wb_state->fb) { + str_printf(&msg, + "drm: failed to attach dma buffer from " \ + "client for writeback state: %s", + weston_plane_failure_reasons_to_str(failure_reasons)); + goto err_fb; + } + } +#endif + else { + str_printf(&msg, "drm: Invalid buffer type"); goto err_fb; } @@ -738,6 +765,7 @@ err_fb: output->wb_state = NULL; err: weston_capture_task_retire_failed(ct, msg); + free(msg); } #ifdef BUILD_DRM_GBM @@ -3312,20 +3340,22 @@ drm_writeback_success_screenshot(struct drm_writeback_state *state) int dst_stride, src_stride; uint32_t *src, *dst; - src = state->fb->map; - src_stride = state->fb->strides[0]; + if (buffer->type == WESTON_BUFFER_SHM) { + src = state->fb->map; + src_stride = state->fb->strides[0]; - dst = wl_shm_buffer_get_data(buffer->shm_buffer); - dst_stride = buffer->stride; + dst = wl_shm_buffer_get_data(buffer->shm_buffer); + dst_stride = buffer->stride; - width = state->fb->width; - height = state->fb->height; + width = state->fb->width; + height = state->fb->height; - wl_shm_buffer_begin_access(buffer->shm_buffer); - pixman_copy_screenshot(dst, src, dst_stride, src_stride, - buffer->pixel_format->pixman_format, - width, height); - wl_shm_buffer_end_access(buffer->shm_buffer); + wl_shm_buffer_begin_access(buffer->shm_buffer); + pixman_copy_screenshot(dst, src, dst_stride, src_stride, + buffer->pixel_format->pixman_format, + width, height); + wl_shm_buffer_end_access(buffer->shm_buffer); + } weston_capture_task_retire_complete(state->ct); drm_writeback_state_free(state); diff --git a/libweston/backend-drm/fb.c b/libweston/backend-drm/fb.c index 335a4a062..8a33b59a6 100644 --- a/libweston/backend-drm/fb.c +++ b/libweston/backend-drm/fb.c @@ -535,7 +535,7 @@ err_free: return NULL; } -static struct drm_fb * +struct drm_fb * drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf, struct drm_device *device, bool is_opaque, uint32_t *try_view_on_plane_failure_reasons) diff --git a/protocol/weston-output-capture.xml b/protocol/weston-output-capture.xml index 56dcd0d7c..a041623ca 100644 --- a/protocol/weston-output-capture.xml +++ b/protocol/weston-output-capture.xml @@ -171,8 +171,8 @@ image buffer. Any buffer is incompatible if it does not have this size. - Row alignment of the buffer must be 4 bytes, and it must not contain - further row padding. Otherwise the buffer is unsupported. + For wl_shm the row alignment of the buffer must be 4 bytes, and it must + not contain further row padding. Otherwise the buffer is unsupported. This is an initial event, and sent whenever the required size changes.