Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qeglfskmsegldevicescreen.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 Pelagicore AG
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6#include <QGuiApplication>
7#include <QLoggingCategory>
8#include <errno.h>
9
11
12Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
13
16 , m_default_fb_handle(uint32_t(-1))
17 , m_default_fb_id(uint32_t(-1))
18{
19 const int fd = device->fd();
20
21 struct drm_mode_create_dumb createRequest;
22 createRequest.width = output.size.width();
23 createRequest.height = output.size.height();
24 createRequest.bpp = 32;
25 createRequest.flags = 0;
26
27 qCDebug(qLcEglfsKmsDebug, "Creating dumb fb %dx%d", createRequest.width, createRequest.height);
28
29 int ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &createRequest);
30 if (ret < 0)
31 qFatal("Unable to create dumb buffer.\n");
32
33 m_default_fb_handle = createRequest.handle;
34
35 uint32_t handles[4] = { 0, 0, 0, 0 };
36 uint32_t pitches[4] = { 0, 0, 0, 0 };
37 uint32_t offsets[4] = { 0, 0, 0, 0 };
38
39 handles[0] = createRequest.handle;
40 pitches[0] = createRequest.pitch;
41 offsets[0] = 0;
42
43 ret = drmModeAddFB2(fd, createRequest.width, createRequest.height, DRM_FORMAT_ARGB8888, handles,
44 pitches, offsets, &m_default_fb_id, 0);
45 if (ret)
46 qFatal("Unable to add fb\n");
47
48 qCDebug(qLcEglfsKmsDebug, "Added dumb fb %dx%d handle:%u pitch:%d id:%u", createRequest.width, createRequest.height,
49 createRequest.handle, createRequest.pitch, m_default_fb_id);
50}
51
53{
54 int ret;
55 const int fd = device()->fd();
56
57 if (m_default_fb_id != uint32_t(-1)) {
58 ret = drmModeRmFB(fd, m_default_fb_id);
59 if (ret)
60 qErrnoWarning("drmModeRmFB failed");
61 }
62
63 if (m_default_fb_handle != uint32_t(-1)) {
64 struct drm_mode_destroy_dumb destroyRequest;
65 destroyRequest.handle = m_default_fb_handle;
66
67 ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroyRequest);
68 if (ret)
69 qErrnoWarning("DRM_IOCTL_MODE_DESTROY_DUMB failed");
70 }
71
72 const int remainingScreenCount = qGuiApp->screens().size();
73 qCDebug(qLcEglfsKmsDebug, "Screen dtor. Remaining screens: %d", remainingScreenCount);
74 if (!remainingScreenCount && !device()->screenConfig()->separateScreens())
75 static_cast<QEglFSKmsEglDevice *>(device())->destroyGlobalCursor();
76}
77
79{
80 // The base class creates a cursor via integration->createCursor()
81 // in its ctor. With separateScreens just use that. Otherwise
82 // there's a virtual desktop and the device has a global cursor
83 // and the base class has no dedicated cursor at all.
84 // config->hwCursor() is ignored for now, just use the standard OpenGL cursor.
87 : static_cast<QEglFSKmsEglDevice *>(device())->globalCursor();
88}
89
91{
92 QKmsOutput &op(output());
93 const int fd = device()->fd();
94 const uint32_t w = op.modes[op.mode].hdisplay;
95 const uint32_t h = op.modes[op.mode].vdisplay;
96
97 if (!op.mode_set) {
98 op.mode_set = true;
99
100 drmModeCrtcPtr currentMode = drmModeGetCrtc(fd, op.crtc_id);
101 const bool alreadySet = currentMode && currentMode->width == w && currentMode->height == h;
102 if (currentMode)
103 drmModeFreeCrtc(currentMode);
104 if (alreadySet) {
105 // Maybe detecting the DPMS mode could help here, but there are no properties
106 // exposed on the connector apparently. So rely on an env var for now.
107 // Note that typically, we need to set crtc with the default fb even if the
108 // mode did not change, unless QT_QPA_EGLFS_ALWAYS_SET_MODE is explicitly specified.
109 static bool envVarSet = false;
110 static bool alwaysDoSet = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ALWAYS_SET_MODE", &envVarSet);
111 if (envVarSet && !alwaysDoSet) {
112 qCDebug(qLcEglfsKmsDebug, "Mode already set");
113 return;
114 }
115 }
116
117 qCDebug(qLcEglfsKmsDebug, "Setting mode");
118 int ret = drmModeSetCrtc(fd, op.crtc_id,
119 m_default_fb_id, 0, 0,
120 &op.connector_id, 1,
121 &op.modes[op.mode]);
122 if (ret)
123 qErrnoWarning(errno, "drmModeSetCrtc failed");
124 }
125
126 if (!op.forced_plane_set) {
127 op.forced_plane_set = true;
128
129 if (op.wants_forced_plane) {
130 qCDebug(qLcEglfsKmsDebug, "Setting plane %u", op.forced_plane_id);
131 int ret = drmModeSetPlane(fd, op.forced_plane_id, op.crtc_id, m_default_fb_id, 0,
132 0, 0, w, h,
133 0 << 16, 0 << 16, op.size.width() << 16, op.size.height() << 16);
134 if (ret == -1)
135 qErrnoWarning(errno, "drmModeSetPlane failed");
136 }
137 }
138}
139
IOBluetoothDevice * device
QPlatformCursor * cursor() const override
Reimplement this function in subclass to return the cursor of the screen.
QKmsOutput & output()
int currentMode() const override
Reimplement this function in subclass to return the index of the current mode from the modes list.
QEglFSKmsDevice * device() const
QPlatformCursor * cursor() const override
Reimplement this function in subclass to return the cursor of the screen.
int fd() const
QKmsScreenConfig * screenConfig() const
bool separateScreens() const
The QPlatformCursor class provides information about pointer device events (movement,...
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
#define qGuiApp
#define qFatal
Definition qlogging.h:168
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
return ret
GLfloat GLfloat GLfloat w
[0]
GLuint64 GLenum GLint fd
GLfloat GLfloat GLfloat GLfloat h
GLuint GLsizei const GLuint const GLintptr * offsets
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
QT_BEGIN_NAMESPACE typedef uchar * output
uint32_t forced_plane_id
uint32_t crtc_id
bool forced_plane_set
QList< drmModeModeInfo > modes
bool wants_forced_plane
uint32_t connector_id