diff options
Diffstat (limited to 'src')
4 files changed, 78 insertions, 4 deletions
diff --git a/src/platformsupport/eglconvenience/qeglplatformscreen.cpp b/src/platformsupport/eglconvenience/qeglplatformscreen.cpp index 6e2fc81c42..61f8cdd9b4 100644 --- a/src/platformsupport/eglconvenience/qeglplatformscreen.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformscreen.cpp @@ -32,6 +32,7 @@ ****************************************************************************/ #include "qeglplatformscreen_p.h" +#include "qeglplatformwindow_p.h" #include <QtGui/qwindow.h> #include <qpa/qwindowsysteminterface.h> #include <QtPlatformSupport/private/qopenglcompositor_p.h> @@ -94,4 +95,52 @@ void QEGLPlatformScreen::handleCursorMove(const QPoint &pos) QWindowSystemInterface::handleEnterLeaveEvent(enter, leave, enter->mapFromGlobal(pos), pos); } +QPixmap QEGLPlatformScreen::grabWindow(WId wid, int x, int y, int width, int height) const +{ + QOpenGLCompositor *compositor = QOpenGLCompositor::instance(); + const QList<QOpenGLCompositorWindow *> windows = compositor->windows(); + Q_ASSERT(!windows.isEmpty()); + + QImage img; + + if (static_cast<QEGLPlatformWindow *>(windows.first()->sourceWindow()->handle())->isRaster()) { + // Request the compositor to render everything into an FBO and read it back. This + // is of course slow, but it's safe and reliable. It will not include the mouse + // cursor, which is a plus. + img = compositor->grab(); + } else { + // Just a single OpenGL window without compositing. Do not support this case for now. Doing + // glReadPixels is not an option since it would read from the back buffer which may have + // undefined content when calling right after a swapBuffers (unless preserved swap is + // available and enabled, but we have no support for that). + qWarning("grabWindow: Not supported for non-composited OpenGL content. Use QQuickWindow::grabWindow() instead."); + return QPixmap(); + } + + if (!wid) { + const QSize screenSize = geometry().size(); + if (width < 0) + width = screenSize.width() - x; + if (height < 0) + height = screenSize.height() - y; + return QPixmap::fromImage(img).copy(x, y, width, height); + } + + foreach (QOpenGLCompositorWindow *w, windows) { + const QWindow *window = w->sourceWindow(); + if (window->winId() == wid) { + const QRect geom = window->geometry(); + if (width < 0) + width = geom.width() - x; + if (height < 0) + height = geom.height() - y; + QRect rect(geom.topLeft() + QPoint(x, y), QSize(width, height)); + rect &= window->geometry(); + return QPixmap::fromImage(img).copy(rect); + } + } + + return QPixmap(); +} + QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglplatformscreen_p.h b/src/platformsupport/eglconvenience/qeglplatformscreen_p.h index 98a108c4b7..4a987f6860 100644 --- a/src/platformsupport/eglconvenience/qeglplatformscreen_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformscreen_p.h @@ -67,6 +67,8 @@ public: void handleCursorMove(const QPoint &pos); + QPixmap grabWindow(WId wid, int x, int y, int width, int height) const Q_DECL_OVERRIDE; + private: EGLDisplay m_dpy; QWindow *m_pointerWindow; diff --git a/src/platformsupport/platformcompositor/qopenglcompositor.cpp b/src/platformsupport/platformcompositor/qopenglcompositor.cpp index 3048b2b777..3fd6c999a2 100644 --- a/src/platformsupport/platformcompositor/qopenglcompositor.cpp +++ b/src/platformsupport/platformcompositor/qopenglcompositor.cpp @@ -32,6 +32,7 @@ ****************************************************************************/ #include <QtGui/QOpenGLContext> +#include <QtGui/QOpenGLFramebufferObject> #include <QtGui/QWindow> #include <QtGui/QMatrix4x4> #include <qpa/qplatformbackingstore.h> @@ -76,7 +77,7 @@ QOpenGLCompositor::QOpenGLCompositor() Q_ASSERT(!compositor); m_updateTimer.setSingleShot(true); m_updateTimer.setInterval(0); - connect(&m_updateTimer, SIGNAL(timeout()), SLOT(renderAll())); + connect(&m_updateTimer, SIGNAL(timeout()), SLOT(handleRenderAllRequest())); } QOpenGLCompositor::~QOpenGLCompositor() @@ -98,10 +99,26 @@ void QOpenGLCompositor::update() m_updateTimer.start(); } -void QOpenGLCompositor::renderAll() +QImage QOpenGLCompositor::grab() { Q_ASSERT(m_context && m_targetWindow); m_context->makeCurrent(m_targetWindow); + QScopedPointer<QOpenGLFramebufferObject> fbo(new QOpenGLFramebufferObject(m_targetWindow->geometry().size())); + renderAll(fbo.data()); + return fbo->toImage(); +} + +void QOpenGLCompositor::handleRenderAllRequest() +{ + Q_ASSERT(m_context && m_targetWindow); + m_context->makeCurrent(m_targetWindow); + renderAll(0); +} + +void QOpenGLCompositor::renderAll(QOpenGLFramebufferObject *fbo) +{ + if (fbo) + fbo->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); @@ -120,7 +137,10 @@ void QOpenGLCompositor::renderAll() render(m_windows.at(i)); m_blitter.release(); - m_context->swapBuffers(m_targetWindow); + if (!fbo) + m_context->swapBuffers(m_targetWindow); + else + fbo->release(); for (int i = 0; i < m_windows.size(); ++i) m_windows.at(i)->endCompositing(); diff --git a/src/platformsupport/platformcompositor/qopenglcompositor_p.h b/src/platformsupport/platformcompositor/qopenglcompositor_p.h index 257bbf2531..2a8257305b 100644 --- a/src/platformsupport/platformcompositor/qopenglcompositor_p.h +++ b/src/platformsupport/platformcompositor/qopenglcompositor_p.h @@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE class QOpenGLContext; +class QOpenGLFramebufferObject; class QWindow; class QPlatformTextureList; @@ -76,6 +77,7 @@ public: QWindow *targetWindow() const { return m_targetWindow; } void update(); + QImage grab(); QList<QOpenGLCompositorWindow *> windows() const { return m_windows; } void addWindow(QOpenGLCompositorWindow *window); @@ -87,12 +89,13 @@ signals: void topWindowChanged(QOpenGLCompositorWindow *window); private slots: - void renderAll(); + void handleRenderAllRequest(); private: QOpenGLCompositor(); ~QOpenGLCompositor(); + void renderAll(QOpenGLFramebufferObject *fbo); void render(QOpenGLCompositorWindow *window); QOpenGLContext *m_context; |