aboutsummaryrefslogtreecommitdiff
path: root/backend/drm
diff options
context:
space:
mode:
Diffstat (limited to 'backend/drm')
-rw-r--r--backend/drm/backend.c11
-rw-r--r--backend/drm/drm.c84
-rw-r--r--backend/drm/util.c19
3 files changed, 100 insertions, 14 deletions
diff --git a/backend/drm/backend.c b/backend/drm/backend.c
index 76918e7d..a9082077 100644
--- a/backend/drm/backend.c
+++ b/backend/drm/backend.c
@@ -65,10 +65,16 @@ static struct wlr_renderer *backend_get_renderer(
}
}
+static clockid_t backend_get_presentation_clock(struct wlr_backend *backend) {
+ struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend);
+ return drm->clock;
+}
+
static struct wlr_backend_impl backend_impl = {
.start = backend_start,
.destroy = backend_destroy,
.get_renderer = backend_get_renderer,
+ .get_presentation_clock = backend_get_presentation_clock,
};
bool wlr_backend_is_drm(struct wlr_backend *b) {
@@ -203,8 +209,3 @@ error_fd:
free(drm);
return NULL;
}
-
-struct wlr_session *wlr_drm_backend_get_session(struct wlr_backend *backend) {
- struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend);
- return drm->session;
-}
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index 784a0233..00525762 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -1,3 +1,4 @@
+#define _POSIX_C_SOURCE 199309L
#include <assert.h>
#include <drm_mode.h>
#include <EGL/egl.h>
@@ -27,8 +28,8 @@
#include "util/signal.h"
bool check_drm_features(struct wlr_drm_backend *drm) {
+ uint64_t cap;
if (drm->parent) {
- uint64_t cap;
if (drmGetCap(drm->fd, DRM_CAP_PRIME, &cap) ||
!(cap & DRM_PRIME_CAP_IMPORT)) {
wlr_log(WLR_ERROR,
@@ -51,16 +52,21 @@ bool check_drm_features(struct wlr_drm_backend *drm) {
const char *no_atomic = getenv("WLR_DRM_NO_ATOMIC");
if (no_atomic && strcmp(no_atomic, "1") == 0) {
- wlr_log(WLR_DEBUG, "WLR_DRM_NO_ATOMIC set, forcing legacy DRM interface");
+ wlr_log(WLR_DEBUG,
+ "WLR_DRM_NO_ATOMIC set, forcing legacy DRM interface");
drm->iface = &legacy_iface;
} else if (drmSetClientCap(drm->fd, DRM_CLIENT_CAP_ATOMIC, 1)) {
- wlr_log(WLR_DEBUG, "Atomic modesetting unsupported, using legacy DRM interface");
+ wlr_log(WLR_DEBUG,
+ "Atomic modesetting unsupported, using legacy DRM interface");
drm->iface = &legacy_iface;
} else {
wlr_log(WLR_DEBUG, "Using atomic DRM interface");
drm->iface = &atomic_iface;
}
+ int ret = drmGetCap(drm->fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap);
+ drm->clock = (ret == 0 && cap == 1) ? CLOCK_MONOTONIC : CLOCK_REALTIME;
+
return true;
}
@@ -150,6 +156,11 @@ bool init_drm_resources(struct wlr_drm_backend *drm) {
wlr_log(WLR_INFO, "Found %d DRM CRTCs", res->count_crtcs);
drm->num_crtcs = res->count_crtcs;
+ if (drm->num_crtcs == 0) {
+ drmModeFreeResources(res);
+ return true;
+ }
+
drm->crtcs = calloc(drm->num_crtcs, sizeof(drm->crtcs[0]));
if (!drm->crtcs) {
wlr_log_errno(WLR_ERROR, "Allocation failed");
@@ -427,9 +438,9 @@ static void realloc_planes(struct wlr_drm_backend *drm, const uint32_t *crtc_in,
continue;
}
- uint32_t possible[drm->num_type_planes[type]];
- uint32_t crtc[drm->num_crtcs];
- uint32_t crtc_res[drm->num_crtcs];
+ uint32_t possible[drm->num_type_planes[type] + 1];
+ uint32_t crtc[drm->num_crtcs + 1];
+ uint32_t crtc_res[drm->num_crtcs + 1];
for (size_t i = 0; i < drm->num_type_planes[type]; ++i) {
possible[i] = drm->type_planes[type][i].possible_crtcs;
@@ -724,6 +735,43 @@ static bool drm_connector_move_cursor(struct wlr_output *output,
return ok;
}
+static void drm_connector_schedule_frame(struct wlr_output *output) {
+ struct wlr_drm_connector *conn = get_drm_connector_from_output(output);
+ struct wlr_drm_backend *drm = get_drm_backend_from_backend(output->backend);
+ if (!drm->session->active) {
+ return;
+ }
+
+ // We need to figure out where we are in the vblank cycle
+ // TODO: try using drmWaitVBlank and fallback to pageflipping
+
+ struct wlr_drm_crtc *crtc = conn->crtc;
+ if (!crtc) {
+ return;
+ }
+ struct wlr_drm_plane *plane = crtc->primary;
+ struct gbm_bo *bo = plane->surf.back;
+ if (!bo) {
+ // We haven't swapped buffers yet -- can't do a pageflip
+ wlr_output_send_frame(output);
+ return;
+ }
+ uint32_t fb_id = get_fb_for_bo(bo);
+
+ if (conn->pageflip_pending) {
+ wlr_log(WLR_ERROR, "Skipping pageflip on output '%s'",
+ conn->output.name);
+ return;
+ }
+
+ if (!drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, NULL)) {
+ return;
+ }
+
+ conn->pageflip_pending = true;
+ wlr_output_update_enabled(output, true);
+}
+
static void drm_connector_destroy(struct wlr_output *output) {
struct wlr_drm_connector *conn = get_drm_connector_from_output(output);
drm_connector_cleanup(conn);
@@ -745,6 +793,7 @@ static const struct wlr_output_impl output_impl = {
.set_gamma = set_drm_connector_gamma,
.get_gamma_size = drm_connector_get_gamma_size,
.export_dmabuf = drm_connector_export_dmabuf,
+ .schedule_frame = drm_connector_schedule_frame,
};
bool wlr_output_is_drm(struct wlr_output *output) {
@@ -1134,7 +1183,7 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) {
}
}
- bool changed_outputs[wl_list_length(&drm->outputs)];
+ bool changed_outputs[wl_list_length(&drm->outputs) + 1];
memset(changed_outputs, false, sizeof(changed_outputs));
for (size_t i = 0; i < new_outputs_len; ++i) {
struct wlr_drm_connector *conn = new_outputs[i];
@@ -1166,9 +1215,13 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) {
attempt_enable_needs_modeset(drm);
}
+static int mhz_to_nsec(int mhz) {
+ return 1000000000000LL / mhz;
+}
+
static void page_flip_handler(int fd, unsigned seq,
- unsigned tv_sec, unsigned tv_usec, void *user) {
- struct wlr_drm_connector *conn = user;
+ unsigned tv_sec, unsigned tv_usec, void *data) {
+ struct wlr_drm_connector *conn = data;
struct wlr_drm_backend *drm =
get_drm_backend_from_backend(conn->output.backend);
@@ -1188,6 +1241,19 @@ static void page_flip_handler(int fd, unsigned seq,
post_drm_surface(&conn->crtc->primary->mgpu_surf);
}
+ struct timespec present_time = {
+ .tv_sec = tv_sec,
+ .tv_nsec = tv_usec * 1000,
+ };
+ struct wlr_output_event_present present_event = {
+ .when = &present_time,
+ .seq = seq,
+ .refresh = mhz_to_nsec(conn->output.refresh),
+ .flags = WLR_OUTPUT_PRESENT_VSYNC | WLR_OUTPUT_PRESENT_HW_CLOCK |
+ WLR_OUTPUT_PRESENT_HW_COMPLETION,
+ };
+ wlr_output_send_present(&conn->output, &present_event);
+
if (drm->session->active) {
wlr_output_send_frame(&conn->output);
}
diff --git a/backend/drm/util.c b/backend/drm/util.c
index f9637c33..6b2c0981 100644
--- a/backend/drm/util.c
+++ b/backend/drm/util.c
@@ -32,21 +32,30 @@ static const char *get_manufacturer(uint16_t id) {
case ID('A', 'A', 'A'): return "Avolites Ltd";
case ID('A', 'C', 'I'): return "Ancor Communications Inc";
case ID('A', 'C', 'R'): return "Acer Technologies";
+ case ID('A', 'D', 'A'): return "Addi-Data GmbH";
case ID('A', 'P', 'P'): return "Apple Computer Inc";
+ case ID('A', 'S', 'K'): return "Ask A/S";
+ case ID('A', 'V', 'T'): return "Avtek (Electronics) Pty Ltd";
case ID('B', 'N', 'O'): return "Bang & Olufsen";
case ID('C', 'M', 'N'): return "Chimei Innolux Corporation";
case ID('C', 'M', 'O'): return "Chi Mei Optoelectronics corp.";
case ID('C', 'R', 'O'): return "Extraordinary Technologies PTY Limited";
case ID('D', 'E', 'L'): return "Dell Inc.";
+ case ID('D', 'G', 'C'): return "Data General Corporation";
case ID('D', 'O', 'N'): return "DENON, Ltd.";
case ID('E', 'N', 'C'): return "Eizo Nanao Corporation";
case ID('E', 'P', 'H'): return "Epiphan Systems Inc.";
+ case ID('E', 'X', 'P'): return "Data Export Corporation";
+ case ID('F', 'N', 'I'): return "Funai Electric Co., Ltd.";
case ID('F', 'U', 'S'): return "Fujitsu Siemens Computers GmbH";
case ID('G', 'S', 'M'): return "Goldstar Company Ltd";
case ID('H', 'I', 'Q'): return "Kaohsiung Opto Electronics Americas, Inc.";
case ID('H', 'S', 'D'): return "HannStar Display Corp";
+ case ID('H', 'T', 'C'): return "Hitachi Ltd";
case ID('H', 'W', 'P'): return "Hewlett Packard";
case ID('I', 'N', 'T'): return "Interphase Corporation";
+ case ID('I', 'N', 'X'): return "Communications Supply Corporation (A division of WESCO)";
+ case ID('I', 'T', 'E'): return "Integrated Tech Express Inc";
case ID('I', 'V', 'M'): return "Iiyama North America";
case ID('L', 'E', 'N'): return "Lenovo Group Limited";
case ID('M', 'A', 'X'): return "Rogen Tech Distribution Inc";
@@ -55,6 +64,7 @@ static const char *get_manufacturer(uint16_t id) {
case ID('M', 'T', 'C'): return "Mars-Tech Corporation";
case ID('M', 'T', 'X'): return "Matrox";
case ID('N', 'E', 'C'): return "NEC Corporation";
+ case ID('N', 'E', 'X'): return "Nexgen Mediatech Inc.";
case ID('O', 'N', 'K'): return "ONKYO Corporation";
case ID('O', 'R', 'N'): return "ORION ELECTRIC CO., LTD.";
case ID('O', 'T', 'M'): return "Optoma Corporation";
@@ -63,15 +73,24 @@ static const char *get_manufacturer(uint16_t id) {
case ID('P', 'I', 'O'): return "Pioneer Electronic Corporation";
case ID('P', 'N', 'R'): return "Planar Systems, Inc.";
case ID('Q', 'D', 'S'): return "Quanta Display Inc.";
+ case ID('R', 'A', 'T'): return "Rent-A-Tech";
+ case ID('R', 'E', 'N'): return "Renesas Technology Corp.";
case ID('S', 'A', 'M'): return "Samsung Electric Company";
+ case ID('S', 'A', 'N'): return "Sanyo Electric Co., Ltd.";
case ID('S', 'E', 'C'): return "Seiko Epson Corporation";
case ID('S', 'H', 'P'): return "Sharp Corporation";
case ID('S', 'I', 'I'): return "Silicon Image, Inc.";
case ID('S', 'N', 'Y'): return "Sony";
+ case ID('S', 'T', 'D'): return "STD Computer Inc";
+ case ID('S', 'V', 'S'): return "SVSI";
+ case ID('S', 'Y', 'N'): return "Synaptics Inc";
+ case ID('T', 'C', 'L'): return "Technical Concepts Ltd";
case ID('T', 'O', 'P'): return "Orion Communications Co., Ltd.";
case ID('T', 'S', 'B'): return "Toshiba America Info Systems Inc";
case ID('T', 'S', 'T'): return "Transtream Inc";
case ID('U', 'N', 'K'): return "Unknown";
+ case ID('V', 'E', 'S'): return "Vestel Elektronik Sanayi ve Ticaret A. S.";
+ case ID('V', 'I', 'T'): return "Visitech AS";
case ID('V', 'I', 'Z'): return "VIZIO, Inc";
case ID('V', 'S', 'C'): return "ViewSonic Corporation";
case ID('Y', 'M', 'H'): return "Yamaha Corporation";