aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/scenegraph')
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp36
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h2
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp84
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h3
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp7
-rw-r--r--src/quick/scenegraph/qsgrhishadereffectnode.cpp12
-rw-r--r--src/quick/scenegraph/util/qsgrhiatlastexture.cpp19
7 files changed, 121 insertions, 42 deletions
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp
index ba9952e19d..09eae137bb 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp
@@ -375,21 +375,7 @@ void QSGSoftwareInternalImageNode::setVerticalWrapMode(QSGTexture::WrapMode wrap
void QSGSoftwareInternalImageNode::update()
{
- if (m_cachedMirroredPixmapIsDirty) {
- if (m_mirrorHorizontally || m_mirrorVertically || m_textureIsLayer) {
- QTransform transform(
- (m_mirrorHorizontally ? -1 : 1), 0,
- 0 , (m_textureIsLayer ? -1 : 1) * (m_mirrorVertically ? -1 : 1),
- 0 , 0
- );
- m_cachedMirroredPixmap = pixmap().transformed(transform);
- } else {
- //Cleanup cached pixmap if necessary
- if (!m_cachedMirroredPixmap.isNull())
- m_cachedMirroredPixmap = QPixmap();
- }
- m_cachedMirroredPixmapIsDirty = false;
- }
+ updateCachedMirroredPixmap();
}
void QSGSoftwareInternalImageNode::preprocess()
@@ -423,6 +409,7 @@ void QSGSoftwareInternalImageNode::paint(QPainter *painter)
// Disable antialiased clipping. It causes transformed tiles to have gaps.
painter->setRenderHint(QPainter::Antialiasing, false);
+ updateCachedMirroredPixmap();
const QPixmap &pm = m_mirrorHorizontally || m_mirrorVertically || m_textureIsLayer ? m_cachedMirroredPixmap : pixmap();
if (m_innerTargetRect != m_targetRect) {
@@ -468,4 +455,23 @@ const QPixmap &QSGSoftwareInternalImageNode::pixmap() const
return nullPixmap;
}
+void QSGSoftwareInternalImageNode::updateCachedMirroredPixmap()
+{
+ if (m_cachedMirroredPixmapIsDirty) {
+ if (m_mirrorHorizontally || m_mirrorVertically || m_textureIsLayer) {
+ QTransform transform(
+ (m_mirrorHorizontally ? -1 : 1), 0,
+ 0 , (m_textureIsLayer ? -1 : 1) * (m_mirrorVertically ? -1 : 1),
+ 0 , 0
+ );
+ m_cachedMirroredPixmap = pixmap().transformed(transform);
+ } else {
+ //Cleanup cached pixmap if necessary
+ if (!m_cachedMirroredPixmap.isNull())
+ m_cachedMirroredPixmap = QPixmap();
+ }
+ m_cachedMirroredPixmapIsDirty = false;
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h
index bfbe8420d2..5b5de86708 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h
@@ -92,7 +92,7 @@ public:
const QPixmap &pixmap() const;
private:
-
+ void updateCachedMirroredPixmap();
QRectF m_targetRect;
QRectF m_innerTargetRect;
QRectF m_innerSourceRect;
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index d1394ee3b1..3d5a6c7705 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -922,7 +922,14 @@ Renderer::~Renderer()
Element *e = n->element();
if (!e->removed)
m_elementsToDelete.add(e);
+ } else if (n->type() == QSGNode::ClipNodeType) {
+ delete n->clipInfo();
+ } else if (n->type() == QSGNode::RenderNodeType) {
+ RenderNodeElement *e = n->renderNodeElement();
+ if (!e->removed)
+ m_elementsToDelete.add(e);
}
+
m_nodeAllocator.release(n);
}
@@ -1681,13 +1688,19 @@ void Renderer::prepareOpaqueBatches()
QSGGeometryNode *gnj = ej->node;
+ const QSGGeometry *gniGeometry = gni->geometry();
+ const QSGMaterial *gniMaterial = gni->activeMaterial();
+ const QSGGeometry *gnjGeometry = gnj->geometry();
+ const QSGMaterial *gnjMaterial = gnj->activeMaterial();
if (gni->clipList() == gnj->clipList()
- && gni->geometry()->drawingMode() == gnj->geometry()->drawingMode()
- && (gni->geometry()->drawingMode() != QSGGeometry::DrawLines || gni->geometry()->lineWidth() == gnj->geometry()->lineWidth())
- && gni->geometry()->attributes() == gnj->geometry()->attributes()
+ && gniGeometry->drawingMode() == gnjGeometry->drawingMode()
+ && (gniGeometry->drawingMode() != QSGGeometry::DrawLines || gniGeometry->lineWidth() == gnjGeometry->lineWidth())
+ && gniGeometry->attributes() == gnjGeometry->attributes()
+ && gniGeometry->indexType() == gnjGeometry->indexType()
&& gni->inheritedOpacity() == gnj->inheritedOpacity()
- && gni->activeMaterial()->type() == gnj->activeMaterial()->type()
- && gni->activeMaterial()->compare(gnj->activeMaterial()) == 0) {
+ && gniMaterial->type() == gnjMaterial->type()
+ && gniMaterial->compare(gnjMaterial) == 0)
+ {
ej->batch = batch;
next->nextInBatch = ej;
next = ej;
@@ -1788,17 +1801,23 @@ void Renderer::prepareAlphaBatches()
if (gnj->geometry()->vertexCount() == 0)
continue;
+ const QSGGeometry *gniGeometry = gni->geometry();
+ const QSGMaterial *gniMaterial = gni->activeMaterial();
+ const QSGGeometry *gnjGeometry = gnj->geometry();
+ const QSGMaterial *gnjMaterial = gnj->activeMaterial();
if (gni->clipList() == gnj->clipList()
- && gni->geometry()->drawingMode() == gnj->geometry()->drawingMode()
- && (gni->geometry()->drawingMode() != QSGGeometry::DrawLines
- || (gni->geometry()->lineWidth() == gnj->geometry()->lineWidth()
+ && gniGeometry->drawingMode() == gnjGeometry->drawingMode()
+ && (gniGeometry->drawingMode() != QSGGeometry::DrawLines
+ || (gniGeometry->lineWidth() == gnjGeometry->lineWidth()
// Must not do overlap checks when the line width is not 1,
// we have no knowledge how such lines are rasterized.
- && gni->geometry()->lineWidth() == 1.0f))
- && gni->geometry()->attributes() == gnj->geometry()->attributes()
+ && gniGeometry->lineWidth() == 1.0f))
+ && gniGeometry->attributes() == gnjGeometry->attributes()
+ && gniGeometry->indexType() == gnjGeometry->indexType()
&& gni->inheritedOpacity() == gnj->inheritedOpacity()
- && gni->activeMaterial()->type() == gnj->activeMaterial()->type()
- && gni->activeMaterial()->compare(gnj->activeMaterial()) == 0) {
+ && gniMaterial->type() == gnjMaterial->type()
+ && gniMaterial->compare(gnjMaterial) == 0)
+ {
if (!overlapBounds.intersects(ej->bounds) || !checkOverlap(i+1, j - 1, ej->bounds)) {
ej->batch = batch;
next->nextInBatch = ej;
@@ -2001,7 +2020,7 @@ void Renderer::uploadBatch(Batch *b)
bool canMerge = (g->drawingMode() == QSGGeometry::DrawTriangles || g->drawingMode() == QSGGeometry::DrawTriangleStrip ||
g->drawingMode() == QSGGeometry::DrawLines || g->drawingMode() == QSGGeometry::DrawPoints)
&& b->positionAttribute >= 0
- && (g->indexType() == QSGGeometry::UnsignedShortType && g->indexCount() > 0)
+ && g->indexType() == QSGGeometry::UnsignedShortType
&& (flags & (QSGMaterial::NoBatching | QSGMaterial_FullMatrix)) == 0
&& ((flags & QSGMaterial::RequiresFullMatrixExceptTranslate) == 0 || b->isTranslateOnlyToRoot())
&& b->isSafeToBatch();
@@ -2014,6 +2033,8 @@ void Renderer::uploadBatch(Batch *b)
int unmergedIndexSize = 0;
Element *e = b->first;
+ // Merged batches always do indexed draw calls. Non-indexed geometry gets
+ // indices generated automatically, when merged.
while (e) {
QSGGeometry *eg = e->node->geometry();
b->vertexCount += eg->vertexCount();
@@ -2829,7 +2850,8 @@ void Renderer::updateMaterialDynamicData(ShaderManager::Shader *sms,
const Batch *batch,
Element *e,
int ubufOffset,
- int ubufRegionSize)
+ int ubufRegionSize,
+ char *directUpdatePtr)
{
m_current_resource_update_batch = m_resourceUpdates;
@@ -2842,8 +2864,12 @@ void Renderer::updateMaterialDynamicData(ShaderManager::Shader *sms,
const bool changed = shader->updateUniformData(renderState, material, m_currentMaterial);
m_current_uniform_data = nullptr;
- if (changed || !batch->ubufDataValid)
- m_resourceUpdates->updateDynamicBuffer(batch->ubuf, ubufOffset, ubufRegionSize, pd->masterUniformData.constData());
+ if (changed || !batch->ubufDataValid) {
+ if (directUpdatePtr)
+ memcpy(directUpdatePtr + ubufOffset, pd->masterUniformData.constData(), ubufRegionSize);
+ else
+ m_resourceUpdates->updateDynamicBuffer(batch->ubuf, ubufOffset, ubufRegionSize, pd->masterUniformData.constData());
+ }
bindings.append(QRhiShaderResourceBinding::uniformBuffer(pd->ubufBinding,
pd->ubufStages,
@@ -2857,7 +2883,7 @@ void Renderer::updateMaterialDynamicData(ShaderManager::Shader *sms,
if (!stages)
continue;
- QVarLengthArray<QSGTexture *, 4> prevTex = pd->textureBindingTable[binding];
+ const QVarLengthArray<QSGTexture *, 4> &prevTex(pd->textureBindingTable[binding]);
QVarLengthArray<QSGTexture *, 4> nextTex = prevTex;
const int count = pd->combinedImageSamplerCount[binding];
@@ -3138,7 +3164,14 @@ bool Renderer::prepareRenderMergedBatch(Batch *batch, PreparedRenderBatch *rende
bool pendingGStatePop = false;
updateMaterialStaticData(sms, renderState, material, batch, &pendingGStatePop);
- updateMaterialDynamicData(sms, renderState, material, batch, e, 0, ubufSize);
+ char *directUpdatePtr = nullptr;
+ if (batch->ubuf->nativeBuffer().slotCount == 0)
+ directUpdatePtr = batch->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
+
+ updateMaterialDynamicData(sms, renderState, material, batch, e, 0, ubufSize, directUpdatePtr);
+
+ if (directUpdatePtr)
+ batch->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
#ifndef QT_NO_DEBUG
if (qsg_test_and_clear_material_failure()) {
@@ -3327,6 +3360,11 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren
QRhiGraphicsPipeline *ps = nullptr;
QRhiGraphicsPipeline *depthPostPassPs = nullptr;
e = batch->first;
+
+ char *directUpdatePtr = nullptr;
+ if (batch->ubuf->nativeBuffer().slotCount == 0)
+ directUpdatePtr = batch->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
+
while (e) {
gn = e->node;
@@ -3341,7 +3379,7 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren
}
QSGMaterialShader::RenderState renderState = state(QSGMaterialShader::RenderState::DirtyStates(int(dirty)));
- updateMaterialDynamicData(sms, renderState, material, batch, e, ubufOffset, ubufSize);
+ updateMaterialDynamicData(sms, renderState, material, batch, e, ubufOffset, ubufSize, directUpdatePtr);
#ifndef QT_NO_DEBUG
if (qsg_test_and_clear_material_failure()) {
@@ -3393,6 +3431,9 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren
e = e->nextInBatch;
}
+ if (directUpdatePtr)
+ batch->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
+
if (pendingGStatePop)
m_gstate = m_gstateStack.pop();
@@ -3802,7 +3843,10 @@ void Renderer::beginRenderPass(RenderPassContext *)
// we have no choice but to set the flag always
// (thus triggering using secondary command
// buffers with Vulkan)
- QRhiCommandBuffer::ExternalContent);
+ QRhiCommandBuffer::ExternalContent
+ // We do not use GPU compute at all at the moment, this means we can
+ // get a small performance gain with OpenGL by declaring this.
+ | QRhiCommandBuffer::DoNotTrackResourcesForCompute);
if (m_renderPassRecordingCallbacks.start)
m_renderPassRecordingCallbacks.start(m_renderPassRecordingCallbacks.userData);
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index 9a024804a7..c0301d1106 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -798,7 +798,8 @@ private:
bool ensurePipelineState(Element *e, const ShaderManager::Shader *sms, bool depthPostPass = false);
QRhiTexture *dummyTexture();
void updateMaterialDynamicData(ShaderManager::Shader *sms, QSGMaterialShader::RenderState &renderState,
- QSGMaterial *material, const Batch *batch, Element *e, int ubufOffset, int ubufRegionSize);
+ QSGMaterial *material, const Batch *batch, Element *e, int ubufOffset, int ubufRegionSize,
+ char *directUpdatePtr);
void updateMaterialStaticData(ShaderManager::Shader *sms, QSGMaterialShader::RenderState &renderState,
QSGMaterial *material, Batch *batch, bool *gstateChanged);
void checkLineWidth(QSGGeometry *g);
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index a9a12a720a..ba85eaf1ef 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -166,7 +166,12 @@ void QSGDistanceFieldGlyphCache::update()
distanceFields.reserve(pendingGlyphsSize);
for (int i = 0; i < pendingGlyphsSize; ++i) {
GlyphData &gd = glyphData(m_pendingGlyphs.at(i));
- distanceFields.append(QDistanceField(gd.path,
+
+ QSize size = QSize(qCeil(gd.texCoord.width + gd.texCoord.xMargin * 2),
+ qCeil(gd.texCoord.height + gd.texCoord.yMargin * 2));
+
+ distanceFields.append(QDistanceField(size,
+ gd.path,
m_pendingGlyphs.at(i),
m_doubleGlyphResolution));
gd.path = QPainterPath(); // no longer needed, so release memory used by the painter path
diff --git a/src/quick/scenegraph/qsgrhishadereffectnode.cpp b/src/quick/scenegraph/qsgrhishadereffectnode.cpp
index 9f634067d5..f1db5804e6 100644
--- a/src/quick/scenegraph/qsgrhishadereffectnode.cpp
+++ b/src/quick/scenegraph/qsgrhishadereffectnode.cpp
@@ -188,7 +188,7 @@ struct QSGRhiShaderMaterialTypeCache
QSGMaterialType *type;
};
QHash<Key, MaterialType> m_types;
- QVector<QSGMaterialType *> m_graveyard;
+ QHash<Key, QSGMaterialType *> m_graveyard;
};
size_t qHash(const QSGRhiShaderMaterialTypeCache::Key &key, size_t seed = 0)
@@ -208,6 +208,14 @@ QSGMaterialType *QSGRhiShaderMaterialTypeCache::ref(const QShader &vs, const QSh
return it->type;
}
+ auto reuseIt = m_graveyard.constFind(k);
+ if (reuseIt != m_graveyard.cend()) {
+ QSGMaterialType *t = reuseIt.value();
+ m_types.insert(k, { 1, t });
+ m_graveyard.erase(reuseIt);
+ return t;
+ }
+
QSGMaterialType *t = new QSGMaterialType;
m_types.insert(k, { 1, t });
return t;
@@ -220,7 +228,7 @@ void QSGRhiShaderMaterialTypeCache::unref(const QShader &vs, const QShader &fs)
auto it = m_types.find(k);
if (it != m_types.end()) {
if (!--it->ref) {
- m_graveyard.append(it->type);
+ m_graveyard.insert(k, it->type);
m_types.erase(it);
}
}
diff --git a/src/quick/scenegraph/util/qsgrhiatlastexture.cpp b/src/quick/scenegraph/util/qsgrhiatlastexture.cpp
index 246335ef69..cdb8509dd2 100644
--- a/src/quick/scenegraph/util/qsgrhiatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgrhiatlastexture.cpp
@@ -160,9 +160,20 @@ void AtlasBase::remove(TextureBase *t)
Atlas::Atlas(QSGDefaultRenderContext *rc, const QSize &size)
: AtlasBase(rc, size)
{
- // use RGBA texture internally as that is the only one guaranteed to be always supported
m_format = QRhiTexture::RGBA8;
+ // Mirror QSGPlainTexture by playing nice with ARGB32[_Pre], because due to
+ // legacy that's what most images come in, not the byte-ordered
+ // RGBA8888[_Pre]. (i.e. with this the behavior matches 5.15) However,
+ // QSGPlainTexture can make a separate decision for each image (texture),
+ // the atlas cannot, so the downside is that now images that come in the
+ // modern byte-ordered formats need a conversion. So perhaps reconsider this
+ // at some point in the future.
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ if (rc->rhi()->isTextureFormatSupported(QRhiTexture::BGRA8))
+ m_format = QRhiTexture::BGRA8;
+#endif
+
m_debug_overlay = qt_sg_envInt("QSG_ATLAS_OVERLAY", 0);
// images smaller than this will retain their QImage.
@@ -211,8 +222,12 @@ void Atlas::enqueueTextureUpload(TextureBase *t, QRhiResourceUpdateBatch *resour
if (image.isNull())
return;
- if (image.format() != QImage::Format_RGBA8888_Premultiplied)
+ if (m_format == QRhiTexture::BGRA8) {
+ if (image.format() != QImage::Format_RGB32 && image.format() != QImage::Format_ARGB32_Premultiplied)
+ image = std::move(image).convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ } else if (image.format() != QImage::Format_RGBA8888_Premultiplied) {
image = std::move(image).convertToFormat(QImage::Format_RGBA8888_Premultiplied);
+ }
if (m_debug_overlay) {
QPainter p(&image);