diff --git a/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h b/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h index c3d3070210..31a79dbc6c 100644 --- a/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h +++ b/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h @@ -131,6 +131,12 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMEROUTPUTEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer); #endif +#ifndef EGL_EXT_stream_acquire_mode +#define EGL_EXT_stream_acquire_mode 1 +#define EGL_CONSUMER_AUTO_ACQUIRE_EXT 0x332B +#define EGL_RESOURCE_BUSY_EXT 0x3353 +#endif + #ifndef EGL_EXT_platform_device #define EGL_PLATFORM_DEVICE_EXT 0x313F #endif @@ -156,6 +162,11 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREATTRIBNVPROC) (EGLDi typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEATTRIBNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); #endif +#ifndef EGL_NV_output_drm_flip_event +#define EGL_NV_output_drm_flip_event 1 +#define EGL_DRM_FLIP_EVENT_DATA_NV 0x333E +#endif + QT_BEGIN_NAMESPACE class QEGLStreamConvenience diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp index ab39af6b80..9f4c9f5703 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp @@ -114,14 +114,18 @@ public: : QEglFSWindow(w) , m_integration(integration) , m_egl_stream(EGL_NO_STREAM_KHR) + , m_framePending(false) { } void invalidateSurface() override; void resetSurface() override; + void flip(); + static void pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data); const QEglFSKmsEglDeviceIntegration *m_integration; EGLStreamKHR m_egl_stream; EGLint m_latency; + bool m_framePending; }; void QEglFSKmsEglDeviceWindow::invalidateSurface() @@ -142,6 +146,9 @@ void QEglFSKmsEglDeviceWindow::resetSurface() streamAttribs[streamAttribCount++] = EGL_STREAM_FIFO_LENGTH_KHR; streamAttribs[streamAttribCount++] = fifoLength; } + + streamAttribs[streamAttribCount++] = EGL_CONSUMER_AUTO_ACQUIRE_EXT; + streamAttribs[streamAttribCount++] = EGL_FALSE; streamAttribs[streamAttribCount++] = EGL_NONE; m_egl_stream = m_integration->m_funcs->create_stream(display, streamAttribs); @@ -239,6 +246,49 @@ void QEglFSKmsEglDeviceWindow::resetSurface() qCDebug(qLcEglfsKmsDebug, "Created stream producer surface %p", m_surface); } +void QEglFSKmsEglDeviceWindow::flip() +{ + EGLDisplay display = screen()->display(); + + EGLAttrib acquire_attribs[3] = { EGL_NONE }; + + acquire_attribs[0] = EGL_DRM_FLIP_EVENT_DATA_NV; + acquire_attribs[1] = (EGLAttrib)this; + acquire_attribs[2] = EGL_NONE; + + if (m_egl_stream != EGL_NO_STREAM_KHR) + if (!m_integration->m_funcs->acquire_stream_attrib_nv(display, m_egl_stream, acquire_attribs)) + qWarning("eglStreamConsumerAcquireAttribNV failed: eglError: %x", eglGetError()); + + m_framePending = true; + + while (m_framePending) { + drmEventContext drmEvent; + memset(&drmEvent, 0, sizeof(drmEvent)); + drmEvent.version = 3; + drmEvent.vblank_handler = nullptr; + drmEvent.page_flip_handler = pageFlipHandler; + drmHandleEvent(m_integration->m_device->fd(), &drmEvent); + } +} + +void QEglFSKmsEglDeviceWindow::pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + Q_UNUSED(fd); + Q_UNUSED(sequence); + Q_UNUSED(tv_sec); + Q_UNUSED(tv_usec); + + QEglFSKmsEglDeviceWindow *window = static_cast(user_data); + window->m_framePending = false; +} + +void QEglFSKmsEglDeviceIntegration::presentBuffer(QPlatformSurface *surface) +{ + QEglFSKmsEglDeviceWindow *eglWindow = static_cast(surface); + eglWindow->flip(); +} + QEglFSWindow *QEglFSKmsEglDeviceIntegration::createWindow(QWindow *window) const { QEglFSKmsEglDeviceWindow *eglWindow = new QEglFSKmsEglDeviceWindow(window, this); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h index 5819d82ebf..0c64d83b12 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h @@ -62,6 +62,8 @@ public: bool supportsPBuffers() const override; QEglFSWindow *createWindow(QWindow *window) const override; + void presentBuffer(QPlatformSurface *surface); + EGLDeviceEXT eglDevice() const { return m_egl_device; } protected: