backend/drm: implement the output layer API

Delegate all of the work to libliftoff.
This commit is contained in:
Simon Ser 2021-08-10 00:33:48 +02:00
parent e45ddda7bc
commit 2a3861024e
3 changed files with 134 additions and 2 deletions

View file

@ -76,6 +76,37 @@ static bool disable_plane(struct wlr_drm_plane *plane) {
return liftoff_layer_set_property(plane->liftoff_layer, "FB_ID", 0) == 0;
}
static bool set_layer_props(struct wlr_drm_layer *layer, uint64_t zpos) {
bool ok = liftoff_layer_set_property(layer->liftoff, "zpos", zpos) == 0 &&
liftoff_layer_set_property(layer->liftoff, "CRTC_X", layer->base.pending.x) == 0 &&
liftoff_layer_set_property(layer->liftoff, "CRTC_Y", layer->base.pending.y) == 0;
if (layer->base.pending.committed & WLR_OUTPUT_LAYER_STATE_BUFFER) {
struct wlr_buffer *buffer = layer->base.pending.buffer;
uint64_t width = buffer->width;
uint64_t height = buffer->height;
ok = ok &&
liftoff_layer_set_property(layer->liftoff, "SRC_X", 0) == 0 &&
liftoff_layer_set_property(layer->liftoff, "SRC_Y", 0) == 0 &&
liftoff_layer_set_property(layer->liftoff, "SRC_W", width << 16) == 0 &&
liftoff_layer_set_property(layer->liftoff, "SRC_H", height << 16) == 0 &&
liftoff_layer_set_property(layer->liftoff, "CRTC_W", width) == 0 &&
liftoff_layer_set_property(layer->liftoff, "CRTC_H", height) == 0;
struct wlr_drm_fb *fb = layer->pending_fb;
if (fb == NULL) {
// We couldn't import the buffer to KMS. Force the layer to be
// composited.
liftoff_layer_set_fb_composited(layer->liftoff);
} else {
ok = ok && liftoff_layer_set_property(layer->liftoff, "FB_ID", fb->id) == 0;
}
}
return ok;
}
static bool liftoff_crtc_commit(struct wlr_drm_connector *conn,
const struct wlr_drm_connector_state *state, uint32_t flags,
bool test_only) {
@ -116,17 +147,41 @@ static bool liftoff_crtc_commit(struct wlr_drm_connector *conn,
if (crtc->cursor) {
if (drm_connector_is_cursor_visible(conn)) {
ok = ok && set_plane_props(crtc->cursor,
crtc->cursor->liftoff_layer,
conn->cursor_x, conn->cursor_y, 1);
crtc->cursor->liftoff_layer, conn->cursor_x, conn->cursor_y,
wl_list_length(&state->base->layers) + 1);
} else {
ok = ok && disable_plane(crtc->cursor);
}
}
size_t i = 0;
struct wlr_drm_layer *layer;
wl_list_for_each(layer, &state->base->layers, base.pending.link) {
if (layer->liftoff == NULL) {
layer->liftoff = liftoff_layer_create(crtc->liftoff);
if (layer->liftoff == NULL) {
wlr_log(WLR_ERROR, "Failed to create libliftoff layer");
continue;
}
}
layer->base.accepted = false;
ok = ok && set_layer_props(layer, i + 1);
i++;
}
} else {
ok = ok && disable_plane(crtc->primary);
if (crtc->cursor) {
ok = ok && disable_plane(crtc->cursor);
}
struct wlr_drm_layer *layer;
wl_list_for_each(layer, &state->base->layers, base.pending.link) {
if (layer->liftoff != NULL) {
liftoff_layer_set_property(layer->liftoff, "FB_ID", 0);
}
}
}
if (!ok) {
@ -148,6 +203,13 @@ static bool liftoff_crtc_commit(struct wlr_drm_connector *conn,
goto out;
}
struct wlr_drm_layer *layer;
wl_list_for_each(layer, &state->base->layers, base.pending.link) {
if (layer->liftoff != NULL) {
layer->base.accepted = !liftoff_layer_needs_composition(layer->liftoff);
}
}
ret = drmModeAtomicCommit(drm->fd, req, flags, drm);
if (ret != 0) {
wlr_drm_conn_log_errno(conn, test_only ? WLR_DEBUG : WLR_ERROR,