1 | // Copyright (C) 2016 The Qt Company Ltd. |
---|---|
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include <Qt3DRender/private/qrendercapture_p.h> |
5 | #include <Qt3DRender/private/rendercapture_p.h> |
6 | #include <Qt3DCore/private/qaspectmanager_p.h> |
7 | #include <Qt3DCore/private/qaspectjobmanager_p.h> |
8 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | namespace Qt3DRender { |
12 | |
13 | namespace Render { |
14 | |
15 | RenderCapture::RenderCapture() |
16 | : FrameGraphNode(FrameGraphNode::RenderCapture, QBackendNode::ReadWrite) |
17 | { |
18 | |
19 | } |
20 | |
21 | void RenderCapture::requestCapture(const QRenderCaptureRequest &request) |
22 | { |
23 | QMutexLocker lock(&m_mutex); |
24 | m_requestedCaptures.push_back(t: request); |
25 | } |
26 | |
27 | // called by render view initializer job |
28 | bool RenderCapture::wasCaptureRequested() const |
29 | { |
30 | QMutexLocker lock(&m_mutex); |
31 | return m_requestedCaptures.size() > 0 && isEnabled(); |
32 | } |
33 | |
34 | // called by render view initializer job |
35 | QRenderCaptureRequest RenderCapture::takeCaptureRequest() |
36 | { |
37 | Q_ASSERT(!m_requestedCaptures.isEmpty()); |
38 | return m_requestedCaptures.takeFirst(); |
39 | } |
40 | |
41 | void RenderCapture::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) |
42 | { |
43 | const QRenderCapture *node = qobject_cast<const QRenderCapture *>(object: frontEnd); |
44 | if (!node) |
45 | return; |
46 | |
47 | FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); |
48 | |
49 | const QRenderCapturePrivate *d = static_cast<const QRenderCapturePrivate *>(QFrameGraphNodePrivate::get(node)); |
50 | const auto newPendingsCaptures = Qt3DCore::moveAndClear(data&: d->m_pendingRequests); |
51 | if (newPendingsCaptures.size() > 0) { |
52 | m_requestedCaptures.append(l: newPendingsCaptures); |
53 | markDirty(changes: AbstractRenderer::FrameGraphDirty); |
54 | } |
55 | |
56 | if (firstTime) |
57 | markDirty(changes: AbstractRenderer::FrameGraphDirty); |
58 | } |
59 | |
60 | // called by render thread |
61 | void RenderCapture::addRenderCapture(int captureId, const QImage &image) |
62 | { |
63 | QMutexLocker lock(&m_mutex); |
64 | auto data = RenderCaptureDataPtr::create(); |
65 | data.data()->captureId = captureId; |
66 | data.data()->image = image; |
67 | m_renderCaptureData.push_back(t: data); |
68 | } |
69 | |
70 | // called to send render capture in main thread |
71 | void RenderCapture::syncRenderCapturesToFrontend(Qt3DCore::QAspectManager *manager) |
72 | { |
73 | auto *frontend = manager->lookupNode(id: peerId()); |
74 | if (!frontend) |
75 | return; |
76 | QRenderCapturePrivate *dfrontend = static_cast<QRenderCapturePrivate *>(Qt3DCore::QNodePrivate::get(q: frontend)); |
77 | |
78 | QMutexLocker lock(&m_mutex); |
79 | for (const RenderCaptureDataPtr &data : std::as_const(t&: m_renderCaptureData)) { |
80 | QPointer<QRenderCaptureReply> reply = dfrontend->takeReply(captureId: data.data()->captureId); |
81 | // Note: QPointer has no operator bool, we must use isNull() to check it |
82 | if (!reply.isNull()) { |
83 | dfrontend->setImage(reply, image: data.data()->image); |
84 | emit reply->completed(); |
85 | } |
86 | } |
87 | m_renderCaptureData.clear(); |
88 | } |
89 | |
90 | } // Render |
91 | |
92 | } // Qt3DRender |
93 | |
94 | QT_END_NAMESPACE |
95 |