On Tue, 10 Jul 2018 18:58:42 +0100 Daniel Stone <dani...@collabora.com> wrote:
> Add support for multiple modes to drm_output_propose_state. Currently we > intend to operate in three modes: planes-only (no renderer buffer, > client buffers in planes only), mixed-mode (promote client buffers to > planes where possible, falling back to the renderer where not), and > renderer-only (no plane usage at all). > > We want to use the first (planes-only) mode where possible: it can avoid > us having to allocate buffers for the renderer, and it also gives us the > best chance of the optimal configuration, with no composition. In this > mode, we walk the scene looking at all views, trying to put them in > planes, and failing as soon as we find a view we cannot place in a > plane. Hi, please add a note that planes-only mode gets added by a later patch. > > In the second mode, rather than failing, we assign those views which > cannot be on a plane to the renderer, and allow the renderer to > composite them. > > In the third mode, planes are not usable, so everything but the cursor > goes to the renderer. We will use this when we cannot use the planes-only > mode (because some views cannot be placed in planes), but also cannot > use the 'mixed' mode because we have no renderer buffer yet. Since we > walk the scene graph from top to bottom, using atomic modesetting we > will determine if planes can be promoted in mixed mode by placing a > renderer buffer at the bottom of the scene, placing a cursor buffer if > applicable, then testing if we can add overlay planes to this mode. > > Without a buffer from the renderer, we cannot do these tests, so we push > everything through the renderer and then switch to mixed mode on the > next repaint. > > Signed-off-by: Daniel Stone <dani...@collabora.com> > Tested-by: Emre Ucan <eu...@de.adit-jv.com> > --- > libweston/compositor-drm.c | 69 +++++++++++++++++++++++++------------- > 1 file changed, 45 insertions(+), 24 deletions(-) > > diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c > index d045778aa..d4898bc46 100644 > --- a/libweston/compositor-drm.c > +++ b/libweston/compositor-drm.c > @@ -1939,6 +1939,11 @@ drm_output_assign_state(struct drm_output_state *state, > } > } > > +enum drm_output_propose_state_mode { > + DRM_OUTPUT_PROPOSE_STATE_MIXED, /**< mix renderer & planes */ > + DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY, /**< only assign to renderer & > cursor */ > +}; > + > static struct weston_plane * > drm_output_prepare_scanout_view(struct drm_output_state *output_state, > struct weston_view *ev) > @@ -3121,10 +3126,9 @@ drm_output_prepare_cursor_view(struct drm_output_state > *output_state, > struct wl_shm_buffer *shmbuf; > bool needs_update = false; > > - if (!plane) > - return NULL; > + assert(!b->cursors_are_broken); > > - if (b->cursors_are_broken) > + if (!plane) > return NULL; > > if (!plane->state_cur->complete) > @@ -3259,7 +3263,8 @@ err: > > static struct drm_output_state * > drm_output_propose_state(struct weston_output *output_base, > - struct drm_pending_state *pending_state) > + struct drm_pending_state *pending_state, > + enum drm_output_propose_state_mode mode) > { > struct drm_output *output = to_drm_output(output_base); > struct drm_backend *b = to_drm_backend(output->base.compositor); > @@ -3267,11 +3272,14 @@ drm_output_propose_state(struct weston_output > *output_base, > struct weston_view *ev; > pixman_region32_t surface_overlap, renderer_region, occluded_region; > struct weston_plane *primary = &output_base->compositor->primary_plane; > + bool planes_ok = (mode != DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY); > > assert(!output->state_last); > state = drm_output_state_duplicate(output->state_cur, > pending_state, > DRM_OUTPUT_STATE_CLEAR_PLANES); > + if (!planes_ok) > + return state; > > /* > * Find a surface for each sprite in the output using some heuristics: > @@ -3339,13 +3347,16 @@ drm_output_propose_state(struct weston_output > *output_base, > next_plane = primary; > pixman_region32_fini(&surface_overlap); > > - if (next_plane == NULL) > + /* The cursor plane is 'special' in the sense that we can still > + * place it in the legacy API, and we gate that with a separate > + * cursors_are_broken flag. */ > + if (next_plane == NULL && !b->cursors_are_broken) > next_plane = drm_output_prepare_cursor_view(state, ev); > > if (next_plane == NULL && !drm_view_is_opaque(ev)) > next_plane = primary; > > - if (next_plane == NULL && b->sprites_are_broken) > + if (next_plane == NULL && !planes_ok) planes_ok is guaranteed to be true. > next_plane = primary; > > if (next_plane == NULL) > @@ -3354,24 +3365,27 @@ drm_output_propose_state(struct weston_output > *output_base, > if (next_plane == NULL) > next_plane = drm_output_prepare_overlay_view(state, ev); > > - if (next_plane == NULL) > - next_plane = primary; > + if (next_plane && next_plane != primary) { > + /* If we have been assigned to an overlay or scanout > + * plane, add this area to the occluded region, so > + * other views are known to be behind it. The cursor > + * plane, however, is special, in that it blends with > + * the content underneath it: the area should neither > + * be added to the renderer region nor the occluded > + * region. */ > + if (!output->cursor_plane || > + next_plane != &output->cursor_plane->base) { > + pixman_region32_union(&occluded_region, > + &occluded_region, > + &clipped_view); > + pixman_region32_fini(&clipped_view); > + } > + continue; > + } > > - /* If we've been assigned to the 'primary' (renderer) plane, > - * add this to our renderer region. If we have been assigned > - * to the cursor plane, do nothing, as the cursor plane is > - * blended with content underneath it. If neither, we have > - * been assigned to an overlay plane, so add this view's > - * area to the occluded region. */ > - if (next_plane == primary) > - pixman_region32_union(&renderer_region, > - &renderer_region, > - &clipped_view); > - else if (!output->cursor_plane || > - next_plane != &output->cursor_plane->base) > - pixman_region32_union(&occluded_region, > - &occluded_region, > - &clipped_view); > + pixman_region32_union(&renderer_region, > + &renderer_region, > + &clipped_view); > pixman_region32_fini(&clipped_view); > } > pixman_region32_fini(&renderer_region); > @@ -3390,8 +3404,15 @@ drm_assign_planes(struct weston_output *output_base, > void *repaint_data) > struct drm_plane_state *plane_state; > struct weston_view *ev; > struct weston_plane *primary = &output_base->compositor->primary_plane; > + enum drm_output_propose_state_mode mode; > + > + if (!b->sprites_are_broken) > + state = drm_output_propose_state(output_base, pending_state, > + > DRM_OUTPUT_PROPOSE_STATE_MIXED); > > - state = drm_output_propose_state(output_base, pending_state); > + if (!state) 'state' may be used uninitialized, needs initialization to NULL. > + state = drm_output_propose_state(output_base, pending_state, > + > DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY); > > wl_list_for_each(ev, &output_base->compositor->view_list, link) { > struct drm_plane *target_plane = NULL; With those three issues fixed: Reviewed-by: Pekka Paalanen <pekka.paala...@collabora.co.uk> Thanks, pq
pgprWmwnsH2Hm.pgp
Description: OpenPGP digital signature
_______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel