summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/xcb')
-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
4 files changed, 97 insertions, 6 deletions
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;