diff options
Diffstat (limited to 'src/plugins/platforms/wayland/gl_integration/readback_glx')
7 files changed, 126 insertions, 104 deletions
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 857c1db6e3..850e7bb0ac 100644 --- a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.cpp +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.cpp @@ -41,9 +41,10 @@ #include "qwaylandreadbackglxcontext.h" -#include "qwaylandshmsurface.h" +#include "qwaylandshmbackingstore.h" #include "qwaylandreadbackglxwindow.h" +#include <QtGui/QOpenGLContext> #include <QtCore/QDebug> static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type) @@ -68,96 +69,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 QSurfaceFormat &format, + QPlatformOpenGLContext *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<QWaylandReadbackGlxContext *>(share)->m_context : 0; + + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(display, config); + m_context = glXCreateContext(display, visualInfo, shareContext, TRUE); + m_format = qglx_surfaceFormatFromGLXFBConfig(display, config, m_context); +} + +QSurfaceFormat QWaylandReadbackGlxContext::format() const +{ + return m_format; } -void QWaylandReadbackGlxContext::makeCurrent() +bool QWaylandReadbackGlxContext::makeCurrent(QPlatformSurface *surface) { - QPlatformGLContext::makeCurrent(); + GLXPixmap glxPixmap = static_cast<QWaylandReadbackGlxWindow *>(surface)->glxPixmap(); - glXMakeCurrent(mGlxIntegration->xDisplay(),mGlxPixmap,mContext); + return glXMakeCurrent(m_display, glxPixmap, m_context); } void QWaylandReadbackGlxContext::doneCurrent() { - QPlatformGLContext::doneCurrent(); + glXMakeCurrent(m_display, 0, 0); } -void QWaylandReadbackGlxContext::swapBuffers() +void QWaylandReadbackGlxContext::swapBuffers(QPlatformSurface *surface) { - if (QPlatformGLContext::currentContext() != this) { - makeCurrent(); - } + // #### makeCurrent() directly on the platform context doesn't update QOpenGLContext::currentContext() + if (QOpenGLContext::currentContext()->handle() != this) + makeCurrent(surface); + + QWaylandReadbackGlxWindow *w = static_cast<QWaylandReadbackGlxWindow *>(surface); - QSize size = mWindow->geometry().size(); + QSize size = w->geometry().size(); - QImage img(size,QImage::Format_ARGB32); + QImage img(size, QImage::Format_ARGB32); const uchar *constBits = img.bits(); void *pixels = const_cast<uchar *>(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 = w->buffer(); uchar *dstBits = const_cast<uchar *>(constDstBits); - memcpy(dstBits,constBits,(img.width()*4) * img.height()); + memcpy(dstBits, constBits, (img.width() * 4) * img.height()); + w->damage(QRect(QPoint(), size)); - mWindow->damage(QRegion(QRect(QPoint(0,0),size))); - mWindow->waitForFrameSync(); - + w->waitForFrameSync(); } -void * QWaylandReadbackGlxContext::getProcAddress(const QString &procName) +void (*QWaylandReadbackGlxContext::getProcAddress(const QByteArray &procName)) () { - return (void *) glXGetProcAddress(reinterpret_cast<GLubyte *>(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<const GLubyte *>(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..7b5eeece93 100644 --- a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.h +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.h @@ -42,38 +42,35 @@ #ifndef QWAYLANDREADBACKGLXCONTEXT_H #define QWAYLANDREADBACKGLXCONTEXT_H -#include <QPlatformGLContext> +#include <QPlatformOpenGLContext> +#include <QSurfaceFormat> #include "qwaylandreadbackglxintegration.h" -#include "qglxconvenience.h" +#include <QtPlatformSupport/private/qglxconvenience_p.h> class QWaylandReadbackGlxWindow; class QWaylandShmBuffer; -class QWaylandReadbackGlxContext : public QPlatformGLContext +class QWaylandReadbackGlxContext : public QPlatformOpenGLContext { public: - QWaylandReadbackGlxContext(QWaylandReadbackGlxIntegration *glxIntegration, QWaylandReadbackGlxWindow *window); + QWaylandReadbackGlxContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, Display *display, int screen); - void makeCurrent(); - void doneCurrent(); - void swapBuffers(); - void* getProcAddress(const QString& procName); + QSurfaceFormat format() const; + + void swapBuffers(QPlatformSurface *surface); - QPlatformWindowFormat platformWindowFormat() const; + bool makeCurrent(QPlatformSurface *surface); + void doneCurrent(); - void geometryChanged(); + void (*getProcAddress(const QByteArray &procName)) (); private: - QWaylandReadbackGlxIntegration *mGlxIntegration; - QWaylandReadbackGlxWindow *mWindow; - QWaylandShmBuffer *mBuffer; + GLXContext m_context; - Pixmap mPixmap; - GLXFBConfig mConfig; - GLXContext mContext; - GLXPixmap mGlxPixmap; + Display *m_display; + QSurfaceFormat 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 37a14a9f4c..752bb06a43 100644 --- a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.cpp +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.cpp @@ -66,9 +66,14 @@ void QWaylandReadbackGlxIntegration::initialize() { } -QWaylandWindow * QWaylandReadbackGlxIntegration::createEglWindow(QWidget *widget) +QWaylandWindow * QWaylandReadbackGlxIntegration::createEglWindow(QWindow *window) { - return new QWaylandReadbackGlxWindow(widget,this); + return new QWaylandReadbackGlxWindow(window,this); +} + +QPlatformOpenGLContext *QWaylandReadbackGlxIntegration::createPlatformOpenGLContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share) const +{ + return new QWaylandReadbackGlxContext(glFormat, share, mDisplay, mScreen); } QWaylandGLIntegration * QWaylandGLIntegration::createGLIntegration(QWaylandDisplay *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 d267d8dffe..ee50d74ebd 100644 --- a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.h +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.h @@ -48,7 +48,7 @@ #include <QtCore/QDataStream> #include <QtCore/QMetaType> #include <QtCore/QVariant> -#include <QtGui/QWidget> +#include <QtGui/QWindow> #include <X11/Xlib.h> @@ -60,7 +60,8 @@ public: void initialize(); - QWaylandWindow *createEglWindow(QWidget *widget); + QWaylandWindow *createEglWindow(QWindow *window); + QPlatformOpenGLContext *createPlatformOpenGLContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *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 98198dfa06..35c3ca3154 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 <QtDebug> + #include "qwaylandreadbackglxwindow.h" +#include "qwaylandshmbackingstore.h" -QWaylandReadbackGlxWindow::QWaylandReadbackGlxWindow(QWidget *window, QWaylandReadbackGlxIntegration *glxIntegration) +QWaylandReadbackGlxWindow::QWaylandReadbackGlxWindow(QWindow *window, QWaylandReadbackGlxIntegration *glxIntegration) : QWaylandShmWindow(window) - , mGlxIntegration(glxIntegration) - , mContext(0) + , m_glxIntegration(glxIntegration) + , m_buffer(0) + , m_pixmap(0) + , m_config(0) + , m_glxPixmap(0) + , m_window(window) { } @@ -54,20 +61,54 @@ QWaylandWindow::WindowType QWaylandReadbackGlxWindow::windowType() const return QWaylandWindow::Egl; } -QPlatformGLContext * QWaylandReadbackGlxWindow::glContext() const +void QWaylandReadbackGlxWindow::setGeometry(const QRect &rect) { - if (!mContext) { - QWaylandReadbackGlxWindow *that = const_cast<QWaylandReadbackGlxWindow *>(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<QWaylandReadbackGlxWindow *>(this)->createSurface(); + + return m_glxPixmap; +} - if (mContext) { - mContext->geometryChanged(); +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); + + if (!m_config) + m_config = qglx_findConfig(m_glxIntegration->xDisplay(), m_glxIntegration->screen(), m_window->format()); + + 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 d478961d53..c92646c80d 100644 --- a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.h +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.h @@ -49,17 +49,25 @@ class QWaylandReadbackGlxWindow : public QWaylandShmWindow { public: - QWaylandReadbackGlxWindow(QWidget *window, QWaylandReadbackGlxIntegration *glxIntegration); + QWaylandReadbackGlxWindow(QWindow *window, QWaylandReadbackGlxIntegration *glxIntegration); WindowType windowType() const; - QPlatformGLContext *glContext() 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; + QWindow *m_window; }; #endif // QWAYLANDREADBACKGLXWINDOW_H diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/readback_glx.pri b/src/plugins/platforms/wayland/gl_integration/readback_glx/readback_glx.pri index f8ea005937..746d594fa2 100644 --- a/src/plugins/platforms/wayland/gl_integration/readback_glx/readback_glx.pri +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/readback_glx.pri @@ -1,4 +1,3 @@ -include (../../../glxconvenience/glxconvenience.pri) HEADERS += \ $$PWD/qwaylandreadbackglxintegration.h \ $$PWD/qwaylandreadbackglxwindow.h \ |