diff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h index 86c25105..4e697aa1 100644 --- a/libweston/backend-drm/drm-internal.h +++ b/libweston/backend-drm/drm-internal.h @@ -227,6 +227,17 @@ enum wdrm_crtc_property { WDRM_CRTC__COUNT }; +/** + * Reasons why placing a view on a plane failed. Needed by the dma-buf feedback. + */ +enum try_view_on_plane_failure_reasons { + FAILURE_REASONS_NONE = 0, + FAILURE_REASONS_FORCE_RENDERER = (1 << 0), + FAILURE_REASONS_FB_FORMAT_INCOMPATIBLE = (1 << 1), + FAILURE_REASONS_DMABUF_MODIFIER_INVALID = (1 << 2), + FAILURE_REASONS_ADD_FB_FAILED = (1 << 3), +}; + struct drm_backend { struct weston_backend base; struct weston_compositor *compositor; @@ -694,13 +705,15 @@ drm_output_set_cursor_view(struct drm_output *output, struct weston_view *ev); #ifdef BUILD_DRM_GBM extern struct drm_fb * -drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev); +drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev, + uint32_t *try_view_on_plane_failure_reasons); extern bool drm_can_scanout_dmabuf(struct weston_compositor *ec, struct linux_dmabuf_buffer *dmabuf); #else static inline struct drm_fb * -drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev) +drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev, + uint32_t *try_view_on_plane_failure_reasons) { return NULL; } diff --git a/libweston/backend-drm/fb.c b/libweston/backend-drm/fb.c index 1d35b493..017422f2 100644 --- a/libweston/backend-drm/fb.c +++ b/libweston/backend-drm/fb.c @@ -220,7 +220,8 @@ drm_fb_destroy_dmabuf(struct drm_fb *fb) static struct drm_fb * drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf, - struct drm_backend *backend, bool is_opaque) + struct drm_backend *backend, bool is_opaque, + uint32_t *try_view_on_plane_failure_reasons) { #ifndef HAVE_GBM_FD_IMPORT /* Importing a buffer to KMS requires explicit modifiers, so @@ -245,8 +246,12 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf, * KMS driver can't know. So giving the buffer to KMS is not safe, as * not knowing its layout can result in garbage being displayed. In * short, importing a buffer to KMS requires explicit modifiers. */ - if (dmabuf->attributes.modifier[0] == DRM_FORMAT_MOD_INVALID) + if (dmabuf->attributes.modifier[0] == DRM_FORMAT_MOD_INVALID) { + if (try_view_on_plane_failure_reasons) + *try_view_on_plane_failure_reasons |= + FAILURE_REASONS_DMABUF_MODIFIER_INVALID; return NULL; + } /* XXX: TODO: * @@ -313,8 +318,12 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf, fb->handles[i] = handle.u32; } - if (drm_fb_addfb(backend, fb) != 0) + if (drm_fb_addfb(backend, fb) != 0) { + if (try_view_on_plane_failure_reasons) + *try_view_on_plane_failure_reasons |= + FAILURE_REASONS_ADD_FB_FAILED; goto err_free; + } return fb; @@ -455,7 +464,7 @@ drm_can_scanout_dmabuf(struct weston_compositor *ec, struct drm_backend *b = to_drm_backend(ec); bool ret = false; - fb = drm_fb_get_from_dmabuf(dmabuf, b, true); + fb = drm_fb_get_from_dmabuf(dmabuf, b, true, NULL); if (fb) ret = true; @@ -466,7 +475,8 @@ drm_can_scanout_dmabuf(struct weston_compositor *ec, } struct drm_fb * -drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev) +drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev, + uint32_t *try_view_on_plane_failure_reasons) { struct drm_output *output = state->output; struct drm_backend *b = to_drm_backend(output->base.compositor); @@ -497,7 +507,8 @@ drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev) dmabuf = linux_dmabuf_buffer_get(buffer->resource); if (dmabuf) { - fb = drm_fb_get_from_dmabuf(dmabuf, b, is_opaque); + fb = drm_fb_get_from_dmabuf(dmabuf, b, is_opaque, + try_view_on_plane_failure_reasons); if (!fb) return NULL; } else { diff --git a/libweston/backend-drm/state-propose.c b/libweston/backend-drm/state-propose.c index ce168d1f..d0f80e3b 100644 --- a/libweston/backend-drm/state-propose.c +++ b/libweston/backend-drm/state-propose.c @@ -654,7 +654,8 @@ drm_output_prepare_plane_view(struct drm_output_state *state, struct weston_view *ev, enum drm_output_propose_state_mode mode, struct drm_plane_state *scanout_state, - uint64_t current_lowest_zpos) + uint64_t current_lowest_zpos, + uint32_t *try_view_on_plane_failure_reasons) { struct drm_output *output = state->output; struct drm_backend *b = to_drm_backend(output->base.compositor); @@ -676,7 +677,7 @@ drm_output_prepare_plane_view(struct drm_output_state *state, buffer = ev->surface->buffer_ref.buffer; shmbuf = wl_shm_buffer_get(buffer->resource); - fb = drm_fb_get_from_view(state, ev); + fb = drm_fb_get_from_view(state, ev, try_view_on_plane_failure_reasons); /* assemble a list with possible candidates */ wl_list_for_each(plane, &b->plane_list, link) { @@ -730,6 +731,8 @@ drm_output_prepare_plane_view(struct drm_output_state *state, } if (!drm_output_plane_view_has_valid_format(plane, state, ev, fb)) { + *try_view_on_plane_failure_reasons |= + FAILURE_REASONS_FB_FORMAT_INCOMPATIBLE; drm_debug(b, "\t\t\t\t[plane] not adding plane %d to " "candidate list: invalid pixel format\n", plane->plane_id); @@ -960,7 +963,18 @@ drm_output_propose_state(struct weston_output *output_base, current_lowest_zpos); ps = drm_output_prepare_plane_view(state, ev, mode, scanout_state, - current_lowest_zpos); + current_lowest_zpos, + &pnode->try_view_on_plane_failure_reasons); + /* If we were able to place the view in a plane, set + * failure reasons to none. */ + if (ps) + pnode->try_view_on_plane_failure_reasons = + FAILURE_REASONS_NONE; + } else { + /* We are forced to place the view in the renderer, set + * the failure reason accordingly. */ + pnode->try_view_on_plane_failure_reasons = + FAILURE_REASONS_FORCE_RENDERER; } if (ps) { diff --git a/libweston/libweston-internal.h b/libweston/libweston-internal.h index 1603db38..7c30706f 100644 --- a/libweston/libweston-internal.h +++ b/libweston/libweston-internal.h @@ -416,6 +416,8 @@ struct weston_paint_node { struct weston_surface_color_transform surf_xform; bool surf_xform_valid; + + uint32_t try_view_on_plane_failure_reasons; }; struct weston_paint_node *