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>bb10
parent
44f7df439f
commit
ef204659b9
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
if (!ok)
|
||||
qWarning("QKmsContext::makeCurrent(): eglError: %d, this: %p",
|
||||
eglGetError(), this);
|
||||
|
||||
QPlatformWindow *window = static_cast<QPlatformWindow *>(surface);
|
||||
QKmsScreen *screen = static_cast<QKmsScreen *> (QPlatformScreen::platformScreenForWindow(window->window()));
|
||||
screen->bindFramebuffer();
|
||||
|
||||
EGLSurface eglSurface = screen->eglSurface();
|
||||
|
||||
screen->waitForPageFlipComplete();
|
||||
|
||||
bool ok = eglMakeCurrent(display, eglSurface, eglSurface, m_eglContext);
|
||||
if (!ok)
|
||||
qWarning("QKmsContext::makeCurrent(): eglError: %x, this: %p",
|
||||
eglGetError(), this);
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
eglSwapBuffers(m_device->eglDisplay(), m_eglWindowSurface);
|
||||
|
||||
if ( m_flipReady )
|
||||
performPageFlip();
|
||||
//TODO: Do something with return value here
|
||||
m_bufferManager.nextBuffer();
|
||||
//qDebug() << "swapBuffers now rendering to " << m_bufferManager.renderTargetBuffer();
|
||||
bindFramebuffer();
|
||||
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 = m_refreshTime;
|
||||
FD_ZERO(&fdSet);
|
||||
FD_SET(m_device->fd(), &fdSet);
|
||||
timeValue.tv_sec = 0;
|
||||
timeValue.tv_usec = 1000;
|
||||
|
||||
returnValue = select(1, &fdSet, 0, 0, &timeValue);
|
||||
returnValue = select(1, &fdSet, 0, 0, &timeValue);
|
||||
printf("select returns %d\n", returnValue);
|
||||
#endif
|
||||
|
||||
if (returnValue) {
|
||||
m_device->handlePageFlipCompleted();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue