kms: Support QOpenGLWidget and QQuickWidget

Also fixes the handling of shareContext() for contexts and format() for windows
and makes QOffscreenSurface working.

Change-Id: I3c3374a9de14a5b8428de3e11d9d7e1285c5b9c7
Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
Reviewed-by: Paul Olav Tvete <paul.tvete@digia.com>
This commit is contained in:
Laszlo Agocs 2014-09-26 14:07:31 +02:00
parent 3a2fdc48ad
commit 684990d148
9 changed files with 98 additions and 16 deletions

View File

@ -49,7 +49,6 @@ QKmsBackingStore::QKmsBackingStore(QWindow *window)
m_context->setFormat(window->requestedFormat());
m_context->setScreen(window->screen());
m_context->create();
window->setSurfaceType(QSurface::OpenGLSurface);
}
QKmsBackingStore::~QKmsBackingStore()

View File

@ -56,6 +56,8 @@ public:
void flush(QWindow *window, const QRegion &region, const QPoint &offset);
void resize(const QSize &size, const QRegion &staticContents);
QImage toImage() const Q_DECL_OVERRIDE { return m_image; }
private:
QOpenGLContext *m_context;
QImage m_image;

View File

@ -35,19 +35,18 @@
#include "qkmsdevice.h"
#include "qkmscontext.h"
#include "qkmswindow.h"
#include "qkmsintegration.h"
#include <QOpenGLContext>
#include <QtGui/QOpenGLContext>
#include <QtPlatformSupport/private/qeglconvenience_p.h>
QT_BEGIN_NAMESPACE
QKmsContext::QKmsContext(QOpenGLContext *context, QKmsDevice *device)
: QPlatformOpenGLContext()
, m_device(device)
: m_device(device)
{
EGLDisplay display = m_device->eglDisplay();
EGLConfig config = q_configFromGLFormat(display, QKmsScreen::tweakFormat(context->format()), true);
EGLConfig config = q_configFromGLFormat(display, QKmsScreen::tweakFormat(context->format()));
m_format = q_glFormatFromConfig(display, config);
//Initialize EGLContext
@ -57,7 +56,12 @@ QKmsContext::QKmsContext(QOpenGLContext *context, QKmsDevice *device)
};
eglBindAPI(EGL_OPENGL_ES_API);
m_eglContext = eglCreateContext(display, config, 0, contextAttribs);
EGLContext share = EGL_NO_CONTEXT;
if (context->shareContext())
share = static_cast<QKmsContext *>(context->shareContext()->handle())->eglContext();
m_eglContext = eglCreateContext(display, config, share, contextAttribs);
if (m_eglContext == EGL_NO_CONTEXT) {
qWarning("QKmsContext::QKmsContext(): eglError: %x, this: %p",
eglGetError(), this);
@ -72,16 +76,19 @@ bool QKmsContext::isValid() const
bool QKmsContext::makeCurrent(QPlatformSurface *surface)
{
Q_ASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface);
Q_ASSERT(surface->surface()->supportsOpenGL());
EGLDisplay display = m_device->eglDisplay();
EGLSurface eglSurface;
QPlatformWindow *window = static_cast<QPlatformWindow *>(surface);
QKmsScreen *screen = static_cast<QKmsScreen *> (QPlatformScreen::platformScreenForWindow(window->window()));
EGLSurface eglSurface = screen->eglSurface();
screen->waitForPageFlipComplete();
if (surface->surface()->surfaceClass() == QSurface::Window) {
QPlatformWindow *window = static_cast<QPlatformWindow *>(surface);
QKmsScreen *screen = static_cast<QKmsScreen *>(QPlatformScreen::platformScreenForWindow(window->window()));
eglSurface = screen->eglSurface();
screen->waitForPageFlipComplete();
} else {
eglSurface = static_cast<QKmsOffscreenWindow *>(surface)->surface();
}
bool ok = eglMakeCurrent(display, eglSurface, eglSurface, m_eglContext);
if (!ok)

View File

@ -48,10 +48,13 @@
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
#include <QtPlatformSupport/private/qfbvthandler_p.h>
#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/QOpenGLContext>
#include <QtGui/QScreen>
#include <QtGui/QOffscreenSurface>
#include <qpa/qplatformoffscreensurface.h>
QT_BEGIN_NAMESPACE
@ -116,6 +119,7 @@ bool QKmsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
case ThreadedPixmaps: return true;
case OpenGL: return true;
case ThreadedOpenGL: return false;
case RasterGLSurface: return true;
default: return QPlatformIntegration::hasCapability(cap);
}
}
@ -138,6 +142,44 @@ QPlatformBackingStore *QKmsIntegration::createPlatformBackingStore(QWindow *wind
return new QKmsBackingStore(window);
}
// Neither a pbuffer nor a hidden QWindow is suitable. Just use an additional, small gbm surface.
QKmsOffscreenWindow::QKmsOffscreenWindow(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface)
: QPlatformOffscreenSurface(offscreenSurface)
, m_format(format)
, m_display(display)
, m_surface(EGL_NO_SURFACE)
, m_window(0)
{
QKmsScreen *screen = static_cast<QKmsScreen *>(offscreenSurface->screen()->handle());
m_window = gbm_surface_create(screen->device()->gbmDevice(),
10, 10,
GBM_FORMAT_XRGB8888,
GBM_BO_USE_RENDERING);
if (!m_window) {
qWarning("QKmsOffscreenWindow: Failed to create native window");
return;
}
EGLConfig config = q_configFromGLFormat(m_display, m_format);
m_surface = eglCreateWindowSurface(m_display, config, m_window, 0);
if (m_surface != EGL_NO_SURFACE)
m_format = q_glFormatFromConfig(m_display, config);
}
QKmsOffscreenWindow::~QKmsOffscreenWindow()
{
if (m_surface != EGL_NO_SURFACE)
eglDestroySurface(m_display, m_surface);
if (m_window)
gbm_surface_destroy((gbm_surface *) m_window);
}
QPlatformOffscreenSurface *QKmsIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
{
QKmsScreen *screen = static_cast<QKmsScreen *>(surface->screen()->handle());
return new QKmsOffscreenWindow(screen->device()->eglDisplay(), QKmsScreen::tweakFormat(surface->format()), surface);
}
QPlatformFontDatabase *QKmsIntegration::fontDatabase() const
{
return m_fontDatabase;

View File

@ -36,7 +36,9 @@
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformnativeinterface.h>
#include <qpa/qplatformoffscreensurface.h>
#include <QtPlatformSupport/private/qdevicediscovery_p.h>
#include <EGL/egl.h>
QT_BEGIN_NAMESPACE
@ -44,6 +46,24 @@ class QKmsScreen;
class QKmsDevice;
class QFbVtHandler;
class QKmsOffscreenWindow : public QPlatformOffscreenSurface
{
public:
QKmsOffscreenWindow(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface);
~QKmsOffscreenWindow();
QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; }
bool isValid() const Q_DECL_OVERRIDE { return m_surface != EGL_NO_SURFACE; }
EGLSurface surface() const { return m_surface; }
private:
QSurfaceFormat m_format;
EGLDisplay m_display;
EGLSurface m_surface;
EGLNativeWindowType m_window;
};
class QKmsIntegration : public QObject, public QPlatformIntegration
{
Q_OBJECT
@ -58,6 +78,7 @@ public:
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE;
QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;

View File

@ -170,10 +170,11 @@ QSurfaceFormat QKmsScreen::tweakFormat(const QSurfaceFormat &format)
void QKmsScreen::initializeWithFormat(const QSurfaceFormat &format)
{
EGLDisplay display = m_device->eglDisplay();
EGLConfig config = q_configFromGLFormat(display, tweakFormat(format), true);
EGLConfig config = q_configFromGLFormat(display, tweakFormat(format));
m_eglWindowSurface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)m_gbmSurface, NULL);
qCDebug(lcQpaScreen) << "created window surface";
m_surfaceFormat = q_glFormatFromConfig(display, config);
}
void QKmsScreen::swapBuffers()

