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!");
85 , m_flipPending(
false)
93 const int remainingScreenCount =
qGuiApp->screens().count();
94 qCDebug(qLcEglfsKmsDebug,
"Screen dtor. Remaining screens: %d", remainingScreenCount);
95 if (!remainingScreenCount && !
device()->screenConfig()->separateScreens())
105 if (!
config->separateScreens())
129 EGLint native_format = -1;
130 EGLBoolean success = eglGetConfigAttrib(
display(), eglConfig, EGL_NATIVE_VISUAL_ID, &native_format);
132 <<
"from eglGetConfigAttrib() with return code" << bool(success);
151 qCDebug(qLcEglfsKmsDebug,
"Could not create surface with EGL_NATIVE_VISUAL_ID, falling back to format %x", gbmFormat);
174 const bool clonesAnother = screenThisScreenClones !=
nullptr;
175 if (clonesAnother && !screensCloningThisScreen.
isEmpty()) {
176 qWarning(
"QEglFSKmsGbmScreen %s cannot be clone source and destination at the same time",
qPrintable(
name()));
200 bool doModeSet =
true;
211 if (
device()->hasAtomicSupport()) {
212#if QT_CONFIG(drm_atomic)
213 drmModeAtomicReq *
request =
device()->threadLocalAtomicRequest();
221 int ret = drmModeSetCrtc(
fd,
238 unsigned int sequence,
240 unsigned int tv_usec,
247 screen->pageFlipped(sequence, tv_sec, tv_usec);
277 if (
d.screen !=
this)
283 drmEventContext drmEvent;
284 memset(&drmEvent, 0,
sizeof(drmEvent));
285 drmEvent.version = 2;
286 drmEvent.vblank_handler =
nullptr;
288 drmHandleEvent(
device()->
fd(), &drmEvent);
292#if QT_CONFIG(drm_atomic)
293 device()->threadLocalAtomicReset();
297#if QT_CONFIG(drm_atomic)
301 output.eglfs_plane->framebufferPropertyId, fb);
307 output.eglfs_plane->srcwidthPropertyId,
output.size.width() << 16);
310 output.eglfs_plane->srcXPropertyId, 0);
313 output.eglfs_plane->srcYPropertyId, 0);
316 output.eglfs_plane->srcheightPropertyId,
output.size.height() << 16);
319 output.eglfs_plane->crtcXPropertyId, 0);
322 output.eglfs_plane->crtcYPropertyId, 0);
345 qWarning(
"Cannot sync before platform init!");
363 qWarning(
"FrameBuffer not available. Cannot flip");
372 if (
device()->hasAtomicSupport()) {
373#if QT_CONFIG(drm_atomic)
374 drmModeAtomicReq *
request =
device()->threadLocalAtomicRequest();
376 addAtomicFlip(
request, thisOutput, fb->fb);
390 int ret = drmModePageFlip(
fd,
393 DRM_MODE_PAGE_FLIP_EVENT,
402 if (
d.screen !=
this) {
403 d.screen->ensureModeSet(fb->fb);
404 d.cloneFlipPending =
true;
407 if (
device()->hasAtomicSupport()) {
408#if QT_CONFIG(drm_atomic)
409 drmModeAtomicReq *
request =
device()->threadLocalAtomicRequest();
411 addAtomicFlip(
request, destOutput, fb->fb);
421 int ret = drmModePageFlip(
fd,
424 DRM_MODE_PAGE_FLIP_EVENT,
427 qErrnoWarning(
"Could not queue DRM page flip for screen %s (clones screen %s)",
430 d.cloneFlipPending =
false;
436 if (
device()->hasAtomicSupport()) {
437#if QT_CONFIG(drm_atomic)
438 if (!
device()->threadLocalAtomicCommit(
this)) {
444 gbmRelease.dismiss();
461 if (
d.screen == cloneDestScreen) {
462 d.cloneFlipPending =
false;
480 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)
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
bool isEmpty() const noexcept
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,...)
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)
uint32_t modeIdPropertyId
struct QKmsPlane * eglfs_plane
QList< drmModeModeInfo > modes
uint32_t activePropertyId
bool drm_format_requested_by_user
uint32_t crtcIdPropertyId
uint32_t blendOpPropertyId