backends/drm: refactor format choosing and prefer alpha formats
Prefering alpha is needed for some interactions with video underlays; more directly choosing formats with an alpha channel will be needed for overlay planes, too.
This commit is contained in:
parent
5cf2e1e84d
commit
432fb52788
4 changed files with 45 additions and 66 deletions
|
@ -161,42 +161,19 @@ bool EglGbmBackend::initBufferConfigs()
|
|||
|
||||
GbmFormat format;
|
||||
format.drmFormat = gbmFormat;
|
||||
EGLint red, green, blue;
|
||||
// Query number of bits for color channel
|
||||
eglGetConfigAttrib(eglDisplay(), configs[i], EGL_RED_SIZE, &format.redSize);
|
||||
eglGetConfigAttrib(eglDisplay(), configs[i], EGL_GREEN_SIZE, &format.greenSize);
|
||||
eglGetConfigAttrib(eglDisplay(), configs[i], EGL_BLUE_SIZE, &format.blueSize);
|
||||
eglGetConfigAttrib(eglDisplay(), configs[i], EGL_RED_SIZE, &red);
|
||||
eglGetConfigAttrib(eglDisplay(), configs[i], EGL_GREEN_SIZE, &green);
|
||||
eglGetConfigAttrib(eglDisplay(), configs[i], EGL_BLUE_SIZE, &blue);
|
||||
eglGetConfigAttrib(eglDisplay(), configs[i], EGL_ALPHA_SIZE, &format.alphaSize);
|
||||
|
||||
if (m_formats.contains(format)) {
|
||||
format.bpp = red + green + blue;
|
||||
if (m_formats.contains(gbmFormat)) {
|
||||
continue;
|
||||
}
|
||||
m_formats << format;
|
||||
m_formats[gbmFormat] = format;
|
||||
m_configs[format.drmFormat] = configs[i];
|
||||
}
|
||||
|
||||
QVector<int> colorDepthOrder = {30, 24};
|
||||
bool ok = false;
|
||||
const int preferred = qEnvironmentVariableIntValue("KWIN_DRM_PREFER_COLOR_DEPTH", &ok);
|
||||
if (ok) {
|
||||
colorDepthOrder.prepend(preferred);
|
||||
}
|
||||
|
||||
std::sort(m_formats.begin(), m_formats.end(), [&colorDepthOrder](const auto &lhs, const auto &rhs) {
|
||||
const int ls = lhs.redSize + lhs.greenSize + lhs.blueSize;
|
||||
const int rs = rhs.redSize + rhs.greenSize + rhs.blueSize;
|
||||
if (ls == rs) {
|
||||
return lhs.alphaSize < rhs.alphaSize;
|
||||
} else {
|
||||
for (const int &d : qAsConst(colorDepthOrder)) {
|
||||
if (ls == d) {
|
||||
return true;
|
||||
} else if (rs == d) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return ls > rs;
|
||||
}
|
||||
});
|
||||
if (!m_formats.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -242,23 +219,11 @@ QSharedPointer<GLTexture> EglGbmBackend::textureForOutput(AbstractOutput *output
|
|||
return static_cast<EglGbmLayer *>(drmOutput->outputLayer())->texture();
|
||||
}
|
||||
|
||||
GbmFormat EglGbmBackend::gbmFormatForDrmFormat(uint32_t format) const
|
||||
std::optional<GbmFormat> EglGbmBackend::gbmFormatForDrmFormat(uint32_t format) const
|
||||
{
|
||||
// TODO use a hardcoded lookup table where needed instead?
|
||||
const auto it = std::find_if(m_formats.begin(), m_formats.end(), [format](const auto &gbmFormat) {
|
||||
return gbmFormat.drmFormat == format;
|
||||
});
|
||||
if (it == m_formats.end()) {
|
||||
return GbmFormat{
|
||||
.drmFormat = DRM_FORMAT_XRGB8888,
|
||||
.redSize = 8,
|
||||
.greenSize = 8,
|
||||
.blueSize = 8,
|
||||
.alphaSize = 0,
|
||||
};
|
||||
} else {
|
||||
return *it;
|
||||
}
|
||||
const auto it = m_formats.constFind(format);
|
||||
return it == m_formats.constEnd() ? std::optional<GbmFormat>() : *it;
|
||||
}
|
||||
|
||||
bool EglGbmBackend::prefer10bpc() const
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <kwinglutils.h>
|
||||
|
||||
#include <QHash>
|
||||
#include <QPointer>
|
||||
#include <QSharedPointer>
|
||||
#include <optional>
|
||||
|
@ -44,9 +45,7 @@ class DrmPipeline;
|
|||
struct GbmFormat
|
||||
{
|
||||
uint32_t drmFormat = 0;
|
||||
EGLint redSize = -1;
|
||||
EGLint greenSize = -1;
|
||||
EGLint blueSize = -1;
|
||||
uint32_t bpp;
|
||||
EGLint alphaSize = -1;
|
||||
};
|
||||
bool operator==(const GbmFormat &lhs, const GbmFormat &rhs);
|
||||
|
@ -76,7 +75,7 @@ public:
|
|||
|
||||
QSharedPointer<DrmBuffer> testBuffer(DrmAbstractOutput *output);
|
||||
EGLConfig config(uint32_t format) const;
|
||||
GbmFormat gbmFormatForDrmFormat(uint32_t format) const;
|
||||
std::optional<GbmFormat> gbmFormatForDrmFormat(uint32_t format) const;
|
||||
DrmGpu *gpu() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
|
@ -88,8 +87,8 @@ private:
|
|||
bool initRenderingContext();
|
||||
|
||||
DrmBackend *m_backend;
|
||||
QVector<GbmFormat> m_formats;
|
||||
QMap<uint32_t, EGLConfig> m_configs;
|
||||
QHash<uint32_t, GbmFormat> m_formats;
|
||||
QHash<uint32_t, EGLConfig> m_configs;
|
||||
|
||||
friend class EglGbmTexture;
|
||||
};
|
||||
|
|
|
@ -100,7 +100,7 @@ OutputLayerBeginFrameInfo EglGbmLayer::beginFrame()
|
|||
m_shadowBuffer = m_oldShadowBuffer;
|
||||
} else {
|
||||
if (m_pipeline->pending.bufferTransformation != m_pipeline->pending.sourceTransformation) {
|
||||
const auto format = m_eglBackend->gbmFormatForDrmFormat(m_gbmSurface->format());
|
||||
const auto format = m_eglBackend->gbmFormatForDrmFormat(m_gbmSurface->format()).value();
|
||||
m_shadowBuffer = QSharedPointer<ShadowBuffer>::create(m_pipeline->sourceSize(), format);
|
||||
if (!m_shadowBuffer->isComplete()) {
|
||||
return {};
|
||||
|
@ -238,18 +238,35 @@ bool EglGbmLayer::createGbmSurface(uint32_t format, const QVector<uint64_t> &mod
|
|||
|
||||
bool EglGbmLayer::createGbmSurface()
|
||||
{
|
||||
const auto tranches = m_eglBackend->dmabuf()->tranches();
|
||||
for (const auto &tranche : tranches) {
|
||||
for (auto it = tranche.formatTable.constBegin(); it != tranche.formatTable.constEnd(); it++) {
|
||||
const uint32_t &format = it.key();
|
||||
if (m_importMode == MultiGpuImportMode::DumbBufferXrgb8888 && format != DRM_FORMAT_XRGB8888) {
|
||||
continue;
|
||||
}
|
||||
if (m_pipeline->isFormatSupported(format) && createGbmSurface(format, m_pipeline->supportedModifiers(format))) {
|
||||
return true;
|
||||
}
|
||||
const auto formats = m_pipeline->supportedFormats();
|
||||
QVector<GbmFormat> sortedFormats;
|
||||
for (auto it = formats.begin(); it != formats.end(); it++) {
|
||||
const auto format = m_eglBackend->gbmFormatForDrmFormat(it.key());
|
||||
if (format.has_value()) {
|
||||
sortedFormats << format.value();
|
||||
}
|
||||
}
|
||||
std::sort(sortedFormats.begin(), sortedFormats.end(), [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))) {
|
||||
// prefer 10bpc / 30bpp formats
|
||||
return lhs.bpp == 30 ? true : false;
|
||||
} else {
|
||||
// fallback
|
||||
return lhs.drmFormat < rhs.drmFormat;
|
||||
}
|
||||
});
|
||||
for (const auto &format : qAsConst(sortedFormats)) {
|
||||
if (m_importMode == MultiGpuImportMode::DumbBufferXrgb8888 && format.drmFormat != DRM_FORMAT_XRGB8888) {
|
||||
continue;
|
||||
}
|
||||
if (formats.contains(format.drmFormat) && createGbmSurface(format.drmFormat, formats[format.drmFormat])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
qCCritical(KWIN_DRM, "Failed to create a gbm surface!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -108,12 +108,10 @@ uint32_t ShadowBuffer::drmFormat() const
|
|||
|
||||
GLint ShadowBuffer::internalFormat(const GbmFormat &format) const
|
||||
{
|
||||
if (format.redSize <= 8 && format.greenSize <= 8 && format.blueSize <= 8) {
|
||||
if (format.bpp <= 24) {
|
||||
return GL_RGBA8;
|
||||
} else if (format.redSize <= 10 && format.greenSize <= 10 && format.blueSize <= 10) {
|
||||
} else if (format.bpp <= 30) {
|
||||
return GL_RGB10_A2;
|
||||
} else if (format.redSize <= 12 && format.greenSize <= 12 && format.blueSize <= 12) {
|
||||
return GL_RGBA12;
|
||||
} else {
|
||||
return GL_RGBA16;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue