Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qeglfskmseventreader.cpp
Go to the documentation of this file.
1// Copyright (C) 2019 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// Qt-Security score:significant reason:default
4
9
10#include <QSocketNotifier>
11#include <QCoreApplication>
12#include <QLoggingCategory>
13
15
16static void pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data)
17{
18 Q_UNUSED(fd);
19
20 QEglFSKmsEventReaderThread *t = static_cast<QEglFSKmsEventReaderThread *>(QThread::currentThread());
22
23 QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(user_data);
24 if (QEglFSKmsScreen::isScreenKnown(screen))
25 screen->pageFlipped(sequence, tv_sec, tv_usec);
26 else
27 qWarning("Deleted screen got it's pageFlipHandler called; Dead pointer: %p", user_data);
28}
29
31{
32public:
33 static const QEvent::Type TYPE = QEvent::Type(QEvent::User + 1);
34 RegisterWaitFlipEvent(void *key, QMutex *mutex, QWaitCondition *cond)
35 : QEvent(TYPE), key(key), mutex(mutex), cond(cond)
36 { }
37 void *key;
40};
41
42bool QEglFSKmsEventHost::event(QEvent *event)
43{
44 if (event->type() == RegisterWaitFlipEvent::TYPE) {
45 RegisterWaitFlipEvent *e = static_cast<RegisterWaitFlipEvent *>(event);
46 PendingFlipWait *p = &pendingFlipWaits[0];
47 PendingFlipWait *end = p + MAX_FLIPS;
48 while (p < end) {
49 if (!p->key) {
50 p->key = e->key;
51 p->mutex = e->mutex;
52 p->cond = e->cond;
54 return true;
55 }
56 ++p;
57 }
58 qWarning("Cannot queue page flip wait (more than %d screens?)", MAX_FLIPS);
59 e->mutex->lock();
60 e->cond->wakeOne();
61 e->mutex->unlock();
62 return true;
63 }
64 return QObject::event(event);
65}
66
68{
69 void **begin = &completedFlips[0];
70 void **end = begin + MAX_FLIPS;
71
72 for (int i = 0; i < MAX_FLIPS; ++i) {
73 PendingFlipWait *w = pendingFlipWaits + i;
74 if (!w->key)
75 continue;
76
77 void **p = begin;
78 while (p < end) {
79 if (*p == w->key) {
80 *p = nullptr;
81 w->key = nullptr;
82 w->mutex->lock();
83 w->cond->wakeOne();
84 w->mutex->unlock();
85 return;
86 }
87 ++p;
88 }
89 }
90}
91
93{
94 void **begin = &completedFlips[0];
95 void **end = begin + MAX_FLIPS;
96 void **p = begin;
97 while (p < end) {
98 if (*p == key) {
100 return;
101 }
102 ++p;
103 }
104 p = begin;
105 while (p < end) {
106 if (!*p) {
107 *p = key;
109 return;
110 }
111 ++p;
112 }
113 qWarning("Cannot store page flip status (more than %d screens?)", MAX_FLIPS);
114}
115
117{
118 qCDebug(qLcEglfsKmsDebug, "Event reader thread: entering event loop");
119
120 QSocketNotifier notifier(m_fd, QSocketNotifier::Read);
121 QObject::connect(&notifier, &QSocketNotifier::activated, &notifier, [this] {
122 drmEventContext drmEvent;
123 memset(&drmEvent, 0, sizeof(drmEvent));
124 drmEvent.version = 2;
125 drmEvent.vblank_handler = nullptr;
126 drmEvent.page_flip_handler = pageFlipHandler;
127 drmHandleEvent(m_fd, &drmEvent);
128 });
129
130 exec();
131
132 m_ev.moveToThread(thread()); // move back to the thread where m_ev was created
133
134 qCDebug(qLcEglfsKmsDebug, "Event reader thread: event loop stopped");
135}
136
137QEglFSKmsEventReader::~QEglFSKmsEventReader()
138{
139 destroy();
140}
141
142void QEglFSKmsEventReader::create(QEglFSKmsDevice *device)
143{
144 destroy();
145
146 if (!device)
147 return;
148
149 m_device = device;
150
151 qCDebug(qLcEglfsKmsDebug, "Initializing event reader for device %p fd %d",
152 m_device, m_device->fd());
153
154 m_thread = new QEglFSKmsEventReaderThread(m_device->fd());
155 m_thread->start();
156
157 // Change thread affinity for the event host, so that postEvent()
158 // goes through the event reader thread's event loop for that object.
159 m_thread->eventHost()->moveToThread(m_thread);
160}
161
162void QEglFSKmsEventReader::destroy()
163{
164 if (!m_device)
165 return;
166
167 qCDebug(qLcEglfsKmsDebug, "Stopping event reader for device %p", m_device);
168
169 if (m_thread) {
170 m_thread->quit();
171 m_thread->wait();
172 delete m_thread;
173 m_thread = nullptr;
174 }
175
176 m_device = nullptr;
177}
178
179void QEglFSKmsEventReader::startWaitFlip(void *key, QMutex *mutex, QWaitCondition *cond)
180{
181 if (m_thread) {
182 QCoreApplication::postEvent(m_thread->eventHost(),
183 new RegisterWaitFlipEvent(key, mutex, cond));
184 }
185}
186
187QT_END_NAMESPACE
QEglFSKmsEventHost * eventHost()
RegisterWaitFlipEvent(void *key, QMutex *mutex, QWaitCondition *cond)
static const QEvent::Type TYPE
Combined button and popup list for selecting options.
static QT_BEGIN_NAMESPACE void pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data)
bool event(QEvent *event) override
This virtual function receives events to an object and should return true if the event e was recogniz...
void * completedFlips[MAX_FLIPS]
void handlePageFlipCompleted(void *key)