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>
dev
Leandro Ribeiro 3 years ago
parent 8eb8414fcd
commit 0a7034c0cb
  1. 17
      libweston/backend-drm/drm-internal.h
  2. 23
      libweston/backend-drm/fb.c
  3. 20
      libweston/backend-drm/state-propose.c
  4. 2
      libweston/libweston-internal.h

@ -227,6 +227,17 @@ enum wdrm_crtc_property {
WDRM_CRTC__COUNT 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 drm_backend {
struct weston_backend base; struct weston_backend base;
struct weston_compositor *compositor; 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 #ifdef BUILD_DRM_GBM
extern struct drm_fb * 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 extern bool
drm_can_scanout_dmabuf(struct weston_compositor *ec, drm_can_scanout_dmabuf(struct weston_compositor *ec,
struct linux_dmabuf_buffer *dmabuf); struct linux_dmabuf_buffer *dmabuf);
#else #else
static inline struct drm_fb * 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; return NULL;
} }

@ -220,7 +220,8 @@ drm_fb_destroy_dmabuf(struct drm_fb *fb)
static struct drm_fb * static struct drm_fb *
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf, 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 #ifndef HAVE_GBM_FD_IMPORT
/* Importing a buffer to KMS requires explicit modifiers, so /* 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 * 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 * not knowing its layout can result in garbage being displayed. In
* short, importing a buffer to KMS requires explicit modifiers. */ * 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; return NULL;
}
/* XXX: TODO: /* XXX: TODO:
* *
@ -313,8 +318,12 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
fb->handles[i] = handle.u32; 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; goto err_free;
}
return fb; return fb;
@ -455,7 +464,7 @@ drm_can_scanout_dmabuf(struct weston_compositor *ec,
struct drm_backend *b = to_drm_backend(ec); struct drm_backend *b = to_drm_backend(ec);
bool ret = false; bool ret = false;
fb = drm_fb_get_from_dmabuf(dmabuf, b, true); fb = drm_fb_get_from_dmabuf(dmabuf, b, true, NULL);
if (fb) if (fb)
ret = true; ret = true;
@ -466,7 +475,8 @@ drm_can_scanout_dmabuf(struct weston_compositor *ec,
} }
struct drm_fb * 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_output *output = state->output;
struct drm_backend *b = to_drm_backend(output->base.compositor); 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); dmabuf = linux_dmabuf_buffer_get(buffer->resource);
if (dmabuf) { 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) if (!fb)
return NULL; return NULL;
} else { } else {

@ -654,7 +654,8 @@ drm_output_prepare_plane_view(struct drm_output_state *state,
struct weston_view *ev, struct weston_view *ev,
enum drm_output_propose_state_mode mode, enum drm_output_propose_state_mode mode,
struct drm_plane_state *scanout_state, 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_output *output = state->output;
struct drm_backend *b = to_drm_backend(output->base.compositor); 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; buffer = ev->surface->buffer_ref.buffer;
shmbuf = wl_shm_buffer_get(buffer->resource); 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 */ /* assemble a list with possible candidates */
wl_list_for_each(plane, &b->plane_list, link) { 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)) { 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 " drm_debug(b, "\t\t\t\t[plane] not adding plane %d to "
"candidate list: invalid pixel format\n", "candidate list: invalid pixel format\n",
plane->plane_id); plane->plane_id);
@ -960,7 +963,18 @@ drm_output_propose_state(struct weston_output *output_base,
current_lowest_zpos); current_lowest_zpos);
ps = drm_output_prepare_plane_view(state, ev, mode, ps = drm_output_prepare_plane_view(state, ev, mode,
scanout_state, 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) { if (ps) {

@ -416,6 +416,8 @@ struct weston_paint_node {
struct weston_surface_color_transform surf_xform; struct weston_surface_color_transform surf_xform;
bool surf_xform_valid; bool surf_xform_valid;
uint32_t try_view_on_plane_failure_reasons;
}; };
struct weston_paint_node * struct weston_paint_node *

Loading…
Cancel
Save