platformsupport/scenes/opengl: move egl dmabuf format queries to KWinEglDisplay

This commit is contained in:
Xaver Hugl 2023-04-02 20:27:11 +02:00
parent 94ac8d235b
commit 7bb56eb363
4 changed files with 92 additions and 68 deletions

View file

@ -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<uint32_t> 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<uint64_t> modifiers(count);
QVector<EGLBoolean> 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<uint32_t, QVector<uint64_t>> 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<uint32_t, QVector<uint64_t>> 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<uint32_t, QVector<uint64_t>> AbstractEglBackend::supportedFormats() const
{
return m_supportedFormats;
return m_display->supportedDrmFormats();
}
::EGLDisplay AbstractEglBackend::eglDisplay() const

View file

@ -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<QByteArray> m_clientExtensions;
const dev_t m_deviceId;
QVector<KWaylandServer::LinuxDmaBufV1Feedback::Tranche> m_tranches;
QHash<uint32_t, QVector<uint64_t>> m_supportedFormats;
QHash<KWaylandServer::LinuxDmaBufV1ClientBuffer *, EGLImageKHR> m_importedBuffers;
};

View file

@ -76,6 +76,7 @@ EglDisplay::EglDisplay(::EGLDisplay display, const QList<QByteArray> &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<uint32_t, QList<uint64_t>> EglDisplay::supportedDrmFormats() const
{
return m_importFormats;
}
QHash<uint32_t, QList<uint64_t>> 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<uint32_t> formats(count);
if (!eglQueryDmaBufFormatsEXT(m_handle, count, (EGLint *)formats.data(), &count)) {
qCCritical(KWIN_OPENGL) << "eglQueryDmaBufFormatsEXT with count" << count << "failed!" << getEglErrorString();
return {};
}
QHash<uint32_t, QVector<uint64_t>> 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<uint64_t> modifiers(count);
QVector<EGLBoolean> 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;
}
}

View file

@ -11,6 +11,7 @@
#include "kwin_export.h"
#include <QByteArray>
#include <QHash>
#include <QList>
#include <epoxy/egl.h>
@ -33,12 +34,15 @@ public:
bool supportsBufferAge() const;
bool supportsSwapBuffersWithDamage() const;
bool supportsNativeFence() const;
QHash<uint32_t, QList<uint64_t>> supportedDrmFormats() const;
EGLImageKHR importDmaBufAsImage(const DmaBufAttributes &dmabuf) const;
static std::unique_ptr<EglDisplay> create(::EGLDisplay display, bool owning = true);
private:
QHash<uint32_t, QList<uint64_t>> queryImportFormats() const;
const ::EGLDisplay m_handle;
const QList<QByteArray> 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<uint32_t, QList<uint64_t>> m_importFormats;
};
}