Commit cb58fc2f authored by Adam Jackson's avatar Adam Jackson 🎧
Browse files

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 means initialization and VT switch are more flickery than they need
to be. It also means they're more fragile than they need to be, as
(especially for EnterVT) 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. 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's avatarAdam Jackson <ajax@redhat.com>
parent f19a91cd
Pipeline #5609 passed with stage
in 1 minute and 57 seconds
......@@ -772,75 +772,71 @@ drmmode_target_output(ScrnInfoPtr scrn, xf86CrtcPtr crtc)
return NULL;
}
static int
drmmode_crtc_set_mode(xf86CrtcPtr crtc, Bool test_only)
drmmode_set_mode_atomic(ScrnInfoPtr scrn, modesettingPtr ms, Bool test_only)
{
modesettingPtr ms = modesettingPTR(crtc->scrn);
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
drmModeModeInfo kmode;
int output_count = 0;
uint32_t *output_ids = NULL;
uint32_t fb_id;
int x, y;
int i, ret = 0;
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 (!drmmode_crtc_get_fb_id(crtc, &fb_id, &x, &y))
if (!req)
return 1;
if (ms->atomic_modeset) {
drmModeAtomicReq *req = drmModeAtomicAlloc();
Bool active;
uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
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;
ret |= crtc_add_dpms_props(req, crtc, DPMSModeOn, &active);
ret |= plane_add_props(req, crtc, active ? fb_id : 0, x, y);
if (active) {
/* XXX this probably doesn't belong here */
if (test_only && !crtc->mode.HDisplay)
memcpy(&crtc->mode, &crtc->desiredMode, sizeof(crtc->mode));
/* 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;
drmmode_ConvertToKMode(crtc->scrn, &kmode, &crtc->mode);
ret |= drm_mode_ensure_blob(crtc, kmode);
}
if (other_crtc == crtc)
continue;
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 (j = 0; j < xf86_config->num_output; j++) {
xf86OutputPtr output = xf86_config->output[j];
drmmode_output_private_ptr drmmode_output = output->driver_private;
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->current_crtc == other_crtc) {
if (output->crtc == crtc)
lost_outputs++;
else
remaining_outputs++;
}
}
if (drmmode_output->output_id == -1)
continue;
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);
}
}
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 (test_only)
flags |= DRM_MODE_ATOMIC_TEST_ONLY;
if (ret == 0)
ret = drmModeAtomicCommit(ms->fd, req, flags, NULL);
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 (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;
......@@ -848,11 +844,32 @@ drmmode_crtc_set_mode(xf86CrtcPtr crtc, Bool test_only)
drmmode_output->current_crtc = NULL;
}
}
drmModeAtomicFree(req);
return ret;
}
drmModeAtomicFree(req);
return ret;
}
static int
drmmode_crtc_set_mode(xf86CrtcPtr crtc, Bool test_only)
{
modesettingPtr ms = modesettingPTR(crtc->scrn);
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
drmModeModeInfo kmode;
int output_count = 0;
uint32_t *output_ids = NULL;
uint32_t fb_id;
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;
output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
if (!output_ids)
return -1;
......@@ -3200,15 +3217,20 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
goto fail;
step++;
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;
if (!drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
crtc->x, crtc->y))
goto fail;
if (!drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
crtc->x, crtc->y))
goto fail;
}
}
if (old_fb_id) {
......@@ -3463,8 +3485,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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment