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