246 lines
8.8 KiB
Diff
246 lines
8.8 KiB
Diff
From e4e389447c59c89d39a5a78a5f19cdfd22d7699c Mon Sep 17 00:00:00 2001
|
|
From: Adam Jackson <ajax@redhat.com>
|
|
Date: Fri, 5 Oct 2018 14:09:35 -0400
|
|
Subject: [PATCH xserver 4/4] modesetting: Use atomic instead of per-crtc walks
|
|
where we can
|
|
|
|
drmmode_set_desired_modes (reachable from CreateScreenResources,
|
|
EnterVT, etc.) currently works by doing ->set_mode_major on each CRTC.
|
|
This is silly, as atomic lets us configure every CRTC at once. It's also
|
|
fragile, because we're not trying very hard to ensure the intermediate
|
|
states are valid.
|
|
|
|
This patch introduces drmmode_set_mode_atomic, which blasts the entire
|
|
RANDR state into the kernel in an... atomic... fashion. We change
|
|
drmmode_set_desired_modes and drmmode_xf86crtc_resize to use this
|
|
instead of walking each CRTC. We also change drmmode_crtc_set_mode to
|
|
use this, so that client RANDR requests (operating CRTC-at-a-time, since
|
|
RANDR doesn't have atomic changes yet) use the same code paths.
|
|
|
|
Signed-off-by: Adam Jackson <ajax@redhat.com>
|
|
---
|
|
.../drivers/modesetting/drmmode_display.c | 179 +++++++++++-------
|
|
1 file changed, 109 insertions(+), 70 deletions(-)
|
|
|
|
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
|
|
index 7924aa396..020678155 100644
|
|
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
|
|
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
|
|
@@ -772,6 +772,96 @@ drmmode_target_output(ScrnInfoPtr scrn, xf86CrtcPtr crtc)
|
|
|
|
return NULL;
|
|
}
|
|
+
|
|
+static int
|
|
+drmmode_set_mode_atomic(ScrnInfoPtr scrn, modesettingPtr ms, Bool test_only)
|
|
+{
|
|
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
|
|
+ drmModeAtomicReq *req = drmModeAtomicAlloc();
|
|
+ uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
|
|
+ int i, j, ret = 0;
|
|
+
|
|
+ if (!req)
|
|
+ return 1;
|
|
+
|
|
+ for (i = 0; i < xf86_config->num_crtc; i++) {
|
|
+ xf86CrtcPtr crtc = xf86_config->crtc[i];
|
|
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
+ Bool active = crtc->enabled;
|
|
+ uint32_t fb_id;
|
|
+ int x, y;
|
|
+ drmModeModeInfo kmode;
|
|
+
|
|
+ if (active) {
|
|
+ drmmode_ConvertToKMode(crtc->scrn, &kmode, &crtc->desiredMode);
|
|
+ ret |= drm_mode_ensure_blob(crtc, kmode);
|
|
+
|
|
+ /* XXX this probably doesn't belong here */
|
|
+ if (!crtc->mode.HDisplay && crtc->desiredMode.HDisplay)
|
|
+ memcpy(&crtc->mode, &crtc->desiredMode, sizeof(crtc->mode));
|
|
+ }
|
|
+
|
|
+ ret |= !drmmode_crtc_get_fb_id(crtc, &fb_id, &x, &y);
|
|
+ ret |= crtc_add_prop(req, drmmode_crtc,
|
|
+ DRMMODE_CRTC_ACTIVE, active);
|
|
+ ret |= crtc_add_prop(req, drmmode_crtc,
|
|
+ DRMMODE_CRTC_MODE_ID,
|
|
+ active ? drmmode_crtc->current_mode->blob_id : 0);
|
|
+ ret |= plane_add_props(req, crtc, active ? fb_id : 0, x, y);
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < xf86_config->num_output; i++) {
|
|
+ xf86OutputPtr output = xf86_config->output[i];
|
|
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
|
|
+ drmmode_crtc_private_ptr drm_crtc =
|
|
+ output->crtc ? output->crtc->driver_private : NULL;
|
|
+
|
|
+ if (drmmode_output->output_id == -1)
|
|
+ continue;
|
|
+
|
|
+ ret |= connector_add_prop(req, drmmode_output,
|
|
+ DRMMODE_CONNECTOR_CRTC_ID,
|
|
+ drm_crtc ? drm_crtc->mode_crtc->crtc_id : 0);
|
|
+ }
|
|
+
|
|
+ if (test_only)
|
|
+ flags |= DRM_MODE_ATOMIC_TEST_ONLY;
|
|
+
|
|
+ if (ret == 0)
|
|
+ ret = drmModeAtomicCommit(ms->fd, req, flags, NULL);
|
|
+
|
|
+ if (ret == 0 && !test_only) {
|
|
+ for (i = 0; i < xf86_config->num_crtc; i++) {
|
|
+ xf86CrtcPtr crtc = xf86_config->crtc[i];
|
|
+ for (j = 0; i < xf86_config->num_output; i++) {
|
|
+ xf86OutputPtr output = xf86_config->output[j];
|
|
+ drmmode_output_private_ptr drmmode_output =
|
|
+ output->driver_private;
|
|
+
|
|
+ if (output->crtc == crtc)
|
|
+ drmmode_output->current_crtc = crtc;
|
|
+ else if (drmmode_output->current_crtc == crtc)
|
|
+ drmmode_output->current_crtc = NULL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (ret == 0 && test_only) {
|
|
+ for (i = 0; i < xf86_config->num_crtc; i++) {
|
|
+ xf86CrtcPtr crtc = xf86_config->crtc[i];
|
|
+ crtc->mode = crtc->desiredMode;
|
|
+ crtc->rotation = crtc->desiredRotation;
|
|
+ crtc->x = crtc->desiredX;
|
|
+ crtc->y = crtc->desiredY;
|
|
+ if (!xf86CrtcRotate(crtc))
|
|
+ ret = 1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ drmModeAtomicFree(req);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static int
|
|
drmmode_crtc_set_mode(xf86CrtcPtr crtc, Bool test_only)
|
|
{
|
|
@@ -786,73 +876,12 @@ drmmode_crtc_set_mode(xf86CrtcPtr crtc, Bool test_only)
|
|
int x, y;
|
|
int i, ret = 0;
|
|
|
|
+ if (ms->atomic_modeset)
|
|
+ return drmmode_set_mode_atomic(crtc->scrn, ms, test_only);
|
|
+
|
|
if (!drmmode_crtc_get_fb_id(crtc, &fb_id, &x, &y))
|
|
return 1;
|
|
|
|
- if (ms->atomic_modeset) {
|
|
- drmModeAtomicReq *req = drmModeAtomicAlloc();
|
|
- Bool active;
|
|
- uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
|
|
-
|
|
- if (!req)
|
|
- return 1;
|
|
-
|
|
- ret |= crtc_add_dpms_props(req, crtc, DPMSModeOn, &active);
|
|
- ret |= plane_add_props(req, crtc, active ? fb_id : 0, x, y);
|
|
-
|
|
- /* Orphaned CRTCs need to be disabled right now in atomic mode */
|
|
- for (i = 0; i < xf86_config->num_crtc; i++) {
|
|
- xf86CrtcPtr other_crtc = xf86_config->crtc[i];
|
|
- drmmode_crtc_private_ptr other_drmmode_crtc = other_crtc->driver_private;
|
|
- int lost_outputs = 0;
|
|
- int remaining_outputs = 0;
|
|
- int j;
|
|
-
|
|
- if (other_crtc == crtc)
|
|
- continue;
|
|
-
|
|
- for (j = 0; j < xf86_config->num_output; j++) {
|
|
- xf86OutputPtr output = xf86_config->output[j];
|
|
- drmmode_output_private_ptr drmmode_output = output->driver_private;
|
|
-
|
|
- if (drmmode_output->current_crtc == other_crtc) {
|
|
- if (output->crtc == crtc)
|
|
- lost_outputs++;
|
|
- else
|
|
- remaining_outputs++;
|
|
- }
|
|
- }
|
|
-
|
|
- if (lost_outputs > 0 && remaining_outputs == 0) {
|
|
- ret |= crtc_add_prop(req, other_drmmode_crtc,
|
|
- DRMMODE_CRTC_ACTIVE, 0);
|
|
- ret |= crtc_add_prop(req, other_drmmode_crtc,
|
|
- DRMMODE_CRTC_MODE_ID, 0);
|
|
- }
|
|
- }
|
|
-
|
|
- if (test_only)
|
|
- flags |= DRM_MODE_ATOMIC_TEST_ONLY;
|
|
-
|
|
- if (ret == 0)
|
|
- ret = drmModeAtomicCommit(ms->fd, req, flags, NULL);
|
|
-
|
|
- if (ret == 0 && !test_only) {
|
|
- for (i = 0; i < xf86_config->num_output; i++) {
|
|
- xf86OutputPtr output = xf86_config->output[i];
|
|
- drmmode_output_private_ptr drmmode_output = output->driver_private;
|
|
-
|
|
- if (output->crtc == crtc)
|
|
- drmmode_output->current_crtc = crtc;
|
|
- else if (drmmode_output->current_crtc == crtc)
|
|
- drmmode_output->current_crtc = NULL;
|
|
- }
|
|
- }
|
|
-
|
|
- drmModeAtomicFree(req);
|
|
- return ret;
|
|
- }
|
|
-
|
|
output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
|
|
if (!output_ids)
|
|
return -1;
|
|
@@ -3199,14 +3228,19 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
|
|
if (!drmmode_glamor_handle_new_screen_pixmap(drmmode))
|
|
goto fail;
|
|
|
|
- for (i = 0; i < xf86_config->num_crtc; i++) {
|
|
- xf86CrtcPtr crtc = xf86_config->crtc[i];
|
|
+ if (ms->atomic_modeset) {
|
|
+ if (drmmode_set_mode_atomic(scrn, ms, FALSE))
|
|
+ goto fail;
|
|
+ } else {
|
|
+ for (i = 0; i < xf86_config->num_crtc; i++) {
|
|
+ xf86CrtcPtr crtc = xf86_config->crtc[i];
|
|
|
|
- if (!crtc->enabled)
|
|
- continue;
|
|
+ if (!crtc->enabled)
|
|
+ continue;
|
|
|
|
- drmmode_set_mode_major(crtc, &crtc->mode,
|
|
- crtc->rotation, crtc->x, crtc->y);
|
|
+ drmmode_set_mode_major(crtc, &crtc->mode,
|
|
+ crtc->rotation, crtc->x, crtc->y);
|
|
+ }
|
|
}
|
|
|
|
if (old_fb_id) {
|
|
@@ -3457,8 +3491,13 @@ Bool
|
|
drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, Bool set_hw)
|
|
{
|
|
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
|
|
+ modesettingPtr ms = modesettingPTR(pScrn);
|
|
int c;
|
|
|
|
+ /* drmmode_set_mode_atomic returns 0 on success, we return TRUE */
|
|
+ if (ms->atomic_modeset)
|
|
+ return !drmmode_set_mode_atomic(pScrn, ms, /* test_only = */ !set_hw);
|
|
+
|
|
for (c = 0; c < config->num_crtc; c++) {
|
|
xf86CrtcPtr crtc = config->crtc[c];
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
--
|
|
2.20.1
|
|
|