Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fixed some Item.layer bugs and added auto-tests.
Change-Id: I3f66f911d1c499c37a66904f8ddab6951ba85e60
Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>
  • Loading branch information
Kim Motoyoshi Kalland authored and Qt by Nokia committed Feb 7, 2012
1 parent 54a2a4e commit a6eb091
Show file tree
Hide file tree
Showing 9 changed files with 361 additions and 44 deletions.
131 changes: 98 additions & 33 deletions src/quick/items/qquickitem.cpp
Expand Up @@ -5366,8 +5366,11 @@ QSGTextureProvider *QQuickItem::textureProvider() const

QQuickItemLayer *QQuickItemPrivate::layer() const
{
if (!_layer)
if (!_layer) {
_layer = new QQuickItemLayer(const_cast<QQuickItem *>(q_func()));
if (!componentComplete)
_layer->classBegin();
}
return _layer;
}

Expand Down Expand Up @@ -5426,28 +5429,30 @@ void QQuickItemLayer::setEnabled(bool e)

void QQuickItemLayer::classBegin()
{
Q_ASSERT(!m_effectSource);
Q_ASSERT(!m_effect);
m_componentComplete = false;
}

void QQuickItemLayer::componentComplete()
{
Q_ASSERT(!m_componentComplete);
m_componentComplete = true;
if (m_enabled)
activate();
}

void QQuickItemLayer::activate()
{
QQuickItem *parentItem = m_item->parentItem();
if (!m_effectSource)
Q_ASSERT(!m_effectSource);
m_effectSource = new QQuickShaderEffectSource();

QQuickItem *parentItem = m_item->parentItem();
if (parentItem) {
m_effectSource->setParentItem(parentItem);
m_effectSource->stackAfter(m_item);
}

m_effectSource->setVisible(!m_effectComponent && m_item->isVisible());
m_effectSource->setSourceItem(m_item);
m_effectSource->setHideSource(true);
m_effectSource->setSmooth(m_smooth);
Expand All @@ -5457,25 +5462,10 @@ void QQuickItemLayer::activate()
m_effectSource->setWrapMode(m_wrapMode);
m_effectSource->setFormat(m_format);

if (m_effectComponent) {
if (!m_effect) {
QObject *created = m_effectComponent->create();
m_effect = qobject_cast<QQuickShaderEffect *>(created);
if (!m_effect) {
qWarning("Item: layer.effect is not a shader effect");
delete created;
}
}
if (m_effect) {
if (parentItem) {
m_effect->setParentItem(parentItem);
m_effect->stackAfter(m_effectSource);
}
m_effect->setVisible(m_item->isVisible());
m_effect->setProperty(m_name.toLatin1(), qVariantFromValue<QObject *>(m_effectSource));
m_effect->update();
}
}
if (m_effectComponent)
activateEffect();

m_effectSource->setVisible(m_item->isVisible() && !m_effect);

updateZ();
updateGeometry();
Expand All @@ -5488,16 +5478,48 @@ void QQuickItemLayer::activate()

void QQuickItemLayer::deactivate()
{
Q_ASSERT(m_effectSource);

if (m_effectComponent)
deactivateEffect();

delete m_effectSource;
m_effectSource = 0;

delete m_effect;
m_effect = 0;

QQuickItemPrivate *id = QQuickItemPrivate::get(m_item);
id->removeItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Opacity | QQuickItemPrivate::Parent | QQuickItemPrivate::Visibility | QQuickItemPrivate::SiblingOrder);
}

void QQuickItemLayer::activateEffect()
{
Q_ASSERT(m_effectSource);
Q_ASSERT(m_effectComponent);
Q_ASSERT(!m_effect);

QObject *created = m_effectComponent->create();
m_effect = qobject_cast<QQuickShaderEffect *>(created);
if (!m_effect) {
qWarning("Item: layer.effect is not a ShaderEffect.");
delete created;
return;
}
QQuickItem *parentItem = m_item->parentItem();
if (parentItem) {
m_effect->setParentItem(parentItem);
m_effect->stackAfter(m_effectSource);
}
m_effect->setVisible(m_item->isVisible());
m_effect->setProperty(m_name.toLatin1(), qVariantFromValue<QObject *>(m_effectSource));
}

void QQuickItemLayer::deactivateEffect()
{
Q_ASSERT(m_effectSource);
Q_ASSERT(m_effectComponent);

delete m_effect;
m_effect = 0;
}


/*!
Expand All @@ -5506,21 +5528,35 @@ void QQuickItemLayer::deactivate()
Holds the effect that is applied to this layer.
The effect must be a \l ShaderEffect.
\sa samplerName
*/

void QQuickItemLayer::setEffect(QDeclarativeComponent *component)
{
if (component == m_effectComponent)
return;

bool updateNeeded = false;
if (m_effectSource && m_effectComponent) {
deactivateEffect();
updateNeeded = true;
}

m_effectComponent = component;

if (m_effect) {
delete m_effect;
m_effect = 0;
if (m_effectSource && m_effectComponent) {
activateEffect();
updateNeeded = true;
}

if (m_effectSource)
activate();
if (updateNeeded) {
updateZ();
updateGeometry();
updateOpacity();
updateMatrix();
m_effectSource->setVisible(m_item->isVisible() && !m_effect);
}

emit effectChanged(component);
}
Expand Down Expand Up @@ -5676,6 +5712,27 @@ void QQuickItemLayer::setWrapMode(QQuickShaderEffectSource::WrapMode mode)
emit wrapModeChanged(mode);
}

/*!
\qmlproperty string QtQuick2::Item::layer.samplerName
Holds the name of the effect's source texture property.
samplerName needs to match the name of the effect's source texture property
so that the Item can pass the layer's offscreen surface to the effect correctly.
\sa effect, ShaderEffect
*/

void QQuickItemLayer::setName(const QString &name) {
if (m_name == name)
return;
if (m_effect) {
m_effect->setProperty(m_name.toLatin1(), QVariant());
m_effect->setProperty(name.toLatin1(), qVariantFromValue<QObject *>(m_effectSource));
}
m_name = name;
emit nameChanged(name);
}

