eglfs: allow forcing an overlay plane
Add a QT_QPA_EGLFS_KMS_PLANE_INDEX environment variable that applies both to the GBM and EGLDevice backends. When set to a value between 0 and the number of planes on the connector - 1, the chosen overlay plane will be used for output, meaning there will be a drmModeSetPlane to configure, and, in case of EGLDevice, the plane's corresponding EGL layer will get chosen instead of the CRTC's. Task-number: QTBUG-57386 Change-Id: I12c89472ea5730987052f39211fadc597d1302ef Reviewed-by: Pasi Petäjäjärvi <pasi.petajajarvi@qt.io>
This commit is contained in:
parent
8d0854c2bd
commit
f30b888465
@ -181,24 +181,41 @@ void QEglFSKmsGbmScreen::flip()
|
||||
|
||||
FrameBuffer *fb = framebufferForBufferObject(m_gbm_bo_next);
|
||||
|
||||
if (!output().mode_set) {
|
||||
int ret = drmModeSetCrtc(device()->fd(),
|
||||
output().crtc_id,
|
||||
QEglFSKmsOutput &op(output());
|
||||
const int fd = device()->fd();
|
||||
const uint32_t w = op.modes[op.mode].hdisplay;
|
||||
const uint32_t h = op.modes[op.mode].vdisplay;
|
||||
|
||||
if (!op.mode_set) {
|
||||
int ret = drmModeSetCrtc(fd,
|
||||
op.crtc_id,
|
||||
fb->fb,
|
||||
0, 0,
|
||||
&output().connector_id, 1,
|
||||
&output().modes[output().mode]);
|
||||
&op.connector_id, 1,
|
||||
&op.modes[op.mode]);
|
||||
|
||||
if (ret) {
|
||||
qErrnoWarning("Could not set DRM mode!");
|
||||
if (ret == -1) {
|
||||
qErrnoWarning(errno, "Could not set DRM mode!");
|
||||
} else {
|
||||
output().mode_set = true;
|
||||
op.mode_set = true;
|
||||
setPowerState(PowerStateOn);
|
||||
|
||||
if (!op.plane_set) {
|
||||
op.plane_set = true;
|
||||
if (op.wants_plane) {
|
||||
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 == -1)
|
||||
qErrnoWarning(errno, "drmModeSetPlane failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ret = drmModePageFlip(device()->fd(),
|
||||
output().crtc_id,
|
||||
int ret = drmModePageFlip(fd,
|
||||
op.crtc_id,
|
||||
fb->fb,
|
||||
DRM_MODE_PAGE_FLIP_EVENT,
|
||||
this);
|
||||
|
@ -39,11 +39,11 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "qeglfskmsegldeviceintegration.h"
|
||||
#include "qeglfskmsegldevice.h"
|
||||
#include "qeglfskmsegldevicescreen.h"
|
||||
#include <QtEglSupport/private/qeglconvenience_p.h>
|
||||
#include "private/qeglfswindow_p.h"
|
||||
#include "private/qeglfscursor_p.h"
|
||||
#include "qeglfskmsegldevice.h"
|
||||
#include "qeglfskmsscreen.h"
|
||||
#include <QLoggingCategory>
|
||||
#include <private/qmath_p.h>
|
||||
|
||||
@ -171,20 +171,23 @@ void QEglJetsonTK1Window::resetSurface()
|
||||
return;
|
||||
}
|
||||
|
||||
QEglFSKmsScreen *cur_screen = static_cast<QEglFSKmsScreen*>(screen());
|
||||
QEglFSKmsEglDeviceScreen *cur_screen = static_cast<QEglFSKmsEglDeviceScreen *>(screen());
|
||||
Q_ASSERT(cur_screen);
|
||||
qCDebug(qLcEglfsKmsDebug, "Searching for id: %d", cur_screen->output().crtc_id);
|
||||
QEglFSKmsOutput &output(cur_screen->output());
|
||||
const uint32_t wantedId = !output.wants_plane ? output.crtc_id : output.plane_id;
|
||||
qCDebug(qLcEglfsKmsDebug, "Searching for id: %d", wantedId);
|
||||
|
||||
EGLOutputLayerEXT layer = EGL_NO_OUTPUT_LAYER_EXT;
|
||||
for (int i = 0; i < actualCount; ++i) {
|
||||
EGLAttrib id;
|
||||
if (m_integration->m_funcs->query_output_layer_attrib(display, layers[i], EGL_DRM_CRTC_EXT, &id)) {
|
||||
qCDebug(qLcEglfsKmsDebug, " [%d] layer %p - crtc %d", i, layers[i], (int) id);
|
||||
if (id == EGLAttrib(cur_screen->output().crtc_id))
|
||||
if (id == EGLAttrib(wantedId))
|
||||
layer = layers[i];
|
||||
} else if (m_integration->m_funcs->query_output_layer_attrib(display, layers[i], EGL_DRM_PLANE_EXT, &id)) {
|
||||
// Not used yet, just for debugging.
|
||||
qCDebug(qLcEglfsKmsDebug, " [%d] layer %p - plane %d", i, layers[i], (int) id);
|
||||
if (id == EGLAttrib(wantedId))
|
||||
layer = layers[i];
|
||||
} else {
|
||||
qCDebug(qLcEglfsKmsDebug, " [%d] layer %p - unknown", i, layers[i]);
|
||||
}
|
||||
|
@ -67,13 +67,16 @@ QPlatformCursor *QEglFSKmsEglDeviceScreen::cursor() const
|
||||
|
||||
void QEglFSKmsEglDeviceScreen::waitForFlip()
|
||||
{
|
||||
if (!output().mode_set) {
|
||||
output().mode_set = true;
|
||||
QEglFSKmsOutput &op(output());
|
||||
const int fd = device()->fd();
|
||||
const uint32_t w = op.modes[op.mode].hdisplay;
|
||||
const uint32_t h = op.modes[op.mode].vdisplay;
|
||||
|
||||
drmModeCrtcPtr currentMode = drmModeGetCrtc(device()->fd(), output().crtc_id);
|
||||
const bool alreadySet = currentMode
|
||||
&& currentMode->width == output().modes[output().mode].hdisplay
|
||||
&& currentMode->height == output().modes[output().mode].vdisplay;
|
||||
if (!op.mode_set) {
|
||||
op.mode_set = true;
|
||||
|
||||
drmModeCrtcPtr currentMode = drmModeGetCrtc(fd, op.crtc_id);
|
||||
const bool alreadySet = currentMode && currentMode->width == w && currentMode->height == h;
|
||||
if (currentMode)
|
||||
drmModeFreeCrtc(currentMode);
|
||||
if (alreadySet) {
|
||||
@ -87,14 +90,26 @@ void QEglFSKmsEglDeviceScreen::waitForFlip()
|
||||
}
|
||||
|
||||
qCDebug(qLcEglfsKmsDebug, "Setting mode");
|
||||
int ret = drmModeSetCrtc(device()->fd(), output().crtc_id,
|
||||
int ret = drmModeSetCrtc(fd, op.crtc_id,
|
||||
uint32_t(-1), 0, 0,
|
||||
&output().connector_id, 1,
|
||||
&output().modes[output().mode]);
|
||||
&op.connector_id, 1,
|
||||
&op.modes[op.mode]);
|
||||
if (ret)
|
||||
qFatal("drmModeSetCrtc failed");
|
||||
qErrnoWarning(errno, "drmModeSetCrtc failed");
|
||||
}
|
||||
|
||||
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 == -1)
|
||||
qErrnoWarning(errno, "drmModeSetPlane failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -329,9 +329,32 @@ QEglFSKmsScreen *QEglFSKmsDevice::createScreenForConnector(drmModeResPtr resourc
|
||||
drmModeGetCrtc(m_dri_fd, crtc_id),
|
||||
modes,
|
||||
connector->subpixel,
|
||||
connectorProperty(connector, QByteArrayLiteral("DPMS"))
|
||||
connectorProperty(connector, QByteArrayLiteral("DPMS")),
|
||||
false,
|
||||
0,
|
||||
false
|
||||
};
|
||||
|
||||
bool ok;
|
||||
int idx = qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_PLANE_INDEX", &ok);
|
||||
if (ok) {
|
||||
drmModePlaneRes *planeResources = drmModeGetPlaneResources(m_dri_fd);
|
||||
if (planeResources) {
|
||||
if (idx >= 0 && idx < int(planeResources->count_planes)) {
|
||||
drmModePlane *plane = drmModeGetPlane(m_dri_fd, planeResources->planes[idx]);
|
||||
if (plane) {
|
||||
output.wants_plane = true;
|
||||
output.plane_id = plane->plane_id;
|
||||
qCDebug(qLcEglfsKmsDebug, "Forcing plane index %d, plane id %u (belongs to crtc id %u)",
|
||||
idx, plane->plane_id, plane->crtc_id);
|
||||
drmModeFreePlane(plane);
|
||||
}
|
||||
} else {
|
||||
qWarning("Invalid plane index %d, must be between 0 and %u", idx, planeResources->count_planes - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_crtc_allocator |= (1 << output.crtc_id);
|
||||
m_connector_allocator |= (1 << output.connector_id);
|
||||
|
||||
@ -406,7 +429,7 @@ void QEglFSKmsDevice::createScreens()
|
||||
if (idx >= 0 && idx < resources->count_connectors)
|
||||
wantedConnectorIndex = idx;
|
||||
else
|
||||
qWarning("Invalid connector index %d", idx);
|
||||
qWarning("Invalid connector index %d, must be between 0 and %u", idx, resources->count_connectors - 1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < resources->count_connectors; i++) {
|
||||
|
@ -67,6 +67,9 @@ struct QEglFSKmsOutput
|
||||
QList<drmModeModeInfo> modes;
|
||||
int subpixel;
|
||||
drmModePropertyPtr dpms_prop;
|
||||
bool wants_plane;
|
||||
uint32_t plane_id;
|
||||
bool plane_set;
|
||||
};
|
||||
|
||||
class Q_EGLFS_EXPORT QEglFSKmsScreen : public QEglFSScreen
|
||||
|
Loading…
x
Reference in New Issue
Block a user