Don't use planes currently in-use on other CRTCs on first commit

When doing the first commit, libliftoff will try to disable all
candidate planes. This is necessary to make sure we start atomic
test commits from a clean state, and are able to incrementally come
up with a combination which works.

However, disabling a plane currently in-use on another CRTC (e.g.
a primary plane) will result in failed commits. We can't steal that
plane without removing it from the other CRTC first.

Add a new liftoff_plane.crtc_id field populated with the current
CRTC ID for the plane.
This commit is contained in:
Simon Ser 2022-08-18 22:01:31 +02:00
parent bcfca8f602
commit a3dc9c48e4
3 changed files with 19 additions and 6 deletions

21
alloc.c
View file

@ -427,7 +427,7 @@ output_choose_layers(struct liftoff_output *output, struct alloc_result *result,
cursor = drmModeAtomicGetCursor(result->req); cursor = drmModeAtomicGetCursor(result->req);
if (plane->layer != NULL) { if (plane->crtc_id != 0) {
goto skip; goto skip;
} }
if ((plane->possible_crtcs & (1 << output->crtc_index)) == 0) { if ((plane->possible_crtcs & (1 << output->crtc_index)) == 0) {
@ -498,14 +498,18 @@ skip:
} }
static int static int
apply_current(struct liftoff_device *device, drmModeAtomicReq *req) apply_current(struct liftoff_output *output, drmModeAtomicReq *req)
{ {
struct liftoff_plane *plane; struct liftoff_plane *plane;
int cursor, ret; int cursor, ret;
cursor = drmModeAtomicGetCursor(req); cursor = drmModeAtomicGetCursor(req);
liftoff_list_for_each(plane, &device->planes, link) { liftoff_list_for_each(plane, &output->device->planes, link) {
if (plane->crtc_id != 0 && plane->crtc_id != output->crtc_id) {
continue;
}
ret = plane_apply(plane, plane->layer, req); ret = plane_apply(plane, plane->layer, req);
assert(ret != -EINVAL); assert(ret != -EINVAL);
if (ret != 0) { if (ret != 0) {
@ -595,7 +599,7 @@ reuse_previous_alloc(struct liftoff_output *output, drmModeAtomicReq *req,
cursor = drmModeAtomicGetCursor(req); cursor = drmModeAtomicGetCursor(req);
ret = apply_current(device, req); ret = apply_current(output, req);
if (ret != 0) { if (ret != 0) {
return ret; return ret;
} }
@ -714,6 +718,10 @@ liftoff_output_apply(struct liftoff_output *output, drmModeAtomicReq *req,
plane->layer->plane = NULL; plane->layer->plane = NULL;
plane->layer = NULL; plane->layer = NULL;
} }
if (plane->crtc_id == output->crtc_id) {
plane->crtc_id = 0;
}
} }
/* Disable all planes we might use. Do it before building mappings to /* Disable all planes we might use. Do it before building mappings to
@ -721,7 +729,7 @@ liftoff_output_apply(struct liftoff_output *output, drmModeAtomicReq *req,
* enabled. */ * enabled. */
candidate_planes = 0; candidate_planes = 0;
liftoff_list_for_each(plane, &device->planes, link) { liftoff_list_for_each(plane, &device->planes, link) {
if (plane->layer == NULL) { if (plane->crtc_id == 0) {
candidate_planes++; candidate_planes++;
liftoff_log(LIFTOFF_DEBUG, liftoff_log(LIFTOFF_DEBUG,
"Disabling plane %"PRIu32, plane->id); "Disabling plane %"PRIu32, plane->id);
@ -786,13 +794,14 @@ liftoff_output_apply(struct liftoff_output *output, drmModeAtomicReq *req,
assert(plane->layer == NULL); assert(plane->layer == NULL);
assert(layer->plane == NULL); assert(layer->plane == NULL);
plane->layer = layer; plane->layer = layer;
plane->crtc_id = layer->output->crtc_id;
layer->plane = plane; layer->plane = plane;
} }
if (i == 0) { if (i == 0) {
liftoff_log(LIFTOFF_DEBUG, " (No layer has a plane)"); liftoff_log(LIFTOFF_DEBUG, " (No layer has a plane)");
} }
ret = apply_current(device, req); ret = apply_current(output, req);
if (ret != 0) { if (ret != 0) {
return ret; return ret;
} }

View file

@ -70,6 +70,9 @@ struct liftoff_plane {
size_t props_len; size_t props_len;
struct liftoff_layer *layer; struct liftoff_layer *layer;
/* Used to avoid picking planes currently in-use by other CRTCs on first
* commit */
uint32_t crtc_id;
}; };
struct liftoff_plane_property { struct liftoff_plane_property {

View file

@ -66,6 +66,7 @@ liftoff_plane_create(struct liftoff_device *device, uint32_t id)
} }
plane->id = drm_plane->plane_id; plane->id = drm_plane->plane_id;
plane->possible_crtcs = drm_plane->possible_crtcs; plane->possible_crtcs = drm_plane->possible_crtcs;
plane->crtc_id = drm_plane->crtc_id;
drmModeFreePlane(drm_plane); drmModeFreePlane(drm_plane);
drm_props = drmModeObjectGetProperties(device->drm_fd, id, drm_props = drmModeObjectGetProperties(device->drm_fd, id,