backend-drm: keep track of the reason why promoting view to a plane failed

Add enum try_view_on_plane_failure_reasons to help us to keep track of
the reason why promoting view to a plane failed. We also add a variable
to struct weston_paint_node so that we can update this information in
each output repaint.

This will be used in the next commits, in which we add proper surface
dma-buf feedback support.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
This commit is contained in:
Leandro Ribeiro 2021-09-13 14:52:53 -03:00
parent 8eb8414fcd
commit 0a7034c0cb
4 changed files with 51 additions and 11 deletions

View File

@ -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;
}

View File

@ -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 {

View File

@ -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) {

View File

@ -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 *