|
|
|
@ -1,6 +1,8 @@
|
|
|
|
|
#include <drm_fourcc.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <wlr/render/drm_syncobj.h>
|
|
|
|
|
#include <wlr/util/log.h>
|
|
|
|
|
#include <xf86drm.h>
|
|
|
|
|
#include <xf86drmMode.h>
|
|
|
|
@ -272,6 +274,15 @@ bool drm_atomic_connector_prepare(struct wlr_drm_connector_state *state, bool mo
|
|
|
|
|
state->primary_fb->wlr_buf->height, &state->base->damage, &fb_damage_clips);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int in_fence_fd = -1;
|
|
|
|
|
if (state->base->committed & WLR_OUTPUT_STATE_WAIT_TIMELINE) {
|
|
|
|
|
in_fence_fd = wlr_drm_syncobj_timeline_export_sync_file(state->base->wait_timeline,
|
|
|
|
|
state->base->wait_point);
|
|
|
|
|
if (in_fence_fd < 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool prev_vrr_enabled =
|
|
|
|
|
output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED;
|
|
|
|
|
bool vrr_enabled = prev_vrr_enabled;
|
|
|
|
@ -285,6 +296,7 @@ bool drm_atomic_connector_prepare(struct wlr_drm_connector_state *state, bool mo
|
|
|
|
|
state->mode_id = mode_id;
|
|
|
|
|
state->gamma_lut = gamma_lut;
|
|
|
|
|
state->fb_damage_clips = fb_damage_clips;
|
|
|
|
|
state->primary_in_fence_fd = in_fence_fd;
|
|
|
|
|
state->vrr_enabled = vrr_enabled;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@ -305,6 +317,15 @@ void drm_atomic_connector_apply_commit(struct wlr_drm_connector_state *state) {
|
|
|
|
|
WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED : WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED;
|
|
|
|
|
|
|
|
|
|
destroy_blob(drm, state->fb_damage_clips);
|
|
|
|
|
if (state->primary_in_fence_fd >= 0) {
|
|
|
|
|
close(state->primary_in_fence_fd);
|
|
|
|
|
}
|
|
|
|
|
if (state->out_fence_fd >= 0) {
|
|
|
|
|
// TODO: error handling
|
|
|
|
|
wlr_drm_syncobj_timeline_import_sync_file(state->base->signal_timeline,
|
|
|
|
|
state->base->signal_point, state->out_fence_fd);
|
|
|
|
|
close(state->out_fence_fd);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void drm_atomic_connector_rollback_commit(struct wlr_drm_connector_state *state) {
|
|
|
|
@ -316,6 +337,12 @@ void drm_atomic_connector_rollback_commit(struct wlr_drm_connector_state *state)
|
|
|
|
|
rollback_blob(drm, &crtc->gamma_lut, state->gamma_lut);
|
|
|
|
|
|
|
|
|
|
destroy_blob(drm, state->fb_damage_clips);
|
|
|
|
|
if (state->primary_in_fence_fd >= 0) {
|
|
|
|
|
close(state->primary_in_fence_fd);
|
|
|
|
|
}
|
|
|
|
|
if (state->out_fence_fd >= 0) {
|
|
|
|
|
close(state->out_fence_fd);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void plane_disable(struct atomic *atom, struct wlr_drm_plane *plane) {
|
|
|
|
@ -353,12 +380,37 @@ static void set_plane_props(struct atomic *atom, struct wlr_drm_backend *drm,
|
|
|
|
|
atomic_add(atom, id, props->crtc_y, (uint64_t)y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool supports_cursor_hotspots(const struct wlr_drm_plane* plane) {
|
|
|
|
|
static bool supports_cursor_hotspots(const struct wlr_drm_plane *plane) {
|
|
|
|
|
return plane->props.hotspot_x && plane->props.hotspot_y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void set_plane_in_fence_fd(struct atomic *atom,
|
|
|
|
|
struct wlr_drm_plane *plane, int sync_file_fd) {
|
|
|
|
|
if (!plane->props.in_fence_fd) {
|
|
|
|
|
wlr_log(WLR_ERROR, "Plane %"PRIu32 " is missing the IN_FENCE_FD property",
|
|
|
|
|
plane->id);
|
|
|
|
|
atom->failed = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
atomic_add(atom, plane->id, plane->props.in_fence_fd, sync_file_fd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void set_crtc_out_fence_ptr(struct atomic *atom, struct wlr_drm_crtc *crtc,
|
|
|
|
|
int *fd_ptr) {
|
|
|
|
|
if (!crtc->props.out_fence_ptr) {
|
|
|
|
|
wlr_log(WLR_ERROR,
|
|
|
|
|
"CRTC %"PRIu32" is missing the OUT_FENCE_PTR property",
|
|
|
|
|
crtc->id);
|
|
|
|
|
atom->failed = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
atomic_add(atom, crtc->id, crtc->props.out_fence_ptr, (uintptr_t)fd_ptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void atomic_connector_add(struct atomic *atom,
|
|
|
|
|
const struct wlr_drm_connector_state *state, bool modeset) {
|
|
|
|
|
struct wlr_drm_connector_state *state, bool modeset) {
|
|
|
|
|
struct wlr_drm_connector *conn = state->connector;
|
|
|
|
|
struct wlr_drm_backend *drm = conn->backend;
|
|
|
|
|
struct wlr_drm_crtc *crtc = conn->crtc;
|
|
|
|
@ -391,6 +443,12 @@ static void atomic_connector_add(struct atomic *atom,
|
|
|
|
|
atomic_add(atom, crtc->primary->id,
|
|
|
|
|
crtc->primary->props.fb_damage_clips, state->fb_damage_clips);
|
|
|
|
|
}
|
|
|
|
|
if (state->primary_in_fence_fd >= 0) {
|
|
|
|
|
set_plane_in_fence_fd(atom, crtc->primary, state->primary_in_fence_fd);
|
|
|
|
|
}
|
|
|
|
|
if (state->base->committed & WLR_OUTPUT_STATE_SIGNAL_TIMELINE) {
|
|
|
|
|
set_crtc_out_fence_ptr(atom, crtc, &state->out_fence_fd);
|
|
|
|
|
}
|
|
|
|
|
if (crtc->cursor) {
|
|
|
|
|
if (drm_connector_is_cursor_visible(conn)) {
|
|
|
|
|
set_plane_props(atom, drm, crtc->cursor, state->cursor_fb,
|
|
|
|
|