aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@jollamobile.com>2014-01-27 10:08:14 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-02-12 09:24:40 +0100
commit15999f14f146b5c04fb40b31b69ceeeece273430 (patch)
treec4694e18da30dc10075ca10e254bca02c3061383
parent4cf4d18b98f5ceaafc3f595c5eadad9ceb337813 (diff)
Add Image::mipmap to support mipmapping of images.
[ChangeLog][QtQuick] New feature: Image.mipmap Task-number: QTBUG-19961 Change-Id: I13acb2408d5b126790adaf9d324ad4beda1e3646 Reviewed-by: Michael Brasser <michael.brasser@live.com>
-rw-r--r--src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc3
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture.cpp2
-rw-r--r--src/quick/items/qquickimage.cpp45
-rw-r--r--src/quick/items/qquickimage_p.h5
-rw-r--r--src/quick/items/qquickimage_p_p.h1
-rw-r--r--src/quick/items/qquickitemsmodule.cpp1
-rw-r--r--src/quick/items/qquickwindow.cpp1
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp1
-rw-r--r--src/quick/scenegraph/util/qsgpainternode.cpp1
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp15
-rw-r--r--src/quick/scenegraph/util/qsgtexture_p.h4
-rw-r--r--tests/auto/quick/scenegraph/data/mipmap_large.pngbin0 -> 4465 bytes
-rw-r--r--tests/auto/quick/scenegraph/data/mipmap_small.pngbin0 -> 170 bytes
-rw-r--r--tests/auto/quick/scenegraph/data/render_Mipmap.qml77
-rw-r--r--tests/auto/quick/scenegraph/tst_scenegraph.cpp1
15 files changed, 135 insertions, 22 deletions
diff --git a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
index 16075f0db3..278733de8d 100644
--- a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
+++ b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
@@ -729,6 +729,9 @@ with multiple windows.
QQuickWindow::setColor() will be used in a call to \c glClear(),
which is potentially faster.
+ \li Mipmapped Image items are not placed in global atlas and will
+ not be batched.
+
\endlist
If an application performs poorly, make sure that rendering is
diff --git a/src/quick/items/context2d/qquickcontext2dtexture.cpp b/src/quick/items/context2d/qquickcontext2dtexture.cpp
index 8dd48b4988..d3f2a956a3 100644
--- a/src/quick/items/context2d/qquickcontext2dtexture.cpp
+++ b/src/quick/items/context2d/qquickcontext2dtexture.cpp
@@ -427,7 +427,6 @@ QSGTexture *QQuickContext2DFBOTexture::textureForNextFrame(QSGTexture *lastTextu
if (m_fbo) {
if (!texture) {
texture = new QSGPlainTexture();
- texture->setHasMipmaps(false);
texture->setHasAlphaChannel(true);
texture->setOwnsTexture(false);
m_dirtyTexture = true;
@@ -655,7 +654,6 @@ QSGTexture *QQuickContext2DImageTexture::textureForNextFrame(QSGTexture *last)
if (!texture) {
texture = new QSGPlainTexture();
- texture->setHasMipmaps(false);
texture->setHasAlphaChannel(true);
m_dirtyTexture = true;
}
diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp
index 62ac72d244..b6b8a2a39b 100644
--- a/src/quick/items/qquickimage.cpp
+++ b/src/quick/items/qquickimage.cpp
@@ -72,7 +72,7 @@ public:
QSGTexture *texture() const {
if (m_texture) {
m_texture->setFiltering(m_smooth ? QSGTexture::Linear : QSGTexture::Nearest);
- m_texture->setMipmapFiltering(QSGTexture::Nearest);
+ m_texture->setMipmapFiltering(m_mipmap ? QSGTexture::Linear : QSGTexture::None);
m_texture->setHorizontalWrapMode(QSGTexture::ClampToEdge);
m_texture->setVerticalWrapMode(QSGTexture::ClampToEdge);
}
@@ -83,6 +83,7 @@ public:
QSGTexture *m_texture;
bool m_smooth;
+ bool m_mipmap;
};
#include "qquickimage.moc"
@@ -92,6 +93,7 @@ QQuickImagePrivate::QQuickImagePrivate()
, paintedWidth(0)
, paintedHeight(0)
, pixmapChanged(false)
+ , mipmap(false)
, hAlign(QQuickImage::AlignHCenter)
, vAlign(QQuickImage::AlignVCenter)
, provider(0)
@@ -372,6 +374,8 @@ qreal QQuickImage::paintedHeight() const
no visual or performance effect.
By default, this property is set to true.
+
+ \sa mipmap
*/
/*!
@@ -549,6 +553,7 @@ QSGTextureProvider *QQuickImage::textureProvider() const
QQuickImagePrivate *dd = const_cast<QQuickImagePrivate *>(d);
dd->provider = new QQuickImageTextureProvider;
dd->provider->m_smooth = d->smooth;
+ dd->provider->m_mipmap = d->mipmap;
dd->provider->updateTexture(d->sceneGraphRenderContext()->textureForFactory(d->pix.textureFactory(), window()));
}
@@ -564,6 +569,7 @@ QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
// Copy over the current texture state into the texture provider...
if (d->provider) {
d->provider->m_smooth = d->smooth;
+ d->provider->m_mipmap = d->mipmap;
d->provider->updateTexture(texture);
}
@@ -673,13 +679,14 @@ QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
if (d->pixmapChanged) {
// force update the texture in the node to trigger reconstruction of
// geometry and the likes when a atlas segment has changed.
- if (texture->isAtlasTexture() && (hWrap == QSGTexture::Repeat || vWrap == QSGTexture::Repeat))
+ if (texture->isAtlasTexture() && (hWrap == QSGTexture::Repeat || vWrap == QSGTexture::Repeat || d->mipmap))
node->setTexture(texture->removedFromAtlas());
else
node->setTexture(texture);
d->pixmapChanged = false;
}
+ node->setMipmapFiltering(d->mipmap ? QSGTexture::Linear : QSGTexture::None);
node->setHorizontalWrapMode(hWrap);
node->setVerticalWrapMode(vWrap);
node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
@@ -746,4 +753,38 @@ void QQuickImage::setHorizontalAlignment(HAlignment align)
emit horizontalAlignmentChanged(align);
}
+/*!
+ \qmlproperty bool QtQuick::Image::mipmap
+ \since 5.3
+
+ This property holds whether the image uses mipmap filtering when scaled or
+ transformed.
+
+ Mipmap filtering gives better visual quality when scaling down
+ compared to smooth, but it may come at a performance cost (both when
+ initializing the image and during rendering).
+
+ By default, this property is set to false.
+
+ \sa smooth
+ */
+
+bool QQuickImage::mipmap() const
+{
+ Q_D(const QQuickImage);
+ return d->mipmap;
+}
+
+void QQuickImage::setMipmap(bool use)
+{
+ Q_D(QQuickImage);
+ if (d->mipmap == use)
+ return;
+ d->mipmap = use;
+ emit mipmapChanged(d->mipmap);
+
+ d->pixmapChanged = true;
+ update();
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickimage_p.h b/src/quick/items/qquickimage_p.h
index e62c355dd4..902e613b04 100644
--- a/src/quick/items/qquickimage_p.h
+++ b/src/quick/items/qquickimage_p.h
@@ -60,6 +60,7 @@ class Q_AUTOTEST_EXPORT QQuickImage : public QQuickImageBase
Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedGeometryChanged)
Q_PROPERTY(HAlignment horizontalAlignment READ horizontalAlignment WRITE setHorizontalAlignment NOTIFY horizontalAlignmentChanged)
Q_PROPERTY(VAlignment verticalAlignment READ verticalAlignment WRITE setVerticalAlignment NOTIFY verticalAlignmentChanged)
+ Q_PROPERTY(bool mipmap READ mipmap WRITE setMipmap NOTIFY mipmapChanged REVISION 1)
public:
QQuickImage(QQuickItem *parent=0);
@@ -91,11 +92,15 @@ public:
bool isTextureProvider() const { return true; }
QSGTextureProvider *textureProvider() const;
+ bool mipmap() const;
+ void setMipmap(bool use);
+
Q_SIGNALS:
void fillModeChanged();
void paintedGeometryChanged();
void horizontalAlignmentChanged(HAlignment alignment);
void verticalAlignmentChanged(VAlignment alignment);
+ void mipmapChanged(bool);
protected:
QQuickImage(QQuickImagePrivate &dd, QQuickItem *parent);
diff --git a/src/quick/items/qquickimage_p_p.h b/src/quick/items/qquickimage_p_p.h
index 632f76c51f..de88662ab8 100644
--- a/src/quick/items/qquickimage_p_p.h
+++ b/src/quick/items/qquickimage_p_p.h
@@ -73,6 +73,7 @@ public:
void setImage(const QImage &img);
bool pixmapChanged : 1;
+ bool mipmap : 1;
QQuickImage::HAlignment hAlign;
QQuickImage::VAlignment vAlign;
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index a52ccf4832..c9c8eeace3 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -272,6 +272,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickText, 3>(uri, 2, 3, "Text");
qmlRegisterType<QQuickTextEdit, 3>(uri, 2, 3, "TextEdit");
+ qmlRegisterType<QQuickImage, 1>(uri, 2, 3,"Image");
}
static void initResources()
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 6778cf13e9..3828c89dbf 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -3094,7 +3094,6 @@ QSGTexture *QQuickWindow::createTextureFromId(uint id, const QSize &size, Create
QSGPlainTexture *texture = new QSGPlainTexture();
texture->setTextureId(id);
texture->setHasAlphaChannel(options & TextureHasAlphaChannel);
- texture->setHasMipmaps(options & TextureHasMipmaps);
texture->setOwnsTexture(options & TextureOwnsGLTexture);
texture->setTextureSize(size);
return texture;
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index e6a2096c80..e39949253f 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -459,6 +459,7 @@ QSGTexture *Texture::removedFromAtlas() const
m_nonatlas_texture = new QSGPlainTexture();
m_nonatlas_texture->setImage(m_image);
m_nonatlas_texture->setFiltering(filtering());
+ m_nonatlas_texture->setMipmapFiltering(mipmapFiltering());
}
return m_nonatlas_texture;
}
diff --git a/src/quick/scenegraph/util/qsgpainternode.cpp b/src/quick/scenegraph/util/qsgpainternode.cpp
index 797fc4d145..ec44a994e0 100644
--- a/src/quick/scenegraph/util/qsgpainternode.cpp
+++ b/src/quick/scenegraph/util/qsgpainternode.cpp
@@ -205,7 +205,6 @@ void QSGPainterNode::update()
void QSGPainterNode::updateTexture()
{
- m_texture->setHasMipmaps(m_mipmapping);
m_texture->setHasAlphaChannel(!m_opaquePainting);
m_material.setTexture(m_texture);
m_materialO.setTexture(m_texture);
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index b738896a6c..9620e48588 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -533,7 +533,6 @@ QSGPlainTexture::QSGPlainTexture()
: QSGTexture()
, m_texture_id(0)
, m_has_alpha(false)
- , m_has_mipmaps(false)
, m_dirty_texture(false)
, m_dirty_bind_options(false)
, m_owns_texture(true)
@@ -597,18 +596,11 @@ void QSGPlainTexture::setTextureId(int id)
m_mipmaps_generated = false;
}
-void QSGPlainTexture::setHasMipmaps(bool mm)
-{
- m_has_mipmaps = mm;
- m_mipmaps_generated = false;
-}
-
-
void QSGPlainTexture::bind()
{
if (!m_dirty_texture) {
glBindTexture(GL_TEXTURE_2D, m_texture_id);
- if (m_has_mipmaps && !m_mipmaps_generated) {
+ if (mipmapFiltering() != QSGTexture::None && !m_mipmaps_generated) {
QOpenGLContext *ctx = QOpenGLContext::currentContext();
ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
m_mipmaps_generated = true;
@@ -642,11 +634,8 @@ void QSGPlainTexture::bind()
}
m_texture_id = 0;
m_texture_size = QSize();
- m_has_mipmaps = false;
m_has_alpha = false;
-
-
return;
}
@@ -726,7 +715,7 @@ void QSGPlainTexture::bind()
#endif
- if (m_has_mipmaps) {
+ if (mipmapFiltering() != QSGTexture::None) {
context->functions()->glGenerateMipmap(GL_TEXTURE_2D);
m_mipmaps_generated = true;
}
diff --git a/src/quick/scenegraph/util/qsgtexture_p.h b/src/quick/scenegraph/util/qsgtexture_p.h
index e0d386e20c..bc81569f84 100644
--- a/src/quick/scenegraph/util/qsgtexture_p.h
+++ b/src/quick/scenegraph/util/qsgtexture_p.h
@@ -85,8 +85,7 @@ public:
void setHasAlphaChannel(bool alpha) { m_has_alpha = alpha; }
bool hasAlphaChannel() const { return m_has_alpha; }
- void setHasMipmaps(bool mm);
- bool hasMipmaps() const { return m_has_mipmaps; }
+ bool hasMipmaps() const { return mipmapFiltering() != QSGTexture::None; }
void setImage(const QImage &image);
const QImage &image() { return m_image; }
@@ -107,7 +106,6 @@ protected:
QRectF m_texture_rect;
uint m_has_alpha : 1;
- uint m_has_mipmaps : 1;
uint m_dirty_texture : 1;
uint m_dirty_bind_options : 1;
uint m_owns_texture : 1;
diff --git a/tests/auto/quick/scenegraph/data/mipmap_large.png b/tests/auto/quick/scenegraph/data/mipmap_large.png
new file mode 100644
index 0000000000..9cb0fc7de1
--- /dev/null
+++ b/tests/auto/quick/scenegraph/data/mipmap_large.png
Binary files differ
diff --git a/tests/auto/quick/scenegraph/data/mipmap_small.png b/tests/auto/quick/scenegraph/data/mipmap_small.png
new file mode 100644
index 0000000000..dc5216fb6c
--- /dev/null
+++ b/tests/auto/quick/scenegraph/data/mipmap_small.png
Binary files differ
diff --git a/tests/auto/quick/scenegraph/data/render_Mipmap.qml b/tests/auto/quick/scenegraph/data/render_Mipmap.qml
new file mode 100644
index 0000000000..0a6195fc1f
--- /dev/null
+++ b/tests/auto/quick/scenegraph/data/render_Mipmap.qml
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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$
+**
+****************************************************************************/
+
+import QtQuick 2.3
+
+/*
+ The test verifies that scaled down mipmapped images contains
+ colors from all pixels.
+
+ #samples: 2
+ PixelPos R G B Error-tolerance
+ #final: 0 0 0.33 0.33 0.33 0.1
+ #final: 1 0 0.33 0.33 0.33 0.1
+*/
+
+RenderTestBase
+{
+ Image {
+ x: 0
+ y: 0
+ transformOrigin: Item.TopLeft
+ source: "mipmap_small.png"
+ mipmap: true
+ smooth: false
+ scale: 1 / width;
+ }
+
+ Image {
+ x: 1
+ y: 0
+ transformOrigin: Item.TopLeft
+ source: "mipmap_large.png"
+ mipmap: true
+ smooth: false
+ scale: 1 / width;
+ }
+
+ onEnterFinalStage: finalStageComplete = true;
+}
diff --git a/tests/auto/quick/scenegraph/tst_scenegraph.cpp b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
index 780d5a97db..af5acde5f3 100644
--- a/tests/auto/quick/scenegraph/tst_scenegraph.cpp
+++ b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
@@ -326,6 +326,7 @@ void tst_SceneGraph::render_data()
<< "data/render_BreakOpacityBatch.qml"
<< "data/render_OutOfFloatRange.qml"
<< "data/render_StackingOrder.qml"
+ << "data/render_Mipmap.qml"
;
QRegExp sampleCount("#samples: *(\\d+)");