aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2017-02-17 09:47:49 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2017-02-23 13:19:37 +0000
commit48c31733383d14447d1c383cefca9ca40daa6a87 (patch)
treee37b14b0ee3bfb841a99baf5c503db8b150a3df9 /src
parent0abdf6db0ee56069407953be2a9e690348a03fd1 (diff)
Add samples property for Item.layer and ShaderEffectSource
[ChangeLog][Qt Quick] Added the properties ShaderEffectSource.samples and Item.layer.samples to allow requesting MSAA rendering of an item subtree, without enabling multisampling for the entire scene. Task-number: QTBUG-58945 Change-Id: I9102cfabba10d4dc1e7ad2aa0b258ada6d9a5a47 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h1
-rw-r--r--src/quick/items/qquickitem.cpp40
-rw-r--r--src/quick/items/qquickitem_p.h7
-rw-r--r--src/quick/items/qquickitemsmodule.cpp4
-rw-r--r--src/quick/items/qquickshadereffectsource.cpp40
-rw-r--r--src/quick/items/qquickshadereffectsource_p.h6
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarelayer_p.h1
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h1
-rw-r--r--src/quick/scenegraph/qsgdefaultlayer.cpp20
-rw-r--r--src/quick/scenegraph/qsgdefaultlayer_p.h4
10 files changed, 119 insertions, 5 deletions
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h
index f1ab580a84..f828843227 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h
@@ -86,6 +86,7 @@ public:
void setDevicePixelRatio(qreal ratio) override;
void setMirrorHorizontal(bool mirror) override;
void setMirrorVertical(bool mirror) override;
+ void setSamples(int) override { }
public Q_SLOTS:
void markDirtyTexture() override;
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index f7b9a58329..22ee3f39e4 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -7865,6 +7865,7 @@ QQuickItemLayer::QQuickItemLayer(QQuickItem *item)
, m_effect(0)
, m_effectSource(0)
, m_textureMirroring(QQuickShaderEffectSource::MirrorVertically)
+ , m_samples(0)
{
}
@@ -7939,6 +7940,7 @@ void QQuickItemLayer::activate()
m_effectSource->setWrapMode(m_wrapMode);
m_effectSource->setFormat(m_format);
m_effectSource->setTextureMirroring(m_textureMirroring);
+ m_effectSource->setSamples(m_samples);
if (m_effectComponent)
activateEffect();
@@ -8232,6 +8234,44 @@ void QQuickItemLayer::setTextureMirroring(QQuickShaderEffectSource::TextureMirro
}
/*!
+ \qmlproperty enumeration QtQuick::Item::layer.samples
+ \since 5.10
+
+ This property allows requesting multisampled rendering in the layer.
+
+ By default multisampling is enabled whenever multisampling is
+ enabled for the entire window, assuming the scenegraph renderer in
+ use and the underlying graphics API supports this.
+
+ By setting the value to 2, 4, etc. multisampled rendering can be requested
+ for a part of the scene without enabling multisampling for the entire
+ scene. This way multisampling is applied only to a given subtree, which can
+ lead to significant performance gains since multisampling is not applied to
+ other parts of the scene.
+
+ \note Enabling multisampling can be potentially expensive regardless of the
+ layer's size, as it incurs a hardware and driver dependent performance and
+ memory cost.
+
+ \note This property is only functional when support for multisample
+ renderbuffers and framebuffer blits is available. Otherwise the value is
+ silently ignored.
+ */
+
+void QQuickItemLayer::setSamples(int count)
+{
+ if (m_samples == count)
+ return;
+
+ m_samples = count;
+
+ if (m_effectSource)
+ m_effectSource->setSamples(m_samples);
+
+ emit samplesChanged(count);
+}
+
+/*!
\qmlproperty string QtQuick::Item::layer.samplerName
Holds the name of the effect's source texture property.
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index c0c9bd46bd..797ba42781 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -152,6 +152,8 @@ class QQuickItemLayer : public QObject, public QQuickItemChangeListener
Q_PROPERTY(QByteArray samplerName READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(QQmlComponent *effect READ effect WRITE setEffect NOTIFY effectChanged)
Q_PROPERTY(QQuickShaderEffectSource::TextureMirroring textureMirroring READ textureMirroring WRITE setTextureMirroring NOTIFY textureMirroringChanged)
+ Q_PROPERTY(int samples READ samples WRITE setSamples NOTIFY samplesChanged)
+
public:
QQuickItemLayer(QQuickItem *item);
~QQuickItemLayer();
@@ -189,6 +191,9 @@ public:
QQuickShaderEffectSource::TextureMirroring textureMirroring() const { return m_textureMirroring; }
void setTextureMirroring(QQuickShaderEffectSource::TextureMirroring mirroring);
+ int samples() const { return m_samples; }
+ void setSamples(int count);
+
QQuickShaderEffectSource *effectSource() const { return m_effectSource; }
void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) Q_DECL_OVERRIDE;
@@ -213,6 +218,7 @@ Q_SIGNALS:
void formatChanged(QQuickShaderEffectSource::Format format);
void sourceRectChanged(const QRectF &sourceRect);
void textureMirroringChanged(QQuickShaderEffectSource::TextureMirroring mirroring);
+ void samplesChanged(int count);
private:
friend class QQuickTransformAnimatorJob;
@@ -237,6 +243,7 @@ private:
QQuickItem *m_effect;
QQuickShaderEffectSource *m_effectSource;
QQuickShaderEffectSource::TextureMirroring m_textureMirroring;
+ int m_samples;
};
#endif
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index a8824de9c8..eeffe1ee48 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -385,6 +385,10 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterUncreatableType<QQuickBasePositioner, 9>(uri, 2, 9, "Positioner",
QStringLiteral("Positioner is an abstract type that is only available as an attached property."));
#endif
+
+#if QT_CONFIG(quick_shadereffect)
+ qmlRegisterType<QQuickShaderEffectSource, 2>(uri, 2, 9, "ShaderEffectSource");
+#endif
}
static void initResources()
diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp
index 1b37a746d3..c782ddb5f7 100644
--- a/src/quick/items/qquickshadereffectsource.cpp
+++ b/src/quick/items/qquickshadereffectsource.cpp
@@ -189,6 +189,7 @@ QQuickShaderEffectSource::QQuickShaderEffectSource(QQuickItem *parent)
, m_sourceItem(0)
, m_textureSize(0, 0)
, m_format(RGBA)
+ , m_samples(0)
, m_live(true)
, m_hideSource(false)
, m_mipmap(false)
@@ -582,6 +583,44 @@ void QQuickShaderEffectSource::setTextureMirroring(TextureMirroring mirroring)
}
/*!
+ \qmlproperty int QtQuick::ShaderEffectSource::samples
+ \since 5.10
+
+ This property allows requesting multisampled rendering.
+
+ By default multisampling is enabled whenever multisampling is enabled for
+ the entire window, assuming the scenegraph renderer in use and the
+ underlying graphics API supports this.
+
+ By setting the value to 2, 4, etc. multisampled rendering can be requested
+ for a part of the scene without enabling multisampling for the entire
+ scene. This way multisampling is applied only to a given subtree, which can
+ lead to significant performance gains since multisampling is not applied to
+ other parts of the scene.
+
+ \note Enabling multisampling can be potentially expensive regardless of the
+ layer's size, as it incurs a hardware and driver dependent performance and
+ memory cost.
+
+ \note This property is only functional when support for multisample
+ renderbuffers and framebuffer blits is available. Otherwise the value is
+ silently ignored.
+ */
+int QQuickShaderEffectSource::samples() const
+{
+ return m_samples;
+}
+
+void QQuickShaderEffectSource::setSamples(int count)
+{
+ if (count == m_samples)
+ return;
+ m_samples = count;
+ update();
+ emit samplesChanged();
+}
+
+/*!
\qmlmethod QtQuick::ShaderEffectSource::scheduleUpdate()
Schedules a re-rendering of the texture for the next frame.
@@ -683,6 +722,7 @@ QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaint
m_texture->setHasMipmaps(m_mipmap);
m_texture->setMirrorHorizontal(m_textureMirroring & MirrorHorizontally);
m_texture->setMirrorVertical(m_textureMirroring & MirrorVertically);
+ m_texture->setSamples(m_samples);
if (m_grab)
m_texture->scheduleUpdate();
diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h
index 5e7e354feb..d9f9079a3d 100644
--- a/src/quick/items/qquickshadereffectsource_p.h
+++ b/src/quick/items/qquickshadereffectsource_p.h
@@ -88,6 +88,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffectSource : public QQuickItem, publi
Q_PROPERTY(bool mipmap READ mipmap WRITE setMipmap NOTIFY mipmapChanged)
Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged)
Q_PROPERTY(TextureMirroring textureMirroring READ textureMirroring WRITE setTextureMirroring NOTIFY textureMirroringChanged REVISION 1)
+ Q_PROPERTY(int samples READ samples WRITE setSamples NOTIFY samplesChanged REVISION 2)
public:
enum WrapMode {
@@ -150,6 +151,9 @@ public:
Q_INVOKABLE void scheduleUpdate();
+ int samples() const;
+ void setSamples(int count);
+
Q_SIGNALS:
void wrapModeChanged();
void sourceItemChanged();
@@ -161,6 +165,7 @@ Q_SIGNALS:
void mipmapChanged();
void recursiveChanged();
void textureMirroringChanged();
+ void samplesChanged();
void scheduledUpdateCompleted();
@@ -185,6 +190,7 @@ private:
QRectF m_sourceRect;
QSize m_textureSize;
Format m_format;
+ int m_samples;
uint m_live : 1;
uint m_hideSource : 1;
uint m_mipmap : 1;
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer_p.h
index d3f13e40b1..9f5a22e66f 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer_p.h
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer_p.h
@@ -93,6 +93,7 @@ public:
void setDevicePixelRatio(qreal ratio) override;
void setMirrorHorizontal(bool mirror) override;
void setMirrorVertical(bool mirror) override;
+ void setSamples(int) override { }
public slots:
void markDirtyTexture() override;
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index 03a1f7f281..a8e35b1ac1 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -209,6 +209,7 @@ public:
virtual void setDevicePixelRatio(qreal ratio) = 0;
virtual void setMirrorHorizontal(bool mirror) = 0;
virtual void setMirrorVertical(bool mirror) = 0;
+ virtual void setSamples(int samples) = 0;
Q_SLOT virtual void markDirtyTexture() = 0;
Q_SLOT virtual void invalidated() = 0;
diff --git a/src/quick/scenegraph/qsgdefaultlayer.cpp b/src/quick/scenegraph/qsgdefaultlayer.cpp
index ad5b57ff83..fc8040e67b 100644
--- a/src/quick/scenegraph/qsgdefaultlayer.cpp
+++ b/src/quick/scenegraph/qsgdefaultlayer.cpp
@@ -99,6 +99,7 @@ QSGDefaultLayer::QSGDefaultLayer(QSGRenderContext *context)
#ifdef QSG_DEBUG_FBO_OVERLAY
, m_debugOverlay(0)
#endif
+ , m_samples(0)
, m_mipmap(false)
, m_live(true)
, m_recursive(false)
@@ -313,11 +314,20 @@ void QSGDefaultLayer::grab()
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))
- {
+
+ int effectiveSamples = m_samples;
+ // By default m_samples is 0. Fall back to the context's setting in this case.
+ if (effectiveSamples == 0)
+ effectiveSamples = m_context->openglContext()->format().samples();
+
+ const bool needsNewFbo = !m_fbo || m_fbo->size() != m_size || m_fbo->format().internalTextureFormat() != m_format;
+ const bool mipmapGotEnabled = m_fbo && !m_fbo->format().mipmap() && m_mipmap;
+ const bool msaaGotEnabled = effectiveSamples > 1 && (!m_secondaryFbo || m_secondaryFbo->format().samples() != effectiveSamples);
+ const bool msaaGotDisabled = effectiveSamples <= 1 && m_secondaryFbo;
+
+ if (needsNewFbo || mipmapGotEnabled || msaaGotEnabled || msaaGotDisabled) {
if (!m_multisamplingChecked) {
- if (m_context->openglContext()->format().samples() <= 1) {
+ if (effectiveSamples <= 1) {
m_multisampling = false;
} else {
const QSet<QByteArray> extensions = m_context->openglContext()->extensions();
@@ -333,7 +343,7 @@ void QSGDefaultLayer::grab()
QOpenGLFramebufferObjectFormat format;
format.setInternalTextureFormat(m_format);
- format.setSamples(m_context->openglContext()->format().samples());
+ format.setSamples(effectiveSamples);
m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo);
} else {
diff --git a/src/quick/scenegraph/qsgdefaultlayer_p.h b/src/quick/scenegraph/qsgdefaultlayer_p.h
index ae39994096..7b09293095 100644
--- a/src/quick/scenegraph/qsgdefaultlayer_p.h
+++ b/src/quick/scenegraph/qsgdefaultlayer_p.h
@@ -113,6 +113,9 @@ public:
QRectF normalizedTextureSubRect() const Q_DECL_OVERRIDE;
+ int samples() const { return m_samples; }
+ void setSamples(int samples) Q_DECL_OVERRIDE { m_samples = samples; }
+
public Q_SLOTS:
void markDirtyTexture() Q_DECL_OVERRIDE;
void invalidated() Q_DECL_OVERRIDE;
@@ -138,6 +141,7 @@ private:
#endif
QSGDefaultRenderContext *m_context;
+ int m_samples;
uint m_mipmap : 1;
uint m_live : 1;