aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorAndy Nichols <andy.nichols@qt.io>2016-12-07 14:14:31 +0100
committerAndy Nichols <andy.nichols@qt.io>2016-12-13 15:43:32 +0000
commit9fbc5aa8866bbc19cc0db9f5f247276f36f3e283 (patch)
tree058118c873d3cf922bed91ddc1c0aba30bb42632 /src/plugins
parent4cdeeea8e2fd90b984c49edeb3765d2079487d79 (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')
-rw-r--r--src/plugins/scenegraph/openvg/qopenvgoffscreensurface.cpp12
-rw-r--r--src/plugins/scenegraph/openvg/qopenvgoffscreensurface.h2
-rw-r--r--src/plugins/scenegraph/openvg/qsgopenvginternalimagenode.cpp3
-rw-r--r--src/plugins/scenegraph/openvg/qsgopenvglayer.cpp51
-rw-r--r--src/plugins/scenegraph/openvg/qsgopenvglayer.h1
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