aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@theqtcompany.com>2016-05-06 14:59:32 +0200
committerLaszlo Agocs <laszlo.agocs@theqtcompany.com>2016-05-08 20:03:30 +0000
commit57a61dc907fb132351bbbf2782a73feb0ce93b30 (patch)
tree64b3bba9999fe8bd226524d974f20de2ee08d775
parent3fe2ecccc96ef1d8243e0683853c5db8c6ed9ee0 (diff)
D3D12: Support QQuickItem::grabToImage
that is, the grabbing of layers. This is where things start getting insane because now the convenient assumptions of updateTexture() for layers only getting called in the sync phase before the rendering of the real frame begins breaks down. With item grabbing the call happens on afterRendering()... the engine will now do a minor hack when doing the readback to make this work. This, together with the previous patches provides us with the following impressive, highly karma-boosting results: tst_scenegraph 24 passed, 0 failed, 11 skipped tst_qquickwindow 52 passed, 0 failed, 6 skipped tst_qquickitem 61 passed, 0 failed, 0 skipped tst_qquickitem2 84 passed, 0 failed, 6 skipped Change-Id: I8f160e6848215a3b3304f2e00516eea0d96eb4a0 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp29
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12layer.cpp3
-rw-r--r--src/quick/items/qquickitemgrabresult.cpp3
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();