wip: backend/drm: add libliftoff interface

TODO:

- Make it work on multi-output setups
- Make it handle VRR and gamma
This commit is contained in:
Simon Ser 2021-08-09 15:19:06 +02:00
parent 937204d769
commit f7276aaf2f
6 changed files with 263 additions and 1 deletions

View file

@ -5,12 +5,14 @@
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <libliftoff.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <time.h>
#include <unistd.h>
#include <wayland-server-core.h>
#include <wayland-util.h>
#include <wlr/backend/interface.h>
@ -72,8 +74,17 @@ bool check_drm_features(struct wlr_drm_backend *drm) {
return false;
}
const char *force_libliftoff = getenv("WLR_DRM_FORCE_LIBLIFTOFF");
const char *no_atomic = getenv("WLR_DRM_NO_ATOMIC");
if (no_atomic && strcmp(no_atomic, "1") == 0) {
if (force_libliftoff && strcmp(force_libliftoff, "1") == 0) {
wlr_log(WLR_DEBUG,
"WLR_FORCE_LIBLIFTOFF set, forcing libliftoff interface");
if (drmSetClientCap(drm->fd, DRM_CLIENT_CAP_ATOMIC, 1) != 0) {
wlr_log_errno(WLR_ERROR, "drmSetClientCap(ATOMIC) failed");
return false;
}
drm->iface = &libliftoff_iface;
} else if (no_atomic && strcmp(no_atomic, "1") == 0) {
wlr_log(WLR_DEBUG,
"WLR_DRM_NO_ATOMIC set, forcing legacy DRM interface");
drm->iface = &legacy_iface;
@ -250,6 +261,57 @@ error:
return false;
}
static bool init_libliftoff(struct wlr_drm_backend *drm) {
// TODO: lower log level
liftoff_log_set_priority(LIFTOFF_DEBUG);
int drm_fd = fcntl(drm->fd, F_DUPFD_CLOEXEC, 0);
if (drm_fd < 0) {
wlr_log_errno(WLR_ERROR, "fcntl(F_DUPFD_CLOEXEC) failed");
return false;
}
drm->liftoff = liftoff_device_create(drm_fd);
if (!drm->liftoff) {
wlr_log(WLR_ERROR, "Failed to create liftoff device");
close(drm_fd);
return false;
}
if (liftoff_device_register_all_planes(drm->liftoff) != 0) {
wlr_log(WLR_ERROR, "Failed to register liftoff planes");
return false;
}
for (size_t i = 0; i < drm->num_crtcs; i++) {
struct wlr_drm_crtc *crtc = &drm->crtcs[i];
crtc->liftoff = liftoff_output_create(drm->liftoff, crtc->id);
if (!crtc->liftoff) {
wlr_log(WLR_ERROR, "Failed to create liftoff output");
return false;
}
if (crtc->primary) {
crtc->primary->liftoff_layer = liftoff_layer_create(crtc->liftoff);
if (!crtc->primary->liftoff_layer) {
wlr_log(WLR_ERROR, "Failed to create liftoff layer for primary plane");
return false;
}
}
if (crtc->cursor) {
crtc->cursor->liftoff_layer = liftoff_layer_create(crtc->liftoff);
if (!crtc->cursor->liftoff_layer) {
wlr_log(WLR_ERROR, "Failed to create liftoff layer for cursor plane");
return false;
}
}
}
return true;
}
bool init_drm_resources(struct wlr_drm_backend *drm) {
drmModeRes *res = drmModeGetResources(drm->fd);
if (!res) {
@ -284,6 +346,10 @@ bool init_drm_resources(struct wlr_drm_backend *drm) {
drmModeFreeResources(res);
if (drm->iface == &libliftoff_iface && !init_libliftoff(drm)) {
goto error_crtcs;
}
return true;
error_crtcs:
@ -311,15 +377,20 @@ void finish_drm_resources(struct wlr_drm_backend *drm) {
}
if (crtc->primary) {
liftoff_layer_destroy(crtc->primary->liftoff_layer);
wlr_drm_format_set_finish(&crtc->primary->formats);
free(crtc->primary);
}
if (crtc->cursor) {
liftoff_layer_destroy(crtc->cursor->liftoff_layer);
wlr_drm_format_set_finish(&crtc->cursor->formats);
free(crtc->cursor);
}
liftoff_output_destroy(crtc->liftoff);
}
liftoff_device_destroy(drm->liftoff);
free(drm->crtcs);
}