diff --git a/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp b/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp index 575526fa30..83b8d37752 100644 --- a/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp +++ b/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp @@ -177,78 +177,37 @@ void AbstractEglBackend::initWayland() } } - if (hasExtension(QByteArrayLiteral("EGL_EXT_image_dma_buf_import")) && hasExtension(QByteArrayLiteral("EGL_EXT_image_dma_buf_import_modifiers"))) { - eglQueryDmaBufFormatsEXT = (eglQueryDmaBufFormatsEXT_func)eglGetProcAddress("eglQueryDmaBufFormatsEXT"); - eglQueryDmaBufModifiersEXT = (eglQueryDmaBufModifiersEXT_func)eglGetProcAddress("eglQueryDmaBufModifiersEXT"); - - EGLint count = 0; - EGLBoolean success = eglQueryDmaBufFormatsEXT(m_display, 0, nullptr, &count); - - if (!success || count == 0) { - qCCritical(KWIN_OPENGL) << "eglQueryDmaBufFormatsEXT failed:" << getEglErrorString(); - return; - } - - QVector formats(count); - if (!eglQueryDmaBufFormatsEXT(m_display, count, (EGLint *)formats.data(), &count)) { - qCCritical(KWIN_OPENGL) << "eglQueryDmaBufFormatsEXT with count" << count << "failed:" << getEglErrorString(); - return; - } - - for (auto format : std::as_const(formats)) { - EGLint count = 0; - const EGLBoolean success = eglQueryDmaBufModifiersEXT(m_display, format, 0, nullptr, nullptr, &count); - if (success && count > 0) { - QVector modifiers(count); - QVector externalOnly(count); - if (eglQueryDmaBufModifiersEXT(m_display, format, count, modifiers.data(), externalOnly.data(), &count)) { - for (int i = modifiers.size() - 1; i >= 0; i--) { - if (externalOnly[i]) { - modifiers.remove(i); - externalOnly.remove(i); - } - } - if (!modifiers.empty()) { - m_supportedFormats.insert(format, modifiers); - } - continue; - } + auto filterFormats = [this](int bpc) { + const auto formats = m_display->supportedDrmFormats(); + QHash> set; + for (auto it = formats.constBegin(); it != formats.constEnd(); it++) { + if (bpcForFormat(it.key()) == bpc) { + set.insert(it.key(), it.value()); } - m_supportedFormats.insert(format, {DRM_FORMAT_MOD_INVALID}); - } - qCDebug(KWIN_OPENGL) << "EGL driver advertises" << m_supportedFormats.count() << "supported dmabuf formats"; - - auto filterFormats = [this](int bpc) { - QHash> set; - for (auto it = m_supportedFormats.constBegin(); it != m_supportedFormats.constEnd(); it++) { - if (bpcForFormat(it.key()) == bpc) { - set.insert(it.key(), it.value()); - } - } - return set; - }; - if (prefer10bpc()) { - m_tranches.append({ - .device = deviceId(), - .flags = {}, - .formatTable = filterFormats(10), - }); } + return set; + }; + if (prefer10bpc()) { m_tranches.append({ .device = deviceId(), .flags = {}, - .formatTable = filterFormats(8), + .formatTable = filterFormats(10), }); - m_tranches.append({ - .device = deviceId(), - .flags = {}, - .formatTable = filterFormats(-1), - }); - - KWaylandServer::LinuxDmaBufV1ClientBufferIntegration *dmabuf = waylandServer()->linuxDmabuf(); - dmabuf->setRenderBackend(this); - dmabuf->setSupportedFormatsWithModifiers(m_tranches); } + m_tranches.append({ + .device = deviceId(), + .flags = {}, + .formatTable = filterFormats(8), + }); + m_tranches.append({ + .device = deviceId(), + .flags = {}, + .formatTable = filterFormats(-1), + }); + + KWaylandServer::LinuxDmaBufV1ClientBufferIntegration *dmabuf = waylandServer()->linuxDmabuf(); + dmabuf->setRenderBackend(this); + dmabuf->setSupportedFormatsWithModifiers(m_tranches); } void AbstractEglBackend::initClientExtensions() @@ -353,7 +312,7 @@ bool AbstractEglBackend::testImportBuffer(KWaylandServer::LinuxDmaBufV1ClientBuf QHash> AbstractEglBackend::supportedFormats() const { - return m_supportedFormats; + return m_display->supportedDrmFormats(); } ::EGLDisplay AbstractEglBackend::eglDisplay() const diff --git a/src/platformsupport/scenes/opengl/abstract_egl_backend.h b/src/platformsupport/scenes/opengl/abstract_egl_backend.h index cafcc15fd6..967135e282 100644 --- a/src/platformsupport/scenes/opengl/abstract_egl_backend.h +++ b/src/platformsupport/scenes/opengl/abstract_egl_backend.h @@ -47,7 +47,7 @@ public: { return &m_functions; } - EGLDisplay eglDisplay() const; + ::EGLDisplay eglDisplay() const; ::EGLContext context() const; EGLSurface surface() const; EGLConfig config() const; @@ -92,7 +92,6 @@ private: QList m_clientExtensions; const dev_t m_deviceId; QVector m_tranches; - QHash> m_supportedFormats; QHash m_importedBuffers; }; diff --git a/src/platformsupport/scenes/opengl/egldisplay.cpp b/src/platformsupport/scenes/opengl/egldisplay.cpp index 257abe7961..50c8264462 100644 --- a/src/platformsupport/scenes/opengl/egldisplay.cpp +++ b/src/platformsupport/scenes/opengl/egldisplay.cpp @@ -76,6 +76,7 @@ EglDisplay::EglDisplay(::EGLDisplay display, const QList &extensions , m_supportsBufferAge(extensions.contains(QByteArrayLiteral("EGL_EXT_buffer_age")) && qgetenv("KWIN_USE_BUFFER_AGE") != "0") , m_supportsSwapBuffersWithDamage(extensions.contains(QByteArrayLiteral("EGL_EXT_swap_buffers_with_damage"))) , m_supportsNativeFence(extensions.contains(QByteArrayLiteral("EGL_ANDROID_native_fence_sync"))) + , m_importFormats(queryImportFormats()) { } @@ -167,4 +168,64 @@ EGLImageKHR EglDisplay::importDmaBufAsImage(const DmaBufAttributes &dmabuf) cons return eglCreateImageKHR(m_handle, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attribs.data()); } + +QHash> EglDisplay::supportedDrmFormats() const +{ + return m_importFormats; +} + +QHash> EglDisplay::queryImportFormats() const +{ + if (!hasExtension(QByteArrayLiteral("EGL_EXT_image_dma_buf_import")) || !hasExtension(QByteArrayLiteral("EGL_EXT_image_dma_buf_import_modifiers"))) { + return {}; + } + + typedef EGLBoolean (*eglQueryDmaBufFormatsEXT_func)(EGLDisplay dpy, EGLint max_formats, EGLint * formats, EGLint * num_formats); + typedef EGLBoolean (*eglQueryDmaBufModifiersEXT_func)(EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR * modifiers, EGLBoolean * external_only, EGLint * num_modifiers); + eglQueryDmaBufFormatsEXT_func eglQueryDmaBufFormatsEXT = nullptr; + eglQueryDmaBufModifiersEXT_func eglQueryDmaBufModifiersEXT = nullptr; + eglQueryDmaBufFormatsEXT = (eglQueryDmaBufFormatsEXT_func)eglGetProcAddress("eglQueryDmaBufFormatsEXT"); + eglQueryDmaBufModifiersEXT = (eglQueryDmaBufModifiersEXT_func)eglGetProcAddress("eglQueryDmaBufModifiersEXT"); + if (eglQueryDmaBufFormatsEXT == nullptr) { + return {}; + } + + EGLint count = 0; + EGLBoolean success = eglQueryDmaBufFormatsEXT(m_handle, 0, nullptr, &count); + if (!success || count == 0) { + qCCritical(KWIN_OPENGL) << "eglQueryDmaBufFormatsEXT failed!" << getEglErrorString(); + return {}; + } + QVector formats(count); + if (!eglQueryDmaBufFormatsEXT(m_handle, count, (EGLint *)formats.data(), &count)) { + qCCritical(KWIN_OPENGL) << "eglQueryDmaBufFormatsEXT with count" << count << "failed!" << getEglErrorString(); + return {}; + } + QHash> ret; + for (const auto format : std::as_const(formats)) { + if (eglQueryDmaBufModifiersEXT != nullptr) { + EGLint count = 0; + const EGLBoolean success = eglQueryDmaBufModifiersEXT(m_handle, format, 0, nullptr, nullptr, &count); + if (success && count > 0) { + QVector modifiers(count); + QVector externalOnly(count); + if (eglQueryDmaBufModifiersEXT(m_handle, format, count, modifiers.data(), nullptr, &count)) { + for (int i = modifiers.size() - 1; i >= 0; i--) { + if (externalOnly[i]) { + modifiers.remove(i); + externalOnly.remove(i); + } + } + if (!modifiers.empty()) { + ret.insert(format, modifiers); + } + continue; + } + } + } + ret.insert(format, {DRM_FORMAT_MOD_INVALID}); + } + return ret; +} + } diff --git a/src/platformsupport/scenes/opengl/egldisplay.h b/src/platformsupport/scenes/opengl/egldisplay.h index b9f291eafc..183a6a3324 100644 --- a/src/platformsupport/scenes/opengl/egldisplay.h +++ b/src/platformsupport/scenes/opengl/egldisplay.h @@ -11,6 +11,7 @@ #include "kwin_export.h" #include +#include #include #include @@ -33,12 +34,15 @@ public: bool supportsBufferAge() const; bool supportsSwapBuffersWithDamage() const; bool supportsNativeFence() const; + QHash> supportedDrmFormats() const; EGLImageKHR importDmaBufAsImage(const DmaBufAttributes &dmabuf) const; static std::unique_ptr create(::EGLDisplay display, bool owning = true); private: + QHash> queryImportFormats() const; + const ::EGLDisplay m_handle; const QList m_extensions; const bool m_owning; @@ -46,6 +50,7 @@ private: const bool m_supportsBufferAge; const bool m_supportsSwapBuffersWithDamage; const bool m_supportsNativeFence; + const QHash> m_importFormats; }; }