2020-01-13 12:22:47 +01:00
|
|
|
#include <errno.h>
|
2019-08-21 22:07:37 +02:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
2019-10-07 08:47:53 +02:00
|
|
|
#include "log.h"
|
2019-08-21 22:07:37 +02:00
|
|
|
#include "private.h"
|
|
|
|
|
2021-08-13 22:02:33 +02:00
|
|
|
struct liftoff_device *
|
|
|
|
liftoff_device_create(int drm_fd)
|
2019-08-21 22:07:37 +02:00
|
|
|
{
|
2019-11-24 12:59:10 +01:00
|
|
|
struct liftoff_device *device;
|
2019-09-08 16:41:25 +02:00
|
|
|
drmModeRes *drm_res;
|
2023-02-06 10:57:13 +01:00
|
|
|
drmModePlaneRes *drm_plane_res;
|
2019-08-21 22:07:37 +02:00
|
|
|
|
2019-11-24 12:59:10 +01:00
|
|
|
device = calloc(1, sizeof(*device));
|
|
|
|
if (device == NULL) {
|
2019-10-19 12:35:14 +02:00
|
|
|
liftoff_log_errno(LIFTOFF_ERROR, "calloc");
|
2019-08-21 22:07:37 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
2019-09-12 19:15:50 +02:00
|
|
|
|
2019-11-24 12:59:10 +01:00
|
|
|
liftoff_list_init(&device->planes);
|
|
|
|
liftoff_list_init(&device->outputs);
|
2019-09-12 19:15:50 +02:00
|
|
|
|
2019-11-24 12:59:10 +01:00
|
|
|
device->drm_fd = dup(drm_fd);
|
|
|
|
if (device->drm_fd < 0) {
|
2019-10-19 12:35:14 +02:00
|
|
|
liftoff_log_errno(LIFTOFF_ERROR, "dup");
|
2019-11-24 12:59:10 +01:00
|
|
|
liftoff_device_destroy(device);
|
2019-08-21 22:07:37 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-09-08 16:41:25 +02:00
|
|
|
drm_res = drmModeGetResources(drm_fd);
|
|
|
|
if (drm_res == NULL) {
|
2019-10-19 12:35:14 +02:00
|
|
|
liftoff_log_errno(LIFTOFF_ERROR, "drmModeGetResources");
|
2019-11-24 12:59:10 +01:00
|
|
|
liftoff_device_destroy(device);
|
2019-09-08 16:41:25 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2023-02-16 21:33:36 +01:00
|
|
|
device->crtcs_len = (size_t)drm_res->count_crtcs;
|
|
|
|
device->crtcs = malloc(device->crtcs_len * sizeof(device->crtcs[0]));
|
2019-11-24 12:59:10 +01:00
|
|
|
if (device->crtcs == NULL) {
|
2019-10-19 12:35:14 +02:00
|
|
|
liftoff_log_errno(LIFTOFF_ERROR, "malloc");
|
2019-09-08 16:41:25 +02:00
|
|
|
drmModeFreeResources(drm_res);
|
2019-11-24 12:59:10 +01:00
|
|
|
liftoff_device_destroy(device);
|
2019-09-08 16:41:25 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
2023-02-16 21:33:36 +01:00
|
|
|
memcpy(device->crtcs, drm_res->crtcs, device->crtcs_len * sizeof(device->crtcs[0]));
|
2019-09-08 16:41:25 +02:00
|
|
|
|
|
|
|
drmModeFreeResources(drm_res);
|
|
|
|
|
2023-02-06 10:57:13 +01:00
|
|
|
drm_plane_res = drmModeGetPlaneResources(device->drm_fd);
|
|
|
|
if (drm_plane_res == NULL) {
|
|
|
|
liftoff_log_errno(LIFTOFF_ERROR, "drmModeGetPlaneResources");
|
|
|
|
liftoff_device_destroy(device);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
device->planes_cap = drm_plane_res->count_planes;
|
|
|
|
drmModeFreePlaneResources(drm_plane_res);
|
|
|
|
|
2019-11-24 12:59:10 +01:00
|
|
|
return device;
|
2019-08-21 22:07:37 +02:00
|
|
|
}
|
|
|
|
|
2021-08-13 22:02:33 +02:00
|
|
|
void
|
|
|
|
liftoff_device_destroy(struct liftoff_device *device)
|
2019-08-21 22:07:37 +02:00
|
|
|
{
|
2019-09-12 10:39:06 +02:00
|
|
|
struct liftoff_plane *plane, *tmp;
|
2019-08-21 22:07:37 +02:00
|
|
|
|
2019-12-31 20:46:08 +01:00
|
|
|
if (device == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-11-24 12:59:10 +01:00
|
|
|
close(device->drm_fd);
|
|
|
|
liftoff_list_for_each_safe(plane, tmp, &device->planes, link) {
|
2021-02-23 18:01:38 +01:00
|
|
|
liftoff_plane_destroy(plane);
|
2019-08-21 22:07:37 +02:00
|
|
|
}
|
2019-11-24 12:59:10 +01:00
|
|
|
free(device->crtcs);
|
|
|
|
free(device);
|
2019-08-21 22:07:37 +02:00
|
|
|
}
|
2020-01-13 12:22:47 +01:00
|
|
|
|
2021-08-13 22:02:33 +02:00
|
|
|
int
|
|
|
|
liftoff_device_register_all_planes(struct liftoff_device *device)
|
2021-02-23 18:01:38 +01:00
|
|
|
{
|
|
|
|
drmModePlaneRes *drm_plane_res;
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
drm_plane_res = drmModeGetPlaneResources(device->drm_fd);
|
|
|
|
if (drm_plane_res == NULL) {
|
|
|
|
liftoff_log_errno(LIFTOFF_ERROR, "drmModeGetPlaneResources");
|
2021-07-30 16:19:29 +02:00
|
|
|
return -errno;
|
2021-02-23 18:01:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < drm_plane_res->count_planes; i++) {
|
|
|
|
if (liftoff_plane_create(device, drm_plane_res->planes[i]) == NULL) {
|
2021-07-30 16:19:29 +02:00
|
|
|
return -errno;
|
2021-02-23 18:01:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
drmModeFreePlaneResources(drm_plane_res);
|
|
|
|
|
2021-07-30 16:19:29 +02:00
|
|
|
return 0;
|
2021-02-23 18:01:38 +01:00
|
|
|
}
|
|
|
|
|
2021-08-13 22:02:33 +02:00
|
|
|
int
|
|
|
|
device_test_commit(struct liftoff_device *device, drmModeAtomicReq *req,
|
|
|
|
uint32_t flags)
|
2020-01-13 12:22:47 +01:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2021-09-30 09:41:39 +02:00
|
|
|
device->test_commit_counter++;
|
|
|
|
|
2023-02-16 21:33:36 +01:00
|
|
|
flags &= ~(uint32_t)DRM_MODE_PAGE_FLIP_EVENT;
|
2020-01-13 12:26:31 +01:00
|
|
|
do {
|
|
|
|
ret = drmModeAtomicCommit(device->drm_fd, req,
|
2020-11-10 16:27:55 +01:00
|
|
|
DRM_MODE_ATOMIC_TEST_ONLY | flags,
|
|
|
|
NULL);
|
2021-07-27 12:28:00 +02:00
|
|
|
} while (ret == -EINTR || ret == -EAGAIN);
|
|
|
|
|
2021-10-08 13:00:40 +02:00
|
|
|
/* The kernel will return -EINVAL for invalid configuration, -ERANGE for
|
|
|
|
* CRTC coords overflow, and -ENOSPC for invalid SRC coords. */
|
|
|
|
if (ret != 0 && ret != -EINVAL && ret != -ERANGE && ret != -ENOSPC) {
|
2021-07-27 12:28:00 +02:00
|
|
|
liftoff_log(LIFTOFF_ERROR, "drmModeAtomicCommit: %s",
|
|
|
|
strerror(-ret));
|
2020-01-13 12:22:47 +01:00
|
|
|
}
|
|
|
|
|
2021-07-27 12:28:00 +02:00
|
|
|
return ret;
|
2020-01-13 12:22:47 +01:00
|
|
|
}
|