diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2023-08-28 10:43:53 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2023-09-04 11:46:13 +0200 |
commit | 9505305c403423f58e70471aaf55994bb734a0bd (patch) | |
tree | ff527f943235082d02335bf5d6dce6da3f3d5d36 /src/gui/painting | |
parent | 961620824ca0ae764b3c6ce98b16ecce951168c8 (diff) |
Use linear filtering again when QT_WIDGETS_HIGHDPI_DOWNSCALE
In ec27b99c2a16994127f77d76eb1fb466c390aee9 the filtering mode is
changed from Linear to Nearest since users encountered obscure cases,
in particular when multisampling with large sample counts got enabled,
where the different filtering mode becomes noticeable. (Qt 5 and Qt 6
up until 6.4 uses Nearest, whereas the OpenGL -> QRhi migration
introduced using Linear in 6.4)
Meanwhile, the as of now undocumented high DPI downscaling feature
got introduced, and that prefers linear filtering. (since that's
definitely not a 1:1 mapping when it comes to texture size and the
on-screen quad) To reconcile the differences, add support for both
kind of samplers, and choose based on the sizes.
This should have no effect when not running with the env.var.
QT_WIDGETS_RHI=1 QT_WIDGETS_HIGHDPI_DOWNSCALE=1 set, but should
restore the pre-6.5.2 look when they are set.
Pick-to: 6.6 6.5
Fixes: QTBUG-115461
Change-Id: I42eb8526cb7f74236b5550e26c4570771d2fbfb4
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
Diffstat (limited to 'src/gui/painting')
-rw-r--r-- | src/gui/painting/qbackingstoredefaultcompositor.cpp | 71 | ||||
-rw-r--r-- | src/gui/painting/qbackingstoredefaultcompositor_p.h | 21 |
2 files changed, 63 insertions, 29 deletions
diff --git a/src/gui/painting/qbackingstoredefaultcompositor.cpp b/src/gui/painting/qbackingstoredefaultcompositor.cpp index d5973d66af..03b169aa3d 100644 --- a/src/gui/painting/qbackingstoredefaultcompositor.cpp +++ b/src/gui/painting/qbackingstoredefaultcompositor.cpp @@ -24,8 +24,10 @@ void QBackingStoreDefaultCompositor::reset() m_psBlend = nullptr; delete m_psPremulBlend; m_psPremulBlend = nullptr; - delete m_sampler; - m_sampler = nullptr; + delete m_samplerNearest; + m_samplerNearest = nullptr; + delete m_samplerLinear; + m_samplerLinear = nullptr; delete m_vbuf; m_vbuf = nullptr; delete m_texture; @@ -347,7 +349,7 @@ QBackingStoreDefaultCompositor::PerQuadData QBackingStoreDefaultCompositor::crea d.srb = m_rhi->newShaderResourceBindings(); d.srb->setBindings({ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf, 0, UBUF_SIZE), - QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture, m_sampler) + QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture, m_samplerNearest) }); if (!d.srb->create()) qWarning("QBackingStoreDefaultCompositor: Failed to create srb"); @@ -357,7 +359,7 @@ QBackingStoreDefaultCompositor::PerQuadData QBackingStoreDefaultCompositor::crea d.srbExtra = m_rhi->newShaderResourceBindings(); d.srbExtra->setBindings({ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf, 0, UBUF_SIZE), - QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, textureExtra, m_sampler) + QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, textureExtra, m_samplerNearest) }); if (!d.srbExtra->create()) qWarning("QBackingStoreDefaultCompositor: Failed to create srb"); @@ -368,27 +370,31 @@ QBackingStoreDefaultCompositor::PerQuadData QBackingStoreDefaultCompositor::crea return d; } -void QBackingStoreDefaultCompositor::updatePerQuadData(PerQuadData *d, QRhiTexture *texture, QRhiTexture *textureExtra) +void QBackingStoreDefaultCompositor::updatePerQuadData(PerQuadData *d, QRhiTexture *texture, QRhiTexture *textureExtra, + UpdateQuadDataOptions options) { // This whole check-if-texture-ptr-is-different is needed because there is // nothing saying a QPlatformTextureList cannot return a different // QRhiTexture* from the same index in a subsequent flush. - if (d->lastUsedTexture == texture || !d->srb) + const QRhiSampler::Filter filter = options.testFlag(NeedsLinearFiltering) ? QRhiSampler::Linear : QRhiSampler::Nearest; + if ((d->lastUsedTexture == texture && d->lastUsedFilter == filter) || !d->srb) return; + QRhiSampler *sampler = filter == QRhiSampler::Linear ? m_samplerLinear : m_samplerNearest; d->srb->setBindings({ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d->ubuf, 0, UBUF_SIZE), - QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture, m_sampler) + QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture, sampler) }); d->srb->updateResources(QRhiShaderResourceBindings::BindingsAreSorted); d->lastUsedTexture = texture; + d->lastUsedFilter = filter; if (textureExtra) { d->srbExtra->setBindings({ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d->ubuf, 0, UBUF_SIZE), - QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, textureExtra, m_sampler) + QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, textureExtra, sampler) }); d->srbExtra->updateResources(QRhiShaderResourceBindings::BindingsAreSorted); @@ -397,13 +403,14 @@ void QBackingStoreDefaultCompositor::updatePerQuadData(PerQuadData *d, QRhiTextu } void QBackingStoreDefaultCompositor::updateUniforms(PerQuadData *d, QRhiResourceUpdateBatch *resourceUpdates, - const QMatrix4x4 &target, const QMatrix3x3 &source, UpdateUniformOption option) + const QMatrix4x4 &target, const QMatrix3x3 &source, + UpdateUniformOptions options) { resourceUpdates->updateDynamicBuffer(d->ubuf, 0, 64, target.constData()); updateMatrix3x3(resourceUpdates, d->ubuf, source); float opacity = 1.0f; resourceUpdates->updateDynamicBuffer(d->ubuf, 112, 4, &opacity); - qint32 textureSwizzle = static_cast<qint32>(option); + qint32 textureSwizzle = options; resourceUpdates->updateDynamicBuffer(d->ubuf, 116, 4, &textureSwizzle); } @@ -426,11 +433,18 @@ void QBackingStoreDefaultCompositor::ensureResources(QRhiResourceUpdateBatch *re qWarning("QBackingStoreDefaultCompositor: Failed to create vertex buffer"); } - if (!m_sampler) { - m_sampler = m_rhi->newSampler(QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None, - QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge); - if (!m_sampler->create()) - qWarning("QBackingStoreDefaultCompositor: Failed to create sampler"); + if (!m_samplerNearest) { + m_samplerNearest = m_rhi->newSampler(QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None, + QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge); + if (!m_samplerNearest->create()) + qWarning("QBackingStoreDefaultCompositor: Failed to create sampler (Nearest filtering)"); + } + + if (!m_samplerLinear) { + m_samplerLinear = m_rhi->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None, + QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge); + if (!m_samplerLinear->create()) + qWarning("QBackingStoreDefaultCompositor: Failed to create sampler (Linear filtering)"); } if (!m_widgetQuadData.isValid()) @@ -513,10 +527,13 @@ QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatfo ensureResources(resourceUpdates, swapchain->renderPassDescriptor()); + UpdateUniformOptions uniformOptions; #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - const UpdateUniformOption uniformOption = (flags & QPlatformBackingStore::TextureSwizzle) != 0? NeedsRedBlueSwap : NoOption; + if (flags & QPlatformBackingStore::TextureSwizzle) + uniformOptions |= NeedsRedBlueSwap; #else - const UpdateUniformOption uniformOption = (flags & QPlatformBackingStore::TextureSwizzle) != 0? NeedsAlphaRotate : NoOption; + if (flags & QPlatformBackingStore::TextureSwizzle) + uniformOptions |= NeedsAlphaRotate; #endif const bool premultiplied = (flags & QPlatformBackingStore::TexturePremultiplied) != 0; SourceTransformOrigin origin = SourceTransformOrigin::TopLeft; @@ -539,7 +556,17 @@ QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatfo QMatrix4x4 target; // identity if (invertTargetY) target.data()[5] = -1.0f; - updateUniforms(&m_widgetQuadData, resourceUpdates, target, source, uniformOption); + updateUniforms(&m_widgetQuadData, resourceUpdates, target, source, uniformOptions); + + // If sourceWindowRect is larger than deviceWindowRect, we are doing + // high DPI downscaling. In that case Linear filtering is a must, + // whereas for the 1:1 case Nearest must be used for Qt 5 visual + // compatibility. + if (sourceWindowRect.width() > deviceWindowRect.width() + && sourceWindowRect.height() > deviceWindowRect.height()) + { + updatePerQuadData(&m_widgetQuadData, m_texture, nullptr, NeedsLinearFiltering); + } } const int textureWidgetCount = textures->count(); @@ -565,13 +592,11 @@ QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatfo QRhiTexture *t = textures->texture(i); QRhiTexture *tExtra = textures->textureExtra(i); if (t) { - if (!m_textureQuadData[i].isValid()) { + if (!m_textureQuadData[i].isValid()) m_textureQuadData[i] = createPerQuadData(t, tExtra); - } - else { + else updatePerQuadData(&m_textureQuadData[i], t, tExtra); - } - updateUniforms(&m_textureQuadData[i], resourceUpdates, target, source, NoOption); + updateUniforms(&m_textureQuadData[i], resourceUpdates, target, source); } else { m_textureQuadData[i].reset(); } diff --git a/src/gui/painting/qbackingstoredefaultcompositor_p.h b/src/gui/painting/qbackingstoredefaultcompositor_p.h index 0e68ac090c..5bc04290d5 100644 --- a/src/gui/painting/qbackingstoredefaultcompositor_p.h +++ b/src/gui/painting/qbackingstoredefaultcompositor_p.h @@ -45,10 +45,14 @@ public: private: enum UpdateUniformOption { - NoOption = 0x00, - NeedsRedBlueSwap = 0x01, - NeedsAlphaRotate = 0x02, + NeedsRedBlueSwap = 1 << 0, + NeedsAlphaRotate = 1 << 1 }; + Q_DECLARE_FLAGS(UpdateUniformOptions, UpdateUniformOption) + enum UpdateQuadDataOption { + NeedsLinearFiltering = 1 << 0 + }; + Q_DECLARE_FLAGS(UpdateQuadDataOptions, UpdateQuadDataOption) void ensureResources(QRhiResourceUpdateBatch *resourceUpdates, QRhiRenderPassDescriptor *rpDesc); QRhiTexture *toTexture(const QImage &image, @@ -61,7 +65,8 @@ private: mutable QRhiTexture *m_texture = nullptr; QRhiBuffer *m_vbuf = nullptr; - QRhiSampler *m_sampler = nullptr; + QRhiSampler *m_samplerNearest = nullptr; + QRhiSampler *m_samplerLinear = nullptr; QRhiGraphicsPipeline *m_psNoBlend = nullptr; QRhiGraphicsPipeline *m_psBlend = nullptr; QRhiGraphicsPipeline *m_psPremulBlend = nullptr; @@ -73,6 +78,7 @@ private: QRhiShaderResourceBindings *srbExtra = nullptr; // may be null (used for stereo) QRhiTexture *lastUsedTexture = nullptr; QRhiTexture *lastUsedTextureExtra = nullptr; // may be null (used for stereo) + QRhiSampler::Filter lastUsedFilter = QRhiSampler::None; bool isValid() const { return ubuf && srb; } void reset() { delete ubuf; @@ -85,15 +91,18 @@ private: } lastUsedTexture = nullptr; lastUsedTextureExtra = nullptr; + lastUsedFilter = QRhiSampler::None; } }; PerQuadData m_widgetQuadData; QVarLengthArray<PerQuadData, 8> m_textureQuadData; PerQuadData createPerQuadData(QRhiTexture *texture, QRhiTexture *textureExtra = nullptr); - void updatePerQuadData(PerQuadData *d, QRhiTexture *texture, QRhiTexture *textureExtra = nullptr); + void updatePerQuadData(PerQuadData *d, QRhiTexture *texture, QRhiTexture *textureExtra = nullptr, + UpdateQuadDataOptions options = {}); void updateUniforms(PerQuadData *d, QRhiResourceUpdateBatch *resourceUpdates, - const QMatrix4x4 &target, const QMatrix3x3 &source, UpdateUniformOption option); + const QMatrix4x4 &target, const QMatrix3x3 &source, + UpdateUniformOptions options = {}); }; QT_END_NAMESPACE |