summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorYoann Lopes <yoann.lopes@digia.com>2013-02-08 20:05:34 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-02-18 13:42:22 +0100
commitc7a51f1858a8cac5cdc458b575df1f0e064e3853 (patch)
tree341033260dcd90b4e87ab47b009c4f17da55f777 /src/plugins
parentf8fdeb68b6e1a710438fc9084a2a3b1b9b6744fa (diff)
Added QOffscreenSurface class.
Inherits QSurface and allows to use OpenGL from an arbitrary thread. Platform plugins can implement QPlatformOffscreenSurface, otherwise an invisible QWindow is used by QOffscreenSurface. This patch includes an implementation of QOffscreenSurface for XCB and EglFS platform plugins using pbuffers. Change-Id: I57b4fc1db417331f34826dcfa754b7698782fde4 Reviewed-by: Lars Knoll <lars.knoll@digia.com> Reviewed-by: Samuel Rødal <samuel.rodal@digia.com>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/eglfs/qeglfscontext.cpp18
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.cpp8
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.h1
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp60
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.h20
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp21
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h2
7 files changed, 118 insertions, 12 deletions
diff --git a/src/plugins/platforms/eglfs/qeglfscontext.cpp b/src/plugins/platforms/eglfs/qeglfscontext.cpp
index 1f0c373818..06db4e02db 100644
--- a/src/plugins/platforms/eglfs/qeglfscontext.cpp
+++ b/src/plugins/platforms/eglfs/qeglfscontext.cpp
@@ -45,6 +45,8 @@
#include "qeglfshooks.h"
#include "qeglfsintegration.h"
+#include <QtPlatformSupport/private/qeglpbuffer_p.h>
+#include <QtGui/QSurface>
#include <QtDebug>
QT_BEGIN_NAMESPACE
@@ -62,16 +64,20 @@ bool QEglFSContext::makeCurrent(QPlatformSurface *surface)
EGLSurface QEglFSContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
{
- QEglFSWindow *window = static_cast<QEglFSWindow *>(surface);
- return window->surface();
+ if (surface->surface()->surfaceClass() == QSurface::Window)
+ return static_cast<QEglFSWindow *>(surface)->surface();
+ else
+ return static_cast<QEGLPbuffer *>(surface)->pbuffer();
}
void QEglFSContext::swapBuffers(QPlatformSurface *surface)
{
- QEglFSWindow *window = static_cast<QEglFSWindow *>(surface);
- // draw the cursor
- if (QEglFSCursor *cursor = static_cast<QEglFSCursor *>(window->screen()->cursor()))
- cursor->paintOnScreen();
+ if (surface->surface()->surfaceClass() == QSurface::Window) {
+ QEglFSWindow *window = static_cast<QEglFSWindow *>(surface);
+ // draw the cursor
+ if (QEglFSCursor *cursor = static_cast<QEglFSCursor *>(window->screen()->cursor()))
+ cursor->paintOnScreen();
+ }
QEGLPlatformContext::swapBuffers(surface);
}
diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
index 9c48ba1575..dd212c80a0 100644
--- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
@@ -51,6 +51,7 @@
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
+#include <QtPlatformSupport/private/qeglpbuffer_p.h>
#if !defined(QT_NO_EVDEV)
#include <QtPlatformSupport/private/qevdevmousemanager_p.h>
@@ -62,6 +63,7 @@
#include <QtGui/QSurfaceFormat>
#include <QtGui/QOpenGLContext>
#include <QtGui/QScreen>
+#include <QtGui/QOffscreenSurface>
#include <qpa/qplatformcursor.h>
#include "qeglfscontext.h"
@@ -154,6 +156,12 @@ QPlatformOpenGLContext *QEglFSIntegration::createPlatformOpenGLContext(QOpenGLCo
return new QEglFSContext(hooks->surfaceFormatFor(context->format()), context->shareHandle(), mDisplay);
}
+QPlatformOffscreenSurface *QEglFSIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
+{
+ QEglFSScreen *screen = static_cast<QEglFSScreen *>(surface->screen()->handle());
+ return new QEGLPbuffer(screen->display(), hooks->surfaceFormatFor(surface->requestedFormat()), surface);
+}
+
QPlatformFontDatabase *QEglFSIntegration::fontDatabase() const
{
return mFontDb;
diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.h b/src/plugins/platforms/eglfs/qeglfsintegration.h
index 9eae8d2703..e048c5d310 100644
--- a/src/plugins/platforms/eglfs/qeglfsintegration.h
+++ b/src/plugins/platforms/eglfs/qeglfsintegration.h
@@ -61,6 +61,7 @@ public:
QPlatformWindow *createPlatformWindow(QWindow *window) const;
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const;
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
+ QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const;
QPlatformNativeInterface *nativeInterface() const;
QPlatformFontDatabase *fontDatabase() const;
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp
index 23bec15b48..5e2731430d 100644
--- a/src/plugins/platforms/xcb/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/qglxintegration.cpp
@@ -50,6 +50,7 @@
#include <GL/glx.h>
#include <QtGui/QOpenGLContext>
+#include <QtGui/QOffscreenSurface>
#include "qglxintegration.h"
#include <QtPlatformSupport/private/qglxconvenience_p.h>
@@ -270,6 +271,7 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
, m_screen(screen)
, m_context(0)
, m_format(format)
+ , m_isPBufferCurrent(false)
{
m_shareContext = 0;
if (share)
@@ -390,19 +392,35 @@ bool QGLXContext::makeCurrent(QPlatformSurface *surface)
{
Q_ASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface);
- GLXDrawable glxDrawable = static_cast<QXcbWindow *>(surface)->xcb_window();
-
- return glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), glxDrawable, m_context);
+ QSurface::SurfaceClass surfaceClass = surface->surface()->surfaceClass();
+ if (surfaceClass == QSurface::Window) {
+ m_isPBufferCurrent = false;
+ QXcbWindow *window = static_cast<QXcbWindow *>(surface);
+ return glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), window->xcb_window(), m_context);
+ } else if (surfaceClass == QSurface::Offscreen) {
+ m_isPBufferCurrent = true;
+ QGLXPbuffer *pbuffer = static_cast<QGLXPbuffer *>(surface);
+ return glXMakeContextCurrent(DISPLAY_FROM_XCB(m_screen), pbuffer->pbuffer(), pbuffer->pbuffer(), m_context);
+ }
+ return false;
}
void QGLXContext::doneCurrent()
{
- glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), 0, 0);
+ if (m_isPBufferCurrent)
+ glXMakeContextCurrent(DISPLAY_FROM_XCB(m_screen), 0, 0, 0);
+ else
+ glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), 0, 0);
+ m_isPBufferCurrent = false;
}
void QGLXContext::swapBuffers(QPlatformSurface *surface)
{
- GLXDrawable glxDrawable = static_cast<QXcbWindow *>(surface)->xcb_window();
+ GLXDrawable glxDrawable = 0;
+ if (surface->surface()->surfaceClass() == QSurface::Offscreen)
+ glxDrawable = static_cast<QGLXPbuffer *>(surface)->pbuffer();
+ else
+ glxDrawable = static_cast<QXcbWindow *>(surface)->xcb_window();
glXSwapBuffers(DISPLAY_FROM_XCB(m_screen), glxDrawable);
}
@@ -454,4 +472,36 @@ bool QGLXContext::isValid() const
return m_context != 0;
}
+
+QGLXPbuffer::QGLXPbuffer(QOffscreenSurface *offscreenSurface)
+ : QPlatformOffscreenSurface(offscreenSurface)
+ , m_format(offscreenSurface->requestedFormat())
+ , m_screen(static_cast<QXcbScreen *>(offscreenSurface->screen()->handle()))
+ , m_pbuffer(0)
+{
+ GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(m_screen), m_screen->screenNumber(), m_format);
+
+ if (config) {
+ const int attributes[] = {
+ GLX_PBUFFER_WIDTH, offscreenSurface->size().width(),
+ GLX_PBUFFER_HEIGHT, offscreenSurface->size().height(),
+ GLX_LARGEST_PBUFFER, False,
+ GLX_PRESERVED_CONTENTS, False,
+ GLX_NONE
+ };
+
+ m_pbuffer = glXCreatePbuffer(DISPLAY_FROM_XCB(m_screen), config, attributes);
+
+ if (m_pbuffer)
+ m_format = qglx_surfaceFormatFromGLXFBConfig(DISPLAY_FROM_XCB(m_screen), config);
+ }
+}
+
+QGLXPbuffer::~QGLXPbuffer()
+{
+ if (m_pbuffer)
+ glXDestroyPbuffer(DISPLAY_FROM_XCB(m_screen), m_pbuffer);
+}
+
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h
index 78e9985334..d10b1d441b 100644
--- a/src/plugins/platforms/xcb/qglxintegration.h
+++ b/src/plugins/platforms/xcb/qglxintegration.h
@@ -46,6 +46,7 @@
#include "qxcbscreen.h"
#include <qpa/qplatformopenglcontext.h>
+#include <qpa/qplatformoffscreensurface.h>
#include <QtGui/QSurfaceFormat>
#include <QtCore/QMutex>
@@ -89,6 +90,25 @@ private:
GLXContext m_context;
GLXContext m_shareContext;
QSurfaceFormat m_format;
+ bool m_isPBufferCurrent;
+};
+
+
+class QGLXPbuffer : public QPlatformOffscreenSurface
+{
+public:
+ explicit QGLXPbuffer(QOffscreenSurface *offscreenSurface);
+ ~QGLXPbuffer();
+
+ QSurfaceFormat format() const { return m_format; }
+ bool isValid() const { return m_pbuffer != 0; }
+
+ GLXPbuffer pbuffer() const { return m_pbuffer; }
+
+private:
+ QSurfaceFormat m_format;
+ QXcbScreen *m_screen;
+ GLXPbuffer m_pbuffer;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 1840dd1ce5..d0b0ab8d02 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -78,10 +78,12 @@
#elif defined(XCB_USE_EGL)
#include "qxcbeglsurface.h"
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
+#include <QtPlatformSupport/private/qeglpbuffer_p.h>
#endif
#include <QtGui/QOpenGLContext>
#include <QtGui/QScreen>
+#include <QtGui/QOffscreenSurface>
#ifndef QT_NO_ACCESSIBILITY
#include <qpa/qplatformaccessibility.h>
#ifndef QT_NO_ACCESSIBILITY_ATSPI_BRIDGE
@@ -168,7 +170,10 @@ public:
EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface)
{
- return static_cast<QXcbWindow *>(surface)->eglSurface()->surface();
+ if (surface->surface()->surfaceClass() == QSurface::Window)
+ return static_cast<QXcbWindow *>(surface)->eglSurface()->surface();
+ else
+ return static_cast<QEGLPbuffer *>(surface)->pbuffer();
}
private:
@@ -205,6 +210,20 @@ QPlatformBackingStore *QXcbIntegration::createPlatformBackingStore(QWindow *wind
return new QXcbBackingStore(window);
}
+QPlatformOffscreenSurface *QXcbIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
+{
+#if defined(XCB_USE_GLX)
+ return new QGLXPbuffer(surface);
+#elif defined(XCB_USE_EGL)
+ QXcbScreen *screen = static_cast<QXcbScreen *>(surface->screen()->handle());
+ return new QEGLPbuffer(screen->connection()->egl_display(), surface->requestedFormat(), surface);
+#else
+ Q_UNUSED(surface);
+ qWarning("QXcbIntegration: Cannot create platform offscreen surface, neither GLX nor EGL are enabled");
+ return 0;
+#endif
+}
+
bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
switch (cap) {
diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h
index cd6c2fd73c..13b3b115ca 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.h
+++ b/src/plugins/platforms/xcb/qxcbintegration.h
@@ -68,6 +68,8 @@ public:
#endif
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const;
+ QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const;
+
bool hasCapability(Capability cap) const;
QAbstractEventDispatcher *guiThreadEventDispatcher() const;