277 QRhiShaderResourceBindings *srb,
278 QRhiRenderPassDescriptor *rpDesc,
281 QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
286 QRhiGraphicsPipeline::TargetBlend blend;
288 blend.srcColor = QRhiGraphicsPipeline::SrcAlpha;
289 blend.dstColor = QRhiGraphicsPipeline::OneMinusSrcAlpha;
290 blend.srcAlpha = QRhiGraphicsPipeline::One;
291 blend.dstAlpha = QRhiGraphicsPipeline::One;
292 ps->setTargetBlends({ blend });
297 QRhiGraphicsPipeline::TargetBlend blend;
299 blend.srcColor = QRhiGraphicsPipeline::One;
300 blend.dstColor = QRhiGraphicsPipeline::OneMinusSrcAlpha;
301 blend.srcAlpha = QRhiGraphicsPipeline::One;
302 blend.dstAlpha = QRhiGraphicsPipeline::One;
303 ps->setTargetBlends({ blend });
310 ps->setShaderStages({
311 { QRhiShaderStage::Vertex, getShader(
":/qt-project.org/gui/painting/shaders/backingstorecompose.vert.qsb"_L1) },
312 { QRhiShaderStage::Fragment, getShader(
":/qt-project.org/gui/painting/shaders/backingstorecompose.frag.qsb"_L1) }
315 inputLayout.setBindings({ { 5 *
sizeof(
float) } });
316 inputLayout.setAttributes({
317 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
318 { 0, 1, QRhiVertexInputAttribute::Float2, quint32(3 *
sizeof(
float)) }
320 ps->setVertexInputLayout(inputLayout);
321 ps->setShaderResourceBindings(srb);
322 ps->setRenderPassDescriptor(rpDesc);
325 qWarning(
"QBackingStoreDefaultCompositor: Failed to build graphics pipeline");
457 QRhiSwapChain *swapchain,
459 qreal sourceDevicePixelRatio,
460 const QRegion ®ion,
461 const QPoint &offset,
462 QPlatformTextureList *textures,
463 bool translucentBackground,
464 qreal sourceTransformFactor)
466 if (!rhi || !swapchain)
467 return QPlatformBackingStore::FlushFailed;
474 if (!sourceTransformFactor)
475 sourceTransformFactor = sourceDevicePixelRatio;
481 }
else if (m_rhi != rhi) {
482 qWarning(
"QBackingStoreDefaultCompositor: the QRhi has changed unexpectedly, this should not happen");
483 return QPlatformBackingStore::FlushFailed;
486 if (!qt_window_private(window)->receivedExpose)
487 return QPlatformBackingStore::FlushSuccess;
489 qCDebug(lcQpaBackingStore) <<
"Composing and flushing" << region <<
"of" << window
490 <<
"at offset" << offset <<
"with" << textures->count() <<
"texture(s) in" << textures
491 <<
"via swapchain" << swapchain;
493 QWindowPrivate::get(window)->lastComposeTime.start();
495 if (swapchain->currentPixelSize() != swapchain->surfacePixelSize())
496 swapchain->createOrResize();
499 QRhi::FrameOpResult frameResult = rhi->beginFrame(swapchain);
500 if (frameResult == QRhi::FrameOpSwapChainOutOfDate) {
501 if (!swapchain->createOrResize())
502 return QPlatformBackingStore::FlushFailed;
503 frameResult = rhi->beginFrame(swapchain);
505 if (frameResult == QRhi::FrameOpDeviceLost)
506 return QPlatformBackingStore::FlushFailedDueToLostDevice;
507 if (frameResult != QRhi::FrameOpSuccess)
508 return QPlatformBackingStore::FlushFailed;
511 QRhiResourceUpdateBatch *resourceUpdates = rhi->nextResourceUpdateBatch();
512 QPlatformBackingStore::TextureFlags flags;
514 bool gotTextureFromGraphicsBuffer =
false;
515 if (QPlatformGraphicsBuffer *graphicsBuffer = backingStore->graphicsBuffer()) {
516 if (graphicsBuffer->lock(QPlatformGraphicsBuffer::SWReadAccess)) {
517 const QImage::Format format = QImage::toImageFormat(graphicsBuffer->format());
518 const QSize size = graphicsBuffer->size();
519 QImage wrapperImage(graphicsBuffer->data(), size.width(), size.height(), graphicsBuffer->bytesPerLine(), format);
520 toTexture(wrapperImage, rhi, resourceUpdates, scaledRegion(region, sourceTransformFactor, offset), &flags);
521 gotTextureFromGraphicsBuffer =
true;
522 graphicsBuffer->unlock();
523 if (graphicsBuffer->origin() == QPlatformGraphicsBuffer::OriginBottomLeft)
524 flags |= QPlatformBackingStore::TextureFlip;
527 if (!gotTextureFromGraphicsBuffer)
528 toTexture(backingStore, rhi, resourceUpdates, scaledRegion(region, sourceTransformFactor, offset), &flags);
530 ensureResources(resourceUpdates, swapchain->renderPassDescriptor());
532 UpdateUniformOptions uniformOptions;
533#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
534 if (flags & QPlatformBackingStore::TextureSwizzle)
535 uniformOptions |= NeedsRedBlueSwap;
537 if (flags & QPlatformBackingStore::TextureSwizzle)
538 uniformOptions |= NeedsAlphaRotate;
540 const bool premultiplied = (flags & QPlatformBackingStore::TexturePremultiplied) != 0;
542 if (flags & QPlatformBackingStore::TextureFlip)
545 const qreal dpr = window->devicePixelRatio();
546 const QRect deviceWindowRect = scaledRect(QRect(QPoint(), window->size()), dpr);
547 const QRect sourceWindowRect = scaledRect(QRect(QPoint(), window->size()), sourceDevicePixelRatio);
551 const bool needsLinearSampler = sourceWindowRect.width() > deviceWindowRect.width()
552 && sourceWindowRect.height() > deviceWindowRect.height();
554 const bool invertTargetY = !rhi->isYUpInNDC();
555 const bool invertSource = !rhi->isYUpInFramebuffer();
561 const QPoint sourceWindowOffset = scaledOffset(offset, sourceTransformFactor);
562 const QRect srcRect = toBottomLeftRect(sourceWindowRect.translated(sourceWindowOffset), m_texture->pixelSize().height());
563 const QMatrix3x3 source = sourceTransform(srcRect, m_texture->pixelSize(), origin);
566 target.data()[5] = -1.0f;
567 updateUniforms(&m_widgetQuadData, resourceUpdates, target, source, uniformOptions);
568 if (needsLinearSampler)
569 updatePerQuadData(&m_widgetQuadData, m_texture.get(),
nullptr, NeedsLinearFiltering);
572 const int textureWidgetCount = textures->count();
573 const int oldTextureQuadDataCount = m_textureQuadData.size();
574 if (oldTextureQuadDataCount != textureWidgetCount) {
575 for (
int i = textureWidgetCount; i < oldTextureQuadDataCount; ++i)
576 m_textureQuadData[i].reset();
577 m_textureQuadData.resize(textureWidgetCount);
580 for (
int i = 0; i < textureWidgetCount; ++i) {
581 const bool invertSourceForTextureWidget = textures->flags(i).testFlag(QPlatformTextureList::MirrorVertically)
582 ? !invertSource : invertSource;
585 if (!prepareDrawForRenderToTextureWidget(textures, i, window, deviceWindowRect,
586 offset, invertTargetY, invertSourceForTextureWidget,
589 m_textureQuadData[i].reset();
592 QRhiTexture *t = textures->texture(i);
593 QRhiTexture *tExtra = textures->textureExtra(i);
595 if (!m_textureQuadData[i].isValid())
596 m_textureQuadData[i] = createPerQuadData(t, tExtra);
598 updatePerQuadData(&m_textureQuadData[i], t, tExtra);
599 updateUniforms(&m_textureQuadData[i], resourceUpdates, target, source);
600 if (needsLinearSampler)
601 updatePerQuadData(&m_textureQuadData[i], t, tExtra, NeedsLinearFiltering);
603 m_textureQuadData[i].reset();
608 QRhiCommandBuffer *cb = swapchain->currentFrameCommandBuffer();
609 const QSize outputSizeInPixels = swapchain->currentPixelSize();
610 QColor clearColor = translucentBackground ? Qt::transparent : Qt::black;
612 cb->resourceUpdate(resourceUpdates);
614 auto render = [&](std::optional<QRhiSwapChain::StereoTargetBuffer> buffer = std::nullopt) {
615 QRhiRenderTarget* target =
nullptr;
616 if (buffer.has_value())
617 target = swapchain->currentFrameRenderTarget(buffer.value());
619 target = swapchain->currentFrameRenderTarget();
621 cb->beginPass(target, clearColor, { 1.0f, 0 });
623 cb->setGraphicsPipeline(m_psNoBlend.get());
624 cb->setViewport({ 0, 0,
float(outputSizeInPixels.width()),
float(outputSizeInPixels.height()) });
625 QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf.get(), 0);
626 cb->setVertexInput(0, 1, &vbufBinding);
629 for (
int i = 0; i < textureWidgetCount; ++i) {
630 if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
631 if (m_textureQuadData[i].isValid()) {
633 QRhiShaderResourceBindings* srb = m_textureQuadData[i].srb;
634 if (buffer == QRhiSwapChain::RightBuffer && m_textureQuadData[i].srbExtra)
635 srb = m_textureQuadData[i].srbExtra;
637 cb->setShaderResources(srb);
643 cb->setGraphicsPipeline(premultiplied ? m_psPremulBlend.get() : m_psBlend.get());
647 cb->setShaderResources(m_widgetQuadData.srb);
652 for (
int i = 0; i < textureWidgetCount; ++i) {
653 const QPlatformTextureList::Flags flags = textures->flags(i);
654 if (flags.testFlag(QPlatformTextureList::StacksOnTop)) {
655 if (m_textureQuadData[i].isValid()) {
656 if (flags.testFlag(QPlatformTextureList::NeedsPremultipliedAlphaBlending))
657 cb->setGraphicsPipeline(m_psPremulBlend.get());
659 cb->setGraphicsPipeline(m_psBlend.get());
661 QRhiShaderResourceBindings* srb = m_textureQuadData[i].srb;
662 if (buffer == QRhiSwapChain::RightBuffer && m_textureQuadData[i].srbExtra)
663 srb = m_textureQuadData[i].srbExtra;
665 cb->setShaderResources(srb);
674 if (swapchain->window()->format().stereo()) {
675 render(QRhiSwapChain::LeftBuffer);
676 render(QRhiSwapChain::RightBuffer);
680 rhi->endFrame(swapchain);
682 return QPlatformBackingStore::FlushSuccess;