aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/items/qsgshadereffectsource.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/items/qsgshadereffectsource.cpp')
-rw-r--r--src/declarative/items/qsgshadereffectsource.cpp157
1 files changed, 109 insertions, 48 deletions
diff --git a/src/declarative/items/qsgshadereffectsource.cpp b/src/declarative/items/qsgshadereffectsource.cpp
index e05d20ed69..bb55af524b 100644
--- a/src/declarative/items/qsgshadereffectsource.cpp
+++ b/src/declarative/items/qsgshadereffectsource.cpp
@@ -46,7 +46,7 @@
#include <private/qsgadaptationlayer_p.h>
#include <private/qsgrenderer_p.h>
-#include "qglframebufferobject.h"
+#include "qopenglframebufferobject.h"
#include "qmath.h"
#include <private/qsgtexture_p.h>
@@ -54,6 +54,33 @@ QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(qmlFboOverlay, QML_FBO_OVERLAY)
+class QSGShaderEffectSourceTextureProvider : public QSGTextureProvider
+{
+ Q_OBJECT
+public:
+ QSGShaderEffectSourceTextureProvider()
+ : sourceTexture(0)
+ {
+ }
+
+ QSGTexture *texture() const {
+ sourceTexture->setMipmapFiltering(mipmapFiltering);
+ sourceTexture->setFiltering(filtering);
+ sourceTexture->setHorizontalWrapMode(horizontalWrap);
+ sourceTexture->setVerticalWrapMode(verticalWrap);
+ return sourceTexture;
+ }
+
+ QSGShaderEffectTexture *sourceTexture;
+
+ QSGTexture::Filtering mipmapFiltering;
+ QSGTexture::Filtering filtering;
+ QSGTexture::WrapMode horizontalWrap;
+ QSGTexture::WrapMode verticalWrap;
+};
+#include "qsgshadereffectsource.moc"
+
+
QSGShaderEffectSourceNode::QSGShaderEffectSourceNode()
{
setFlag(UsePreprocess, true);
@@ -76,6 +103,7 @@ QSGShaderEffectTexture::QSGShaderEffectTexture(QSGItem *shaderSource)
#ifdef QSG_DEBUG_FBO_OVERLAY
, m_debugOverlay(0)
#endif
+ , m_context(0)
, m_mipmap(false)
, m_live(true)
, m_recursive(false)
@@ -96,6 +124,17 @@ QSGShaderEffectTexture::~QSGShaderEffectTexture()
#endif
}
+void QSGShaderEffectTexture::scheduleForCleanup()
+{
+ if (m_context)
+ m_context->scheduleTextureForCleanup(this);
+ else {
+ // Never really been used, hence we can delete it right away..
+ Q_ASSERT(!m_fbo);
+ delete this;
+ }
+}
+
int QSGShaderEffectTexture::textureId() const
{
@@ -226,10 +265,12 @@ void QSGShaderEffectTexture::grab()
return;
}
- QSGContext *context = QSGItemPrivate::get(m_shaderSource)->sceneGraphContext();
+ if (!m_context)
+ m_context = QSGItemPrivate::get(m_shaderSource)->sceneGraphContext();
+ Q_ASSERT(QSGItemPrivate::get(m_shaderSource)->sceneGraphContext() == m_context);
if (!m_renderer) {
- m_renderer = context->createRenderer();
+ m_renderer = m_context->createRenderer();
connect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture()), Qt::DirectConnection);
}
m_renderer->setRootNode(static_cast<QSGRootNode *>(root));
@@ -248,27 +289,27 @@ void QSGShaderEffectTexture::grab()
// Don't delete the FBO right away in case it is used recursively.
deleteFboLater = true;
delete m_secondaryFbo;
- QGLFramebufferObjectFormat format;
+ QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
format.setInternalTextureFormat(m_format);
format.setSamples(8);
- m_secondaryFbo = new QGLFramebufferObject(m_size, format);
+ m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
} else {
- QGLFramebufferObjectFormat format;
- format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
format.setInternalTextureFormat(m_format);
format.setMipmap(m_mipmap);
if (m_recursive) {
deleteFboLater = true;
delete m_secondaryFbo;
- m_secondaryFbo = new QGLFramebufferObject(m_size, format);
+ m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
updateBindOptions(true);
} else {
delete m_fbo;
delete m_secondaryFbo;
- m_fbo = new QGLFramebufferObject(m_size, format);
+ m_fbo = new QOpenGLFramebufferObject(m_size, format);
m_secondaryFbo = 0;
glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
updateBindOptions(true);
@@ -281,7 +322,7 @@ void QSGShaderEffectTexture::grab()
Q_ASSERT(m_fbo);
Q_ASSERT(!m_multisampling);
- m_secondaryFbo = new QGLFramebufferObject(m_size, m_fbo->format());
+ m_secondaryFbo = new QOpenGLFramebufferObject(m_size, m_fbo->format());
glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
updateBindOptions(true);
}
@@ -293,7 +334,7 @@ void QSGShaderEffectTexture::grab()
#ifdef QSG_DEBUG_FBO_OVERLAY
if (qmlFboOverlay()) {
if (!m_debugOverlay)
- m_debugOverlay = context->createRectangleNode();
+ m_debugOverlay = m_context->createRectangleNode();
m_debugOverlay->setRect(QRectF(0, 0, m_size.width(), m_size.height()));
m_debugOverlay->setColor(QColor(0xff, 0x00, 0x80, 0x40));
m_debugOverlay->setPenColor(QColor());
@@ -306,7 +347,7 @@ void QSGShaderEffectTexture::grab()
m_dirtyTexture = false;
- const QGLContext *ctx = QGLContext::currentContext();
+ QOpenGLContext *ctx = m_context->glContext();
m_renderer->setDeviceRect(m_size);
m_renderer->setViewportRect(m_size);
QRectF mirrored(m_rect.left(), m_rect.bottom(), m_rect.width(), -m_rect.height());
@@ -318,29 +359,29 @@ void QSGShaderEffectTexture::grab()
if (deleteFboLater) {
delete m_fbo;
- QGLFramebufferObjectFormat format;
+ QOpenGLFramebufferObjectFormat format;
format.setInternalTextureFormat(m_format);
- format.setAttachment(QGLFramebufferObject::NoAttachment);
+ format.setAttachment(QOpenGLFramebufferObject::NoAttachment);
format.setMipmap(m_mipmap);
format.setSamples(0);
- m_fbo = new QGLFramebufferObject(m_size, format);
+ m_fbo = new QOpenGLFramebufferObject(m_size, format);
glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
updateBindOptions(true);
}
QRect r(QPoint(), m_size);
- QGLFramebufferObject::blitFramebuffer(m_fbo, r, m_secondaryFbo, r);
+ QOpenGLFramebufferObject::blitFramebuffer(m_fbo, r, m_secondaryFbo, r);
} else {
if (m_recursive) {
m_renderer->renderScene(QSGBindableFbo(m_secondaryFbo));
if (deleteFboLater) {
delete m_fbo;
- QGLFramebufferObjectFormat format;
- format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
format.setInternalTextureFormat(m_format);
format.setMipmap(m_mipmap);
- m_fbo = new QGLFramebufferObject(m_size, format);
+ m_fbo = new QOpenGLFramebufferObject(m_size, format);
glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
updateBindOptions(true);
}
@@ -452,6 +493,7 @@ QImage QSGShaderEffectTexture::toImage() const
QSGShaderEffectSource::QSGShaderEffectSource(QSGItem *parent)
: QSGItem(parent)
+ , m_provider(0)
, m_wrapMode(ClampToEdge)
, m_sourceItem(0)
, m_textureSize(0, 0)
@@ -464,17 +506,36 @@ QSGShaderEffectSource::QSGShaderEffectSource(QSGItem *parent)
{
setFlag(ItemHasContents);
m_texture = new QSGShaderEffectTexture(this);
- connect(m_texture, SIGNAL(textureChanged()), this, SIGNAL(textureChanged()), Qt::DirectConnection);
connect(m_texture, SIGNAL(textureChanged()), this, SLOT(update()));
}
QSGShaderEffectSource::~QSGShaderEffectSource()
{
- delete m_texture;
+ m_texture->scheduleForCleanup();
+
+ if (m_provider)
+ m_provider->deleteLater();
+
if (m_sourceItem)
QSGItemPrivate::get(m_sourceItem)->derefFromEffectItem(m_hideSource);
}
+QSGTextureProvider *QSGShaderEffectSource::textureProvider() const
+{
+ if (!m_provider) {
+ // Make sure it gets thread affinity on the rendering thread so deletion works properly..
+ Q_ASSERT_X(QSGItemPrivate::get(this)->canvas
+ && QSGItemPrivate::get(this)->sceneGraphContext()
+ && QThread::currentThread() == QSGItemPrivate::get(this)->sceneGraphContext()->thread(),
+ "QSGShaderEffectSource::textureProvider",
+ "Cannot be used outside the GUI thread");
+ const_cast<QSGShaderEffectSource *>(this)->m_provider = new QSGShaderEffectSourceTextureProvider();
+ connect(m_texture, SIGNAL(textureChanged()), m_provider, SIGNAL(textureChanged()), Qt::DirectConnection);
+ m_provider->sourceTexture = m_texture;
+ }
+ return m_provider;
+}
+
/*!
\qmlproperty enumeration ShaderEffectSource::wrapMode
@@ -761,17 +822,6 @@ static void get_wrap_mode(QSGShaderEffectSource::WrapMode mode, QSGTexture::Wrap
}
-QSGTexture *QSGShaderEffectSource::texture() const
-{
- m_texture->setMipmapFiltering(m_mipmap ? QSGTexture::Linear : QSGTexture::None);
- m_texture->setFiltering(QSGItemPrivate::get(this)->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
- QSGTexture::WrapMode h, v;
- get_wrap_mode(m_wrapMode, &h, &v);
- m_texture->setHorizontalWrapMode(h);
- m_texture->setVerticalWrapMode(v);
- return m_texture;
-}
-
QSGNode *QSGShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
if (!m_sourceItem || m_sourceItem->width() == 0 || m_sourceItem->height() == 0) {
@@ -779,19 +829,7 @@ QSGNode *QSGShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaintNod
return 0;
}
- QSGShaderEffectSourceNode *node = static_cast<QSGShaderEffectSourceNode *>(oldNode);
- if (!node) {
- node = new QSGShaderEffectSourceNode;
- node->setTexture(m_texture);
- connect(m_texture, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()), Qt::DirectConnection);
- }
-
- // If live and recursive, update continuously.
- if (m_live && m_recursive)
- node->markDirty(QSGNode::DirtyMaterial);
-
QSGShaderEffectTexture *tex = qobject_cast<QSGShaderEffectTexture *>(m_texture);
-
tex->setLive(m_live);
tex->setItem(QSGItemPrivate::get(m_sourceItem)->itemNode());
QRectF sourceRect = m_sourceRect.width() == 0 || m_sourceRect.height() == 0
@@ -823,12 +861,35 @@ QSGNode *QSGShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaintNod
? QSGTexture::Linear
: QSGTexture::Nearest;
QSGTexture::Filtering mmFiltering = m_mipmap ? filtering : QSGTexture::None;
- node->setMipmapFiltering(mmFiltering);
- node->setFiltering(filtering);
-
QSGTexture::WrapMode hWrap, vWrap;
get_wrap_mode(m_wrapMode, &hWrap, &vWrap);
+ if (m_provider) {
+ m_provider->mipmapFiltering = mmFiltering;
+ m_provider->filtering = filtering;
+ m_provider->horizontalWrap = hWrap;
+ m_provider->verticalWrap = vWrap;
+ }
+
+ // Don't create the paint node if we're not spanning any area
+ if (width() == 0 || height() == 0) {
+ delete oldNode;
+ return 0;
+ }
+
+ QSGShaderEffectSourceNode *node = static_cast<QSGShaderEffectSourceNode *>(oldNode);
+ if (!node) {
+ node = new QSGShaderEffectSourceNode;
+ node->setTexture(m_texture);
+ connect(m_texture, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()), Qt::DirectConnection);
+ }
+
+ // If live and recursive, update continuously.
+ if (m_live && m_recursive)
+ node->markDirty(QSGNode::DirtyMaterial);
+
+ node->setMipmapFiltering(mmFiltering);
+ node->setFiltering(filtering);
node->setHorizontalWrapMode(hWrap);
node->setVerticalWrapMode(vWrap);
node->setTargetRect(QRectF(0, 0, width(), height()));