Fixed KMS y-invertedness.
authorSamuel Rødal <samuel.rodal@nokia.com>
Tue, 29 May 2012 12:18:04 +0000 (14:18 +0200)
committerQt by Nokia <qt-info@nokia.com>
Tue, 29 May 2012 21:48:29 +0000 (23:48 +0200)
Upgrade to new gbm_surface API which lets us use eglCreateWindowSurface.

Change-Id: I4af86d442375017ae3b4744e7b3bdebf3b496b6e
Reviewed-by: Andy Nichols <andy.nichols@nokia.com>
12 files changed:
src/plugins/platforms/kms/kms.pro
src/plugins/platforms/kms/qkmsbuffermanager.cpp [deleted file]
src/plugins/platforms/kms/qkmsbuffermanager.h [deleted file]
src/plugins/platforms/kms/qkmscontext.cpp
src/plugins/platforms/kms/qkmscontext.h
src/plugins/platforms/kms/qkmsdevice.cpp
src/plugins/platforms/kms/qkmsdevice.h
src/plugins/platforms/kms/qkmsintegration.cpp
src/plugins/platforms/kms/qkmsnativeinterface.cpp
src/plugins/platforms/kms/qkmsscreen.cpp
src/plugins/platforms/kms/qkmsscreen.h
src/plugins/platforms/kms/qkmswindow.cpp

index f97973b..4a50569 100644 (file)
@@ -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 (file)
index 05da957..0000000
+++ /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 (file)
index 8f7970f..0000000
+++ /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 <QObject>
-#include <QList>
-
-#define EGL_EGLEXT_PROTOTYPES 1
-#define GL_GLEXT_PROTOTYPES 1
-
-extern "C" {
-#include <gbm.h>
-#include <xf86drmMode.h>
-#include <xf86drm.h>
-}
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-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<QKmsFramebuffer*> m_framebuffers;
-    GLuint m_frameBufferObject;
-    GLuint m_depthAndStencilBufferObject;
-
-    QKmsFramebuffer *m_renderTarget;
-    QKmsFramebuffer *m_displayCanidate;
-    QKmsFramebuffer *m_currentDisplay;
-
-};
-
-QT_END_NAMESPACE
-
-#endif // QKMSBUFFERMANAGER_H
index f2662e0..e5fd10a 100644 (file)
 #include "qkmscontext.h"
 #include "qkmswindow.h"
 
+#include <QOpenGLContext>
+
+#include <QtPlatformSupport/private/qeglconvenience_p.h>
 
 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<QPlatformWindow *>(surface);
+    QKmsScreen *screen = static_cast<QKmsScreen *> (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<QPlatformWindow *>(surface);
-    QKmsScreen *screen = static_cast<QKmsScreen *> (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<QPlatformWindow *>(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<QPlatformWindow *>(surface);
-    QKmsScreen *screen = static_cast<QKmsScreen *> (QPlatformScreen::platformScreenForWindow(window->window()));
-    return screen->framebufferObject();
+    return m_format;
 }
 
 QT_END_NAMESPACE
index 32223ad..4318202 100644 (file)
@@ -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;
 };
index 43f2101..1937b26 100644 (file)
@@ -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<QKmsScreen *>(data);
-
-    if (previousTime == 0)
-        refreshTime = 16000;
-    else
-        refreshTime = currentTime - previousTime;
-
-    screen->setFlipReady(refreshTime);
+    screen->handlePageFlipped();
 }
 
 QT_END_NAMESPACE
index 638fe78..8797b82 100644 (file)
@@ -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,
index 91e8ae4..8b3ef91 100644 (file)
@@ -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<QKmsScreen *>(context->screen()->handle());
-    return new QKmsContext(screen->device());
+    return new QKmsContext(context, screen->device());
 }
 
 QPlatformWindow *QKmsIntegration::createPlatformWindow(QWindow *window) const
index 8e026b2..b24e9d7 100644 (file)
@@ -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)
index 76b9bce..790c231 100644 (file)
 **
 ****************************************************************************/
 //#include <QDebug>
-#include "qkmscursor.h"
+
 #include "qkmsscreen.h"
+#include "qkmscursor.h"
 #include "qkmsdevice.h"
 #include "qkmscontext.h"
-#include "qkmsbuffermanager.h"
+
+#include <QtPlatformSupport/private/qeglconvenience_p.h>
+
+#include <QCoreApplication>
+#include <QtDebug>
 
 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();
     }
-
 }
 
 
index e8e6bda..57c96fb 100644 (file)
 #ifndef QKMSSCREEN_H
 #define QKMSSCREEN_H
 
+#include <stddef.h>
+
+#define EGL_EGLEXT_PROTOTYPES 1
+#define GL_GLEXT_PROTOTYPES 1
+
+extern "C" {
+#include <gbm.h>
+#include <xf86drmMode.h>
+#include <xf86drm.h>
+}
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
 #include <qpa/qplatformscreen.h>
-#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
index edbd35d..ebf327c 100644 (file)
@@ -49,6 +49,8 @@ QKmsWindow::QKmsWindow(QWindow *window)
     : QPlatformWindow(window)
 {
     m_screen = QPlatformScreen::platformScreenForWindow(window);
+
+    static_cast<QKmsScreen *>(m_screen)->initializeWithFormat(window->requestedFormat());
 }
 
 void QKmsWindow::setGeometry(const QRect &rect)