diff options
author | Andy Nichols <andy.nichols@qt.io> | 2016-12-07 14:14:31 +0100 |
---|---|---|
committer | Andy Nichols <andy.nichols@qt.io> | 2016-12-13 15:43:32 +0000 |
commit | 9fbc5aa8866bbc19cc0db9f5f247276f36f3e283 (patch) | |
tree | 058118c873d3cf922bed91ddc1c0aba30bb42632 /src/plugins | |
parent | 4cdeeea8e2fd90b984c49edeb3765d2079487d79 (diff) |
OpenVG: Fix Recursive Layers
OpenVG also needed to ping-pong between two offscreen surfaces like the
OpenGL renderer.
Change-Id: I41f671d98d361eb114be5c00ebfe62710a971aaa
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'src/plugins')
5 files changed, 56 insertions, 13 deletions
diff --git a/src/plugins/scenegraph/openvg/qopenvgoffscreensurface.cpp b/src/plugins/scenegraph/openvg/qopenvgoffscreensurface.cpp index 3a4643ab5a..80af227fb4 100644 --- a/src/plugins/scenegraph/openvg/qopenvgoffscreensurface.cpp +++ b/src/plugins/scenegraph/openvg/qopenvgoffscreensurface.cpp @@ -39,6 +39,9 @@ #include "qopenvgoffscreensurface.h" +#include <QtGui/QImage> +#include <QDebug> + QT_BEGIN_NAMESPACE QOpenVGOffscreenSurface::QOpenVGOffscreenSurface(const QSize &size) @@ -79,6 +82,7 @@ QOpenVGOffscreenSurface::~QOpenVGOffscreenSurface() { vgDestroyImage(m_image); eglDestroySurface(m_display, m_renderTarget); + eglDestroyContext(m_display, m_context); } void QOpenVGOffscreenSurface::makeCurrent() @@ -98,7 +102,6 @@ void QOpenVGOffscreenSurface::doneCurrent() EGLContext currentContext = eglGetCurrentContext(); if (m_context == currentContext) { eglMakeCurrent(m_display, m_previousDrawSurface, m_previousReadSurface, m_previousContext); - m_context = EGL_NO_CONTEXT; m_previousContext = EGL_NO_CONTEXT; m_previousReadSurface = EGL_NO_SURFACE; m_previousDrawSurface = EGL_NO_SURFACE; @@ -110,4 +113,11 @@ void QOpenVGOffscreenSurface::swapBuffers() eglSwapBuffers(m_display, m_renderTarget); } +QImage QOpenVGOffscreenSurface::readbackQImage() +{ + QImage readbackImage(m_size, QImage::Format_ARGB32_Premultiplied); + vgGetImageSubData(m_image, readbackImage.bits(), readbackImage.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, m_size.width(), m_size.height()); + return readbackImage; +} + QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/openvg/qopenvgoffscreensurface.h b/src/plugins/scenegraph/openvg/qopenvgoffscreensurface.h index 833c9669bf..746e4de1cd 100644 --- a/src/plugins/scenegraph/openvg/qopenvgoffscreensurface.h +++ b/src/plugins/scenegraph/openvg/qopenvgoffscreensurface.h @@ -57,6 +57,8 @@ public: VGImage image() { return m_image; } QSize size() const { return m_size; } + QImage readbackQImage(); + private: VGImage m_image; QSize m_size; diff --git a/src/plugins/scenegraph/openvg/qsgopenvginternalimagenode.cpp b/src/plugins/scenegraph/openvg/qsgopenvginternalimagenode.cpp index c9545d5e9a..3dd1f9133c 100644 --- a/src/plugins/scenegraph/openvg/qsgopenvginternalimagenode.cpp +++ b/src/plugins/scenegraph/openvg/qsgopenvginternalimagenode.cpp @@ -79,6 +79,9 @@ void QSGOpenVGInternalImageNode::render() VGImage image = static_cast<VGImage>(m_texture->textureId()); QSize textureSize = m_texture->textureSize(); + if (image == VG_INVALID_HANDLE || !textureSize.isValid()) + return; + // If Mirrored if (m_mirror) { diff --git a/src/plugins/scenegraph/openvg/qsgopenvglayer.cpp b/src/plugins/scenegraph/openvg/qsgopenvglayer.cpp index cafd0d4e1e..047539d431 100644 --- a/src/plugins/scenegraph/openvg/qsgopenvglayer.cpp +++ b/src/plugins/scenegraph/openvg/qsgopenvglayer.cpp @@ -54,6 +54,7 @@ QSGOpenVGLayer::QSGOpenVGLayer(QSGRenderContext *renderContext) , m_recursive(false) , m_dirtyTexture(true) , m_offscreenSurface(nullptr) + , m_secondaryOffscreenSurface(nullptr) { m_context = static_cast<QSGOpenVGRenderContext*>(renderContext); } @@ -113,7 +114,9 @@ void QSGOpenVGLayer::setItem(QSGNode *item) if (m_live && !m_item) { delete m_offscreenSurface; + delete m_secondaryOffscreenSurface; m_offscreenSurface = nullptr; + m_secondaryOffscreenSurface = nullptr; } markDirtyTexture(); @@ -135,7 +138,9 @@ void QSGOpenVGLayer::setSize(const QSize &size) if (m_live && m_size.isNull()) { delete m_offscreenSurface; + delete m_secondaryOffscreenSurface; m_offscreenSurface = nullptr; + m_secondaryOffscreenSurface = nullptr; } markDirtyTexture(); @@ -153,8 +158,7 @@ void QSGOpenVGLayer::scheduleUpdate() QImage QSGOpenVGLayer::toImage() const { - // XXX - return QImage(); + return m_offscreenSurface->readbackQImage(); } void QSGOpenVGLayer::setLive(bool live) @@ -165,7 +169,9 @@ void QSGOpenVGLayer::setLive(bool live) if (m_live && (!m_item || m_size.isNull())) { delete m_offscreenSurface; + delete m_secondaryOffscreenSurface; m_offscreenSurface = nullptr; + m_secondaryOffscreenSurface = nullptr; } markDirtyTexture(); @@ -218,16 +224,20 @@ void QSGOpenVGLayer::markDirtyTexture() void QSGOpenVGLayer::invalidated() { delete m_offscreenSurface; + delete m_secondaryOffscreenSurface; delete m_renderer; m_renderer = nullptr; m_offscreenSurface = nullptr; + m_secondaryOffscreenSurface = nullptr; } void QSGOpenVGLayer::grab() { if (!m_item || m_size.isNull()) { delete m_offscreenSurface; + delete m_secondaryOffscreenSurface; m_offscreenSurface = nullptr; + m_secondaryOffscreenSurface = nullptr; m_dirtyTexture = false; return; } @@ -244,14 +254,23 @@ void QSGOpenVGLayer::grab() m_renderer->setDevicePixelRatio(m_device_pixel_ratio); m_renderer->setRootNode(static_cast<QSGRootNode *>(root)); - + bool deleteOffscreenSurfaceLater = false; if (m_offscreenSurface == nullptr || m_offscreenSurface->size() != m_size ) { - if (m_offscreenSurface != nullptr) + if (m_recursive) { + deleteOffscreenSurfaceLater = true; + delete m_secondaryOffscreenSurface; + m_secondaryOffscreenSurface = new QOpenVGOffscreenSurface(m_size); + } else { delete m_offscreenSurface; - - m_offscreenSurface = new QOpenVGOffscreenSurface(m_size); + delete m_secondaryOffscreenSurface; + m_offscreenSurface = new QOpenVGOffscreenSurface(m_size); + m_secondaryOffscreenSurface = nullptr; + } } + if (m_recursive && !m_secondaryOffscreenSurface) + m_secondaryOffscreenSurface = new QOpenVGOffscreenSurface(m_size); + // Render texture. root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip and opacity update. m_renderer->nodeChanged(root, QSGNode::DirtyForceUpdate); // Force render list update. @@ -267,17 +286,25 @@ void QSGOpenVGLayer::grab() m_renderer->setProjectionMatrixToRect(mirrored); m_renderer->setClearColor(Qt::transparent); - m_offscreenSurface->makeCurrent(); - // Before Rendering setup context for adjusting to Qt Coordinates to PixelBuffer - // Should already be inverted by default - vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); - vgLoadIdentity(); + if (m_recursive) + m_secondaryOffscreenSurface->makeCurrent(); + else + m_offscreenSurface->makeCurrent(); m_renderer->renderScene(); // Make the previous surface and context active again - m_offscreenSurface->doneCurrent(); + if (m_recursive) { + if (deleteOffscreenSurfaceLater) { + delete m_offscreenSurface; + m_offscreenSurface = new QOpenVGOffscreenSurface(m_size); + } + m_secondaryOffscreenSurface->doneCurrent(); + qSwap(m_offscreenSurface, m_secondaryOffscreenSurface); + } else { + m_offscreenSurface->doneCurrent(); + } root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip, opacity and render list update. diff --git a/src/plugins/scenegraph/openvg/qsgopenvglayer.h b/src/plugins/scenegraph/openvg/qsgopenvglayer.h index 760a22f0bc..2af0bfb40f 100644 --- a/src/plugins/scenegraph/openvg/qsgopenvglayer.h +++ b/src/plugins/scenegraph/openvg/qsgopenvglayer.h @@ -105,6 +105,7 @@ private: bool m_dirtyTexture; QOpenVGOffscreenSurface *m_offscreenSurface; + QOpenVGOffscreenSurface *m_secondaryOffscreenSurface; }; QT_END_NAMESPACE |