Changeset View
Changeset View
Standalone View
Standalone View
platformsupport/scenes/opengl/linux_dmabuf.cpp
- This file was added.
1 | /******************************************************************** | ||||
---|---|---|---|---|---|
2 | KWin - the KDE window manager | ||||
3 | This file is part of the KDE project. | ||||
4 | | ||||
5 | Copyright © 2019 Roman Gilg <subdiff@gmail.com> | ||||
6 | Copyright © 2018 Fredrik Höglund <fredrik@kde.org> | ||||
7 | | ||||
8 | This program is free software; you can redistribute it and/or modify | ||||
9 | it under the terms of the GNU General Public License as published by | ||||
10 | the Free Software Foundation; either version 2 of the License, or | ||||
11 | (at your option) any later version. | ||||
12 | | ||||
13 | This program is distributed in the hope that it will be useful, | ||||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
16 | GNU General Public License for more details. | ||||
17 | | ||||
18 | You should have received a copy of the GNU General Public License | ||||
19 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
20 | *********************************************************************/ | ||||
21 | #include "linux_dmabuf.h" | ||||
22 | | ||||
23 | #include "drm_fourcc.h" | ||||
24 | #include "../../../wayland_server.h" | ||||
25 | | ||||
26 | #include <KWayland/Server/display.h> | ||||
27 | | ||||
28 | #include <unistd.h> | ||||
29 | #include <EGL/eglmesaext.h> | ||||
30 | | ||||
31 | namespace KWin | ||||
32 | { | ||||
33 | | ||||
34 | typedef EGLBoolean (*eglQueryDmaBufFormatsEXT_func) (EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats); | ||||
35 | typedef EGLBoolean (*eglQueryDmaBufModifiersEXT_func) (EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers); | ||||
36 | eglQueryDmaBufFormatsEXT_func eglQueryDmaBufFormatsEXT = nullptr; | ||||
37 | eglQueryDmaBufModifiersEXT_func eglQueryDmaBufModifiersEXT = nullptr; | ||||
38 | | ||||
39 | #ifndef EGL_EXT_image_dma_buf_import | ||||
40 | #define EGL_LINUX_DMA_BUF_EXT 0x3270 | ||||
41 | #define EGL_LINUX_DRM_FOURCC_EXT 0x3271 | ||||
42 | #define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272 | ||||
43 | #define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273 | ||||
44 | #define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274 | ||||
45 | #define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275 | ||||
46 | #define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276 | ||||
47 | #define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277 | ||||
48 | #define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278 | ||||
49 | #define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279 | ||||
50 | #define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A | ||||
51 | #define EGL_YUV_COLOR_SPACE_HINT_EXT 0x327B | ||||
52 | #define EGL_SAMPLE_RANGE_HINT_EXT 0x327C | ||||
53 | #define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D | ||||
54 | #define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E | ||||
55 | #define EGL_ITU_REC601_EXT 0x327F | ||||
56 | #define EGL_ITU_REC709_EXT 0x3280 | ||||
57 | #define EGL_ITU_REC2020_EXT 0x3281 | ||||
58 | #define EGL_YUV_FULL_RANGE_EXT 0x3282 | ||||
59 | #define EGL_YUV_NARROW_RANGE_EXT 0x3283 | ||||
60 | #define EGL_YUV_CHROMA_SITING_0_EXT 0x3284 | ||||
61 | #define EGL_YUV_CHROMA_SITING_0_5_EXT 0x3285 | ||||
62 | #endif // EGL_EXT_image_dma_buf_import | ||||
63 | | ||||
64 | #ifndef EGL_EXT_image_dma_buf_import_modifiers | ||||
65 | #define EGL_DMA_BUF_PLANE3_FD_EXT 0x3440 | ||||
66 | #define EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441 | ||||
67 | #define EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442 | ||||
68 | #define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443 | ||||
69 | #define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444 | ||||
70 | #define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445 | ||||
71 | #define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446 | ||||
72 | #define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447 | ||||
73 | #define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448 | ||||
74 | #define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449 | ||||
75 | #define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A | ||||
76 | #endif // EGL_EXT_image_dma_buf_import_modifiers | ||||
77 | | ||||
78 | struct YuvPlane | ||||
79 | { | ||||
80 | int widthDivisor; | ||||
81 | int heightDivisor; | ||||
82 | uint32_t format; | ||||
83 | int planeIndex; | ||||
84 | }; | ||||
85 | | ||||
86 | struct YuvFormat | ||||
87 | { | ||||
88 | uint32_t format; | ||||
89 | int inputPlanes; | ||||
90 | int outputPlanes; | ||||
91 | int textureType; | ||||
92 | struct YuvPlane planes[3]; | ||||
93 | }; | ||||
94 | | ||||
95 | YuvFormat yuvFormats[] = { | ||||
96 | { | ||||
97 | DRM_FORMAT_YUYV, | ||||
98 | 1, 2, | ||||
99 | EGL_TEXTURE_Y_XUXV_WL, | ||||
100 | { | ||||
101 | { | ||||
102 | 1, 1, | ||||
103 | DRM_FORMAT_GR88, | ||||
104 | 0 | ||||
105 | }, | ||||
106 | { | ||||
107 | 2, 1, | ||||
108 | DRM_FORMAT_ARGB8888, | ||||
109 | 0 | ||||
110 | } | ||||
111 | } | ||||
112 | }, | ||||
113 | { | ||||
114 | DRM_FORMAT_NV12, | ||||
115 | 2, 2, | ||||
116 | EGL_TEXTURE_Y_UV_WL, | ||||
117 | { | ||||
118 | { | ||||
119 | 1, 1, | ||||
120 | DRM_FORMAT_R8, | ||||
121 | 0 | ||||
122 | }, | ||||
123 | { | ||||
124 | 2, 2, | ||||
125 | DRM_FORMAT_GR88, | ||||
126 | 1 | ||||
127 | } | ||||
128 | } | ||||
129 | }, | ||||
130 | { | ||||
131 | DRM_FORMAT_YUV420, | ||||
132 | 3, 3, | ||||
133 | EGL_TEXTURE_Y_U_V_WL, | ||||
134 | { | ||||
135 | { | ||||
136 | 1, 1, | ||||
137 | DRM_FORMAT_R8, | ||||
138 | 0 | ||||
139 | }, | ||||
140 | { | ||||
141 | 2, 2, | ||||
142 | DRM_FORMAT_R8, | ||||
143 | 1 | ||||
144 | }, | ||||
145 | { | ||||
146 | 2, 2, | ||||
147 | DRM_FORMAT_R8, | ||||
148 | 2 | ||||
149 | } | ||||
150 | } | ||||
151 | }, | ||||
152 | { | ||||
153 | DRM_FORMAT_YUV444, | ||||
154 | 3, 3, | ||||
155 | EGL_TEXTURE_Y_U_V_WL, | ||||
156 | { | ||||
157 | { | ||||
158 | 1, 1, | ||||
159 | DRM_FORMAT_R8, | ||||
160 | 0 | ||||
161 | }, | ||||
162 | { | ||||
163 | 1, 1, | ||||
164 | DRM_FORMAT_R8, | ||||
165 | 1 | ||||
166 | }, | ||||
167 | { | ||||
168 | 1, 1, | ||||
169 | DRM_FORMAT_R8, | ||||
170 | 2 | ||||
171 | } | ||||
172 | } | ||||
173 | } | ||||
174 | }; | ||||
175 | | ||||
176 | DmabufBuffer::DmabufBuffer(EGLImage image, | ||||
177 | const QVector<Plane> &planes, | ||||
178 | uint32_t format, | ||||
179 | const QSize &size, | ||||
180 | Flags flags, | ||||
181 | LinuxDmabuf *interfaceImpl) | ||||
182 | : DmabufBuffer(planes, format, size, flags, interfaceImpl) | ||||
183 | { | ||||
184 | m_importType = ImportType::Direct; | ||||
185 | addImage(image); | ||||
186 | } | ||||
187 | | ||||
188 | | ||||
189 | DmabufBuffer::DmabufBuffer(const QVector<Plane> &planes, | ||||
190 | uint32_t format, | ||||
191 | const QSize &size, | ||||
192 | Flags flags, | ||||
193 | LinuxDmabuf *interfaceImpl) | ||||
194 | : KWayland::Server::LinuxDmabufUnstableV1Buffer(format, size) | ||||
195 | , m_planes(planes) | ||||
196 | , m_flags(flags) | ||||
197 | , m_interfaceImpl(interfaceImpl) | ||||
198 | { | ||||
199 | m_importType = ImportType::Conversion; | ||||
200 | } | ||||
201 | | ||||
202 | DmabufBuffer::~DmabufBuffer() | ||||
203 | { | ||||
204 | if (m_interfaceImpl) { | ||||
205 | m_interfaceImpl->removeBuffer(this); | ||||
206 | removeImages(); | ||||
207 | } | ||||
208 | | ||||
209 | // Close all open file descriptors | ||||
210 | for (int i = 0; i < m_planes.count(); i++) { | ||||
211 | if (m_planes[i].fd != -1) | ||||
212 | ::close(m_planes[i].fd); | ||||
213 | m_planes[i].fd = -1; | ||||
214 | } | ||||
215 | } | ||||
216 | | ||||
217 | void DmabufBuffer::addImage(EGLImage image) | ||||
218 | { | ||||
219 | m_images << image; | ||||
220 | } | ||||
221 | | ||||
222 | void DmabufBuffer::removeImages() | ||||
223 | { | ||||
224 | for (auto image : m_images) { | ||||
225 | eglDestroyImageKHR(m_interfaceImpl->m_backend->eglDisplay(), image); | ||||
226 | } | ||||
227 | m_images.clear(); | ||||
228 | m_interfaceImpl = nullptr; | ||||
229 | } | ||||
230 | | ||||
231 | using Plane = KWayland::Server::LinuxDmabufUnstableV1Interface::Plane; | ||||
232 | using Flags = KWayland::Server::LinuxDmabufUnstableV1Interface::Flags; | ||||
233 | | ||||
234 | EGLImage LinuxDmabuf::createImage(const QVector<Plane> &planes, | ||||
235 | uint32_t format, | ||||
236 | const QSize &size) | ||||
237 | { | ||||
238 | const bool hasModifiers = eglQueryDmaBufModifiersEXT != nullptr && | ||||
239 | planes[0].modifier != DRM_FORMAT_MOD_INVALID; | ||||
240 | | ||||
241 | QVector<EGLint> attribs; | ||||
242 | attribs << EGL_WIDTH << size.width() | ||||
243 | << EGL_HEIGHT << size.height() | ||||
244 | << EGL_LINUX_DRM_FOURCC_EXT << EGLint(format) | ||||
245 | | ||||
246 | << EGL_DMA_BUF_PLANE0_FD_EXT << planes[0].fd | ||||
247 | << EGL_DMA_BUF_PLANE0_OFFSET_EXT << EGLint(planes[0].offset) | ||||
248 | << EGL_DMA_BUF_PLANE0_PITCH_EXT << EGLint(planes[0].stride); | ||||
249 | | ||||
250 | if (hasModifiers) { | ||||
251 | attribs | ||||
252 | << EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT << EGLint(planes[0].modifier & 0xffffffff) | ||||
253 | << EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT << EGLint(planes[0].modifier >> 32); | ||||
254 | } | ||||
255 | | ||||
256 | if (planes.count() > 1) { | ||||
257 | attribs | ||||
258 | << EGL_DMA_BUF_PLANE1_FD_EXT << planes[1].fd | ||||
259 | << EGL_DMA_BUF_PLANE1_OFFSET_EXT << EGLint(planes[1].offset) | ||||
260 | << EGL_DMA_BUF_PLANE1_PITCH_EXT << EGLint(planes[1].stride); | ||||
261 | | ||||
262 | if (hasModifiers) { | ||||
263 | attribs | ||||
264 | << EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT << EGLint(planes[1].modifier & 0xffffffff) | ||||
265 | << EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT << EGLint(planes[1].modifier >> 32); | ||||
266 | } | ||||
267 | } | ||||
268 | | ||||
269 | if (planes.count() > 2) { | ||||
270 | attribs | ||||
271 | << EGL_DMA_BUF_PLANE2_FD_EXT << planes[2].fd | ||||
272 | << EGL_DMA_BUF_PLANE2_OFFSET_EXT << EGLint(planes[2].offset) | ||||
273 | << EGL_DMA_BUF_PLANE2_PITCH_EXT << EGLint(planes[2].stride); | ||||
274 | | ||||
275 | if (hasModifiers) { | ||||
276 | attribs | ||||
277 | << EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT << EGLint(planes[2].modifier & 0xffffffff) | ||||
278 | << EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT << EGLint(planes[2].modifier >> 32); | ||||
279 | } | ||||
280 | } | ||||
281 | | ||||
282 | if (eglQueryDmaBufModifiersEXT != nullptr && planes.count() > 3) { | ||||
283 | attribs | ||||
284 | << EGL_DMA_BUF_PLANE3_FD_EXT << planes[3].fd | ||||
285 | << EGL_DMA_BUF_PLANE3_OFFSET_EXT << EGLint(planes[3].offset) | ||||
286 | << EGL_DMA_BUF_PLANE3_PITCH_EXT << EGLint(planes[3].stride); | ||||
287 | | ||||
288 | if (hasModifiers) { | ||||
289 | attribs | ||||
290 | << EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT << EGLint(planes[3].modifier & 0xffffffff) | ||||
291 | << EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT << EGLint(planes[3].modifier >> 32); | ||||
292 | } | ||||
293 | } | ||||
294 | | ||||
295 | attribs << EGL_NONE; | ||||
296 | | ||||
297 | EGLImage image = eglCreateImageKHR(m_backend->eglDisplay(), | ||||
298 | EGL_NO_CONTEXT, | ||||
299 | EGL_LINUX_DMA_BUF_EXT, | ||||
300 | (EGLClientBuffer) nullptr, | ||||
301 | attribs.data()); | ||||
302 | if (image == EGL_NO_IMAGE_KHR) { | ||||
303 | return nullptr; | ||||
304 | } | ||||
305 | | ||||
306 | return image; | ||||
307 | } | ||||
308 | | ||||
309 | KWayland::Server::LinuxDmabufUnstableV1Buffer* LinuxDmabuf::importBuffer(const QVector<Plane> &planes, | ||||
310 | uint32_t format, | ||||
311 | const QSize &size, | ||||
312 | Flags flags) | ||||
313 | { | ||||
314 | Q_ASSERT(planes.count() > 0); | ||||
315 | | ||||
316 | // Try first to import as a single image | ||||
317 | if (auto *img = createImage(planes, format, size)) { | ||||
318 | return new DmabufBuffer(img, planes, format, size, flags, this); | ||||
319 | } | ||||
320 | | ||||
321 | // TODO: to enable this we must be able to store multiple textures per window pixmap | ||||
322 | // and when on window draw do yuv to rgb transformation per shader (see Weston) | ||||
323 | // // not a single image, try yuv import | ||||
324 | // return yuvImport(planes, format, size, flags); | ||||
325 | | ||||
326 | return nullptr; | ||||
327 | } | ||||
328 | | ||||
329 | KWayland::Server::LinuxDmabufUnstableV1Buffer* LinuxDmabuf::yuvImport(const QVector<Plane> &planes, | ||||
330 | uint32_t format, | ||||
331 | const QSize &size, | ||||
332 | Flags flags) | ||||
333 | { | ||||
334 | YuvFormat yuvFormat; | ||||
335 | for (YuvFormat f : yuvFormats) { | ||||
336 | if (f.format == format) { | ||||
337 | yuvFormat = f; | ||||
338 | break; | ||||
339 | } | ||||
340 | } | ||||
341 | if (yuvFormat.format == 0) { | ||||
342 | return nullptr; | ||||
343 | } | ||||
344 | if (planes.count() != yuvFormat.inputPlanes) { | ||||
345 | return nullptr; | ||||
346 | } | ||||
347 | | ||||
348 | auto *buf = new DmabufBuffer(planes, format, size, flags, this); | ||||
349 | | ||||
350 | for (int i = 0; i < yuvFormat.outputPlanes; i++) { | ||||
351 | int planeIndex = yuvFormat.planes[i].planeIndex; | ||||
352 | Plane plane = { | ||||
353 | planes[planeIndex].fd, | ||||
354 | planes[planeIndex].offset, | ||||
355 | planes[planeIndex].stride, | ||||
356 | planes[planeIndex].modifier | ||||
357 | }; | ||||
358 | const auto planeFormat = yuvFormat.planes[i].format; | ||||
359 | const auto planeSize = QSize(size.width() / yuvFormat.planes[i].widthDivisor, | ||||
360 | size.height() / yuvFormat.planes[i].heightDivisor); | ||||
361 | auto *image = createImage(QVector<Plane>(1, plane), | ||||
362 | planeFormat, | ||||
363 | planeSize); | ||||
364 | if (!image) { | ||||
365 | delete buf; | ||||
366 | return nullptr; | ||||
367 | } | ||||
368 | buf->addImage(image); | ||||
369 | } | ||||
370 | // TODO: add buf import properties | ||||
371 | return buf; | ||||
372 | } | ||||
373 | | ||||
374 | LinuxDmabuf* LinuxDmabuf::factory(AbstractEglBackend *backend) | ||||
375 | { | ||||
376 | if (!backend->hasExtension(QByteArrayLiteral("EGL_EXT_image_dma_buf_import"))) { | ||||
377 | return nullptr; | ||||
378 | } | ||||
379 | | ||||
380 | if (backend->hasExtension(QByteArrayLiteral("EGL_EXT_image_dma_buf_import_modifiers"))) { | ||||
381 | eglQueryDmaBufFormatsEXT = (eglQueryDmaBufFormatsEXT_func) eglGetProcAddress("eglQueryDmaBufFormatsEXT"); | ||||
382 | eglQueryDmaBufModifiersEXT = (eglQueryDmaBufModifiersEXT_func) eglGetProcAddress("eglQueryDmaBufModifiersEXT"); | ||||
383 | } | ||||
384 | | ||||
385 | if (eglQueryDmaBufFormatsEXT == nullptr) { | ||||
386 | return nullptr; | ||||
387 | } | ||||
388 | | ||||
389 | return new LinuxDmabuf(backend); | ||||
390 | } | ||||
391 | | ||||
392 | LinuxDmabuf::LinuxDmabuf(AbstractEglBackend *backend) | ||||
393 | : KWayland::Server::LinuxDmabufUnstableV1Interface::Impl() | ||||
394 | , m_backend(backend) | ||||
395 | { | ||||
396 | Q_ASSERT(waylandServer()); | ||||
397 | m_interface = waylandServer()->display()->createLinuxDmabufInterface(backend); | ||||
398 | setSupportedFormatsAndModifiers(); | ||||
399 | m_interface->setImpl(this); | ||||
400 | m_interface->create(); | ||||
401 | } | ||||
402 | | ||||
403 | LinuxDmabuf::~LinuxDmabuf() | ||||
404 | { | ||||
405 | for (auto *dmabuf : qAsConst(m_buffers)) { | ||||
406 | dmabuf->removeImages(); | ||||
407 | } | ||||
408 | } | ||||
409 | | ||||
410 | void LinuxDmabuf::removeBuffer(DmabufBuffer *buffer) | ||||
411 | { | ||||
412 | m_buffers.remove(buffer); | ||||
413 | } | ||||
414 | | ||||
415 | const uint32_t s_multiPlaneFormats[] = { | ||||
416 | DRM_FORMAT_XRGB8888_A8, | ||||
417 | DRM_FORMAT_XBGR8888_A8, | ||||
418 | DRM_FORMAT_RGBX8888_A8, | ||||
419 | DRM_FORMAT_BGRX8888_A8, | ||||
420 | DRM_FORMAT_RGB888_A8, | ||||
421 | DRM_FORMAT_BGR888_A8, | ||||
422 | DRM_FORMAT_RGB565_A8, | ||||
423 | DRM_FORMAT_BGR565_A8, | ||||
424 | | ||||
425 | DRM_FORMAT_NV12, | ||||
426 | DRM_FORMAT_NV21, | ||||
427 | DRM_FORMAT_NV16, | ||||
428 | DRM_FORMAT_NV61, | ||||
429 | DRM_FORMAT_NV24, | ||||
430 | DRM_FORMAT_NV42, | ||||
431 | | ||||
432 | DRM_FORMAT_YUV410, | ||||
433 | DRM_FORMAT_YVU410, | ||||
434 | DRM_FORMAT_YUV411, | ||||
435 | DRM_FORMAT_YVU411, | ||||
436 | DRM_FORMAT_YUV420, | ||||
437 | DRM_FORMAT_YVU420, | ||||
438 | DRM_FORMAT_YUV422, | ||||
439 | DRM_FORMAT_YVU422, | ||||
440 | DRM_FORMAT_YUV444, | ||||
441 | DRM_FORMAT_YVU444 | ||||
442 | }; | ||||
443 | | ||||
444 | void filterFormatsWithMultiplePlanes(QVector<uint32_t> &formats) | ||||
445 | { | ||||
446 | QVector<uint32_t>::iterator it = formats.begin(); | ||||
447 | while (it != formats.end()) { | ||||
448 | for (auto linuxFormat : s_multiPlaneFormats) { | ||||
449 | if (*it == linuxFormat) { | ||||
450 | qDebug() << "Filter multi-plane format" << *it; | ||||
451 | it = formats.erase(it); | ||||
452 | it--; | ||||
453 | break; | ||||
454 | } | ||||
455 | } | ||||
456 | it++; | ||||
457 | } | ||||
458 | } | ||||
459 | | ||||
460 | void LinuxDmabuf::setSupportedFormatsAndModifiers() | ||||
461 | { | ||||
462 | const EGLDisplay eglDisplay = m_backend->eglDisplay(); | ||||
463 | EGLint count = 0; | ||||
464 | EGLBoolean success = eglQueryDmaBufFormatsEXT(eglDisplay, 0, NULL, &count); | ||||
465 | | ||||
466 | if (!success || count == 0) { | ||||
467 | return; | ||||
468 | } | ||||
469 | | ||||
470 | QVector<uint32_t> formats(count); | ||||
471 | if (!eglQueryDmaBufFormatsEXT(eglDisplay, count, (EGLint *) formats.data(), &count)) { | ||||
472 | return; | ||||
473 | } | ||||
474 | | ||||
475 | filterFormatsWithMultiplePlanes(formats); | ||||
476 | | ||||
477 | QHash<uint32_t, QSet<uint64_t> > set; | ||||
478 | | ||||
479 | for (auto format : qAsConst(formats)) { | ||||
480 | if (eglQueryDmaBufModifiersEXT != nullptr) { | ||||
481 | count = 0; | ||||
482 | success = eglQueryDmaBufModifiersEXT(eglDisplay, format, 0, NULL, NULL, &count); | ||||
483 | | ||||
484 | if (success && count > 0) { | ||||
485 | QVector<uint64_t> modifiers(count); | ||||
486 | if (eglQueryDmaBufModifiersEXT(eglDisplay, | ||||
487 | format, count, modifiers.data(), | ||||
488 | NULL, &count)) { | ||||
489 | QSet<uint64_t> modifiersSet; | ||||
490 | for (auto mod : qAsConst(modifiers)) { | ||||
491 | modifiersSet.insert(mod); | ||||
492 | } | ||||
493 | set.insert(format, modifiersSet); | ||||
494 | continue; | ||||
495 | } | ||||
496 | } | ||||
497 | } | ||||
498 | set.insert(format, QSet<uint64_t>()); | ||||
499 | } | ||||
500 | | ||||
501 | m_interface->setSupportedFormatsWithModifiers(set); | ||||
502 | } | ||||
503 | | ||||
504 | } |