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
qdmabufvideobuffer.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 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
5
6#include <QtMultimedia/private/qmultimedia_dmabuf_support_p.h>
7#include <QtMultimedia/private/qvideotexturehelper_p.h>
8#include <QtMultimedia/private/qrhivaluemapper_p.h>
9#include <QtGui/rhi/qrhi.h>
10#include <QtCore/qloggingcategory.h>
11#include <QtCore/private/qcore_unix_p.h>
12
13#if QT_CONFIG(opengl) && QT_CONFIG(egl)
14# include <QtMultimedia/private/qdmabuftextureimporter_p.h>
15#endif
16
17#include <cerrno>
18#include <cstring>
19#include <system_error>
20#include <fcntl.h>
21#include <unistd.h>
22#include <sys/mman.h>
23
24static_assert(QT_CONFIG(linux_dmabuf));
25
27
28Q_STATIC_LOGGING_CATEGORY(qLcDmaBufVideoBuffer, "qt.multimedia.dmabufvideobuffer");
29
30namespace QtMultimediaPrivate {
31
32#if QT_CONFIG(opengl) && QT_CONFIG(egl)
34#endif
35
36namespace {
37
38q23::expected<QUniqueFileDescriptorHandle, std::error_code> dupFd(int fd)
39{
40 QUniqueFileDescriptorHandle duped{ ::fcntl(fd, F_DUPFD_CLOEXEC, 0) };
41 if (!duped)
42 return q23::unexpected(std::error_code(errno, std::generic_category()));
43 return duped;
44}
45
46q23::expected<DmaBufPlane, std::error_code> planeWithDupedFd(DmaBufPlane plane)
47{
48 auto duped = dupFd(plane.fd);
49 if (!duped)
50 return q23::unexpected(duped.error());
51
52 plane.fd = duped->release();
53 return plane;
54}
55
56} // namespace
57
76
86
88{
90
91 if (rhi.backend() != QRhi::OpenGLES2)
92 return {};
93
94#if QT_CONFIG(opengl) && QT_CONFIG(egl)
95 // DmaBufEglContext is bound to the GL context associated with a QRhi;
96 // textures are (re-)imported on the RHI render thread, so this is
97 // created lazily here (rather than in the constructor, which may run on
98 // a different thread) and cached per-rhi.
100 return DmaBufEglContext(&rhi);
101 });
102
103 if (!eglContext.isValid()) {
104 qCDebug(qLcDmaBufVideoBuffer) << "DmaBufEglContext is not valid, falling back to CPU path";
105 return {};
106 }
107
110 if (!handles) {
113 << "Unrecoverable EGL import failure, disabling texture import for this buffer";
115 }
116 return {};
117 }
118
120 m_size);
121#else // QT_CONFIG(opengl) && QT_CONFIG(egl)
123 << "DMABUF texture import is not supported in this build, falling back to CPU path";
124 return {};
125#endif // QT_CONFIG(opengl) && QT_CONFIG(egl)
126}
127
129{
130 for (const MappedRegion &region : regions) {
133 }
134}
135
137{
139
140 // The producer (driver/compositor) owns write access to the DMABUF.
142 return mapData;
143
145 if (!desc)
146 return mapData;
147
148 for (qsizetype i = 0; i < m_planes.size(); ++i) {
149 const DmaBufPlane &plane = m_planes[i];
150
151 auto fd = dupFd(plane.fd);
152 if (!fd) {
154 << "Failed to dup DMABUF fd for plane" << i << ':' << fd.error().message();
157 return {};
158 }
159
160 const off_t len = ::lseek(fd->get(), 0, SEEK_END);
161 void *mapped = len > 0 ? ::mmap(nullptr, size_t(len), PROT_READ, MAP_SHARED, fd->get(), 0)
162 : MAP_FAILED;
163 if (mapped == MAP_FAILED) {
165 << "Could not map DMABUF for plane" << i << ':' << qt_error_string(errno);
168 return {};
169 }
170
172 const QSpan<std::byte> data{
173 static_cast<std::byte *>(mapped),
174 qsizetype(len),
175 };
177 std::move(*fd),
178 data,
179 });
180
181 mapData.data[i] = reinterpret_cast<uchar *>(data.data()) + plane.offset;
184 }
185
187
188 m_mapMode = mode;
189 return mapData;
190}
191
199
200} // namespace QtMultimediaPrivate
201
202QT_END_NAMESPACE
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)
#define MAP_FAILED