diff options
-rw-r--r-- | src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp | 29 | ||||
-rw-r--r-- | src/plugins/scenegraph/d3d12/qsgd3d12layer.cpp | 3 | ||||
-rw-r--r-- | src/quick/items/qquickitemgrabresult.cpp | 3 |
3 files changed, 26 insertions, 9 deletions
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp index c77e86ca99..1abc529835 100644 --- a/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp +++ b/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp @@ -2815,11 +2815,21 @@ void QSGD3D12EnginePrivate::useRenderTargetAsTexture(uint id) QImage QSGD3D12EnginePrivate::executeAndWaitReadbackRenderTarget(uint id) { - if (inFrame) { + // Readback due to QQuickWindow::grabWindow() happens outside + // begin-endFrame, but QQuickItemGrabResult leads to rendering a layer + // without a real frame afterwards and triggering readback. This has to be + // supported as well. + if (inFrame && (!activeLayers || currentLayerDepth)) { qWarning("%s: Cannot be called while frame preparation is active", __FUNCTION__); return QImage(); } + // Due to the above we insert a fake "real" frame when a layer was just rendered into. + if (inFrame) { + beginFrame(); + endFrame(); + } + frameCommandList->Reset(frameCommandAllocator[frameIndex % frameInFlightCount].Get(), nullptr); D3D12_RESOURCE_STATES bstate; @@ -2913,10 +2923,19 @@ QImage QSGD3D12EnginePrivate::executeAndWaitReadbackRenderTarget(uint id) qWarning("Mapping the readback buffer failed"); return QImage(); } - for (UINT y = 0; y < rtDesc.Height; ++y) { - quint8 *dst = img.scanLine(y); - memcpy(dst, p, rtDesc.Width * 4); - p += textureLayout.Footprint.RowPitch; + const int bpp = 4; // ### + if (id == 0) { + for (UINT y = 0; y < rtDesc.Height; ++y) { + quint8 *dst = img.scanLine(y); + memcpy(dst, p, rtDesc.Width * bpp); + p += textureLayout.Footprint.RowPitch; + } + } else { + for (int y = rtDesc.Height - 1; y >= 0; --y) { + quint8 *dst = img.scanLine(y); + memcpy(dst, p, rtDesc.Width * bpp); + p += textureLayout.Footprint.RowPitch; + } } readbackBuf->Unmap(0, nullptr); diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12layer.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12layer.cpp index ef2f923d5b..faa6f7566a 100644 --- a/src/plugins/scenegraph/d3d12/qsgd3d12layer.cpp +++ b/src/plugins/scenegraph/d3d12/qsgd3d12layer.cpp @@ -186,8 +186,7 @@ void QSGD3D12Layer::scheduleUpdate() QImage QSGD3D12Layer::toImage() const { - // ### figure out something for item grab support - return QImage(); + return m_rc->engine()->executeAndWaitReadbackRenderTarget(m_rt); } void QSGD3D12Layer::setLive(bool live) diff --git a/src/quick/items/qquickitemgrabresult.cpp b/src/quick/items/qquickitemgrabresult.cpp index 3ff61be241..f69b5b3f4b 100644 --- a/src/quick/items/qquickitemgrabresult.cpp +++ b/src/quick/items/qquickitemgrabresult.cpp @@ -240,8 +240,7 @@ void QQuickItemGrabResult::render() return; d->texture->setRect(QRectF(0, d->itemSize.height(), d->itemSize.width(), -d->itemSize.height())); - QSGContext *sg = QSGDefaultRenderContext::from(QOpenGLContext::currentContext())->sceneGraphContext(); - const QSize minSize = sg->minimumFBOSize(); + const QSize minSize = QQuickWindowPrivate::get(d->window.data())->context->sceneGraphContext()->minimumFBOSize(); d->texture->setSize(QSize(qMax(minSize.width(), d->textureSize.width()), qMax(minSize.height(), d->textureSize.height()))); d->texture->scheduleUpdate(); |