View File

@ -48,6 +48,7 @@ extern "C" {
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <QtGui/qopengl.h>
#include <QtGui/qsurfaceformat.h>
#include <QtCore/qloggingcategory.h>
#include <qpa/qplatformscreen.h>
@ -87,6 +88,8 @@ public:
static QSurfaceFormat tweakFormat(const QSurfaceFormat &format);
QSurfaceFormat surfaceFormat() const { return m_surfaceFormat; }
private:
void performPageFlip();
void initializeScreenMode(const drmModeRes *resources, const drmModeConnector *connector);
@ -111,6 +114,7 @@ private:
EGLSurface m_eglWindowSurface;
bool m_modeSet;
QSurfaceFormat m_surfaceFormat;
};
QT_END_NAMESPACE

View File

@ -58,4 +58,9 @@ void QKmsWindow::setGeometry(const QRect &rect)
QPlatformWindow::setGeometry(fullscreenRect);
}
QSurfaceFormat QKmsWindow::format() const
{
return static_cast<QKmsScreen *>(m_screen)->surfaceFormat();
}
QT_END_NAMESPACE

View File

@ -45,7 +45,8 @@ class QKmsWindow : public QPlatformWindow
public:
QKmsWindow(QWindow *window);
void setGeometry(const QRect &rect);
void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
QSurfaceFormat format() const Q_DECL_OVERRIDE;
private:
QPlatformScreen *m_screen;