aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@theqtcompany.com>2014-12-09 15:09:20 +0100
committerSimon Hausmann <simon.hausmann@theqtcompany.com>2014-12-09 15:09:26 +0100
commitff466a1881435f927f5df9ce1e5eac07d5591904 (patch)
tree760e068743e6a8e1cc4ec63bb2f8e7dcef88b3e2 /src/quick
parente04822f3c2a6b69b7d75e2039256aa2433c59dd2 (diff)
parent4a3f6e58b591f2fe2204f7cbc1efc8abb0aade74 (diff)
Merge remote-tracking branch 'origin/5.4' into dev
Conflicts: src/qml/jsruntime/qv4arraydata.cpp src/qml/jsruntime/qv4context_p.h src/qml/jsruntime/qv4globalobject.cpp src/qml/jsruntime/qv4internalclass.cpp src/quick/items/qquicktext_p.h src/quick/items/qquicktextedit_p.h src/quick/items/qquicktextinput_p.h Change-Id: If07e483e03197cb997ef47a9c647a479cdb09f4c
Diffstat (limited to 'src/quick')
-rw-r--r--src/quick/doc/src/examples.qdoc24
-rw-r--r--src/quick/doc/src/qmltypereference.qdoc10
-rw-r--r--src/quick/items/qquickanimatedsprite.cpp21
-rw-r--r--src/quick/items/qquickborderimage.cpp424
-rw-r--r--src/quick/items/qquickborderimage_p.h2
-rw-r--r--src/quick/items/qquickborderimage_p_p.h10
-rw-r--r--src/quick/items/qquickimagebase.cpp10
-rw-r--r--src/quick/items/qquickimagebase_p.h2
-rw-r--r--src/quick/items/qquickimagebase_p_p.h3
-rw-r--r--src/quick/items/qquickitem.cpp2
-rw-r--r--src/quick/items/qquickrendercontrol.cpp15
-rw-r--r--src/quick/items/qquicktext.cpp45
-rw-r--r--src/quick/items/qquicktext_p.h1
-rw-r--r--src/quick/items/qquicktext_p_p.h1
-rw-r--r--src/quick/items/qquicktextedit.cpp31
-rw-r--r--src/quick/items/qquicktextedit_p.h4
-rw-r--r--src/quick/items/qquicktextinput.cpp27
-rw-r--r--src/quick/items/qquicktextinput_p.h6
-rw-r--r--src/quick/items/qquickview.cpp4
-rw-r--r--src/quick/items/qquickwindow.cpp141
-rw-r--r--src/quick/items/qquickwindow.h2
-rw-r--r--src/quick/items/qquickwindowattached.cpp6
-rw-r--r--src/quick/items/qquickwindowattached_p.h3
-rw-r--r--src/quick/qtquick2.cpp5
-rw-r--r--src/quick/qtquick2_p.h1
-rw-r--r--src/quick/qtquickglobal_p.h1
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp162
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h16
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp2
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp28
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h3
-rw-r--r--src/quick/scenegraph/qsgdefaultimagenode.cpp57
-rw-r--r--src/quick/scenegraph/qsgdefaultimagenode_p.h3
-rw-r--r--src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp173
-rw-r--r--src/quick/scenegraph/qsgwindowsrenderloop.cpp21
-rw-r--r--src/quick/scenegraph/scenegraph.pri1
-rw-r--r--src/quick/scenegraph/util/qsgsimpletexturenode.cpp4
-rw-r--r--src/quick/util/qquickglobal.cpp7
38 files changed, 592 insertions, 686 deletions
diff --git a/src/quick/doc/src/examples.qdoc b/src/quick/doc/src/examples.qdoc
index 51525b8f57..0ec4507450 100644
--- a/src/quick/doc/src/examples.qdoc
+++ b/src/quick/doc/src/examples.qdoc
@@ -72,8 +72,8 @@ The following pages show how to develop Qt applications using
\l{Qt Creator Manual}{Qt Creator} and Qt Quick. The pages demonstrate various
steps such as use cases and introductory material. For more information about Qt Quick Applications and related modules, visit the \l{QML Applications} page.
-\div {class="landingicons"}
- \div {class="icons1of3"}
+\div {class="multi-column"}
+ \div {class="doc-column"}
\b{Development Environment}
\list
\li \l{Qt Creator: Creating Qt Quick Projects}{Creating Qt Quick Projects}
@@ -84,7 +84,7 @@ steps such as use cases and introductory material. For more information about Qt
\li \l{Qt Creator: Using QML Modules with Plugins}{Using QML Modules with Plugins}
\endlist
\enddiv
- \div {class="icons1of3"}
+ \div {class="doc-column"}
\b{Beginning with QML and Qt Quick}
\list
\li \l{First Steps with QML}
@@ -92,7 +92,7 @@ steps such as use cases and introductory material. For more information about Qt
\li \l{QML Advanced Tutorial}{SameGame}
\endlist
\enddiv
- \div {class="icons1of3"}
+ \div {class="doc-column"}
\b{Use Cases}
\list
\li \l{qtquick-usecase-visual.html}{Visual types in QML}
@@ -120,8 +120,8 @@ Examples are small applications which show how to implement various Qt Quick
features. The examples run on various platforms and are opened from within Qt
Creator.
-\div {class="landingicons"}
- \div {class="icons1of3"}
+\div {class="multi-column"}
+ \div {class="doc-column"}
\b{QML Types and Controls}
\list
\li \l{Qt Quick Controls - Gallery}{Controls Gallery}
@@ -132,7 +132,7 @@ Creator.
\li \l{Qt Quick Examples - Toggle Switch}{Custom Toggle Switch}
\endlist
\enddiv
- \div {class="icons1of3"}
+ \div {class="doc-column"}
\b{Layouts and Views}
\list
\li \l{Qt Quick Controls - Basic Layouts Example}{Basic Layouts}
@@ -142,7 +142,7 @@ Creator.
\li \l{Qt Quick Examples - Right to Left}{Right-to-Left and Text Layout}
\endlist
\enddiv
- \div {class="icons1of3"}
+ \div {class="doc-column"}
\b{Image and Graphics}
\list
\li \l{Qt Quick Examples - Image Elements}{Image Elements}
@@ -153,8 +153,8 @@ Creator.
\enddiv
\enddiv
-\div {class="landingicons"}
- \div {class="icons1of3"}
+\div {class="multi-column"}
+ \div {class="doc-column"}
\b{Keyboard, Focus, and Touch}
\list
\li \l{Qt Quick Examples - Key Interaction}{Key Interaction}
@@ -162,7 +162,7 @@ Creator.
\li \l{Qt Quick Controls - Touch Gallery}{Touch Gallery}
\endlist
\enddiv
- \div {class="icons1of3"}
+ \div {class="doc-column"}
\b{System and Events}
\list
\li \l{Qt Quick Examples - Threading}{Threading}
@@ -171,7 +171,7 @@ Creator.
\li \l{Qt Quick Examples - Drag and Drop}{Drag and Drop}
\endlist
\enddiv
- \div {class="icons1of3"}
+ \div {class="doc-column"}
\b{Scene Graph}
\list
\li \l{Scene Graph - OpenGL Under QML}{OpenGL Under QML}
diff --git a/src/quick/doc/src/qmltypereference.qdoc b/src/quick/doc/src/qmltypereference.qdoc
index 4d3341aac4..430c0ed11a 100644
--- a/src/quick/doc/src/qmltypereference.qdoc
+++ b/src/quick/doc/src/qmltypereference.qdoc
@@ -26,7 +26,7 @@
****************************************************************************/
/*!
-\qmlmodule QtQuick 2.3
+\qmlmodule QtQuick 2.4
\title Qt Quick QML Types
\ingroup qmlmodules
\brief Provides graphical QML types.
@@ -34,11 +34,11 @@
The \l{Qt Quick} module provides graphical primitive types. These types are only
available in a QML document if that document imports the \c QtQuick namespace.
-The current version of the \c QtQuick module is version 2.3, and thus it may be
+The current version of the \c QtQuick module is version 2.4, and thus it may be
imported via the following statement:
\qml
-import QtQuick 2.3
+import QtQuick 2.4
\endqml
Visit the \l {Qt Quick} module documentation for more
@@ -830,14 +830,14 @@ console.log(c + " " + d); // false true
*/
/*!
-\qmlmodule QtTest 1.0
+\qmlmodule QtTest 1.1
\title Qt Quick Test QML Types
\brief This module provides QML types to unit test your QML application
\ingroup qmlmodules
You can import this module using the following statement:
\code
-import QtTest 1.0
+import QtTest 1.1
\endcode
For more information about how to use these types, see
diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp
index f144345b6c..4d1d8b251e 100644
--- a/src/quick/items/qquickanimatedsprite.cpp
+++ b/src/quick/items/qquickanimatedsprite.cpp
@@ -628,8 +628,25 @@ void QQuickAnimatedSprite::prepareNextFrame()
qreal w = m_spriteEngine->spriteWidth() / m_sheetSize.width();
qreal h = m_spriteEngine->spriteHeight() / m_sheetSize.height();
- qreal x1 = m_spriteEngine->spriteX() / m_sheetSize.width() + frameAt * w;
- qreal y1 = m_spriteEngine->spriteY() / m_sheetSize.height();
+ qreal x1;
+ qreal y1;
+ if (m_paused) {
+ int spriteY = m_spriteEngine->spriteY();
+ if (reverse) {
+ int rows = m_spriteEngine->maxFrames() * m_spriteEngine->spriteWidth() / m_sheetSize.width();
+ spriteY -= rows * m_spriteEngine->spriteHeight();
+ frameAt = (frameCount - 1) - frameAt;
+ }
+
+ int position = frameAt * m_spriteEngine->spriteWidth() + m_spriteEngine->spriteX();
+ int row = position / m_sheetSize.width();
+
+ x1 = (position - (row * m_sheetSize.width())) / m_sheetSize.width();
+ y1 = (row * m_spriteEngine->spriteHeight() + spriteY) / m_sheetSize.height();
+ } else {
+ x1 = m_spriteEngine->spriteX() / m_sheetSize.width() + frameAt * w;
+ y1 = m_spriteEngine->spriteY() / m_sheetSize.height();
+ }
//### hard-coded 0/1 work because we are the only
// images in the sprite sheet (without this we cannot assume
diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp
index 07b8958664..38bbc66896 100644
--- a/src/quick/items/qquickborderimage.cpp
+++ b/src/quick/items/qquickborderimage.cpp
@@ -540,390 +540,90 @@ void QQuickBorderImage::doUpdate()
update();
}
-QImage QQuickBorderImage::shallowCopy(const QImage &image, const QRect &rect)
-{
- if (image.depth() == 1) {
- return image.copy(rect);
- } else {
- const uchar *bits = image.constBits() + image.bytesPerLine() * rect.y() + (image.depth() / 8) * rect.x();
- return QImage(bits, rect.width(), rect.height(), image.bytesPerLine(), image.format());
- }
-}
-
QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
Q_D(QQuickBorderImage);
- if (!d->pix.isReady() || width() <= 0 || height() <= 0) {
+ QSGTexture *texture = d->sceneGraphRenderContext()->textureForFactory(d->pix.textureFactory(), window());
+
+ if (!texture || width() <= 0 || height() <= 0) {
delete oldNode;
return 0;
}
- // Don't implicitly create the scalegrid in the rendering thread...
- QRectF innerSourceRect(0, 0, 1, 1);
- QRectF innerTargetRect(0, 0, width(), height());
- int borderLeft = 0, borderTop = 0, borderRight = 0, borderBottom = 0;
-
- bool updateNode = !oldNode;
- if (d->border) {
- const QQuickScaleGrid *border = d->getScaleGrid();
-
- borderLeft = qBound(0, border->left(), d->pix.width());
- borderTop = qBound(0, border->top(), d->pix.height());
- borderRight = d->pix.rect().width() - qBound(0, border->right(), d->pix.rect().width() - borderLeft);
- borderBottom = d->pix.rect().height() - qBound(0, border->bottom(), d->pix.rect().height() - borderTop);
-
- innerSourceRect = QRectF(borderLeft / qreal(d->pix.width()),
- borderTop / qreal(d->pix.height()),
- qMax<qreal>(0, borderRight - borderLeft) / d->pix.width(),
- qMax<qreal>(0, borderBottom - borderTop) / d->pix.height());
- innerTargetRect = QRectF(borderLeft,
- borderTop,
- qMax<qreal>(0, width() - border->right() - border->left()),
- qMax<qreal>(0, height() - border->bottom() - border->top()));
-
- QSizeF newSize(width(), height());
- if (innerSourceRect != d->oldInnerSourceRect
- || innerTargetRect != d->oldInnerTargetRect
- || newSize != d->oldSize) {
- updateNode = true;
- }
-
- d->oldInnerSourceRect = innerSourceRect;
- d->oldInnerTargetRect = innerTargetRect;
- d->oldSize = newSize;
- }
+ QSGImageNode *node = static_cast<QSGImageNode *>(oldNode);
bool updatePixmap = d->pixmapChanged;
d->pixmapChanged = false;
- if (updateNode) {
- delete oldNode;
- oldNode = new QSGNode;
+ if (!node) {
+ node = d->sceneGraphContext()->createImageNode();
updatePixmap = true;
-
- for (int i=0; i<9; ++i)
- d->regions[i].node = 0;
-
- if (innerSourceRect.left() > 0) {
- if (innerSourceRect.top() > 0) {
- QRectF rect(0,
- 0,
- innerTargetRect.left(),
- innerTargetRect.top());
-
- if (!rect.isEmpty()) {
- d->regions[0].node = d->sceneGraphContext()->createImageNode();
- d->regions[0].node->setTargetRect(rect);
- d->regions[0].node->setInnerTargetRect(rect);
- d->regions[0].targetRect = rect;
- }
- }
-
- if (innerSourceRect.bottom() < 1) {
- QRectF rect(0,
- innerTargetRect.bottom(),
- innerTargetRect.left(),
- height() - innerTargetRect.height() - innerTargetRect.top());
-
- if (!rect.isEmpty()) {
- d->regions[6].node = d->sceneGraphContext()->createImageNode();
- d->regions[6].node->setTargetRect(rect);
- d->regions[6].node->setInnerTargetRect(rect);
- d->regions[6].targetRect = rect;
- }
- }
-
- if (innerSourceRect.top() < innerSourceRect.bottom()) {
- QRectF rect(0,
- innerTargetRect.top(),
- innerTargetRect.left(),
- innerTargetRect.height());
-
- if (!rect.isEmpty()) {
- d->regions[3].node = d->sceneGraphContext()->createImageNode();
- d->regions[3].node->setTargetRect(rect);
- d->regions[3].node->setInnerTargetRect(rect);
- d->regions[3].targetRect = rect;
- }
- }
- }
-
- if (innerSourceRect.right() < 1) {
- if (innerSourceRect.top() > 0) {
- QRectF rect(innerTargetRect.right(),
- 0,
- width() - innerTargetRect.width() - innerTargetRect.left(),
- innerTargetRect.top());
-
- if (!rect.isEmpty()) {
- d->regions[2].node = d->sceneGraphContext()->createImageNode();
- d->regions[2].node->setTargetRect(rect);
- d->regions[2].node->setInnerTargetRect(rect);
- d->regions[2].targetRect = rect;
- }
- }
-
- if (innerSourceRect.bottom() < 1) {
- QRectF rect(innerTargetRect.right(),
- innerTargetRect.bottom(),
- width() - innerTargetRect.width() - innerTargetRect.left(),
- height() - innerTargetRect.height() - innerTargetRect.top());
-
- if (!rect.isEmpty()) {
- d->regions[8].node = d->sceneGraphContext()->createImageNode();
- d->regions[8].node->setTargetRect(rect);
- d->regions[8].node->setInnerTargetRect(rect);
- d->regions[8].targetRect = rect;
- }
- }
-
- if (innerSourceRect.top() < innerSourceRect.bottom()) {
- QRectF rect(innerTargetRect.right(),
- innerTargetRect.top(),
- width() - innerTargetRect.width() - innerTargetRect.left(),
- innerTargetRect.height());
-
- if (!rect.isEmpty()) {
- d->regions[5].node = d->sceneGraphContext()->createImageNode();
- d->regions[5].node->setTargetRect(rect);
- d->regions[5].node->setInnerTargetRect(rect);
- d->regions[5].targetRect = rect;
- }
- }
- }
-
- if (innerSourceRect.top() > 0 && innerSourceRect.left() < innerSourceRect.right()) {
- QRectF rect(innerTargetRect.left(),
- 0,
- innerTargetRect.width(),
- innerTargetRect.top());
-
- if (!rect.isEmpty()) {
- d->regions[1].node = d->sceneGraphContext()->createImageNode();
- d->regions[1].node->setTargetRect(rect);
- d->regions[1].node->setInnerTargetRect(rect);
- d->regions[1].targetRect = rect;
- }
- }
-
- if (innerSourceRect.bottom() < 1 && innerSourceRect.left() < innerSourceRect.right()) {
- QRectF rect(innerTargetRect.left(),
- innerTargetRect.bottom(),
- innerTargetRect.width(),
- height() - innerTargetRect.height() - innerTargetRect.top());
-
- if (!rect.isEmpty()) {
- d->regions[7].node = d->sceneGraphContext()->createImageNode();
- d->regions[7].node->setTargetRect(rect);
- d->regions[7].node->setInnerTargetRect(rect);
- d->regions[7].targetRect = rect;
- }
- }
-
- if (innerSourceRect.left() < innerSourceRect.right()
- && innerSourceRect.top() < innerSourceRect.bottom()) {
- if (!innerTargetRect.isEmpty()) {
- d->regions[4].node = d->sceneGraphContext()->createImageNode();
- d->regions[4].node->setInnerTargetRect(innerTargetRect);
- d->regions[4].node->setTargetRect(innerTargetRect);
- d->regions[4].targetRect = innerTargetRect;
- }
- }
-
- for (int i=0; i<9; ++i) {
- if (d->regions[i].node != 0)
- oldNode->appendChildNode(d->regions[i].node);
- }
- }
-
-
- QImage image = d->pix.image();
-
- if (d->regions[0].node != 0) {
- if (updatePixmap)
- d->regions[0].image = shallowCopy(image, QRect(QPoint(0, 0), QSize(borderLeft, borderTop)));
-
- QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingFlags(QSGImageNode::AntialiasingLeft | QSGImageNode::AntialiasingTop);
- if (d->regions[1].node == 0 && d->regions[2].node == 0)
- antialiasing |= QSGImageNode::AntialiasingRight;
- if (d->regions[3].node == 0 && d->regions[6].node == 0)
- antialiasing |= QSGImageNode::AntialiasingBottom;
- d->regions[0].node->setAntialiasing(antialiasing);
}
- if (d->regions[1].node != 0) {
- if (updatePixmap)
- d->regions[1].image = shallowCopy(image, QRect(QPoint(borderLeft, 0), QSize(borderRight - borderLeft, borderTop)));
-
- QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingTop;
- if (d->regions[0].node == 0)
- antialiasing |= QSGImageNode::AntialiasingLeft;
- if (d->regions[2].node == 0)
- antialiasing |= QSGImageNode::AntialiasingRight;
- if (d->regions[4].node == 0 && d->regions[7].node == 0)
- antialiasing |= QSGImageNode::AntialiasingBottom;
- d->regions[1].node->setAntialiasing(antialiasing);
- }
-
- if (d->regions[2].node != 0) {
- if (updatePixmap)
- d->regions[2].image = shallowCopy(image, QRect(QPoint(borderRight, 0), QSize(d->pix.rect().width() - borderRight, borderTop)));
+ if (updatePixmap)
+ node->setTexture(texture);
- QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingFlags(QSGImageNode::AntialiasingTop | QSGImageNode::AntialiasingRight);
- if (d->regions[0].node == 0 && d->regions[1].node == 0)
- antialiasing |= QSGImageNode::AntialiasingLeft;
- if (d->regions[5].node == 0 && d->regions[8].node == 0)
- antialiasing |= QSGImageNode::AntialiasingBottom;
- d->regions[2].node->setAntialiasing(antialiasing);
- }
-
- if (d->regions[3].node != 0) {
- if (updatePixmap)
- d->regions[3].image = shallowCopy(image, QRect(QPoint(0, borderTop), QSize(borderLeft, borderBottom - borderTop)));
-
- QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingLeft;
- if (d->regions[4].node == 0 && d->regions[5].node == 0)
- antialiasing |= QSGImageNode::AntialiasingRight;
- if (d->regions[6].node == 0)
- antialiasing |= QSGImageNode::AntialiasingBottom;
- if (d->regions[0].node == 0)
- antialiasing |= QSGImageNode::AntialiasingTop;
- d->regions[3].node->setAntialiasing(antialiasing);
+ // Don't implicitly create the scalegrid in the rendering thread...
+ QRectF innerSourceRect(0, 0, 1, 1);
+ QRectF targetRect(0, 0, width(), height());
+ QRectF innerTargetRect = targetRect;
+ if (d->border) {
+ const QQuickScaleGrid *border = d->getScaleGrid();
+ innerSourceRect = QRectF(border->left() / qreal(d->pix.width()),
+ border->top() / qreal(d->pix.height()),
+ qMax<qreal>(0, d->pix.width() - border->right() - border->left()) / d->pix.width(),
+ qMax<qreal>(0, d->pix.height() - border->bottom() - border->top()) / d->pix.height());
+ innerTargetRect = QRectF(border->left(),
+ border->top(),
+ qMax<qreal>(0, width() - border->right() - border->left()),
+ qMax<qreal>(0, height() - border->bottom() - border->top()));
}
-
- if (d->regions[4].node != 0) {
- if (updatePixmap) {
- if (innerSourceRect == QRectF(0, 0, 1, 1)) {
- d->regions[4].image = image;
- } else {
- d->regions[4].image = shallowCopy(image, QRect(QPoint(borderLeft, borderTop), QSize(borderRight - borderLeft, borderBottom - borderTop)));
- }
+ qreal hTiles = 1;
+ qreal vTiles = 1;
+ if (innerSourceRect.width() != 0) {
+ switch (d->horizontalTileMode) {
+ case QQuickBorderImage::Repeat:
+ hTiles = innerTargetRect.width() / qreal(innerSourceRect.width() * d->pix.width());
+ break;
+ case QQuickBorderImage::Round:
+ hTiles = qCeil(innerTargetRect.width() / qreal(innerSourceRect.width() * d->pix.width()));
+ break;
+ default:
+ break;
}
-
- QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingNone;
- if (d->regions[3].node == 0)
- antialiasing |= QSGImageNode::AntialiasingLeft;
- if (d->regions[5].node == 0)
- antialiasing |= QSGImageNode::AntialiasingRight;
- if (d->regions[1].node == 0)
- antialiasing |= QSGImageNode::AntialiasingTop;
- if (d->regions[7].node == 0)
- antialiasing |= QSGImageNode::AntialiasingBottom;
- d->regions[4].node->setAntialiasing(antialiasing);
}
-
- if (d->regions[5].node != 0) {
- if (updatePixmap)
- d->regions[5].image = shallowCopy(image, QRect(QPoint(borderRight, borderTop), QSize(d->pix.rect().width() - borderRight, borderBottom - borderTop)));
-
- QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingRight;
- if (d->regions[4].node == 0 && d->regions[3].node == 0)
- antialiasing |= QSGImageNode::AntialiasingLeft;
- if (d->regions[2].node == 0)
- antialiasing |= QSGImageNode::AntialiasingTop;
- if (d->regions[8].node == 0)
- antialiasing |= QSGImageNode::AntialiasingBottom;
- d->regions[5].node->setAntialiasing(antialiasing);
- }
-
- if (d->regions[6].node != 0) {
- if (updatePixmap)
- d->regions[6].image = shallowCopy(image, QRect(QPoint(0, borderBottom), QSize(borderLeft, d->pix.rect().height() - borderBottom)));
-
- QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingFlags(QSGImageNode::AntialiasingBottom | QSGImageNode::AntialiasingLeft);
- if (d->regions[7].node == 0 && d->regions[8].node == 0)
- antialiasing |= QSGImageNode::AntialiasingRight;
- if (d->regions[3].node == 0 && d->regions[0].node == 0)
- antialiasing |= QSGImageNode::AntialiasingTop;
- d->regions[6].node->setAntialiasing(antialiasing);
- }
-
- if (d->regions[7].node != 0) {
- if (updatePixmap)
- d->regions[7].image = shallowCopy(image, QRect(QPoint(borderLeft, borderBottom), QSize(borderRight - borderLeft, d->pix.rect().height() - borderBottom)));
-
- QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingBottom;
- if (d->regions[6].node == 0)
- antialiasing |= QSGImageNode::AntialiasingLeft;
- if (d->regions[8].node == 0)
- antialiasing |= QSGImageNode::AntialiasingRight;
- if (d->regions[4].node == 0 && d->regions[1].node == 0)
- antialiasing |= QSGImageNode::AntialiasingTop;
- d->regions[7].node->setAntialiasing(antialiasing);
- }
-
- if (d->regions[8].node != 0) {
- if (updatePixmap)
- d->regions[8].image = shallowCopy(image, QRect(QPoint(borderRight, borderBottom), QSize(d->pix.rect().width() - borderRight, d->pix.rect().height() - borderBottom)));
-
- QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingFlags(QSGImageNode::AntialiasingBottom | QSGImageNode::AntialiasingRight);
- if (d->regions[7].node == 0 && d->regions[6].node == 0)
- antialiasing |= QSGImageNode::AntialiasingLeft;
- if (d->regions[5].node == 0 && d->regions[2].node == 0)
- antialiasing |= QSGImageNode::AntialiasingTop;
- d->regions[8].node->setAntialiasing(antialiasing);
+ if (innerSourceRect.height() != 0) {
+ switch (d->verticalTileMode) {
+ case QQuickBorderImage::Repeat:
+ vTiles = innerTargetRect.height() / qreal(innerSourceRect.height() * d->pix.height());
+ break;
+ case QQuickBorderImage::Round:
+ vTiles = qCeil(innerTargetRect.height() / qreal(innerSourceRect.height() * d->pix.height()));
+ break;
+ default:
+ break;
+ }
}
- for (int i=0; i<9; ++i) {
- if (d->regions[i].node != 0) {
- if (updatePixmap) {
- QQuickTextureFactory *textureFactory = QSGContext::createTextureFactoryFromImage(d->regions[i].image);
- if (textureFactory == 0)
- textureFactory = new QQuickDefaultTextureFactory(d->regions[i].image);
- d->regions[i].textureFactory.reset(textureFactory);
- d->regions[i].node->setTexture(d->sceneGraphRenderContext()->textureForFactory(d->regions[i].textureFactory.data(),
- window()));
- }
-
- d->regions[i].node->setInnerSourceRect(QRectF(0, 0, 1, 1));
- d->regions[i].node->setMipmapFiltering(QSGTexture::None);
- d->regions[i].node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
- d->regions[i].node->setMirror(d->mirror);
-
-
- qreal hTiles = 1;
- qreal vTiles = 1;
-
- if (innerSourceRect.width() != 0) {
- switch (d->horizontalTileMode) {
- case QQuickBorderImage::Repeat:
- hTiles = d->regions[i].targetRect.width() / qreal(d->regions[i].image.width());
- break;
- case QQuickBorderImage::Round:
- hTiles = qCeil(d->regions[i].targetRect.width() / qreal(d->regions[i].image.width()));
- break;
- default:
- break;
- }
- }
-
- if (innerSourceRect.height() != 0) {
- switch (d->verticalTileMode) {
- case QQuickBorderImage::Repeat:
- vTiles = d->regions[i].targetRect.height() / qreal(d->regions[i].image.height());
- break;
- case QQuickBorderImage::Round:
- vTiles = qCeil(d->regions[i].targetRect.height() / qreal(d->regions[i].image.height()));
- break;
- default:
- break;
- }
- }
-
- if (vTiles > 1 || hTiles > 1) {
- d->regions[i].node->setHorizontalWrapMode(QSGTexture::Repeat);
- d->regions[i].node->setVerticalWrapMode(QSGTexture::Repeat);
- } else {
- d->regions[i].node->setHorizontalWrapMode(QSGTexture::ClampToEdge);
- d->regions[i].node->setVerticalWrapMode(QSGTexture::ClampToEdge);
- }
-
- d->regions[i].node->setSubSourceRect(QRectF(0, 0, hTiles, vTiles));
- d->regions[i].node->update();
- }
+ node->setTargetRect(targetRect);
+ node->setInnerSourceRect(innerSourceRect);
+ node->setInnerTargetRect(innerTargetRect);
+ node->setSubSourceRect(QRectF(0, 0, hTiles, vTiles));
+ node->setMirror(d->mirror);
+
+ node->setMipmapFiltering(QSGTexture::None);
+ node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
+ if (innerSourceRect == QRectF(0, 0, 1, 1) && (vTiles > 1 || hTiles > 1)) {
+ node->setHorizontalWrapMode(QSGTexture::Repeat);
+ node->setVerticalWrapMode(QSGTexture::Repeat);
+ } else {
+ node->setHorizontalWrapMode(QSGTexture::ClampToEdge);
+ node->setVerticalWrapMode(QSGTexture::ClampToEdge);
}
+ node->setAntialiasing(d->antialiasing);
+ node->update();
- return oldNode;
+ return node;
}
void QQuickBorderImage::pixmapChange()
diff --git a/src/quick/items/qquickborderimage_p.h b/src/quick/items/qquickborderimage_p.h
index a33098d3b1..e998646e48 100644
--- a/src/quick/items/qquickborderimage_p.h
+++ b/src/quick/items/qquickborderimage_p.h
@@ -87,8 +87,6 @@ private Q_SLOTS:
void sciRequestFinished();
private:
- static QImage shallowCopy(const QImage &image, const QRect &rect);
-
Q_DISABLE_COPY(QQuickBorderImage)
Q_DECLARE_PRIVATE(QQuickBorderImage)
};
diff --git a/src/quick/items/qquickborderimage_p_p.h b/src/quick/items/qquickborderimage_p_p.h
index bda2867696..d5b959fd9f 100644
--- a/src/quick/items/qquickborderimage_p_p.h
+++ b/src/quick/items/qquickborderimage_p_p.h
@@ -89,16 +89,6 @@ public:
QQuickBorderImage::TileMode verticalTileMode;
int redirectCount;
- struct BorderImageRegion
- {
- BorderImageRegion() : node(0), textureFactory(0) {}
- QImage image;
- QSGImageNode *node;
- QScopedPointer<QQuickTextureFactory> textureFactory;
- QRectF targetRect;
- };
- BorderImageRegion regions[9];
-
bool pixmapChanged : 1;
};
diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp
index 1a5d115a3c..a4c4af4e45 100644
--- a/src/quick/items/qquickimagebase.cpp
+++ b/src/quick/items/qquickimagebase.cpp
@@ -35,6 +35,7 @@
#include "qquickimagebase_p_p.h"
#include <QtGui/qguiapplication.h>
+#include <QtGui/qscreen.h>
#include <QtQml/qqmlinfo.h>
#include <QtQml/qqmlfile.h>
@@ -45,14 +46,12 @@ QQuickImageBase::QQuickImageBase(QQuickItem *parent)
: QQuickImplicitSizeItem(*(new QQuickImageBasePrivate), parent)
{
setFlag(ItemHasContents);
- connect(this, SIGNAL(windowChanged(QQuickWindow*)), SLOT(handleWindowChanged(QQuickWindow*)));
}
QQuickImageBase::QQuickImageBase(QQuickImageBasePrivate &dd, QQuickItem *parent)
: QQuickImplicitSizeItem(dd, parent)
{
setFlag(ItemHasContents);
- connect(this, SIGNAL(windowChanged(QQuickWindow*)), SLOT(handleWindowChanged(QQuickWindow*)));
}
QQuickImageBase::~QQuickImageBase()
@@ -278,10 +277,11 @@ void QQuickImageBase::requestProgress(qint64 received, qint64 total)
}
}
-void QQuickImageBase::handleWindowChanged(QQuickWindow* window)
+void QQuickImageBase::itemChange(ItemChange change, const ItemChangeData &value)
{
- if (window)
- connect(window, SIGNAL(screenChanged(QScreen*)), this, SLOT(handleScreenChanged(QScreen*)));
+ if (change == ItemSceneChange && value.window)
+ connect(value.window, &QQuickWindow::screenChanged, this, &QQuickImageBase::handleScreenChanged);
+ QQuickItem::itemChange(change, value);
}
void QQuickImageBase::handleScreenChanged(QScreen* screen)
diff --git a/src/quick/items/qquickimagebase_p.h b/src/quick/items/qquickimagebase_p.h
index 860cb2e670..c204bdd442 100644
--- a/src/quick/items/qquickimagebase_p.h
+++ b/src/quick/items/qquickimagebase_p.h
@@ -93,12 +93,12 @@ protected:
virtual void load();
void componentComplete() Q_DECL_OVERRIDE;
virtual void pixmapChange();
+ void itemChange(ItemChange change, const ItemChangeData &value) Q_DECL_OVERRIDE;
QQuickImageBase(QQuickImageBasePrivate &dd, QQuickItem *parent);
private Q_SLOTS:
virtual void requestFinished();
void requestProgress(qint64,qint64);
- void handleWindowChanged(QQuickWindow *window);
void handleScreenChanged(QScreen *screen);
private:
diff --git a/src/quick/items/qquickimagebase_p_p.h b/src/quick/items/qquickimagebase_p_p.h
index 21d11a7448..f30eacb4ac 100644
--- a/src/quick/items/qquickimagebase_p_p.h
+++ b/src/quick/items/qquickimagebase_p_p.h
@@ -75,9 +75,6 @@ public:
QSize sourcesize;
QSize oldSourceSize;
qreal devicePixelRatio;
- QRectF oldInnerSourceRect;
- QRectF oldInnerTargetRect;
- QSizeF oldSize;
bool async : 1;
bool cache : 1;
bool mirror: 1;
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 25f139549d..6ae74281ca 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -2481,7 +2481,7 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
return;
if (parentItem) {
- QQuickItem *itemAncestor = parentItem->parentItem();
+ QQuickItem *itemAncestor = parentItem;
while (itemAncestor != 0) {
if (itemAncestor == this) {
qWarning("QQuickItem::setParentItem: Parent is already part of this items subtree.");
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
index 7ccd3a0fb4..a666bb59c9 100644
--- a/src/quick/items/qquickrendercontrol.cpp
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -106,7 +106,7 @@ extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_
rendered by calling render(). After making the context current, applications
are expected to call render().
- \li QQuickRenderControl::sceneChanged() Inidcates that the scene has changed
+ \li QQuickRenderControl::sceneChanged() Indicates that the scene has changed
meaning that, before rendering, polishing and synchronizing is also necessary.
\endlist
@@ -172,6 +172,10 @@ void QQuickRenderControlPrivate::windowDestroyed()
/*!
Initializes the scene graph resources. The context \a gl has to
be the current context.
+
+ \note Qt Quick does not take ownership of the context. It is up to the
+ application to destroy it after a call to invalidate() or after the
+ QQuickRenderControl instance is destroyed.
*/
void QQuickRenderControl::initialize(QOpenGLContext *gl)
{
@@ -274,7 +278,6 @@ void QQuickRenderControl::invalidate()
// application right after returning from this function. Invalidating is
// also essential to allow a subsequent initialize() to succeed.
d->rc->invalidate();
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
d->initialized = false;
}
@@ -296,6 +299,10 @@ void QQuickRenderControl::render()
\fn void QQuickRenderControl::renderRequested()
This signal is emitted when the scene graph needs to be rendered. It is not necessary to call sync().
+
+ \note Avoid triggering rendering directly when this signal is
+ emitted. Instead, prefer deferring it by using a timer for example. This
+ will lead to better performance.
*/
/*!
@@ -304,6 +311,10 @@ void QQuickRenderControl::render()
This signal is emitted when the scene graph is updated, meaning that
polishItems() and sync() needs to be called. If sync() returns
true, then render() needs to be called.
+
+ \note Avoid triggering polishing, synchronization and rendering directly
+ when this signal is emitted. Instead, prefer deferring it by using a timer
+ for example. This will lead to better performance.
*/
/*!
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index bfa2fccd67..87255f4bd9 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -79,6 +79,7 @@ QQuickTextPrivate::QQuickTextPrivate()
, requireImplicitSize(false), implicitWidthValid(false), implicitHeightValid(false)
, truncated(false), hAlignImplicit(true), rightToLeftText(false)
, layoutTextElided(false), textHasChanged(true), needToUpdateLayout(false), formatModifiesFontSize(false)
+ , polishSize(false)
{
implicitAntialiasing = true;
}
@@ -356,6 +357,8 @@ void QQuickTextPrivate::updateLayout()
textHasChanged = true;
updateLayout();
}
+
+ q->polish();
}
void QQuickText::imageDownloadFinished()
@@ -2248,13 +2251,22 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data
node->addImage(QRectF(img->pos.x() + dx, img->pos.y() + dy, pix->width(), pix->height()), pix->image());
}
}
+
+ // The font caches have now been initialized on the render thread, so they have to be
+ // invalidated before we can use them from the main thread again.
+ invalidateFontCaches();
+
return node;
}
void QQuickText::updatePolish()
{
Q_D(QQuickText);
- d->updateSize();
+ if (d->polishSize) {
+ d->updateSize();
+ d->polishSize = false;
+ }
+ invalidateFontCaches();
}
/*!
@@ -2381,6 +2393,7 @@ void QQuickText::setFontSizeMode(FontSizeMode mode)
if (d->fontSizeMode() == mode)
return;
+ d->polishSize = true;
polish();
d->extra.value().fontSizeMode = mode;
@@ -2409,8 +2422,10 @@ void QQuickText::setMinimumPixelSize(int size)
if (d->minimumPixelSize() == size)
return;
- if (d->fontSizeMode() != FixedSize && (widthValid() || heightValid()))
+ if (d->fontSizeMode() != FixedSize && (widthValid() || heightValid())) {
+ d->polishSize = true;
polish();
+ }
d->extra.value().minimumPixelSize = size;
emit minimumPixelSizeChanged();
}
@@ -2437,8 +2452,10 @@ void QQuickText::setMinimumPointSize(int size)
if (d->minimumPointSize() == size)
return;
- if (d->fontSizeMode() != FixedSize && (widthValid() || heightValid()))
+ if (d->fontSizeMode() != FixedSize && (widthValid() || heightValid())) {
+ d->polishSize = true;
polish();
+ }
d->extra.value().minimumPointSize = size;
emit minimumPointSizeChanged();
}
@@ -2699,4 +2716,26 @@ QString QQuickText::linkAt(qreal x, qreal y) const
return d->anchorAt(QPointF(x, y));
}
+/*!
+ * \internal
+ *
+ * Invalidates font caches owned by the text objects owned by the element
+ * to work around the fact that text objects cannot be used from multiple threads.
+ */
+void QQuickText::invalidateFontCaches()
+{
+ Q_D(QQuickText);
+
+ if (d->richText && d->extra->doc != 0) {
+ QTextBlock block;
+ for (block = d->extra->doc->firstBlock(); block.isValid(); block = block.next()) {
+ if (block.layout() != 0 && block.layout()->engine() != 0)
+ block.layout()->engine()->resetFontEngineCache();
+ }
+ } else {
+ if (d->layout.engine() != 0)
+ d->layout.engine()->resetFontEngineCache();
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h
index bc1a5198e8..18f2a73470 100644
--- a/src/quick/items/qquicktext_p.h
+++ b/src/quick/items/qquicktext_p.h
@@ -245,6 +245,7 @@ protected:
void hoverEnterEvent(QHoverEvent *event) Q_DECL_OVERRIDE;
void hoverMoveEvent(QHoverEvent *event) Q_DECL_OVERRIDE;
void hoverLeaveEvent(QHoverEvent *event) Q_DECL_OVERRIDE;
+ void invalidateFontCaches();
private Q_SLOTS:
void q_imagesLoaded();
diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h
index 04a78f9c21..3b83d37899 100644
--- a/src/quick/items/qquicktext_p_p.h
+++ b/src/quick/items/qquicktext_p_p.h
@@ -151,6 +151,7 @@ public:
bool textHasChanged:1;
bool needToUpdateLayout:1;
bool formatModifiesFontSize:1;
+ bool polishSize:1; // Workaround for problem with polish called after updateSize (QTBUG-42636)
static const QChar elideChar;
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 1ad37ed7dd..c46df8f1b0 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -1745,6 +1745,7 @@ void QQuickTextEdit::triggerPreprocess()
Q_D(QQuickTextEdit);
if (d->updateType == QQuickTextEditPrivate::UpdateNone)
d->updateType = QQuickTextEditPrivate::UpdateOnlyPreprocess;
+ polish();
update();
}
@@ -1764,6 +1765,25 @@ static inline void updateNodeTransform(QQuickTextNode* node, const QPointF &topL
node->setMatrix(transformMatrix);
}
+/*!
+ * \internal
+ *
+ * Invalidates font caches owned by the text objects owned by the element
+ * to work around the fact that text objects cannot be used from multiple threads.
+ */
+void QQuickTextEdit::invalidateFontCaches()
+{
+ Q_D(QQuickTextEdit);
+ if (d->document == 0)
+ return;
+
+ QTextBlock block;
+ for (block = d->document->firstBlock(); block.isValid(); block = block.next()) {
+ if (block.layout() != 0 && block.layout()->engine() != 0)
+ block.layout()->engine()->resetFontEngineCache();
+ }
+}
+
QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData)
{
Q_UNUSED(updatePaintNodeData);
@@ -1917,9 +1937,16 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
rootNode->resetCursorNode(cursor);
}
+ invalidateFontCaches();
+
return rootNode;
}
+void QQuickTextEdit::updatePolish()
+{
+ invalidateFontCaches();
+}
+
/*!
\qmlproperty bool QtQuick::TextEdit::canPaste
@@ -2087,6 +2114,7 @@ void QQuickTextEdit::q_contentsChange(int pos, int charsRemoved, int charsAdded)
markDirtyNodesForRange(pos, editRange, delta);
+ polish();
if (isComponentComplete()) {
d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
update();
@@ -2114,6 +2142,7 @@ void QQuickTextEdit::updateSelection()
// No need for node updates when we go from an empty selection to another empty selection
if (d->control->textCursor().hasSelection() || d->hadSelection) {
markDirtyNodesForRange(qMin(d->lastSelectionStart, d->control->textCursor().selectionStart()), qMax(d->control->textCursor().selectionEnd(), d->lastSelectionEnd), 0);
+ polish();
if (isComponentComplete()) {
d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
update();
@@ -2254,6 +2283,7 @@ void QQuickTextEdit::updateWholeDocument()
node->setDirty();
}
+ polish();
if (isComponentComplete()) {
d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
update();
@@ -2268,6 +2298,7 @@ void QQuickTextEdit::invalidateBlock(const QTextBlock &block)
void QQuickTextEdit::updateCursor()
{
Q_D(QQuickTextEdit);
+ polish();
if (isComponentComplete()) {
d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
update();
diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h
index ea47c3b60e..5320ecc2ca 100644
--- a/src/quick/items/qquicktextedit_p.h
+++ b/src/quick/items/qquicktextedit_p.h
@@ -215,7 +215,7 @@ public:
#ifndef QT_NO_IM
QVariant inputMethodQuery(Qt::InputMethodQuery property) const Q_DECL_OVERRIDE;
- Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const;
+ Q_REVISION(4) Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const;
#endif
qreal contentWidth() const;
@@ -318,6 +318,7 @@ private Q_SLOTS:
private:
void markDirtyNodesForRange(int start, int end, int charDelta);
void updateTotalLines();
+ void invalidateFontCaches();
protected:
void geometryChanged(const QRectF &newGeometry,
@@ -342,6 +343,7 @@ protected:
void inputMethodEvent(QInputMethodEvent *e) Q_DECL_OVERRIDE;
#endif
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData) Q_DECL_OVERRIDE;
+ void updatePolish();
friend class QQuickTextUtil;
friend class QQuickTextDocument;
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index d1bf022184..288464e0b4 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -56,6 +56,8 @@
#include "qquickaccessibleattached_p.h"
#endif
+#include <QtGui/private/qtextengine_p.h>
+
QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
@@ -362,6 +364,7 @@ void QQuickTextInput::setColor(const QColor &c)
d->color = c;
d->textLayoutDirty = true;
d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
+ polish();
update();
emit colorChanged();
}
@@ -389,6 +392,7 @@ void QQuickTextInput::setSelectionColor(const QColor &color)
if (d->hasSelectedText()) {
d->textLayoutDirty = true;
d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
+ polish();
update();
}
emit selectionColorChanged();
@@ -414,6 +418,7 @@ void QQuickTextInput::setSelectedTextColor(const QColor &color)
if (d->hasSelectedText()) {
d->textLayoutDirty = true;
d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
+ polish();
update();
}
emit selectedTextColorChanged();
@@ -723,6 +728,7 @@ void QQuickTextInput::setCursorVisible(bool on)
if (!d->cursorItem) {
d->setCursorBlinkPeriod(on ? qApp->styleHints()->cursorFlashTime() : 0);
d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
+ polish();
update();
}
emit cursorVisibleChanged(d->cursorVisible);
@@ -1846,9 +1852,23 @@ void QQuickTextInput::triggerPreprocess()
Q_D(QQuickTextInput);
if (d->updateType == QQuickTextInputPrivate::UpdateNone)
d->updateType = QQuickTextInputPrivate::UpdateOnlyPreprocess;
+ polish();
update();
}
+void QQuickTextInput::updatePolish()
+{
+ invalidateFontCaches();
+}
+
+void QQuickTextInput::invalidateFontCaches()
+{
+ Q_D(QQuickTextInput);
+
+ if (d->m_textLayout.engine() != 0)
+ d->m_textLayout.engine()->resetFontEngineCache();
+}
+
QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
{
Q_UNUSED(data);
@@ -1907,6 +1927,8 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
d->textLayoutDirty = false;
}
+ invalidateFontCaches();
+
return node;
}
@@ -2669,6 +2691,7 @@ void QQuickTextInput::updateCursorRectangle(bool scroll)
d->updateVerticalScroll();
}
d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
+ polish();
update();
emit cursorRectangleChanged();
if (d->cursorItem) {
@@ -2686,6 +2709,7 @@ void QQuickTextInput::selectionChanged()
Q_D(QQuickTextInput);
d->textLayoutDirty = true; //TODO: Only update rect in selection
d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
+ polish();
update();
emit selectedTextChanged();
@@ -2897,6 +2921,7 @@ void QQuickTextInputPrivate::updateLayout()
contentSize = QSizeF(width, height);
updateType = UpdatePaintNode;
+ q->polish();
q->update();
if (!requireImplicitWidth && !q->widthValid())
@@ -4185,6 +4210,7 @@ void QQuickTextInputPrivate::setCursorBlinkPeriod(int msec)
m_blinkTimer = 0;
if (m_blinkStatus == 1) {
updateType = UpdatePaintNode;
+ q->polish();
q->update();
}
}
@@ -4197,6 +4223,7 @@ void QQuickTextInput::timerEvent(QTimerEvent *event)
if (event->timerId() == d->m_blinkTimer) {
d->m_blinkStatus = !d->m_blinkStatus;
d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
+ polish();
update();
} else if (event->timerId() == d->m_passwordEchoTimer.timerId()) {
d->m_passwordEchoTimer.stop();
diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h
index 0d32cb2179..3cd5b7ad18 100644
--- a/src/quick/items/qquicktextinput_p.h
+++ b/src/quick/items/qquicktextinput_p.h
@@ -239,7 +239,7 @@ public:
#ifndef QT_NO_IM
QVariant inputMethodQuery(Qt::InputMethodQuery property) const Q_DECL_OVERRIDE;
- Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const;
+ Q_REVISION(3) Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const;
#endif
QRectF boundingRect() const Q_DECL_OVERRIDE;
@@ -301,6 +301,9 @@ Q_SIGNALS:
void inputMethodHintsChanged();
void renderTypeChanged();
+private:
+ void invalidateFontCaches();
+
protected:
void geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry) Q_DECL_OVERRIDE;
@@ -319,6 +322,7 @@ protected:
void focusInEvent(QFocusEvent *event) Q_DECL_OVERRIDE;
void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE;
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) Q_DECL_OVERRIDE;
+ void updatePolish();
public Q_SLOTS:
void selectAll();
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp
index 41b53ddffe..0a16457e0e 100644
--- a/src/quick/items/qquickview.cpp
+++ b/src/quick/items/qquickview.cpp
@@ -379,10 +379,6 @@ QList<QQmlError> QQuickView::errors() const
If this property is set to SizeRootObjectToView, the view will
automatically resize the root item to the size of the view.
- Regardless of this property, the sizeHint of the view
- is the initial size of the root item. Note though that
- since QML may load dynamically, that size may change.
-
\sa initialSize()
*/
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 13462317a3..aba36ce118 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -897,8 +897,10 @@ void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item,
void QQuickWindowPrivate::clearFocusObject()
{
- if (activeFocusItem)
- activeFocusItem->setFocus(false, Qt::OtherFocusReason);
+ if (activeFocusItem == contentItem)
+ return;
+
+ clearFocusInScope(contentItem, QQuickItemPrivate::get(contentItem)->subFocusItem, Qt::OtherFocusReason);
}
void QQuickWindowPrivate::notifyFocusChangesRecur(QQuickItem **items, int remaining)
@@ -970,10 +972,10 @@ void QQuickWindowPrivate::cleanup(QSGNode *n)
Alternatively you can set or bind \l x and \l y to position the Window
explicitly on the screen.
- When the user attempts to close a window, the \a closing signal will be
+ When the user attempts to close a window, the \l closing signal will be
emitted. You can force the window to stay open (for example to prompt the
- user to save changes) by writing an onClosing handler and setting
- close.accepted = false.
+ user to save changes) by writing an \c onClosing handler and setting
+ \c {close.accepted = false}.
*/
/*!
\class QQuickWindow
@@ -1254,6 +1256,14 @@ bool QQuickWindow::isPersistentSceneGraph() const
+/*!
+ \qmlattachedproperty Item Window::contentItem
+ \since 5.4
+
+ This attached property holds the invisible root item of the scene or
+ \c null if the item is not in a window. The Window attached property
+ can be attached to any Item.
+*/
/*!
\property QQuickWindow::contentItem
@@ -1795,7 +1805,9 @@ void QQuickWindowPrivate::deliverTouchEvent(QTouchEvent *event)
if (!delayedTouch) {
delayedTouch = new QTouchEvent(event->type(), event->device(), event->modifiers(), event->touchPointStates(), event->touchPoints());
delayedTouch->setTimestamp(event->timestamp());
- if (windowManager)
+ if (renderControl)
+ QQuickRenderControlPrivate::get(renderControl)->maybeUpdate();
+ else if (windowManager)
windowManager->maybeUpdate(q);
return;
} else {
@@ -3088,7 +3100,7 @@ bool QQuickWindow::isSceneGraphInitialized() const
\since 5.1
Notification that a window is about to be closed by the windowing system
- (e.g. the user clicked the titlebar close button). The CloseEvent contains
+ (e.g. the user clicked the title bar close button). The CloseEvent contains
an accepted property which can be set to false to abort closing the window.
\sa Window.closing()
@@ -3115,9 +3127,9 @@ bool QQuickWindow::isSceneGraphInitialized() const
This signal is emitted when the user tries to close the window.
- This signal includes a closeEvent parameter. The \a close \l accepted
+ This signal includes a \a close parameter. The \a close \l accepted
property is true by default so that the window is allowed to close; but you
- can implement an onClosing() handler and set close.accepted = false if
+ can implement an \c onClosing handler and set \c {close.accepted = false} if
you need to do something else before the window can be closed.
The corresponding handler is \c onClosing.
@@ -3799,7 +3811,7 @@ void QQuickWindow::resetOpenGLState()
Whether the window is visible on the screen.
- Setting visible to false is the same as setting \l visibility to Hidden.
+ Setting visible to false is the same as setting \l visibility to \l {QWindow::}{Hidden}.
\sa visibility
*/
@@ -3812,13 +3824,14 @@ void QQuickWindow::resetOpenGLState()
Visibility is whether the window should appear in the windowing system as
normal, minimized, maximized, fullscreen or hidden.
- To set the visibility to AutomaticVisibility means to give the window a
- default visible state, which might be fullscreen or windowed depending on
- the platform. However when reading the visibility property you will always
- get the actual state, never AutomaticVisibility.
+ To set the visibility to \l {QWindow::}{AutomaticVisibility} means to give the
+ window a default visible state, which might be \l {QWindow::}{FullScreen} or
+ \l {QWindow::}{Windowed} depending on the platform. However when reading the
+ visibility property you will always get the actual state, never
+ \c AutomaticVisibility.
When a window is not visible its visibility is Hidden, and setting
- visibility to Hidden is the same as setting \l visible to false.
+ visibility to \l {QWindow::}{Hidden} is the same as setting \l visible to \c false.
\sa visible
\since 5.1
@@ -3830,7 +3843,7 @@ void QQuickWindow::resetOpenGLState()
This attached property holds whether the window is currently shown
in the windowing system as normal, minimized, maximized, fullscreen or
- hidden. The Window attached property can be attached to any Item. If the
+ hidden. The \c Window attached property can be attached to any Item. If the
item is not shown in any window, the value will be \l {QWindow::}{Hidden}.
\sa visible, visibility
@@ -3931,12 +3944,94 @@ void QQuickWindow::resetOpenGLState()
\qmlmethod QtQuick::Window::alert(int msec)
\since 5.1
- Causes an alert to be shown for \a msec miliseconds. If \a msec is \c 0 (the
- default), then the alert is shown indefinitely until the window becomes
- active again.
+ Causes an alert to be shown for \a msec milliseconds. If \a msec is \c 0
+ (the default), then the alert is shown indefinitely until the window
+ becomes active again.
+
+ In alert state, the window indicates that it demands attention, for example
+ by flashing or bouncing the taskbar entry.
+*/
+
+/*!
+ \qmlmethod QtQuick::Window::close()
+
+ Closes the window.
+
+ When this method is called, or when the user tries to close the window by
+ its title bar button, the \l closing signal will be emitted. If there is no
+ handler, or the handler does not revoke permission to close, the window
+ will subsequently close. If the QGuiApplication::quitOnLastWindowClosed
+ property is \c true, and there are no other windows open, the application
+ will quit.
+*/
+
+/*!
+ \qmlmethod QtQuick::Window::raise()
+
+ Raises the window in the windowing system.
+
+ Requests that the window be raised to appear above other windows.
+*/
+
+/*!
+ \qmlmethod QtQuick::Window::lower()
+
+ Lowers the window in the windowing system.
+
+ Requests that the window be lowered to appear below other windows.
+*/
+
+/*!
+ \qmlmethod QtQuick::Window::show()
+
+ Shows the window.
+
+ This is equivalent to calling showFullScreen(), showMaximized(), or showNormal(),
+ depending on the platform's default behavior for the window type and flags.
+
+ \sa showFullScreen(), showMaximized(), showNormal(), hide(), flags()
+*/
+
+/*!
+ \qmlmethod QtQuick::Window::hide()
+
+ Hides the window.
+
+ Equivalent to setting \l visible to \c false or \l visibility to \l {QWindow::}{Hidden}.
+
+ \sa show()
+*/
+
+/*!
+ \qmlmethod QtQuick::Window::showMinimized()
+
+ Shows the window as minimized.
+
+ Equivalent to setting \l visibility to \l {QWindow::}{Minimized}.
+*/
+
+/*!
+ \qmlmethod QtQuick::Window::showMaximized()
+
+ Shows the window as maximized.
+
+ Equivalent to setting \l visibility to \l {QWindow::}{Maximized}.
+*/
+
+/*!
+ \qmlmethod QtQuick::Window::showFullScreen()
+
+ Shows the window as fullscreen.
+
+ Equivalent to setting \l visibility to \l {QWindow::}{FullScreen}.
+*/
+
+/*!
+ \qmlmethod QtQuick::Window::showNormal()
+
+ Shows the window as normal, i.e. neither maximized, minimized, nor fullscreen.
- In alert state, the window indicates that it demands attention, for example by
- flashing or bouncing the taskbar entry.
+ Equivalent to setting \l visibility to \l {QWindow::}{Windowed}.
*/
/*!
@@ -3955,7 +4050,7 @@ void QQuickWindow::resetOpenGLState()
/*!
\since 5.4
- Schedule \a job to run when the rendering of this window reaches
+ Schedules \a job to run when the rendering of this window reaches
the given \a stage.
This is a convenience to the equivalent signals in QQuickWindow for
@@ -4030,7 +4125,7 @@ void QQuickWindow::runJobsAfterSwap()
*
* \sa QWindow::devicePixelRatio()
*/
-int QQuickWindow::effectiveDevicePixelRatio() const
+qreal QQuickWindow::effectiveDevicePixelRatio() const
{
QWindow *w = QQuickRenderControl::renderWindowFor(const_cast<QQuickWindow *>(this));
return w ? w->devicePixelRatio() : devicePixelRatio();
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index d02423d8af..349cdf7474 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -143,7 +143,7 @@ public:
void scheduleRenderJob(QRunnable *job, RenderStage schedule);
- int effectiveDevicePixelRatio() const;
+ qreal effectiveDevicePixelRatio() const;
Q_SIGNALS:
void frameSwapped();
diff --git a/src/quick/items/qquickwindowattached.cpp b/src/quick/items/qquickwindowattached.cpp
index 121da9e5d9..f74e903be3 100644
--- a/src/quick/items/qquickwindowattached.cpp
+++ b/src/quick/items/qquickwindowattached.cpp
@@ -65,6 +65,11 @@ QQuickItem *QQuickWindowAttached::activeFocusItem() const
return (m_window ? m_window->activeFocusItem() : Q_NULLPTR);
}
+QQuickItem *QQuickWindowAttached::contentItem() const
+{
+ return (m_window ? m_window->contentItem() : Q_NULLPTR);
+}
+
void QQuickWindowAttached::windowChanged(QQuickWindow *window)
{
if (window != m_window) {
@@ -83,6 +88,7 @@ void QQuickWindowAttached::windowChanged(QQuickWindow *window)
emit activeChanged();
if (!oldWindow || window->activeFocusItem() != oldWindow->activeFocusItem())
emit activeFocusItemChanged();
+ emit contentItemChanged();
// QQuickWindowQmlImpl::visibilityChanged also exists, and window might even
// be QQuickWindowQmlImpl, but that's not what we are connecting to.
diff --git a/src/quick/items/qquickwindowattached_p.h b/src/quick/items/qquickwindowattached_p.h
index 12dd273d60..7c2b0bc873 100644
--- a/src/quick/items/qquickwindowattached_p.h
+++ b/src/quick/items/qquickwindowattached_p.h
@@ -49,6 +49,7 @@ class Q_AUTOTEST_EXPORT QQuickWindowAttached : public QObject
Q_PROPERTY(QWindow::Visibility visibility READ visibility NOTIFY visibilityChanged)
Q_PROPERTY(bool active READ isActive NOTIFY activeChanged)
Q_PROPERTY(QQuickItem* activeFocusItem READ activeFocusItem NOTIFY activeFocusItemChanged)
+ Q_PROPERTY(QQuickItem* contentItem READ contentItem NOTIFY contentItemChanged)
public:
QQuickWindowAttached(QObject* attachee);
@@ -56,12 +57,14 @@ public:
QWindow::Visibility visibility() const;
bool isActive() const;
QQuickItem* activeFocusItem() const;
+ QQuickItem* contentItem() const;
Q_SIGNALS:
void visibilityChanged();
void activeChanged();
void activeFocusItemChanged();
+ void contentItemChanged();
protected Q_SLOTS:
void windowChanged(QQuickWindow*);
diff --git a/src/quick/qtquick2.cpp b/src/quick/qtquick2.cpp
index 6acff85961..09784d161a 100644
--- a/src/quick/qtquick2.cpp
+++ b/src/quick/qtquick2.cpp
@@ -194,5 +194,10 @@ void QQmlQtQuick2Module::defineModule()
}
}
+void QQmlQtQuick2Module::undefineModule()
+{
+ QQuick_deinitializeProviders();
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/qtquick2_p.h b/src/quick/qtquick2_p.h
index 2847d5d3ff..8f415cbd02 100644
--- a/src/quick/qtquick2_p.h
+++ b/src/quick/qtquick2_p.h
@@ -42,6 +42,7 @@ class Q_QUICK_PRIVATE_EXPORT QQmlQtQuick2Module
{
public:
static void defineModule();
+ static void undefineModule();
};
QT_END_NAMESPACE
diff --git a/src/quick/qtquickglobal_p.h b/src/quick/qtquickglobal_p.h
index e2bf198b1c..7fe09da92e 100644
--- a/src/quick/qtquickglobal_p.h
+++ b/src/quick/qtquickglobal_p.h
@@ -54,6 +54,7 @@
QT_BEGIN_NAMESPACE
void QQuick_initializeProviders();
+void QQuick_deinitializeProviders();
Q_DECLARE_LOGGING_CATEGORY(DBG_TOUCH)
Q_DECLARE_LOGGING_CATEGORY(DBG_MOUSE)
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index e0b96a45b6..7ddfdeb2d4 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -175,6 +175,11 @@ void QSGDistanceFieldGlyphCache::update()
storeGlyphs(distanceFields);
+#if defined(QSG_DISTANCEFIELD_CACHE_DEBUG)
+ foreach (Texture texture, m_textures)
+ saveTexture(texture.textureId, texture.size.width(), texture.size.height());
+#endif
+
if (QSG_LOG_TIME_GLYPH().isDebugEnabled()) {
quint64 now = qsg_render_timer.elapsed();
qCDebug(QSG_LOG_TIME_GLYPH,
@@ -283,6 +288,163 @@ void QSGDistanceFieldGlyphCache::updateTexture(GLuint oldTex, GLuint newTex, con
}
}
+#if defined(QSG_DISTANCEFIELD_CACHE_DEBUG)
+#include <QtGui/qopenglfunctions.h>
+
+void QSGDistanceFieldGlyphCache::saveTexture(GLuint textureId, int width, int height) const
+{
+ QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions();
+
+ GLuint fboId;
+ functions->glGenFramebuffers(1, &fboId);
+
+ GLuint tmpTexture = 0;
+ functions->glGenTextures(1, &tmpTexture);
+ functions->glBindTexture(GL_TEXTURE_2D, tmpTexture);
+ functions->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ functions->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ functions->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ functions->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ functions->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ functions->glBindTexture(GL_TEXTURE_2D, 0);
+
+ functions->glBindFramebuffer(GL_FRAMEBUFFER_EXT, fboId);
+ functions->glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,
+ tmpTexture, 0);
+
+ functions->glActiveTexture(GL_TEXTURE0);
+ functions->glBindTexture(GL_TEXTURE_2D, textureId);
+
+ functions->glDisable(GL_STENCIL_TEST);
+ functions->glDisable(GL_DEPTH_TEST);
+ functions->glDisable(GL_SCISSOR_TEST);
+ functions->glDisable(GL_BLEND);
+
+ GLfloat textureCoordinateArray[8];
+ textureCoordinateArray[0] = 0.0f;
+ textureCoordinateArray[1] = 0.0f;
+ textureCoordinateArray[2] = 1.0f;
+ textureCoordinateArray[3] = 0.0f;
+ textureCoordinateArray[4] = 1.0f;
+ textureCoordinateArray[5] = 1.0f;
+ textureCoordinateArray[6] = 0.0f;
+ textureCoordinateArray[7] = 1.0f;
+
+ GLfloat vertexCoordinateArray[8];
+ vertexCoordinateArray[0] = -1.0f;
+ vertexCoordinateArray[1] = -1.0f;
+ vertexCoordinateArray[2] = 1.0f;
+ vertexCoordinateArray[3] = -1.0f;
+ vertexCoordinateArray[4] = 1.0f;
+ vertexCoordinateArray[5] = 1.0f;
+ vertexCoordinateArray[6] = -1.0f;
+ vertexCoordinateArray[7] = 1.0f;
+
+ functions->glViewport(0, 0, width, height);
+ functions->glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray);
+ functions->glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray);
+
+ {
+ static const char *vertexShaderSource =
+ "attribute vec4 vertexCoordsArray; \n"
+ "attribute vec2 textureCoordArray; \n"
+ "varying vec2 textureCoords; \n"
+ "void main(void) \n"
+ "{ \n"
+ " gl_Position = vertexCoordsArray; \n"
+ " textureCoords = textureCoordArray; \n"
+ "} \n";
+
+ static const char *fragmentShaderSource =
+ "varying vec2 textureCoords; \n"
+ "uniform sampler2D texture; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = texture2D(texture, textureCoords); \n"
+ "} \n";
+
+ GLuint vertexShader = functions->glCreateShader(GL_VERTEX_SHADER);
+ GLuint fragmentShader = functions->glCreateShader(GL_FRAGMENT_SHADER);
+
+ if (vertexShader == 0 || fragmentShader == 0) {
+ GLenum error = functions->glGetError();
+ qWarning("QSGDistanceFieldGlyphCache::saveTexture: Failed to create shaders. (GL error: %x)",
+ error);
+ return;
+ }
+
+ functions->glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
+ functions->glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
+ functions->glCompileShader(vertexShader);
+
+ GLint len = 1;
+ functions->glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &len);
+
+ char infoLog[2048];
+ functions->glGetShaderInfoLog(vertexShader, 2048, NULL, infoLog);
+ if (qstrlen(infoLog) > 0)
+ qWarning("Problems compiling vertex shader:\n %s", infoLog);
+
+ functions->glCompileShader(fragmentShader);
+ functions->glGetShaderInfoLog(fragmentShader, 2048, NULL, infoLog);
+ if (qstrlen(infoLog) > 0)
+ qWarning("Problems compiling fragment shader:\n %s", infoLog);
+
+ GLuint shaderProgram = functions->glCreateProgram();
+ functions->glAttachShader(shaderProgram, vertexShader);
+ functions->glAttachShader(shaderProgram, fragmentShader);
+
+ functions->glBindAttribLocation(shaderProgram, 0, "vertexCoordsArray");
+ functions->glBindAttribLocation(shaderProgram, 1, "textureCoordArray");
+
+ functions->glLinkProgram(shaderProgram);
+ functions->glGetProgramInfoLog(shaderProgram, 2048, NULL, infoLog);
+ if (qstrlen(infoLog) > 0)
+ qWarning("Problems linking shaders:\n %s", infoLog);
+
+ functions->glUseProgram(shaderProgram);
+ functions->glEnableVertexAttribArray(0);
+ functions->glEnableVertexAttribArray(1);
+
+ int textureUniformLocation = functions->glGetUniformLocation(shaderProgram, "texture");
+ functions->glUniform1i(textureUniformLocation, 0);
+ }
+
+ functions->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ {
+ GLenum error = functions->glGetError();
+ if (error != GL_NO_ERROR)
+ qWarning("glDrawArrays reported error 0x%x", error);
+ }
+
+ uchar *data = new uchar[width * height * 4];
+
+ functions->glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+
+ QImage image(data, width, height, QImage::Format_ARGB32);
+
+ QByteArray fileName = m_referenceFont.familyName().toLatin1() + '_' + QByteArray::number(textureId);
+ fileName = fileName.replace('/', '_').replace(' ', '_') + ".png";
+
+ image.save(QString::fromLocal8Bit(fileName));
+
+ {
+ GLenum error = functions->glGetError();
+ if (error != GL_NO_ERROR)
+ qWarning("glReadPixels reported error 0x%x", error);
+ }
+
+ functions->glDisableVertexAttribArray(0);
+ functions->glDisableVertexAttribArray(1);
+
+ functions->glDeleteFramebuffers(1, &fboId);
+ functions->glDeleteTextures(1, &tmpTexture);
+
+ delete[] data;
+}
+#endif
+
void QSGNodeVisitorEx::visitChildren(QSGNode *node)
{
for (QSGNode *child = node->firstChild(); child; child = child->nextSibling()) {
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index a63299fcde..ef21385ee6 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -126,17 +126,6 @@ public:
class Q_QUICK_PRIVATE_EXPORT QSGImageNode : public QSGVisitableNode
{
public:
- enum AntialiasingFlag
- {
- AntialiasingNone = 0,
- AntialiasingLeft = 1,
- AntialiasingRight = 2,
- AntialiasingTop = 4,
- AntialiasingBottom = 8,
- AntialiasingAll = AntialiasingLeft | AntialiasingRight | AntialiasingBottom | AntialiasingTop
- };
- Q_DECLARE_FLAGS(AntialiasingFlags, AntialiasingFlag)
-
virtual void setTargetRect(const QRectF &rect) = 0;
virtual void setInnerTargetRect(const QRectF &rect) = 0;
virtual void setInnerSourceRect(const QRectF &rect) = 0;
@@ -151,7 +140,6 @@ public:
virtual void setFiltering(QSGTexture::Filtering filtering) = 0;
virtual void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) = 0;
virtual void setVerticalWrapMode(QSGTexture::WrapMode wrapMode) = 0;
- virtual void setAntialiasing(AntialiasingFlags flags) { Q_UNUSED(flags); }
virtual void update() = 0;
@@ -357,6 +345,10 @@ protected:
GlyphData &glyphData(glyph_t glyph);
+#if defined(QSG_DISTANCEFIELD_CACHE_DEBUG)
+ void saveTexture(GLuint textureId, int width, int height) const;
+#endif
+
inline bool isCoreProfile() const { return m_coreProfile; }
private:
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 50db3883a5..95388d82e0 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -357,7 +357,7 @@ void QSGContext::renderContextInitialized(QSGRenderContext *renderContext)
// before without a context. Now the context is ready.
if (!d->distanceFieldAntialiasingDecided) {
d->distanceFieldAntialiasingDecided = true;
-#ifndef Q_OS_WIN
+#ifndef Q_OS_WIN32
if (renderContext->openglContext()->isOpenGLES())
d->distanceFieldAntialiasing = QSGGlyphNode::GrayAntialiasing;
#endif
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
index 093e84b618..3d958245d2 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
@@ -48,6 +48,10 @@ QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(qmlUseGlyphCacheWorkaround, QML_USE_GLYPHCACHE_WORKAROUND)
+#if !defined(QSG_DEFAULT_DISTANCEFIELD_GLYPH_CACHE_PADDING)
+# define QSG_DEFAULT_DISTANCEFIELD_GLYPH_CACHE_PADDING 2
+#endif
+
QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font)
: QSGDistanceFieldGlyphCache(man, c, font)
, m_maxTextureSize(0)
@@ -90,8 +94,9 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyph
for (QSet<glyph_t>::const_iterator it = glyphs.constBegin(); it != glyphs.constEnd() ; ++it) {
glyph_t glyphIndex = *it;
+ int padding = QSG_DEFAULT_DISTANCEFIELD_GLYPH_CACHE_PADDING;
int glyphWidth = qCeil(glyphData(glyphIndex).boundingRect.width()) + distanceFieldRadius() * 2;
- QSize glyphSize(glyphWidth, QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()));
+ QSize glyphSize(glyphWidth + padding * 2, QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()) + padding * 2);
QRect alloc = m_areaAllocator->allocate(glyphSize);
if (alloc.isNull()) {
@@ -101,7 +106,10 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyph
TexCoord unusedCoord = glyphTexCoord(unusedGlyph);
int unusedGlyphWidth = qCeil(glyphData(unusedGlyph).boundingRect.width()) + distanceFieldRadius() * 2;
- m_areaAllocator->deallocate(QRect(unusedCoord.x, unusedCoord.y, unusedGlyphWidth, QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution())));
+ m_areaAllocator->deallocate(QRect(unusedCoord.x - padding,
+ unusedCoord.y - padding,
+ padding * 2 + unusedGlyphWidth,
+ padding * 2 + QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution())));
m_unusedGlyphs.remove(unusedGlyph);
m_glyphsTexture.remove(unusedGlyph);
@@ -117,11 +125,14 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyph
TextureInfo *tex = textureInfo(alloc.y() / maxTextureSize());
alloc = QRect(alloc.x(), alloc.y() % maxTextureSize(), alloc.width(), alloc.height());
+
tex->allocatedArea |= alloc;
+ Q_ASSERT(tex->padding == padding || tex->padding < 0);
+ tex->padding = padding;
GlyphPosition p;
p.glyph = glyphIndex;
- p.position = alloc.topLeft();
+ p.position = alloc.topLeft() + QPoint(padding, padding);
glyphPositions.append(p);
glyphsToRender.append(glyphIndex);
@@ -153,13 +164,14 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QList<QDistanceField>
glyphTextures[texInfo].append(glyphIndex);
+ int padding = texInfo->padding;
int expectedWidth = qCeil(c.width + c.xMargin * 2);
- if (glyph.width() != expectedWidth)
- glyph = glyph.copy(0, 0, expectedWidth, glyph.height());
+ glyph = glyph.copy(-padding, -padding,
+ expectedWidth + padding * 2, glyph.height() + padding * 2);
if (useTextureResizeWorkaround()) {
uchar *inBits = glyph.scanLine(0);
- uchar *outBits = texInfo->image.scanLine(int(c.y)) + int(c.x);
+ uchar *outBits = texInfo->image.scanLine(int(c.y) - padding) + int(c.x) - padding;
for (int y = 0; y < glyph.height(); ++y) {
memcpy(outBits, inBits, glyph.width());
inBits += glyph.width();
@@ -175,13 +187,13 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QList<QDistanceField>
if (useTextureUploadWorkaround()) {
for (int i = 0; i < glyph.height(); ++i) {
m_funcs->glTexSubImage2D(GL_TEXTURE_2D, 0,
- c.x, c.y + i, glyph.width(),1,
+ c.x - padding, c.y + i - padding, glyph.width(),1,
format, GL_UNSIGNED_BYTE,
glyph.scanLine(i));
}
} else {
m_funcs->glTexSubImage2D(GL_TEXTURE_2D, 0,
- c.x, c.y, glyph.width(), glyph.height(),
+ c.x - padding, c.y - padding, glyph.width(), glyph.height(),
format, GL_UNSIGNED_BYTE,
glyph.constBits());
}
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
index f7314776d6..2f9331f6d8 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
@@ -73,8 +73,9 @@ private:
QSize size;
QRect allocatedArea;
QDistanceField image;
+ int padding;
- TextureInfo() : texture(0)
+ TextureInfo() : texture(0), padding(-1)
{ }
};
diff --git a/src/quick/scenegraph/qsgdefaultimagenode.cpp b/src/quick/scenegraph/qsgdefaultimagenode.cpp
index 69df506d2a..7f85c31ccb 100644
--- a/src/quick/scenegraph/qsgdefaultimagenode.cpp
+++ b/src/quick/scenegraph/qsgdefaultimagenode.cpp
@@ -140,11 +140,10 @@ void SmoothTextureMaterialShader::initialize()
QSGDefaultImageNode::QSGDefaultImageNode()
: m_innerSourceRect(0, 0, 1, 1)
, m_subSourceRect(0, 0, 1, 1)
+ , m_antialiasing(false)
, m_mirror(false)
, m_dirtyGeometry(false)
, m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
- , m_antialiasing(AntialiasingNone)
-
{
setMaterial(&m_materialO);
setOpaqueMaterial(&m_material);
@@ -250,20 +249,10 @@ void QSGDefaultImageNode::setTexture(QSGTexture *texture)
void QSGDefaultImageNode::setAntialiasing(bool antialiasing)
{
- AntialiasingFlags antialiasingFlags = antialiasing
- ? AntialiasingAll
- : AntialiasingNone;
-
- setAntialiasing(antialiasingFlags);
-}
-
-void QSGDefaultImageNode::setAntialiasing(AntialiasingFlags antialiasingFlags)
-{
- if (antialiasingFlags == m_antialiasing)
+ if (antialiasing == m_antialiasing)
return;
-
- m_antialiasing = antialiasingFlags;
- if (m_antialiasing != AntialiasingNone) {
+ m_antialiasing = antialiasing;
+ if (m_antialiasing) {
setMaterial(&m_smoothMaterial);
setOpaqueMaterial(0);
setGeometry(new QSGGeometry(smoothAttributeSet(), 0));
@@ -375,14 +364,11 @@ void QSGDefaultImageNode::updateGeometry()
}
// An image can be rendered as a single quad if:
- // - There is antialiasing on all or no edges
// - There are no margins, and either:
// - the image isn't repeated
// - the source rectangle fills the entire texture so that texture wrapping can be used,
// and NPOT is supported
- if (!hasMargins
- && (m_antialiasing == AntialiasingAll || m_antialiasing == AntialiasingNone)
- && (!hasTiles || (fullTexture && wrapSupported))) {
+ if (!hasMargins && (!hasTiles || (fullTexture && wrapSupported))) {
QRectF sr;
if (!fullTexture) {
sr = QRectF(innerSourceRect.x() + (m_subSourceRect.left() - floorLeft) * innerSourceRect.width(),
@@ -561,35 +547,10 @@ void QSGDefaultImageNode::updateGeometry()
topDv = bottomDv *= 0.5f;
}
- if (!m_antialiasing.testFlag(AntialiasingTop)) {
- topDy = 0.0f;
- topDv = 0.0f;
- }
-
- if (!m_antialiasing.testFlag(AntialiasingBottom)) {
- bottomDy = 0.0f;
- bottomDv = 0.0f;
- }
-
- if (!m_antialiasing.testFlag(AntialiasingLeft)) {
- leftDx = 0.0f;
- leftDu = 0.0f;
- }
-
- if (!m_antialiasing.testFlag(AntialiasingRight)) {
- rightDx = 0.0f;
- rightDu = 0.0f;
- }
-
// This delta is how much the fuzziness can reach out from the image.
float delta = float(qAbs(m_targetRect.width()) < qAbs(m_targetRect.height())
? m_targetRect.width() : m_targetRect.height()) * 0.5f;
- float deltaTop = m_antialiasing.testFlag(AntialiasingTop) ? delta : 0.0f;
- float deltaBottom = m_antialiasing.testFlag(AntialiasingBottom) ? delta : 0.0f;
- float deltaLeft = m_antialiasing.testFlag(AntialiasingLeft) ? delta : 0.0f;
- float deltaRight = m_antialiasing.testFlag(AntialiasingRight) ? delta : 0.0f;
-
quint16 index = 0;
ys = yData.data();
for (int j = 0; j < vCells; ++j, ys += 2) {
@@ -639,28 +600,28 @@ void QSGDefaultImageNode::updateGeometry()
if (isTop) {
vertices[topLeft].dy = vertices[topRight].dy = topDy;
vertices[topLeft].dv = vertices[topRight].dv = topDv;
- vertices[topLeft + 1].dy = vertices[topRight + 1].dy = -deltaTop;
+ vertices[topLeft + 1].dy = vertices[topRight + 1].dy = -delta;
appendQuad(&indices, topLeft + 1, topRight + 1, topLeft, topRight);
}
if (isBottom) {
vertices[bottomLeft].dy = vertices[bottomRight].dy = -bottomDy;
vertices[bottomLeft].dv = vertices[bottomRight].dv = -bottomDv;
- vertices[bottomLeft + 1].dy = vertices[bottomRight + 1].dy = deltaBottom;
+ vertices[bottomLeft + 1].dy = vertices[bottomRight + 1].dy = delta;
appendQuad(&indices, bottomLeft, bottomRight, bottomLeft + 1, bottomRight + 1);
}
if (isLeft) {
vertices[topLeft].dx = vertices[bottomLeft].dx = leftDx;
vertices[topLeft].du = vertices[bottomLeft].du = leftDu;
- vertices[topLeft + 1].dx = vertices[bottomLeft + 1].dx = -deltaLeft;
+ vertices[topLeft + 1].dx = vertices[bottomLeft + 1].dx = -delta;
appendQuad(&indices, topLeft + 1, topLeft, bottomLeft + 1, bottomLeft);
}
if (isRight) {
vertices[topRight].dx = vertices[bottomRight].dx = -rightDx;
vertices[topRight].du = vertices[bottomRight].du = -rightDu;
- vertices[topRight + 1].dx = vertices[bottomRight + 1].dx = deltaRight;
+ vertices[topRight + 1].dx = vertices[bottomRight + 1].dx = delta;
appendQuad(&indices, topRight, topRight + 1, bottomRight, bottomRight + 1);
}
}
diff --git a/src/quick/scenegraph/qsgdefaultimagenode_p.h b/src/quick/scenegraph/qsgdefaultimagenode_p.h
index 558e4d8ba4..26b087284b 100644
--- a/src/quick/scenegraph/qsgdefaultimagenode_p.h
+++ b/src/quick/scenegraph/qsgdefaultimagenode_p.h
@@ -62,7 +62,6 @@ public:
virtual void setSubSourceRect(const QRectF &rect);
virtual void setTexture(QSGTexture *t);
virtual void setAntialiasing(bool antialiasing);
- virtual void setAntialiasing(AntialiasingFlags antialiasing);
virtual void setMirror(bool mirror);
virtual void update();
@@ -85,11 +84,11 @@ private:
QSGTextureMaterial m_materialO;
QSGSmoothTextureMaterial m_smoothMaterial;
+ uint m_antialiasing : 1;
uint m_mirror : 1;
uint m_dirtyGeometry : 1;
QSGGeometry m_geometry;
- AntialiasingFlags m_antialiasing;
};
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
index 6f54b258ff..f635ccd17b 100644
--- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
@@ -399,176 +399,6 @@ void QSGSharedDistanceFieldGlyphCache::unregisterOwnerElement(QQuickItem *ownerE
}
}
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG_)
-# include <QtOpenGL/private/qglextensions_p.h>
-
-void QSGSharedDistanceFieldGlyphCache::saveTexture(GLuint textureId, int width, int height)
-{
- GLuint fboId;
- glGenFramebuffers(1, &fboId);
-
- GLuint tmpTexture = 0;
- glGenTextures(1, &tmpTexture);
- glBindTexture(GL_TEXTURE_2D, tmpTexture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- glBindFramebuffer(GL_FRAMEBUFFER_EXT, fboId);
- glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,
- tmpTexture, 0);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, textureId);
-
- glDisable(GL_STENCIL_TEST);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_SCISSOR_TEST);
- glDisable(GL_BLEND);
-
- GLfloat textureCoordinateArray[8];
- textureCoordinateArray[0] = 0.0f;
- textureCoordinateArray[1] = 0.0f;
- textureCoordinateArray[2] = 1.0f;
- textureCoordinateArray[3] = 0.0f;
- textureCoordinateArray[4] = 1.0f;
- textureCoordinateArray[5] = 1.0f;
- textureCoordinateArray[6] = 0.0f;
- textureCoordinateArray[7] = 1.0f;
-
- GLfloat vertexCoordinateArray[8];
- vertexCoordinateArray[0] = -1.0f;
- vertexCoordinateArray[1] = -1.0f;
- vertexCoordinateArray[2] = 1.0f;
- vertexCoordinateArray[3] = -1.0f;
- vertexCoordinateArray[4] = 1.0f;
- vertexCoordinateArray[5] = 1.0f;
- vertexCoordinateArray[6] = -1.0f;
- vertexCoordinateArray[7] = 1.0f;
-
- glViewport(0, 0, width, height);
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray);
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray);
-
- {
- static const char vertexShaderSource[] =
- "attribute highp vec4 vertexCoordsArray; \n"
- "attribute highp vec2 textureCoordArray; \n"
- "varying highp vec2 textureCoords; \n"
- "void main(void) \n"
- "{ \n"
- " gl_Position = vertexCoordsArray; \n"
- " textureCoords = textureCoordArray; \n"
- "} \n";
-
- static const char fragmentShaderSource[] =
- "varying highp vec2 textureCoords; \n"
- "uniform sampler2D texture; \n"
- "void main() \n"
- "{ \n"
- " gl_FragColor = texture2D(texture, textureCoords); \n"
- "} \n";
-
- GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
- GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
-
- if (vertexShader == 0 || fragmentShader == 0) {
- GLenum error = glGetError();
- qWarning("SharedGraphicsCacheServer::setupShaderPrograms: Failed to create shaders. (GL error: %x)",
- error);
- return;
- }
-
- glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
- glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
- glCompileShader(vertexShader);
-
- GLint len = 1;
- glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &len);
-
- char infoLog[2048];
- glGetShaderInfoLog(vertexShader, 2048, NULL, infoLog);
- if (qstrlen(infoLog) > 0) {
- qWarning("SharedGraphicsCacheServer::setupShaderPrograms, problems compiling vertex shader:\n %s",
- infoLog);
- //return;
- }
-
- glCompileShader(fragmentShader);
- glGetShaderInfoLog(fragmentShader, 2048, NULL, infoLog);
- if (qstrlen(infoLog) > 0) {
- qWarning("SharedGraphicsCacheServer::setupShaderPrograms, problems compiling fragent shader:\n %s",
- infoLog);
- //return;
- }
-
- GLuint shaderProgram = glCreateProgram();
- glAttachShader(shaderProgram, vertexShader);
- glAttachShader(shaderProgram, fragmentShader);
-
- glBindAttribLocation(shaderProgram, 0, "vertexCoordsArray");
- glBindAttribLocation(shaderProgram, 1, "textureCoordArray");
-
- glLinkProgram(shaderProgram);
- glGetProgramInfoLog(shaderProgram, 2048, NULL, infoLog);
- if (qstrlen(infoLog) > 0) {
- qWarning("SharedGraphicsCacheServer::setupShaderPrograms, problems linking shaders:\n %s",
- infoLog);
- //return;
- }
-
- glUseProgram(shaderProgram);
- glEnableVertexAttribArray(0);
- glEnableVertexAttribArray(1);
-
- int textureUniformLocation = glGetUniformLocation(shaderProgram, "_qt_texture");
- glUniform1i(textureUniformLocation, 0);
- }
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- {
- GLenum error = glGetError();
- if (error != GL_NO_ERROR) {
- qWarning("SharedGraphicsCacheServer::readBackBuffer: glDrawArrays reported error 0x%x",
- error);
- }
- }
-
- uchar *data = new uchar[width * height * 4];
-
- glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
-
- QImage image(width, height, QImage::Format_ARGB32);
- quint32 *dest = reinterpret_cast<quint32 *>(image.bits());
- for (int i=0; i<width*height; ++i)
- dest[i] = qRgba(0xff, 0xff, 0xff, data[i]);
-
- QByteArray fileName = m_cacheId + ' ' + QByteArray::number(textureId);
- fileName = fileName.replace('/', '_').replace(' ', '_') + ".png";
- image.save(QString::fromLocal8Bit(fileName));
-
- {
- GLenum error = glGetError();
- if (error != GL_NO_ERROR) {
- qWarning("SharedGraphicsCacheServer::readBackBuffer: glReadPixels reported error 0x%x",
- error);
- }
- }
-
- glDisableVertexAttribArray(0);
- glDisableVertexAttribArray(1);
-
- glDeleteFramebuffers(1, &fboId);
- glDeleteTextures(1, &tmpTexture);
-
- delete[] data;
-}
-#endif
-
namespace {
struct TextureContent {
QSize size;
@@ -683,9 +513,6 @@ void QSGSharedDistanceFieldGlyphCache::processPendingGlyphs()
texture.textureId = m_sharedGraphicsCache->textureIdForBuffer(it.key());
texture.size = m_sharedGraphicsCache->sizeOfBuffer(it.key());
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG_)
- saveTexture(texture.textureId, texture.size.width(), texture.size.height());
-#endif
setGlyphsTexture(it.value().glyphs, texture);
++it;
diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
index 469cd1d21b..58d618a049 100644
--- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp
+++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
@@ -38,6 +38,7 @@
#include <QtGui/QScreen>
#include <QtGui/QGuiApplication>
+#include <QtGui/QOffscreenSurface>
#include <QtQuick/private/qsgcontext_p.h>
#include <QtQuick/private/qquickwindow_p.h>
@@ -214,15 +215,29 @@ void QSGWindowsRenderLoop::windowDestroyed(QQuickWindow *window)
hide(window);
QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
- if (m_gl)
- m_gl->makeCurrent(window);
+ bool current = false;
+ QScopedPointer<QOffscreenSurface> offscreenSurface;
+ if (m_gl) {
+ QSurface *surface = window;
+ // There may be no platform window if the window got closed.
+ if (!window->handle()) {
+ offscreenSurface.reset(new QOffscreenSurface);
+ offscreenSurface->setFormat(m_gl->format());
+ offscreenSurface->create();
+ surface = offscreenSurface.data();
+ }
+ current = m_gl->makeCurrent(surface);
+ }
+ if (Q_UNLIKELY(!current))
+ qCDebug(QSG_LOG_RENDERLOOP) << "cleanup without an OpenGL context";
+
d->cleanupNodesOnShutdown();
if (m_windows.size() == 0) {
d->context->invalidate();
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
delete m_gl;
m_gl = 0;
- } else if (m_gl) {
+ } else if (m_gl && current) {
m_gl->doneCurrent();
}
}
diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri
index bcb523f90d..480ac5e569 100644
--- a/src/quick/scenegraph/scenegraph.pri
+++ b/src/quick/scenegraph/scenegraph.pri
@@ -1,6 +1,7 @@
!contains(QT_CONFIG, egl):DEFINES += QT_NO_EGL
# DEFINES += QSG_SEPARATE_INDEX_BUFFER
+# DEFINES += QSG_DISTANCEFIELD_CACHE_DEBUG
# Core API
HEADERS += \
diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp
index 27b9e656ec..34e00e0b01 100644
--- a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp
+++ b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp
@@ -299,6 +299,8 @@ QSGSimpleTextureNode::TextureCoordinatesTransformMode QSGSimpleTextureNode::text
By default, the node does not take ownership of the texture.
\sa setTexture()
+
+ \since 5.4
*/
void QSGSimpleTextureNode::setOwnsTexture(bool owns)
{
@@ -308,6 +310,8 @@ void QSGSimpleTextureNode::setOwnsTexture(bool owns)
/*!
Returns \c true if the node takes ownership of the texture; otherwise returns \c false.
+
+ \since 5.4
*/
bool QSGSimpleTextureNode::ownsTexture() const
{
diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp
index 455e180dbe..139bae4038 100644
--- a/src/quick/util/qquickglobal.cpp
+++ b/src/quick/util/qquickglobal.cpp
@@ -982,4 +982,11 @@ void QQuick_initializeProviders()
QQml_setGuiProvider(getGuiProvider());
}
+void QQuick_deinitializeProviders()
+{
+ QQml_removeValueTypeProvider(getValueTypeProvider());
+ QQml_setColorProvider(0); // technically, another plugin may have overridden our providers
+ QQml_setGuiProvider(0); // but we cannot handle that case in a sane way.
+}
+
QT_END_NAMESPACE