Changeset View
Standalone View
platformsupport/scenes/opengl/abstract_egl_backend.cpp
Show All 31 Lines | |||||
32 | #include <logging.h> | 32 | #include <logging.h> | ||
33 | #include <kwinglplatform.h> | 33 | #include <kwinglplatform.h> | ||
34 | #include <kwinglutils.h> | 34 | #include <kwinglutils.h> | ||
35 | // Qt | 35 | // Qt | ||
36 | #include <QOpenGLContext> | 36 | #include <QOpenGLContext> | ||
37 | #include <QOpenGLFramebufferObject> | 37 | #include <QOpenGLFramebufferObject> | ||
38 | 38 | | |||
39 | #include <memory> | 39 | #include <memory> | ||
40 | #include <unistd.h> | ||||
40 | 41 | | |||
41 | namespace KWin | 42 | namespace KWin | ||
42 | { | 43 | { | ||
43 | 44 | | |||
44 | typedef GLboolean(*eglBindWaylandDisplayWL_func)(EGLDisplay dpy, wl_display *display); | 45 | typedef GLboolean(*eglBindWaylandDisplayWL_func)(EGLDisplay dpy, wl_display *display); | ||
45 | typedef GLboolean(*eglUnbindWaylandDisplayWL_func)(EGLDisplay dpy, wl_display *display); | 46 | typedef GLboolean(*eglUnbindWaylandDisplayWL_func)(EGLDisplay dpy, wl_display *display); | ||
46 | typedef GLboolean(*eglQueryWaylandBufferWL_func)(EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); | 47 | typedef GLboolean(*eglQueryWaylandBufferWL_func)(EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); | ||
47 | eglBindWaylandDisplayWL_func eglBindWaylandDisplayWL = nullptr; | 48 | eglBindWaylandDisplayWL_func eglBindWaylandDisplayWL = nullptr; | ||
48 | eglUnbindWaylandDisplayWL_func eglUnbindWaylandDisplayWL = nullptr; | 49 | eglUnbindWaylandDisplayWL_func eglUnbindWaylandDisplayWL = nullptr; | ||
49 | eglQueryWaylandBufferWL_func eglQueryWaylandBufferWL = nullptr; | 50 | eglQueryWaylandBufferWL_func eglQueryWaylandBufferWL = nullptr; | ||
50 | 51 | | |||
52 | typedef EGLBoolean (*eglQueryDmaBufFormatsEXT_func) (EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats); | ||||
53 | typedef EGLBoolean (*eglQueryDmaBufModifiersEXT_func) (EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers); | ||||
54 | eglQueryDmaBufFormatsEXT_func eglQueryDmaBufFormatsEXT = nullptr; | ||||
55 | eglQueryDmaBufModifiersEXT_func eglQueryDmaBufModifiersEXT = nullptr; | ||||
56 | | ||||
51 | #ifndef EGL_WAYLAND_BUFFER_WL | 57 | #ifndef EGL_WAYLAND_BUFFER_WL | ||
52 | #define EGL_WAYLAND_BUFFER_WL 0x31D5 | 58 | #define EGL_WAYLAND_BUFFER_WL 0x31D5 | ||
53 | #endif | 59 | #endif | ||
54 | #ifndef EGL_WAYLAND_PLANE_WL | 60 | #ifndef EGL_WAYLAND_PLANE_WL | ||
55 | #define EGL_WAYLAND_PLANE_WL 0x31D6 | 61 | #define EGL_WAYLAND_PLANE_WL 0x31D6 | ||
56 | #endif | 62 | #endif | ||
57 | #ifndef EGL_WAYLAND_Y_INVERTED_WL | 63 | #ifndef EGL_WAYLAND_Y_INVERTED_WL | ||
58 | #define EGL_WAYLAND_Y_INVERTED_WL 0x31DB | 64 | #define EGL_WAYLAND_Y_INVERTED_WL 0x31DB | ||
59 | #endif | 65 | #endif | ||
60 | 66 | | |||
67 | #ifndef EGL_EXT_image_dma_buf_import | ||||
68 | #define EGL_LINUX_DMA_BUF_EXT 0x3270 | ||||
69 | #define EGL_LINUX_DRM_FOURCC_EXT 0x3271 | ||||
70 | #define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272 | ||||
71 | #define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273 | ||||
72 | #define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274 | ||||
73 | #define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275 | ||||
74 | #define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276 | ||||
75 | #define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277 | ||||
76 | #define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278 | ||||
77 | #define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279 | ||||
78 | #define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A | ||||
79 | #define EGL_YUV_COLOR_SPACE_HINT_EXT 0x327B | ||||
80 | #define EGL_SAMPLE_RANGE_HINT_EXT 0x327C | ||||
81 | #define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D | ||||
82 | #define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E | ||||
83 | #define EGL_ITU_REC601_EXT 0x327F | ||||
84 | #define EGL_ITU_REC709_EXT 0x3280 | ||||
85 | #define EGL_ITU_REC2020_EXT 0x3281 | ||||
86 | #define EGL_YUV_FULL_RANGE_EXT 0x3282 | ||||
87 | #define EGL_YUV_NARROW_RANGE_EXT 0x3283 | ||||
88 | #define EGL_YUV_CHROMA_SITING_0_EXT 0x3284 | ||||
89 | #define EGL_YUV_CHROMA_SITING_0_5_EXT 0x3285 | ||||
90 | #endif // EGL_EXT_image_dma_buf_import | ||||
91 | | ||||
92 | #ifndef EGL_EXT_image_dma_buf_import_modifiers | ||||
93 | #define EGL_DMA_BUF_PLANE3_FD_EXT 0x3440 | ||||
94 | #define EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441 | ||||
95 | #define EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442 | ||||
96 | #define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443 | ||||
97 | #define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444 | ||||
98 | #define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445 | ||||
99 | #define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446 | ||||
100 | #define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447 | ||||
101 | #define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448 | ||||
102 | #define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449 | ||||
103 | #define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A | ||||
104 | #endif // EGL_EXT_image_dma_buf_import_modifiers | ||||
105 | | ||||
61 | AbstractEglBackend::AbstractEglBackend() | 106 | AbstractEglBackend::AbstractEglBackend() | ||
62 | : QObject(nullptr) | 107 | : QObject(nullptr) | ||
63 | , OpenGLBackend() | 108 | , OpenGLBackend() | ||
64 | { | 109 | { | ||
65 | connect(Compositor::self(), &Compositor::aboutToDestroy, this, &AbstractEglBackend::unbindWaylandDisplay); | 110 | connect(Compositor::self(), &Compositor::aboutToDestroy, this, &AbstractEglBackend::unbindWaylandDisplay); | ||
66 | } | 111 | } | ||
67 | 112 | | |||
68 | AbstractEglBackend::~AbstractEglBackend() = default; | 113 | AbstractEglBackend::~AbstractEglBackend() | ||
114 | { | ||||
115 | for (auto *dmabuf : qAsConst(m_dmabufBuffers)) { | ||||
116 | dmabuf->destroyImage(); | ||||
117 | } | ||||
anthonyfieroni: Call delete dmabuf will have same effect. | |||||
No, it will not. It will leave a dangling pointer in the wl_resource, which will result in a double-free when the client deletes the buffer. Or a segfault the next time it tries to attach the buffer to a surface. I will expand on this in a separate comment. fredrik: No, it will not. It will leave a dangling pointer in the wl_resource, which will result in a… | |||||
118 | } | ||||
69 | 119 | | |||
70 | void AbstractEglBackend::unbindWaylandDisplay() | 120 | void AbstractEglBackend::unbindWaylandDisplay() | ||
71 | { | 121 | { | ||
72 | if (eglUnbindWaylandDisplayWL && m_display != EGL_NO_DISPLAY) { | 122 | if (eglUnbindWaylandDisplayWL && m_display != EGL_NO_DISPLAY) { | ||
73 | eglUnbindWaylandDisplayWL(m_display, *(WaylandServer::self()->display())); | 123 | eglUnbindWaylandDisplayWL(m_display, *(WaylandServer::self()->display())); | ||
74 | } | 124 | } | ||
75 | } | 125 | } | ||
76 | 126 | | |||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Line(s) | 213 | if (waylandServer()->display()->eglDisplay() != eglDisplay()) { | |||
164 | if (!eglBindWaylandDisplayWL(eglDisplay(), *(WaylandServer::self()->display()))) { | 214 | if (!eglBindWaylandDisplayWL(eglDisplay(), *(WaylandServer::self()->display()))) { | ||
165 | eglUnbindWaylandDisplayWL = nullptr; | 215 | eglUnbindWaylandDisplayWL = nullptr; | ||
166 | eglQueryWaylandBufferWL = nullptr; | 216 | eglQueryWaylandBufferWL = nullptr; | ||
167 | } else { | 217 | } else { | ||
168 | waylandServer()->display()->setEglDisplay(eglDisplay()); | 218 | waylandServer()->display()->setEglDisplay(eglDisplay()); | ||
169 | } | 219 | } | ||
170 | } | 220 | } | ||
171 | } | 221 | } | ||
222 | | ||||
223 | if (hasExtension(QByteArrayLiteral("EGL_EXT_image_dma_buf_import_modifiers"))) { | ||||
224 | eglQueryDmaBufFormatsEXT = (eglQueryDmaBufFormatsEXT_func) eglGetProcAddress("eglQueryDmaBufFormatsEXT"); | ||||
225 | eglQueryDmaBufModifiersEXT = (eglQueryDmaBufModifiersEXT_func) eglGetProcAddress("eglQueryDmaBufModifiersEXT"); | ||||
226 | } | ||||
227 | | ||||
228 | m_haveDmabufImport = hasExtension(QByteArrayLiteral("EGL_EXT_image_dma_buf_import")); | ||||
172 | } | 229 | } | ||
173 | 230 | | |||
174 | void AbstractEglBackend::initClientExtensions() | 231 | void AbstractEglBackend::initClientExtensions() | ||
175 | { | 232 | { | ||
176 | // Get the list of client extensions | 233 | // Get the list of client extensions | ||
177 | const char* clientExtensionsCString = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); | 234 | const char* clientExtensionsCString = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); | ||
178 | const QByteArray clientExtensionsString = QByteArray::fromRawData(clientExtensionsCString, qstrlen(clientExtensionsCString)); | 235 | const QByteArray clientExtensionsString = QByteArray::fromRawData(clientExtensionsCString, qstrlen(clientExtensionsCString)); | ||
179 | if (clientExtensionsString.isEmpty()) { | 236 | if (clientExtensionsString.isEmpty()) { | ||
▲ Show 20 Lines • Show All 133 Lines • ▼ Show 20 Line(s) | |||||
313 | } | 370 | } | ||
314 | 371 | | |||
315 | void AbstractEglBackend::setSurface(const EGLSurface &surface) | 372 | void AbstractEglBackend::setSurface(const EGLSurface &surface) | ||
316 | { | 373 | { | ||
317 | m_surface = surface; | 374 | m_surface = surface; | ||
318 | kwinApp()->platform()->setSceneEglSurface(surface); | 375 | kwinApp()->platform()->setSceneEglSurface(surface); | ||
319 | } | 376 | } | ||
320 | 377 | | |||
378 | void AbstractEglBackend::removeDmabufBuffer(EglDmabufBuffer *buffer) | ||||
Name should be more descriptive in relation to functionality, also it's not a signal, so "aboutTo" imo not recommended. Suggestion: removeDmabufBuffer romangg: Name should be more descriptive in relation to functionality, also it's not a signal, so… | |||||
379 | { | ||||
380 | m_dmabufBuffers.remove(buffer); | ||||
381 | } | ||||
382 | | ||||
383 | QVector<uint32_t> AbstractEglBackend::supportedDrmFormats() | ||||
384 | { | ||||
385 | if (!m_haveDmabufImport || eglQueryDmaBufFormatsEXT == nullptr) | ||||
386 | return QVector<uint32_t>(); | ||||
387 | | ||||
388 | EGLint count = 0; | ||||
389 | EGLBoolean success = eglQueryDmaBufFormatsEXT(m_display, 0, NULL, &count); | ||||
390 | | ||||
391 | if (success && count > 0) { | ||||
392 | QVector<uint32_t> formats(count); | ||||
393 | if (eglQueryDmaBufFormatsEXT(m_display, count, (EGLint *) formats.data(), &count)) { | ||||
394 | return formats; | ||||
395 | } | ||||
396 | } | ||||
397 | | ||||
398 | return QVector<uint32_t>(); | ||||
399 | } | ||||
400 | | ||||
401 | QVector<uint64_t> AbstractEglBackend::supportedDrmModifiers(uint32_t format) | ||||
402 | { | ||||
403 | if (!m_haveDmabufImport || eglQueryDmaBufModifiersEXT == nullptr) | ||||
404 | return QVector<uint64_t>(); | ||||
405 | | ||||
406 | EGLint count = 0; | ||||
407 | EGLBoolean success = eglQueryDmaBufModifiersEXT(m_display, format, 0, NULL, NULL, &count); | ||||
408 | | ||||
409 | if (success && count > 0) { | ||||
410 | QVector<uint64_t> modifiers(count); | ||||
411 | if (eglQueryDmaBufModifiersEXT(m_display, format, count, modifiers.data(), NULL, &count)) { | ||||
412 | return modifiers; | ||||
413 | } | ||||
414 | } | ||||
415 | | ||||
416 | return QVector<uint64_t>(); | ||||
417 | } | ||||
418 | | ||||
419 | KWayland::Server::LinuxDmabuf::Buffer *AbstractEglBackend::importDmabufBuffer(const QVector<KWayland::Server::LinuxDmabuf::Plane> &planes, | ||||
420 | uint32_t format, | ||||
421 | const QSize &size, | ||||
422 | KWayland::Server::LinuxDmabuf::Flags flags) | ||||
423 | { | ||||
424 | if (!m_haveDmabufImport) | ||||
425 | return nullptr; | ||||
426 | | ||||
427 | // FIXME: Add support for multi-planar images | ||||
zzag: What's holding us from doing that? | |||||
We would need to create a separate EGL image and a separate texture for each plane. fredrik: We would need to create a separate EGL image and a separate texture for each plane.
The scene… | |||||
Thanks for the explanation @fredrik. It wasn't clear to me how multi-planes buffers are handled (also that it's the same notion as for hw-planes is annoying!). Until we support multi-plane buffers shouldn't we then filter out all multi-plane formats in the supportedFormats call such that the client does not even try to use these instead of just failing with null here? romangg: Thanks for the explanation @fredrik. It wasn't clear to me how multi-planes buffers are handled… | |||||
428 | if (planes.count() != 1) | ||||
429 | return nullptr; | ||||
430 | | ||||
431 | const EGLint attribs[] = { | ||||
432 | EGL_WIDTH, size.width(), | ||||
433 | EGL_HEIGHT, size.height(), | ||||
434 | EGL_LINUX_DRM_FOURCC_EXT, EGLint(format), | ||||
435 | EGL_DMA_BUF_PLANE0_FD_EXT, planes[0].fd, | ||||
436 | EGL_DMA_BUF_PLANE0_OFFSET_EXT, EGLint(planes[0].offset), | ||||
437 | EGL_DMA_BUF_PLANE0_PITCH_EXT, EGLint(planes[0].stride), | ||||
438 | EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, EGLint(planes[0].modifier & 0xffffffff), | ||||
439 | EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, EGLint(planes[0].modifier >> 32), | ||||
Perhaps we need to add modifier only if EGL_EXT_image_dma_buf_import_modifiers is present. zzag: Perhaps we need to add modifier only if EGL_EXT_image_dma_buf_import_modifiers is present. | |||||
440 | EGL_NONE | ||||
441 | }; | ||||
442 | | ||||
443 | // Note that the EGLImage does NOT take onwership of the file descriptors | ||||
444 | EGLImage image = eglCreateImageKHR(m_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, (EGLClientBuffer) nullptr, attribs); | ||||
445 | if (image == EGL_NO_IMAGE_KHR) | ||||
446 | return nullptr; | ||||
447 | | ||||
448 | EglDmabufBuffer *buffer = new EglDmabufBuffer(image, planes, format, size, flags, this); | ||||
449 | | ||||
450 | // We track imported buffers so we can clean up the EGL images | ||||
451 | // from the AbstractEglBackend destructor. | ||||
452 | m_dmabufBuffers.insert(buffer); | ||||
453 | | ||||
454 | return buffer; | ||||
455 | } | ||||
456 | | ||||
321 | AbstractEglTexture::AbstractEglTexture(SceneOpenGLTexture *texture, AbstractEglBackend *backend) | 457 | AbstractEglTexture::AbstractEglTexture(SceneOpenGLTexture *texture, AbstractEglBackend *backend) | ||
322 | : SceneOpenGLTexturePrivate() | 458 | : SceneOpenGLTexturePrivate() | ||
323 | , q(texture) | 459 | , q(texture) | ||
324 | , m_backend(backend) | 460 | , m_backend(backend) | ||
325 | , m_image(EGL_NO_IMAGE_KHR) | 461 | , m_image(EGL_NO_IMAGE_KHR) | ||
326 | { | 462 | { | ||
327 | m_target = GL_TEXTURE_2D; | 463 | m_target = GL_TEXTURE_2D; | ||
328 | } | 464 | } | ||
Show All 18 Lines | 482 | if (updateFromFBO(pixmap->fbo())) { | |||
347 | return true; | 483 | return true; | ||
348 | } | 484 | } | ||
349 | return false; | 485 | return false; | ||
350 | } | 486 | } | ||
351 | // try Wayland loading | 487 | // try Wayland loading | ||
352 | if (auto s = pixmap->surface()) { | 488 | if (auto s = pixmap->surface()) { | ||
353 | s->resetTrackedDamage(); | 489 | s->resetTrackedDamage(); | ||
354 | } | 490 | } | ||
355 | if (buffer->shmBuffer()) { | 491 | if (buffer->linuxDmabufBuffer()) { | ||
492 | return loadDmabufTexture(buffer); | ||||
493 | } else if (buffer->shmBuffer()) { | ||||
356 | return loadShmTexture(buffer); | 494 | return loadShmTexture(buffer); | ||
357 | } else { | | |||
358 | return loadEglTexture(buffer); | | |||
359 | } | 495 | } | ||
496 | return loadEglTexture(buffer); | ||||
360 | } | 497 | } | ||
361 | 498 | | |||
362 | void AbstractEglTexture::updateTexture(WindowPixmap *pixmap) | 499 | void AbstractEglTexture::updateTexture(WindowPixmap *pixmap) | ||
363 | { | 500 | { | ||
364 | const auto &buffer = pixmap->buffer(); | 501 | const auto &buffer = pixmap->buffer(); | ||
365 | if (buffer.isNull()) { | 502 | if (buffer.isNull()) { | ||
366 | const auto &fbo = pixmap->fbo(); | 503 | const auto &fbo = pixmap->fbo(); | ||
367 | if (!fbo.isNull()) { | 504 | if (!fbo.isNull()) { | ||
368 | if (m_texture != fbo->texture()) { | 505 | if (m_texture != fbo->texture()) { | ||
369 | updateFromFBO(fbo); | 506 | updateFromFBO(fbo); | ||
370 | } | 507 | } | ||
371 | return; | 508 | return; | ||
372 | } | 509 | } | ||
373 | return; | 510 | return; | ||
374 | } | 511 | } | ||
375 | auto s = pixmap->surface(); | 512 | auto s = pixmap->surface(); | ||
513 | if (EglDmabufBuffer *dmabuf = static_cast<EglDmabufBuffer *>(buffer->linuxDmabufBuffer())) { | ||||
514 | q->bind(); | ||||
515 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES) dmabuf->image()); | ||||
516 | q->unbind(); | ||||
517 | if (m_image != EGL_NO_IMAGE_KHR) { | ||||
518 | eglDestroyImageKHR(m_backend->eglDisplay(), m_image); | ||||
519 | } | ||||
520 | m_image = EGL_NO_IMAGE_KHR; // The wl_buffer has ownership of the image | ||||
521 | // The origin in a dmabuf-buffer is at the upper-left corner, so the meaning | ||||
522 | // of Y-inverted is the inverse of OpenGL. | ||||
523 | const bool yInverted = !(dmabuf->flags() & KWayland::Server::LinuxDmabuf::YInverted); | ||||
524 | if (m_size != dmabuf->size() || yInverted != q->isYInverted()) { | ||||
525 | m_size = dmabuf->size(); | ||||
526 | q->setYInverted(yInverted); | ||||
527 | } | ||||
528 | if (s) { | ||||
529 | s->resetTrackedDamage(); | ||||
530 | } | ||||
531 | return; | ||||
532 | } | ||||
376 | if (!buffer->shmBuffer()) { | 533 | if (!buffer->shmBuffer()) { | ||
377 | q->bind(); | 534 | q->bind(); | ||
378 | EGLImageKHR image = attach(buffer); | 535 | EGLImageKHR image = attach(buffer); | ||
379 | q->unbind(); | 536 | q->unbind(); | ||
380 | if (image != EGL_NO_IMAGE_KHR) { | 537 | if (image != EGL_NO_IMAGE_KHR) { | ||
538 | if (m_image != EGL_NO_IMAGE_KHR) { | ||||
381 | eglDestroyImageKHR(m_backend->eglDisplay(), m_image); | 539 | eglDestroyImageKHR(m_backend->eglDisplay(), m_image); | ||
540 | } | ||||
romangg: rm | |||||
romangg: Nope, better not. Overlooked the `m_`. | |||||
382 | m_image = image; | 541 | m_image = image; | ||
383 | } | 542 | } | ||
384 | if (s) { | 543 | if (s) { | ||
385 | s->resetTrackedDamage(); | 544 | s->resetTrackedDamage(); | ||
386 | } | 545 | } | ||
387 | return; | 546 | return; | ||
388 | } | 547 | } | ||
389 | // shm fallback | 548 | // shm fallback | ||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Line(s) | 657 | if (EGL_NO_IMAGE_KHR == m_image) { | |||
499 | qCDebug(KWIN_OPENGL) << "failed to create egl image"; | 658 | qCDebug(KWIN_OPENGL) << "failed to create egl image"; | ||
500 | q->discard(); | 659 | q->discard(); | ||
501 | return false; | 660 | return false; | ||
502 | } | 661 | } | ||
503 | 662 | | |||
504 | return true; | 663 | return true; | ||
505 | } | 664 | } | ||
506 | 665 | | |||
666 | bool AbstractEglTexture::loadDmabufTexture(const QPointer< KWayland::Server::BufferInterface > &buffer) | ||||
667 | { | ||||
668 | EglDmabufBuffer *dmabuf = static_cast<EglDmabufBuffer *>(buffer->linuxDmabufBuffer()); | ||||
669 | if (!dmabuf || dmabuf->image() == EGL_NO_IMAGE_KHR) { | ||||
670 | qCritical(KWIN_OPENGL) << "Invalid dmabuf-based wl_buffer"; | ||||
671 | q->discard(); | ||||
672 | return false; | ||||
673 | } | ||||
674 | | ||||
675 | assert(m_image == EGL_NO_IMAGE_KHR); | ||||
676 | | ||||
677 | glGenTextures(1, &m_texture); | ||||
678 | q->setWrapMode(GL_CLAMP_TO_EDGE); | ||||
679 | q->setFilter(GL_NEAREST); | ||||
680 | q->bind(); | ||||
681 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES) dmabuf->image()); | ||||
682 | q->unbind(); | ||||
683 | | ||||
684 | m_size = dmabuf->size(); | ||||
685 | q->setYInverted(!(dmabuf->flags() & KWayland::Server::LinuxDmabuf::YInverted)); | ||||
686 | | ||||
687 | return true; | ||||
688 | } | ||||
689 | | ||||
507 | EGLImageKHR AbstractEglTexture::attach(const QPointer< KWayland::Server::BufferInterface > &buffer) | 690 | EGLImageKHR AbstractEglTexture::attach(const QPointer< KWayland::Server::BufferInterface > &buffer) | ||
508 | { | 691 | { | ||
509 | EGLint format, yInverted; | 692 | EGLint format, yInverted; | ||
510 | eglQueryWaylandBufferWL(m_backend->eglDisplay(), buffer->resource(), EGL_TEXTURE_FORMAT, &format); | 693 | eglQueryWaylandBufferWL(m_backend->eglDisplay(), buffer->resource(), EGL_TEXTURE_FORMAT, &format); | ||
511 | if (format != EGL_TEXTURE_RGB && format != EGL_TEXTURE_RGBA) { | 694 | if (format != EGL_TEXTURE_RGB && format != EGL_TEXTURE_RGBA) { | ||
512 | qCDebug(KWIN_OPENGL) << "Unsupported texture format: " << format; | 695 | qCDebug(KWIN_OPENGL) << "Unsupported texture format: " << format; | ||
513 | return EGL_NO_IMAGE_KHR; | 696 | return EGL_NO_IMAGE_KHR; | ||
514 | } | 697 | } | ||
Show All 26 Lines | 719 | { | |||
541 | m_size = fbo->size(); | 724 | m_size = fbo->size(); | ||
542 | q->setWrapMode(GL_CLAMP_TO_EDGE); | 725 | q->setWrapMode(GL_CLAMP_TO_EDGE); | ||
543 | q->setFilter(GL_LINEAR); | 726 | q->setFilter(GL_LINEAR); | ||
544 | q->setYInverted(false); | 727 | q->setYInverted(false); | ||
545 | updateMatrix(); | 728 | updateMatrix(); | ||
546 | return true; | 729 | return true; | ||
547 | } | 730 | } | ||
548 | 731 | | |||
732 | EglDmabufBuffer::EglDmabufBuffer(EGLImage image, | ||||
733 | const QVector<Plane> &planes, | ||||
734 | uint32_t format, | ||||
735 | const QSize &size, | ||||
736 | Flags flags, | ||||
737 | AbstractEglBackend *backend) | ||||
738 | : KWayland::Server::LinuxDmabuf::Buffer(format, size), | ||||
anthonyfieroni: This function is useless. | |||||
739 | m_backend(backend), | ||||
740 | m_image(image), | ||||
741 | m_planes(planes), | ||||
742 | m_flags(flags) | ||||
743 | { | ||||
744 | } | ||||
745 | | ||||
746 | EglDmabufBuffer::~EglDmabufBuffer() | ||||
747 | { | ||||
748 | if (m_backend) { | ||||
749 | m_backend->removeDmabufBuffer(this); | ||||
750 | | ||||
751 | assert(m_image != EGL_NO_IMAGE_KHR); | ||||
752 | eglDestroyImageKHR(m_backend->eglDisplay(), m_image); | ||||
753 | } | ||||
754 | | ||||
755 | // Close all open file descriptors | ||||
756 | for (int i = 0; i < m_planes.count(); i++) { | ||||
757 | if (m_planes[i].fd != -1) | ||||
758 | ::close(m_planes[i].fd); | ||||
759 | m_planes[i].fd = -1; | ||||
760 | } | ||||
761 | } | ||||
762 | | ||||
763 | void EglDmabufBuffer::destroyImage() | ||||
764 | { | ||||
765 | assert(m_image != EGL_NO_IMAGE_KHR); | ||||
766 | eglDestroyImageKHR(m_backend->eglDisplay(), m_image); | ||||
767 | m_image = EGL_NO_IMAGE_KHR; | ||||
768 | m_backend = nullptr; | ||||
769 | } | ||||
770 | | ||||
549 | } | 771 | } | ||
550 | 772 | |
Call delete dmabuf will have same effect.