From ef204659b9c5d21c77a40c8bc11cd98039785303 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Samuel=20R=C3=B8dal?= Date: Tue, 29 May 2012 14:18:04 +0200 Subject: [PATCH] Fixed KMS y-invertedness. Upgrade to new gbm_surface API which lets us use eglCreateWindowSurface. Change-Id: I4af86d442375017ae3b4744e7b3bdebf3b496b6e Reviewed-by: Andy Nichols --- src/plugins/platforms/kms/kms.pro | 2 - src/plugins/platforms/kms/qkmsbuffermanager.cpp | 200 ---------------------- src/plugins/platforms/kms/qkmsbuffermanager.h | 105 ------------ src/plugins/platforms/kms/qkmscontext.cpp | 64 ++++--- src/plugins/platforms/kms/qkmscontext.h | 8 +- src/plugins/platforms/kms/qkmsdevice.cpp | 42 +---- src/plugins/platforms/kms/qkmsdevice.h | 1 - src/plugins/platforms/kms/qkmsintegration.cpp | 3 +- src/plugins/platforms/kms/qkmsnativeinterface.cpp | 10 +- src/plugins/platforms/kms/qkmsscreen.cpp | 146 ++++++++++------ src/plugins/platforms/kms/qkmsscreen.h | 41 ++++- src/plugins/platforms/kms/qkmswindow.cpp | 2 + 12 files changed, 177 insertions(+), 447 deletions(-) delete mode 100644 src/plugins/platforms/kms/qkmsbuffermanager.cpp delete mode 100644 src/plugins/platforms/kms/qkmsbuffermanager.h diff --git a/src/plugins/platforms/kms/kms.pro b/src/plugins/platforms/kms/kms.pro index f97973b..4a50569 100644 --- a/src/plugins/platforms/kms/kms.pro +++ b/src/plugins/platforms/kms/kms.pro @@ -17,7 +17,6 @@ SOURCES = main.cpp \ qkmswindow.cpp \ qkmscursor.cpp \ qkmsdevice.cpp \ - qkmsbuffermanager.cpp \ qkmsbackingstore.cpp \ qkmsnativeinterface.cpp \ qkmsudevlistener.cpp \ @@ -29,7 +28,6 @@ HEADERS = qkmsintegration.h \ qkmswindow.h \ qkmscursor.h \ qkmsdevice.h \ - qkmsbuffermanager.h \ qkmsbackingstore.h \ qkmsnativeinterface.h \ qkmsudevlistener.h \ diff --git a/src/plugins/platforms/kms/qkmsbuffermanager.cpp b/src/plugins/platforms/kms/qkmsbuffermanager.cpp deleted file mode 100644 index 05da957..0000000 --- a/src/plugins/platforms/kms/qkmsbuffermanager.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qkmsbuffermanager.h" -#include "qkmsscreen.h" -#include "qkmscontext.h" -#include "qkmsdevice.h" - -QT_BEGIN_NAMESPACE - -QKmsBufferManager::QKmsBufferManager(QKmsScreen *screen) : - m_screen(screen), - m_frameBufferObject(0), - m_renderTarget(0), - m_displayCanidate(0), - m_currentDisplay(0) -{ -} - -QKmsBufferManager::~QKmsBufferManager() -{ - clearBuffers(); - glDeleteFramebuffers(1, &m_frameBufferObject); -} - -void QKmsBufferManager::setupBuffersForMode(const drmModeModeInfo &mode, int numBuffers) -{ - eglMakeCurrent(m_screen->device()->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, m_screen->device()->eglContext()); - m_screen->bindFramebuffer(); - - - if (m_frameBufferObject) { - clearBuffers(); - } else { - //Setup Framebuffer Object - glGenFramebuffers(1, &m_frameBufferObject); - glBindFramebuffer(GL_FRAMEBUFFER, m_frameBufferObject); - } - - //Setup shared Depth/Stencil buffer - glGenRenderbuffers(1, &m_depthAndStencilBufferObject); - glBindRenderbuffer(GL_RENDERBUFFER, m_depthAndStencilBufferObject); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, - mode.hdisplay, mode.vdisplay); - - //Setup "numBuffer" many rendering targets - for (int i = 0; i < numBuffers; i++) { - QKmsFramebuffer *buffer = new QKmsFramebuffer(); - - glGenRenderbuffers(1, &buffer->renderBuffer); - glBindRenderbuffer(GL_RENDERBUFFER, buffer->renderBuffer); - - buffer->graphicsBufferObject = gbm_bo_create(m_screen->device()->gbmDevice(), - mode.hdisplay, mode.vdisplay, - GBM_BO_FORMAT_XRGB8888, - GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); - buffer->eglImage = eglCreateImageKHR(m_screen->device()->eglDisplay(), 0, EGL_NATIVE_PIXMAP_KHR, - buffer->graphicsBufferObject, 0); - glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, buffer->eglImage); - - quint32 stride = gbm_bo_get_pitch(buffer->graphicsBufferObject); - quint32 handle = gbm_bo_get_handle(buffer->graphicsBufferObject).u32; - - int status = drmModeAddFB(m_screen->device()->fd(), mode.hdisplay, mode.vdisplay, - 32, 32, stride, handle, &buffer->framebufferId); - //Todo: IF this returns true, then this is one less buffer that we use - //Not so fatal, but not handled at the moment. - if (status) - qFatal("failed to add framebuffer"); - m_framebuffers.append(buffer); - } - //Attach the Depth and Stencil buffer - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, - m_depthAndStencilBufferObject); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_STENCIL_ATTACHMENT, - GL_RENDERBUFFER, - m_depthAndStencilBufferObject); - //Attach renderbuffer as Color Attachment. - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - this->renderTargetBuffer()); - - eglMakeCurrent(m_screen->device()->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); -} - -void QKmsBufferManager::clearBuffers() -{ - //Make sure that the FBO is binded - glBindFramebuffer(GL_FRAMEBUFFER, m_frameBufferObject); - //Detach the Color/Depth/Stencil Attachments. - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, - 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_STENCIL_ATTACHMENT, - GL_RENDERBUFFER, - 0); - glBindRenderbuffer(GL_RENDERBUFFER, 0); - //Delete the shared Depth/Stencil buffer - glDeleteRenderbuffers(1, &m_depthAndStencilBufferObject); - - //Delete each renderbuffer object - //Delete each EGLImage - //Remove each drm Framebuffer - foreach (QKmsFramebuffer *buffer, m_framebuffers) { - glDeleteRenderbuffers(1, &buffer->renderBuffer); - eglDestroyImageKHR(m_screen->device()->eglDisplay(), buffer->eglImage); - drmModeRmFB(m_screen->device()->fd(), buffer->framebufferId); - delete buffer; - } - m_framebuffers.clear(); -} - -GLuint QKmsBufferManager::renderTargetBuffer() -{ - //TODO: Handle more senarios than assuming at least 2 buffers - if (!m_renderTarget) { - m_renderTarget = m_framebuffers.at(1); - } - return m_renderTarget->renderBuffer; -} - -quint32 QKmsBufferManager::displayFramebufferId() -{ - if (!m_currentDisplay) { - m_currentDisplay = m_framebuffers.at(0); - m_currentDisplay->available = false; - return m_currentDisplay->framebufferId; - } - - if (!m_displayCanidate) - return m_currentDisplay->framebufferId; - - m_currentDisplay->available = true; - m_displayCanidate->available = false; - m_currentDisplay = m_displayCanidate; - return m_currentDisplay->framebufferId; - -} - -bool QKmsBufferManager::nextBuffer() -{ - m_displayCanidate = m_renderTarget; - foreach (QKmsFramebuffer *buffer, m_framebuffers) { - if (buffer->available && buffer != m_displayCanidate) { - m_renderTarget = buffer; - return true; - } - } - return false; -} - -QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmsbuffermanager.h b/src/plugins/platforms/kms/qkmsbuffermanager.h deleted file mode 100644 index 8f7970f..0000000 --- a/src/plugins/platforms/kms/qkmsbuffermanager.h +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QKMSBUFFERMANAGER_H -#define QKMSBUFFERMANAGER_H - -#include -#include - -#define EGL_EGLEXT_PROTOTYPES 1 -#define GL_GLEXT_PROTOTYPES 1 - -extern "C" { -#include -#include -#include -} - -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QKmsScreen; - -class QKmsFramebuffer -{ -public: - QKmsFramebuffer() : available(true) {} - gbm_bo *graphicsBufferObject; - GLuint renderBuffer; - EGLImageKHR eglImage; - quint32 framebufferId; - bool available; -}; - - -class QKmsBufferManager -{ -public: - explicit QKmsBufferManager(QKmsScreen *screen); - ~QKmsBufferManager(); - void setupBuffersForMode(const drmModeModeInfo &mode, int numBuffers = 3); - GLuint framebufferObject() const { return m_frameBufferObject; } - quint32 displayFramebufferId(); - GLuint renderTargetBuffer(); - bool nextBuffer(); - -private: - void clearBuffers(); - - QKmsScreen *m_screen; - QList m_framebuffers; - GLuint m_frameBufferObject; - GLuint m_depthAndStencilBufferObject; - - QKmsFramebuffer *m_renderTarget; - QKmsFramebuffer *m_displayCanidate; - QKmsFramebuffer *m_currentDisplay; - -}; - -QT_END_NAMESPACE - -#endif // QKMSBUFFERMANAGER_H diff --git a/src/plugins/platforms/kms/qkmscontext.cpp b/src/plugins/platforms/kms/qkmscontext.cpp index f2662e0..e5fd10a 100644 --- a/src/plugins/platforms/kms/qkmscontext.cpp +++ b/src/plugins/platforms/kms/qkmscontext.cpp @@ -44,29 +44,56 @@ #include "qkmscontext.h" #include "qkmswindow.h" +#include + +#include QT_BEGIN_NAMESPACE -QKmsContext::QKmsContext(QKmsDevice *device) - : QPlatformOpenGLContext(), - m_device(device) +QKmsContext::QKmsContext(QOpenGLContext *context, QKmsDevice *device) + : QPlatformOpenGLContext() + , m_device(device) +{ + EGLDisplay display = m_device->eglDisplay(); + EGLConfig config = q_configFromGLFormat(display, QKmsScreen::tweakFormat(context->format()), true); + m_format = q_glFormatFromConfig(display, config); + + //Initialize EGLContext + static EGLint contextAttribs[] = { + EGL_CONTEXT_CLIENT_VERSION, context->format().majorVersion(), + EGL_NONE + }; + + eglBindAPI(EGL_OPENGL_ES_API); + m_eglContext = eglCreateContext(display, config, 0, contextAttribs); + if (m_eglContext == EGL_NO_CONTEXT) { + qWarning("QKmsContext::QKmsContext(): eglError: %x, this: %p", + eglGetError(), this); + m_eglContext = 0; + } +} + +bool QKmsContext::isValid() const { + return m_eglContext != EGL_NO_CONTEXT; } bool QKmsContext::makeCurrent(QPlatformSurface *surface) { EGLDisplay display = m_device->eglDisplay(); - EGLContext context = m_device->eglContext(); - bool ok = eglMakeCurrent(display, EGL_NO_SURFACE, - EGL_NO_SURFACE, context); + QPlatformWindow *window = static_cast(surface); + QKmsScreen *screen = static_cast (QPlatformScreen::platformScreenForWindow(window->window())); + + EGLSurface eglSurface = screen->eglSurface(); + + screen->waitForPageFlipComplete(); + + bool ok = eglMakeCurrent(display, eglSurface, eglSurface, m_eglContext); if (!ok) - qWarning("QKmsContext::makeCurrent(): eglError: %d, this: %p", + qWarning("QKmsContext::makeCurrent(): eglError: %x, this: %p", eglGetError(), this); - QPlatformWindow *window = static_cast(surface); - QKmsScreen *screen = static_cast (QPlatformScreen::platformScreenForWindow(window->window())); - screen->bindFramebuffer(); return true; } @@ -75,17 +102,13 @@ void QKmsContext::doneCurrent() bool ok = eglMakeCurrent(m_device->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (!ok) - qWarning("QKmsContext::doneCurrent(): eglError: %d, this: %p", + qWarning("QKmsContext::doneCurrent(): eglError: %x, this: %p", eglGetError(), this); } void QKmsContext::swapBuffers(QPlatformSurface *surface) { - //After flush, the current render target should be moved to - //latest complete - glFlush(); - //Cast context to a window surface and get the screen the context //is on and call swapBuffers on that screen. QPlatformWindow *window = static_cast(surface); @@ -101,19 +124,12 @@ void (*QKmsContext::getProcAddress(const QByteArray &procName)) () EGLContext QKmsContext::eglContext() const { - return m_device->eglContext(); + return m_eglContext; } QSurfaceFormat QKmsContext::format() const { - return QSurfaceFormat(); -} - -GLuint QKmsContext::defaultFramebufferObject(QPlatformSurface *surface) const -{ - QPlatformWindow *window = static_cast(surface); - QKmsScreen *screen = static_cast (QPlatformScreen::platformScreenForWindow(window->window())); - return screen->framebufferObject(); + return m_format; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmscontext.h b/src/plugins/platforms/kms/qkmscontext.h index 32223ad..4318202 100644 --- a/src/plugins/platforms/kms/qkmscontext.h +++ b/src/plugins/platforms/kms/qkmscontext.h @@ -54,20 +54,22 @@ class QKmsDevice; class QKmsContext : public QPlatformOpenGLContext { public: - QKmsContext(QKmsDevice *device); + QKmsContext(QOpenGLContext *context, QKmsDevice *device); bool makeCurrent(QPlatformSurface *surface); void doneCurrent(); void swapBuffers(QPlatformSurface *surface); void (*getProcAddress(const QByteArray &procName)) (); + bool isValid() const; + QSurfaceFormat format() const; EGLContext eglContext() const; - GLuint defaultFramebufferObject(QPlatformSurface *surface) const; - private: + EGLContext m_eglContext; + QSurfaceFormat m_format; QKmsDevice *m_device; }; diff --git a/src/plugins/platforms/kms/qkmsdevice.cpp b/src/plugins/platforms/kms/qkmsdevice.cpp index 43f2101..1937b26 100644 --- a/src/plugins/platforms/kms/qkmsdevice.cpp +++ b/src/plugins/platforms/kms/qkmsdevice.cpp @@ -73,37 +73,14 @@ QKmsDevice::QKmsDevice(const QString &path, QKmsIntegration *parent) : qFatal("EGL error"); } - QString extensions = eglQueryString(m_eglDisplay, EGL_EXTENSIONS); - if (!extensions.contains(QString::fromLatin1("EGL_KHR_surfaceless_opengl"))) { - qFatal("EGL_KHR_surfaceless_opengl extension not available"); - } - - //Initialize EGLContext - static EGLint contextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - - eglBindAPI(EGL_OPENGL_ES_API); - m_eglContext = eglCreateContext(m_eglDisplay, 0, 0, contextAttribs); - if (m_eglContext == EGL_NO_CONTEXT) { - qWarning("Could not create the EGL context."); - eglTerminate(m_eglDisplay); - qFatal("EGL error"); - } - createScreens(); - QSocketNotifier *notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); - connect(notifier, SIGNAL(activated(int)), this, SLOT(handlePageFlipCompleted())); +// QSocketNotifier *notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); +// connect(notifier, SIGNAL(activated(int)), this, SLOT(handlePageFlipCompleted())); } QKmsDevice::~QKmsDevice() { - if (m_eglContext != EGL_NO_CONTEXT) { - eglDestroyContext(m_eglDisplay, m_eglContext); - m_eglContext = EGL_NO_CONTEXT; - } } void QKmsDevice::createScreens() @@ -127,7 +104,6 @@ void QKmsDevice::createScreens() void QKmsDevice::handlePageFlipCompleted() { - //qDebug() << "Display signal received"; drmEventContext eventContext; memset(&eventContext, 0, sizeof eventContext); @@ -143,21 +119,9 @@ void QKmsDevice::pageFlipHandler(int fd, unsigned int frame, unsigned int sec, u Q_UNUSED(frame) Q_UNUSED(sec) Q_UNUSED(usec) - static unsigned int previousTime = 0; - unsigned int currentTime = sec * 1000000 + usec; - unsigned int refreshTime = 0; -// qDebug() << "fd: " << fd << " frame: " << frame << " sec: " -// << sec << " usec: " << usec << " data: " << data -// << "msecs" << sec * 1000 + usec / 1000; QKmsScreen *screen = static_cast(data); - - if (previousTime == 0) - refreshTime = 16000; - else - refreshTime = currentTime - previousTime; - - screen->setFlipReady(refreshTime); + screen->handlePageFlipped(); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmsdevice.h b/src/plugins/platforms/kms/qkmsdevice.h index 638fe78..8797b82 100644 --- a/src/plugins/platforms/kms/qkmsdevice.h +++ b/src/plugins/platforms/kms/qkmsdevice.h @@ -65,7 +65,6 @@ public: EGLDisplay eglDisplay() { return m_eglDisplay; } gbm_device *gbmDevice() { return m_graphicsBufferManager; } - EGLContext eglContext() { return m_eglContext; } int fd() const { return m_fd; } static void pageFlipHandler(int fd, unsigned int frame, unsigned int sec, diff --git a/src/plugins/platforms/kms/qkmsintegration.cpp b/src/plugins/platforms/kms/qkmsintegration.cpp index 91e8ae4..8b3ef91 100644 --- a/src/plugins/platforms/kms/qkmsintegration.cpp +++ b/src/plugins/platforms/kms/qkmsintegration.cpp @@ -95,6 +95,7 @@ bool QKmsIntegration::hasCapability(QPlatformIntegration::Capability cap) const case ThreadedPixmaps: return true; case OpenGL: return true; case ThreadedOpenGL: return true; + case BufferQueueingOpenGL: return true; default: return QPlatformIntegration::hasCapability(cap); } } @@ -102,7 +103,7 @@ bool QKmsIntegration::hasCapability(QPlatformIntegration::Capability cap) const QPlatformOpenGLContext *QKmsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { QKmsScreen *screen = static_cast(context->screen()->handle()); - return new QKmsContext(screen->device()); + return new QKmsContext(context, screen->device()); } QPlatformWindow *QKmsIntegration::createPlatformWindow(QWindow *window) const diff --git a/src/plugins/platforms/kms/qkmsnativeinterface.cpp b/src/plugins/platforms/kms/qkmsnativeinterface.cpp index 8e026b2..b24e9d7 100644 --- a/src/plugins/platforms/kms/qkmsnativeinterface.cpp +++ b/src/plugins/platforms/kms/qkmsnativeinterface.cpp @@ -87,15 +87,9 @@ void *QKmsNativeInterface::eglDisplayForWindow(QWindow *window) return device->eglDisplay(); } -void *QKmsNativeInterface::eglContextForWindow(QWindow *window) +void *QKmsNativeInterface::eglContextForWindow(QWindow *) { - QKmsScreen *screen = qPlatformScreenForWindow(window); - if (!screen) - return 0; - QKmsDevice *device = screen->device(); - if (!device) - return 0; - return device->eglContext(); + return 0; } QKmsScreen *QKmsNativeInterface::qPlatformScreenForWindow(QWindow *window) diff --git a/src/plugins/platforms/kms/qkmsscreen.cpp b/src/plugins/platforms/kms/qkmsscreen.cpp index 76b9bce..790c231 100644 --- a/src/plugins/platforms/kms/qkmsscreen.cpp +++ b/src/plugins/platforms/kms/qkmsscreen.cpp @@ -39,11 +39,16 @@ ** ****************************************************************************/ //#include -#include "qkmscursor.h" + #include "qkmsscreen.h" +#include "qkmscursor.h" #include "qkmsdevice.h" #include "qkmscontext.h" -#include "qkmsbuffermanager.h" + +#include + +#include +#include QT_BEGIN_NAMESPACE @@ -60,12 +65,13 @@ static drmModeModeInfo builtin_1024x768 = { QKmsScreen::QKmsScreen(QKmsDevice *device, int connectorId) : m_device(device), - m_flipReady(true), + m_current_bo(0), + m_next_bo(0), m_connectorId(connectorId), m_depth(32), m_format(QImage::Format_Invalid), - m_bufferManager(this), - m_refreshTime(16000) + m_refreshTime(16000), + m_modeSet(false) { m_cursor = new QKmsCursor(this); initializeScreenMode(); @@ -101,11 +107,6 @@ QPlatformCursor *QKmsScreen::cursor() const return m_cursor; } -GLuint QKmsScreen::framebufferObject() const -{ - return m_bufferManager.framebufferObject(); -} - void QKmsScreen::initializeScreenMode() { //Determine optimal mode for screen @@ -132,71 +133,100 @@ void QKmsScreen::initializeScreenMode() if (i == resources->count_crtcs) qFatal("No usable crtc for encoder."); + m_oldCrtc = drmModeGetCrtc(m_device->fd(), encoder->crtc_id); + m_crtcId = resources->crtcs[i]; m_mode = *mode; m_geometry = QRect(0, 0, m_mode.hdisplay, m_mode.vdisplay); + qDebug() << "kms initialized with geometry" << m_geometry; m_depth = 32; m_format = QImage::Format_RGB32; m_physicalSize = QSizeF(connector->mmWidth, connector->mmHeight); - //Setup three buffers for current mode - m_bufferManager.setupBuffersForMode(m_mode, 3); - - //Set the Mode of the screen. - int ret = drmModeSetCrtc(m_device->fd(), m_crtcId, m_bufferManager.displayFramebufferId(), - 0, 0, &m_connectorId, 1, &m_mode); - if (ret) - qFatal("failed to set mode"); + m_gbmSurface = gbm_surface_create(m_device->gbmDevice(), + m_mode.hdisplay, m_mode.vdisplay, + GBM_BO_FORMAT_XRGB8888, + GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); + qDebug() << "created gbm surface" << m_gbmSurface << m_mode.hdisplay << m_mode.vdisplay; //Cleanup drmModeFreeEncoder(encoder); drmModeFreeConnector(connector); drmModeFreeResources(resources); } -void QKmsScreen::bindFramebuffer() +QSurfaceFormat QKmsScreen::tweakFormat(const QSurfaceFormat &format) { - if (m_bufferManager.framebufferObject()) { - glBindFramebuffer(GL_FRAMEBUFFER, m_bufferManager.framebufferObject()); + QSurfaceFormat fmt = format; + fmt.setRedBufferSize(8); + fmt.setGreenBufferSize(8); + fmt.setBlueBufferSize(8); + if (fmt.alphaBufferSize() != -1) + fmt.setAlphaBufferSize(8); + return fmt; +} - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - m_bufferManager.renderTargetBuffer()); - } +void QKmsScreen::initializeWithFormat(const QSurfaceFormat &format) +{ + EGLDisplay display = m_device->eglDisplay(); + EGLConfig config = q_configFromGLFormat(display, tweakFormat(format), true); + + m_eglWindowSurface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)m_gbmSurface, NULL); + qDebug() << "created window surface"; } void QKmsScreen::swapBuffers() { - waitForPageFlipComplete(); - - if ( m_flipReady ) - performPageFlip(); - //TODO: Do something with return value here - m_bufferManager.nextBuffer(); - //qDebug() << "swapBuffers now rendering to " << m_bufferManager.renderTargetBuffer(); - bindFramebuffer(); + eglSwapBuffers(m_device->eglDisplay(), m_eglWindowSurface); + + m_next_bo = gbm_surface_lock_front_buffer(m_gbmSurface); + if (!m_next_bo) + qFatal("kms: Failed to lock front buffer"); + + performPageFlip(); } void QKmsScreen::performPageFlip() { - quint32 displayFramebufferId = m_bufferManager.displayFramebufferId(); - //qDebug() << "Flipping to framebuffer: " << displayFramebufferId; + if (!m_next_bo) + return; + + uint32_t width = gbm_bo_get_width(m_next_bo); + uint32_t height = gbm_bo_get_height(m_next_bo); + uint32_t stride = gbm_bo_get_pitch(m_next_bo); + uint32_t handle = gbm_bo_get_handle(m_next_bo).u32; + + uint32_t fb_id; + int ret = drmModeAddFB(m_device->fd(), width, height, 24, 32, + stride, handle, &fb_id); + if (ret) { + qFatal("kms: Failed to create fb: fd %d, w %d, h %d, stride %d, handle %d, ret %d", + m_device->fd(), width, height, stride, handle, ret); + } + + if (!m_modeSet) { + //Set the Mode of the screen. + int ret = drmModeSetCrtc(m_device->fd(), m_crtcId, fb_id, + 0, 0, &m_connectorId, 1, &m_mode); + if (ret) + qFatal("failed to set mode"); + m_modeSet = true; + } int pageFlipStatus = drmModePageFlip(m_device->fd(), m_crtcId, - displayFramebufferId, + fb_id, DRM_MODE_PAGE_FLIP_EVENT, this); if (pageFlipStatus) qWarning("Pageflip status: %d", pageFlipStatus); - - m_flipReady = false; } -void QKmsScreen::setFlipReady(unsigned int time) +void QKmsScreen::handlePageFlipped() { - m_flipReady = true; - m_refreshTime = time; - performPageFlip(); + if (m_current_bo) + gbm_surface_release_buffer(m_gbmSurface, m_current_bo); + + m_current_bo = m_next_bo; + m_next_bo = 0; } QKmsDevice * QKmsScreen::device() const @@ -206,23 +236,25 @@ QKmsDevice * QKmsScreen::device() const void QKmsScreen::waitForPageFlipComplete() { - //Check manually if there is something to be read on the device - //as there are senarios where the signal is not received (starvation) - fd_set fdSet; - timeval timeValue; - int returnValue; + while (m_next_bo) { +#if 0 + //Check manually if there is something to be read on the device + //as there are senarios where the signal is not received (starvation) + fd_set fdSet; + timeval timeValue; + int returnValue; + + FD_ZERO(&fdSet); + FD_SET(m_device->fd(), &fdSet); + timeValue.tv_sec = 0; + timeValue.tv_usec = 1000; + + returnValue = select(1, &fdSet, 0, 0, &timeValue); + printf("select returns %d\n", returnValue); +#endif - FD_ZERO(&fdSet); - FD_SET(m_device->fd(), &fdSet); - timeValue.tv_sec = 0; - timeValue.tv_usec = m_refreshTime; - - returnValue = select(1, &fdSet, 0, 0, &timeValue); - - if (returnValue) { m_device->handlePageFlipCompleted(); } - } diff --git a/src/plugins/platforms/kms/qkmsscreen.h b/src/plugins/platforms/kms/qkmsscreen.h index e8e6bda..57c96fb 100644 --- a/src/plugins/platforms/kms/qkmsscreen.h +++ b/src/plugins/platforms/kms/qkmsscreen.h @@ -42,8 +42,23 @@ #ifndef QKMSSCREEN_H #define QKMSSCREEN_H +#include + +#define EGL_EGLEXT_PROTOTYPES 1 +#define GL_GLEXT_PROTOTYPES 1 + +extern "C" { +#include +#include +#include +} + +#include +#include +#include +#include + #include -#include "qkmsbuffermanager.h" QT_BEGIN_NAMESPACE @@ -63,22 +78,28 @@ public: QSizeF physicalSize() const; QPlatformCursor *cursor() const; - GLuint framebufferObject() const; quint32 crtcId() const { return m_crtcId; } QKmsDevice *device() const; + void initializeWithFormat(const QSurfaceFormat &format); + //Called by context for each screen - void bindFramebuffer(); void swapBuffers(); - void setFlipReady(unsigned int time); + void handlePageFlipped(); + + EGLSurface eglSurface() const { return m_eglWindowSurface; } + + void waitForPageFlipComplete(); + + static QSurfaceFormat tweakFormat(const QSurfaceFormat &format); private: void performPageFlip(); void initializeScreenMode(); - void waitForPageFlipComplete(); QKmsDevice *m_device; - bool m_flipReady; + gbm_bo *m_current_bo; + gbm_bo *m_next_bo; quint32 m_connectorId; quint32 m_crtcId; @@ -88,9 +109,15 @@ private: int m_depth; QImage::Format m_format; + drmModeCrtcPtr m_oldCrtc; + QKmsCursor *m_cursor; - QKmsBufferManager m_bufferManager; unsigned int m_refreshTime; + + gbm_surface *m_gbmSurface; + EGLSurface m_eglWindowSurface; + + bool m_modeSet; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmswindow.cpp b/src/plugins/platforms/kms/qkmswindow.cpp index edbd35d..ebf327c 100644 --- a/src/plugins/platforms/kms/qkmswindow.cpp +++ b/src/plugins/platforms/kms/qkmswindow.cpp @@ -49,6 +49,8 @@ QKmsWindow::QKmsWindow(QWindow *window) : QPlatformWindow(window) { m_screen = QPlatformScreen::platformScreenForWindow(window); + + static_cast(m_screen)->initializeWithFormat(window->requestedFormat()); } void QKmsWindow::setGeometry(const QRect &rect) -- 2.7.4