eglfs: Add vsync support when using NVIDIA eglstreams

Similar to the kms backend a flip event handler can be retrieved using
the drmEvent API to implement vsync.
For this to work the acquire calls need to be done manuallly and the
automatic acquiring needs to be disabled.

Change-Id: I670d288ef68eb49846108db2a31993c6167d9313
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
Dominik Holland 2018-11-07 10:18:14 +01:00 committed by Paul Olav Tvete
parent f20adcde30
commit df2b76046d
3 changed files with 63 additions and 0 deletions

View File

@ -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

View File

@ -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<QEglFSKmsEglDeviceWindow*>(user_data);
window->m_framePending = false;
}
void QEglFSKmsEglDeviceIntegration::presentBuffer(QPlatformSurface *surface)
{
QEglFSKmsEglDeviceWindow *eglWindow = static_cast<QEglFSKmsEglDeviceWindow*>(surface);
eglWindow->flip();
}
QEglFSWindow *QEglFSKmsEglDeviceIntegration::createWindow(QWindow *window) const
{
QEglFSKmsEglDeviceWindow *eglWindow = new QEglFSKmsEglDeviceWindow(window, this);

View File

@ -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: