summaryrefslogtreecommitdiffstats
path: root/src/gui/painting
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2023-08-28 10:43:53 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2023-09-04 11:46:13 +0200
commit9505305c403423f58e70471aaf55994bb734a0bd (patch)
treeff527f943235082d02335bf5d6dce6da3f3d5d36 /src/gui/painting
parent961620824ca0ae764b3c6ce98b16ecce951168c8 (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.cpp71
-rw-r--r--src/gui/painting/qbackingstoredefaultcompositor_p.h21
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