void QQuickItemLayer::itemOpacityChanged(QQuickItem *item)
{
Expand All @@ -5691,8 +5748,9 @@ void QQuickItemLayer::itemGeometryChanged(QQuickItem *, const QRectF &, const QR
void QQuickItemLayer::itemParentChanged(QQuickItem *item, QQuickItem *parent)
{
Q_UNUSED(item)
if (parent == m_effectSource || parent == m_effect)
return;
Q_ASSERT(item == m_item);
Q_ASSERT(parent != m_effectSource);
Q_ASSERT(parent == 0 || parent != m_effect);

m_effectSource->setParentItem(parent);
if (parent)
Expand All @@ -5715,24 +5773,30 @@ void QQuickItemLayer::itemSiblingOrderChanged(QQuickItem *)
void QQuickItemLayer::itemVisibilityChanged(QQuickItem *)
{
QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
Q_ASSERT(l);
l->setVisible(m_item->isVisible());
}

void QQuickItemLayer::updateZ()
{
if (!m_componentComplete || !m_enabled)
return;
QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
Q_ASSERT(l);
l->setZ(m_item->z());
}

void QQuickItemLayer::updateOpacity()
{
QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
Q_ASSERT(l);
l->setOpacity(m_item->opacity());
}

void QQuickItemLayer::updateGeometry()
{
QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
Q_ASSERT(l);
QRectF bounds = m_item->boundingRect();
l->setWidth(bounds.width());
l->setHeight(bounds.height());
Expand All @@ -5747,6 +5811,7 @@ void QQuickItemLayer::updateMatrix()
if (!m_componentComplete || !m_enabled)
return;
QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
Q_ASSERT(l);
QQuickItemPrivate *ld = QQuickItemPrivate::get(l);
l->setScale(m_item->scale());
l->setRotation(m_item->rotation());
Expand Down
11 changes: 4 additions & 7 deletions src/quick/items/qquickitem_p.h
Expand Up @@ -157,7 +157,7 @@ class QQuickItemLayer : public QObject, public QQuickItemChangeListener
void classBegin();
void componentComplete();

bool enabled() const { return m_effectSource != 0; }
bool enabled() const { return m_enabled; }
void setEnabled(bool enabled);

bool mipmap() const { return m_mipmap; }
Expand All @@ -179,12 +179,7 @@ class QQuickItemLayer : public QObject, public QQuickItemChangeListener
void setWrapMode(QQuickShaderEffectSource::WrapMode mode);

QString name() const { return m_name; }
void setName(const QString &name) {
if (m_name == name)
return;
m_name = name;
emit nameChanged(name);
}
void setName(const QString &name);

QDeclarativeComponent *effect() const { return m_effectComponent; }
void setEffect(QDeclarativeComponent *effect);
Expand Down Expand Up @@ -216,6 +211,8 @@ class QQuickItemLayer : public QObject, public QQuickItemChangeListener
private:
void activate();
void deactivate();
void activateEffect();
void deactivateEffect();

QQuickItem *m_item;
bool m_enabled;
Expand Down
18 changes: 18 additions & 0 deletions tests/auto/qtquick2/qquickitemlayer/data/DisableLayer.qml
@@ -0,0 +1,18 @@
import QtQuick 2.0

Item {
width: 200
height: 200
Rectangle {
width: 100
height: 100
color: "red"
layer.enabled: true
Component.onCompleted: {
layer.enabled = false
visible = false
width = 120
x = 10
}
}
}
18 changes: 18 additions & 0 deletions tests/auto/qtquick2/qquickitemlayer/data/SamplerNameChange.qml
@@ -0,0 +1,18 @@
import QtQuick 2.0

Rectangle {
width: 200
height: 200
color: "blue"
layer.enabled: true
layer.effect: ShaderEffect {
fragmentShader: "
uniform sampler2D foo;
uniform lowp float qt_Opacity;
varying highp vec2 qt_TexCoord0;
void main() {
gl_FragColor = texture2D(foo, qt_TexCoord0) * qt_Opacity;
}"
}
Component.onCompleted: layer.samplerName = "foo"
}
23 changes: 23 additions & 0 deletions tests/auto/qtquick2/qquickitemlayer/data/ToggleLayerAndEffect.qml
@@ -0,0 +1,23 @@
import QtQuick 2.0

Item {
width: 200
height: 200
Rectangle {
width: 100
height: 100
color: "red"
Component.onCompleted: {
layer.enabled = true
layer.effect = effectComponent
layer.enabled = false
visible = false
width = 120
x = 10
}
}
Component {
id: effectComponent
ShaderEffect { }
}
}
50 changes: 50 additions & 0 deletions tests/auto/qtquick2/qquickitemlayer/data/ZOrderChange.qml
@@ -0,0 +1,50 @@
import QtQuick 2.0

Item {
width: 200
height: 200
property bool layerEffect: false
property bool layerEnabled: false
property real layerZ: 0
Rectangle {
anchors.fill: parent
color: "#00ffff"
}
Rectangle {
id: foo
anchors.fill: parent
color: "#ffff00"
Rectangle {
width: 100
height: 100
color: "#00ffff"
}
layer.enabled: parent.layerEnabled
layer.effect: parent.layerEffect ? effectComponent : null
opacity: 0.5
z: layerZ
}
Rectangle {
width: 100
height: 100
x: 100
color: "#ff0000"
}
Rectangle {
width: 100
height: 100
y: 100
color: "#0000ff"
z: 1
}
Component {
id: effectComponent
ShaderEffect {
fragmentShader: "
uniform sampler2D source;
uniform lowp float qt_Opacity;
varying highp vec2 qt_TexCoord0;
void main() { gl_FragColor = texture2D(source, qt_TexCoord0).xzyw * qt_Opacity; }"
}
}
}

0 comments on commit a6eb091

Please sign in to comment.