summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/config/ConfigDescriptions.hpp6
-rw-r--r--src/config/ConfigManager.cpp1
-rw-r--r--src/protocols/LinuxDMABUF.cpp58
3 files changed, 54 insertions, 11 deletions
diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp
index 0a1e37d5..fa1ad35b 100644
--- a/src/config/ConfigDescriptions.hpp
+++ b/src/config/ConfigDescriptions.hpp
@@ -2047,5 +2047,11 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.type = CONFIG_OPTION_INT,
.data = SConfigOptionDescription::SRangeData{.value = 0, .min = 0, .max = 2},
},
+ SConfigOptionDescription{
+ .value = "quirks:skip_non_kms_dmabuf_formats",
+ .description = "Do not report dmabuf formats which cannot be imported into KMS",
+ .type = CONFIG_OPTION_BOOL,
+ .data = SConfigOptionDescription::SBoolData{true},
+ },
};
diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp
index 09ec4456..61ba9dd3 100644
--- a/src/config/ConfigManager.cpp
+++ b/src/config/ConfigManager.cpp
@@ -791,6 +791,7 @@ CConfigManager::CConfigManager() {
registerConfigVar("ecosystem:enforce_permissions", Hyprlang::INT{0});
registerConfigVar("quirks:prefer_hdr", Hyprlang::INT{0});
+ registerConfigVar("quirks:skip_non_kms_dmabuf_formats", Hyprlang::INT{0});
// devices
m_config->addSpecialCategory("device", {"name"});
diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp
index 4f59e4b3..296a27ed 100644
--- a/src/protocols/LinuxDMABUF.cpp
+++ b/src/protocols/LinuxDMABUF.cpp
@@ -26,6 +26,8 @@ static std::optional<dev_t> devIDFromFD(int fd) {
CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vector<std::pair<PHLMONITORREF, SDMABUFTranche>> tranches_) :
m_rendererTranche(_rendererTranche), m_monitorTranches(tranches_) {
+ static const auto PSKIP_NON_KMS = CConfigValue<Hyprlang::INT>("quirks:skip_non_kms_dmabuf_formats");
+
std::vector<SDMABUFFormatTableEntry> formatsVec;
std::set<std::pair<uint32_t, uint64_t>> formats;
@@ -35,6 +37,17 @@ CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vec
m_rendererTranche.indices.clear();
for (auto const& fmt : m_rendererTranche.formats) {
for (auto const& mod : fmt.modifiers) {
+ LOGM(Log::TRACE, "Render format 0x{:x} ({}) with mod 0x{:x} ({})", fmt.drmFormat, NFormatUtils::drmFormatName(fmt.drmFormat), mod, NFormatUtils::drmModifierName(mod));
+ if (*PSKIP_NON_KMS && !m_monitorTranches.empty()) {
+ if (std::ranges::none_of(m_monitorTranches, [fmt, mod](const std::pair<PHLMONITORREF, SDMABUFTranche>& pair) {
+ return std::ranges::any_of(pair.second.formats, [fmt, mod](const SDRMFormat& format) {
+ return format.drmFormat == fmt.drmFormat && std::ranges::any_of(format.modifiers, [mod](uint64_t modifier) { return mod == modifier; });
+ });
+ })) {
+ LOGM(Log::TRACE, " skipped");
+ continue;
+ }
+ }
auto format = std::make_pair<>(fmt.drmFormat, mod);
auto [_, inserted] = formats.insert(format);
if (inserted) {
@@ -56,6 +69,9 @@ CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vec
tranche.indices.clear();
for (auto const& fmt : tranche.formats) {
for (auto const& mod : fmt.modifiers) {
+ LOGM(Log::TRACE, "[DMA] Monitor format 0x{:x} ({}) with mod 0x{:x} ({})", fmt.drmFormat, NFormatUtils::drmFormatName(fmt.drmFormat), mod,
+ NFormatUtils::drmModifierName(mod));
+ // FIXME: recheck this. DRM_FORMAT_MOD_INVALID is allowed by the proto "For legacy support". DRM_FORMAT_MOD_LINEAR should be the most compatible mod
// apparently these can implode on planes, so don't use them
if (mod == DRM_FORMAT_MOD_INVALID || mod == DRM_FORMAT_MOD_LINEAR)
continue;
@@ -147,10 +163,17 @@ CLinuxDMABUFParamsResource::CLinuxDMABUFParamsResource(UP<CZwpLinuxBufferParamsV
return;
}
+ const uint64_t modifier = (sc<uint64_t>(modHi) << 32) | modLo;
+
+ if (m_resource->version() >= 5 && m_attrs->modifier && m_attrs->modifier != modifier) {
+ r->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT, "planes have different modifiers");
+ return;
+ }
+
m_attrs->fds[plane] = fd;
m_attrs->strides[plane] = stride;
m_attrs->offsets[plane] = offset;
- m_attrs->modifier = (sc<uint64_t>(modHi) << 32) | modLo;
+ m_attrs->modifier = modifier;
});
m_resource->setCreate([this](CZwpLinuxBufferParamsV1* r, int32_t w, int32_t h, uint32_t fmt, zwpLinuxBufferParamsV1Flags flags) {
@@ -165,6 +188,13 @@ CLinuxDMABUFParamsResource::CLinuxDMABUFParamsResource(UP<CZwpLinuxBufferParamsV
return;
}
+ if (m_resource->version() >= 4 && std::ranges::none_of(PROTO::linuxDma->m_formatTable->m_rendererTranche.formats, [this, fmt](const auto format) {
+ return format.drmFormat == fmt && std::ranges::any_of(format.modifiers, [this](const auto mod) { return !mod || mod == m_attrs->modifier; });
+ })) {
+ r->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT, "format + modifier pair is not supported");
+ return;
+ }
+
m_attrs->size = {w, h};
m_attrs->format = fmt;
m_attrs->planes = 4 - std::ranges::count(m_attrs->fds, -1);
@@ -382,8 +412,7 @@ CLinuxDMABUFResource::CLinuxDMABUFResource(UP<CZwpLinuxDmabufV1>&& resource_) :
}
});
- if (m_resource->version() < 4)
- sendMods();
+ sendMods();
}
bool CLinuxDMABUFResource::good() {
@@ -392,16 +421,14 @@ bool CLinuxDMABUFResource::good() {
void CLinuxDMABUFResource::sendMods() {
for (auto const& fmt : PROTO::linuxDma->m_formatTable->m_rendererTranche.formats) {
- for (auto const& mod : fmt.modifiers) {
- if (m_resource->version() < 3) {
- if (mod == DRM_FORMAT_MOD_INVALID || mod == DRM_FORMAT_MOD_LINEAR)
- m_resource->sendFormat(fmt.drmFormat);
- continue;
- }
+ m_resource->sendFormat(fmt.drmFormat);
- // TODO: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1166
+ if (m_resource->version() == 3) {
+ for (auto const& mod : fmt.modifiers) {
+ // TODO: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1166
- m_resource->sendModifier(fmt.drmFormat, mod >> 32, mod & 0xFFFFFFFF);
+ m_resource->sendModifier(fmt.drmFormat, mod >> 32, mod & 0xFFFFFFFF);
+ }
}
}
}
@@ -456,6 +483,15 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const
std::erase_if(m_formatTable->m_monitorTranches, [pMonitor](std::pair<PHLMONITORREF, SDMABUFTranche> pair) { return pair.first == pMonitor; });
resetFormatTable();
});
+
+ static auto configReloaded = g_pHookSystem->hookDynamic("configReloaded", [this](void* self, SCallbackInfo& info, std::any param) {
+ static const auto PSKIP_NON_KMS = CConfigValue<Hyprlang::INT>("quirks:skip_non_kms_dmabuf_formats");
+ static auto prev = *PSKIP_NON_KMS;
+ if (prev != *PSKIP_NON_KMS) {
+ prev = *PSKIP_NON_KMS;
+ resetFormatTable();
+ }
+ });
}
m_formatTable = makeUnique<CDMABUFFormatTable>(eglTranche, tches);