backend/drm: rework struct wlr_drm_page_flip for multiple connectors

We need to store the CRTC ID for each connector at the time of the
atomic commit, because future commits may change the CRTC/connector
mapping.
This commit is contained in:
Simon Ser 2024-02-14 18:01:49 +01:00 committed by Kenny Levinsen
parent 805807fd5b
commit fc4996d853
2 changed files with 65 additions and 16 deletions

View file

@ -422,33 +422,75 @@ static struct wlr_drm_layer *get_or_create_layer(struct wlr_drm_backend *drm,
return layer; return layer;
} }
static void drm_connector_set_pending_page_flip(struct wlr_drm_connector *conn,
struct wlr_drm_page_flip *page_flip) {
if (conn->pending_page_flip != NULL) {
conn->pending_page_flip->conn = NULL;
}
conn->pending_page_flip = page_flip;
}
void drm_page_flip_destroy(struct wlr_drm_page_flip *page_flip) { void drm_page_flip_destroy(struct wlr_drm_page_flip *page_flip) {
if (!page_flip) { if (!page_flip) {
return; return;
} }
wl_list_remove(&page_flip->link); wl_list_remove(&page_flip->link);
free(page_flip->connectors);
free(page_flip); free(page_flip);
} }
static struct wlr_drm_page_flip *drm_page_flip_create(struct wlr_drm_connector *conn) { static struct wlr_drm_page_flip *drm_page_flip_create(struct wlr_drm_backend *drm,
const struct wlr_drm_device_state *state) {
struct wlr_drm_page_flip *page_flip = calloc(1, sizeof(*page_flip)); struct wlr_drm_page_flip *page_flip = calloc(1, sizeof(*page_flip));
if (page_flip == NULL) { if (page_flip == NULL) {
return NULL; return NULL;
} }
page_flip->conn = conn; page_flip->connectors_len = state->connectors_len;
wl_list_insert(&conn->backend->page_flips, &page_flip->link); page_flip->connectors =
calloc(page_flip->connectors_len, sizeof(page_flip->connectors[0]));
if (page_flip->connectors == NULL) {
free(page_flip);
return NULL;
}
for (size_t i = 0; i < state->connectors_len; i++) {
struct wlr_drm_connector *conn = state->connectors[i].connector;
page_flip->connectors[i] = (struct wlr_drm_page_flip_connector){
.connector = conn,
.crtc_id = conn->crtc->id,
};
}
wl_list_insert(&drm->page_flips, &page_flip->link);
return page_flip; return page_flip;
} }
static struct wlr_drm_connector *drm_page_flip_pop(
struct wlr_drm_page_flip *page_flip, uint32_t crtc_id) {
bool found = false;
size_t i;
for (i = 0; i < page_flip->connectors_len; i++) {
if (page_flip->connectors[i].crtc_id == crtc_id) {
found = true;
break;
}
}
if (!found) {
return NULL;
}
struct wlr_drm_connector *conn = page_flip->connectors[i].connector;
if (i != page_flip->connectors_len - 1) {
page_flip->connectors[i] = page_flip->connectors[page_flip->connectors_len - 1];
}
page_flip->connectors_len--;
return conn;
}
static void drm_connector_set_pending_page_flip(struct wlr_drm_connector *conn,
struct wlr_drm_page_flip *page_flip) {
if (conn->pending_page_flip != NULL) {
struct wlr_drm_page_flip *page_flip = conn->pending_page_flip;
for (size_t i = 0; i < page_flip->connectors_len; i++) {
if (page_flip->connectors[i].connector == conn) {
page_flip->connectors[i].connector = NULL;
}
}
}
conn->pending_page_flip = page_flip;
}
static void drm_connector_apply_commit(const struct wlr_drm_connector_state *state, static void drm_connector_apply_commit(const struct wlr_drm_connector_state *state,
struct wlr_drm_page_flip *page_flip) { struct wlr_drm_page_flip *page_flip) {
struct wlr_drm_connector *conn = state->connector; struct wlr_drm_connector *conn = state->connector;
@ -496,8 +538,7 @@ static bool drm_commit(struct wlr_drm_backend *drm,
struct wlr_drm_page_flip *page_flip = NULL; struct wlr_drm_page_flip *page_flip = NULL;
if (flags & DRM_MODE_PAGE_FLIP_EVENT) { if (flags & DRM_MODE_PAGE_FLIP_EVENT) {
assert(state->connectors_len == 1); page_flip = drm_page_flip_create(drm, state);
page_flip = drm_page_flip_create(state->connectors[0].connector);
if (page_flip == NULL) { if (page_flip == NULL) {
return false; return false;
} }
@ -1874,11 +1915,13 @@ static void handle_page_flip(int fd, unsigned seq,
unsigned tv_sec, unsigned tv_usec, unsigned crtc_id, void *data) { unsigned tv_sec, unsigned tv_usec, unsigned crtc_id, void *data) {
struct wlr_drm_page_flip *page_flip = data; struct wlr_drm_page_flip *page_flip = data;
struct wlr_drm_connector *conn = page_flip->conn; struct wlr_drm_connector *conn = drm_page_flip_pop(page_flip, crtc_id);
if (conn != NULL) { if (conn != NULL) {
conn->pending_page_flip = NULL; conn->pending_page_flip = NULL;
} }
drm_page_flip_destroy(page_flip); if (page_flip->connectors_len == 0) {
drm_page_flip_destroy(page_flip);
}
if (conn == NULL) { if (conn == NULL) {
return; return;

View file

@ -159,7 +159,13 @@ struct wlr_drm_connector_state {
*/ */
struct wlr_drm_page_flip { struct wlr_drm_page_flip {
struct wl_list link; // wlr_drm_connector.page_flips struct wl_list link; // wlr_drm_connector.page_flips
struct wlr_drm_connector *conn; struct wlr_drm_page_flip_connector *connectors;
size_t connectors_len;
};
struct wlr_drm_page_flip_connector {
uint32_t crtc_id;
struct wlr_drm_connector *connector; // may be NULL
}; };
struct wlr_drm_connector { struct wlr_drm_connector {