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