backends/drm: hardcode a list of known formats instead of querying egl for information on drm formats
This commit is contained in:
parent
7992813abc
commit
7872e7cb22
7 changed files with 138 additions and 195 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
114
src/utils/drm_format_helper.h
Normal file
114
src/utils/drm_format_helper.h
Normal 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;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue