aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-03-14 10:49:51 +0100
committerLiang Qi <liang.qi@qt.io>2017-03-14 10:49:51 +0100
commit12e82111ab86669969430ab10118236d8d846d33 (patch)
treefb2345160fbe9d46cb61212f4a5eac81389464ba /src/quick/scenegraph
parent30635ee2424dbd08bb5c2170be0c2dc5f9d23b2c (diff)
parent77e0dc0485953427320ed0b442ba24eef4f9d73b (diff)
Merge remote-tracking branch 'origin/5.9' into dev
Diffstat (limited to 'src/quick/scenegraph')
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp9
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop_p.h2
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode.cpp128
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.h23
4 files changed, 158 insertions, 4 deletions
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
index 6856d34616..b3b8274a73 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
@@ -101,7 +101,7 @@ void QSGSoftwareRenderLoop::windowDestroyed(QQuickWindow *window)
}
}
-void QSGSoftwareRenderLoop::renderWindow(QQuickWindow *window)
+void QSGSoftwareRenderLoop::renderWindow(QQuickWindow *window, bool isNewExpose)
{
QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window);
if (!m_windows.contains(window))
@@ -174,7 +174,10 @@ void QSGSoftwareRenderLoop::renderWindow(QQuickWindow *window)
if (alsoSwap && window->isVisible()) {
//Flush backingstore to window
- m_backingStores[window]->flush(softwareRenderer->flushRegion());
+ if (!isNewExpose)
+ m_backingStores[window]->flush(softwareRenderer->flushRegion());
+ else
+ m_backingStores[window]->flush(QRegion(QRect(QPoint(0,0), window->size())));
cd->fireFrameSwapped();
}
@@ -206,7 +209,7 @@ void QSGSoftwareRenderLoop::exposureChanged(QQuickWindow *window)
{
if (window->isExposed()) {
m_windows[window].updatePending = true;
- renderWindow(window);
+ renderWindow(window, true);
}
}
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop_p.h
index 02dcf4eefa..c724d18298 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop_p.h
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop_p.h
@@ -69,7 +69,7 @@ public:
void windowDestroyed(QQuickWindow *window) override;
- void renderWindow(QQuickWindow *window);
+ void renderWindow(QQuickWindow *window, bool isNewExpose = false);
void exposureChanged(QQuickWindow *window) override;
QImage grab(QQuickWindow *window) override;
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode.cpp b/src/quick/scenegraph/qsgdefaultglyphnode.cpp
index b856d99bc1..0d42102f36 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode.cpp
@@ -42,11 +42,33 @@
QT_BEGIN_NAMESPACE
+QSGDefaultGlyphNode::QSGDefaultGlyphNode()
+ : m_glyphNodeType(RootGlyphNode)
+ , m_dirtyGeometry(false)
+{
+ setFlag(UsePreprocess);
+}
+
+QSGDefaultGlyphNode::~QSGDefaultGlyphNode()
+{
+ if (m_glyphNodeType == SubGlyphNode)
+ return;
+
+ qDeleteAll(m_nodesToDelete);
+ m_nodesToDelete.clear();
+}
+
void QSGDefaultGlyphNode::setMaterialColor(const QColor &color)
{
static_cast<QSGTextMaskMaterial *>(m_material)->setColor(color);
}
+void QSGDefaultGlyphNode::setGlyphs(const QPointF &position, const QGlyphRun &glyphs)
+{
+ QSGBasicGlyphNode::setGlyphs(position, glyphs);
+ m_dirtyGeometry = true;
+}
+
void QSGDefaultGlyphNode::update()
{
QRawFont font = m_glyphs.rawFont();
@@ -84,4 +106,110 @@ void QSGDefaultGlyphNode::update()
markDirty(DirtyGeometry);
}
+void QSGDefaultGlyphNode::preprocess()
+{
+ qDeleteAll(m_nodesToDelete);
+ m_nodesToDelete.clear();
+
+ if (m_dirtyGeometry)
+ updateGeometry();
+}
+
+void QSGDefaultGlyphNode::updateGeometry()
+{
+ // Remove previously created sub glyph nodes
+ // We assume all the children are sub glyph nodes
+ QSGNode *subnode = firstChild();
+ while (subnode) {
+ // We can't delete the node now as it might be in the preprocess list
+ // It will be deleted in the next preprocess
+ m_nodesToDelete.append(subnode);
+ subnode = subnode->nextSibling();
+ }
+ removeAllChildNodes();
+
+ GlyphInfo glyphInfo;
+
+ const QVector<quint32> indexes = m_glyphs.glyphIndexes();
+ const QVector<QPointF> positions = m_glyphs.positions();
+
+ const int maxGlyphs = (USHRT_MAX + 1) / 4; // 16384
+ const int maxVertices = maxGlyphs * 4; // 65536
+ const int maxIndexes = maxGlyphs * 6; // 98304
+
+ for (int i = 0; i < indexes.size(); ++i) {
+ const int glyphIndex = indexes.at(i);
+ const QPointF position = positions.at(i);
+
+ // As we use UNSIGNED_SHORT indexing in the geometry, we overload the
+ // "glyphsInOtherNodes" concept as overflow for if there are more than
+ // 65536 (16384 * 4) vertices to render which would otherwise exceed
+ // the maximum index size. This will cause sub-nodes to be recursively
+ // created to handle any number of glyphs.
+ if (i >= maxGlyphs) {
+ glyphInfo.indexes.append(glyphIndex);
+ glyphInfo.positions.append(position);
+ continue;
+ }
+ }
+
+ if (!glyphInfo.indexes.isEmpty()) {
+ QGlyphRun subNodeGlyphRun(m_glyphs);
+ subNodeGlyphRun.setGlyphIndexes(glyphInfo.indexes);
+ subNodeGlyphRun.setPositions(glyphInfo.positions);
+
+ QSGDefaultGlyphNode *subNode = new QSGDefaultGlyphNode();
+ subNode->setGlyphNodeType(SubGlyphNode);
+ subNode->setColor(m_color);
+ subNode->setStyle(m_style);
+ subNode->setStyleColor(m_styleColor);
+ subNode->setGlyphs(m_position, subNodeGlyphRun);
+ subNode->update();
+ subNode->updateGeometry(); // we have to explicitly call this now as preprocess won't be called before it's rendered
+ appendChildNode(subNode);
+
+ QSGGeometry *g = geometry();
+
+ QSGGeometry::TexturedPoint2D *vertexData = g->vertexDataAsTexturedPoint2D();
+ quint16 *indexData = g->indexDataAsUShort();
+
+ QVector<QSGGeometry::TexturedPoint2D> tempVertexData(maxVertices);
+ QVector<quint16> tempIndexData(maxIndexes);
+
+ for (int i = 0; i < maxGlyphs; i++) {
+ tempVertexData[i * 4 + 0] = vertexData[i * 4 + 0];
+ tempVertexData[i * 4 + 1] = vertexData[i * 4 + 1];
+ tempVertexData[i * 4 + 2] = vertexData[i * 4 + 2];
+ tempVertexData[i * 4 + 3] = vertexData[i * 4 + 3];
+
+ tempIndexData[i * 6 + 0] = indexData[i * 6 + 0];
+ tempIndexData[i * 6 + 1] = indexData[i * 6 + 1];
+ tempIndexData[i * 6 + 2] = indexData[i * 6 + 2];
+ tempIndexData[i * 6 + 3] = indexData[i * 6 + 3];
+ tempIndexData[i * 6 + 4] = indexData[i * 6 + 4];
+ tempIndexData[i * 6 + 5] = indexData[i * 6 + 5];
+ }
+
+ g->allocate(maxVertices, maxIndexes);
+ vertexData = g->vertexDataAsTexturedPoint2D();
+ indexData = g->indexDataAsUShort();
+
+ for (int i = 0; i < maxGlyphs; i++) {
+ vertexData[i * 4 + 0] = tempVertexData[i * 4 + 0];
+ vertexData[i * 4 + 1] = tempVertexData[i * 4 + 1];
+ vertexData[i * 4 + 2] = tempVertexData[i * 4 + 2];
+ vertexData[i * 4 + 3] = tempVertexData[i * 4 + 3];
+
+ indexData[i * 6 + 0] = tempIndexData[i * 6 + 0];
+ indexData[i * 6 + 1] = tempIndexData[i * 6 + 1];
+ indexData[i * 6 + 2] = tempIndexData[i * 6 + 2];
+ indexData[i * 6 + 3] = tempIndexData[i * 6 + 3];
+ indexData[i * 6 + 4] = tempIndexData[i * 6 + 4];
+ indexData[i * 6 + 5] = tempIndexData[i * 6 + 5];
+ }
+ }
+
+ m_dirtyGeometry = false;
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.h b/src/quick/scenegraph/qsgdefaultglyphnode_p.h
index 0eb7a4e4bd..37a89c70b9 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.h
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.h
@@ -59,8 +59,31 @@ QT_BEGIN_NAMESPACE
class QSGDefaultGlyphNode : public QSGBasicGlyphNode
{
public:
+ QSGDefaultGlyphNode();
+ ~QSGDefaultGlyphNode();
void setMaterialColor(const QColor &color) override;
+ void setGlyphs(const QPointF &position, const QGlyphRun &glyphs) override;
void update() override;
+ void preprocess() override;
+ void updateGeometry();
+
+private:
+ enum DefaultGlyphNodeType {
+ RootGlyphNode,
+ SubGlyphNode
+ };
+
+ void setGlyphNodeType(DefaultGlyphNodeType type) { m_glyphNodeType = type; }
+
+ DefaultGlyphNodeType m_glyphNodeType;
+ QLinkedList<QSGNode *> m_nodesToDelete;
+
+ struct GlyphInfo {
+ QVector<quint32> indexes;
+ QVector<QPointF> positions;
+ };
+
+ uint m_dirtyGeometry: 1;
};
QT_END_NAMESPACE