mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2024-11-25 08:32:30 +00:00
backend/drm: implement wlr_backend_impl.{test,commit}
This commit is contained in:
parent
d41b5efc65
commit
52e01a9c8b
@ -75,15 +75,29 @@ static int backend_get_drm_fd(struct wlr_backend *backend) {
|
||||
return drm->fd;
|
||||
}
|
||||
|
||||
static uint32_t drm_backend_get_buffer_caps(struct wlr_backend *backend) {
|
||||
static uint32_t backend_get_buffer_caps(struct wlr_backend *backend) {
|
||||
return WLR_BUFFER_CAP_DMABUF;
|
||||
}
|
||||
|
||||
static bool backend_test(struct wlr_backend *backend,
|
||||
const struct wlr_backend_output_state *states, size_t states_len) {
|
||||
struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend);
|
||||
return commit_drm_device(drm, states, states_len, true);
|
||||
}
|
||||
|
||||
static bool backend_commit(struct wlr_backend *backend,
|
||||
const struct wlr_backend_output_state *states, size_t states_len) {
|
||||
struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend);
|
||||
return commit_drm_device(drm, states, states_len, false);
|
||||
}
|
||||
|
||||
static const struct wlr_backend_impl backend_impl = {
|
||||
.start = backend_start,
|
||||
.destroy = backend_destroy,
|
||||
.get_drm_fd = backend_get_drm_fd,
|
||||
.get_buffer_caps = drm_backend_get_buffer_caps,
|
||||
.get_buffer_caps = backend_get_buffer_caps,
|
||||
.test = backend_test,
|
||||
.commit = backend_commit,
|
||||
};
|
||||
|
||||
bool wlr_backend_is_drm(struct wlr_backend *b) {
|
||||
|
@ -1870,6 +1870,73 @@ void restore_drm_device(struct wlr_drm_backend *drm) {
|
||||
}
|
||||
}
|
||||
|
||||
bool commit_drm_device(struct wlr_drm_backend *drm,
|
||||
const struct wlr_backend_output_state *output_states, size_t output_states_len,
|
||||
bool test_only) {
|
||||
if (!drm->session->active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct wlr_drm_connector_state *conn_states = calloc(output_states_len, sizeof(conn_states[0]));
|
||||
if (conn_states == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
bool modeset = false;
|
||||
size_t conn_states_len = 0;
|
||||
for (size_t i = 0; i < output_states_len; i++) {
|
||||
const struct wlr_backend_output_state *output_state = &output_states[i];
|
||||
struct wlr_output *output = output_state->output;
|
||||
if (!output->enabled && !output_pending_enabled(output, &output_state->base)) {
|
||||
// KMS rejects commits which disable already-disabled connectors
|
||||
// and have the DRM_MODE_PAGE_FLIP_EVENT flag
|
||||
continue;
|
||||
}
|
||||
|
||||
struct wlr_drm_connector *conn = get_drm_connector_from_output(output);
|
||||
|
||||
if (output_pending_enabled(output, &output_state->base) && !drm_connector_alloc_crtc(conn)) {
|
||||
wlr_drm_conn_log(conn, WLR_DEBUG,
|
||||
"No CRTC available for this connector");
|
||||
goto out;
|
||||
}
|
||||
|
||||
struct wlr_drm_connector_state *conn_state = &conn_states[conn_states_len];
|
||||
drm_connector_state_init(conn_state, conn, &output_state->base);
|
||||
conn_states_len++;
|
||||
|
||||
if (!drm_connector_prepare(conn_state, test_only)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (output_state->base.tearing_page_flip) {
|
||||
wlr_log(WLR_DEBUG, "Tearing not supported for DRM device-wide commits");
|
||||
goto out;
|
||||
}
|
||||
|
||||
modeset |= output_state->base.allow_reconfiguration;
|
||||
}
|
||||
|
||||
uint32_t flags = 0;
|
||||
if (!test_only) {
|
||||
flags |= DRM_MODE_PAGE_FLIP_EVENT;
|
||||
}
|
||||
struct wlr_drm_device_state dev_state = {
|
||||
.modeset = modeset,
|
||||
.connectors = conn_states,
|
||||
.connectors_len = conn_states_len,
|
||||
};
|
||||
ok = drm_commit(drm, &dev_state, flags, test_only);
|
||||
|
||||
out:
|
||||
for (size_t i = 0; i < conn_states_len; i++) {
|
||||
drm_connector_state_finish(&conn_states[i]);
|
||||
}
|
||||
free(conn_states);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int mhz_to_nsec(int mhz) {
|
||||
return 1000000000000LL / mhz;
|
||||
}
|
||||
|
@ -206,6 +206,8 @@ void finish_drm_resources(struct wlr_drm_backend *drm);
|
||||
void scan_drm_connectors(struct wlr_drm_backend *state,
|
||||
struct wlr_device_hotplug_event *event);
|
||||
void scan_drm_leases(struct wlr_drm_backend *drm);
|
||||
bool commit_drm_device(struct wlr_drm_backend *drm,
|
||||
const struct wlr_backend_output_state *states, size_t states_len, bool test_only);
|
||||
void restore_drm_device(struct wlr_drm_backend *drm);
|
||||
int handle_drm_event(int fd, uint32_t mask, void *data);
|
||||
void destroy_drm_connector(struct wlr_drm_connector *conn);
|
||||
|
Loading…
Reference in New Issue
Block a user