From 4a189c188ccd2fb5f8d1d5ddadf06cbd6bc0916f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 7 Jun 2011 17:25:22 +0200 Subject: QWindowContext / QWindowFormat refactor. To enable having a single GL context used for multiple drawables we need to de-couple the context class a bit more from the window class in the plugin API. Now contexts are created stand-alone based on a GL format and a share context, and when calling makeCurrent() a desired surface is specified. This maps well to GLX, EGL, Cocoa, AGL, and WGL, which all support this use case. QWindowContext is renamed to QGuiGLContext, and QWindowFormat is renamed to QGuiGLFormat. We have the ability to introduce a pbuffer or similar other offscreen GL drawable abstraction in the future. --- src/plugins/platforms/cocoa/qcocoaglcontext.h | 40 +++++-- src/plugins/platforms/cocoa/qcocoaglcontext.mm | 92 ++++++++++------ src/plugins/platforms/cocoa/qcocoaintegration.h | 1 + src/plugins/platforms/cocoa/qcocoaintegration.mm | 5 + .../platforms/cocoa/qcocoanativeinterface.mm | 9 +- src/plugins/platforms/cocoa/qcocoawindow.h | 9 +- src/plugins/platforms/cocoa/qcocoawindow.mm | 35 +++++- src/plugins/platforms/cocoa/qnswindowdelegate.h | 3 +- src/plugins/platforms/cocoa/qnswindowdelegate.mm | 8 ++ .../platforms/eglconvenience/qeglconvenience.cpp | 12 ++- .../platforms/eglconvenience/qeglconvenience.h | 8 +- .../eglconvenience/qeglplatformcontext.cpp | 79 ++++++++------ .../platforms/eglconvenience/qeglplatformcontext.h | 32 ++++-- .../platforms/glxconvenience/qglxconvenience.cpp | 20 ++-- .../platforms/glxconvenience/qglxconvenience.h | 13 +-- .../wayland/gl_integration/qwaylandglintegration.h | 4 + .../gl_integration/qwaylandglwindowsurface.cpp | 24 +++-- .../gl_integration/qwaylandglwindowsurface.h | 3 + .../qwaylandreadbackeglintegration.cpp | 7 +- .../readback_egl/qwaylandreadbackeglintegration.h | 1 + .../readback_glx/qwaylandreadbackglxcontext.cpp | 111 ++++++++----------- .../readback_glx/qwaylandreadbackglxcontext.h | 39 ++++--- .../qwaylandreadbackglxintegration.cpp | 5 + .../readback_glx/qwaylandreadbackglxintegration.h | 1 + .../readback_glx/qwaylandreadbackglxwindow.cpp | 60 +++++++++-- .../readback_glx/qwaylandreadbackglxwindow.h | 15 ++- .../qwaylandxcompositeeglcontext.cpp | 118 +++------------------ .../xcomposite_egl/qwaylandxcompositeeglcontext.h | 34 +++--- .../qwaylandxcompositeeglintegration.cpp | 5 + .../qwaylandxcompositeeglintegration.h | 3 + .../xcomposite_egl/qwaylandxcompositeeglwindow.cpp | 101 +++++++++++++++--- .../xcomposite_egl/qwaylandxcompositeeglwindow.h | 20 +++- .../xcomposite_egl/xcomposite_egl.pri | 1 + .../qwaylandxcompositeglxcontext.cpp | 117 ++++++-------------- .../xcomposite_glx/qwaylandxcompositeglxcontext.h | 44 ++++---- .../qwaylandxcompositeglxintegration.cpp | 7 +- .../qwaylandxcompositeglxintegration.h | 1 + .../xcomposite_glx/qwaylandxcompositeglxwindow.cpp | 91 +++++++++++++--- .../xcomposite_glx/qwaylandxcompositeglxwindow.h | 22 +++- .../platforms/wayland/qwaylandintegration.cpp | 10 +- .../platforms/wayland/qwaylandintegration.h | 1 + .../platforms/wayland/qwaylandshmwindow.cpp | 4 +- src/plugins/platforms/wayland/qwaylandshmwindow.h | 2 +- src/plugins/platforms/xcb/qglxintegration.cpp | 51 ++++----- src/plugins/platforms/xcb/qglxintegration.h | 28 ++--- src/plugins/platforms/xcb/qxcbintegration.cpp | 17 +++ src/plugins/platforms/xcb/qxcbintegration.h | 1 + src/plugins/platforms/xcb/qxcbnativeinterface.cpp | 6 +- src/plugins/platforms/xcb/qxcbwindow.cpp | 42 +++----- src/plugins/platforms/xcb/qxcbwindow.h | 7 +- 50 files changed, 815 insertions(+), 554 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h index 4d330a4294..01d931b662 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.h +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h @@ -1,26 +1,52 @@ #ifndef QCOCOAGLCONTEXT_H #define QCOCOAGLCONTEXT_H +#include #include -#include +#include +#include #include QT_BEGIN_NAMESPACE +class QCocoaGLSurface : public QPlatformGLSurface +{ +public: + QCocoaGLSurface(const QGuiGLFormat &format, QWindow *window) + : QPlatformGLSurface(format) + , window(window) + { + } + + QWindow *window; +}; + class QCocoaGLContext : public QPlatformGLContext { public: - QCocoaGLContext(NSOpenGLView *glView); - void makeCurrent(); + QCocoaGLContext(const QGuiGLFormat &format, QPlatformGLContext *share); + + QGuiGLFormat format() const; + + void swapBuffers(const QPlatformGLSurface &surface); + + bool makeCurrent(const QPlatformGLSurface &surface); void doneCurrent(); - void swapBuffers(); - void* getProcAddress(const QString& procName); - QWindowFormat windowFormat() const; + + void (*getProcAddress(const QByteArray &procName)) (); + + void update(); + static NSOpenGLPixelFormat *createNSOpenGLPixelFormat(); NSOpenGLContext *nsOpenGLContext() const; + private: - NSOpenGLView *m_glView; + void setActiveWindow(QWindow *window); + + NSOpenGLContext *m_context; + QGuiGLFormat m_format; + QWeakPointer m_currentWindow; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index 3a87537e64..f9cda1bb37 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -1,66 +1,88 @@ #include "qcocoaglcontext.h" +#include "qcocoawindow.h" #include #include #import -QCocoaGLContext::QCocoaGLContext(NSOpenGLView *glView) -:m_glView(glView) +QCocoaGLContext::QCocoaGLContext(const QGuiGLFormat &format, QPlatformGLContext *share) + : m_format(format) { + NSOpenGLPixelFormat *pixelFormat = createNSOpenGLPixelFormat(); + NSOpenGLContext *actualShare = share ? static_cast(share)->m_context : 0; + m_context = [NSOpenGLContext alloc]; + [m_context initWithFormat:pixelFormat shareContext:actualShare]; } -void QCocoaGLContext::makeCurrent() +// Match up with createNSOpenGLPixelFormat! +QGuiGLFormat QCocoaGLContext::format() const { - [[m_glView openGLContext] makeCurrentContext]; + return m_format; } -void QCocoaGLContext::doneCurrent() + +void QCocoaGLContext::swapBuffers(const QPlatformGLSurface &surface) { - [NSOpenGLContext clearCurrentContext]; + QWindow *window = static_cast(surface).window; + setActiveWindow(window); + + [m_context flushBuffer]; +} + +bool QCocoaGLContext::makeCurrent(const QPlatformGLSurface &surface) +{ + QWindow *window = static_cast(surface).window; + setActiveWindow(window); + + [m_context makeCurrentContext]; + return true; +} + +void QCocoaGLContext::setActiveWindow(QWindow *window) +{ + if (window == m_currentWindow.data()) + return; + + if (m_currentWindow) + static_cast(m_currentWindow.data()->handle())->setCurrentContext(0); + + Q_ASSERT(window->handle()); + + m_currentWindow = window; + + QCocoaWindow *cocoaWindow = static_cast(window->handle()); + cocoaWindow->setCurrentContext(this); + + NSView *view = cocoaWindow->windowSurfaceView(); + [m_context setView:view]; } -void QCocoaGLContext::swapBuffers() +void QCocoaGLContext::doneCurrent() { - [[m_glView openGLContext] flushBuffer]; + if (m_currentWindow) + static_cast(m_currentWindow.data()->handle())->setCurrentContext(0); + + m_currentWindow.clear(); + + [NSOpenGLContext clearCurrentContext]; } -void* QCocoaGLContext::getProcAddress(const QString& procName) +void (*QCocoaGLContext::getProcAddress(const QByteArray &procName)) () { CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("/System/Library/Frameworks/OpenGL.framework"), kCFURLPOSIXPathStyle, false); CFBundleRef bundle = CFBundleCreate(kCFAllocatorDefault, url); - CFStringRef procNameCF = QCFString::toCFStringRef(procName); + CFStringRef procNameCF = QCFString::toCFStringRef(QString::fromAscii(procName.constData())); void *proc = CFBundleGetFunctionPointerForName(bundle, procNameCF); CFRelease(url); CFRelease(bundle); CFRelease(procNameCF); - return proc; + return (void (*) ())proc; } -// Match up with createNSOpenGLPixelFormat below! -QWindowFormat QCocoaGLContext::windowFormat() const +void QCocoaGLContext::update() { - QWindowFormat format; - format.setRedBufferSize(8); - format.setGreenBufferSize(8); - format.setBlueBufferSize(8); - format.setAlphaBufferSize(8); - -/* - format.setDepthBufferSize(24); - format.setAccumBufferSize(0); - format.setStencilBufferSize(8); - format.setSampleBuffers(false); - format.setSamples(1); - format.setDepth(true); - format.setRgba(true); - format.setAlpha(true); - format.setAccum(false); - format.setStencil(true); - format.setStereo(false); - format.setDirectRendering(false); -*/ - return format; + [m_context update]; } NSOpenGLPixelFormat *QCocoaGLContext::createNSOpenGLPixelFormat() @@ -78,6 +100,6 @@ NSOpenGLPixelFormat *QCocoaGLContext::createNSOpenGLPixelFormat() NSOpenGLContext *QCocoaGLContext::nsOpenGLContext() const { - return [m_glView openGLContext]; + return m_context; } diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index 3e705e7805..59008b4e3f 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -78,6 +78,7 @@ public: bool hasCapability(QPlatformIntegration::Capability cap) const; QPixmapData *createPixmapData(QPixmapData::PixelType type) const; QPlatformWindow *createPlatformWindow(QWindow *window) const; + QPlatformGLContext *createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const; QWindowSurface *createWindowSurface(QWindow *widget, WId winId) const; QList screens() const { return mScreens; } diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 42ec268964..dfe225ff2e 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -113,6 +113,11 @@ QPlatformWindow *QCocoaIntegration::createPlatformWindow(QWindow *window) const return new QCocoaWindow(window); } +QPlatformGLContext *QCocoaIntegration::createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const +{ + return new QCocoaGLContext(glFormat, share); +} + QWindowSurface *QCocoaIntegration::createWindowSurface(QWindow *window, WId winId) const { return new QCocoaWindowSurface(window, winId); diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 6b86108f75..87d0ec4a0c 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -41,19 +41,20 @@ #include "qcocoanativeinterface.h" #include "qcocoaglcontext.h" +#include "qcocoawindow.h" #include #include #include "qplatformwindow_qpa.h" -#include "qwindowformat_qpa.h" +#include "qguiglformat_qpa.h" #include "qplatformglcontext_qpa.h" -#include "qwindowcontext_qpa.h" +#include "qguiglcontext_qpa.h" #include void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) { if (resourceString == "nsopenglcontext") { - QPlatformGLContext *platformContext = window->glContext()->handle(); - return static_cast(platformContext)->nsOpenGLContext(); + + static_cast(window->handle())->currentContext()->nsOpenGLContext(); } return 0; } diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index dcf755d009..9d7d37c2ee 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -65,17 +65,22 @@ public: WId winId() const; NSView *contentView() const; + NSView *windowSurfaceView() const; + void windowDidMove(); void windowDidResize(); - QPlatformGLContext *glContext() const; + QPlatformGLSurface *createGLSurface() const; + + void setCurrentContext(QCocoaGLContext *context); + QCocoaGLContext *currentContext() const; private: friend class QCocoaWindowSurface; NSWindow *m_nsWindow; QNSView *m_contentView; NSView *m_windowSurfaceView; - mutable QCocoaGLContext *m_glContext; + QCocoaGLContext *m_glContext; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index a5ad8c87ae..874790a128 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -84,6 +84,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw) QCocoaWindow::~QCocoaWindow() { + } void QCocoaWindow::setGeometry(const QRect &rect) @@ -92,6 +93,9 @@ void QCocoaWindow::setGeometry(const QRect &rect) NSRect bounds = NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()); [[m_nsWindow contentView]setFrameSize:bounds.size]; + + if (m_glContext) + m_glContext->update(); } void QCocoaWindow::setVisible(bool visible) @@ -131,18 +135,41 @@ NSView *QCocoaWindow::contentView() const return [m_nsWindow contentView]; } +NSView *QCocoaWindow::windowSurfaceView() const +{ + return m_windowSurfaceView; +} + +void QCocoaWindow::windowDidMove() +{ + if (m_glContext) + m_glContext->update(); +} + void QCocoaWindow::windowDidResize() { //jlind: XXX This isn't ideal. Eventdispatcher does not run when resizing... NSRect rect = [[m_nsWindow contentView]frame]; QRect geo(rect.origin.x,rect.origin.y,rect.size.width,rect.size.height); QWindowSystemInterface::handleGeometryChange(window(),geo); + + if (m_glContext) + m_glContext->update(); } -QPlatformGLContext *QCocoaWindow::glContext() const +QPlatformGLSurface *QCocoaWindow::createGLSurface() const +{ + Q_ASSERT(window()->surfaceType() == QWindow::OpenGLSurface); + return new QCocoaGLSurface(window()->glFormat(), window()); +} + +void QCocoaWindow::setCurrentContext(QCocoaGLContext *context) +{ + m_glContext = context; +} + +QCocoaGLContext *QCocoaWindow::currentContext() const { - if (!m_glContext) { - m_glContext = new QCocoaGLContext(m_windowSurfaceView); - } return m_glContext; } + diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.h b/src/plugins/platforms/cocoa/qnswindowdelegate.h index 1ea02ac016..5cd226a71d 100644 --- a/src/plugins/platforms/cocoa/qnswindowdelegate.h +++ b/src/plugins/platforms/cocoa/qnswindowdelegate.h @@ -53,7 +53,7 @@ - (void)windowDidResize:(NSNotification *)notification; - (void)windowWillClose:(NSNotification *)notification; //- (NSRect)windowWillUseStandardFrame:(NSWindow *)window defaultFrame:(NSRect)defaultFrame; -//- (void)windowDidMove:(NSNotification *)notification; +- (void)windowDidMove:(NSNotification *)notification; //- (BOOL)windowShouldClose:(id)window; //- (void)windowDidDeminiaturize:(NSNotification *)notification; //- (void)windowDidBecomeMain:(NSNotification*)notification; @@ -74,6 +74,7 @@ - (id)initWithQCocoaWindow: (QCocoaWindow *) cocoaWindow; - (void)windowDidResize:(NSNotification *)notification; +- (void)windowDidMove:(NSNotification *)notification; - (void)windowWillClose:(NSNotification *)notification; @end diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.mm b/src/plugins/platforms/cocoa/qnswindowdelegate.mm index 54def7e592..6521db5cf7 100644 --- a/src/plugins/platforms/cocoa/qnswindowdelegate.mm +++ b/src/plugins/platforms/cocoa/qnswindowdelegate.mm @@ -64,6 +64,14 @@ } } +- (void)windowDidMove:(NSNotification *)notification +{ + Q_UNUSED(notification); + if (m_cocoaWindow) { + m_cocoaWindow->windowDidMove(); + } +} + - (void)windowWillClose:(NSNotification *)notification { Q_UNUSED(notification); diff --git a/src/plugins/platforms/eglconvenience/qeglconvenience.cpp b/src/plugins/platforms/eglconvenience/qeglconvenience.cpp index 333425632c..2f686d6f76 100644 --- a/src/plugins/platforms/eglconvenience/qeglconvenience.cpp +++ b/src/plugins/platforms/eglconvenience/qeglconvenience.cpp @@ -39,11 +39,13 @@ ** ****************************************************************************/ +#include + #include "qeglconvenience.h" QT_BEGIN_NAMESPACE -QVector q_createConfigAttributesFromFormat(const QWindowFormat &format) +QVector q_createConfigAttributesFromFormat(const QGuiGLFormat &format) { int redSize = format.redBufferSize(); int greenSize = format.greenBufferSize(); @@ -68,7 +70,7 @@ QVector q_createConfigAttributesFromFormat(const QWindowFormat &format) // "AtLeast" for EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are // put in the list before 32-bit configs. So, to make sure 16-bit is preffered over 32-bit, // we must set the red/green/blue sizes to zero. This has an unfortunate consequence that - // if the application sets the red/green/blue size to 5/6/5 on the QPlatformWindowFormat, + // if the application sets the red/green/blue size to 5/6/5 on the QGuiGLFormat, // they will probably get a 32-bit config, even when there's an RGB565 config available. // // Now normalize the values so -1 becomes 0 @@ -195,7 +197,7 @@ bool q_reduceConfigAttributes(QVector *configAttributes) return false; } -EGLConfig q_configFromQWindowFormat(EGLDisplay display, const QWindowFormat &format, bool highestPixelFormat, int surfaceType) +EGLConfig q_configFromGLFormat(EGLDisplay display, const QGuiGLFormat &format, bool highestPixelFormat, int surfaceType) { EGLConfig cfg = 0; QVector configureAttributes = q_createConfigAttributesFromFormat(format); @@ -257,9 +259,9 @@ EGLConfig q_configFromQWindowFormat(EGLDisplay display, const QWindowFormat &for return 0; } -QWindowFormat q_windowFormatFromConfig(EGLDisplay display, const EGLConfig config) +QGuiGLFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config) { - QWindowFormat format; + QGuiGLFormat format; EGLint redSize = 0; EGLint greenSize = 0; EGLint blueSize = 0; diff --git a/src/plugins/platforms/eglconvenience/qeglconvenience.h b/src/plugins/platforms/eglconvenience/qeglconvenience.h index 978cab4925..302aba318f 100644 --- a/src/plugins/platforms/eglconvenience/qeglconvenience.h +++ b/src/plugins/platforms/eglconvenience/qeglconvenience.h @@ -43,16 +43,16 @@ #define QEGLCONVENIENCE_H -#include +#include #include #include QT_BEGIN_NAMESPACE -QVector q_createConfigAttributesFromFormat(const QWindowFormat &format); +QVector q_createConfigAttributesFromFormat(const QGuiGLFormat &format); bool q_reduceConfigAttributes(QVector *configAttributes); -EGLConfig q_configFromQWindowFormat(EGLDisplay display, const QWindowFormat &format, bool highestPixelFormat = false, int surfaceType = EGL_WINDOW_BIT); -QWindowFormat q_windowFormatFromConfig(EGLDisplay display, const EGLConfig config); +EGLConfig q_configFromGLFormat(EGLDisplay display, const QGuiGLFormat &format, bool highestPixelFormat = false, int surfaceType = EGL_WINDOW_BIT); +QGuiGLFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config); bool q_hasEglExtension(EGLDisplay display,const char* extensionName); QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp b/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp index db3666bb3e..c96e8ed67a 100644 --- a/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp +++ b/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp @@ -48,51 +48,47 @@ #include -QEGLPlatformContext::QEGLPlatformContext(EGLDisplay display, EGLConfig config, EGLint contextAttrs[], EGLSurface surface, EGLenum eglApi) - : QPlatformGLContext() - , m_eglDisplay(display) +QEGLSurface::QEGLSurface(EGLSurface surface, const QGuiGLFormat &format) + : QPlatformGLSurface(format) , m_eglSurface(surface) +{ +} + +QEGLPlatformContext::QEGLPlatformContext(const QGuiGLFormat &format, QPlatformGLContext *share, EGLDisplay display, + EGLint eglClientVersion, EGLenum eglApi) + : m_eglDisplay(display) , m_eglApi(eglApi) + , m_format(format) { - if (m_eglSurface == EGL_NO_SURFACE) { - qWarning("Createing QEGLPlatformContext with no surface"); - } + EGLConfig config = q_configFromGLFormat(display, format, true); + m_format = q_glFormatFromConfig(display, config); + + EGLContext shareContext = share ? static_cast(share)->m_eglContext : 0; + + QVector contextAttrs; + contextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); + contextAttrs.append(eglClientVersion); + contextAttrs.append(EGL_NONE); eglBindAPI(m_eglApi); - m_eglContext = eglCreateContext(m_eglDisplay,config, 0,contextAttrs); + m_eglContext = eglCreateContext(m_eglDisplay, config, shareContext, contextAttrs.constData()); if (m_eglContext == EGL_NO_CONTEXT) { qWarning("Could not create the egl context\n"); eglTerminate(m_eglDisplay); qFatal("EGL error"); } - - m_windowFormat = q_windowFormatFromConfig(display,config); -} - -QEGLPlatformContext::~QEGLPlatformContext() -{ -#ifdef QEGL_EXTRA_DEBUG - qWarning("QEglContext::~QEglContext(): %p\n",this); -#endif - if (m_eglSurface != EGL_NO_SURFACE) { - doneCurrent(); - eglDestroySurface(m_eglDisplay, m_eglSurface); - m_eglSurface = EGL_NO_SURFACE; - } - - if (m_eglContext != EGL_NO_CONTEXT) { - eglDestroyContext(m_eglDisplay, m_eglContext); - m_eglContext = EGL_NO_CONTEXT; - } } -void QEGLPlatformContext::makeCurrent() +bool QEGLPlatformContext::makeCurrent(const QPlatformGLSurface &surface) { #ifdef QEGL_EXTRA_DEBUG qWarning("QEglContext::makeCurrent: %p\n",this); #endif eglBindAPI(m_eglApi); - bool ok = eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); + + EGLSurface eglSurface = static_cast(surface).eglSurface(); + + bool ok = eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_eglContext); if (!ok) qWarning("QEGLPlatformContext::makeCurrent: eglError: %d, this: %p \n", eglGetError(), this); #ifdef QEGL_EXTRA_DEBUG @@ -114,7 +110,20 @@ void QEGLPlatformContext::makeCurrent() } #endif + return ok; +} + +QEGLPlatformContext::~QEGLPlatformContext() +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglContext::~QEglContext(): %p\n",this); +#endif + if (m_eglContext != EGL_NO_CONTEXT) { + eglDestroyContext(m_eglDisplay, m_eglContext); + m_eglContext = EGL_NO_CONTEXT; + } } + void QEGLPlatformContext::doneCurrent() { #ifdef QEGL_EXTRA_DEBUG @@ -125,28 +134,30 @@ void QEGLPlatformContext::doneCurrent() if (!ok) qWarning("QEGLPlatformContext::doneCurrent(): eglError: %d, this: %p \n", eglGetError(), this); } -void QEGLPlatformContext::swapBuffers() + +void QEGLPlatformContext::swapBuffers(const QPlatformGLSurface &surface) { #ifdef QEGL_EXTRA_DEBUG qWarning("QEglContext::swapBuffers:%p\n",this); #endif eglBindAPI(m_eglApi); - bool ok = eglSwapBuffers(m_eglDisplay, m_eglSurface); + bool ok = eglSwapBuffers(m_eglDisplay, static_cast(surface).eglSurface()); if (!ok) qWarning("QEGLPlatformContext::swapBuffers(): eglError: %d, this: %p \n", eglGetError(), this); } -void* QEGLPlatformContext::getProcAddress(const QString& procName) + +void (*QEGLPlatformContext::getProcAddress(const QByteArray &procName)) () { #ifdef QEGL_EXTRA_DEBUG qWarning("QEglContext::getProcAddress%p\n",this); #endif eglBindAPI(m_eglApi); - return (void *)eglGetProcAddress(qPrintable(procName)); + return eglGetProcAddress(procName.constData()); } -QWindowFormat QEGLPlatformContext::windowFormat() const +QGuiGLFormat QEGLPlatformContext::format() const { - return m_windowFormat; + return m_format; } EGLContext QEGLPlatformContext::eglContext() const diff --git a/src/plugins/platforms/eglconvenience/qeglplatformcontext.h b/src/plugins/platforms/eglconvenience/qeglplatformcontext.h index 531f553f3b..9877b77e4e 100644 --- a/src/plugins/platforms/eglconvenience/qeglplatformcontext.h +++ b/src/plugins/platforms/eglconvenience/qeglplatformcontext.h @@ -39,33 +39,45 @@ ** ****************************************************************************/ -#ifndef QOPENKODEGLINTEGRATION_H -#define QOPENKODEGLINTEGRATION_H +#ifndef QEGLPLATFORMCONTEXT_H +#define QEGLPLATFORMCONTEXT_H #include #include +class QEGLSurface : public QPlatformGLSurface +{ +public: + QEGLSurface(EGLSurface surface, const QGuiGLFormat &format); + + virtual EGLSurface eglSurface() const { return m_eglSurface; } + +private: + EGLSurface m_eglSurface; +}; + class QEGLPlatformContext : public QPlatformGLContext { public: - QEGLPlatformContext(EGLDisplay display, EGLConfig config, EGLint contextAttrs[], EGLSurface surface, EGLenum eglApi); + QEGLPlatformContext(const QGuiGLFormat &format, QPlatformGLContext *share, EGLDisplay display, + EGLint eglClientVersion = 2, EGLenum eglApi = EGL_OPENGL_ES_API); ~QEGLPlatformContext(); - void makeCurrent(); + bool makeCurrent(const QPlatformGLSurface &surface); void doneCurrent(); - void swapBuffers(); - void* getProcAddress(const QString& procName); + void swapBuffers(const QPlatformGLSurface &surface); + void (*getProcAddress(const QByteArray &procName)) (); - QWindowFormat windowFormat() const; + QGuiGLFormat format() const; EGLContext eglContext() const; + private: EGLContext m_eglContext; EGLDisplay m_eglDisplay; - EGLSurface m_eglSurface; EGLenum m_eglApi; - QWindowFormat m_windowFormat; + QGuiGLFormat m_format; }; -#endif //QOPENKODEGLINTEGRATION_H +#endif //QEGLPLATFORMCONTEXT_H diff --git a/src/plugins/platforms/glxconvenience/qglxconvenience.cpp b/src/plugins/platforms/glxconvenience/qglxconvenience.cpp index ad7668136d..189ab397d2 100644 --- a/src/plugins/platforms/glxconvenience/qglxconvenience.cpp +++ b/src/plugins/platforms/glxconvenience/qglxconvenience.cpp @@ -70,7 +70,7 @@ enum { #undef FontChange #endif -QVector qglx_buildSpec(const QWindowFormat &format, int drawableBit) +QVector qglx_buildSpec(const QGuiGLFormat &format, int drawableBit) { QVector spec(48); int i = 0; @@ -88,7 +88,7 @@ QVector qglx_buildSpec(const QWindowFormat &format, int drawableBit) spec[i++] = GLX_ALPHA_SIZE; spec[i++] = format.alphaBufferSize(); } - spec[i++] = GLX_DOUBLEBUFFER; spec[i++] = format.swapBehavior() != QWindowFormat::SingleBuffer ? True : False; + spec[i++] = GLX_DOUBLEBUFFER; spec[i++] = format.swapBehavior() != QGuiGLFormat::SingleBuffer ? True : False; spec[i++] = GLX_STEREO; spec[i++] = format.stereo() ? True : False; @@ -111,11 +111,11 @@ QVector qglx_buildSpec(const QWindowFormat &format, int drawableBit) return spec; } -GLXFBConfig qglx_findConfig(Display *display, int screen , const QWindowFormat &format, int drawableBit) +GLXFBConfig qglx_findConfig(Display *display, int screen , const QGuiGLFormat &format, int drawableBit) { bool reduced = true; GLXFBConfig chosenConfig = 0; - QWindowFormat reducedFormat = format; + QGuiGLFormat reducedFormat = format; while (!chosenConfig && reduced) { QVector spec = qglx_buildSpec(reducedFormat, drawableBit); int confcount = 0; @@ -147,7 +147,7 @@ GLXFBConfig qglx_findConfig(Display *display, int screen , const QWindowFormat & XFree(configs); } - reducedFormat = qglx_reduceWindowFormat(reducedFormat,&reduced); + reducedFormat = qglx_reduceGuiGLFormat(reducedFormat,&reduced); } if (!chosenConfig) @@ -156,16 +156,16 @@ GLXFBConfig qglx_findConfig(Display *display, int screen , const QWindowFormat & return chosenConfig; } -XVisualInfo *qglx_findVisualInfo(Display *display, int screen, const QWindowFormat &format) +XVisualInfo *qglx_findVisualInfo(Display *display, int screen, const QGuiGLFormat &format) { GLXFBConfig config = qglx_findConfig(display,screen,format); XVisualInfo *visualInfo = glXGetVisualFromFBConfig(display,config); return visualInfo; } -QWindowFormat qglx_platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext) +QGuiGLFormat qglx_guiGLFormatFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext) { - QWindowFormat format; + QGuiGLFormat format; int redSize = 0; int greenSize = 0; int blueSize = 0; @@ -203,9 +203,9 @@ QWindowFormat qglx_platformWindowFromGLXFBConfig(Display *display, GLXFBConfig c return format; } -QWindowFormat qglx_reduceWindowFormat(const QWindowFormat &format, bool *reduced) +QGuiGLFormat qglx_reduceGuiGLFormat(const QGuiGLFormat &format, bool *reduced) { - QWindowFormat retFormat = format; + QGuiGLFormat retFormat = format; *reduced = true; if (retFormat.samples() > 1) { diff --git a/src/plugins/platforms/glxconvenience/qglxconvenience.h b/src/plugins/platforms/glxconvenience/qglxconvenience.h index fe51214006..1a0510067b 100644 --- a/src/plugins/platforms/glxconvenience/qglxconvenience.h +++ b/src/plugins/platforms/glxconvenience/qglxconvenience.h @@ -42,15 +42,16 @@ #ifndef QGLXCONVENIENCE_H #define QGLXCONVENIENCE_H -#include +#include +#include #include #include -XVisualInfo *qglx_findVisualInfo(Display *display, int screen, const QWindowFormat &format); -GLXFBConfig qglx_findConfig(Display *display, int screen, const QWindowFormat &format, int drawableBit = GLX_WINDOW_BIT); -QWindowFormat qglx_platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext context); -QVector qglx_buildSpec(const QWindowFormat &format, int drawableBit = GLX_WINDOW_BIT); -QWindowFormat qglx_reduceWindowFormat(const QWindowFormat &format, bool *reduced); +XVisualInfo *qglx_findVisualInfo(Display *display, int screen, const QGuiGLFormat &format); +GLXFBConfig qglx_findConfig(Display *display, int screen, const QGuiGLFormat &format, int drawableBit = GLX_WINDOW_BIT); +QGuiGLFormat qglx_guiGLFormatFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext context); +QVector qglx_buildSpec(const QGuiGLFormat &format, int drawableBit = GLX_WINDOW_BIT); +QGuiGLFormat qglx_reduceGuiGLFormat(const QGuiGLFormat &format, bool *reduced); #endif // QGLXCONVENIENCE_H diff --git a/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.h b/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.h index 250fdccf41..2960d64eea 100644 --- a/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.h +++ b/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.h @@ -46,6 +46,9 @@ class QWaylandWindow; class QWaylandDisplay; class QWindow; +class QPlatformGLContext; +class QGuiGLFormat; + class QWaylandGLIntegration { public: @@ -55,6 +58,7 @@ public: virtual void initialize() = 0; virtual QWaylandWindow *createEglWindow(QWindow *window) = 0; + virtual QPlatformGLContext *createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const = 0; static QWaylandGLIntegration *createGLIntegration(QWaylandDisplay *waylandDisplay); }; diff --git a/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp b/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp index 57da38ed3c..1d6e79e94c 100644 --- a/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp +++ b/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp @@ -138,13 +138,14 @@ QWaylandGLWindowSurface::QWaylandGLWindowSurface(QWindow *window) : QWindowSurface(window) , mDisplay(QWaylandScreen::waylandScreenFromWindow(window)->display()) , mPaintDevice(0) + , mContext(0) { - } QWaylandGLWindowSurface::~QWaylandGLWindowSurface() { delete mPaintDevice; + delete mContext; } QPaintDevice *QWaylandGLWindowSurface::paintDevice() @@ -152,31 +153,38 @@ QPaintDevice *QWaylandGLWindowSurface::paintDevice() return mPaintDevice; } +QGuiGLContext *QWaylandGLWindowSurface::context() const +{ + if (!mContext) + const_cast(mContext) = new QGuiGLContext(window()->glFormat()); + return mContext; +} + void QWaylandGLWindowSurface::beginPaint(const QRegion &) { - window()->handle()->glContext()->makeCurrent(); - glClearColor(0,0,0,0xff); + context()->makeCurrent(window()->glSurface()); + glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); } -void QWaylandGLWindowSurface::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) +void QWaylandGLWindowSurface::flush(QWindow *, const QRegion ®ion, const QPoint &offset) { Q_UNUSED(offset); Q_UNUSED(region); - + if (mPaintDevice->isBound()) mPaintDevice->release(); QRect rect(0,0,size().width(),size().height()); - QGLContext *ctx = QGLContext::fromWindowContext(window->glContext()); + QGLContext *ctx = QGLContext::fromGuiGLContext(context()); blitTexture(ctx,mPaintDevice->texture(),size(),mPaintDevice->size(),rect,rect); - window->glContext()->swapBuffers(); + context()->swapBuffers(window()->glSurface()); } void QWaylandGLWindowSurface::resize(const QSize &size) { QWindowSurface::resize(size); - window()->glContext()->makeCurrent(); + context()->makeCurrent(window()->glSurface()); delete mPaintDevice; mPaintDevice = new QGLFramebufferObject(size); } diff --git a/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.h b/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.h index 31c0fd2daa..3703869a60 100644 --- a/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.h +++ b/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.h @@ -61,9 +61,12 @@ public: void resize(const QSize &size); + QGuiGLContext *context() const; + private: QWaylandDisplay *mDisplay; QGLFramebufferObject *mPaintDevice; + QGuiGLContext *mContext; }; #endif // QWAYLANDDRMSURFACE_H diff --git a/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.cpp b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.cpp index 50a1170f79..7fbe5cc725 100644 --- a/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.cpp +++ b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.cpp @@ -83,7 +83,12 @@ void QWaylandReadbackEglIntegration::initialize() QWaylandWindow * QWaylandReadbackEglIntegration::createEglWindow(QWindow *window) { - return new QWaylandReadbackEglWindow(window,this); + return new QWaylandReadbackEglWindow(window, this); +} + +QPlatformGLContext *QWaylandReadbackEglWindow::createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const +{ + return new QWaylandReadbackEglContext(glFormat, share, this); } EGLDisplay QWaylandReadbackEglIntegration::eglDisplay() diff --git a/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.h b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.h index 649f96e9cc..8945cdab38 100644 --- a/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.h +++ b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.h @@ -63,6 +63,7 @@ public: void initialize(); QWaylandWindow *createEglWindow(QWindow *window); + QPlatformGLContext *createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const; QWaylandDisplay *waylandDisplay() const; Display *xDisplay() const; diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.cpp b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.cpp index 5750c948cd..54b7d322f8 100644 --- a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.cpp +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.cpp @@ -44,8 +44,19 @@ #include "qwaylandshmsurface.h" #include "qwaylandreadbackglxwindow.h" +#include #include +QWaylandReadbackGlxSurface::QWaylandReadbackGlxSurface(QWaylandReadbackGlxWindow *window) + : m_window(window) +{ +} + +GLXPixmap QWaylandReadbackGlxSurface::glxPixmap() const +{ + return m_window->glxPixmap(); +} + static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type) { const int width = img.width(); @@ -68,94 +79,66 @@ static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type) } } -QWaylandReadbackGlxContext::QWaylandReadbackGlxContext(QWaylandReadbackGlxIntegration *glxIntegration, QWaylandReadbackGlxWindow *window) - : QPlatformGLContext() - , mGlxIntegration(glxIntegration) - , mWindow(window) - , mBuffer(0) - , mPixmap(0) - , mConfig(qglx_findConfig(glxIntegration->xDisplay(),glxIntegration->screen(),window->widget()->platformWindowFormat(),GLX_PIXMAP_BIT)) - , mGlxPixmap(0) +QWaylandReadbackGlxContext::QWaylandReadbackGlxContext(const QGuiGLFormat &format, + QPlatformGLContext *share, Display *display, int screen) + : m_display(display) { - XVisualInfo *visualInfo = glXGetVisualFromFBConfig(glxIntegration->xDisplay(),mConfig); - mContext = glXCreateContext(glxIntegration->xDisplay(),visualInfo,0,TRUE); + GLXFBConfig config = qglx_findConfig(display, screen, format, GLX_PIXMAP_BIT); - geometryChanged(); + GLXContext shareContext = share ? static_cast(share)->m_context : 0; + + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(display, config); + m_context = glXCreateContext(display, visualInfo, shareContext, TRUE); + m_format = qglx_guiGLFormatFromGLXFBConfig(display, config, m_context); } -void QWaylandReadbackGlxContext::makeCurrent() +QGuiGLFormat QWaylandReadbackGlxContext::format() const { - glXMakeCurrent(mGlxIntegration->xDisplay(),mGlxPixmap,mContext); + return m_format; +} + +bool QWaylandReadbackGlxContext::makeCurrent(const QPlatformGLSurface &surface) +{ + GLXPixmap glxPixmap = static_cast(surface).glxPixmap(); + + return glXMakeCurrent(m_display, glxPixmap, m_context); } void QWaylandReadbackGlxContext::doneCurrent() { - QPlatformGLContext::doneCurrent(); + glXMakeCurrent(m_display, 0, 0); } -void QWaylandReadbackGlxContext::swapBuffers() +void QWaylandReadbackGlxContext::swapBuffers(const QPlatformGLSurface &surface) { - if (QWindowContext::currentContext().handle() != this) { - makeCurrent(); - } + // #### makeCurrent() directly on the platform context doesn't update QGuiGLContext::currentContext() + if (QGuiGLContext::currentContext()->handle() != this) + makeCurrent(surface, surface); - QSize size = mWindow->geometry().size(); + const QWaylandReadbackGlxSurface &s = + static_cast(surface); - QImage img(size,QImage::Format_ARGB32); + QSize size = s.window()->geometry().size(); + + QImage img(size, QImage::Format_ARGB32); const uchar *constBits = img.bits(); void *pixels = const_cast(constBits); - glReadPixels(0,0, size.width(), size.height(), GL_RGBA,GL_UNSIGNED_BYTE, pixels); + glReadPixels(0, 0, size.width(), size.height(), GL_RGBA,GL_UNSIGNED_BYTE, pixels); img = img.mirrored(); - qgl_byteSwapImage(img,GL_UNSIGNED_INT_8_8_8_8_REV); + qgl_byteSwapImage(img, GL_UNSIGNED_INT_8_8_8_8_REV); constBits = img.bits(); - const uchar *constDstBits = mBuffer->image()->bits(); + const uchar *constDstBits = s.window()->buffer(); uchar *dstBits = const_cast(constDstBits); - memcpy(dstBits,constBits,(img.width()*4) * img.height()); - - - mWindow->damage(QRegion(QRect(QPoint(0,0),size))); - mWindow->waitForFrameSync(); + memcpy(dstBits, constBits, (img.width() * 4) * img.height()); + s.window()->damage(QRect(QPoint(), size)); + s.window()->waitForFrameSync(); } -void * QWaylandReadbackGlxContext::getProcAddress(const QString &procName) +void (*QWaylandReadbackGlxContext::getProcAddress(const QByteArray &procName)) () { - return (void *) glXGetProcAddress(reinterpret_cast(procName.toLatin1().data())); -} - -QPlatformWindowFormat QWaylandReadbackGlxContext::platformWindowFormat() const -{ - return qglx_platformWindowFromGLXFBConfig(mGlxIntegration->xDisplay(),mConfig,mContext); -} - -void QWaylandReadbackGlxContext::geometryChanged() -{ - QSize size(mWindow->geometry().size()); - if (size.isEmpty()) { - //QGLWidget wants a context for a window without geometry - size = QSize(1,1); - } - - mWindow->waitForFrameSync(); - - delete mBuffer; - //XFreePixmap deletes the glxPixmap as well - if (mPixmap) { - XFreePixmap(mGlxIntegration->xDisplay(),mPixmap); - } - - mBuffer = new QWaylandShmBuffer(mGlxIntegration->waylandDisplay(),size,QImage::Format_ARGB32); - mWindow->attach(mBuffer); - int depth = XDefaultDepth(mGlxIntegration->xDisplay(),mGlxIntegration->screen()); - mPixmap = XCreatePixmap(mGlxIntegration->xDisplay(),mGlxIntegration->rootWindow(),size.width(),size.height(),depth); - XSync(mGlxIntegration->xDisplay(),False); - - mGlxPixmap = glXCreatePixmap(mGlxIntegration->xDisplay(),mConfig,mPixmap,0); - - if (!mGlxPixmap) { - qDebug() << "Could not make egl surface out of pixmap :("; - } + return glXGetProcAddress(reinterpret_cast(procName.constData())); } diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.h b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.h index 07e0f620de..27a7287b07 100644 --- a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.h +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.h @@ -43,6 +43,7 @@ #define QWAYLANDREADBACKGLXCONTEXT_H #include +#include #include "qwaylandreadbackglxintegration.h" @@ -51,29 +52,37 @@ class QWaylandReadbackGlxWindow; class QWaylandShmBuffer; +class QWaylandReadbackGlxSurface : public QPlatformGLSurface +{ +public: + QWaylandReadbackGlxSurface(QWaylandReadbackGlxWindow *window); + + QWaylandReadbackGlxWindow *window() const { return m_window; } + GLXPixmap glxPixmap() const; + +private: + QWaylandReadbackGlxWindow *m_window; +}; + class QWaylandReadbackGlxContext : public QPlatformGLContext { public: - QWaylandReadbackGlxContext(QWaylandReadbackGlxIntegration *glxIntegration, QWaylandReadbackGlxWindow *window); + QWaylandReadbackGlxContext(const QGuiGLFormat &format, QPlatformGLContext *share, Display *display, int screen); - void makeCurrent(); - void doneCurrent(); - void swapBuffers(); - void* getProcAddress(const QString& procName); + QGuiGLFormat format() const; - QPlatformWindowFormat platformWindowFormat() const; + void swapBuffers(const QPlatformGLSurface &surface); - void geometryChanged(); + bool makeCurrent(const QPlatformGLSurface &surface); + void doneCurrent(); + + void (*getProcAddress(const QByteArray &procName)) (); private: - QWaylandReadbackGlxIntegration *mGlxIntegration; - QWaylandReadbackGlxWindow *mWindow; - QWaylandShmBuffer *mBuffer; - - Pixmap mPixmap; - GLXFBConfig mConfig; - GLXContext mContext; - GLXPixmap mGlxPixmap; + GLXContext m_context; + + Display *m_display; + QGuiGLFormat m_format; }; #endif // QWAYLANDREADBACKGLXCONTEXT_H diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.cpp b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.cpp index e17e3f87a0..6fb2a178c8 100644 --- a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.cpp +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.cpp @@ -71,6 +71,11 @@ QWaylandWindow * QWaylandReadbackGlxIntegration::createEglWindow(QWindow *window return new QWaylandReadbackGlxWindow(window,this); } +QPlatformGLContext *QWaylandReadbackGlxIntegration::createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const +{ + return new QWaylandReadbackGlxContext(glFormat, share, mDisplay, mScreen); +} + QWaylandGLIntegration * QWaylandGLIntegration::createGLIntegration(QWaylandDisplay *waylandDisplay) { return new QWaylandReadbackGlxIntegration(waylandDisplay); diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.h b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.h index 3055169c0a..0b3d0cc2cc 100644 --- a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.h +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.h @@ -61,6 +61,7 @@ public: void initialize(); QWaylandWindow *createEglWindow(QWindow *window); + QPlatformGLContext *createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const; QWaylandDisplay *waylandDisplay() const; diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.cpp b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.cpp index b70ed43e69..f878bef0c4 100644 --- a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.cpp +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.cpp @@ -39,12 +39,19 @@ ** ****************************************************************************/ +#include + #include "qwaylandreadbackglxwindow.h" +#include "qwaylandshmsurface.h" + QWaylandReadbackGlxWindow::QWaylandReadbackGlxWindow(QWindow *window, QWaylandReadbackGlxIntegration *glxIntegration) : QWaylandShmWindow(window) - , mGlxIntegration(glxIntegration) - , mContext(0) + , m_glxIntegration(glxIntegration) + , m_buffer(0) + , m_pixmap(0) + , m_config(qglx_findConfig(glxIntegration->xDisplay(), glxIntegration->screen(), window->glFormat())) + , m_glxPixmap(0) { } @@ -54,20 +61,51 @@ QWaylandWindow::WindowType QWaylandReadbackGlxWindow::windowType() const return QWaylandWindow::Egl; } -QPlatformGLContext * QWaylandReadbackGlxWindow::glContext() const +void QWaylandReadbackGlxWindow::setGeometry(const QRect &rect) { - if (!mContext) { - QWaylandReadbackGlxWindow *that = const_cast(this); - that->mContext = new QWaylandReadbackGlxContext(mGlxIntegration,that); + QWaylandShmWindow::setGeometry(rect); + + if (m_pixmap) { + delete mBuffer; + //XFreePixmap deletes the glxPixmap as well + XFreePixmap(m_glxIntegration->xDisplay(), m_pixmap); + m_pixmap = 0; } - return mContext; } -void QWaylandReadbackGlxWindow::setGeometry(const QRect &rect) +GLXPixmap QWaylandReadbackGlxWindow::glxPixmap() const { - QWaylandShmWindow::setGeometry(rect); + if (!m_pixmap) + const_cast(this)->createSurface(); - if (mContext) { - mContext->geometryChanged(); + return m_glxPixmap; +} + +uchar *QWaylandReadbackGlxWindow::buffer() +{ + return m_buffer->image()->bits(); +} + +void QWaylandReadbackGlxWindow::createSurface() +{ + QSize size(geometry().size()); + if (size.isEmpty()) { + //QGLWidget wants a context for a window without geometry + size = QSize(1,1); } + + waitForFrameSync(); + + m_buffer = new QWaylandShmBuffer(m_glxIntegration->waylandDisplay(), size, QImage::Format_ARGB32); + attach(m_buffer); + + int depth = XDefaultDepth(m_glxIntegration->xDisplay(), m_glxIntegration->screen()); + m_pixmap = XCreatePixmap(m_glxIntegration->xDisplay(), m_glxIntegration->rootWindow(), size.width(), size.height(), depth); + XSync(m_glxIntegration->xDisplay(), False); + + m_glxPixmap = glXCreatePixmap(m_glxIntegration->xDisplay(), m_config, m_pixmap,0); + + if (!m_glxPixmap) + qDebug() << "Could not make glx surface out of pixmap :("; } + diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.h b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.h index 3f20a0e2fc..60b22a4408 100644 --- a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.h +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.h @@ -52,14 +52,23 @@ public: QWaylandReadbackGlxWindow(QWindow *window, QWaylandReadbackGlxIntegration *glxIntegration); WindowType windowType() const; - QPlatformGLContext *glContext() const; + QPlatformGLSurface *createGLSurface() const; void setGeometry(const QRect &rect); + Pixmap glxPixmap() const; + + uchar *buffer(); + private: - QWaylandReadbackGlxIntegration *mGlxIntegration; - QWaylandReadbackGlxContext *mContext; + void createSurface(); + + QWaylandReadbackGlxIntegration *m_glxIntegration; + QWaylandShmBuffer *m_buffer; + Pixmap m_pixmap; + GLXFBConfig m_config; + GLXPixmap m_glxPixmap; }; #endif // QWAYLANDREADBACKGLXWINDOW_H diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.cpp index e61ee69d37..08b6f76daf 100644 --- a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.cpp +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.cpp @@ -42,127 +42,37 @@ #include "qwaylandxcompositeeglcontext.h" #include "qwaylandxcompositeeglwindow.h" -#include "qwaylandxcompositebuffer.h" -#include "wayland-xcomposite-client-protocol.h" #include #include #include "qeglconvenience.h" -#include "qxlibeglintegration.h" -#include - -QWaylandXCompositeEGLContext::QWaylandXCompositeEGLContext(QWaylandXCompositeEGLIntegration *glxIntegration, QWaylandXCompositeEGLWindow *window) - : QPlatformGLContext() - , mEglIntegration(glxIntegration) - , mWindow(window) - , mBuffer(0) - , mXWindow(0) - , mConfig(q_configFromQWindowFormat(glxIntegration->eglDisplay(),window->window()->requestedWindowFormat(),true,EGL_WINDOW_BIT)) - , mWaitingForSync(false) -{ - QVector eglContextAttrs; - eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); eglContextAttrs.append(2); - eglContextAttrs.append(EGL_NONE); - - mContext = eglCreateContext(glxIntegration->eglDisplay(),mConfig,EGL_NO_CONTEXT,eglContextAttrs.constData()); - if (mContext == EGL_NO_CONTEXT) { - qFatal("failed to find context"); - } - - geometryChanged(); -} - -void QWaylandXCompositeEGLContext::makeCurrent() +QWaylandXCompositeEGLSurface::QWaylandXCompositeEGLSurface(QWaylandXCompositeEGLWindow *window) + : QEGLSurface(window->eglSurface(), window->window()->glFormat()) + , m_window(window) { - eglMakeCurrent(mEglIntegration->eglDisplay(),mEglWindowSurface,mEglWindowSurface,mContext); } -void QWaylandXCompositeEGLContext::doneCurrent() +EGLSurface QWaylandXCompositeEGLSurface::eglSurface() const { - QPlatformGLContext::doneCurrent(); - eglMakeCurrent(mEglIntegration->eglDisplay(),EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT); + return m_window->eglSurface(); } -void QWaylandXCompositeEGLContext::swapBuffers() +QWaylandXCompositeEGLContext::QWaylandXCompositeEGLContext(const QGuiGLFormat &format, QPlatformGLContext *share, EGLDisplay display) + : QEGLPlatformContext(format, share, display) { - QSize size = mWindow->geometry().size(); - - eglSwapBuffers(mEglIntegration->eglDisplay(),mEglWindowSurface); - mWindow->damage(QRegion(QRect(QPoint(0,0),size))); - mWindow->waitForFrameSync(); -} - -void * QWaylandXCompositeEGLContext::getProcAddress(const QString &procName) -{ - return (void *)eglGetProcAddress(qPrintable(procName)); } -QWindowFormat QWaylandXCompositeEGLContext::windowFormat() const +void QWaylandXCompositeEGLContext::swapBuffers(const QPlatformGLSurface &surface) { - return q_windowFormatFromConfig(mEglIntegration->eglDisplay(),mConfig); -} - -void QWaylandXCompositeEGLContext::sync_function(void *data) -{ - QWaylandXCompositeEGLContext *that = static_cast(data); - that->mWaitingForSync = false; -} - -void QWaylandXCompositeEGLContext::geometryChanged() -{ - QSize size(mWindow->geometry().size()); - if (size.isEmpty()) { - //QGLWidget wants a context for a window without geometry - size = QSize(1,1); - } - - delete mBuffer; - //XFreePixmap deletes the glxPixmap as well - if (mXWindow) { - XDestroyWindow(mEglIntegration->xDisplay(),mXWindow); - } - - VisualID visualId = QXlibEglIntegration::getCompatibleVisualId(mEglIntegration->xDisplay(),mEglIntegration->eglDisplay(),mConfig); - - XVisualInfo visualInfoTemplate; - memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); - visualInfoTemplate.visualid = visualId; - - int matchingCount = 0; - XVisualInfo *visualInfo = XGetVisualInfo(mEglIntegration->xDisplay(), VisualIDMask, &visualInfoTemplate, &matchingCount); - - Colormap cmap = XCreateColormap(mEglIntegration->xDisplay(),mEglIntegration->rootWindow(),visualInfo->visual,AllocNone); - - XSetWindowAttributes a; - a.colormap = cmap; - mXWindow = XCreateWindow(mEglIntegration->xDisplay(), mEglIntegration->rootWindow(),0, 0, size.width(), size.height(), - 0, visualInfo->depth, InputOutput, visualInfo->visual, - CWColormap, &a); - - XCompositeRedirectWindow(mEglIntegration->xDisplay(), mXWindow, CompositeRedirectManual); - XMapWindow(mEglIntegration->xDisplay(), mXWindow); + QEGLPlatformContext::swapBuffers(surface); - mEglWindowSurface = eglCreateWindowSurface(mEglIntegration->eglDisplay(),mConfig,mXWindow,0); - if (mEglWindowSurface == EGL_NO_SURFACE) { - qFatal("Could not make eglsurface"); - } + const QWaylandXCompositeEGLSurface &s = + static_cast(surface); - XSync(mEglIntegration->xDisplay(),False); - mBuffer = new QWaylandXCompositeBuffer(mEglIntegration->waylandXComposite(), - (uint32_t)mXWindow, - size, - mEglIntegration->waylandDisplay()->argbVisual()); - mWindow->attach(mBuffer); - wl_display_sync_callback(mEglIntegration->waylandDisplay()->wl_display(), - QWaylandXCompositeEGLContext::sync_function, - this); + QSize size = s.window()->geometry().size(); - mWaitingForSync = true; - wl_display_sync(mEglIntegration->waylandDisplay()->wl_display(),0); - mEglIntegration->waylandDisplay()->flushRequests(); - while (mWaitingForSync) { - mEglIntegration->waylandDisplay()->readEvents(); - } + s.window()->damage(QRect(QPoint(), size)); + s.window()->waitForFrameSync(); } diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.h index 528faf07c5..bd7039f284 100644 --- a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.h +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.h @@ -44,37 +44,29 @@ #include -#include "qwaylandbuffer.h" #include "qwaylandxcompositeeglintegration.h" +#include "qeglplatformcontext.h" + class QWaylandXCompositeEGLWindow; -class QWaylandXCompositeEGLContext : public QPlatformGLContext +class QWaylandXCompositeEGLSurface : public QEGLSurface { public: - QWaylandXCompositeEGLContext(QWaylandXCompositeEGLIntegration *glxIntegration, QWaylandXCompositeEGLWindow *window); - - void makeCurrent(); - void doneCurrent(); - void swapBuffers(); - void* getProcAddress(const QString& procName); - - QWindowFormat windowFormat() const; - - void geometryChanged(); + QWaylandXCompositeEGLSurface(QWaylandXCompositeEGLWindow *window); + EGLSurface eglSurface() const; + QWaylandXCompositeEGLWindow *window() const { return m_window; } private: - QWaylandXCompositeEGLIntegration *mEglIntegration; - QWaylandXCompositeEGLWindow *mWindow; - QWaylandBuffer *mBuffer; + QWaylandXCompositeEGLWindow *m_window; +}; - Window mXWindow; - EGLConfig mConfig; - EGLContext mContext; - EGLSurface mEglWindowSurface; +class QWaylandXCompositeEGLContext : public QEGLPlatformContext +{ +public: + QWaylandXCompositeEGLContext(const QGuiGLFormat &format, QPlatformGLContext *share, EGLDisplay display); - static void sync_function(void *data); - bool mWaitingForSync; + void swapBuffers(const QPlatformGLSurface &surface); }; #endif // QWAYLANDXCOMPOSITEEGLCONTEXT_H diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.cpp index 239ec8963d..90d5bea770 100644 --- a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.cpp +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.cpp @@ -75,6 +75,11 @@ QWaylandWindow * QWaylandXCompositeEGLIntegration::createEglWindow(QWindow *wind return new QWaylandXCompositeEGLWindow(window,this); } +QPlatformGLContext *QWaylandXCompositeEGLIntegration::createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const +{ + return new QWaylandXCompositeEGLContext(glFormat, share, eglDisplay()); +} + Display * QWaylandXCompositeEGLIntegration::xDisplay() const { return mDisplay; diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.h index 3252ce741e..ac302ef89f 100644 --- a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.h +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.h @@ -51,6 +51,8 @@ #include #include +#include + #include #include @@ -67,6 +69,7 @@ public: void initialize(); QWaylandWindow *createEglWindow(QWindow *window); + QPlatformGLContext *createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const; QWaylandDisplay *waylandDisplay() const; struct wl_xcomposite *waylandXComposite() const; diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp index e57203f772..5c6717eb0c 100644 --- a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp @@ -40,15 +40,27 @@ ****************************************************************************/ #include "qwaylandxcompositeeglwindow.h" +#include "qwaylandxcompositebuffer.h" + +#include "qeglconvenience.h" + +#include "wayland-xcomposite-client-protocol.h" +#include "qxlibeglintegration.h" + +#include #include QWaylandXCompositeEGLWindow::QWaylandXCompositeEGLWindow(QWindow *window, QWaylandXCompositeEGLIntegration *glxIntegration) : QWaylandWindow(window) - , mGlxIntegration(glxIntegration) - , mContext(0) + , m_glxIntegration(glxIntegration) + , m_context(0) + , m_buffer(0) + , m_xWindow(0) + , m_config(q_configFromGLFormat(glxIntegration->eglDisplay(), window->glFormat(), true)) + , m_surface(0) + , m_waitingForSync(false) { - } QWaylandWindow::WindowType QWaylandXCompositeEGLWindow::windowType() const @@ -57,21 +69,86 @@ QWaylandWindow::WindowType QWaylandXCompositeEGLWindow::windowType() const return QWaylandWindow::Egl; } -QPlatformGLContext * QWaylandXCompositeEGLWindow::glContext() const +QPlatformGLSurface *QWaylandXCompositeEGLWindow::createGLSurface() const { - if (!mContext) { - qDebug() << "creating glcontext;"; - QWaylandXCompositeEGLWindow *that = const_cast(this); - that->mContext = new QWaylandXCompositeEGLContext(mGlxIntegration,that); - } - return mContext; + return new QWaylandXCompositeEGLSurface(const_cast(this)); } void QWaylandXCompositeEGLWindow::setGeometry(const QRect &rect) { QWaylandWindow::setGeometry(rect); - if (mContext) { - mContext->geometryChanged(); + if (m_surface) { + eglDestroySurface(m_glxIntegration->eglDisplay(), m_surface); + m_surface = 0; + } +} + +EGLSurface QWaylandXCompositeEGLWindow::eglSurface() const +{ + if (!m_surface) + const_cast(this)->createEglSurface(); + return m_surface; +} + +void QWaylandXCompositeEGLWindow::createEglSurface() +{ + QSize size(geometry().size()); + if (size.isEmpty()) { + // QGLWidget wants a context for a window without geometry + size = QSize(1,1); + } + + delete m_buffer; + //XFreePixmap deletes the glxPixmap as well + if (m_xWindow) { + XDestroyWindow(m_glxIntegration->xDisplay(), m_xWindow); } + + VisualID visualId = QXlibEglIntegration::getCompatibleVisualId(m_glxIntegration->xDisplay(), m_glxIntegration->eglDisplay(), m_config); + + XVisualInfo visualInfoTemplate; + memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); + visualInfoTemplate.visualid = visualId; + + int matchingCount = 0; + XVisualInfo *visualInfo = XGetVisualInfo(m_glxIntegration->xDisplay(), VisualIDMask, &visualInfoTemplate, &matchingCount); + + Colormap cmap = XCreateColormap(m_glxIntegration->xDisplay(),m_glxIntegration->rootWindow(),visualInfo->visual,AllocNone); + + XSetWindowAttributes a; + a.colormap = cmap; + m_xWindow = XCreateWindow(m_glxIntegration->xDisplay(), m_glxIntegration->rootWindow(),0, 0, size.width(), size.height(), + 0, visualInfo->depth, InputOutput, visualInfo->visual, + CWColormap, &a); + + XCompositeRedirectWindow(m_glxIntegration->xDisplay(), m_xWindow, CompositeRedirectManual); + XMapWindow(m_glxIntegration->xDisplay(), m_xWindow); + + m_surface = eglCreateWindowSurface(m_glxIntegration->eglDisplay(), m_config, m_xWindow,0); + if (m_surface == EGL_NO_SURFACE) { + qFatal("Could not make eglsurface"); + } + + XSync(m_glxIntegration->xDisplay(),False); + mBuffer = new QWaylandXCompositeBuffer(m_glxIntegration->waylandXComposite(), + (uint32_t)m_xWindow, + size, + m_glxIntegration->waylandDisplay()->argbVisual()); + attach(m_buffer); + wl_display_sync_callback(m_glxIntegration->waylandDisplay()->wl_display(), + QWaylandXCompositeEGLWindow::sync_function, + this); + + m_waitingForSync = true; + wl_display_sync(m_glxIntegration->waylandDisplay()->wl_display(),0); + m_glxIntegration->waylandDisplay()->flushRequests(); + while (m_waitingForSync) + m_glxIntegration->waylandDisplay()->readEvents(); +} + +void QWaylandXCompositeEGLWindow::sync_function(void *data) +{ + QWaylandXCompositeEGLWindow *that = static_cast(data); + that->m_waitingForSync = false; } diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h index 6efe556fb5..16188ca3e0 100644 --- a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h @@ -43,6 +43,8 @@ #define QWAYLANDXCOMPOSITEEGLWINDOW_H #include "qwaylandwindow.h" +#include "qwaylandbuffer.h" + #include "qwaylandxcompositeeglintegration.h" #include "qwaylandxcompositeeglcontext.h" @@ -52,14 +54,26 @@ public: QWaylandXCompositeEGLWindow(QWindow *window, QWaylandXCompositeEGLIntegration *glxIntegration); WindowType windowType() const; - QPlatformGLContext *glContext() const; + QPlatformGLSurface *createGLSurface() const; void setGeometry(const QRect &rect); + EGLSurface eglSurface() const; + private: - QWaylandXCompositeEGLIntegration *mGlxIntegration; - QWaylandXCompositeEGLContext *mContext; + void createEglSurface(); + + QWaylandXCompositeEGLIntegration *m_glxIntegration; + QWaylandXCompositeEGLContext *m_context; + QWaylandBuffer *m_buffer; + + Window m_xWindow; + EGLConfig m_config; + EGLSurface m_surface; + + bool m_waitingForSync; + static void sync_function(void *data); }; #endif // QWAYLANDXCOMPOSITEEGLWINDOW_H diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/xcomposite_egl.pri b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/xcomposite_egl.pri index 7d2f8ad443..a61391b2d1 100644 --- a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/xcomposite_egl.pri +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/xcomposite_egl.pri @@ -1,5 +1,6 @@ include (../xcomposite_share/xcomposite_share.pri) load(qpa/egl/convenience) +load(qpa/egl/context) load(qpa/egl/xlibintegration) LIBS += -lXcomposite -lEGL diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.cpp index aa26971021..5d4cf7a567 100644 --- a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.cpp +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.cpp @@ -39,114 +39,67 @@ ** ****************************************************************************/ +#include + #include "qwaylandxcompositeglxcontext.h" #include "qwaylandxcompositeglxwindow.h" -#include "qwaylandxcompositebuffer.h" -#include "wayland-xcomposite-client-protocol.h" -#include -#include - -#include - -QWaylandXCompositeGLXContext::QWaylandXCompositeGLXContext(QWaylandXCompositeGLXIntegration *glxIntegration, QWaylandXCompositeGLXWindow *window) - : QPlatformGLContext() - , mGlxIntegration(glxIntegration) - , mWindow(window) - , mBuffer(0) - , mXWindow(0) - , mConfig(qglx_findConfig(glxIntegration->xDisplay(),glxIntegration->screen(),window->window()->requestedWindowFormat())) - , mWaitingForSyncCallback(false) -{ - XVisualInfo *visualInfo = glXGetVisualFromFBConfig(glxIntegration->xDisplay(),mConfig); - mContext = glXCreateContext(glxIntegration->xDisplay(),visualInfo,0,TRUE); +#include - geometryChanged(); -} - -void QWaylandXCompositeGLXContext::makeCurrent() +QWaylandXCompositeGLXSurface::QWaylandXCompositeGLXSurface(QWaylandXCompositeGLXWindow *window) + : m_window(window) { - glXMakeCurrent(mGlxIntegration->xDisplay(),mXWindow,mContext); } -void QWaylandXCompositeGLXContext::doneCurrent() +Window QWaylandXCompositeGLXSurface::xWindow() const { - glXMakeCurrent(mGlxIntegration->xDisplay(),0,0); - QPlatformGLContext::doneCurrent(); + return m_window->xWindow(); } -void QWaylandXCompositeGLXContext::swapBuffers() +QWaylandXCompositeGLXContext::QWaylandXCompositeGLXContext(const QGuiGLFormat &format, QPlatformGLContext *share, Display *display, int screen) + : m_display(display) { - QSize size = mWindow->geometry().size(); + GLXContext shareContext = share ? static_cast(share)->m_context : 0; - glXSwapBuffers(mGlxIntegration->xDisplay(),mXWindow); - mWindow->damage(QRegion(QRect(QPoint(0,0),size))); - mWindow->waitForFrameSync(); + GLXFBConfig config = qglx_findConfig(display, screen, format); + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(display, config); + m_context = glXCreateContext(display, visualInfo, shareContext, true); + m_format = qglx_guiGLFormatFromGLXFBConfig(display, config, m_context); } -void * QWaylandXCompositeGLXContext::getProcAddress(const QString &procName) +bool QWaylandXCompositeGLXContext::makeCurrent(const QPlatformGLSurface &surface) { - return (void *) glXGetProcAddress(reinterpret_cast(procName.toLatin1().data())); + Window xWindow = static_cast(surface).xWindow(); + + return glXMakeCurrent(m_display, xWindow, m_context); } -QWindowFormat QWaylandXCompositeGLXContext::windowFormat() const +void QWaylandXCompositeGLXContext::doneCurrent() { - return qglx_platformWindowFromGLXFBConfig(mGlxIntegration->xDisplay(),mConfig,mContext); + glXMakeCurrent(m_display, 0, 0); } -void QWaylandXCompositeGLXContext::sync_function(void *data) +void QWaylandXCompositeGLXContext::swapBuffers(const QPlatformGLSurface &surface) { - QWaylandXCompositeGLXContext *that = static_cast(data); - that->mWaitingForSyncCallback = false; + const QWaylandXCompositeGLXSurface &s = + static_cast(surface); + + QSize size = s.window()->geometry().size(); + + glXSwapBuffers(m_display, s.xWindow()); + + s.window()->damage(QRect(QPoint(), size)); + s.window()->waitForFrameSync(); } -void QWaylandXCompositeGLXContext::waitForSync() +void (*QWaylandXCompositeGLXContext::getProcAddress(const QByteArray &procName)) () { - wl_display_sync_callback(mGlxIntegration->waylandDisplay()->wl_display(), - QWaylandXCompositeGLXContext::sync_function, - this); - mWaitingForSyncCallback = true; - wl_display_sync(mGlxIntegration->waylandDisplay()->wl_display(),0); - mGlxIntegration->waylandDisplay()->flushRequests(); - while (mWaitingForSyncCallback) { - mGlxIntegration->waylandDisplay()->readEvents(); - } + return glXGetProcAddress(reinterpret_cast(procName.constData())); } -void QWaylandXCompositeGLXContext::geometryChanged() +QGuiGLFormat QWaylandXCompositeGLXContext::format() const { - QSize size(mWindow->geometry().size()); - if (size.isEmpty()) { - //QGLWidget wants a context for a window without geometry - size = QSize(1,1); - } - - delete mBuffer; - //XFreePixmap deletes the glxPixmap as well - if (mXWindow) { - XDestroyWindow(mGlxIntegration->xDisplay(),mXWindow); - } - - XVisualInfo *visualInfo = glXGetVisualFromFBConfig(mGlxIntegration->xDisplay(),mConfig); - Colormap cmap = XCreateColormap(mGlxIntegration->xDisplay(),mGlxIntegration->rootWindow(),visualInfo->visual,AllocNone); - - XSetWindowAttributes a; - a.background_pixel = WhitePixel(mGlxIntegration->xDisplay(), mGlxIntegration->screen()); - a.border_pixel = BlackPixel(mGlxIntegration->xDisplay(), mGlxIntegration->screen()); - a.colormap = cmap; - mXWindow = XCreateWindow(mGlxIntegration->xDisplay(), mGlxIntegration->rootWindow(),0, 0, size.width(), size.height(), - 0, visualInfo->depth, InputOutput, visualInfo->visual, - CWBackPixel|CWBorderPixel|CWColormap, &a); - - XCompositeRedirectWindow(mGlxIntegration->xDisplay(), mXWindow, CompositeRedirectManual); - XMapWindow(mGlxIntegration->xDisplay(), mXWindow); - - XSync(mGlxIntegration->xDisplay(),False); - mBuffer = new QWaylandXCompositeBuffer(mGlxIntegration->waylandXComposite(), - (uint32_t)mXWindow, - size, - mGlxIntegration->waylandDisplay()->argbVisual()); - mWindow->attach(mBuffer); - waitForSync(); + return m_format; } + diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.h index 49ae73de40..e0de801a5e 100644 --- a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.h +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.h @@ -44,42 +44,44 @@ #include -#include - -#include "qwaylandbuffer.h" #include "qwaylandxcompositeglxintegration.h" - #include "qglxconvenience.h" class QWaylandXCompositeGLXWindow; class QWaylandShmBuffer; +class QWaylandXCompositeGLXSurface : public QPlatformGLSurface +{ +public: + QWaylandXCompositeGLXSurface(QWaylandXCompositeGLXWindow *window); + + QWaylandXCompositeGLXWindow *window() const { return m_window; } + Window xWindow() const; + +private: + QWaylandXCompositeGLXWindow *m_window; +}; + + class QWaylandXCompositeGLXContext : public QPlatformGLContext { public: - QWaylandXCompositeGLXContext(QWaylandXCompositeGLXIntegration *glxIntegration, QWaylandXCompositeGLXWindow *window); + QWaylandXCompositeGLXContext(const QGuiGLFormat &format, QPlatformGLContext *share, Display *display, int screen); - void makeCurrent(); - void doneCurrent(); - void swapBuffers(); - void* getProcAddress(const QString& procName); + QGuiGLFormat format() const; - QWindowFormat windowFormat() const; + void swapBuffers(const QPlatformGLSurface &surface); - void geometryChanged(); + bool makeCurrent(const QPlatformGLSurface &surface); + void doneCurrent(); -private: - QWaylandXCompositeGLXIntegration *mGlxIntegration; - QWaylandXCompositeGLXWindow *mWindow; - QWaylandBuffer *mBuffer; + void (*getProcAddress(const QByteArray &procName)) (); - Window mXWindow; - GLXFBConfig mConfig; - GLXContext mContext; +private: + GLXContext m_context; - static void sync_function(void *data); - void waitForSync(); - bool mWaitingForSyncCallback; + Display *m_display; + QGuiGLFormat m_format; }; #endif // QWAYLANDXCOMPOSITEGLXCONTEXT_H diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.cpp index e5f4feb436..a80a595768 100644 --- a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.cpp +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.cpp @@ -72,7 +72,12 @@ void QWaylandXCompositeGLXIntegration::initialize() QWaylandWindow * QWaylandXCompositeGLXIntegration::createEglWindow(QWindow *window) { - return new QWaylandXCompositeGLXWindow(window,this); + return new QWaylandXCompositeGLXWindow(window, this); +} + +QPlatformGLContext *QWaylandXCompositeGLXIntegration::createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const +{ + return new QWaylandXCompositeGLXContext(glFormat, share, mDisplay, mScreen); } Display * QWaylandXCompositeGLXIntegration::xDisplay() const diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.h index f934a9a4d2..c347b110c6 100644 --- a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.h +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.h @@ -64,6 +64,7 @@ public: void initialize(); QWaylandWindow *createEglWindow(QWindow *window); + QPlatformGLContext *createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const; QWaylandDisplay *waylandDisplay() const; struct wl_xcomposite *waylandXComposite() const; diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.cpp index 6eec1d4eb8..41a14e3f66 100644 --- a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.cpp +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.cpp @@ -40,15 +40,24 @@ ****************************************************************************/ #include "qwaylandxcompositeglxwindow.h" +#include "qwaylandxcompositebuffer.h" #include +#include "wayland-xcomposite-client-protocol.h" +#include + +#include + + QWaylandXCompositeGLXWindow::QWaylandXCompositeGLXWindow(QWindow *window, QWaylandXCompositeGLXIntegration *glxIntegration) : QWaylandWindow(window) - , mGlxIntegration(glxIntegration) - , mContext(0) + , m_glxIntegration(glxIntegration) + , m_xWindow(0) + , m_config(qglx_findConfig(glxIntegration->xDisplay(), glxIntegration->screen(), window->glFormat())) + , m_buffer(0) + , m_waitingForSync(false) { - } QWaylandWindow::WindowType QWaylandXCompositeGLXWindow::windowType() const @@ -57,21 +66,79 @@ QWaylandWindow::WindowType QWaylandXCompositeGLXWindow::windowType() const return QWaylandWindow::Egl; } -QPlatformGLContext * QWaylandXCompositeGLXWindow::glContext() const +QPlatformGLSurface *QWaylandXCompositeGLXWindow::createGLSurface() const { - if (!mContext) { - qDebug() << "creating glcontext;"; - QWaylandXCompositeGLXWindow *that = const_cast(this); - that->mContext = new QWaylandXCompositeGLXContext(mGlxIntegration,that); - } - return mContext; + return new QWaylandXCompositeGLXSurface(const_cast(this)); } void QWaylandXCompositeGLXWindow::setGeometry(const QRect &rect) { QWaylandWindow::setGeometry(rect); - if (mContext) { - mContext->geometryChanged(); + if (m_xWindow) { + delete m_buffer; + + XDestroyWindow(m_glxIntegration->xDisplay(), m_xWindow); + m_xWindow = 0; + } +} + +Window QWaylandXCompositeGLXWindow::xWindow() const +{ + if (!m_xWindow) + const_cast(this)->createSurface(); + + return m_xWindow; +} + +void QWaylandXCompositeGLXWindow::waitForSync() +{ + wl_display_sync_callback(m_glxIntegration->waylandDisplay()->wl_display(), + QWaylandXCompositeGLXWindow::sync_function, + this); + m_waitingForSync= true; + wl_display_sync(m_glxIntegration->waylandDisplay()->wl_display(), 0); + m_glxIntegration->waylandDisplay()->flushRequests(); + while (m_waitingForSync) + m_glxIntegration->waylandDisplay()->readEvents(); +} + + +void QWaylandXCompositeGLXWindow::createSurface() +{ + QSize size(geometry().size()); + if (size.isEmpty()) { + //QGLWidget wants a context for a window without geometry + size = QSize(1,1); } + + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(m_glxIntegration->xDisplay(), m_config); + Colormap cmap = XCreateColormap(m_glxIntegration->xDisplay(), m_glxIntegration->rootWindow(), + visualInfo->visual, AllocNone); + + XSetWindowAttributes a; + a.background_pixel = WhitePixel(m_glxIntegration->xDisplay(), m_glxIntegration->screen()); + a.border_pixel = BlackPixel(m_glxIntegration->xDisplay(), m_glxIntegration->screen()); + a.colormap = cmap; + m_xWindow = XCreateWindow(m_glxIntegration->xDisplay(), m_glxIntegration->rootWindow(),0, 0, size.width(), size.height(), + 0, visualInfo->depth, InputOutput, visualInfo->visual, + CWBackPixel|CWBorderPixel|CWColormap, &a); + + XCompositeRedirectWindow(m_glxIntegration->xDisplay(), m_xWindow, CompositeRedirectManual); + XMapWindow(m_glxIntegration->xDisplay(), m_xWindow); + + XSync(m_glxIntegration->xDisplay(), False); + m_buffer = new QWaylandXCompositeBuffer(m_glxIntegration->waylandXComposite(), + (uint32_t)m_xWindow, + size, + m_glxIntegration->waylandDisplay()->argbVisual()); + attach(m_buffer); + waitForSync(); +} + +void QWaylandXCompositeGLXWindow::sync_function(void *data) +{ + QWaylandXCompositeGLXWindow *that = static_cast(data); + that->m_waitingForSync = false; } + diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.h index 3305c12fa7..7a19c7175a 100644 --- a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.h +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.h @@ -46,20 +46,36 @@ #include "qwaylandxcompositeglxintegration.h" #include "qwaylandxcompositeglxcontext.h" +#include + +#include "qwaylandbuffer.h" + class QWaylandXCompositeGLXWindow : public QWaylandWindow { public: QWaylandXCompositeGLXWindow(QWindow *window, QWaylandXCompositeGLXIntegration *glxIntegration); WindowType windowType() const; - QPlatformGLContext *glContext() const; + QPlatformGLSurface *createGLSurface() const; void setGeometry(const QRect &rect); + Window xWindow() const; + private: - QWaylandXCompositeGLXIntegration *mGlxIntegration; - QWaylandXCompositeGLXContext *mContext; + void createSurface(); + + QWaylandXCompositeGLXIntegration *m_glxIntegration; + + Window m_xWindow; + GLXFBConfig m_config; + + QWaylandBuffer *m_buffer; + + void waitForSync(); + bool m_waitingForSync; + static void sync_function(void *data); }; #endif // QWAYLANDXCOMPOSITEGLXWINDOW_H diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 9aa512b38d..226bfd44d5 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -51,7 +51,7 @@ #include #include -#include +#include #include #ifdef QT_WAYLAND_GL_SUPPORT @@ -108,6 +108,14 @@ QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWindow *window) cons return new QWaylandShmWindow(window); } +QPlatformGLContext *QWaylandIntegration::createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const +{ +#ifdef QT_WAYLAND_GL_SUPPORT + return mDisplay->eglIntegration()->createPlatformGLContext(glFormat, share); +#endif + return 0; +} + QWindowSurface *QWaylandIntegration::createWindowSurface(QWindow *window, WId winId) const { Q_UNUSED(winId); diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index 1ca468cca4..2e05faf677 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -57,6 +57,7 @@ public: bool hasCapability(QPlatformIntegration::Capability cap) const; QPixmapData *createPixmapData(QPixmapData::PixelType type) const; QPlatformWindow *createPlatformWindow(QWindow *window) const; + QPlatformGLContext *createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const; QWindowSurface *createWindowSurface(QWindow *window, WId winId) const; QList screens() const; diff --git a/src/plugins/platforms/wayland/qwaylandshmwindow.cpp b/src/plugins/platforms/wayland/qwaylandshmwindow.cpp index 087139e0b3..bd1e61fa4c 100644 --- a/src/plugins/platforms/wayland/qwaylandshmwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandshmwindow.cpp @@ -63,9 +63,9 @@ QWaylandWindow::WindowType QWaylandShmWindow::windowType() const return QWaylandWindow::Shm; } -QPlatformGLContext * QWaylandShmWindow::glContext() const +QPlatformGLSurface * QWaylandShmWindow::glSurface() const { - qWarning("Trying to retrieve a glContext from a Raster window surface!"); + qWarning("Raster window does not have a GL drawable"); return 0; } diff --git a/src/plugins/platforms/wayland/qwaylandshmwindow.h b/src/plugins/platforms/wayland/qwaylandshmwindow.h index e964e0d933..db26c5c928 100644 --- a/src/plugins/platforms/wayland/qwaylandshmwindow.h +++ b/src/plugins/platforms/wayland/qwaylandshmwindow.h @@ -52,7 +52,7 @@ public: ~QWaylandShmWindow(); WindowType windowType() const; - QPlatformGLContext *glContext() const; + QPlatformGLSurface *glSurface() const; }; #endif // QWAYLANDSHMWINDOW_H diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index 24d5d69ac7..67791080d5 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -50,7 +50,7 @@ #include #include -#include +#include #include "qglxintegration.h" #include "qglxconvenience.h" @@ -59,60 +59,61 @@ #include #endif -QGLXContext::QGLXContext(Window window, QXcbScreen *screen, const QWindowFormat &format) +QGLXSurface::QGLXSurface(GLXDrawable drawable, const QGuiGLFormat &format) + : QPlatformGLSurface(format) + , glxDrawable(drawable) +{ +} + +QGLXContext::QGLXContext(QXcbScreen *screen, const QGuiGLFormat &format, QPlatformGLContext *share) : QPlatformGLContext() , m_screen(screen) - , m_drawable((Drawable)window) , m_context(0) { Q_XCB_NOOP(m_screen->connection()); - const QWindowContext *shareContext = format.sharedContext(); GLXContext shareGlxContext = 0; - if (shareContext) - shareGlxContext = static_cast(shareContext->handle())->glxContext(); + if (share) + shareGlxContext = static_cast(share)->glxContext(); GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(screen),screen->screenNumber(),format); m_context = glXCreateNewContext(DISPLAY_FROM_XCB(screen), config, GLX_RGBA_TYPE, shareGlxContext, TRUE); - m_windowFormat = qglx_platformWindowFromGLXFBConfig(DISPLAY_FROM_XCB(screen), config, m_context); + m_format = qglx_guiGLFormatFromGLXFBConfig(DISPLAY_FROM_XCB(screen), config, m_context); Q_XCB_NOOP(m_screen->connection()); } -QGLXContext::QGLXContext(QXcbScreen *screen, Drawable drawable, GLXContext context) - : QPlatformGLContext(), m_screen(screen), m_drawable(drawable), m_context(context) -{ - -} - QGLXContext::~QGLXContext() { Q_XCB_NOOP(m_screen->connection()); - if (m_context) - glXDestroyContext(DISPLAY_FROM_XCB(m_screen), m_context); + glXDestroyContext(DISPLAY_FROM_XCB(m_screen), m_context); Q_XCB_NOOP(m_screen->connection()); } -void QGLXContext::makeCurrent() +bool QGLXContext::makeCurrent(const QPlatformGLSurface &surface) { Q_XCB_NOOP(m_screen->connection()); - glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), m_drawable, m_context); + + GLXDrawable glxSurface = static_cast(surface).glxDrawable; + + bool result = glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), glxSurface, m_context); + Q_XCB_NOOP(m_screen->connection()); + return result; } void QGLXContext::doneCurrent() { - Q_XCB_NOOP(m_screen->connection()); glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), 0, 0); - Q_XCB_NOOP(m_screen->connection()); } -void QGLXContext::swapBuffers() +void QGLXContext::swapBuffers(const QPlatformGLSurface &drawable) { Q_XCB_NOOP(m_screen->connection()); - glXSwapBuffers(DISPLAY_FROM_XCB(m_screen), m_drawable); + GLXDrawable glxDrawable = static_cast(drawable).glxDrawable; + glXSwapBuffers(DISPLAY_FROM_XCB(m_screen), glxDrawable); Q_XCB_NOOP(m_screen->connection()); } -void* QGLXContext::getProcAddress(const QString& procName) +void (*QGLXContext::getProcAddress(const QByteArray &procName)) () { Q_XCB_NOOP(m_screen->connection()); typedef void *(*qt_glXGetProcAddressARB)(const GLubyte *); @@ -143,10 +144,10 @@ void* QGLXContext::getProcAddress(const QString& procName) } if (!glXGetProcAddressARB) return 0; - return glXGetProcAddressARB(reinterpret_cast(procName.toLatin1().data())); + return (void (*)())glXGetProcAddressARB(reinterpret_cast(procName.constData())); } -QWindowFormat QGLXContext::windowFormat() const +QGuiGLFormat QGLXContext::format() const { - return m_windowFormat; + return m_format; } diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h index 1760521d47..ae95e23b81 100644 --- a/src/plugins/platforms/xcb/qglxintegration.h +++ b/src/plugins/platforms/xcb/qglxintegration.h @@ -45,34 +45,38 @@ #include "qxcbwindow.h" #include -#include +#include #include #include +class QGLXSurface : public QPlatformGLSurface +{ +public: + QGLXSurface(GLXDrawable drawable, const QGuiGLFormat &format); + GLXDrawable glxDrawable; +}; + class QGLXContext : public QPlatformGLContext { public: - QGLXContext(Window window, QXcbScreen *xd, const QWindowFormat &format); + QGLXContext(QXcbScreen *xd, const QGuiGLFormat &format, QPlatformGLContext *share); ~QGLXContext(); - virtual void makeCurrent(); - virtual void doneCurrent(); - virtual void swapBuffers(); - virtual void* getProcAddress(const QString& procName); + bool makeCurrent(const QPlatformGLSurface &surface); + void doneCurrent(); + void swapBuffers(const QPlatformGLSurface &surface); + void (*getProcAddress(const QByteArray &procName)) (); - GLXContext glxContext() const { return m_context; } + QGuiGLFormat format() const; - QWindowFormat windowFormat() const; + GLXContext glxContext() const { return m_context; } private: QXcbScreen *m_screen; - Drawable m_drawable; GLXContext m_context; - QWindowFormat m_windowFormat; - - QGLXContext (QXcbScreen *screen, Drawable drawable, GLXContext context); + QGuiGLFormat m_format; }; #endif diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index aa11ba5cb0..bd1924def9 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -63,6 +63,12 @@ #include #endif +#if defined(XCB_USE_GLX) +#include "qglxintegration.h" +#elif defined(XCB_USE_EGL) +#include "../eglconvenience/qeglplatformcontext.h" +#endif + QXcbIntegration::QXcbIntegration() : m_connection(new QXcbConnection), m_printerSupport(new QGenericUnixPrinterSupport) { @@ -97,6 +103,17 @@ QPlatformWindow *QXcbIntegration::createPlatformWindow(QWindow *window) const return new QXcbWindow(window); } +QPlatformGLContext *QXcbIntegration::createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const +{ +#if defined(XCB_USE_GLX) + return new QGLXContext(static_cast(m_screens.at(0)), glFormat, share); +#elif defined(XCB_USE_EGL) + return new QEGLPlatformContext(glFormat, share, m_connection->egl_display()); +#elif defined(XCB_USE_DRI2) + return new QDri2Context(glFormat, share); +#endif +} + QWindowSurface *QXcbIntegration::createWindowSurface(QWindow *window, WId winId) const { Q_UNUSED(winId); diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h index 1c1ca24094..d931e2a787 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.h +++ b/src/plugins/platforms/xcb/qxcbintegration.h @@ -58,6 +58,7 @@ public: bool hasCapability(Capability cap) const; QPixmapData *createPixmapData(QPixmapData::PixelType type) const; QPlatformWindow *createPlatformWindow(QWindow *window) const; + QPlatformGLContext *createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const; QWindowSurface *createWindowSurface(QWindow *window, WId winId) const; QList screens() const; diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 43f93d07bc..bf8ca2a584 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -48,7 +48,7 @@ #include -#include +#include #if defined(XCB_USE_EGL) #include "../eglconvenience/qeglplatformcontext.h" @@ -163,6 +163,7 @@ void *QXcbNativeInterface::graphicsDeviceForWindow(QWindow *window) void * QXcbNativeInterface::eglContextForWindow(QWindow *window) { +#if 0 Q_ASSERT(window); QPlatformGLContext *platformContext = window->glContext()->handle(); if (!platformContext) { @@ -179,4 +180,7 @@ void * QXcbNativeInterface::eglContextForWindow(QWindow *window) #else return 0; #endif +#else + return 0; +#endif } diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index de48c83cd1..22a476b690 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -95,7 +95,6 @@ static inline bool isTransient(const QWindow *w) QXcbWindow::QXcbWindow(QWindow *window) : QPlatformWindow(window) , m_window(0) - , m_context(0) , m_syncCounter(0) , m_mapped(false) , m_netWmUserTimeWindow(XCB_NONE) @@ -157,14 +156,14 @@ void QXcbWindow::create() #if defined(XCB_USE_GLX) || defined(XCB_USE_EGL) if ((window()->surfaceType() == QWindow::OpenGLSurface && QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) - || window()->requestedWindowFormat().hasAlpha()) + || window()->glFormat().hasAlpha()) { #if defined(XCB_USE_GLX) - XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen),m_screen->screenNumber(), window()->requestedWindowFormat()); + XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen),m_screen->screenNumber(), window()->glFormat()); #elif defined(XCB_USE_EGL) EGLDisplay eglDisplay = connection()->egl_display(); - EGLConfig eglConfig = q_configFromQWindowFormat(eglDisplay,window()->requestedWindowFormat(),true); + EGLConfig eglConfig = q_configFromGLFormat(eglDisplay, window()->glFormat(), true); VisualID id = QXlibEglIntegration::getCompatibleVisualId(DISPLAY_FROM_XCB(this), eglDisplay, eglConfig); XVisualInfo visualInfoTemplate; @@ -283,7 +282,6 @@ QXcbWindow::~QXcbWindow() void QXcbWindow::destroy() { - delete m_context; if (m_syncCounter && m_screen->syncRequestSupported()) Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter)); if (m_window) { @@ -936,33 +934,27 @@ void QXcbWindow::requestActivateWindow() connection()->sync(); } -QPlatformGLContext *QXcbWindow::glContext() const +QPlatformGLSurface *QXcbWindow::createGLSurface() const { if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) { - printf("no opengl\n"); + qWarning() << "QXcb::createGLSurface() called without OpenGL support"; return 0; } - if (!m_context) { + + QGuiGLFormat format = window()->glFormat(); + #if defined(XCB_USE_GLX) - QXcbWindow *that = const_cast(this); - that->m_context = new QGLXContext(m_window, m_screen, window()->requestedWindowFormat()); + return new QGLXSurface(m_window, format); #elif defined(XCB_USE_EGL) - EGLDisplay display = connection()->egl_display(); - EGLConfig config = q_configFromQWindowFormat(display,window()->requestedWindowFormat(),true); - QVector eglContextAttrs; - eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); - eglContextAttrs.append(2); - eglContextAttrs.append(EGL_NONE); - - EGLSurface eglSurface = eglCreateWindowSurface(display,config,(EGLNativeWindowType)m_window,0); - QXcbWindow *that = const_cast(this); - that->m_context = new QEGLPlatformContext(display, config, eglContextAttrs.data(), eglSurface, EGL_OPENGL_ES_API); -#elif defined(XCB_USE_DRI2) - QXcbWindow *that = const_cast(this); - that->m_context = new QDri2Context(that); + EGLDisplay display = connection()->egl_display(); + EGLConfig config = q_configFromGLFormat(display, format, true); + + EGLSurface eglSurface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)m_window, 0); + + return new QEGLSurface(eglSurface, window()->glFormat()); +#else + return 0; #endif - } - return m_context; } void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event) diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index f6869c7937..f50a611b4e 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -43,7 +43,7 @@ #define QXCBWINDOW_H #include -#include +#include #include #include @@ -72,9 +72,9 @@ public: void lower(); void propagateSizeHints(); - void requestActivateWindow(); + QPlatformGLSurface *createGLSurface() const; - QPlatformGLContext *glContext() const; + void requestActivateWindow(); bool setKeyboardGrabEnabled(bool grab); bool setMouseGrabEnabled(bool grab); @@ -127,7 +127,6 @@ private: QXcbScreen *m_screen; xcb_window_t m_window; - QPlatformGLContext *m_context; uint m_depth; QImage::Format m_format; -- cgit v1.2.3