aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickshadereffectsource.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-08-11 13:21:11 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2014-08-23 07:56:30 +0200
commit15ee12508ec8663ae09ebfc61cc4f0725311bdec (patch)
tree7f788285afbde14f0d1eaab9065b21410c277ac5 /src/quick/items/qquickshadereffectsource.cpp
parent253e9257e1f586d1c1dfa585aa6f862d310cdec3 (diff)
Cleanup: Separate the sub-tree layering out of QtQuick into the scene graph
This basically renames QQuickShaderEffectTexture to QSGDefaultLayer and introduces QSGLayer as interface to be used. QQuickShaderEffectTexture is generic for the scene graph and has no QtQuick dependencies. The interface separation allows scene graph backends to customize layers. Change-Id: I9a7f37addaa4b80a34ff9a1456b0cb9b16d4e9f3 Reviewed-by: Gunnar Sletta <gunnar.sletta@jollamobile.com>
Diffstat (limited to 'src/quick/items/qquickshadereffectsource.cpp')
-rw-r--r--src/quick/items/qquickshadereffectsource.cpp416
1 files changed, 5 insertions, 411 deletions
diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp
index 2b42a01fc1..f027e044e1 100644
--- a/src/quick/items/qquickshadereffectsource.cpp
+++ b/src/quick/items/qquickshadereffectsource.cpp
@@ -54,44 +54,6 @@
QT_BEGIN_NAMESPACE
-DEFINE_BOOL_CONFIG_OPTION(qmlFboOverlay, QML_FBO_OVERLAY)
-DEFINE_BOOL_CONFIG_OPTION(qmlFboFlushBeforeDetach, QML_FBO_FLUSH_BEFORE_DETACH)
-
-namespace
-{
- class BindableFbo : public QSGBindable
- {
- public:
- BindableFbo(QOpenGLFramebufferObject *fbo, QSGDepthStencilBuffer *depthStencil);
- virtual ~BindableFbo();
- virtual void bind() const;
- private:
- QOpenGLFramebufferObject *m_fbo;
- QSGDepthStencilBuffer *m_depthStencil;
- };
-
- BindableFbo::BindableFbo(QOpenGLFramebufferObject *fbo, QSGDepthStencilBuffer *depthStencil)
- : m_fbo(fbo)
- , m_depthStencil(depthStencil)
- {
- }
-
- BindableFbo::~BindableFbo()
- {
- if (qmlFboFlushBeforeDetach())
- QOpenGLContext::currentContext()->functions()->glFlush();
- if (m_depthStencil)
- m_depthStencil->detach();
- }
-
- void BindableFbo::bind() const
- {
- m_fbo->bind();
- if (m_depthStencil)
- m_depthStencil->attach();
- }
-}
-
class QQuickShaderEffectSourceTextureProvider : public QSGTextureProvider
{
Q_OBJECT
@@ -113,7 +75,7 @@ public:
return sourceTexture;
}
- QQuickShaderEffectTexture *sourceTexture;
+ QSGLayer *sourceTexture;
QSGTexture::Filtering mipmapFiltering;
QSGTexture::Filtering filtering;
@@ -122,379 +84,10 @@ public:
};
#include "qquickshadereffectsource.moc"
-QQuickShaderEffectTexture::QQuickShaderEffectTexture(QQuickItem *shaderSource)
- : QSGDynamicTexture()
- , m_item(0)
- , m_shaderSourceNode(0)
- , m_device_pixel_ratio(1)
- , m_format(GL_RGBA)
- , m_renderer(0)
- , m_fbo(0)
- , m_secondaryFbo(0)
- , m_transparentTexture(0)
-#ifdef QSG_DEBUG_FBO_OVERLAY
- , m_debugOverlay(0)
-#endif
- , m_context(QQuickItemPrivate::get(shaderSource)->sceneGraphRenderContext())
- , m_mipmap(false)
- , m_live(true)
- , m_recursive(false)
- , m_dirtyTexture(true)
- , m_multisamplingChecked(false)
- , m_multisampling(false)
- , m_grab(false)
-{
-}
-
-QQuickShaderEffectTexture::~QQuickShaderEffectTexture()
-{
- invalidated();
-}
-
-void QQuickShaderEffectTexture::invalidated()
-{
- delete m_renderer;
- m_renderer = 0;
- delete m_fbo;
- delete m_secondaryFbo;
- m_fbo = m_secondaryFbo = 0;
-#ifdef QSG_DEBUG_FBO_OVERLAY
- delete m_debugOverlay;
- m_debugOverlay = 0;
-#endif
- if (m_transparentTexture) {
- QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &m_transparentTexture);
- m_transparentTexture = 0;
- }
-}
-
-void QQuickShaderEffectTexture::markDirtyTextureLater()
-{
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
-}
-
-void QQuickShaderEffectTexture::customEvent(QEvent *)
-{
- markDirtyTexture();
-}
-
-int QQuickShaderEffectTexture::textureId() const
-{
- return m_fbo ? m_fbo->texture() : 0;
-}
-
-bool QQuickShaderEffectTexture::hasAlphaChannel() const
-{
- return m_format != GL_RGB;
-}
-
-bool QQuickShaderEffectTexture::hasMipmaps() const
-{
- return m_mipmap;
-}
-
-
-void QQuickShaderEffectTexture::bind()
-{
-#ifndef QT_NO_DEBUG
- if (!m_recursive && m_fbo && ((m_multisampling && m_secondaryFbo->isBound()) || m_fbo->isBound()))
- qWarning("ShaderEffectSource: \'recursive\' must be set to true when rendering recursively.");
-#endif
- QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
- if (!m_fbo && m_format == GL_RGBA) {
- if (m_transparentTexture == 0) {
- funcs->glGenTextures(1, &m_transparentTexture);
- funcs->glBindTexture(GL_TEXTURE_2D, m_transparentTexture);
- const uint zero = 0;
- funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &zero);
- } else {
- funcs->glBindTexture(GL_TEXTURE_2D, m_transparentTexture);
- }
- } else {
- funcs->glBindTexture(GL_TEXTURE_2D, m_fbo ? m_fbo->texture() : 0);
- updateBindOptions();
- }
-}
-
-bool QQuickShaderEffectTexture::updateTexture()
-{
- bool doGrab = (m_live || m_grab) && m_dirtyTexture;
- if (doGrab)
- grab();
- if (m_grab)
- emit scheduledUpdateCompleted();
- m_grab = false;
- return doGrab;
-}
-
-void QQuickShaderEffectTexture::setHasMipmaps(bool mipmap)
-{
- if (mipmap == m_mipmap)
- return;
- m_mipmap = mipmap;
- if (m_mipmap && m_fbo && !m_fbo->format().mipmap())
- markDirtyTexture();
-}
-
-
-void QQuickShaderEffectTexture::setItem(QSGNode *item)
-{
- if (item == m_item)
- return;
- m_item = item;
-
- if (m_live && !m_item) {
- delete m_fbo;
- delete m_secondaryFbo;
- m_fbo = m_secondaryFbo = 0;
- m_depthStencilBuffer.clear();
- }
-
- markDirtyTexture();
-}
-
-void QQuickShaderEffectTexture::setRect(const QRectF &rect)
-{
- if (rect == m_rect)
- return;
- m_rect = rect;
- markDirtyTexture();
-}
-
-void QQuickShaderEffectTexture::setSize(const QSize &size)
-{
- if (size == m_size)
- return;
- m_size = size;
-
- if (m_live && m_size.isNull()) {
- delete m_fbo;
- delete m_secondaryFbo;
- m_fbo = m_secondaryFbo = 0;
- m_depthStencilBuffer.clear();
- }
-
- markDirtyTexture();
-}
-
-void QQuickShaderEffectTexture::setFormat(GLenum format)
-{
- if (format == m_format)
- return;
- m_format = format;
- markDirtyTexture();
-}
-
-void QQuickShaderEffectTexture::setLive(bool live)
-{
- if (live == m_live)
- return;
- m_live = live;
-
- if (m_live && (!m_item || m_size.isNull())) {
- delete m_fbo;
- delete m_secondaryFbo;
- m_fbo = m_secondaryFbo = 0;
- m_depthStencilBuffer.clear();
- }
-
- markDirtyTexture();
-}
-
-void QQuickShaderEffectTexture::scheduleUpdate()
-{
- if (m_grab)
- return;
- m_grab = true;
- if (m_dirtyTexture) {
- emit updateRequested();
- if (m_shaderSourceNode)
- m_shaderSourceNode->markDirty(QSGNode::DirtyMaterial);
- }
-}
-
-void QQuickShaderEffectTexture::setRecursive(bool recursive)
-{
- m_recursive = recursive;
-}
-
-void QQuickShaderEffectTexture::markDirtyTexture()
-{
- m_dirtyTexture = true;
- if (m_live || m_grab) {
- emit updateRequested();
- if (m_shaderSourceNode)
- m_shaderSourceNode->markDirty(QSGNode::DirtyMaterial);
- }
-}
-
-void QQuickShaderEffectTexture::grab()
-{
- if (!m_item || m_size.isNull()) {
- delete m_fbo;
- delete m_secondaryFbo;
- m_fbo = m_secondaryFbo = 0;
- m_depthStencilBuffer.clear();
- m_dirtyTexture = false;
- return;
- }
- QSGNode *root = m_item;
- while (root->firstChild() && root->type() != QSGNode::RootNodeType)
- root = root->firstChild();
- if (root->type() != QSGNode::RootNodeType)
- return;
-
- if (!m_renderer) {
- m_renderer = m_context->createRenderer();
- connect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTextureLater()));
- }
- m_renderer->setDevicePixelRatio(m_device_pixel_ratio);
- m_renderer->setRootNode(static_cast<QSGRootNode *>(root));
-
- QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
- bool deleteFboLater = false;
- if (!m_fbo || m_fbo->size() != m_size || m_fbo->format().internalTextureFormat() != m_format
- || (!m_fbo->format().mipmap() && m_mipmap))
- {
- if (!m_multisamplingChecked) {
- if (m_context->openglContext()->format().samples() <= 1) {
- m_multisampling = false;
- } else {
- const QSet<QByteArray> extensions = m_context->openglContext()->extensions();
- m_multisampling = extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_multisample"))
- && extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_blit"));
- }
- m_multisamplingChecked = true;
- }
- if (m_multisampling) {
- // Don't delete the FBO right away in case it is used recursively.
- deleteFboLater = true;
- delete m_secondaryFbo;
- QOpenGLFramebufferObjectFormat format;
-
- format.setInternalTextureFormat(m_format);
- format.setSamples(m_context->openglContext()->format().samples());
- m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
- m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo);
- } else {
- QOpenGLFramebufferObjectFormat format;
- format.setInternalTextureFormat(m_format);
- format.setMipmap(m_mipmap);
- if (m_recursive) {
- deleteFboLater = true;
- delete m_secondaryFbo;
- m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
- funcs->glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
- updateBindOptions(true);
- m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo);
- } else {
- delete m_fbo;
- delete m_secondaryFbo;
- m_fbo = new QOpenGLFramebufferObject(m_size, format);
- m_secondaryFbo = 0;
- funcs->glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
- updateBindOptions(true);
- m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_fbo);
- }
- }
- }
-
- if (m_recursive && !m_secondaryFbo) {
- // m_fbo already created, m_recursive was just set.
- Q_ASSERT(m_fbo);
- Q_ASSERT(!m_multisampling);
-
- m_secondaryFbo = new QOpenGLFramebufferObject(m_size, m_fbo->format());
- funcs->glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
- updateBindOptions(true);
- }
-
- // Render texture.
- root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip and opacity update.
- m_renderer->nodeChanged(root, QSGNode::DirtyForceUpdate); // Force render list update.
-
-#ifdef QSG_DEBUG_FBO_OVERLAY
- if (qmlFboOverlay()) {
- if (!m_debugOverlay)
- m_debugOverlay = new QSGSimpleRectNode();
- m_debugOverlay->setRect(QRectF(0, 0, m_size.width(), m_size.height()));
- m_debugOverlay->setColor(QColor(0xff, 0x00, 0x80, 0x40));
- root->appendChildNode(m_debugOverlay);
- }
-#endif
-
- m_dirtyTexture = false;
-
- m_renderer->setDeviceRect(m_size);
- m_renderer->setViewportRect(m_size);
- QRectF mirrored(m_rect.left(), m_rect.bottom(), m_rect.width(), -m_rect.height());
- m_renderer->setProjectionMatrixToRect(mirrored);
- m_renderer->setClearColor(Qt::transparent);
-
- if (m_multisampling) {
- m_renderer->renderScene(BindableFbo(m_secondaryFbo, m_depthStencilBuffer.data()));
-
- if (deleteFboLater) {
- delete m_fbo;
- QOpenGLFramebufferObjectFormat format;
- format.setInternalTextureFormat(m_format);
- format.setAttachment(QOpenGLFramebufferObject::NoAttachment);
- format.setMipmap(m_mipmap);
- format.setSamples(0);
- m_fbo = new QOpenGLFramebufferObject(m_size, format);
- funcs->glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
- updateBindOptions(true);
- }
-
- QRect r(QPoint(), m_size);
- QOpenGLFramebufferObject::blitFramebuffer(m_fbo, r, m_secondaryFbo, r);
- } else {
- if (m_recursive) {
- m_renderer->renderScene(BindableFbo(m_secondaryFbo, m_depthStencilBuffer.data()));
-
- if (deleteFboLater) {
- delete m_fbo;
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
- format.setInternalTextureFormat(m_format);
- format.setMipmap(m_mipmap);
- m_fbo = new QOpenGLFramebufferObject(m_size, format);
- funcs->glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
- updateBindOptions(true);
- }
- qSwap(m_fbo, m_secondaryFbo);
- } else {
- m_renderer->renderScene(BindableFbo(m_fbo, m_depthStencilBuffer.data()));
- }
- }
-
- if (m_mipmap) {
- funcs->glBindTexture(GL_TEXTURE_2D, textureId());
- funcs->glGenerateMipmap(GL_TEXTURE_2D);
- }
-
- root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip, opacity and render list update.
-
-#ifdef QSG_DEBUG_FBO_OVERLAY
- if (qmlFboOverlay())
- root->removeChildNode(m_debugOverlay);
-#endif
- if (m_recursive)
- markDirtyTexture(); // Continuously update if 'live' and 'recursive'.
-}
-
-QImage QQuickShaderEffectTexture::toImage() const
-{
- if (m_fbo)
- return m_fbo->toImage();
-
- return QImage();
-}
-
class QQuickShaderEffectSourceCleanup : public QRunnable
{
public:
- QQuickShaderEffectSourceCleanup(QQuickShaderEffectTexture *t, QQuickShaderEffectSourceTextureProvider *p)
+ QQuickShaderEffectSourceCleanup(QSGLayer *t, QQuickShaderEffectSourceTextureProvider *p)
: texture(t)
, provider(p)
{}
@@ -502,7 +95,7 @@ public:
delete texture;
delete provider;
}
- QQuickShaderEffectTexture *texture;
+ QSGLayer *texture;
QQuickShaderEffectSourceTextureProvider *provider;
};
@@ -642,7 +235,8 @@ void QQuickShaderEffectSource::ensureTexture()
"QQuickShaderEffectSource::ensureTexture",
"Cannot be used outside the rendering thread");
- m_texture = new QQuickShaderEffectTexture(this);
+ QSGRenderContext *rc = QQuickItemPrivate::get(this)->sceneGraphRenderContext();
+ m_texture = rc->sceneGraphContext()->createLayer(rc);
connect(QQuickItemPrivate::get(this)->window, SIGNAL(sceneGraphInvalidated()), m_texture, SLOT(invalidated()), Qt::DirectConnection);
connect(m_texture, SIGNAL(updateRequested()), this, SLOT(update()));
connect(m_texture, SIGNAL(scheduledUpdateCompleted()), this, SIGNAL(scheduledUpdateCompleted()));