aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/designer/designersupport.cpp9
-rw-r--r--src/quick/designer/designersupport.h4
-rw-r--r--src/quick/items/context2d/qquickcanvascontext_p.h2
-rw-r--r--src/quick/items/qquickitemgrabresult.cpp5
-rw-r--r--src/quick/items/qquickshadereffectnode.cpp2
-rw-r--r--src/quick/items/qquickshadereffectsource.cpp416
-rw-r--r--src/quick/items/qquickshadereffectsource_p.h93
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp22
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h31
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp9
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h2
-rw-r--r--src/quick/scenegraph/qsgdefaultimagenode.cpp2
-rw-r--r--src/quick/scenegraph/qsgdefaultlayer.cpp445
-rw-r--r--src/quick/scenegraph/qsgdefaultlayer_p.h131
-rw-r--r--src/quick/scenegraph/scenegraph.pri6
15 files changed, 663 insertions, 516 deletions
diff --git a/src/quick/designer/designersupport.cpp b/src/quick/designer/designersupport.cpp
index 82f796361b..a57c1ae569 100644
--- a/src/quick/designer/designersupport.cpp
+++ b/src/quick/designer/designersupport.cpp
@@ -65,10 +65,10 @@ DesignerSupport::DesignerSupport()
DesignerSupport::~DesignerSupport()
{
- QHash<QQuickItem*, QQuickShaderEffectTexture*>::iterator iterator;
+ QHash<QQuickItem*, QSGLayer*>::iterator iterator;
for (iterator = m_itemTextureHash.begin(); iterator != m_itemTextureHash.end(); ++iterator) {
- QQuickShaderEffectTexture *texture = iterator.value();
+ QSGLayer *texture = iterator.value();
QQuickItem *item = iterator.key();
QQuickItemPrivate::get(item)->derefFromEffectItem(true);
delete texture;
@@ -86,7 +86,8 @@ void DesignerSupport::refFromEffectItem(QQuickItem *referencedItem, bool hide)
Q_ASSERT(QQuickItemPrivate::get(referencedItem)->rootNode());
if (!m_itemTextureHash.contains(referencedItem)) {
- QQuickShaderEffectTexture *texture = new QQuickShaderEffectTexture(referencedItem);
+ QSGRenderContext *rc = QQuickWindowPrivate::get(referencedItem->window())->context;
+ QSGLayer *texture = rc->sceneGraphContext()->createLayer(rc);
texture->setLive(true);
texture->setItem(QQuickItemPrivate::get(referencedItem)->rootNode());
@@ -123,7 +124,7 @@ QImage DesignerSupport::renderImageForItem(QQuickItem *referencedItem, const QRe
return QImage();
}
- QQuickShaderEffectTexture *renderTexture = m_itemTextureHash.value(referencedItem);
+ QSGLayer *renderTexture = m_itemTextureHash.value(referencedItem);
Q_ASSERT(renderTexture);
if (renderTexture == 0)
diff --git a/src/quick/designer/designersupport.h b/src/quick/designer/designersupport.h
index 41458ae3d6..8dfb4af167 100644
--- a/src/quick/designer/designersupport.h
+++ b/src/quick/designer/designersupport.h
@@ -62,7 +62,7 @@
QT_BEGIN_NAMESPACE
class QQuickItem;
-class QQuickShaderEffectTexture;
+class QSGLayer;
class QImage;
class QTransform;
class QQmlContext;
@@ -154,7 +154,7 @@ public:
static void polishItems(QQuickWindow *window);
private:
- QHash<QQuickItem*, QQuickShaderEffectTexture*> m_itemTextureHash;
+ QHash<QQuickItem*, QSGLayer*> m_itemTextureHash;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/context2d/qquickcanvascontext_p.h b/src/quick/items/context2d/qquickcanvascontext_p.h
index 2d8fbb5f85..8988ea9105 100644
--- a/src/quick/items/context2d/qquickcanvascontext_p.h
+++ b/src/quick/items/context2d/qquickcanvascontext_p.h
@@ -49,7 +49,7 @@
QT_BEGIN_NAMESPACE
class QQuickCanvasItem;
-class QSGDynamicTexture;
+class QSGLayer;
class QQuickCanvasContextPrivate;
class QQuickCanvasContext : public QObject
diff --git a/src/quick/items/qquickitemgrabresult.cpp b/src/quick/items/qquickitemgrabresult.cpp
index 93b9261c44..f5d72bbd3a 100644
--- a/src/quick/items/qquickitemgrabresult.cpp
+++ b/src/quick/items/qquickitemgrabresult.cpp
@@ -91,7 +91,7 @@ public:
QPointer<QQuickItem> item;
QPointer<QQuickWindow> window;
- QQuickShaderEffectTexture *texture;
+ QSGLayer *texture;
QSizeF itemSize;
QSize textureSize;
};
@@ -228,7 +228,8 @@ void QQuickItemGrabResult::setup()
return;
}
- d->texture = new QQuickShaderEffectTexture(d->item);
+ QSGRenderContext *rc = QQuickWindowPrivate::get(d->window.data())->context;
+ d->texture = rc->sceneGraphContext()->createLayer(rc);
d->texture->setItem(QQuickItemPrivate::get(d->item)->itemNode());
d->itemSize = QSizeF(d->item->width(), d->item->height());
}
diff --git a/src/quick/items/qquickshadereffectnode.cpp b/src/quick/items/qquickshadereffectnode.cpp
index cefb006648..3f7938c386 100644
--- a/src/quick/items/qquickshadereffectnode.cpp
+++ b/src/quick/items/qquickshadereffectnode.cpp
@@ -418,7 +418,7 @@ void QQuickShaderEffectMaterial::updateTextures() const
{
for (int i = 0; i < textureProviders.size(); ++i) {
if (QSGTextureProvider *provider = textureProviders.at(i)) {
- if (QSGDynamicTexture *texture = qobject_cast<QSGDynamicTexture *>(provider->texture()))
+ if (QSGLayer *texture = qobject_cast<QSGLayer *>(provider->texture()))
texture->updateTexture();
}
}
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()));
diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h
index 4caeaab52c..35899339ce 100644
--- a/src/quick/items/qquickshadereffectsource_p.h
+++ b/src/quick/items/qquickshadereffectsource_p.h
@@ -53,8 +53,6 @@
#include "qsize.h"
#include "qrect.h"
-#define QSG_DEBUG_FBO_OVERLAY
-
QT_BEGIN_NAMESPACE
class QSGNode;
@@ -64,95 +62,6 @@ class QSGSimpleRectNode;
class QQuickShaderEffectSourceTextureProvider;
-class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffectTexture : public QSGDynamicTexture
-{
- Q_OBJECT
-public:
- QQuickShaderEffectTexture(QQuickItem *shaderSource);
- ~QQuickShaderEffectTexture();
-
- virtual bool updateTexture();
-
- // The item's "paint node", not effect node.
- QSGNode *item() const { return m_item; }
- void setItem(QSGNode *item);
-
- void setShaderSourceNode(QSGNode *node) { m_shaderSourceNode = node; }
-
- QRectF rect() const { return m_rect; }
- void setRect(const QRectF &rect);
-
- QSize size() const { return m_size; }
- void setSize(const QSize &size);
-
- void setHasMipmaps(bool mipmap);
-
- void bind();
-
- bool hasAlphaChannel() const;
- bool hasMipmaps() const;
- int textureId() const;
- QSize textureSize() const { return m_size; }
-
- GLenum format() const { return m_format; }
- void setFormat(GLenum format);
-
- bool live() const { return bool(m_live); }
- void setLive(bool live);
-
- bool recursive() const { return bool(m_recursive); }
- void setRecursive(bool recursive);
-
- void setDevicePixelRatio(qreal ratio) { m_device_pixel_ratio = ratio; }
-
- void scheduleUpdate();
-
- QImage toImage() const;
-
-Q_SIGNALS:
- void updateRequested();
- void scheduledUpdateCompleted();
-
-public Q_SLOTS:
- void markDirtyTexture();
- void invalidated();
- void markDirtyTextureLater();
-
-protected:
- virtual void customEvent(QEvent *);
-
-private:
- void grab();
-
- QSGNode *m_item;
- QSGNode *m_shaderSourceNode;
- QRectF m_rect;
- QSize m_size;
- qreal m_device_pixel_ratio;
- GLenum m_format;
-
- QSGRenderer *m_renderer;
- QOpenGLFramebufferObject *m_fbo;
- QOpenGLFramebufferObject *m_secondaryFbo;
- QSharedPointer<QSGDepthStencilBuffer> m_depthStencilBuffer;
-
- GLuint m_transparentTexture;
-
-#ifdef QSG_DEBUG_FBO_OVERLAY
- QSGSimpleRectNode *m_debugOverlay;
-#endif
-
- QSGRenderContext *m_context;
-
- uint m_mipmap : 1;
- uint m_live : 1;
- uint m_recursive : 1;
- uint m_dirtyTexture : 1;
- uint m_multisamplingChecked : 1;
- uint m_multisampling : 1;
- uint m_grab : 1;
-};
-
class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffectSource : public QQuickItem, public QQuickItemChangeListener
{
Q_OBJECT
@@ -244,7 +153,7 @@ private:
void ensureTexture();
QQuickShaderEffectSourceTextureProvider *m_provider;
- QQuickShaderEffectTexture *m_texture;
+ QSGLayer *m_texture;
WrapMode m_wrapMode;
QQuickItem *m_sourceItem;
QRectF m_sourceRect;
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index ee077dbaf1..68b1882c3f 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -328,6 +328,7 @@ void QSGNodeVisitorEx::visitChildren(QSGNode *node)
}
break;
}
+ case QSGNode::RootNodeType: // fall through
case QSGNode::BasicNodeType: {
visitChildren(child);
break;
@@ -339,4 +340,25 @@ void QSGNodeVisitorEx::visitChildren(QSGNode *node)
}
}
+void QSGLayer::markDirtyTextureLater()
+{
+ QCoreApplication::postEvent(this, new QEvent(static_cast<QEvent::Type>(markDirtyEventType())));
+}
+
+void QSGLayer::customEvent(QEvent *event)
+{
+ if (event->type() == markDirtyEventType())
+ markDirtyTexture();
+ else
+ QObject::customEvent(event);
+}
+
+int QSGLayer::markDirtyEventType()
+{
+ static int type = QEvent::None;
+ if (type == QEvent::None)
+ type = QEvent::registerEventType();
+ return type;
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index cc998a9cef..2e17cfdf40 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -158,6 +158,37 @@ public:
virtual void accept(QSGNodeVisitorEx *visitor) { visitor->visit(this); visitor->visitChildren(this); visitor->endVisit(this); }
};
+class Q_QUICK_EXPORT QSGLayer : public QSGDynamicTexture
+{
+ Q_OBJECT
+public:
+ virtual void setItem(QSGNode *item) = 0;
+ virtual void setShaderSourceNode(QSGNode *node) = 0;
+ virtual void setRect(const QRectF &rect) = 0;
+ virtual void setSize(const QSize &size) = 0;
+ virtual void scheduleUpdate() = 0;
+ virtual QImage toImage() const = 0;
+ virtual void setLive(bool live) = 0;
+ virtual void setRecursive(bool recursive) = 0;
+ virtual void setFormat(GLenum format) = 0;
+ virtual void setHasMipmaps(bool mipmap) = 0;
+ virtual void setDevicePixelRatio(qreal ratio) = 0;
+ Q_SLOT virtual void markDirtyTexture() = 0;
+ Q_SLOT virtual void invalidated() = 0;
+
+ Q_SLOT void markDirtyTextureLater();
+
+Q_SIGNALS:
+ void updateRequested();
+ void scheduledUpdateCompleted();
+
+protected:
+ virtual void customEvent(QEvent *);
+
+private:
+ int markDirtyEventType();
+};
+
class Q_QUICK_PRIVATE_EXPORT QSGGlyphNode : public QSGVisitableNode
{
public:
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index f69dd7adde..6ebc479ec5 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -51,6 +51,7 @@
#include <QtQuick/private/qsgshareddistancefieldglyphcache_p.h>
#include <QtQuick/private/qsgatlastexture_p.h>
#include <QtQuick/private/qsgrenderloop_p.h>
+#include <QtQuick/private/qsgdefaultlayer_p.h>
#include <QtQuick/private/qsgtexture_p.h>
#include <QtQuick/private/qquickpixmapcache_p.h>
@@ -321,6 +322,14 @@ QSGNinePatchNode *QSGContext::createNinePatchNode()
return 0;
}
+/*!
+ Factory function for scene graph backends of layers.
+ */
+QSGLayer *QSGContext::createLayer(QSGRenderContext *renderContext)
+{
+ return new QSGDefaultLayer(renderContext);
+}
+
QSurfaceFormat QSGContext::defaultSurfaceFormat() const
{
QSurfaceFormat format = QSurfaceFormat::defaultFormat();
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index abf1abd4c0..b5271f9f37 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -72,6 +72,7 @@ class QSGTexture;
class QSGMaterial;
class QSGMaterialShader;
class QSGRenderLoop;
+class QSGLayer;
class QOpenGLContext;
class QOpenGLFramebufferObject;
@@ -177,6 +178,7 @@ public:
virtual QSGImageNode *createImageNode();
virtual QSGGlyphNode *createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode);
virtual QSGNinePatchNode *createNinePatchNode();
+ virtual QSGLayer *createLayer(QSGRenderContext *renderContext);
virtual QAnimationDriver *createAnimationDriver(QObject *parent);
virtual QSize minimumFBOSize() const;
diff --git a/src/quick/scenegraph/qsgdefaultimagenode.cpp b/src/quick/scenegraph/qsgdefaultimagenode.cpp
index d925b1c7c4..7c70a259aa 100644
--- a/src/quick/scenegraph/qsgdefaultimagenode.cpp
+++ b/src/quick/scenegraph/qsgdefaultimagenode.cpp
@@ -292,7 +292,7 @@ void QSGDefaultImageNode::update()
void QSGDefaultImageNode::preprocess()
{
bool doDirty = false;
- QSGDynamicTexture *t = qobject_cast<QSGDynamicTexture *>(m_material.texture());
+ QSGLayer *t = qobject_cast<QSGLayer *>(m_material.texture());
if (t) {
doDirty = t->updateTexture();
updateGeometry();
diff --git a/src/quick/scenegraph/qsgdefaultlayer.cpp b/src/quick/scenegraph/qsgdefaultlayer.cpp
new file mode 100644
index 0000000000..c93517fe3f
--- /dev/null
+++ b/src/quick/scenegraph/qsgdefaultlayer.cpp
@@ -0,0 +1,445 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qsgdefaultlayer_p.h"
+
+#include <private/qqmlglobal_p.h>
+#include <private/qsgrenderer_p.h>
+
+#include <QOpenGLFramebufferObject>
+
+#ifdef QSG_DEBUG_FBO_OVERLAY
+DEFINE_BOOL_CONFIG_OPTION(qmlFboOverlay, QML_FBO_OVERLAY)
+#endif
+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();
+ }
+}
+
+QSGDefaultLayer::QSGDefaultLayer(QSGRenderContext *context)
+ : QSGLayer()
+ , 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(context)
+ , m_mipmap(false)
+ , m_live(true)
+ , m_recursive(false)
+ , m_dirtyTexture(true)
+ , m_multisamplingChecked(false)
+ , m_multisampling(false)
+ , m_grab(false)
+{
+}
+
+QSGDefaultLayer::~QSGDefaultLayer()
+{
+ invalidated();
+}
+
+void QSGDefaultLayer::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;
+ }
+}
+
+int QSGDefaultLayer::textureId() const
+{
+ return m_fbo ? m_fbo->texture() : 0;
+}
+
+bool QSGDefaultLayer::hasAlphaChannel() const
+{
+ return m_format != GL_RGB;
+}
+
+bool QSGDefaultLayer::hasMipmaps() const
+{
+ return m_mipmap;
+}
+
+
+void QSGDefaultLayer::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 QSGDefaultLayer::updateTexture()
+{
+ bool doGrab = (m_live || m_grab) && m_dirtyTexture;
+ if (doGrab)
+ grab();
+ if (m_grab)
+ emit scheduledUpdateCompleted();
+ m_grab = false;
+ return doGrab;
+}
+
+void QSGDefaultLayer::setHasMipmaps(bool mipmap)
+{
+ if (mipmap == m_mipmap)
+ return;
+ m_mipmap = mipmap;
+ if (m_mipmap && m_fbo && !m_fbo->format().mipmap())
+ markDirtyTexture();
+}
+
+
+void QSGDefaultLayer::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 QSGDefaultLayer::setRect(const QRectF &rect)
+{
+ if (rect == m_rect)
+ return;
+ m_rect = rect;
+ markDirtyTexture();
+}
+
+void QSGDefaultLayer::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 QSGDefaultLayer::setFormat(GLenum format)
+{
+ if (format == m_format)
+ return;
+ m_format = format;
+ markDirtyTexture();
+}
+
+void QSGDefaultLayer::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 QSGDefaultLayer::scheduleUpdate()
+{
+ if (m_grab)
+ return;
+ m_grab = true;
+ if (m_dirtyTexture) {
+ emit updateRequested();
+ if (m_shaderSourceNode)
+ m_shaderSourceNode->markDirty(QSGNode::DirtyMaterial);
+ }
+}
+
+void QSGDefaultLayer::setRecursive(bool recursive)
+{
+ m_recursive = recursive;
+}
+
+void QSGDefaultLayer::markDirtyTexture()
+{
+ m_dirtyTexture = true;
+ if (m_live || m_grab) {
+ emit updateRequested();
+ if (m_shaderSourceNode)
+ m_shaderSourceNode->markDirty(QSGNode::DirtyMaterial);
+ }
+}
+
+void QSGDefaultLayer::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 QSGDefaultLayer::toImage() const
+{
+ if (m_fbo)
+ return m_fbo->toImage();
+
+ return QImage();
+}
diff --git a/src/quick/scenegraph/qsgdefaultlayer_p.h b/src/quick/scenegraph/qsgdefaultlayer_p.h
new file mode 100644
index 0000000000..47a0448846
--- /dev/null
+++ b/src/quick/scenegraph/qsgdefaultlayer_p.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QSGDEFAULTLAYER_P_H
+#define QSGDEFAULTLAYER_P_H
+
+#include <private/qsgadaptationlayer_p.h>
+#include <private/qsgcontext_p.h>
+#include <qsgsimplerectnode.h>
+
+#define QSG_DEBUG_FBO_OVERLAY
+
+class Q_QUICK_PRIVATE_EXPORT QSGDefaultLayer : public QSGLayer
+{
+ Q_OBJECT
+public:
+ QSGDefaultLayer(QSGRenderContext *context);
+ ~QSGDefaultLayer();
+
+ virtual bool updateTexture();
+
+ // The item's "paint node", not effect node.
+ QSGNode *item() const { return m_item; }
+ void setItem(QSGNode *item);
+
+ void setShaderSourceNode(QSGNode *node) { m_shaderSourceNode = node; }
+
+ QRectF rect() const { return m_rect; }
+ void setRect(const QRectF &rect);
+
+ QSize size() const { return m_size; }
+ void setSize(const QSize &size);
+
+ void setHasMipmaps(bool mipmap);
+
+ void bind();
+
+ bool hasAlphaChannel() const;
+ bool hasMipmaps() const;
+ int textureId() const;
+ QSize textureSize() const { return m_size; }
+
+ GLenum format() const { return m_format; }
+ void setFormat(GLenum format);
+
+ bool live() const { return bool(m_live); }
+ void setLive(bool live);
+
+ bool recursive() const { return bool(m_recursive); }
+ void setRecursive(bool recursive);
+
+ void setDevicePixelRatio(qreal ratio) { m_device_pixel_ratio = ratio; }
+
+ void scheduleUpdate();
+
+ QImage toImage() const;
+
+public Q_SLOTS:
+ void markDirtyTexture();
+ void invalidated();
+
+private:
+ void grab();
+
+ QSGNode *m_item;
+ QSGNode *m_shaderSourceNode;
+ QRectF m_rect;
+ QSize m_size;
+ qreal m_device_pixel_ratio;
+ GLenum m_format;
+
+ QSGRenderer *m_renderer;
+ QOpenGLFramebufferObject *m_fbo;
+ QOpenGLFramebufferObject *m_secondaryFbo;
+ QSharedPointer<QSGDepthStencilBuffer> m_depthStencilBuffer;
+
+ GLuint m_transparentTexture;
+
+#ifdef QSG_DEBUG_FBO_OVERLAY
+ QSGSimpleRectNode *m_debugOverlay;
+#endif
+
+ QSGRenderContext *m_context;
+
+ uint m_mipmap : 1;
+ uint m_live : 1;
+ uint m_recursive : 1;
+ uint m_dirtyTexture : 1;
+ uint m_multisamplingChecked : 1;
+ uint m_multisampling : 1;
+ uint m_grab : 1;
+};
+
+#endif // QSGDEFAULTLAYER_P_H
diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri
index d08fce0336..4d9d7444b3 100644
--- a/src/quick/scenegraph/scenegraph.pri
+++ b/src/quick/scenegraph/scenegraph.pri
@@ -81,7 +81,8 @@ HEADERS += \
$$PWD/qsgshareddistancefieldglyphcache_p.h \
$$PWD/qsgrenderloop_p.h \
$$PWD/qsgthreadedrenderloop_p.h \
- $$PWD/qsgwindowsrenderloop_p.h
+ $$PWD/qsgwindowsrenderloop_p.h \
+ $$PWD/qsgdefaultlayer_p.h
SOURCES += \
$$PWD/qsgadaptationlayer.cpp \
@@ -97,7 +98,8 @@ SOURCES += \
$$PWD/qsgshareddistancefieldglyphcache.cpp \
$$PWD/qsgrenderloop.cpp \
$$PWD/qsgthreadedrenderloop.cpp \
- $$PWD/qsgwindowsrenderloop.cpp
+ $$PWD/qsgwindowsrenderloop.cpp \
+ $$PWD/qsgdefaultlayer.cpp
RESOURCES += \
$$PWD/scenegraph.qrc