Initial support for Qt using Kernel Mode-setting (KMS)
authorAndy Nichols <andy.nichols@nokia.com>
Tue, 2 Aug 2011 13:07:50 +0000 (15:07 +0200)
committerJørgen Lind <jorgen.lind@nokia.com>
Thu, 4 Aug 2011 07:01:03 +0000 (09:01 +0200)
This platform plugin supports fullscreen OpenGLES2 windows on devices
that support Kernel Mode-setting.

Change-Id: I7d4077319654c13851f0ff7ec0228b7b13936382
Reviewed-on: http://codereview.qt.nokia.com/2516
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Jørgen Lind <jorgen.lind@nokia.com>
18 files changed:
src/plugins/platforms/kms/kms.pro [new file with mode: 0644]
src/plugins/platforms/kms/main.cpp [new file with mode: 0644]
src/plugins/platforms/kms/qkmsbackingstore.cpp [new file with mode: 0644]
src/plugins/platforms/kms/qkmsbackingstore.h [new file with mode: 0644]
src/plugins/platforms/kms/qkmsbuffermanager.cpp [new file with mode: 0644]
src/plugins/platforms/kms/qkmsbuffermanager.h [new file with mode: 0644]
src/plugins/platforms/kms/qkmscontext.cpp [new file with mode: 0644]
src/plugins/platforms/kms/qkmscontext.h [new file with mode: 0644]
src/plugins/platforms/kms/qkmscursor.cpp [new file with mode: 0644]
src/plugins/platforms/kms/qkmscursor.h [new file with mode: 0644]
src/plugins/platforms/kms/qkmsdevice.cpp [new file with mode: 0644]
src/plugins/platforms/kms/qkmsdevice.h [new file with mode: 0644]
src/plugins/platforms/kms/qkmsintegration.cpp [new file with mode: 0644]
src/plugins/platforms/kms/qkmsintegration.h [new file with mode: 0644]
src/plugins/platforms/kms/qkmsscreen.cpp [new file with mode: 0644]
src/plugins/platforms/kms/qkmsscreen.h [new file with mode: 0644]
src/plugins/platforms/kms/qkmswindow.cpp [new file with mode: 0644]
src/plugins/platforms/kms/qkmswindow.h [new file with mode: 0644]

