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:
parent
f20adcde30
commit
df2b76046d
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user