backends/drm: hardcode a list of known formats instead of querying egl for information on drm formats

This commit is contained in:
Xaver Hugl 2023-06-20 16:57:56 +02:00
parent 7992813abc
commit 7872e7cb22
7 changed files with 138 additions and 195 deletions

View file

@ -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<SurfaceTexture> EglGbmBackend::createSurfaceTextureInternal(SurfacePixmapInternal *pixmap)
{
return std::make_unique<BasicEGLSurfaceTextureInternal>(this, pixmap);
@ -232,22 +164,6 @@ std::pair<std::shared_ptr<KWin::GLTexture>, ColorDescription> EglGbmBackend::tex
return std::make_pair(layer->texture(), layer->colorDescription());
}
std::optional<GbmFormat> 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

View file

@ -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<std::shared_ptr<KWin::GLTexture>, ColorDescription> textureForOutput(Output *requestedOutput) const override;
std::optional<GbmFormat> 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<EglDisplay *, std::unique_ptr<EglContext>> m_contexts;
QHash<EglDisplay *, QHash<uint32_t, GbmFormat>> m_formats;
friend class EglGbmTexture;
};

View file

@ -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 <drm_fourcc.h>
#include <errno.h>
@ -203,12 +204,12 @@ bool EglGbmLayerSurface::doesSurfaceFit(const Surface &surface, const QSize &siz
std::optional<EglGbmLayerSurface::Surface> EglGbmLayerSurface::createSurface(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats) const
{
QVector<GbmFormat> preferredFormats;
QVector<GbmFormat> fallbackFormats;
QVector<FormatInfo> preferredFormats;
QVector<FormatInfo> 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::Surface> 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<GbmFormat> &gbmFormats, MultiGpuImportMode importMode) -> std::optional<Surface> {
const auto doTestFormats = [this, &size, &formats](const QVector<FormatInfo> &gbmFormats, MultiGpuImportMode importMode) -> std::optional<Surface> {
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::Surface> EglGbmLayerSurface::createSurface(con
}
return std::nullopt;
};
const auto testFormats = [this, &sort, &doTestFormats](QVector<GbmFormat> &formats) -> std::optional<Surface> {
const auto testFormats = [this, &sort, &doTestFormats](QVector<FormatInfo> &formats) -> std::optional<Surface> {
std::sort(formats.begin(), formats.end(), sort);
if (m_gpu == m_eglBackend->gpu()) {
return doTestFormats(formats, MultiGpuImportMode::None);

View file

@ -5,6 +5,7 @@
*/
#include "core/graphicsbuffer.h"
#include "utils/drm_format_helper.h"
#include <drm_fourcc.h>
@ -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

View file

@ -18,6 +18,7 @@
#include "libkwineffects/kwineglimagetexture.h"
#include "libkwineffects/kwinglplatform.h"
#include "libkwineffects/kwinglutils.h"
#include "utils/drm_format_helper.h"
#include <kwineglutils_p.h>
// Qt
#include <QOpenGLContext>
@ -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<uint32_t, QVector<uint64_t>> 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());
}
}

View file

@ -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 <QOpenGLContext>
@ -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<GLTexture> 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;

View file

@ -0,0 +1,114 @@
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2023 Xaver Hugl <xaver.hugl@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <drm_fourcc.h>
#include <epoxy/gl.h>
#include <optional>
#include <stdint.h>
struct FormatInfo
{
uint32_t drmFormat;
uint32_t bitsPerColor;
uint32_t alphaBits;
uint32_t bitsPerPixel;
GLint openglFormat;
};
static std::optional<FormatInfo> 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;
}
}