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
qeglimagefunctions.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_ranges_p.h>
7
8#include <QtCore/qloggingcategory.h>
9
10#include <optional>
11#include <vector>
12
13#if defined(EGL_KHR_image)
14# include <limits>
15# include <mutex>
16#endif
17
18QT_BEGIN_NAMESPACE
19
20namespace QtMultimediaPrivate {
21
22namespace {
23
24#if defined(EGL_KHR_image)
25Q_STATIC_LOGGING_CATEGORY(qLcEglImage, "qt.multimedia.egl");
26
27// eglCreateImageKHR takes an EGLint attribute list, while our callers build an EGLAttrib
28// (intptr_t) list, as required by core eglCreateImage. On 64-bit platforms we need to perform
29// narrowing conversion; all of our current attribute values (dimensions, fds, offsets/strides,
30// and the already 32-bit-split dma-buf modifier) fit into EGLint, but we still validate this
31// rather than silently truncate.
32[[maybe_unused]] std::optional<std::vector<EGLint>> narrowToEGLint(QSpan<const EGLAttrib> attribs)
33{
34 std::vector<EGLint> narrowed(size_t(attribs.size()));
35
36 Q_ASSERT(sizeof(EGLAttrib) > sizeof(EGLint));
37 static std::once_flag warnOnce;
38 std::call_once(warnOnce, [] {
39 qCDebug(qLcEglImage) << "EGL_KHR_image_base fallback: narrowing 64-bit EGLAttrib "
40 "attribute values to 32-bit EGLint";
41 });
42
43 for (qsizetype i = 0; i < attribs.size(); ++i) {
44 const EGLAttrib value = attribs[i];
45 if (value < std::numeric_limits<EGLint>::min()
46 || value > std::numeric_limits<EGLint>::max()) {
47 qCWarning(qLcEglImage)
48 << "EGL attribute value" << value
49 << "does not fit into EGLint; cannot use the EGL_KHR_image_base fallback";
50 return std::nullopt;
51 }
52 narrowed[size_t(i)] = EGLint(value);
53 }
54
55 return narrowed;
56}
57#endif
58
59template <typename Fn>
60Fn getEglFunction(const char *name)
61{
62 return reinterpret_cast<Fn>(eglGetProcAddress(name));
63}
64
65} // namespace
66
68 :
69#ifdef GL_OES_EGL_image
71 getEglFunction<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>("glEGLImageTargetTexture2DOES"),
72 }
73#endif
74#ifdef EGL_VERSION_1_5
75 ,
77 getEglFunction<PFNEGLCREATEIMAGEPROC>("eglCreateImage"),
78 },
80 getEglFunction<PFNEGLDESTROYIMAGEPROC>("eglDestroyImage"),
81 }
82#endif
83#if defined(EGL_KHR_image)
84 ,
86 getEglFunction<PFNEGLCREATEIMAGEKHRPROC>("eglCreateImageKHR"),
87 },
89 getEglFunction<PFNEGLDESTROYIMAGEKHRPROC>("eglDestroyImageKHR"),
90 }
91#endif
92#if defined(EGL_EXT_image_dma_buf_import_modifiers)
93 ,
95 getEglFunction<PFNEGLQUERYDMABUFMODIFIERSEXTPROC>("eglQueryDmaBufModifiersEXT"),
96 }
97#endif
98{
99}
100
102{
103 static const QEglImageFunctions singleton;
104 return singleton;
105}
106
108{
109#ifdef GL_OES_EGL_image
111 return false;
112#else
113 return false;
114#endif
115
116#ifdef EGL_VERSION_1_5
118 return true;
119#endif
120#if defined(EGL_KHR_image)
122 return true;
123#endif
124 return false;
125}
126
133
136 QSpan<const EGLAttrib> attribs) const
137{
139#ifdef EGL_VERSION_1_5
140 if (m_eglCreateImage) {
141 return EGLImageHandle(
143 attribs.empty() ? nullptr : attribs.data()),
144 deleter);
145 }
146#endif
147#if defined(EGL_KHR_image)
149 if constexpr (sizeof(EGLAttrib) == sizeof(EGLint)) {
150 return EGLImageHandle(
152 dpy, ctx, target, buffer,
153 attribs.empty() ? nullptr
154 : reinterpret_cast<const EGLint *>(attribs.data())),
155 deleter);
156 } else {
157 const auto narrowed = narrowToEGLint(attribs);
158 if (!narrowed)
159 return EGLImageHandle(EGL_NO_IMAGE, deleter);
160 return EGLImageHandle(
162 narrowed->empty() ? nullptr : narrowed->data()),
163 deleter);
164 }
165 }
166#endif
167 return EGLImageHandle(EGL_NO_IMAGE, deleter);
168}
169
171{
172#ifdef EGL_VERSION_1_5
174 return m_eglDestroyImage(dpy, image);
175#endif
176#if defined(EGL_KHR_image)
179#endif
180 return EGL_FALSE;
181}
182
185 DRMModifier modifier) const
186{
187#if defined(EGL_EXT_image_dma_buf_import_modifiers)
189 return std::nullopt; // can't introspect
190
193 if (!m_eglQueryDmaBufModifiersEXT(display, format, 0, nullptr, nullptr, &numModifiers)
194 || numModifiers <= 0)
195 return std::nullopt; // query unsupported
196
199 &numModifiers))
200 return std::nullopt;
201
203#else
207 return std::nullopt;
208#endif
209}
210
211} // namespace QtMultimediaPrivate
212
213QT_END_NAMESPACE