9#include <private/qeglfsintegration_p.h>
11#include <QtCore/QLoggingCategory>
13#include <QtGui/private/qguiapplication_p.h>
14#include <QtGui/private/qtguiglobal_p.h>
15#include <QtFbSupport/private/qfbvthandler_p.h>
27 Q_ASSERT(DRM_FORMAT_XRGB8888 == GBM_FORMAT_XRGB8888);
33 Q_ASSERT(DRM_FORMAT_XRGB8888 == GBM_FORMAT_XRGB8888);
42 gbm_device *
device = gbm_bo_get_device(bo);
43 drmModeRmFB(gbm_device_get_fd(
device), fb->
fb);
57 uint32_t
width = gbm_bo_get_width(bo);
58 uint32_t
height = gbm_bo_get_height(bo);
59 uint32_t handles[4] = { gbm_bo_get_handle(bo).u32 };
60 uint32_t
strides[4] = { gbm_bo_get_stride(bo) };
64 auto fb = std::make_unique<FrameBuffer>();
65 qCDebug(qLcEglfsKmsDebug,
"Adding FB, size %ux%u, DRM format 0x%x, stride %u, handle %u",
72 qWarning(
"Failed to create KMS FB!");
86 , m_flipPending(
false)
94 const int remainingScreenCount =
qGuiApp->screens().count();
95 qCDebug(qLcEglfsKmsDebug,
"Screen dtor. Remaining screens: %d", remainingScreenCount);
96 if (!remainingScreenCount && !
device()->screenConfig()->separateScreens())
106 if (!
config->separateScreens())
130 EGLint native_format = -1;
131 EGLBoolean success = eglGetConfigAttrib(
display(), eglConfig, EGL_NATIVE_VISUAL_ID, &native_format);
133 <<
"from eglGetConfigAttrib() with return code" << bool(success);
153 qCDebug(qLcEglfsKmsDebug,
"Could not create surface with EGL_NATIVE_VISUAL_ID, falling back to format %x", gbmFormat);
173 qFatal(
"Could not create GBM surface!");
191 if (!
device()->hasAtomicSupport())
196 const QList<QPlatformScreen *> &screensCloningThisScreen)
199 const bool clonesAnother = screenThisScreenClones !=
nullptr;
200 if (clonesAnother && !screensCloningThisScreen.isEmpty()) {
201 qWarning(
"QEglFSKmsGbmScreen %s cannot be clone source and destination at the same time",
qPrintable(
name()));
226 bool doModeSet =
true;
237 if (
device()->hasAtomicSupport()) {
238#if QT_CONFIG(drm_atomic)
239 drmModeAtomicReq *
request =
device()->threadLocalAtomicRequest();
247 int ret = drmModeSetCrtc(
fd,
264 unsigned int sequence,
266 unsigned int tv_usec,
273 screen->pageFlipped(sequence, tv_sec, tv_usec);
303 if (
d.screen !=
this)
309 drmEventContext drmEvent;
310 memset(&drmEvent, 0,
sizeof(drmEvent));
311 drmEvent.version = 2;
312 drmEvent.vblank_handler =
nullptr;
314 drmHandleEvent(
device()->
fd(), &drmEvent);
318#if QT_CONFIG(drm_atomic)
319 device()->threadLocalAtomicReset();
323#if QT_CONFIG(drm_atomic)
327 output.eglfs_plane->framebufferPropertyId, fb);
333 output.eglfs_plane->srcwidthPropertyId,
output.size.width() << 16);
336 output.eglfs_plane->srcXPropertyId, 0);
339 output.eglfs_plane->srcYPropertyId, 0);
342 output.eglfs_plane->srcheightPropertyId,
output.size.height() << 16);
345 output.eglfs_plane->crtcXPropertyId, 0);
348 output.eglfs_plane->crtcYPropertyId, 0);
371 qWarning(
"Cannot sync before platform init!");
389 qWarning(
"FrameBuffer not available. Cannot flip");
398 if (
device()->hasAtomicSupport()) {
399#if QT_CONFIG(drm_atomic)
400 drmModeAtomicReq *
request =
device()->threadLocalAtomicRequest();
402 addAtomicFlip(
request, thisOutput, fb->fb);
405 drmModeAtomicAddProperty(
request, thisOutput.eglfs_plane->id,
406 thisOutput.eglfs_plane->zposPropertyId, zpos);
410 drmModeAtomicAddProperty(
request, thisOutput.eglfs_plane->id,
411 thisOutput.eglfs_plane->blendOpPropertyId, blendOp);
416 int ret = drmModePageFlip(
fd,
419 DRM_MODE_PAGE_FLIP_EVENT,
428 if (
d.screen !=
this) {
429 d.screen->ensureModeSet(fb->fb);
430 d.cloneFlipPending =
true;
433 if (
device()->hasAtomicSupport()) {
434#if QT_CONFIG(drm_atomic)
435 drmModeAtomicReq *
request =
device()->threadLocalAtomicRequest();
437 addAtomicFlip(
request, destOutput, fb->fb);
447 int ret = drmModePageFlip(
fd,
450 DRM_MODE_PAGE_FLIP_EVENT,
453 qErrnoWarning(
"Could not queue DRM page flip for screen %s (clones screen %s)",
456 d.cloneFlipPending =
false;
462 if (
device()->hasAtomicSupport()) {
463#if QT_CONFIG(drm_atomic)
464 if (!
device()->threadLocalAtomicCommit(
this)) {
470 gbmRelease.dismiss();
487 if (
d.screen == cloneDestScreen) {
488 d.cloneFlipPending =
false;
506 if (
d.cloneFlipPending)
IOBluetoothDevice * device
void startWaitFlip(void *key, QMutex *mutex, QWaitCondition *cond)
QEglFSKmsEventReader * eventReader()
bool usesEventReader() const
static QMutex m_nonThreadedFlipMutex
QEglFSKmsGbmScreen(QEglFSKmsDevice *device, const QKmsOutput &output, bool headless)
void cloneDestFlipFinished(QEglFSKmsGbmScreen *cloneDestScreen)
bool needsNewModeSetForNextFb
gbm_surface * m_gbm_surface
void waitForFlip() override
QEglFSKmsGbmScreen * m_cloneSource
virtual uint32_t gbmFlags()
void initCloning(QPlatformScreen *screenThisScreenClones, const QList< QPlatformScreen * > &screensCloningThisScreen)
void ensureModeSet(uint32_t fb)
QScopedPointer< QEglFSKmsGbmCursor > m_cursor
static void bufferDestroyedHandler(gbm_bo *bo, void *data)
gbm_bo * m_gbm_bo_current
void waitForFlipWithEventReader(QEglFSKmsGbmScreen *screen)
QWaitCondition m_flipCond
virtual void updateFlipStatus()
QPlatformCursor * cursor() const override
Reimplement this function in subclass to return the cursor of the screen.
gbm_surface * createSurface(EGLConfig eglConfig)
FrameBuffer * framebufferForBufferObject(gbm_bo *bo)
QList< CloneDestination > m_cloneDests
static void nonThreadedPageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data)
QString name() const override
int currentMode() const override
Reimplement this function in subclass to return the index of the current mode from the modes list.
QEglFSKmsDevice * device() const
void setPowerState(QPlatformScreen::PowerState state) override
Sets the power state for this screen.
QRect rawGeometry() const override
QPlatformCursor * cursor() const override
Reimplement this function in subclass to return the cursor of the screen.
EGLDisplay display() const
QKmsScreenConfig * screenConfig() const
void unlock() noexcept
Unlocks the mutex.
void lock() noexcept
Locks the mutex.
T * data() const noexcept
Returns the value of the pointer referenced by this object.
bool isNull() const noexcept
Returns true if this object refers to \nullptr.
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
bool wait(QMutex *, QDeadlineTimer=QDeadlineTimer(QDeadlineTimer::Forever))
void qErrnoWarning(const char *msg,...)
#define DRM_FORMAT_MOD_LINEAR
Combined button and popup list for selecting options.
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
QTextStream & dec(QTextStream &stream)
Calls QTextStream::setIntegerBase(10) on stream and returns stream.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void * user_data
static uint32_t gbmFormatToDrmFormat(uint32_t gbmFormat)
static uint32_t drmFormatToGbmFormat(uint32_t drmFormat)
typedef EGLBoolean(EGLAPIENTRYP PFNEGLQUERYDEVICESEXTPROC)(EGLint max_devices
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLint GLsizei GLsizei height
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint GLsizei const GLuint const GLintptr * offsets
GLsizei const GLuint const GLintptr const GLsizei * strides
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
#define qPrintable(string)
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
QT_BEGIN_NAMESPACE typedef uchar * output
QNetworkRequest request(url)
QEglFSKmsGbmScreen * screen
uint32_t modeIdPropertyId
QList< drmModeModeInfo > modes
uint32_t activePropertyId
bool drm_format_requested_by_user
uint32_t crtcIdPropertyId