From 9a652ed802d5ec1114ba97ad86eca8d2f25c53d9 Mon Sep 17 00:00:00 2001 From: Andy Nichols Date: Tue, 2 Aug 2011 15:07:50 +0200 Subject: Initial support for Qt using Kernel Mode-setting (KMS) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Jørgen Lind --- src/plugins/platforms/kms/kms.pro | 42 +++++ src/plugins/platforms/kms/main.cpp | 72 ++++++++ src/plugins/platforms/kms/qkmsbackingstore.cpp | 72 ++++++++ src/plugins/platforms/kms/qkmsbackingstore.h | 65 +++++++ src/plugins/platforms/kms/qkmsbuffermanager.cpp | 198 +++++++++++++++++++++ src/plugins/platforms/kms/qkmsbuffermanager.h | 105 +++++++++++ src/plugins/platforms/kms/qkmscontext.cpp | 113 ++++++++++++ src/plugins/platforms/kms/qkmscontext.h | 75 ++++++++ src/plugins/platforms/kms/qkmscursor.cpp | 131 ++++++++++++++ src/plugins/platforms/kms/qkmscursor.h | 74 ++++++++ src/plugins/platforms/kms/qkmsdevice.cpp | 163 +++++++++++++++++ src/plugins/platforms/kms/qkmsdevice.h | 87 +++++++++ src/plugins/platforms/kms/qkmsintegration.cpp | 138 +++++++++++++++ src/plugins/platforms/kms/qkmsintegration.h | 82 +++++++++ src/plugins/platforms/kms/qkmsscreen.cpp | 224 ++++++++++++++++++++++++ src/plugins/platforms/kms/qkmsscreen.h | 97 ++++++++++ src/plugins/platforms/kms/qkmswindow.cpp | 64 +++++++ src/plugins/platforms/kms/qkmswindow.h | 62 +++++++ 18 files changed, 1864 insertions(+) create mode 100644 src/plugins/platforms/kms/kms.pro create mode 100644 src/plugins/platforms/kms/main.cpp create mode 100644 src/plugins/platforms/kms/qkmsbackingstore.cpp create mode 100644 src/plugins/platforms/kms/qkmsbackingstore.h create mode 100644 src/plugins/platforms/kms/qkmsbuffermanager.cpp create mode 100644 src/plugins/platforms/kms/qkmsbuffermanager.h create mode 100644 src/plugins/platforms/kms/qkmscontext.cpp create mode 100644 src/plugins/platforms/kms/qkmscontext.h create mode 100644 src/plugins/platforms/kms/qkmscursor.cpp create mode 100644 src/plugins/platforms/kms/qkmscursor.h create mode 100644 src/plugins/platforms/kms/qkmsdevice.cpp create mode 100644 src/plugins/platforms/kms/qkmsdevice.h create mode 100644 src/plugins/platforms/kms/qkmsintegration.cpp create mode 100644 src/plugins/platforms/kms/qkmsintegration.h create mode 100644 src/plugins/platforms/kms/qkmsscreen.cpp create mode 100644 src/plugins/platforms/kms/qkmsscreen.h create mode 100644 src/plugins/platforms/kms/qkmswindow.cpp create mode 100644 src/plugins/platforms/kms/qkmswindow.h diff --git a/src/plugins/platforms/kms/kms.pro b/src/plugins/platforms/kms/kms.pro new file mode 100644 index 0000000000..73a3fa0418 --- /dev/null +++ b/src/plugins/platforms/kms/kms.pro @@ -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 index 0000000000..a07f1645dc --- /dev/null +++ b/src/plugins/platforms/kms/main.cpp @@ -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 +#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 index 0000000000..eb682e8ab3 --- /dev/null +++ b/src/plugins/platforms/kms/qkmsbackingstore.cpp @@ -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 ®ion, 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 index 0000000000..e270d04db0 --- /dev/null +++ b/src/plugins/platforms/kms/qkmsbackingstore.h @@ -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 +#include + +QT_BEGIN_NAMESPACE + +class QKmsBackingStore : public QPlatformBackingStore +{ +public: + QKmsBackingStore(QWindow *window); + + QPaintDevice *paintDevice(); + void flush(QWindow *window, const QRegion ®ion, 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 index 0000000000..0c2eec0f3b --- /dev/null +++ b/src/plugins/platforms/kms/qkmsbuffermanager.cpp @@ -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 index 0000000000..59db7ebeb1 --- /dev/null +++ b/src/plugins/platforms/kms/qkmsbuffermanager.h @@ -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 +#include + +#define EGL_EGLEXT_PROTOTYPES 1 +#define GL_GLEXT_PROTOTYPES 1 + +extern "C" { +#include +#include +#include +} + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QKmsScreen; + +class QKmsFramebuffer +{ +public: + QKmsFramebuffer() : available(true) {} + gbm_bo *graphicsBufferObject; + GLuint renderBuffer; + EGLImageKHR eglImage; + quint32 framebufferId; + bool available; +}; + + +class QKmsBufferManager +{ +public: + explicit QKmsBufferManager(QKmsScreen *screen); + ~QKmsBufferManager(); + void setupBuffersForMode(const drmModeModeInfo &mode, int numBuffers = 3); + GLuint framebufferObject() const { return m_frameBufferObject; } + quint32 displayFramebufferId(); + GLuint renderTargetBuffer(); + bool nextBuffer(); + +private: + void clearBuffers(); + + QKmsScreen *m_screen; + QList m_framebuffers; + GLuint m_frameBufferObject; + GLuint m_depthAndStencilBufferObject; + + QKmsFramebuffer *m_renderTarget; + QKmsFramebuffer *m_displayCanidate; + QKmsFramebuffer *m_currentDisplay; + +}; + +QT_END_NAMESPACE + +#endif // QKMSBUFFERMANAGER_H diff --git a/src/plugins/platforms/kms/qkmscontext.cpp b/src/plugins/platforms/kms/qkmscontext.cpp new file mode 100644 index 0000000000..835b6e8e7a --- /dev/null +++ b/src/plugins/platforms/kms/qkmscontext.cpp @@ -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(surface); + QKmsScreen *screen = static_cast (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(surface); + QKmsScreen *screen = static_cast (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 index 0000000000..25398c5530 --- /dev/null +++ b/src/plugins/platforms/kms/qkmscontext.h @@ -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 + +#define EGL_EGLEXT_PROTOTYPES 1 +#include + +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 index 0000000000..91c23b0f1c --- /dev/null +++ b/src/plugins/platforms/kms/qkmscursor.cpp @@ -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 +#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 index 0000000000..96be88e991 --- /dev/null +++ b/src/plugins/platforms/kms/qkmscursor.h @@ -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 + +#define EGL_EGLEXT_PROTOTYPES 1 + +#include +#include + +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 index 0000000000..e0fac5611d --- /dev/null +++ b/src/plugins/platforms/kms/qkmsdevice.cpp @@ -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 +#include "qkmsscreen.h" +#include "qkmsdevice.h" + +#include "qkmsintegration.h" + +#include +#include + +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(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 index 0000000000..4868a72ede --- /dev/null +++ b/src/plugins/platforms/kms/qkmsdevice.h @@ -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 +} +#include + +#include + +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 index 0000000000..18e305d633 --- /dev/null +++ b/src/plugins/platforms/kms/qkmsintegration.cpp @@ -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 +#include +#include +#include +#include +#include + +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(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 index 0000000000..bf84e1b33b --- /dev/null +++ b/src/plugins/platforms/kms/qkmsintegration.h @@ -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 + +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 m_screens; + QList 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 index 0000000000..0cd1530930 --- /dev/null +++ b/src/plugins/platforms/kms/qkmsscreen.cpp @@ -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 +#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 index 0000000000..5c8b5ca4f5 --- /dev/null +++ b/src/plugins/platforms/kms/qkmsscreen.h @@ -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 +#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 index 0000000000..63271c4ef5 --- /dev/null +++ b/src/plugins/platforms/kms/qkmswindow.cpp @@ -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 +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 index 0000000000..789d42e6f8 --- /dev/null +++ b/src/plugins/platforms/kms/qkmswindow.h @@ -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 + +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 -- cgit v1.2.3