diff --git a/src/plugins/platforms/kms/kms.pro b/src/plugins/platforms/kms/kms.pro
new file mode 100644 (file)
index 0000000..73a3fa0
--- /dev/null
@@ -0,0 +1,42 @@
+TARGET = qkms
+
+load(qt_plugin)
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms
+
+QT = core-private gui-private platformsupport-private opengl-private
+
+CONFIG += link_pkgconfig qpa/genericunixfontdatabase
+
+PKGCONFIG += libdrm egl gbm glesv2
+
+SOURCES =   main.cpp \
+            qkmsintegration.cpp \
+            qkmsscreen.cpp \
+            qkmscontext.cpp \
+            qkmswindow.cpp \
+            qkmscursor.cpp \
+            qkmsdevice.cpp \
+            qkmsbuffermanager.cpp \
+            qkmsbackingstore.cpp
+HEADERS =   qkmsintegration.h \
+            qkmsscreen.h \
+            qkmscontext.h \
+            qkmswindow.h \
+            qkmscursor.h \
+            qkmsdevice.h \
+            qkmsbuffermanager.h \
+            qkmsbackingstore.h
+
+target.path += $$[QT_INSTALL_PLUGINS]/platforms
+INSTALLS += target
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/plugins/platforms/kms/main.cpp b/src/plugins/platforms/kms/main.cpp
new file mode 100644 (file)
index 0000000..a07f164
--- /dev/null
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QtGui/QPlatformIntegrationPlugin>
+#include "qkmsintegration.h"
+
+QT_BEGIN_NAMESPACE
+
+class QKmsIntegrationPlugin : public QPlatformIntegrationPlugin
+{
+public:
+    QStringList keys() const;
+    QPlatformIntegration *create(const QString&, const QStringList&);
+};
+
+QStringList QKmsIntegrationPlugin::keys() const
+{
+    QStringList list;
+    list << "kms";
+    return list;
+}
+
+QPlatformIntegration *QKmsIntegrationPlugin::create(const QString& system, const QStringList& paramList)
+{
+    Q_UNUSED(paramList);
+    if (system.toLower() == "kms")
+        return new QKmsIntegration;
+
+    return 0;
+}
+
+Q_EXPORT_PLUGIN2(kms, QKmsIntegrationPlugin)
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmsbackingstore.cpp b/src/plugins/platforms/kms/qkmsbackingstore.cpp
new file mode 100644 (file)
index 0000000..eb682e8
--- /dev/null
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qkmsbackingstore.h"
+
+QT_BEGIN_NAMESPACE
+
+QKmsBackingStore::QKmsBackingStore(QWindow *window)
+    : QPlatformBackingStore(window)
+{
+}
+
+QPaintDevice *QKmsBackingStore::paintDevice()
+{
+    return &m_image;
+}
+
+void QKmsBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
+{
+    //'window' can be a child window, in which case 'region' is in child window coordinates and
+    // offset is the (child) window's offset in relation to the window surface.
+
+    Q_UNUSED(region)
+    Q_UNUSED(offset)
+    Q_UNUSED(window)
+}
+
+void QKmsBackingStore::resize(const QSize &size, const QRegion &staticContents)
+{
+    Q_UNUSED(staticContents)
+    m_image = QImage(size, QImage::Format_RGB32);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmsbackingstore.h b/src/plugins/platforms/kms/qkmsbackingstore.h
new file mode 100644 (file)
index 0000000..e270d04
--- /dev/null
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QBACKINGSTORE_KMS_H
+#define QBACKINGSTORE_KMS_H
+
+#include <QtGui/QPlatformBackingStore>
+#include <QImage>
+
+QT_BEGIN_NAMESPACE
+
+class QKmsBackingStore : public QPlatformBackingStore
+{
+public:
+    QKmsBackingStore(QWindow *window);
+
+    QPaintDevice *paintDevice();
+    void flush(QWindow *window, const QRegion &region, const QPoint &offset);
+    void resize(const QSize &size, const QRegion &staticContents);
+
+private:
+    QImage m_image;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/kms/qkmsbuffermanager.cpp b/src/plugins/platforms/kms/qkmsbuffermanager.cpp
new file mode 100644 (file)
index 0000000..0c2eec0
--- /dev/null
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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());
+}
+
+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
new file mode 100644 (file)
index 0000000..59db7eb
--- /dev/null
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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
diff --git a/src/plugins/platforms/kms/qkmscontext.cpp b/src/plugins/platforms/kms/qkmscontext.cpp
new file mode 100644 (file)
index 0000000..835b6e8
--- /dev/null
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qkmsscreen.h"
+#include "qkmsdevice.h"
+#include "qkmscontext.h"
+#include "qkmswindow.h"
+
+
+QT_BEGIN_NAMESPACE
+
+QKmsContext::QKmsContext(QKmsDevice *device)
+    : QPlatformGLContext(),
+      m_device(device)
+{
+}
+
+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);
+    if (!ok)
+        qWarning("QKmsContext::makeCurrent(): eglError: %d, this: %p",
+                 eglGetError(), this);
+
+    QPlatformWindow *window = static_cast<QPlatformWindow *>(surface);
+    QKmsScreen *screen = static_cast<QKmsScreen *> (QPlatformScreen::platformScreenForWindow(window->window()));
+    screen->bindFramebuffer();
+    return true;
+}
+
+void QKmsContext::doneCurrent()
+{
+    QPlatformGLContext::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",
+                 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);
+    QKmsScreen *screen = static_cast<QKmsScreen *> (QPlatformScreen::platformScreenForWindow(window->window()));
+    screen->swapBuffers();
+}
+
+void (*QKmsContext::getProcAddress(const QByteArray &procName)) ()
+{
+    return eglGetProcAddress(procName.data());
+}
+
+
+EGLContext QKmsContext::eglContext() const
+{
+    return m_device->eglContext();
+}
+
+QSurfaceFormat QKmsContext::format() const
+{
+    return QSurfaceFormat();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmscontext.h b/src/plugins/platforms/kms/qkmscontext.h
new file mode 100644 (file)
index 0000000..25398c5
--- /dev/null
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QKMSCONTEXT_H
+#define QKMSCONTEXT_H
+
+#include <QtGui/QPlatformGLContext>
+
+#define EGL_EGLEXT_PROTOTYPES 1
+#include <EGL/egl.h>
+
+QT_BEGIN_NAMESPACE
+
+class QKmsDevice;
+
+class QKmsContext : public QPlatformGLContext
+{
+public:
+    QKmsContext(QKmsDevice *device);
+
+    bool makeCurrent(QPlatformSurface *surface);
+    void doneCurrent();
+    void swapBuffers(QPlatformSurface *surface);
+    void (*getProcAddress(const QByteArray &procName)) ();
+
+    QSurfaceFormat format() const;
+
+    EGLContext eglContext() const;
+
+private:
+
+    QKmsDevice *m_device;
+};
+
+QT_END_NAMESPACE
+
+#endif // QKMSCONTEXT_H
diff --git a/src/plugins/platforms/kms/qkmscursor.cpp b/src/plugins/platforms/kms/qkmscursor.cpp
new file mode 100644 (file)
index 0000000..91c23b0
--- /dev/null
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QDebug>
+#include "qkmscursor.h"
+#include "qkmsscreen.h"
+#include "qkmsdevice.h"
+
+QT_BEGIN_NAMESPACE
+
+QKmsCursor::QKmsCursor(QKmsScreen *screen)
+    : QPlatformCursor(screen), m_screen(screen),
+      m_graphicsBufferManager(screen->device()->gbmDevice())
+{
+    gbm_bo *bo = gbm_bo_create(m_graphicsBufferManager, 64, 64,
+                               GBM_BO_FORMAT_ARGB8888,
+                               GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_RENDERING);
+
+    m_eglImage = eglCreateImageKHR(m_screen->device()->eglDisplay(), 0, EGL_NATIVE_PIXMAP_KHR,
+                                   bo, 0);
+    gbm_bo_destroy(bo);
+    m_cursorImage = new QPlatformCursorImage(0, 0, 0, 0, 0, 0);
+}
+
+void QKmsCursor::pointerEvent(const QMouseEvent &event)
+{
+    int status = drmModeMoveCursor(m_screen->device()->fd(),
+                                   m_screen->crtcId(),
+                                   event.globalX(),
+                                   event.globalY());
+    if (status) {
+        qWarning("failed to move cursor: %d", status);
+    }
+}
+
+void QKmsCursor::changeCursor(QCursor *widgetCursor, QWindow *window)
+{
+    Q_UNUSED(window)
+
+    if (widgetCursor->shape() != Qt::BitmapCursor) {
+        m_cursorImage->set(widgetCursor->shape());
+    } else {
+        m_cursorImage->set(widgetCursor->pixmap().toImage(),
+                           widgetCursor->hotSpot().x(),
+                           widgetCursor->hotSpot().y());
+    }
+
+    if ((m_cursorImage->image()->width() > 64) || (m_cursorImage->image()->width() > 64)) {
+        qWarning("failed to set hardware cursor: larger than 64x64.");
+        return;
+    }
+
+    QImage cursorImage = m_cursorImage->image()->convertToFormat(QImage::Format_RGB32);
+
+    //Load cursor image into EGLImage
+    GLuint cursorTexture;
+    glGenTextures(1, &cursorTexture);
+    glBindTexture(GL_TEXTURE_2D, cursorTexture);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+
+    //TODO: Format may be wrong here, need a color icon to test.
+    if (m_eglImage != EGL_NO_IMAGE_KHR) {
+        glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
+        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, cursorImage.width(),
+                        cursorImage.height(), GL_RGBA,
+                        GL_UNSIGNED_BYTE, cursorImage.constBits());
+    } else {
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cursorImage.width(),
+                     cursorImage.height(), 0, GL_RGBA,
+                     GL_UNSIGNED_BYTE, cursorImage.constBits());
+    }
+
+    //EGLImage needs to contain sprite before calling this:
+    gbm_bo *bufferObject = gbm_bo_create_from_egl_image(m_graphicsBufferManager,
+                                                        m_screen->device()->eglDisplay(),
+                                                        m_eglImage, 64, 64,
+                                                        GBM_BO_USE_CURSOR_64X64);
+    quint32 handle = gbm_bo_get_handle(bufferObject).u32;
+
+    gbm_bo_destroy(bufferObject);
+
+    int status = drmModeSetCursor(m_screen->device()->fd(),
+                                  m_screen->crtcId(), handle, 64, 64);
+
+    if (status) {
+        qWarning("failed to set cursor: %d", status);
+    }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmscursor.h b/src/plugins/platforms/kms/qkmscursor.h
new file mode 100644 (file)
index 0000000..96be88e
--- /dev/null
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QKMSCURSOR_H
+#define QKMSCURSOR_H
+
+#include <QtGui/QPlatformCursor>
+
+#define EGL_EGLEXT_PROTOTYPES 1
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+QT_BEGIN_NAMESPACE
+
+class QKmsScreen;
+class gbm_device;
+
+class QKmsCursor : public QPlatformCursor
+{
+public:
+    QKmsCursor(QKmsScreen *screen);
+
+    void pointerEvent(const QMouseEvent &event);
+    void changeCursor(QCursor *widgetCursor, QWindow *window);
+
+private:
+    QKmsScreen *m_screen;
+    gbm_device *m_graphicsBufferManager;
+    EGLImageKHR m_eglImage;
+    QPlatformCursorImage *m_cursorImage;
+};
+
+QT_END_NAMESPACE
+
+#endif // QKMSCURSOR_H
diff --git a/src/plugins/platforms/kms/qkmsdevice.cpp b/src/plugins/platforms/kms/qkmsdevice.cpp
new file mode 100644 (file)
index 0000000..e0fac56
--- /dev/null
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QDebug>
+#include "qkmsscreen.h"
+#include "qkmsdevice.h"
+
+#include "qkmsintegration.h"
+
+#include <QtCore/QSocketNotifier>
+#include <QtCore/private/qcore_unix_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QKmsDevice::QKmsDevice(const QString &path, QKmsIntegration *parent) :
+    QObject(0), m_integration(parent)
+{
+    m_fd = QT_OPEN(path.toAscii().constData(), O_RDWR);
+    if (m_fd < 0) {
+        qWarning("Could not open %s.", path.toAscii().constData());
+        qFatal("No DRM display device");
+    }
+
+    m_graphicsBufferManager = gbm_create_device(m_fd);
+    m_eglDisplay = eglGetDisplay(m_graphicsBufferManager);
+
+    if (m_eglDisplay == EGL_NO_DISPLAY) {
+        qWarning("Could not open EGL display");
+        qFatal("EGL error");
+    }
+
+    EGLint major;
+    EGLint minor;
+    if (!eglInitialize(m_eglDisplay, &major, &minor)) {
+        qWarning("Could not initialize EGL display");
+        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()));
+}
+
+QKmsDevice::~QKmsDevice()
+{
+    if (m_eglContext != EGL_NO_CONTEXT) {
+        eglDestroyContext(m_eglDisplay, m_eglContext);
+        m_eglContext = EGL_NO_CONTEXT;
+    }
+}
+
+void QKmsDevice::createScreens()
+{
+    drmModeRes *resources = 0;
+    resources = drmModeGetResources(m_fd);
+    if (!resources)
+        qFatal("drmModeGetResources failed");
+
+    //Iterate connectors and create screens on each one active
+    for (int i = 0; i < resources->count_connectors; i++) {
+        drmModeConnector *connector = 0;
+        connector = drmModeGetConnector(m_fd, resources->connectors[i]);
+        if (connector && connector->connection == DRM_MODE_CONNECTED) {
+            m_integration->addScreen(new QKmsScreen(this, connector->connector_id));
+        }
+        drmModeFreeConnector(connector);
+    }
+    drmModeFreeResources(resources);
+}
+
+void QKmsDevice::handlePageFlipCompleted()
+{
+    //qDebug() << "Display signal recieved";
+    drmEventContext eventContext;
+
+    memset(&eventContext, 0, sizeof eventContext);
+    eventContext.version = DRM_EVENT_CONTEXT_VERSION;
+    eventContext.page_flip_handler = QKmsDevice::pageFlipHandler;
+    drmHandleEvent(m_fd, &eventContext);
+
+}
+
+void QKmsDevice::pageFlipHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data)
+{
+    Q_UNUSED(fd)
+    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);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmsdevice.h b/src/plugins/platforms/kms/qkmsdevice.h
new file mode 100644 (file)
index 0000000..4868a72
--- /dev/null
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QKMSDEVICE_H
+#define QKMSDEVICE_H
+
+extern "C" {
+#include <gbm.h>
+}
+#include <EGL/egl.h>
+
+#include <QObject>
+
+QT_BEGIN_NAMESPACE
+
+class gbm_device;
+class QKmsIntegration;
+
+class QKmsDevice : public QObject
+{
+    Q_OBJECT
+public:
+    explicit QKmsDevice(const QString &path, QKmsIntegration *parent);
+    ~QKmsDevice();
+
+    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,
+                                unsigned int usec, void *data);
+
+public slots:
+    void handlePageFlipCompleted();
+private:
+    void createScreens();
+
+    QKmsIntegration *m_integration;
+
+    EGLDisplay m_eglDisplay;
+    EGLContext m_eglContext;
+    gbm_device *m_graphicsBufferManager;
+    int m_fd;
+};
+
+QT_END_NAMESPACE
+
+#endif // QKMSDEVICE_H
diff --git a/src/plugins/platforms/kms/qkmsintegration.cpp b/src/plugins/platforms/kms/qkmsintegration.cpp
new file mode 100644 (file)
index 0000000..18e305d
--- /dev/null
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qkmsintegration.h"
+#include "qkmsdevice.h"
+#include "qkmsscreen.h"
+#include "qkmswindow.h"
+#include "qkmsbackingstore.h"
+#include "qkmscontext.h"
+
+#include <QtPlatformSupport/private/qgenericunixprintersupport_p.h>
+#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
+#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/QGuiGLContext>
+#include <QtGui/QScreen>
+
+QT_BEGIN_NAMESPACE
+
+QKmsIntegration::QKmsIntegration()
+    : QPlatformIntegration(),
+      m_fontDatabase(new QGenericUnixFontDatabase()),
+      m_printerSupport(new QGenericUnixPrinterSupport()),
+      m_eventDispatcher(createUnixEventDispatcher())
+{
+    QGuiApplicationPrivate::instance()->setEventDispatcher(m_eventDispatcher);
+    setenv("EGL_PLATFORM", "drm",1);
+    QStringList drmDevices = findDrmDevices();
+    foreach (QString path, drmDevices) {
+        m_devices.append(new QKmsDevice(path, this));
+    }
+}
+
+QKmsIntegration::~QKmsIntegration()
+{
+    foreach (QKmsDevice *device, m_devices) {
+        delete device;
+    }
+    foreach (QPlatformScreen *screen, m_screens) {
+        delete screen;
+    }
+    delete m_printerSupport;
+    delete m_fontDatabase;
+}
+
+bool QKmsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
+{
+    switch (cap) {
+    case ThreadedPixmaps: return true;
+    case OpenGL: return true;
+    default: return QPlatformIntegration::hasCapability(cap);
+    }
+}
+
+QPlatformGLContext *QKmsIntegration::createPlatformGLContext(QGuiGLContext *context) const
+{
+    QKmsScreen *screen = static_cast<QKmsScreen *>(context->screen()->handle());
+    return new QKmsContext(screen->device());
+}
+
+QPlatformWindow *QKmsIntegration::createPlatformWindow(QWindow *window) const
+{
+    return new QKmsWindow(window);
+}
+
+QPlatformBackingStore *QKmsIntegration::createPlatformBackingStore(QWindow *window) const
+{
+    return new QKmsBackingStore(window);
+}
+
+QPlatformFontDatabase *QKmsIntegration::fontDatabase() const
+{
+    return m_fontDatabase;
+}
+
+QStringList QKmsIntegration::findDrmDevices()
+{
+    //Return a list addresses of DRM supported devices
+    //Hardcoded now, but could use udev to return a list
+    //of multiple devices.
+    return QStringList(QString::fromLatin1("/dev/dri/card0"));
+}
+
+void QKmsIntegration::addScreen(QKmsScreen *screen)
+{
+    m_screens.append(screen);
+    screenAdded(screen);
+}
+
+QAbstractEventDispatcher *QKmsIntegration::guiThreadEventDispatcher() const
+{
+    return m_eventDispatcher;
+}
+
+QPlatformPrinterSupport *QKmsIntegration::printerSupport() const
+{
+    return m_printerSupport;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmsintegration.h b/src/plugins/platforms/kms/qkmsintegration.h
new file mode 100644 (file)
index 0000000..bf84e1b
--- /dev/null
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QPLATFORMINTEGRATION_KMS_H
+#define QPLATFORMINTEGRATION_KMS_H
+
+#include <QtGui/QPlatformIntegration>
+
+QT_BEGIN_NAMESPACE
+
+class QKmsScreen;
+class QKmsDevice;
+
+class QKmsIntegration : public QPlatformIntegration
+{
+public:
+    QKmsIntegration();
+    ~QKmsIntegration();
+
+    bool hasCapability(QPlatformIntegration::Capability cap) const;
+
+    QPlatformGLContext *createPlatformGLContext(QGuiGLContext *context) const;
+    QPlatformWindow *createPlatformWindow(QWindow *window) const;
+    QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const;
+
+    QPlatformFontDatabase *fontDatabase() const;
+    QPlatformPrinterSupport *printerSupport() const;
+    QAbstractEventDispatcher *guiThreadEventDispatcher() const;
+
+    void addScreen(QKmsScreen *screen);
+
+private:
+    QStringList findDrmDevices();
+
+    QList<QPlatformScreen *> m_screens;
+    QList<QKmsDevice *> m_devices;
+    QPlatformFontDatabase *m_fontDatabase;
+    QPlatformPrinterSupport *m_printerSupport;
+    QAbstractEventDispatcher *m_eventDispatcher;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/kms/qkmsscreen.cpp b/src/plugins/platforms/kms/qkmsscreen.cpp
new file mode 100644 (file)
index 0000000..0cd1530
--- /dev/null
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QDebug>
+#include "qkmscursor.h"
+#include "qkmsscreen.h"
+#include "qkmsdevice.h"
+#include "qkmscontext.h"
+#include "qkmsbuffermanager.h"
+
+QT_BEGIN_NAMESPACE
+
+//Fallback mode (taken from Wayland DRM demo compositor)
+static drmModeModeInfo builtin_1024x768 = {
+    63500, //clock
+    1024, 1072, 1176, 1328, 0,
+    768, 771, 775, 798, 0,
+    59920,
+    DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC,
+    0,
+    "1024x768"
+};
+
+QKmsScreen::QKmsScreen(QKmsDevice *device, int connectorId)
+    : m_device(device),
+      m_flipReady(true),
+      m_connectorId(connectorId),
+      m_depth(32),
+      m_format(QImage::Format_Invalid),
+      m_bufferManager(this),
+      m_refreshTime(16000)
+{
+    m_cursor = new QKmsCursor(this);
+    initializeScreenMode();
+}
+
+QKmsScreen::~QKmsScreen()
+{
+    delete m_cursor;
+}
+
+QRect QKmsScreen::geometry() const
+{
+    return m_geometry;
+}
+
+int QKmsScreen::depth() const
+{
+    return m_depth;
+}
+
+QImage::Format QKmsScreen::format() const
+{
+    return m_format;
+}
+
+QSize QKmsScreen::physicalSize() const
+{
+    return m_physicalSize;
+}
+
+GLuint QKmsScreen::framebufferObject() const
+{
+    return m_bufferManager.framebufferObject();
+}
+
+void QKmsScreen::initializeScreenMode()
+{
+    //Determine optimal mode for screen
+    drmModeRes *resources = drmModeGetResources(m_device->fd());
+    if (!resources)
+        qFatal("drmModeGetResources failed");
+
+    drmModeConnector *connector = drmModeGetConnector(m_device->fd(), m_connectorId);
+    drmModeModeInfo *mode = 0;
+    if (connector->count_modes > 0)
+        mode = &connector->modes[0];
+    else
+        mode = &builtin_1024x768;
+
+    drmModeEncoder *encoder = drmModeGetEncoder(m_device->fd(), connector->encoders[0]);
+    if (encoder == 0)
+        qFatal("No encoder for connector.");
+
+    int i;
+    for (i = 0; i < resources->count_crtcs; i++) {
+        if (encoder->possible_crtcs & (1 << i))
+            break;
+    }
+    if (i == resources->count_crtcs)
+        qFatal("No usable crtc for encoder.");
+
+    m_crtcId = resources->crtcs[i];
+    m_mode = *mode;
+    m_geometry = QRect(0, 0, m_mode.hdisplay, m_mode.vdisplay);
+    m_depth = 32;
+    m_format = QImage::Format_RGB32;
+    m_physicalSize = QSize(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");
+
+    //Cleanup
+    drmModeFreeEncoder(encoder);
+    drmModeFreeConnector(connector);
+    drmModeFreeResources(resources);
+}
+
+void QKmsScreen::bindFramebuffer()
+{
+    if (m_bufferManager.framebufferObject()) {
+        glBindFramebuffer(GL_FRAMEBUFFER, m_bufferManager.framebufferObject());
+
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER,
+                                  GL_COLOR_ATTACHMENT0,
+                                  GL_RENDERBUFFER,
+                                  m_bufferManager.renderTargetBuffer());
+    }
+}
+
+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();
+}
+
+void QKmsScreen::performPageFlip()
+{
+    quint32 displayFramebufferId = m_bufferManager.displayFramebufferId();
+    //qDebug() << "Flipping to framebuffer: " << displayFramebufferId;
+
+    int pageFlipStatus = drmModePageFlip(m_device->fd(), m_crtcId,
+                                         displayFramebufferId,
+                                         DRM_MODE_PAGE_FLIP_EVENT, this);
+    if (pageFlipStatus)
+        qWarning("Pageflip status: %d", pageFlipStatus);
+
+    m_flipReady = false;
+}
+
+void QKmsScreen::setFlipReady(unsigned int time)
+{
+    m_flipReady = true;
+    m_refreshTime = time;
+    performPageFlip();
+}
+
+QKmsDevice * QKmsScreen::device() const
+{
+    return m_device;
+}
+
+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;
+
+    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();
+    }
+
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmsscreen.h b/src/plugins/platforms/kms/qkmsscreen.h
new file mode 100644 (file)
index 0000000..5c8b5ca
--- /dev/null
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QKMSSCREEN_H
+#define QKMSSCREEN_H
+
+#include <QtGui/QPlatformScreen>
+#include "qkmsbuffermanager.h"
+
+QT_BEGIN_NAMESPACE
+
+class QKmsCursor;
+class QKmsDevice;
+class QKmsContext;
+
+class QKmsScreen : public QPlatformScreen
+{
+public:
+    QKmsScreen(QKmsDevice *device, int connectorId);
+    ~QKmsScreen();
+
+    QRect geometry() const;
+    int depth() const;
+    QImage::Format format() const;
+    QSize physicalSize() const;
+
+    GLuint framebufferObject() const;
+    quint32 crtcId() const { return m_crtcId; }
+    QKmsDevice *device() const;
+
+    //Called by context for each screen
+    void bindFramebuffer();
+    void swapBuffers();
+    void setFlipReady(unsigned int time);
+
+private:
+    void performPageFlip();
+    void initializeScreenMode();
+    void waitForPageFlipComplete();
+
+    QKmsDevice *m_device;
+    bool m_flipReady;
+    quint32 m_connectorId;
+
+    quint32 m_crtcId;
+    drmModeModeInfo m_mode;
+    QRect m_geometry;
+    QSize m_physicalSize;
+    int m_depth;
+    QImage::Format m_format;
+
+    QKmsCursor *m_cursor;
+    QKmsBufferManager m_bufferManager;
+    unsigned int m_refreshTime;
+};
+
+QT_END_NAMESPACE
+
+#endif // QKMSSCREEN_H
diff --git a/src/plugins/platforms/kms/qkmswindow.cpp b/src/plugins/platforms/kms/qkmswindow.cpp
new file mode 100644 (file)
index 0000000..63271c4
--- /dev/null
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qkmswindow.h"
+#include "qkmsscreen.h"
+
+#include <QtGui/QWindowSystemInterface>
+QT_BEGIN_NAMESPACE
+
+QKmsWindow::QKmsWindow(QWindow *window)
+    : QPlatformWindow(window)
+{
+    m_screen = QPlatformScreen::platformScreenForWindow(window);
+}
+
+void QKmsWindow::setGeometry(const QRect &rect)
+{
+    Q_UNUSED(rect)
+    //All Windows must be fullscreen
+    QRect fullscreenRect = m_screen->availableGeometry();
+    QWindowSystemInterface::handleGeometryChange(window(), fullscreenRect);
+
+    QPlatformWindow::setGeometry(fullscreenRect);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmswindow.h b/src/plugins/platforms/kms/qkmswindow.h
new file mode 100644 (file)
index 0000000..789d42e
--- /dev/null
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QKMSWINDOW_H
+#define QKMSWINDOW_H
+
+#include <QtGui/QPlatformWindow>
+
+QT_BEGIN_NAMESPACE
+
+class QKmsWindow : public QPlatformWindow
+{
+public:
+    QKmsWindow(QWindow *window);
+
+    void setGeometry(const QRect &rect);
+
+private:
+    QPlatformScreen *m_screen;
+};
+
+QT_END_NAMESPACE
+
+#endif // QKMSWINDOW_H