1// Copyright (C) 2015 Paul Lemire
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 "vsyncframeadvanceservice_p.h"
5#include <Qt3DRender/private/renderlogging_p.h>
6#include <Qt3DCore/private/qabstractframeadvanceservice_p.h>
7#include <Qt3DCore/private/qabstractframeadvanceservice_p_p.h>
8#include <QSemaphore>
9#include <QElapsedTimer>
10
11QT_BEGIN_NAMESPACE
12
13namespace Qt3DRender {
14namespace Render {
15
16class VSyncFrameAdvanceServicePrivate final : public Qt3DCore::QAbstractFrameAdvanceServicePrivate
17{
18public:
19 explicit VSyncFrameAdvanceServicePrivate(bool drivenByRenderThread)
20 : QAbstractFrameAdvanceServicePrivate(QStringLiteral("Renderer Aspect Frame Advance Service - aligned with vsync"))
21 , m_semaphore(0)
22 , m_elapsedTimeSincePreviousFrame(0)
23 , m_drivenByRenderThread(drivenByRenderThread)
24 {
25 }
26
27 QSemaphore m_semaphore;
28 QElapsedTimer m_elapsed;
29 qint64 m_elapsedTimeSincePreviousFrame;
30 bool m_drivenByRenderThread;
31};
32
33VSyncFrameAdvanceService::VSyncFrameAdvanceService(bool drivenByRenderThread)
34 : QAbstractFrameAdvanceService(*new VSyncFrameAdvanceServicePrivate(drivenByRenderThread))
35{
36}
37
38VSyncFrameAdvanceService::~VSyncFrameAdvanceService()
39{
40}
41
42// Main Thread
43qint64 VSyncFrameAdvanceService::waitForNextFrame()
44{
45 Q_D(VSyncFrameAdvanceService);
46
47 d->m_semaphore.acquire(n: std::max(a: d->m_semaphore.available(), b: 1));
48
49 const qint64 currentTime = d->m_elapsed.nsecsElapsed();
50 qCDebug(VSyncAdvanceService) << "Elapsed nsecs since last call " << currentTime - d->m_elapsedTimeSincePreviousFrame;
51 d->m_elapsedTimeSincePreviousFrame = currentTime;
52 return currentTime;
53}
54
55void VSyncFrameAdvanceService::start()
56{
57 Q_D(VSyncFrameAdvanceService);
58 d->m_elapsed.start();
59}
60
61/*!
62 \internal
63
64 Stops the VSyncFrameAdvanceService, releases the semaphore to allow the
65 renderer to cleanup without having to call waitForNextFrame.
66 */
67void VSyncFrameAdvanceService::stop()
68{
69 Q_D(VSyncFrameAdvanceService);
70 d->m_semaphore.release(n: 1);
71 qCDebug(VSyncAdvanceService) << "Terminating VSyncFrameAdvanceService";
72}
73
74// Render Thread
75void VSyncFrameAdvanceService::proceedToNextFrame()
76{
77 Q_D(VSyncFrameAdvanceService);
78 d->m_semaphore.release(n: 1);
79}
80
81} // namespace Render
82} // namespace Qt3DRender
83
84QT_END_NAMESPACE
85

source code of qt3d/src/render/services/vsyncframeadvanceservice.cpp