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