eglfs_kms: Skip modesetting when current is good enough

...unless explicitly requested via QT_QPA_EGLFS_ALWAYS_SET_MODE.

This mirrors the behavior of the EGLDevice backend.

Synchronize the "swap" behavior in other aspects too: do not retry
a failing modeset until infinity, and make the (currently limited but
soon enhanced) plane setup independent of the modesetting.

Task-number: QTBUG-62262
Change-Id: If43c4edf09c526a3d0f566994a3d632c217d2c31
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
Laszlo Agocs 2017-08-02 15:10:45 +02:00
parent 744bb7e85a
commit 77a70b2195

View File

@ -132,7 +132,7 @@ QPlatformCursor *QEglFSKmsGbmScreen::cursor() const
gbm_surface *QEglFSKmsGbmScreen::createSurface() gbm_surface *QEglFSKmsGbmScreen::createSurface()
{ {
if (!m_gbm_surface) { if (!m_gbm_surface) {
qCDebug(qLcEglfsKmsDebug) << "Creating gbm_surface for screen" << name(); qCDebug(qLcEglfsKmsDebug, "Creating gbm_surface for screen %s", qPrintable(name()));
m_gbm_surface = gbm_surface_create(static_cast<QEglFSKmsGbmDevice *>(device())->gbmDevice(), m_gbm_surface = gbm_surface_create(static_cast<QEglFSKmsGbmDevice *>(device())->gbmDevice(),
rawGeometry().width(), rawGeometry().width(),
rawGeometry().height(), rawGeometry().height(),
@ -179,31 +179,48 @@ void QEglFSKmsGbmScreen::flip()
const uint32_t h = op.modes[op.mode].vdisplay; const uint32_t h = op.modes[op.mode].vdisplay;
if (!op.mode_set) { if (!op.mode_set) {
int ret = drmModeSetCrtc(fd, op.mode_set = true;
op.crtc_id,
fb->fb,
0, 0,
&op.connector_id, 1,
&op.modes[op.mode]);
if (ret == -1) { bool doModeSet = true;
qErrnoWarning(errno, "Could not set DRM mode!"); drmModeCrtcPtr currentMode = drmModeGetCrtc(fd, op.crtc_id);
} else { const bool alreadySet = currentMode && !memcmp(&currentMode->mode, &op.modes[op.mode], sizeof(drmModeModeInfo));
op.mode_set = true; if (currentMode)
setPowerState(PowerStateOn); drmModeFreeCrtc(currentMode);
if (alreadySet) {
if (!op.plane_set) { static bool alwaysDoSet = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ALWAYS_SET_MODE");
op.plane_set = true; if (!alwaysDoSet) {
if (op.wants_plane) { qCDebug(qLcEglfsKmsDebug, "Mode already set, skipping modesetting for screen %s", qPrintable(name()));
int ret = drmModeSetPlane(fd, op.plane_id, op.crtc_id, doModeSet = false;
uint32_t(-1), 0,
0, 0, w, h,
0 << 16, 0 << 16, w << 16, h << 16);
if (ret == -1)
qErrnoWarning(errno, "drmModeSetPlane failed");
}
} }
} }
if (doModeSet) {
qCDebug(qLcEglfsKmsDebug, "Setting mode for screen %s", qPrintable(name()));
int ret = drmModeSetCrtc(fd,
op.crtc_id,
fb->fb,
0, 0,
&op.connector_id, 1,
&op.modes[op.mode]);
if (ret == 0)
setPowerState(PowerStateOn);
else
qErrnoWarning(errno, "Could not set DRM mode for screen %s", qPrintable(name()));
}
}
if (!op.plane_set) {
op.plane_set = true;
if (op.wants_plane) {
qCDebug(qLcEglfsKmsDebug, "Setting plane %u", op.plane_id);
int ret = drmModeSetPlane(fd, op.plane_id, op.crtc_id,
uint32_t(-1), 0,
0, 0, w, h,
0 << 16, 0 << 16, w << 16, h << 16);
if (ret)
qErrnoWarning(errno, "drmModeSetPlane failed");
}
} }
int ret = drmModePageFlip(fd, int ret = drmModePageFlip(fd,
@ -212,7 +229,7 @@ void QEglFSKmsGbmScreen::flip()
DRM_MODE_PAGE_FLIP_EVENT, DRM_MODE_PAGE_FLIP_EVENT,
this); this);
if (ret) { if (ret) {
qErrnoWarning("Could not queue DRM page flip!"); qErrnoWarning("Could not queue DRM page flip on screen %s", qPrintable(name()));
gbm_surface_release_buffer(m_gbm_surface, m_gbm_bo_next); gbm_surface_release_buffer(m_gbm_surface, m_gbm_bo_next);
m_gbm_bo_next = Q_NULLPTR; m_gbm_bo_next = Q_NULLPTR;
} }