summaryrefslogtreecommitdiffstats
path: root/src/gui/painting
diff options
context:
space:
mode:
authorKristoffer Skau <kristoffer.skau@qt.io>2022-10-27 15:38:53 +0200
committerKristoffer Skau <kristoffer.skau@qt.io>2022-11-28 19:12:27 +0100
commitee2dbcada81f5220a05414d7bf9d5eeebdda8972 (patch)
tree2bca1fc0c3569a98f26a0717d9e555a9b88f2364 /src/gui/painting
parent8155bd54261688f333b2d68e2d76f0fc076a0fb4 (diff)
Add support for stereoscopic content in QOpenGLWidget
Need to add the plumbing necessary to support two textures in QOpenGLWidget and use these in the backing store. The changes required on the RHI level is already done in an earlier patch. Then paintGL() needs to be called twice, once for each buffer. Also add overloads for the other functions of QOopenGLWidget where it makes sense to query for left or right buffer. Then finally create an example. [ChangeLog][Widgets][QOpenGLWidget] Added support for stereoscopic rendering. Fixes: QTBUG-64587 Change-Id: I5a5c53506dcf8a56442097290dceb7eb730d50ce Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'src/gui/painting')
-rw-r--r--src/gui/painting/qbackingstoredefaultcompositor.cpp128
-rw-r--r--src/gui/painting/qbackingstoredefaultcompositor_p.h11
-rw-r--r--src/gui/painting/qplatformbackingstore.cpp23
-rw-r--r--src/gui/painting/qplatformbackingstore.h4
4 files changed, 125 insertions, 41 deletions
diff --git a/src/gui/painting/qbackingstoredefaultcompositor.cpp b/src/gui/painting/qbackingstoredefaultcompositor.cpp
index 076ae3e984..1dd116ac81 100644
--- a/src/gui/painting/qbackingstoredefaultcompositor.cpp
+++ b/src/gui/painting/qbackingstoredefaultcompositor.cpp
@@ -335,7 +335,7 @@ static QRhiGraphicsPipeline *createGraphicsPipeline(QRhi *rhi,
static const int UBUF_SIZE = 120;
-QBackingStoreDefaultCompositor::PerQuadData QBackingStoreDefaultCompositor::createPerQuadData(QRhiTexture *texture)
+QBackingStoreDefaultCompositor::PerQuadData QBackingStoreDefaultCompositor::createPerQuadData(QRhiTexture *texture, QRhiTexture *textureExtra)
{
PerQuadData d;
@@ -350,13 +350,24 @@ QBackingStoreDefaultCompositor::PerQuadData QBackingStoreDefaultCompositor::crea
});
if (!d.srb->create())
qWarning("QBackingStoreDefaultCompositor: Failed to create srb");
-
d.lastUsedTexture = texture;
+ if (textureExtra) {
+ 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)
+ });
+ if (!d.srbExtra->create())
+ qWarning("QBackingStoreDefaultCompositor: Failed to create srb");
+ }
+
+ d.lastUsedTextureExtra = textureExtra;
+
return d;
}
-void QBackingStoreDefaultCompositor::updatePerQuadData(PerQuadData *d, QRhiTexture *texture)
+void QBackingStoreDefaultCompositor::updatePerQuadData(PerQuadData *d, QRhiTexture *texture, QRhiTexture *textureExtra)
{
// This whole check-if-texture-ptr-is-different is needed because there is
// nothing saying a QPlatformTextureList cannot return a different
@@ -371,8 +382,17 @@ void QBackingStoreDefaultCompositor::updatePerQuadData(PerQuadData *d, QRhiTextu
});
d->srb->updateResources(QRhiShaderResourceBindings::BindingsAreSorted);
-
d->lastUsedTexture = texture;
+
+ 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)
+ });
+
+ d->srbExtra->updateResources(QRhiShaderResourceBindings::BindingsAreSorted);
+ d->lastUsedTextureExtra = textureExtra;
+ }
}
void QBackingStoreDefaultCompositor::updateUniforms(PerQuadData *d, QRhiResourceUpdateBatch *resourceUpdates,
@@ -534,11 +554,14 @@ QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatfo
continue;
}
QRhiTexture *t = textures->texture(i);
+ QRhiTexture *tExtra = textures->textureExtra(i);
if (t) {
- if (!m_textureQuadData[i].isValid())
- m_textureQuadData[i] = createPerQuadData(t);
- else
- updatePerQuadData(&m_textureQuadData[i], t);
+ if (!m_textureQuadData[i].isValid()) {
+ m_textureQuadData[i] = createPerQuadData(t, tExtra);
+ }
+ else {
+ updatePerQuadData(&m_textureQuadData[i], t, tExtra);
+ }
updateUniforms(&m_textureQuadData[i], resourceUpdates, target, source, NoOption);
} else {
m_textureQuadData[i].reset();
@@ -549,47 +572,74 @@ QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatfo
QRhiCommandBuffer *cb = swapchain->currentFrameCommandBuffer();
const QSize outputSizeInPixels = swapchain->currentPixelSize();
QColor clearColor = translucentBackground ? Qt::transparent : Qt::black;
- cb->beginPass(swapchain->currentFrameRenderTarget(), clearColor, { 1.0f, 0 }, resourceUpdates);
- cb->setGraphicsPipeline(m_psNoBlend);
- cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
- QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf, 0);
- cb->setVertexInput(0, 1, &vbufBinding);
+ cb->resourceUpdate(resourceUpdates);
- // Textures for renderToTexture widgets.
- for (int i = 0; i < textureWidgetCount; ++i) {
- if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
- if (m_textureQuadData[i].isValid()) {
- cb->setShaderResources(m_textureQuadData[i].srb);
- cb->draw(6);
+ auto render = [&](std::optional<QRhiSwapChain::StereoTargetBuffer> buffer = std::nullopt) {
+ QRhiRenderTarget* target = nullptr;
+ if (buffer.has_value())
+ target = swapchain->currentFrameRenderTarget(buffer.value());
+ else
+ target = swapchain->currentFrameRenderTarget();
+
+ cb->beginPass(target, clearColor, { 1.0f, 0 });
+
+ cb->setGraphicsPipeline(m_psNoBlend);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding);
+
+ // Textures for renderToTexture widgets.
+ for (int i = 0; i < textureWidgetCount; ++i) {
+ if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
+ if (m_textureQuadData[i].isValid()) {
+
+ QRhiShaderResourceBindings* srb = m_textureQuadData[i].srb;
+ if (buffer == QRhiSwapChain::RightBuffer && m_textureQuadData[i].srbExtra)
+ srb = m_textureQuadData[i].srbExtra;
+
+ cb->setShaderResources(srb);
+ cb->draw(6);
+ }
}
}
- }
- cb->setGraphicsPipeline(premultiplied ? m_psPremulBlend : m_psBlend);
+ cb->setGraphicsPipeline(premultiplied ? m_psPremulBlend : m_psBlend);
- // Backingstore texture with the normal widgets.
- if (m_texture) {
- cb->setShaderResources(m_widgetQuadData.srb);
- cb->draw(6);
- }
+ // Backingstore texture with the normal widgets.
+ if (m_texture) {
+ cb->setShaderResources(m_widgetQuadData.srb);
+ cb->draw(6);
+ }
- // Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set.
- for (int i = 0; i < textureWidgetCount; ++i) {
- const QPlatformTextureList::Flags flags = textures->flags(i);
- if (flags.testFlag(QPlatformTextureList::StacksOnTop)) {
- if (m_textureQuadData[i].isValid()) {
- if (flags.testFlag(QPlatformTextureList::NeedsPremultipliedAlphaBlending))
- cb->setGraphicsPipeline(m_psPremulBlend);
- else
- cb->setGraphicsPipeline(m_psBlend);
- cb->setShaderResources(m_textureQuadData[i].srb);
- cb->draw(6);
+ // Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set.
+ for (int i = 0; i < textureWidgetCount; ++i) {
+ const QPlatformTextureList::Flags flags = textures->flags(i);
+ if (flags.testFlag(QPlatformTextureList::StacksOnTop)) {
+ if (m_textureQuadData[i].isValid()) {
+ if (flags.testFlag(QPlatformTextureList::NeedsPremultipliedAlphaBlending))
+ cb->setGraphicsPipeline(m_psPremulBlend);
+ else
+ cb->setGraphicsPipeline(m_psBlend);
+
+ QRhiShaderResourceBindings* srb = m_textureQuadData[i].srb;
+ if (buffer == QRhiSwapChain::RightBuffer && m_textureQuadData[i].srbExtra)
+ srb = m_textureQuadData[i].srbExtra;
+
+ cb->setShaderResources(srb);
+ cb->draw(6);
+ }
}
}
- }
- cb->endPass();
+ cb->endPass();
+ };
+
+ if (swapchain->window()->format().stereo()) {
+ render(QRhiSwapChain::LeftBuffer);
+ render(QRhiSwapChain::RightBuffer);
+ } else
+ render();
rhi->endFrame(swapchain);
diff --git a/src/gui/painting/qbackingstoredefaultcompositor_p.h b/src/gui/painting/qbackingstoredefaultcompositor_p.h
index 75080f6994..d69c17f98f 100644
--- a/src/gui/painting/qbackingstoredefaultcompositor_p.h
+++ b/src/gui/painting/qbackingstoredefaultcompositor_p.h
@@ -70,21 +70,28 @@ private:
QRhiBuffer *ubuf = nullptr;
// All srbs are layout-compatible.
QRhiShaderResourceBindings *srb = nullptr;
+ QRhiShaderResourceBindings *srbExtra = nullptr; // may be null (used for stereo)
QRhiTexture *lastUsedTexture = nullptr;
+ QRhiTexture *lastUsedTextureExtra = nullptr; // may be null (used for stereo)
bool isValid() const { return ubuf && srb; }
void reset() {
delete ubuf;
ubuf = nullptr;
delete srb;
srb = nullptr;
+ if (srbExtra) {
+ delete srbExtra;
+ srbExtra = nullptr;
+ }
lastUsedTexture = nullptr;
+ lastUsedTextureExtra = nullptr;
}
};
PerQuadData m_widgetQuadData;
QVarLengthArray<PerQuadData, 8> m_textureQuadData;
- PerQuadData createPerQuadData(QRhiTexture *texture);
- void updatePerQuadData(PerQuadData *d, QRhiTexture *texture);
+ PerQuadData createPerQuadData(QRhiTexture *texture, QRhiTexture *textureExtra = nullptr);
+ void updatePerQuadData(PerQuadData *d, QRhiTexture *texture, QRhiTexture *textureExtra = nullptr);
void updateUniforms(PerQuadData *d, QRhiResourceUpdateBatch *resourceUpdates,
const QMatrix4x4 &target, const QMatrix3x3 &source, UpdateUniformOption option);
};
diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp
index 8a23003065..82e7778b86 100644
--- a/src/gui/painting/qplatformbackingstore.cpp
+++ b/src/gui/painting/qplatformbackingstore.cpp
@@ -37,6 +37,7 @@ struct QBackingstoreTextureInfo
{
void *source; // may be null
QRhiTexture *texture;
+ QRhiTexture *textureExtra;
QRect rect;
QRect clipRect;
QPlatformTextureList::Flags flags;
@@ -77,6 +78,12 @@ QRhiTexture *QPlatformTextureList::texture(int index) const
return d->textures.at(index).texture;
}
+QRhiTexture *QPlatformTextureList::textureExtra(int index) const
+{
+ Q_D(const QPlatformTextureList);
+ return d->textures.at(index).textureExtra;
+}
+
void *QPlatformTextureList::source(int index)
{
Q_D(const QPlatformTextureList);
@@ -123,6 +130,22 @@ void QPlatformTextureList::appendTexture(void *source, QRhiTexture *texture, con
QBackingstoreTextureInfo bi;
bi.source = source;
bi.texture = texture;
+ bi.textureExtra = nullptr;
+ bi.rect = geometry;
+ bi.clipRect = clipRect;
+ bi.flags = flags;
+ d->textures.append(bi);
+}
+
+void QPlatformTextureList::appendTexture(void *source, QRhiTexture *textureLeft, QRhiTexture *textureRight, const QRect &geometry,
+ const QRect &clipRect, Flags flags)
+{
+ Q_D(QPlatformTextureList);
+
+ QBackingstoreTextureInfo bi;
+ bi.source = source;
+ bi.texture = textureLeft;
+ bi.textureExtra = textureRight;
bi.rect = geometry;
bi.clipRect = clipRect;
bi.flags = flags;
diff --git a/src/gui/painting/qplatformbackingstore.h b/src/gui/painting/qplatformbackingstore.h
index c6b66e57ef..40453574aa 100644
--- a/src/gui/painting/qplatformbackingstore.h
+++ b/src/gui/painting/qplatformbackingstore.h
@@ -103,6 +103,7 @@ public:
int count() const;
bool isEmpty() const { return count() == 0; }
QRhiTexture *texture(int index) const;
+ QRhiTexture *textureExtra(int index) const;
QRect geometry(int index) const;
QRect clipRect(int index) const;
void *source(int index);
@@ -112,6 +113,9 @@ public:
void appendTexture(void *source, QRhiTexture *texture, const QRect &geometry,
const QRect &clipRect = QRect(), Flags flags = { });
+
+ void appendTexture(void *source, QRhiTexture *textureLeft, QRhiTexture *textureRight, const QRect &geometry,
+ const QRect &clipRect = QRect(), Flags flags = { });
void clear();
Q_SIGNALS: