Merge upstream

This commit is contained in:
Christian Kröner 2022-02-23 21:43:41 +01:00
commit c673b684a0
203 changed files with 6752 additions and 4861 deletions

View file

@ -118,9 +118,15 @@ static bool add_plane(struct wlr_drm_backend *drm,
p->id = drm_plane->plane_id;
p->props = *props;
for (size_t j = 0; j < drm_plane->count_formats; ++j) {
wlr_drm_format_set_add(&p->formats, drm_plane->formats[j],
DRM_FORMAT_MOD_INVALID);
for (size_t i = 0; i < drm_plane->count_formats; ++i) {
// Force a LINEAR layout for the cursor if the driver doesn't support
// modifiers
wlr_drm_format_set_add(&p->formats, drm_plane->formats[i],
DRM_FORMAT_MOD_LINEAR);
if (type != DRM_PLANE_TYPE_CURSOR) {
wlr_drm_format_set_add(&p->formats, drm_plane->formats[i],
DRM_FORMAT_MOD_INVALID);
}
}
if (p->props.in_formats && drm->addfb2_modifiers) {
@ -136,27 +142,12 @@ static bool add_plane(struct wlr_drm_backend *drm,
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);
}
}
drmModeFormatModifierIterator iter = {0};
while (drmModeFormatModifierBlobIterNext(blob, &iter)) {
wlr_drm_format_set_add(&p->formats, iter.fmt, iter.mod);
}
drmModeFreePropertyBlob(blob);
} else if (type == DRM_PLANE_TYPE_CURSOR) {
// Force a LINEAR layout for the cursor if the driver doesn't support
// modifiers
for (size_t i = 0; i < p->formats.len; ++i) {
wlr_drm_format_set_add(&p->formats, p->formats.formats[i]->format,
DRM_FORMAT_MOD_LINEAR);
}
}
switch (type) {
@ -1300,8 +1291,7 @@ void scan_drm_connectors(struct wlr_drm_backend *drm,
wlr_output_init(&wlr_conn->output, &drm->backend, &output_impl,
drm->display);
memcpy(wlr_conn->output.name, wlr_conn->name,
sizeof(wlr_conn->output.name));
wlr_output_set_name(&wlr_conn->output, wlr_conn->name);
wlr_conn->output.phys_width = drm_conn->mmWidth;
wlr_conn->output.phys_height = drm_conn->mmHeight;
@ -1431,6 +1421,36 @@ void scan_drm_connectors(struct wlr_drm_backend *drm,
}
}
void scan_drm_leases(struct wlr_drm_backend *drm) {
drmModeLesseeListRes *list = drmModeListLessees(drm->fd);
if (list == NULL) {
wlr_log_errno(WLR_ERROR, "drmModeListLessees failed");
return;
}
struct wlr_drm_connector *conn;
wl_list_for_each(conn, &drm->outputs, link) {
if (conn->lease == NULL) {
continue;
}
bool found = false;
for (size_t i = 0; i < list->count; i++) {
if (list->lessees[i] == conn->lease->lessee_id) {
found = true;
break;
}
}
if (!found) {
wlr_log(WLR_DEBUG, "DRM lease %"PRIu32" has been terminated",
conn->lease->lessee_id);
drm_lease_destroy(conn->lease);
}
}
drmFree(list);
}
static int mhz_to_nsec(int mhz) {
return 1000000000000LL / mhz;
}
@ -1560,17 +1580,13 @@ int wlr_drm_backend_get_non_master_fd(struct wlr_backend *backend) {
return fd;
}
/* TODO: make the function return a `wlr_drm_lease` to provide a destroy event
* that can be fired when the kernel notifies us through uevent that the lease
* has been destroyed
*/
int wlr_drm_create_lease(struct wlr_output **outputs, size_t n_outputs,
uint32_t *lessee_id) {
struct wlr_drm_lease *wlr_drm_create_lease(struct wlr_output **outputs,
size_t n_outputs, int *lease_fd_ptr) {
assert(outputs);
if (n_outputs == 0) {
wlr_log(WLR_ERROR, "Can't lease 0 outputs");
return -1;
return NULL;
}
struct wlr_drm_backend *drm =
@ -1581,11 +1597,11 @@ int wlr_drm_create_lease(struct wlr_output **outputs, size_t n_outputs,
for (size_t i = 0; i < n_outputs; ++i) {
struct wlr_drm_connector *conn =
get_drm_connector_from_output(outputs[i]);
assert(conn->lessee_id == 0);
assert(conn->lease == NULL);
if (conn->backend != drm) {
wlr_log(WLR_ERROR, "Can't lease output from different backends");
return -1;
return NULL;
}
objects[n_objects++] = conn->id;
@ -1593,7 +1609,7 @@ int wlr_drm_create_lease(struct wlr_output **outputs, size_t n_outputs,
if (!conn->crtc) {
wlr_log(WLR_ERROR, "Connector has no CRTC");
return -1;
return NULL;
}
objects[n_objects++] = conn->crtc->id;
@ -1610,50 +1626,63 @@ int wlr_drm_create_lease(struct wlr_output **outputs, size_t n_outputs,
assert(n_objects != 0);
wlr_log(WLR_DEBUG, "Issuing DRM lease with the %d objects", n_objects);
int lease_fd = drmModeCreateLease(drm->fd, objects, n_objects, 0,
lessee_id);
if (lease_fd < 0) {
return lease_fd;
struct wlr_drm_lease *lease = calloc(1, sizeof(*lease));
if (lease == NULL) {
return NULL;
}
wlr_log(WLR_DEBUG, "Issued DRM lease %"PRIu32, *lessee_id);
lease->backend = drm;
wl_signal_init(&lease->events.destroy);
wlr_log(WLR_DEBUG, "Issuing DRM lease with %d objects", n_objects);
int lease_fd = drmModeCreateLease(drm->fd, objects, n_objects, 0,
&lease->lessee_id);
if (lease_fd < 0) {
free(lease);
return NULL;
}
*lease_fd_ptr = lease_fd;
wlr_log(WLR_DEBUG, "Issued DRM lease %"PRIu32, lease->lessee_id);
for (size_t i = 0; i < n_outputs; ++i) {
struct wlr_drm_connector *conn =
get_drm_connector_from_output(outputs[i]);
conn->lessee_id = *lessee_id;
conn->crtc->lessee_id = *lessee_id;
conn->lease = lease;
conn->crtc->lease = lease;
}
return lease_fd;
return lease;
}
bool wlr_drm_backend_terminate_lease(struct wlr_backend *backend,
uint32_t lessee_id) {
wlr_log(WLR_DEBUG, "Terminating DRM lease %d", lessee_id);
void wlr_drm_lease_terminate(struct wlr_drm_lease *lease) {
struct wlr_drm_backend *drm = lease->backend;
assert(backend);
struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend);
int r = drmModeRevokeLease(drm->fd, lessee_id);
if (r < 0) {
wlr_log_errno(WLR_DEBUG, "Failed to terminate lease");
wlr_log(WLR_DEBUG, "Terminating DRM lease %d", lease->lessee_id);
int ret = drmModeRevokeLease(drm->fd, lease->lessee_id);
if (ret < 0) {
wlr_log_errno(WLR_ERROR, "Failed to terminate lease");
}
drm_lease_destroy(lease);
}
void drm_lease_destroy(struct wlr_drm_lease *lease) {
struct wlr_drm_backend *drm = lease->backend;
wlr_signal_emit_safe(&lease->events.destroy, NULL);
struct wlr_drm_connector *conn;
wl_list_for_each(conn, &drm->outputs, link) {
if (conn->lessee_id == lessee_id) {
conn->lessee_id = 0;
/* Will be re-initialized in scan_drm_connectors */
if (conn->lease == lease) {
conn->lease = NULL;
}
}
for (size_t i = 0; i < drm->num_crtcs; ++i) {
if (drm->crtcs[i].lessee_id == lessee_id) {
drm->crtcs[i].lessee_id = 0;
if (drm->crtcs[i].lease == lease) {
drm->crtcs[i].lease = NULL;
}
}
return r >= 0;
free(lease);
}