compositor: let backends handle output->disable_planes

On weston_output_repaint(), we have:

output_assign_planes(output);
...
output->repaint(output);

output_assign_planes() avoids calling output->assign_planes() when
output->disable_planes > 0. This brings a few complications to backends,
because they can't rely on the repaint loop starting from a certain
function: sometimes it starts from assign_planes(), others from
repaint().

Let's be more consistent: always call assign_planes() and let backends
handle output->disable_planes.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
This commit is contained in:
Leandro Ribeiro 2025-07-04 12:00:20 -03:00 committed by Robert Mader
parent 3eed20254c
commit 3f81d2fd38
4 changed files with 44 additions and 24 deletions

View file

@ -897,18 +897,6 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
connectors[n_conn++] = head->connector.connector_id;
}
/* If disable_planes is set then assign_planes() wasn't
* called for this render, so we could still have a stale
* cursor plane set up.
*/
if (output->base.disable_planes) {
drm_output_set_cursor_view(output, NULL);
if (output->cursor_plane) {
output->cursor_plane->base.x = INT32_MIN;
output->cursor_plane->base.y = INT32_MIN;
}
}
if (state->dpms != WESTON_DPMS_ON) {
if (output->cursor_plane) {
ret = drmModeSetCursor(device->drm.fd, crtc->crtc_id,

View file

@ -48,12 +48,14 @@
enum drm_output_propose_state_mode {
DRM_OUTPUT_PROPOSE_STATE_MIXED, /**< mix renderer & planes */
DRM_OUTPUT_PROPOSE_STATE_RENDERER_AND_CURSOR, /**< only assign to renderer & cursor plane */
DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY, /**< only assign to renderer */
DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY, /**< no renderer use, only planes */
};
static const char *const drm_output_propose_state_mode_as_string[] = {
[DRM_OUTPUT_PROPOSE_STATE_MIXED] = "mixed state",
[DRM_OUTPUT_PROPOSE_STATE_RENDERER_AND_CURSOR] = "renderer-and-cursor state",
[DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY] = "renderer-only state",
[DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY] = "plane-only state"
};
@ -504,6 +506,13 @@ drm_output_find_plane_for_view(struct drm_output_state *state,
pnode->try_view_on_plane_failure_reasons = FAILURE_REASONS_NONE;
/* renderer-only mode, so no view assignments to planes */
if (mode == DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY) {
pnode->try_view_on_plane_failure_reasons |=
FAILURE_REASONS_FORCE_RENDERER;
return NULL;
}
/* filter out non-cursor views in renderer-and-cursor mode */
if (mode == DRM_OUTPUT_PROPOSE_STATE_RENDERER_AND_CURSOR &&
ev->layer_link.layer != &b->compositor->cursor_layer) {
@ -1032,9 +1041,10 @@ drm_output_propose_state(struct weston_output *output_base,
pixman_region32_fini(&renderer_region);
pixman_region32_fini(&occluded_region);
/* In renderer-and-cursor mode, we can't test the state as we don't have
* a renderer buffer yet. */
if (mode == DRM_OUTPUT_PROPOSE_STATE_RENDERER_AND_CURSOR)
/* In renderer-only and renderer-and-cursor modes, we can't test the
* state as we don't have a renderer buffer yet. */
if (mode == DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY ||
mode == DRM_OUTPUT_PROPOSE_STATE_RENDERER_AND_CURSOR)
return state;
/* check if we have invalid zpos values, like duplicate(s) */
@ -1086,7 +1096,8 @@ drm_assign_planes(struct weston_output *output_base)
drm_debug(b, "\t[repaint] preparing state for output %s (%lu)\n",
output_base->name, (unsigned long) output_base->id);
if (!device->sprites_are_broken && !output->is_virtual && b->gbm) {
if (!device->sprites_are_broken && !output_base->disable_planes &&
!output->is_virtual && b->gbm) {
drm_debug(b, "\t[repaint] trying planes-only build state\n");
state = drm_output_propose_state(output_base, pending_state, mode);
if (!state) {
@ -1105,17 +1116,26 @@ drm_assign_planes(struct weston_output *output_base)
* 1. If we didn't enter the last block (for some reason we can't use planes)
* 2. If we entered but both the planes-only and the mixed modes didn't work */
if (!state) {
if (output_base->disable_planes)
mode = DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY;
else
mode = DRM_OUTPUT_PROPOSE_STATE_RENDERER_AND_CURSOR;
drm_debug(b, "\t[repaint] could not build state with planes, "
"trying renderer-and-cursor\n");
mode = DRM_OUTPUT_PROPOSE_STATE_RENDERER_AND_CURSOR;
"trying %s\n",
(mode == DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY) ?
"renderer-only" : "renderer-and-cursor");
state = drm_output_propose_state(output_base, pending_state,
mode);
/* If renderer-and-cursor mode failed and we are in a writeback
* screenshot, let's abort the writeback screenshot and try
* again. */
/* If renderer/renderer-and-cursor mode failed and we are in a
* writeback screenshot, let's abort the writeback screenshot
* and try again. */
if (!state && drm_output_get_writeback_state(output) != DRM_OUTPUT_WB_SCREENSHOT_OFF) {
drm_debug(b, "\t[repaint] could not build renderer-and-cursor "
"state, trying without writeback setup\n");
drm_debug(b, "\t[repaint] could not build %s "
"state, trying without writeback setup\n",
(mode == DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY) ?
"renderer-only" : "renderer-and-cursor");
drm_writeback_fail_screenshot(wb_state, "drm: failed to propose state");
state = drm_output_propose_state(output_base, pending_state,
mode);

View file

@ -1082,6 +1082,9 @@ vnc_output_assign_planes(struct weston_output *base)
assert(output);
if (output->base.disable_planes)
return;
if (wl_list_empty(&output->peers))
return;

View file

@ -3734,9 +3734,18 @@ output_assign_planes(struct weston_output *output)
WESTON_TRACE_FUNC();
struct weston_paint_node *pnode;
if (output->assign_planes && !output->disable_planes) {
if (output->assign_planes) {
/**
* Even if output->disable_planes, we must call assign_planes().
* Each backend should handle that accordingly. This gives the
* backend a consistent starting point for a repaint loop.
*/
output->assign_planes(output);
} else {
/**
* Backend does not have an assign_planes() callback, so move
* all paint nodes to the primary plane.
*/
wl_list_for_each(pnode, &output->paint_node_z_order_list,
z_order_link) {
weston_paint_node_move_to_plane(pnode, &output->primary_plane);