From 3f4d7a755585f1b79c7e9675220b8210f10f358e Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 10 Aug 2015 14:33:14 +0300 Subject: Add possibility to mirror ShaderEffectSource generated textures Using textures generated by ShaderEffectSource items (or Item.layer) with custom OpenGL code was non-intuitive due to mismatching coordinate systems, so added a possibility to control the generated texture orientation. [ChangeLog][QtQuick][ShaderEffectSource] Added possibility to mirror generated OpenGL texture. Change-Id: I7c03d8b6fbfc43d69812c15d244200fb8e7c7bb9 Reviewed-by: Gunnar Sletta --- src/quick/items/qquickitem.cpp | 31 +++++++++++++++++++++++++ src/quick/items/qquickitem_p.h | 6 +++++ src/quick/items/qquickitemsmodule.cpp | 1 + src/quick/items/qquickshadereffectsource.cpp | 34 ++++++++++++++++++++++++++++ src/quick/items/qquickshadereffectsource_p.h | 13 +++++++++++ src/quick/scenegraph/qsgadaptationlayer_p.h | 2 ++ src/quick/scenegraph/qsgdefaultlayer.cpp | 25 +++++++++++++++++++- src/quick/scenegraph/qsgdefaultlayer_p.h | 10 ++++++++ 8 files changed, 121 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 32c3e651d..0c9ee4fe7 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -7488,6 +7488,7 @@ QQuickItemLayer::QQuickItemLayer(QQuickItem *item) , m_effectComponent(0) , m_effect(0) , m_effectSource(0) + , m_textureMirroring(QQuickShaderEffectSource::MirrorVertically) { } @@ -7559,6 +7560,7 @@ void QQuickItemLayer::activate() m_effectSource->setMipmap(m_mipmap); m_effectSource->setWrapMode(m_wrapMode); m_effectSource->setFormat(m_format); + m_effectSource->setTextureMirroring(m_textureMirroring); if (m_effectComponent) activateEffect(); @@ -7811,6 +7813,35 @@ void QQuickItemLayer::setWrapMode(QQuickShaderEffectSource::WrapMode mode) emit wrapModeChanged(mode); } +/*! + \qmlproperty enumeration QtQuick::Item::layer.textureMirroring + \since 5.6 + + This property defines how the generated OpenGL texture should be mirrored. + The default value is \c{ShaderEffectSource.MirrorVertically}. + Custom mirroring can be useful if the generated texture is directly accessed by custom shaders, + such as those specified by ShaderEffect. If no effect is specified for the layered + item, mirroring has no effect on the UI representation of the item. + + \list + \li ShaderEffectSource.NoMirroring - No mirroring + \li ShaderEffectSource.MirrorHorizontally - The generated texture is flipped along X-axis. + \li ShaderEffectSource.MirrorVertically - The generated texture is flipped along Y-axis. + \endlist + */ + +void QQuickItemLayer::setTextureMirroring(QQuickShaderEffectSource::TextureMirroring mirroring) +{ + if (mirroring == m_textureMirroring) + return; + m_textureMirroring = mirroring; + + if (m_effectSource) + m_effectSource->setTextureMirroring(m_textureMirroring); + + emit textureMirroringChanged(mirroring); +} + /*! \qmlproperty string QtQuick::Item::layer.samplerName diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 5e0246c32..942b51bf6 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -143,6 +143,7 @@ class QQuickItemLayer : public QObject, public QQuickItemChangeListener Q_PROPERTY(QQuickShaderEffectSource::Format format READ format WRITE setFormat NOTIFY formatChanged) 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) public: QQuickItemLayer(QQuickItem *item); ~QQuickItemLayer(); @@ -177,6 +178,9 @@ public: QQmlComponent *effect() const { return m_effectComponent; } void setEffect(QQmlComponent *effect); + QQuickShaderEffectSource::TextureMirroring textureMirroring() const { return m_textureMirroring; } + void setTextureMirroring(QQuickShaderEffectSource::TextureMirroring mirroring); + QQuickShaderEffectSource *effectSource() const { return m_effectSource; } void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &) Q_DECL_OVERRIDE; @@ -200,6 +204,7 @@ Q_SIGNALS: void smoothChanged(bool smooth); void formatChanged(QQuickShaderEffectSource::Format format); void sourceRectChanged(const QRectF &sourceRect); + void textureMirroringChanged(QQuickShaderEffectSource::TextureMirroring mirroring); private: friend class QQuickTransformAnimatorJob; @@ -223,6 +228,7 @@ private: QQmlComponent *m_effectComponent; QQuickItem *m_effect; QQuickShaderEffectSource *m_effectSource; + QQuickShaderEffectSource::TextureMirroring m_textureMirroring; }; class Q_QUICK_PRIVATE_EXPORT QQuickItemPrivate : public QObjectPrivate diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 4df1ef038..62e0adcb0 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -273,6 +273,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType(uri, 2, 6, "Flow"); qmlRegisterUncreatableType(uri, 2, 6, "EnterKey", QQuickEnterKeyAttached::tr("EnterKey is only available via attached properties")); + qmlRegisterType(uri, 2, 6, "ShaderEffectSource"); } static void initResources() diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp index bf69fe427..2effc0d0a 100644 --- a/src/quick/items/qquickshadereffectsource.cpp +++ b/src/quick/items/qquickshadereffectsource.cpp @@ -189,6 +189,7 @@ QQuickShaderEffectSource::QQuickShaderEffectSource(QQuickItem *parent) , m_mipmap(false) , m_recursive(false) , m_grab(true) + , m_textureMirroring(MirrorVertically) { setFlag(ItemHasContents); } @@ -542,6 +543,37 @@ void QQuickShaderEffectSource::setRecursive(bool enabled) emit recursiveChanged(); } +/*! + \qmlproperty enumeration QtQuick::ShaderEffectSource::textureMirroring + \since 5.6 + + This property defines how the generated OpenGL texture should be mirrored. + The default value is \c{ShaderEffectSource.MirrorVertically}. + Custom mirroring can be useful if the generated texture is directly accessed by custom shaders, + such as those specified by ShaderEffect. Mirroring has no effect on the UI representation of + the ShaderEffectSource item itself. + + \list + \li ShaderEffectSource.NoMirroring - No mirroring + \li ShaderEffectSource.MirrorHorizontally - The generated texture is flipped along X-axis. + \li ShaderEffectSource.MirrorVertically - The generated texture is flipped along Y-axis. + \endlist +*/ + +QQuickShaderEffectSource::TextureMirroring QQuickShaderEffectSource::textureMirroring() const +{ + return QQuickShaderEffectSource::TextureMirroring(m_textureMirroring); +} + +void QQuickShaderEffectSource::setTextureMirroring(TextureMirroring mirroring) +{ + if (mirroring == QQuickShaderEffectSource::TextureMirroring(m_textureMirroring)) + return; + m_textureMirroring = mirroring; + update(); + emit textureMirroringChanged(); +} + /*! \qmlmethod QtQuick::ShaderEffectSource::scheduleUpdate() @@ -642,6 +674,8 @@ QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaint m_texture->setRecursive(m_recursive); m_texture->setFormat(GLenum(m_format)); m_texture->setHasMipmaps(m_mipmap); + m_texture->setMirrorHorizontal(m_textureMirroring & MirrorHorizontally); + m_texture->setMirrorVertical(m_textureMirroring & MirrorVertically); if (m_grab) m_texture->scheduleUpdate(); diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h index 94bb31556..629acf0f5 100644 --- a/src/quick/items/qquickshadereffectsource_p.h +++ b/src/quick/items/qquickshadereffectsource_p.h @@ -66,6 +66,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffectSource : public QQuickItem, publi Q_PROPERTY(bool hideSource READ hideSource WRITE setHideSource NOTIFY hideSourceChanged) 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) public: enum WrapMode { @@ -83,6 +84,13 @@ public: }; Q_ENUM(Format) + enum TextureMirroring { + NoMirroring = 0x00, + MirrorHorizontally = 0x01, + MirrorVertically = 0x02 + }; + Q_ENUM(TextureMirroring) + QQuickShaderEffectSource(QQuickItem *parent = 0); ~QQuickShaderEffectSource(); @@ -113,6 +121,9 @@ public: bool recursive() const; void setRecursive(bool enabled); + TextureMirroring textureMirroring() const; + void setTextureMirroring(TextureMirroring mirroring); + bool isTextureProvider() const Q_DECL_OVERRIDE { return true; } QSGTextureProvider *textureProvider() const Q_DECL_OVERRIDE; @@ -128,6 +139,7 @@ Q_SIGNALS: void hideSourceChanged(); void mipmapChanged(); void recursiveChanged(); + void textureMirroringChanged(); void scheduledUpdateCompleted(); @@ -157,6 +169,7 @@ private: uint m_mipmap : 1; uint m_recursive : 1; uint m_grab : 1; + uint m_textureMirroring : 2; // Stores TextureMirroring enum }; QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h index 1253711a9..fde3fa06b 100644 --- a/src/quick/scenegraph/qsgadaptationlayer_p.h +++ b/src/quick/scenegraph/qsgadaptationlayer_p.h @@ -195,6 +195,8 @@ public: virtual void setFormat(GLenum format) = 0; virtual void setHasMipmaps(bool mipmap) = 0; virtual void setDevicePixelRatio(qreal ratio) = 0; + virtual void setMirrorHorizontal(bool mirror) = 0; + virtual void setMirrorVertical(bool mirror) = 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 cca0712ec..fa69f911d 100644 --- a/src/quick/scenegraph/qsgdefaultlayer.cpp +++ b/src/quick/scenegraph/qsgdefaultlayer.cpp @@ -97,6 +97,8 @@ QSGDefaultLayer::QSGDefaultLayer(QSGRenderContext *context) , m_multisamplingChecked(false) , m_multisampling(false) , m_grab(false) + , m_mirrorHorizontal(false) + , m_mirrorVertical(true) { } @@ -259,6 +261,16 @@ void QSGDefaultLayer::setRecursive(bool recursive) m_recursive = recursive; } +void QSGDefaultLayer::setMirrorHorizontal(bool mirror) +{ + m_mirrorHorizontal = mirror; +} + +void QSGDefaultLayer::setMirrorVertical(bool mirror) +{ + m_mirrorVertical = mirror; +} + void QSGDefaultLayer::markDirtyTexture() { m_dirtyTexture = true; @@ -365,7 +377,10 @@ void QSGDefaultLayer::grab() m_renderer->setDeviceRect(m_size); m_renderer->setViewportRect(m_size); - QRectF mirrored(m_rect.left(), m_rect.bottom(), m_rect.width(), -m_rect.height()); + QRectF mirrored(m_mirrorHorizontal ? m_rect.right() : m_rect.left(), + m_mirrorVertical ? m_rect.bottom() : m_rect.top(), + m_mirrorHorizontal ? -m_rect.width() : m_rect.width(), + m_mirrorVertical ? -m_rect.height() : m_rect.height()); m_renderer->setProjectionMatrixToRect(mirrored); m_renderer->setClearColor(Qt::transparent); @@ -428,3 +443,11 @@ QImage QSGDefaultLayer::toImage() const return QImage(); } + +QRectF QSGDefaultLayer::normalizedTextureSubRect() const +{ + return QRectF(m_mirrorHorizontal ? 1 : 0, + m_mirrorVertical ? 0 : 1, + m_mirrorHorizontal ? -1 : 1, + m_mirrorVertical ? 1 : -1); +} diff --git a/src/quick/scenegraph/qsgdefaultlayer_p.h b/src/quick/scenegraph/qsgdefaultlayer_p.h index 0ba7109ef..7baaed5f6 100644 --- a/src/quick/scenegraph/qsgdefaultlayer_p.h +++ b/src/quick/scenegraph/qsgdefaultlayer_p.h @@ -78,10 +78,18 @@ public: void setDevicePixelRatio(qreal ratio) Q_DECL_OVERRIDE { m_device_pixel_ratio = ratio; } + bool mirrorHorizontal() const { return bool(m_mirrorHorizontal); } + void setMirrorHorizontal(bool mirror) Q_DECL_OVERRIDE; + + bool mirrorVertical() const { return bool(m_mirrorVertical); } + void setMirrorVertical(bool mirror) Q_DECL_OVERRIDE; + void scheduleUpdate() Q_DECL_OVERRIDE; QImage toImage() const Q_DECL_OVERRIDE; + QRectF normalizedTextureSubRect() const Q_DECL_OVERRIDE; + public Q_SLOTS: void markDirtyTexture() Q_DECL_OVERRIDE; void invalidated() Q_DECL_OVERRIDE; @@ -115,6 +123,8 @@ private: uint m_multisamplingChecked : 1; uint m_multisampling : 1; uint m_grab : 1; + uint m_mirrorHorizontal : 1; + uint m_mirrorVertical : 1; }; #endif // QSGDEFAULTLAYER_P_H -- cgit v1.2.3