}
}
+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)
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)
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);
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,
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)
next_plane = primary;
if (next_plane == NULL)
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);
struct drm_backend *b = to_drm_backend(output_base->compositor);
struct drm_pending_state *pending_state = repaint_data;
struct drm_output *output = to_drm_output(output_base);
- struct drm_output_state *state;
+ struct drm_output_state *state = NULL;
struct drm_plane_state *plane_state;
struct weston_view *ev;
struct weston_plane *primary = &output_base->compositor->primary_plane;
- state = drm_output_propose_state(output_base, pending_state);
+ if (!b->sprites_are_broken)
+ state = drm_output_propose_state(output_base, pending_state,
+ DRM_OUTPUT_PROPOSE_STATE_MIXED);
+
+ if (!state)
+ state = drm_output_propose_state(output_base, pending_state,
+ DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY);
+
+ assert(state);
wl_list_for_each(ev, &output_base->compositor->view_list, link) {
struct drm_plane *target_plane = NULL;