backend-drm: Unify overlay/primary view->plane code

There's no real reason for these to be separate now that the eligibility
checks have been moved up so we don't call them unless it makes sense.

Signed-off-by: Daniel Stone <daniels@collabora.com>
dev
Daniel Stone 3 years ago
parent 81e74ff334
commit 0ace8b66af
  1. 195
      libweston/backend-drm/state-propose.c

@ -76,70 +76,78 @@ drm_output_check_plane_has_view_assigned(struct drm_plane *plane,
}
static struct drm_plane_state *
drm_output_prepare_overlay_view(struct drm_plane *plane,
struct drm_output_state *output_state,
struct weston_view *ev,
enum drm_output_propose_state_mode mode,
struct drm_fb *fb, uint64_t zpos)
drm_output_try_view_on_plane(struct drm_plane *plane,
struct drm_output_state *output_state,
struct weston_view *ev,
enum drm_output_propose_state_mode mode,
struct drm_fb *fb, uint64_t zpos)
{
struct drm_output *output = output_state->output;
struct weston_compositor *ec = output->base.compositor;
struct weston_surface *surface = ev->surface;
struct drm_backend *b = to_drm_backend(ec);
struct drm_plane_state *state = NULL;
int ret;
assert(!b->sprites_are_broken);
assert(b->atomic_modeset);
assert(fb);
assert(mode == DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY ||
(mode == DRM_OUTPUT_PROPOSE_STATE_MIXED &&
plane->type == WDRM_PLANE_TYPE_OVERLAY));
state = drm_output_state_get_plane(output_state, plane);
/* we can't have a 'pending' framebuffer as never set one before reaching here */
assert(!state->fb);
state->ev = ev;
state->output = output;
if (!drm_plane_state_coords_for_view(state, ev, zpos)) {
drm_debug(b, "\t\t\t\t[overlay] not placing view %p on overlay: "
drm_debug(b, "\t\t\t\t[view] not placing view %p on plane: "
"unsuitable transform\n", ev);
drm_plane_state_put_back(state);
state = NULL;
goto out;
}
/* Should've been ensured by weston_view_matches_entire_output. */
if (plane->type == WDRM_PLANE_TYPE_PRIMARY) {
assert(state->dest_x == 0 && state->dest_y == 0 &&
state->dest_w == (unsigned) output->base.current_mode->width &&
state->dest_h == (unsigned) output->base.current_mode->height);
}
/* We hold one reference for the lifetime of this function; from
* calling drm_fb_get_from_view() in drm_output_prepare_plane_view(),
* so, we take another reference here to live within the state. */
state->ev = ev;
state->fb = drm_fb_ref(fb);
state->in_fence_fd = ev->surface->acquire_fence_fd;
/* In planes-only mode, we don't have an incremental state to
* test against, so we just hope it'll work. */
if (mode == DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY) {
drm_debug(b, "\t\t\t[overlay] provisionally placing "
"view %p on overlay %lu in planes-only mode\n",
if (mode != DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY &&
drm_pending_state_test(output_state->pending_state) != 0) {
drm_debug(b, "\t\t\t[view] not placing view %p on plane %lu: "
"atomic test failed\n",
ev, (unsigned long) plane->plane_id);
goto out;
}
ret = drm_pending_state_test(output_state->pending_state);
if (ret == 0) {
drm_debug(b, "\t\t\t[overlay] provisionally placing "
"view %p on overlay %d in mixed mode\n",
ev, plane->plane_id);
goto out;
}
drm_debug(b, "\t\t\t[overlay] not placing view %p on overlay %lu "
"in mixed mode: kernel test failed\n",
drm_debug(b, "\t\t\t[view] provisionally placing view %p on plane %lu\n",
ev, (unsigned long) plane->plane_id);
drm_plane_state_put_back(state);
state = NULL;
/* Take a reference on the buffer so that we don't release it
* back to the client until we're done with it; cursor buffers
* don't require a reference since we copy them. */
assert(state->fb_ref.buffer.buffer == NULL);
assert(state->fb_ref.release.buffer_release == NULL);
weston_buffer_reference(&state->fb_ref.buffer,
surface->buffer_ref.buffer);
weston_buffer_release_reference(&state->fb_ref.release,
surface->buffer_release_ref.buffer_release);
out:
return state;
out:
drm_plane_state_put_back(state);
return NULL;
}
#ifdef BUILD_DRM_GBM
@ -275,117 +283,6 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state,
}
#endif
static struct drm_plane_state *
drm_output_prepare_scanout_view(struct drm_output_state *output_state,
struct weston_view *ev,
enum drm_output_propose_state_mode mode,
struct drm_fb *fb, uint64_t zpos)
{
struct drm_output *output = output_state->output;
struct drm_backend *b = to_drm_backend(output->base.compositor);
struct drm_plane *scanout_plane = output->scanout_plane;
struct drm_plane_state *state;
const char *p_name = drm_output_get_plane_type_name(scanout_plane);
assert(!b->sprites_are_broken);
assert(b->atomic_modeset);
assert(mode == DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY);
assert(fb);
state = drm_output_state_get_plane(output_state, scanout_plane);
/* The only way we can already have a buffer in the scanout plane is
* if we are in mixed mode, or if a client buffer has already been
* placed into scanout. The former case will never call into here,
* and in the latter case, the view must have been marked as occluded,
* meaning we should never have ended up here. */
assert(!state->fb);
/* take another reference here to live within the state */
state->fb = drm_fb_ref(fb);
state->ev = ev;
state->output = output;
if (!drm_plane_state_coords_for_view(state, ev, zpos)) {
drm_debug(b, "\t\t\t\t[%s] not placing view %p on %s: "
"unsuitable transform\n", p_name, ev, p_name);
goto err;
}
if (state->dest_x != 0 || state->dest_y != 0 ||
state->dest_w != (unsigned) output->base.current_mode->width ||
state->dest_h != (unsigned) output->base.current_mode->height) {
drm_debug(b, "\t\t\t\t[%s] not placing view %p on %s: "
" invalid plane state\n", p_name, ev, p_name);
goto err;
}
state->in_fence_fd = ev->surface->acquire_fence_fd;
/* In plane-only mode, we don't need to test the state now, as we
* will only test it once at the end. */
return state;
err:
drm_plane_state_put_back(state);
return NULL;
}
static struct drm_plane_state *
drm_output_try_view_on_plane(struct drm_plane *plane,
struct drm_output_state *state,
struct weston_view *ev,
enum drm_output_propose_state_mode mode,
struct drm_fb *fb, uint64_t zpos)
{
struct drm_backend *b = state->pending_state->backend;
struct drm_plane_state *ps = NULL;
const char *p_name = drm_output_get_plane_type_name(plane);
struct weston_surface *surface = ev->surface;
/* sanity checks in case we over/underflow zpos or pass incorrect
* values */
assert(zpos <= plane->zpos_max ||
zpos != DRM_PLANE_ZPOS_INVALID_PLANE);
switch (plane->type) {
case WDRM_PLANE_TYPE_OVERLAY:
ps = drm_output_prepare_overlay_view(plane, state, ev, mode,
fb, zpos);
break;
case WDRM_PLANE_TYPE_PRIMARY:
ps = drm_output_prepare_scanout_view(state, ev, mode,
fb, zpos);
break;
default:
assert(0);
break;
}
if (ps) {
/* Take a reference on the buffer so that we don't release it
* back to the client until we're done with it; cursor buffers
* don't require a reference since we copy them. */
assert(ps->fb_ref.buffer.buffer == NULL);
assert(ps->fb_ref.release.buffer_release == NULL);
if (ps->plane->type == WDRM_PLANE_TYPE_CURSOR) {
assert(ps->fb->type == BUFFER_CURSOR);
} else if (fb->type == BUFFER_CLIENT || fb->type == BUFFER_DMABUF) {
assert(ps->fb == fb);
weston_buffer_reference(&ps->fb_ref.buffer,
surface->buffer_ref.buffer);
weston_buffer_release_reference(&ps->fb_ref.release,
surface->buffer_release_ref.buffer_release);
}
} else {
drm_debug(b, "\t\t\t\t[plane] plane %d refusing to "
"place view %p in %s\n",
plane->plane_id, ev, p_name);
}
return ps;
}
static void
drm_output_check_zpos_plane_states(struct drm_output_state *state)
{
@ -521,12 +418,12 @@ dmabuf_feedback_maybe_update(struct drm_backend *b, struct weston_view *ev,
}
static struct drm_plane_state *
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,
uint32_t *try_view_on_plane_failure_reasons)
drm_output_find_plane_for_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,
uint32_t *try_view_on_plane_failure_reasons)
{
struct drm_output *output = state->output;
struct drm_backend *b = to_drm_backend(output->base.compositor);
@ -883,10 +780,10 @@ drm_output_propose_state(struct weston_output *output_base,
if (!force_renderer) {
drm_debug(b, "\t\t\t[plane] started with zpos %"PRIu64"\n",
current_lowest_zpos);
ps = drm_output_prepare_plane_view(state, ev, mode,
scanout_state,
current_lowest_zpos,
&pnode->try_view_on_plane_failure_reasons);
ps = drm_output_find_plane_for_view(state, ev, mode,
scanout_state,
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)

Loading…
Cancel
Save