diff options
Diffstat (limited to 'src/gui/painting/qbackingstoredefaultcompositor.cpp')
-rw-r--r-- | src/gui/painting/qbackingstoredefaultcompositor.cpp | 288 |
1 files changed, 184 insertions, 104 deletions
diff --git a/src/gui/painting/qbackingstoredefaultcompositor.cpp b/src/gui/painting/qbackingstoredefaultcompositor.cpp index c14efdd42e..c1452ca768 100644 --- a/src/gui/painting/qbackingstoredefaultcompositor.cpp +++ b/src/gui/painting/qbackingstoredefaultcompositor.cpp @@ -17,18 +17,14 @@ QBackingStoreDefaultCompositor::~QBackingStoreDefaultCompositor() void QBackingStoreDefaultCompositor::reset() { - delete m_psNoBlend; - m_psNoBlend = nullptr; - delete m_psBlend; - m_psBlend = nullptr; - delete m_psPremulBlend; - m_psPremulBlend = nullptr; - delete m_sampler; - m_sampler = nullptr; - delete m_vbuf; - m_vbuf = nullptr; - delete m_texture; - m_texture = nullptr; + m_rhi = nullptr; + m_psNoBlend.reset(); + m_psBlend.reset(); + m_psPremulBlend.reset(); + m_samplerNearest.reset(); + m_samplerLinear.reset(); + m_vbuf.reset(); + m_texture.reset(); m_widgetQuadData.reset(); for (PerQuadData &d : m_textureQuadData) d.reset(); @@ -71,9 +67,7 @@ QRhiTexture *QBackingStoreDefaultCompositor::toTexture(const QImage &sourceImage Q_FALLTHROUGH(); case QImage::Format_RGB32: case QImage::Format_ARGB32: -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN *flags |= QPlatformBackingStore::TextureSwizzle; -#endif break; case QImage::Format_RGBA8888_Premultiplied: *flags |= QPlatformBackingStore::TexturePremultiplied; @@ -101,7 +95,7 @@ QRhiTexture *QBackingStoreDefaultCompositor::toTexture(const QImage &sourceImage const bool resized = !m_texture || m_texture->pixelSize() != image.size(); if (dirtyRegion.isEmpty() && !resized) - return m_texture; + return m_texture.get(); if (needsConversion) image = image.convertToFormat(QImage::Format_RGBA8888); @@ -110,11 +104,11 @@ QRhiTexture *QBackingStoreDefaultCompositor::toTexture(const QImage &sourceImage if (resized) { if (!m_texture) - m_texture = rhi->newTexture(QRhiTexture::RGBA8, image.size()); + m_texture.reset(rhi->newTexture(QRhiTexture::RGBA8, image.size())); else m_texture->setPixelSize(image.size()); m_texture->create(); - resourceUpdates->uploadTexture(m_texture, image); + resourceUpdates->uploadTexture(m_texture.get(), image); } else { QRect imageRect = image.rect(); QRect rect = dirtyRegion.boundingRect() & imageRect; @@ -123,35 +117,34 @@ QRhiTexture *QBackingStoreDefaultCompositor::toTexture(const QImage &sourceImage subresDesc.setSourceSize(rect.size()); subresDesc.setDestinationTopLeft(rect.topLeft()); QRhiTextureUploadDescription uploadDesc(QRhiTextureUploadEntry(0, 0, subresDesc)); - resourceUpdates->uploadTexture(m_texture, uploadDesc); + resourceUpdates->uploadTexture(m_texture.get(), uploadDesc); } - return m_texture; + return m_texture.get(); } -static inline QRect deviceRect(const QRect &rect, QWindow *window) +static inline QRect scaledRect(const QRect &rect, qreal factor) { - return QRect(rect.topLeft() * window->devicePixelRatio(), - rect.size() * window->devicePixelRatio()); + return QRect(rect.topLeft() * factor, rect.size() * factor); } -static inline QPoint deviceOffset(const QPoint &pt, QWindow *window) +static inline QPoint scaledOffset(const QPoint &pt, qreal factor) { - return pt * window->devicePixelRatio(); + return pt * factor; } -static QRegion deviceRegion(const QRegion ®ion, QWindow *window, const QPoint &offset) +static QRegion scaledRegion(const QRegion ®ion, qreal factor, const QPoint &offset) { - if (offset.isNull() && window->devicePixelRatio() <= 1) + if (offset.isNull() && factor <= 1) return region; QVarLengthArray<QRect, 4> rects; rects.reserve(region.rectCount()); for (const QRect &rect : region) - rects.append(deviceRect(rect.translated(offset), window)); + rects.append(scaledRect(rect.translated(offset), factor)); QRegion deviceRegion; - deviceRegion.setRects(rects.constData(), rects.count()); + deviceRegion.setRects(rects.constData(), rects.size()); return deviceRegion; } @@ -173,7 +166,7 @@ static QMatrix4x4 targetTransform(const QRectF &target, const QRect &viewport, b matrix(1,3) = y_translate; matrix(0,0) = x_scale; - matrix(1,1) = y_scale; + matrix(1,1) = (invertY ? -1.0 : 1.0) * y_scale; return matrix; } @@ -236,12 +229,12 @@ static bool prepareDrawForRenderToTextureWidget(const QPlatformTextureList *text const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft()); const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height()); - *target = targetTransform(deviceRect(clippedRectInWindow, window), + *target = targetTransform(scaledRect(clippedRectInWindow, window->devicePixelRatio()), deviceWindowRect, invertTargetY); - *source = sourceTransform(deviceRect(srcRect, window), - deviceRect(rectInWindow, window).size(), + *source = sourceTransform(scaledRect(srcRect, window->devicePixelRatio()), + scaledRect(rectInWindow, window->devicePixelRatio()).size(), invertSource ? SourceTransformOrigin::TopLeft : SourceTransformOrigin::BottomLeft); return true; @@ -282,7 +275,7 @@ enum class PipelineBlend { static QRhiGraphicsPipeline *createGraphicsPipeline(QRhi *rhi, QRhiShaderResourceBindings *srb, - QRhiSwapChain *swapchain, + QRhiRenderPassDescriptor *rpDesc, PipelineBlend blend) { QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline(); @@ -326,7 +319,7 @@ static QRhiGraphicsPipeline *createGraphicsPipeline(QRhi *rhi, }); ps->setVertexInputLayout(inputLayout); ps->setShaderResourceBindings(srb); - ps->setRenderPassDescriptor(swapchain->renderPassDescriptor()); + ps->setRenderPassDescriptor(rpDesc); if (!ps->create()) { qWarning("QBackingStoreDefaultCompositor: Failed to build graphics pipeline"); @@ -338,7 +331,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; @@ -349,47 +342,72 @@ 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.get()) }); 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_samplerNearest.get()) + }); + 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, + 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.get() : m_samplerNearest.get(); 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, sampler) + }); + + d->srbExtra->updateResources(QRhiShaderResourceBindings::BindingsAreSorted); + d->lastUsedTextureExtra = textureExtra; + } } void QBackingStoreDefaultCompositor::updateUniforms(PerQuadData *d, QRhiResourceUpdateBatch *resourceUpdates, - const QMatrix4x4 &target, const QMatrix3x3 &source, bool needsRedBlueSwap) + 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 swapRedBlue = needsRedBlueSwap ? 1 : 0; - resourceUpdates->updateDynamicBuffer(d->ubuf, 116, 4, &swapRedBlue); + qint32 textureSwizzle = options; + resourceUpdates->updateDynamicBuffer(d->ubuf, 116, 4, &textureSwizzle); } -void QBackingStoreDefaultCompositor::ensureResources(QRhiSwapChain *swapchain, QRhiResourceUpdateBatch *resourceUpdates) +void QBackingStoreDefaultCompositor::ensureResources(QRhiResourceUpdateBatch *resourceUpdates, QRhiRenderPassDescriptor *rpDesc) { static const float vertexData[] = { -1, -1, 0, 0, 0, @@ -401,41 +419,52 @@ void QBackingStoreDefaultCompositor::ensureResources(QRhiSwapChain *swapchain, Q }; if (!m_vbuf) { - m_vbuf = m_rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData)); + m_vbuf.reset(m_rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData))); if (m_vbuf->create()) - resourceUpdates->uploadStaticBuffer(m_vbuf, vertexData); + resourceUpdates->uploadStaticBuffer(m_vbuf.get(), vertexData); else 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.reset(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.reset(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()) - m_widgetQuadData = createPerQuadData(m_texture); + m_widgetQuadData = createPerQuadData(m_texture.get()); QRhiShaderResourceBindings *srb = m_widgetQuadData.srb; // just for the layout if (!m_psNoBlend) - m_psNoBlend = createGraphicsPipeline(m_rhi, srb, swapchain, PipelineBlend::None); + m_psNoBlend.reset(createGraphicsPipeline(m_rhi, srb, rpDesc, PipelineBlend::None)); if (!m_psBlend) - m_psBlend = createGraphicsPipeline(m_rhi, srb, swapchain, PipelineBlend::Alpha); + m_psBlend.reset(createGraphicsPipeline(m_rhi, srb, rpDesc, PipelineBlend::Alpha)); if (!m_psPremulBlend) - m_psPremulBlend = createGraphicsPipeline(m_rhi, srb, swapchain, PipelineBlend::PremulAlpha); + m_psPremulBlend.reset(createGraphicsPipeline(m_rhi, srb, rpDesc, PipelineBlend::PremulAlpha)); } QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatformBackingStore *backingStore, QRhi *rhi, QRhiSwapChain *swapchain, QWindow *window, + qreal sourceDevicePixelRatio, const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, bool translucentBackground) { + if (!rhi) + return QPlatformBackingStore::FlushFailed; + Q_ASSERT(textures); // may be empty if there are no render-to-texture widgets at all, but null it cannot be if (!m_rhi) { @@ -479,7 +508,7 @@ QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatfo const QImage::Format format = QImage::toImageFormat(graphicsBuffer->format()); const QSize size = graphicsBuffer->size(); QImage wrapperImage(graphicsBuffer->data(), size.width(), size.height(), graphicsBuffer->bytesPerLine(), format); - toTexture(wrapperImage, rhi, resourceUpdates, deviceRegion(region, window, offset), &flags); + toTexture(wrapperImage, rhi, resourceUpdates, scaledRegion(region, sourceDevicePixelRatio, offset), &flags); gotTextureFromGraphicsBuffer = true; graphicsBuffer->unlock(); if (graphicsBuffer->origin() == QPlatformGraphicsBuffer::OriginBottomLeft) @@ -487,34 +516,52 @@ QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatfo } } if (!gotTextureFromGraphicsBuffer) - toTexture(backingStore, rhi, resourceUpdates, deviceRegion(region, window, offset), &flags); + toTexture(backingStore, rhi, resourceUpdates, scaledRegion(region, sourceDevicePixelRatio, offset), &flags); - ensureResources(swapchain, resourceUpdates); + ensureResources(resourceUpdates, swapchain->renderPassDescriptor()); - const bool needsRedBlueSwap = (flags & QPlatformBackingStore::TextureSwizzle) != 0; + UpdateUniformOptions uniformOptions; +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + if (flags & QPlatformBackingStore::TextureSwizzle) + uniformOptions |= NeedsRedBlueSwap; +#else + if (flags & QPlatformBackingStore::TextureSwizzle) + uniformOptions |= NeedsAlphaRotate; +#endif const bool premultiplied = (flags & QPlatformBackingStore::TexturePremultiplied) != 0; SourceTransformOrigin origin = SourceTransformOrigin::TopLeft; if (flags & QPlatformBackingStore::TextureFlip) origin = SourceTransformOrigin::BottomLeft; - const QRect deviceWindowRect = deviceRect(QRect(QPoint(), window->size()), window); - const QPoint deviceWindowOffset = deviceOffset(offset, window); + const qreal dpr = window->devicePixelRatio(); + const QRect deviceWindowRect = scaledRect(QRect(QPoint(), window->size()), dpr); + const QRect sourceWindowRect = scaledRect(QRect(QPoint(), window->size()), sourceDevicePixelRatio); + // 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. + const bool needsLinearSampler = sourceWindowRect.width() > deviceWindowRect.width() + && sourceWindowRect.height() > deviceWindowRect.height(); + + const bool invertTargetY = !rhi->isYUpInNDC(); + const bool invertSource = !rhi->isYUpInFramebuffer(); - const bool invertTargetY = rhi->clipSpaceCorrMatrix().data()[5] < 0.0f; - const bool invertSource = rhi->isYUpInFramebuffer() != rhi->isYUpInNDC(); if (m_texture) { - // The backingstore is for the entire tlw. - // In case of native children offset tells the position relative to the tlw. - const QRect srcRect = toBottomLeftRect(deviceWindowRect.translated(deviceWindowOffset), m_texture->pixelSize().height()); + // The backingstore is for the entire tlw. In case of native children, offset tells the position + // relative to the tlw. The window rect is scaled by the source device pixel ratio to get + // the source rect. + const QPoint sourceWindowOffset = scaledOffset(offset, sourceDevicePixelRatio); + const QRect srcRect = toBottomLeftRect(sourceWindowRect.translated(sourceWindowOffset), m_texture->pixelSize().height()); const QMatrix3x3 source = sourceTransform(srcRect, m_texture->pixelSize(), origin); QMatrix4x4 target; // identity if (invertTargetY) target.data()[5] = -1.0f; - updateUniforms(&m_widgetQuadData, resourceUpdates, target, source, needsRedBlueSwap); + updateUniforms(&m_widgetQuadData, resourceUpdates, target, source, uniformOptions); + if (needsLinearSampler) + updatePerQuadData(&m_widgetQuadData, m_texture.get(), nullptr, NeedsLinearFiltering); } const int textureWidgetCount = textures->count(); - const int oldTextureQuadDataCount = m_textureQuadData.count(); + const int oldTextureQuadDataCount = m_textureQuadData.size(); if (oldTextureQuadDataCount != textureWidgetCount) { for (int i = textureWidgetCount; i < oldTextureQuadDataCount; ++i) m_textureQuadData[i].reset(); @@ -522,21 +569,27 @@ QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatfo } for (int i = 0; i < textureWidgetCount; ++i) { + const bool invertSourceForTextureWidget = textures->flags(i).testFlag(QPlatformTextureList::MirrorVertically) + ? !invertSource : invertSource; QMatrix4x4 target; QMatrix3x3 source; if (!prepareDrawForRenderToTextureWidget(textures, i, window, deviceWindowRect, - offset, invertTargetY, invertSource, &target, &source)) + offset, invertTargetY, invertSourceForTextureWidget, + &target, &source)) { m_textureQuadData[i].reset(); continue; } QRhiTexture *t = textures->texture(i); + QRhiTexture *tExtra = textures->textureExtra(i); if (t) { if (!m_textureQuadData[i].isValid()) - m_textureQuadData[i] = createPerQuadData(t); + m_textureQuadData[i] = createPerQuadData(t, tExtra); else - updatePerQuadData(&m_textureQuadData[i], t); - updateUniforms(&m_textureQuadData[i], resourceUpdates, target, source, false); + updatePerQuadData(&m_textureQuadData[i], t, tExtra); + updateUniforms(&m_textureQuadData[i], resourceUpdates, target, source); + if (needsLinearSampler) + updatePerQuadData(&m_textureQuadData[i], t, tExtra, NeedsLinearFiltering); } else { m_textureQuadData[i].reset(); } @@ -546,47 +599,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.get()); + cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) }); + QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf.get(), 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.get() : m_psBlend.get()); - // 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.get()); + else + cb->setGraphicsPipeline(m_psBlend.get()); + + 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); |