aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/drm/drm.c522
-rw-r--r--include/backend/drm/drm.h39
2 files changed, 223 insertions, 338 deletions
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index 47857df7..7ff8c7f5 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -1,4 +1,4 @@
-#define _POSIX_C_SOURCE 200112L
+#define _XOPEN_SOURCE 700
#include <assert.h>
#include <drm_fourcc.h>
#include <drm_mode.h>
@@ -10,6 +10,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <time.h>
#include <wayland-server.h>
#include <wayland-util.h>
@@ -72,11 +73,86 @@ bool check_drm_features(struct wlr_drm_backend *drm) {
return true;
}
-static int cmp_plane(const void *arg1, const void *arg2) {
- const struct wlr_drm_plane *a = arg1;
- const struct wlr_drm_plane *b = arg2;
+static bool add_plane(struct wlr_drm_backend *drm,
+ struct wlr_drm_crtc *crtc, drmModePlane *drm_plane,
+ uint32_t type, union wlr_drm_plane_props *props) {
+ assert(!(type == DRM_PLANE_TYPE_PRIMARY && crtc->primary));
- return (int)a->type - (int)b->type;
+ if (type == DRM_PLANE_TYPE_CURSOR && crtc->cursor) {
+ return true;
+ }
+
+ struct wlr_drm_plane *p = calloc(1, sizeof(*p));
+ if (!p) {
+ wlr_log_errno(WLR_ERROR, "Allocation failed");
+ return false;
+ }
+
+ p->type = type;
+ p->id = drm_plane->plane_id;
+ p->props = *props;
+
+ // Choose an RGB format for the plane
+ uint32_t rgb_format = DRM_FORMAT_INVALID;
+ for (size_t j = 0; j < drm_plane->count_formats; ++j) {
+ uint32_t fmt = drm_plane->formats[j];
+ wlr_drm_format_set_add(&p->formats, fmt, DRM_FORMAT_MOD_INVALID);
+
+ if (fmt == DRM_FORMAT_ARGB8888) {
+ // Prefer formats with alpha channel
+ rgb_format = fmt;
+ break;
+ } else if (fmt == DRM_FORMAT_XRGB8888) {
+ rgb_format = fmt;
+ }
+ }
+ p->drm_format = rgb_format;
+
+ if (p->props.in_formats) {
+ uint64_t blob_id;
+ if (!get_drm_prop(drm->fd, p->id, p->props.in_formats, &blob_id)) {
+ wlr_log(WLR_ERROR, "Failed to read IN_FORMATS property");
+ goto error;
+ }
+
+ drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(drm->fd, blob_id);
+ if (!blob) {
+ wlr_log(WLR_ERROR, "Failed to read IN_FORMATS blob");
+ goto error;
+ }
+
+ struct drm_format_modifier_blob *data = blob->data;
+ uint32_t *fmts = (uint32_t *)((char *)data + data->formats_offset);
+ struct drm_format_modifier *mods = (struct drm_format_modifier *)
+ ((char *)data + data->modifiers_offset);
+ for (uint32_t i = 0; i < data->count_modifiers; ++i) {
+ for (int j = 0; j < 64; ++j) {
+ if (mods[i].formats & ((uint64_t)1 << j)) {
+ wlr_drm_format_set_add(&p->formats,
+ fmts[j + mods[i].offset], mods[i].modifier);
+ }
+ }
+ }
+
+ drmModeFreePropertyBlob(blob);
+ }
+
+ switch (type) {
+ case DRM_PLANE_TYPE_PRIMARY:
+ crtc->primary = p;
+ break;
+ case DRM_PLANE_TYPE_CURSOR:
+ crtc->cursor = p;
+ break;
+ default:
+ abort();
+ }
+
+ return true;
+
+error:
+ free(p);
+ return false;
}
static bool init_planes(struct wlr_drm_backend *drm) {
@@ -88,118 +164,72 @@ static bool init_planes(struct wlr_drm_backend *drm) {
wlr_log(WLR_INFO, "Found %"PRIu32" DRM planes", plane_res->count_planes);
- if (plane_res->count_planes == 0) {
- drmModeFreePlaneResources(plane_res);
- return true;
- }
-
- drm->num_planes = plane_res->count_planes;
- drm->planes = calloc(drm->num_planes, sizeof(*drm->planes));
- if (!drm->planes) {
- wlr_log_errno(WLR_ERROR, "Allocation failed");
- goto error_res;
- }
-
- for (size_t i = 0; i < drm->num_planes; ++i) {
- struct wlr_drm_plane *p = &drm->planes[i];
+ for (uint32_t i = 0; i < plane_res->count_planes; ++i) {
+ uint32_t id = plane_res->planes[i];
- drmModePlane *plane = drmModeGetPlane(drm->fd, plane_res->planes[i]);
+ drmModePlane *plane = drmModeGetPlane(drm->fd, id);
if (!plane) {
wlr_log_errno(WLR_ERROR, "Failed to get DRM plane");
- goto error_planes;
+ goto error;
}
- p->id = plane->plane_id;
- p->possible_crtcs = plane->possible_crtcs;
+ union wlr_drm_plane_props props = {0};
+ if (!get_drm_plane_props(drm->fd, id, &props)) {
+ drmModeFreePlane(plane);
+ goto error;
+ }
uint64_t type;
- if (!get_drm_plane_props(drm->fd, p->id, &p->props) ||
- !get_drm_prop(drm->fd, p->id, p->props.type, &type)) {
+ if (!get_drm_prop(drm->fd, id, props.type, &type)) {
drmModeFreePlane(plane);
- goto error_planes;
+ goto error;
}
- p->type = type;
- drm->num_type_planes[type]++;
-
- // Choose an RGB format for the plane
- uint32_t rgb_format = DRM_FORMAT_INVALID;
- for (size_t j = 0; j < plane->count_formats; ++j) {
- uint32_t fmt = plane->formats[j];
- wlr_drm_format_set_add(&p->formats, fmt, DRM_FORMAT_MOD_INVALID);
-
- if (fmt == DRM_FORMAT_ARGB8888) {
- // Prefer formats with alpha channel
- rgb_format = fmt;
- break;
- } else if (fmt == DRM_FORMAT_XRGB8888) {
- rgb_format = fmt;
+ /*
+ * This is a very naive implementation of the plane matching
+ * logic. Primary and cursor planes should only work on a
+ * single CRTC, and this should be perfectly adequate, but
+ * overlay planes can potentially work with multiple CRTCs,
+ * meaning this could return inefficent/skewed results.
+ *
+ * However, we don't really care about overlay planes, as we
+ * don't support them yet. We only bother to keep basic
+ * tracking of them for DRM lease clients.
+ *
+ * possible_crtcs is a bitmask of crtcs, where each bit is an
+ * index into drmModeRes.crtcs. So if bit 0 is set (ffs starts
+ * counting from 1), crtc 0 is possible.
+ */
+ int crtc_bit = ffs(plane->possible_crtcs) - 1;
+
+ // This would be a kernel bug
+ assert(crtc_bit >= 0 && (size_t)crtc_bit < drm->num_crtcs);
+
+ struct wlr_drm_crtc *crtc = &drm->crtcs[crtc_bit];
+
+ if (type == DRM_PLANE_TYPE_OVERLAY) {
+ uint32_t *tmp = realloc(crtc->overlays,
+ sizeof(*crtc->overlays) * (crtc->num_overlays + 1));
+ if (tmp) {
+ crtc->overlays = tmp;
+ crtc->overlays[crtc->num_overlays++] = id;
}
- }
- // Some overlays exist which don't support XRGB8888/ARGB8888
- // We aren't even using overlay planes currently, so don't fail
- // on something unnecessary.
- if (type != DRM_PLANE_TYPE_OVERLAY && rgb_format == DRM_FORMAT_INVALID) {
- wlr_log(WLR_ERROR, "Failed to find an RGB format for plane %zu", i);
drmModeFreePlane(plane);
- goto error_planes;
+ continue;
}
- p->drm_format = rgb_format;
-
- if (p->props.in_formats) {
- uint64_t blob_id;
- if (!get_drm_prop(drm->fd, p->id, p->props.in_formats, &blob_id)) {
- wlr_log(WLR_ERROR, "Failed to read IN_FORMATS property");
- drmModeFreePlane(plane);
- goto error_planes;
- }
-
- drmModePropertyBlobRes *blob =
- drmModeGetPropertyBlob(drm->fd, blob_id);
- if (!blob) {
- wlr_log(WLR_ERROR, "Failed to read IN_FORMATS blob");
- drmModeFreePlane(plane);
- goto error_planes;
- }
-
- struct drm_format_modifier_blob *data = blob->data;
- uint32_t *fmts = (uint32_t *)((char *)data + data->formats_offset);
- struct drm_format_modifier *mods = (struct drm_format_modifier *)
- ((char *)data + data->modifiers_offset);
- for (uint32_t i = 0; i < data->count_modifiers; ++i) {
- for (int j = 0; j < 64; ++j) {
- if (mods[i].formats & ((uint64_t)1 << j)) {
- wlr_drm_format_set_add(&p->formats,
- fmts[j + mods[i].offset], mods[i].modifier);
- }
- }
- }
- drmModeFreePropertyBlob(blob);
+ if (!add_plane(drm, crtc, plane, type, &props)) {
+ drmModeFreePlane(plane);
+ goto error;
}
drmModeFreePlane(plane);
}
- wlr_log(WLR_INFO, "(%zu overlay, %zu primary, %zu cursor)",
- drm->num_overlay_planes,
- drm->num_primary_planes,
- drm->num_cursor_planes);
-
- qsort(drm->planes, drm->num_planes, sizeof(*drm->planes), cmp_plane);
-
- drm->overlay_planes = drm->planes;
- drm->primary_planes = drm->overlay_planes
- + drm->num_overlay_planes;
- drm->cursor_planes = drm->primary_planes
- + drm->num_primary_planes;
-
drmModeFreePlaneResources(plane_res);
return true;
-error_planes:
- free(drm->planes);
-error_res:
+error:
drmModeFreePlaneResources(plane_res);
return false;
}
@@ -252,26 +282,33 @@ void finish_drm_resources(struct wlr_drm_backend *drm) {
return;
}
- for (size_t i = 0; i < drm->num_planes; ++i) {
- struct wlr_drm_plane *p = &drm->planes[i];
- wlr_drm_format_set_finish(&p->formats);
- }
-
for (size_t i = 0; i < drm->num_crtcs; ++i) {
struct wlr_drm_crtc *crtc = &drm->crtcs[i];
+
drmModeAtomicFree(crtc->atomic);
drmModeFreeCrtc(crtc->legacy_crtc);
+
if (crtc->mode_id) {
drmModeDestroyPropertyBlob(drm->fd, crtc->mode_id);
}
if (crtc->gamma_lut) {
drmModeDestroyPropertyBlob(drm->fd, crtc->gamma_lut);
}
+
free(crtc->gamma_table);
+
+ if (crtc->primary) {
+ wlr_drm_format_set_finish(&crtc->primary->formats);
+ free(crtc->primary);
+ }
+ if (crtc->cursor) {
+ wlr_drm_format_set_finish(&crtc->cursor->formats);
+ free(crtc->cursor);
+ }
+ free(crtc->overlays);
}
free(drm->crtcs);
- free(drm->planes);
}
static struct wlr_drm_connector *get_drm_connector_from_output(
@@ -477,7 +514,7 @@ static void drm_connector_start_renderer(struct wlr_drm_connector *conn) {
}
}
-static void realloc_crtcs(struct wlr_drm_backend *drm, bool *changed_outputs);
+static void realloc_crtcs(struct wlr_drm_backend *drm);
static void attempt_enable_needs_modeset(struct wlr_drm_backend *drm) {
// Try to modeset any output that has a desired mode and a CRTC (ie. was
@@ -506,7 +543,7 @@ bool enable_drm_connector(struct wlr_output *output, bool enable) {
if (enable && conn->crtc == NULL) {
// Maybe we can steal a CRTC from a disabled output
- realloc_crtcs(drm, NULL);
+ realloc_crtcs(drm);
}
bool ok = drm->iface->conn_enable(drm, conn, enable);
@@ -517,7 +554,7 @@ bool enable_drm_connector(struct wlr_output *output, bool enable) {
if (enable) {
drm_connector_start_renderer(conn);
} else {
- realloc_crtcs(drm, NULL);
+ realloc_crtcs(drm);
attempt_enable_needs_modeset(drm);
}
@@ -526,82 +563,6 @@ bool enable_drm_connector(struct wlr_output *output, bool enable) {
return true;
}
-static ssize_t connector_index_from_crtc(struct wlr_drm_backend *drm,
- struct wlr_drm_crtc *crtc) {
- size_t i = 0;
- struct wlr_drm_connector *conn;
- wl_list_for_each(conn, &drm->outputs, link) {
- if (conn->crtc == crtc) {
- return i;
- }
- ++i;
- }
- return -1;
-}
-
-static void realloc_planes(struct wlr_drm_backend *drm, const uint32_t *crtc_in,
- bool *changed_outputs) {
- wlr_log(WLR_DEBUG, "Reallocating planes");
-
- // overlay, primary, cursor
- for (size_t type = 0; type < 3; ++type) {
- if (drm->num_type_planes[type] == 0) {
- continue;
- }
-
- 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;
- }
-
- for (size_t i = 0; i < drm->num_crtcs; ++i) {
- if (crtc_in[i] == UNMATCHED) {
- crtc[i] = SKIP;
- } else if (drm->crtcs[i].planes[type]) {
- crtc[i] = drm->crtcs[i].planes[type]
- - drm->type_planes[type];
- } else {
- crtc[i] = UNMATCHED;
- }
- }
-
- match_obj(drm->num_type_planes[type], possible,
- drm->num_crtcs, crtc, crtc_res);
-
- for (size_t i = 0; i < drm->num_crtcs; ++i) {
- if (crtc_res[i] == UNMATCHED || crtc_res[i] == SKIP) {
- continue;
- }
-
- struct wlr_drm_crtc *c = &drm->crtcs[i];
- struct wlr_drm_plane **old = &c->planes[type];
- struct wlr_drm_plane *new = &drm->type_planes[type][crtc_res[i]];
-
- if (*old != new) {
- wlr_log(WLR_DEBUG,
- "Assigning plane %d -> %d (type %zu) to CRTC %d",
- *old ? (int)(*old)->id : -1,
- new ? (int)new->id : -1,
- type,
- c->id);
-
- ssize_t conn_idx = connector_index_from_crtc(drm, c);
- if (conn_idx >= 0) {
- changed_outputs[conn_idx] = true;
- }
- if (*old) {
- finish_drm_surface(&(*old)->surf);
- }
- finish_drm_surface(&new->surf);
- *old = new;
- }
- }
- }
-}
-
static void drm_connector_cleanup(struct wlr_drm_connector *conn);
bool drm_connector_set_mode(struct wlr_output *output,
@@ -610,7 +571,7 @@ bool drm_connector_set_mode(struct wlr_output *output,
struct wlr_drm_backend *drm = get_drm_backend_from_backend(output->backend);
if (conn->crtc == NULL) {
// Maybe we can steal a CRTC from a disabled output
- realloc_crtcs(drm, NULL);
+ realloc_crtcs(drm);
}
if (conn->crtc == NULL) {
wlr_log(WLR_ERROR, "Cannot modeset '%s': no CRTC for this connector",
@@ -1001,51 +962,37 @@ static void dealloc_crtc(struct wlr_drm_connector *conn) {
conn->crtc - drm->crtcs, conn->output.name);
set_drm_connector_gamma(&conn->output, 0, NULL, NULL, NULL);
-
- for (size_t type = 0; type < 3; ++type) {
- struct wlr_drm_plane *plane = conn->crtc->planes[type];
- if (plane == NULL) {
- continue;
- }
-
- finish_drm_surface(&plane->surf);
- conn->crtc->planes[type] = NULL;
- }
+ finish_drm_surface(&conn->crtc->primary->surf);
+ finish_drm_surface(&conn->crtc->cursor->surf);
drm->iface->conn_enable(drm, conn, false);
conn->crtc = NULL;
}
-static void realloc_crtcs(struct wlr_drm_backend *drm, bool *changed_outputs) {
- size_t num_outputs = wl_list_length(&drm->outputs);
- bool changed_local = changed_outputs ? false : true;
+static void realloc_crtcs(struct wlr_drm_backend *drm) {
+ assert(drm->num_crtcs > 0);
- if (changed_local) {
- changed_outputs = calloc(num_outputs, sizeof(bool));
- if (changed_outputs == NULL) {
- wlr_log(WLR_ERROR, "Allocation failed");
- return;
- }
+ size_t num_outputs = wl_list_length(&drm->outputs);
+ if (num_outputs == 0) {
+ return;
}
wlr_log(WLR_DEBUG, "Reallocating CRTCs");
- uint32_t crtc[drm->num_crtcs + 1];
+ struct wlr_drm_connector *connectors[num_outputs];
+ uint32_t connector_constraints[num_outputs];
+ uint32_t previous_match[drm->num_crtcs];
+ uint32_t new_match[drm->num_crtcs];
+
for (size_t i = 0; i < drm->num_crtcs; ++i) {
- crtc[i] = UNMATCHED;
+ previous_match[i] = UNMATCHED;
}
- struct wlr_drm_connector *connectors[num_outputs + 1];
-
- uint32_t possible_crtc[num_outputs + 1];
- memset(possible_crtc, 0, sizeof(possible_crtc));
-
wlr_log(WLR_DEBUG, "State before reallocation:");
- ssize_t i = -1;
+ size_t i = 0;
struct wlr_drm_connector *conn;
wl_list_for_each(conn, &drm->outputs, link) {
- i++;
connectors[i] = conn;
wlr_log(WLR_DEBUG, " '%s' crtc=%d state=%d desired_enabled=%d",
@@ -1054,7 +1001,7 @@ static void realloc_crtcs(struct wlr_drm_backend *drm, bool *changed_outputs) {
conn->state, conn->desired_enabled);
if (conn->crtc) {
- crtc[conn->crtc - drm->crtcs] = i;
+ previous_match[conn->crtc - drm->crtcs] = i;
}
// Only search CRTCs for user-enabled outputs (that are already
@@ -1062,86 +1009,84 @@ static void realloc_crtcs(struct wlr_drm_backend *drm, bool *changed_outputs) {
if ((conn->state == WLR_DRM_CONN_CONNECTED ||
conn->state == WLR_DRM_CONN_NEEDS_MODESET) &&
conn->desired_enabled) {
- possible_crtc[i] = conn->possible_crtc;
+ connector_constraints[i] = conn->possible_crtc;
+ } else {
+ // Will always fail to match anything
+ connector_constraints[i] = 0;
}
+
+ ++i;
}
- uint32_t crtc_res[drm->num_crtcs + 1];
- match_obj(wl_list_length(&drm->outputs), possible_crtc,
- drm->num_crtcs, crtc, crtc_res);
+ match_obj(num_outputs, connector_constraints,
+ drm->num_crtcs, previous_match, new_match);
- bool matched[num_outputs + 1];
- memset(matched, false, sizeof(matched));
- for (size_t i = 0; i < drm->num_crtcs; ++i) {
- if (crtc_res[i] != UNMATCHED) {
- matched[crtc_res[i]] = true;
- }
+ // Converts our crtc=>connector result into a connector=>crtc one.
+ ssize_t connector_match[num_outputs];
+ for (size_t i = 0 ; i < num_outputs; ++i) {
+ connector_match[i] = -1;
}
-
for (size_t i = 0; i < drm->num_crtcs; ++i) {
- // We don't want any of the current monitors to be deactivated
- if (crtc[i] != UNMATCHED && !matched[crtc[i]] &&
- connectors[crtc[i]]->desired_enabled) {
- wlr_log(WLR_DEBUG, "Could not match a CRTC for connected output %d",
- crtc[i]);
- goto free_changed_outputs;
+ if (new_match[i] != UNMATCHED) {
+ connector_match[new_match[i]] = i;
}
}
- for (size_t i = 0; i < drm->num_crtcs; ++i) {
- if (crtc_res[i] == crtc[i]) {
- continue;
- }
-
- // De-allocate this CRTC on previous output
- if (crtc[i] != UNMATCHED) {
- changed_outputs[crtc[i]] = true;
- dealloc_crtc(connectors[crtc[i]]);
- }
-
- // Assign this CRTC to next output
- if (crtc_res[i] != UNMATCHED) {
- changed_outputs[crtc_res[i]] = true;
-
- struct wlr_drm_connector *conn = connectors[crtc_res[i]];
- dealloc_crtc(conn);
- conn->crtc = &drm->crtcs[i];
-
- wlr_log(WLR_DEBUG, "Assigning CRTC %zu to output %d -> %d '%s'",
- i, crtc[i], crtc_res[i], conn->output.name);
+ /*
+ * In the case that we add a new connector (hotplug) and we fail to
+ * match everything, we prefer to fail the new connector and keep all
+ * of the old mappings instead.
+ */
+ for (size_t i = 0; i < num_outputs; ++i) {
+ struct wlr_drm_connector *conn = connectors[i];
+ if (conn->state == WLR_DRM_CONN_CONNECTED &&
+ conn->desired_enabled &&
+ connector_match[i] == -1) {
+ wlr_log(WLR_DEBUG, "Could not match a CRTC for previously connected output; "
+ "keeping old configuration");
+ return;
}
}
-
wlr_log(WLR_DEBUG, "State after reallocation:");
- wl_list_for_each(conn, &drm->outputs, link) {
- wlr_log(WLR_DEBUG, " '%s' crtc=%d state=%d desired_enabled=%d",
+
+ // Apply new configuration
+ for (size_t i = 0; i < num_outputs; ++i) {
+ struct wlr_drm_connector *conn = connectors[i];
+ bool prev_enabled = conn->crtc;
+
+ wlr_log(WLR_DEBUG, " '%s' crtc=%zd state=%d desired_enabled=%d",
conn->output.name,
- conn->crtc ? (int)(conn->crtc - drm->crtcs) : -1,
+ connector_match[i],
conn->state, conn->desired_enabled);
- }
- realloc_planes(drm, crtc_res, changed_outputs);
+ // We don't need to change anything.
+ if (prev_enabled && connector_match[i] == conn->crtc - drm->crtcs) {
+ continue;
+ }
- // We need to reinitialize any plane that has changed
- i = -1;
- wl_list_for_each(conn, &drm->outputs, link) {
- i++;
- struct wlr_output_mode *mode = conn->output.current_mode;
+ dealloc_crtc(conn);
- if (conn->state != WLR_DRM_CONN_CONNECTED || !changed_outputs[i]) {
+ if (connector_match[i] == -1) {
+ if (prev_enabled) {
+ wlr_log(WLR_DEBUG, "Output has %s lost its CRTC",
+ conn->output.name);
+ conn->state = WLR_DRM_CONN_NEEDS_MODESET;
+ wlr_output_update_enabled(&conn->output, false);
+ conn->desired_mode = conn->output.current_mode;
+ wlr_output_update_mode(&conn->output, NULL);
+ }
continue;
}
- if (conn->crtc == NULL) {
- wlr_log(WLR_DEBUG, "Output has %s lost its CRTC",
- conn->output.name);
- conn->state = WLR_DRM_CONN_NEEDS_MODESET;
- wlr_output_update_enabled(&conn->output, false);
- conn->desired_mode = conn->output.current_mode;
- wlr_output_update_mode(&conn->output, NULL);
+ conn->crtc = &drm->crtcs[connector_match[i]];
+
+ // Only realloc buffers if we have actually been modeset
+ if (conn->state != WLR_DRM_CONN_CONNECTED) {
continue;
}
+ struct wlr_output_mode *mode = conn->output.current_mode;
+
if (!init_drm_plane_surfaces(conn->crtc->primary, drm,
mode->width, mode->height, drm->renderer.gbm_format)) {
wlr_log(WLR_ERROR, "Failed to initialize renderer for plane");
@@ -1153,11 +1098,6 @@ static void realloc_crtcs(struct wlr_drm_backend *drm, bool *changed_outputs) {
wlr_output_damage_whole(&conn->output);
}
-
-free_changed_outputs:
- if (changed_local) {
- free(changed_outputs);
- }
}
static uint32_t get_possible_crtcs(int fd, drmModeRes *res,
@@ -1392,25 +1332,7 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) {
}
}
- 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];
-
- ssize_t pos = -1;
- struct wlr_drm_connector *c;
- wl_list_for_each(c, &drm->outputs, link) {
- ++pos;
- if (c == conn) {
- break;
- }
- }
- assert(pos >= 0);
-
- changed_outputs[pos] = true;
- }
-
- realloc_crtcs(drm, changed_outputs);
+ realloc_crtcs(drm);
for (size_t i = 0; i < new_outputs_len; ++i) {
struct wlr_drm_connector *conn = new_outputs[i];
@@ -1536,23 +1458,7 @@ static void drm_connector_cleanup(struct wlr_drm_connector *conn) {
switch (conn->state) {
case WLR_DRM_CONN_CONNECTED:
- case WLR_DRM_CONN_CLEANUP:;
- struct wlr_drm_crtc *crtc = conn->crtc;
- if (crtc != NULL) {
- for (int i = 0; i < 3; ++i) {
- if (!crtc->planes[i]) {
- continue;
- }
-
- finish_drm_surface(&crtc->planes[i]->surf);
- finish_drm_surface(&crtc->planes[i]->mgpu_surf);
- if (crtc->planes[i]->id == 0) {
- free(crtc->planes[i]);
- crtc->planes[i] = NULL;
- }
- }
- }
-
+ case WLR_DRM_CONN_CLEANUP:
conn->output.current_mode = NULL;
conn->desired_mode = NULL;
struct wlr_drm_mode *mode, *tmp;
diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h
index 99120852..bc1c2933 100644
--- a/include/backend/drm/drm.h
+++ b/include/backend/drm/drm.h
@@ -22,8 +22,6 @@ struct wlr_drm_plane {
uint32_t type;
uint32_t id;
- uint32_t possible_crtcs;
-
struct wlr_drm_surface surf;
struct wlr_drm_surface mgpu_surf;
@@ -49,14 +47,15 @@ struct wlr_drm_crtc {
// Legacy only
drmModeCrtc *legacy_crtc;
- union {
- struct {
- struct wlr_drm_plane *overlay;
- struct wlr_drm_plane *primary;
- struct wlr_drm_plane *cursor;
- };
- struct wlr_drm_plane *planes[3];
- };
+ struct wlr_drm_plane *primary;
+ struct wlr_drm_plane *cursor;
+
+ /*
+ * We don't support overlay planes yet, but we keep track of them to
+ * give to DRM lease clients.
+ */
+ size_t num_overlays;
+ uint32_t *overlays;
union wlr_drm_crtc_props props;
@@ -78,26 +77,6 @@ struct wlr_drm_backend {
size_t num_crtcs;
struct wlr_drm_crtc *crtcs;
- size_t num_planes;
- struct wlr_drm_plane *planes;
-
- union {
- struct {
- size_t num_overlay_planes;
- size_t num_primary_planes;
- size_t num_cursor_planes;
- };
- size_t num_type_planes[3];
- };
-
- union {
- struct {
- struct wlr_drm_plane *overlay_planes;
- struct wlr_drm_plane *primary_planes;
- struct wlr_drm_plane *cursor_planes;
- };
- struct wlr_drm_plane *type_planes[3];
- };
struct wl_display *display;
struct wl_event_source *drm_event;