diff --git a/src/backends/drm/drm_egl_backend.cpp b/src/backends/drm/drm_egl_backend.cpp index 9e901eec19..881c45bd38 100644 --- a/src/backends/drm/drm_egl_backend.cpp +++ b/src/backends/drm/drm_egl_backend.cpp @@ -98,7 +98,7 @@ void EglGbmBackend::init() bool EglGbmBackend::initRenderingContext() { - return initBufferConfigs(eglDisplayObject()) && createContext(EGL_NO_CONFIG_KHR) && makeCurrent(); + return createContext(EGL_NO_CONFIG_KHR) && makeCurrent(); } EglDisplay *EglGbmBackend::displayForGpu(DrmGpu *gpu) @@ -132,74 +132,6 @@ EglContext *EglGbmBackend::contextForGpu(DrmGpu *gpu) return context.get(); } -bool EglGbmBackend::initBufferConfigs(EglDisplay *display) -{ - const EGLint config_attribs[] = { - EGL_SURFACE_TYPE, - EGL_WINDOW_BIT, - EGL_RED_SIZE, - 1, - EGL_GREEN_SIZE, - 1, - EGL_BLUE_SIZE, - 1, - EGL_ALPHA_SIZE, - 0, - EGL_RENDERABLE_TYPE, - isOpenGLES() ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_BIT, - EGL_CONFIG_CAVEAT, - EGL_NONE, - EGL_NONE, - }; - - EGLint count; - EGLConfig configs[1024]; - if (!eglChooseConfig(display->handle(), config_attribs, configs, - sizeof(configs) / sizeof(EGLConfig), - &count)) { - qCCritical(KWIN_DRM) << "eglChooseConfig failed:" << getEglErrorString(); - return false; - } - - // Loop through all configs, choosing the first one that has suitable format. - auto &formats = m_formats[display]; - for (EGLint i = 0; i < count; i++) { - EGLint gbmFormat; - eglGetConfigAttrib(display->handle(), configs[i], EGL_NATIVE_VISUAL_ID, &gbmFormat); - - GbmFormat format; - format.drmFormat = gbmFormat; - EGLint red, green, blue; - // Query number of bits for color channel - eglGetConfigAttrib(display->handle(), configs[i], EGL_RED_SIZE, &red); - eglGetConfigAttrib(display->handle(), configs[i], EGL_GREEN_SIZE, &green); - eglGetConfigAttrib(display->handle(), configs[i], EGL_BLUE_SIZE, &blue); - eglGetConfigAttrib(display->handle(), configs[i], EGL_ALPHA_SIZE, &format.alphaSize); - format.bpp = red + green + blue; - if (formats.contains(gbmFormat)) { - continue; - } - formats[gbmFormat] = format; - } - if (!formats.isEmpty()) { - return true; - } - - qCCritical(KWIN_DRM, "Choosing EGL config did not return a supported config. There were %u configs", count); - for (EGLint i = 0; i < count; i++) { - EGLint gbmFormat, blueSize, redSize, greenSize, alphaSize; - eglGetConfigAttrib(display->handle(), configs[i], EGL_NATIVE_VISUAL_ID, &gbmFormat); - eglGetConfigAttrib(display->handle(), configs[i], EGL_RED_SIZE, &redSize); - eglGetConfigAttrib(display->handle(), configs[i], EGL_GREEN_SIZE, &greenSize); - eglGetConfigAttrib(display->handle(), configs[i], EGL_BLUE_SIZE, &blueSize); - eglGetConfigAttrib(display->handle(), configs[i], EGL_ALPHA_SIZE, &alphaSize); - gbm_format_name_desc name; - gbm_format_get_name(gbmFormat, &name); - qCCritical(KWIN_DRM, "EGL config %d has format %s with %d,%d,%d,%d bits for r,g,b,a", i, name.name, redSize, greenSize, blueSize, alphaSize); - } - return false; -} - std::unique_ptr EglGbmBackend::createSurfaceTextureInternal(SurfacePixmapInternal *pixmap) { return std::make_unique(this, pixmap); @@ -232,22 +164,6 @@ std::pair, ColorDescription> EglGbmBackend::tex return std::make_pair(layer->texture(), layer->colorDescription()); } -std::optional EglGbmBackend::gbmFormatForDrmFormat(uint32_t format) const -{ - const auto it = m_formats.find(eglDisplayObject()); - if (it == m_formats.end()) { - return std::nullopt; - } else { - const auto &formats = *it; - const auto formatIt = formats.find(format); - if (formatIt == formats.end()) { - return std::nullopt; - } else { - return *formatIt; - } - } -} - bool EglGbmBackend::prefer10bpc() const { static bool ok = false; @@ -275,9 +191,4 @@ DrmGpu *EglGbmBackend::gpu() const return m_backend->primaryGpu(); } -bool operator==(const GbmFormat &lhs, const GbmFormat &rhs) -{ - return lhs.drmFormat == rhs.drmFormat; -} - } // namespace KWin diff --git a/src/backends/drm/drm_egl_backend.h b/src/backends/drm/drm_egl_backend.h index 3a9c610e51..8a4c926b9c 100644 --- a/src/backends/drm/drm_egl_backend.h +++ b/src/backends/drm/drm_egl_backend.h @@ -37,14 +37,6 @@ class DrmPipeline; class EglContext; class EglDisplay; -struct GbmFormat -{ - uint32_t drmFormat = 0; - uint32_t bpp; - EGLint alphaSize = -1; -}; -bool operator==(const GbmFormat &lhs, const GbmFormat &rhs); - /** * @brief OpenGL Backend using Egl on a GBM surface. */ @@ -70,7 +62,6 @@ public: std::pair, ColorDescription> textureForOutput(Output *requestedOutput) const override; - std::optional gbmFormatForDrmFormat(uint32_t format) const; DrmGpu *gpu() const; EglDisplay *displayForGpu(DrmGpu *gpu); @@ -78,13 +69,11 @@ public: private: bool initializeEgl(); - bool initBufferConfigs(EglDisplay *display); bool initRenderingContext(); EglDisplay *createEglDisplay(DrmGpu *gpu) const; DrmBackend *m_backend; std::map> m_contexts; - QHash> m_formats; friend class EglGbmTexture; }; diff --git a/src/backends/drm/drm_egl_layer_surface.cpp b/src/backends/drm/drm_egl_layer_surface.cpp index 0a74a5b8d3..cee3a2d847 100644 --- a/src/backends/drm/drm_egl_layer_surface.cpp +++ b/src/backends/drm/drm_egl_layer_surface.cpp @@ -16,6 +16,7 @@ #include "drm_gpu.h" #include "drm_logging.h" #include "platformsupport/scenes/opengl/eglnativefence.h" +#include "utils/drm_format_helper.h" #include #include @@ -203,12 +204,12 @@ bool EglGbmLayerSurface::doesSurfaceFit(const Surface &surface, const QSize &siz std::optional EglGbmLayerSurface::createSurface(const QSize &size, const QMap> &formats) const { - QVector preferredFormats; - QVector fallbackFormats; + QVector preferredFormats; + QVector fallbackFormats; for (auto it = formats.begin(); it != formats.end(); it++) { - const auto format = m_eglBackend->gbmFormatForDrmFormat(it.key()); - if (format.has_value() && format->bpp >= 24) { - if (format->bpp <= 32) { + const auto format = formatInfo(it.key()); + if (format.has_value() && format->bitsPerColor >= 8) { + if (format->bitsPerPixel <= 32) { preferredFormats.push_back(format.value()); } else { fallbackFormats.push_back(format.value()); @@ -218,18 +219,18 @@ std::optional EglGbmLayerSurface::createSurface(con const auto sort = [this](const auto &lhs, const auto &rhs) { if (lhs.drmFormat == rhs.drmFormat) { // prefer having an alpha channel - return lhs.alphaSize > rhs.alphaSize; - } else if (m_eglBackend->prefer10bpc() && ((lhs.bpp == 30) != (rhs.bpp == 30))) { + return lhs.alphaBits > rhs.alphaBits; + } else if (m_eglBackend->prefer10bpc() && ((lhs.bitsPerColor == 10) != (rhs.bitsPerColor == 10))) { // prefer 10bpc / 30bpp formats - return lhs.bpp == 30; + return lhs.bitsPerColor == 10; } else { // fallback: prefer formats with lower bandwidth requirements - return lhs.bpp < rhs.bpp; + return lhs.bitsPerPixel < rhs.bitsPerPixel; } }; - const auto doTestFormats = [this, &size, &formats](const QVector &gbmFormats, MultiGpuImportMode importMode) -> std::optional { + const auto doTestFormats = [this, &size, &formats](const QVector &gbmFormats, MultiGpuImportMode importMode) -> std::optional { for (const auto &format : gbmFormats) { - if (m_formatOption == FormatOption::RequireAlpha && format.alphaSize == 0) { + if (m_formatOption == FormatOption::RequireAlpha && format.alphaBits == 0) { continue; } const auto surface = createSurface(size, format.drmFormat, formats[format.drmFormat], importMode); @@ -239,7 +240,7 @@ std::optional EglGbmLayerSurface::createSurface(con } return std::nullopt; }; - const auto testFormats = [this, &sort, &doTestFormats](QVector &formats) -> std::optional { + const auto testFormats = [this, &sort, &doTestFormats](QVector &formats) -> std::optional { std::sort(formats.begin(), formats.end(), sort); if (m_gpu == m_eglBackend->gpu()) { return doTestFormats(formats, MultiGpuImportMode::None); diff --git a/src/core/graphicsbuffer.cpp b/src/core/graphicsbuffer.cpp index f06cb23af5..a3aed5bff6 100644 --- a/src/core/graphicsbuffer.cpp +++ b/src/core/graphicsbuffer.cpp @@ -5,6 +5,7 @@ */ #include "core/graphicsbuffer.h" +#include "utils/drm_format_helper.h" #include @@ -74,39 +75,8 @@ const ShmAttributes *GraphicsBuffer::shmAttributes() const bool GraphicsBuffer::alphaChannelFromDrmFormat(uint32_t format) { - switch (format) { - case DRM_FORMAT_ARGB4444: - case DRM_FORMAT_ABGR4444: - case DRM_FORMAT_RGBA4444: - case DRM_FORMAT_BGRA4444: - - case DRM_FORMAT_ARGB1555: - case DRM_FORMAT_ABGR1555: - case DRM_FORMAT_RGBA5551: - case DRM_FORMAT_BGRA5551: - - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_ABGR8888: - case DRM_FORMAT_RGBA8888: - case DRM_FORMAT_BGRA8888: - - case DRM_FORMAT_ARGB2101010: - case DRM_FORMAT_ABGR2101010: - case DRM_FORMAT_RGBA1010102: - case DRM_FORMAT_BGRA1010102: - - case DRM_FORMAT_XRGB8888_A8: - case DRM_FORMAT_XBGR8888_A8: - case DRM_FORMAT_RGBX8888_A8: - case DRM_FORMAT_BGRX8888_A8: - case DRM_FORMAT_RGB888_A8: - case DRM_FORMAT_BGR888_A8: - case DRM_FORMAT_RGB565_A8: - case DRM_FORMAT_BGR565_A8: - return true; - default: - return false; - } + const auto info = formatInfo(format); + return info && info->alphaBits > 0; } } // namespace KWin diff --git a/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp b/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp index 6fa62de1b2..9ff353593a 100644 --- a/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp +++ b/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp @@ -18,6 +18,7 @@ #include "libkwineffects/kwineglimagetexture.h" #include "libkwineffects/kwinglplatform.h" #include "libkwineffects/kwinglutils.h" +#include "utils/drm_format_helper.h" #include // Qt #include @@ -122,34 +123,6 @@ void AbstractEglBackend::initKWinGL() initGL(&getProcAddress); } -static int bpcForFormat(uint32_t format) -{ - switch (format) { - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_XBGR8888: - case DRM_FORMAT_RGBX8888: - case DRM_FORMAT_BGRX8888: - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_ABGR8888: - case DRM_FORMAT_RGBA8888: - case DRM_FORMAT_BGRA8888: - case DRM_FORMAT_RGB888: - case DRM_FORMAT_BGR888: - return 8; - case DRM_FORMAT_XRGB2101010: - case DRM_FORMAT_XBGR2101010: - case DRM_FORMAT_RGBX1010102: - case DRM_FORMAT_BGRX1010102: - case DRM_FORMAT_ARGB2101010: - case DRM_FORMAT_ABGR2101010: - case DRM_FORMAT_RGBA1010102: - case DRM_FORMAT_BGRA1010102: - return 10; - default: - return -1; - } -} - void AbstractEglBackend::initWayland() { if (!WaylandServer::self()) { @@ -180,11 +153,12 @@ void AbstractEglBackend::initWayland() } } - auto filterFormats = [this](int bpc) { + auto filterFormats = [this](uint32_t bpc) { const auto formats = m_display->supportedDrmFormats(); QHash> set; for (auto it = formats.constBegin(); it != formats.constEnd(); it++) { - if (bpcForFormat(it.key()) == bpc) { + const auto info = formatInfo(it.key()); + if (info && info->bitsPerColor == bpc) { set.insert(it.key(), it.value()); } } diff --git a/src/platformsupport/scenes/opengl/eglcontext.cpp b/src/platformsupport/scenes/opengl/eglcontext.cpp index 114b2765f6..c3014ca545 100644 --- a/src/platformsupport/scenes/opengl/eglcontext.cpp +++ b/src/platformsupport/scenes/opengl/eglcontext.cpp @@ -13,6 +13,7 @@ #include "kwineglutils_p.h" #include "kwinglutils.h" #include "utils/common.h" +#include "utils/drm_format_helper.h" #include "utils/egl_context_attribute_builder.h" #include @@ -189,29 +190,12 @@ bool EglContext::isValid() const return EGL_NO_CONTEXT; } -static GLint glFormatForDrmFormat(uint32_t format) -{ - switch (format) { - case DRM_FORMAT_ARGB16161616: - return GL_RGBA16; - case DRM_FORMAT_ARGB16161616F: - return GL_RGBA16F; - case DRM_FORMAT_ARGB2101010: - case DRM_FORMAT_XRGB2101010: - return GL_RGB10_A2; - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_ABGR8888: - default: - return GL_RGBA8; - } -}; - std::shared_ptr EglContext::importDmaBufAsTexture(const DmaBufAttributes &attributes) const { EGLImageKHR image = m_display->importDmaBufAsImage(attributes); if (image != EGL_NO_IMAGE_KHR) { - return EGLImageTexture::create(m_display->handle(), image, glFormatForDrmFormat(attributes.format), QSize(attributes.width, attributes.height), m_display->isExternalOnly(attributes.format, attributes.modifier)); + const auto info = formatInfo(attributes.format); + return EGLImageTexture::create(m_display->handle(), image, info ? info->openglFormat : GL_RGBA8, QSize(attributes.width, attributes.height), m_display->isExternalOnly(attributes.format, attributes.modifier)); } else { qCWarning(KWIN_OPENGL) << "Error creating EGLImageKHR: " << getEglErrorString(); return nullptr; diff --git a/src/utils/drm_format_helper.h b/src/utils/drm_format_helper.h new file mode 100644 index 0000000000..62d383dc5c --- /dev/null +++ b/src/utils/drm_format_helper.h @@ -0,0 +1,114 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2023 Xaver Hugl + + SPDX-License-Identifier: GPL-2.0-or-later +*/ +#pragma once +#include +#include +#include +#include + +struct FormatInfo +{ + uint32_t drmFormat; + uint32_t bitsPerColor; + uint32_t alphaBits; + uint32_t bitsPerPixel; + GLint openglFormat; +}; + +static std::optional formatInfo(uint32_t format) +{ + switch (format) { + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_BGRX8888: + return FormatInfo{ + .drmFormat = format, + .bitsPerColor = 8, + .alphaBits = 0, + .bitsPerPixel = 32, + .openglFormat = GL_RGBA8, + }; + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_BGRA8888: + return FormatInfo{ + .drmFormat = format, + .bitsPerColor = 8, + .alphaBits = 8, + .bitsPerPixel = 32, + .openglFormat = GL_RGBA8, + }; + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_RGBX1010102: + case DRM_FORMAT_BGRX1010102: + return FormatInfo{ + .drmFormat = format, + .bitsPerColor = 10, + .alphaBits = 0, + .bitsPerPixel = 32, + .openglFormat = GL_RGB10_A2, + }; + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_RGBA1010102: + case DRM_FORMAT_BGRA1010102: + return FormatInfo{ + .drmFormat = format, + .bitsPerColor = 10, + .alphaBits = 2, + .bitsPerPixel = 32, + .openglFormat = GL_RGB10_A2, + }; + case DRM_FORMAT_XRGB16161616F: + case DRM_FORMAT_XBGR16161616F: + return FormatInfo{ + .drmFormat = format, + .bitsPerColor = 16, + .alphaBits = 0, + .bitsPerPixel = 64, + .openglFormat = GL_RGBA16F, + }; + case DRM_FORMAT_ARGB16161616F: + case DRM_FORMAT_ABGR16161616F: + return FormatInfo{ + .drmFormat = format, + .bitsPerColor = 16, + .alphaBits = 16, + .bitsPerPixel = 64, + .openglFormat = GL_RGBA16F, + }; + case DRM_FORMAT_ARGB4444: + case DRM_FORMAT_ABGR4444: + case DRM_FORMAT_RGBA4444: + case DRM_FORMAT_BGRA4444: + return FormatInfo{ + .drmFormat = format, + .bitsPerColor = 4, + .alphaBits = 4, + .bitsPerPixel = 16, + .openglFormat = GL_RGBA4, + }; + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_ABGR1555: + case DRM_FORMAT_RGBA5551: + case DRM_FORMAT_BGRA5551: + return FormatInfo{ + .drmFormat = format, + .bitsPerColor = 5, + .alphaBits = 1, + .bitsPerPixel = 16, + .openglFormat = GL_RGB5_A1, + }; + default: + return std::nullopt; + } +}