eglfs: add a default framebuffer to NVIDIA eglstreams

Newer versions of NVIDIA's DRM driver are rejecting the previously
accepted but non-standard use of framebuffer_id -1 in order to set
the output mode but not issue a page flip.

This change adds a default framebuffer to the egldevice driver for
use with the initial calls to set the CRTC mode and plane.

Pick-to: 6.5
Change-Id: I63dbb6b099250fcff7d995eec38fb75c675894cd
Reviewed-by: Samuli Piippo <samuli.piippo@qt.io>
(cherry picked from commit 17a68dae5e9007d9a8b122b4ede1647d5900d6d4)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Kurt Kiefer 2023-09-14 09:25:50 -07:00 committed by Qt Cherry-pick Bot
parent 1f0a31d6a6
commit cf44289e12
2 changed files with 61 additions and 4 deletions

View File

@ -13,11 +13,62 @@ Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
QEglFSKmsEglDeviceScreen::QEglFSKmsEglDeviceScreen(QEglFSKmsDevice *device, const QKmsOutput &output)
: QEglFSKmsScreen(device, output)
, m_default_fb_handle(uint32_t(-1))
, m_default_fb_id(uint32_t(-1))
{
const int fd = device->fd();
struct drm_mode_create_dumb createRequest;
createRequest.width = output.size.width();
createRequest.height = output.size.height();
createRequest.bpp = 32;
createRequest.flags = 0;
qCDebug(qLcEglfsKmsDebug, "Creating dumb fb %dx%d", createRequest.width, createRequest.height);
int ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &createRequest);
if (ret < 0)
qFatal("Unable to create dumb buffer.\n");
m_default_fb_handle = createRequest.handle;
uint32_t handles[4] = { 0, 0, 0, 0 };
uint32_t pitches[4] = { 0, 0, 0, 0 };
uint32_t offsets[4] = { 0, 0, 0, 0 };
handles[0] = createRequest.handle;
pitches[0] = createRequest.pitch;
offsets[0] = 0;
ret = drmModeAddFB2(fd, createRequest.width, createRequest.height, DRM_FORMAT_ARGB8888, handles,
pitches, offsets, &m_default_fb_id, 0);
if (ret)
qFatal("Unable to add fb\n");
qCDebug(qLcEglfsKmsDebug, "Added dumb fb %dx%d handle:%u pitch:%d id:%u", createRequest.width, createRequest.height,
createRequest.handle, createRequest.pitch, m_default_fb_id);
}
QEglFSKmsEglDeviceScreen::~QEglFSKmsEglDeviceScreen()
{
int ret;
const int fd = device()->fd();
if (m_default_fb_id != uint32_t(-1)) {
ret = drmModeRmFB(fd, m_default_fb_id);
if (ret)
qErrnoWarning("drmModeRmFB failed");
}
if (m_default_fb_handle != uint32_t(-1)) {
struct drm_mode_destroy_dumb destroyRequest;
destroyRequest.handle = m_default_fb_handle;
ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroyRequest);
if (ret)
qErrnoWarning("DRM_IOCTL_MODE_DESTROY_DUMB failed");
}
const int remainingScreenCount = qGuiApp->screens().size();
qCDebug(qLcEglfsKmsDebug, "Screen dtor. Remaining screens: %d", remainingScreenCount);
if (!remainingScreenCount && !device()->screenConfig()->separateScreens())
@ -53,8 +104,11 @@ void QEglFSKmsEglDeviceScreen::waitForFlip()
if (alreadySet) {
// Maybe detecting the DPMS mode could help here, but there are no properties
// exposed on the connector apparently. So rely on an env var for now.
static bool alwaysDoSet = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ALWAYS_SET_MODE");
if (!alwaysDoSet) {
// Note that typically, we need to set crtc with the default fb even if the
// mode did not change, unless QT_QPA_EGLFS_ALWAYS_SET_MODE is explicitly specified.
static bool envVarSet = false;
static bool alwaysDoSet = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ALWAYS_SET_MODE", &envVarSet);
if (envVarSet && !alwaysDoSet) {
qCDebug(qLcEglfsKmsDebug, "Mode already set");
return;
}
@ -62,7 +116,7 @@ void QEglFSKmsEglDeviceScreen::waitForFlip()
qCDebug(qLcEglfsKmsDebug, "Setting mode");
int ret = drmModeSetCrtc(fd, op.crtc_id,
uint32_t(-1), 0, 0,
m_default_fb_id, 0, 0,
&op.connector_id, 1,
&op.modes[op.mode]);
if (ret)
@ -74,7 +128,7 @@ void QEglFSKmsEglDeviceScreen::waitForFlip()
if (op.wants_forced_plane) {
qCDebug(qLcEglfsKmsDebug, "Setting plane %u", op.forced_plane_id);
int ret = drmModeSetPlane(fd, op.forced_plane_id, op.crtc_id, uint32_t(-1), 0,
int ret = drmModeSetPlane(fd, op.forced_plane_id, op.crtc_id, m_default_fb_id, 0,
0, 0, w, h,
0 << 16, 0 << 16, op.size.width() << 16, op.size.height() << 16);
if (ret == -1)

View File

@ -17,6 +17,9 @@ public:
QPlatformCursor *cursor() const override;
void waitForFlip() override;
private:
uint32_t m_default_fb_handle;
uint32_t m_default_fb_id;
};
QT_END_NAMESPACE