backends/drm: replace drmModeAtomicCommit with a custom implementation

drmModeAtomicCommit does additional allocations and sorting that KWin doesn't
use or need
master
Xaver Hugl 1 year ago
parent dee8a3b3a7
commit 1c18d11206

@ -330,15 +330,35 @@ int drmHandleEvent(int fd, drmEventContextPtr evctx)
int drmIoctl(int fd, unsigned long request, void *arg)
{
GPU(fd, -EINVAL);
if (request == DRM_IOCTL_PRIME_FD_TO_HANDLE) {
GPU(fd, -EINVAL);
auto args = static_cast<drm_prime_handle *>(arg);
args->handle = 42; // just pass a dummy value so the request doesn't fail
return 0;
} else if (request == DRM_IOCTL_PRIME_HANDLE_TO_FD) {
return -(errno = ENOTSUP);
} else if (request == DRM_IOCTL_GEM_CLOSE) {
GPU(fd, -EINVAL);
return 0;
} else if (request == DRM_IOCTL_MODE_ATOMIC) {
const auto args = static_cast<drm_mode_atomic *>(arg);
auto req = drmModeAtomicAlloc();
const uint32_t *const objects = reinterpret_cast<const uint32_t *>(args->objs_ptr);
const uint32_t *const propsCounts = reinterpret_cast<const uint32_t *>(args->count_props_ptr);
const uint32_t *const props = reinterpret_cast<const uint32_t *>(args->props_ptr);
const uint64_t *const values = reinterpret_cast<const uint64_t *>(args->prop_values_ptr);
uint32_t propIndex = 0;
for (uint32_t objIndex = 0; objIndex < args->count_objs; objIndex++) {
const uint32_t objectId = objects[objIndex];
const uint32_t count = propsCounts[objIndex];
for (uint32_t i = 0; i < count; i++) {
drmModeAtomicAddProperty(req, objectId, props[propIndex + i], values[propIndex + i]);
}
propIndex += count;
}
int ret = drmModeAtomicCommit(fd, req, args->flags, reinterpret_cast<void *>(args->user_data));
drmModeAtomicFree(req);
return ret;
}
return -(errno = ENOTSUP);
}

@ -39,13 +39,12 @@ DrmGpu *DrmCommit::gpu() const
DrmAtomicCommit::DrmAtomicCommit(const QVector<DrmPipeline *> &pipelines)
: DrmCommit(pipelines.front()->gpu())
, m_pipelines(pipelines)
, m_req(drmModeAtomicAlloc())
{
}
void DrmAtomicCommit::addProperty(const DrmProperty &prop, uint64_t value)
{
drmModeAtomicAddProperty(m_req.get(), prop.drmObject()->id(), prop.propId(), value);
m_properties[prop.drmObject()->id()][prop.propId()] = value;
}
void DrmAtomicCommit::addBlob(const DrmProperty &prop, const std::shared_ptr<DrmBlob> &blob)
@ -68,27 +67,57 @@ void DrmAtomicCommit::setVrr(DrmCrtc *crtc, bool vrr)
bool DrmAtomicCommit::test()
{
return drmModeAtomicCommit(gpu()->fd(), m_req.get(), DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_NONBLOCK, this) == 0;
return doCommit(DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_NONBLOCK);
}
bool DrmAtomicCommit::testAllowModeset()
{
return drmModeAtomicCommit(gpu()->fd(), m_req.get(), DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET, this) == 0;
return doCommit(DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET);
}
bool DrmAtomicCommit::commit()
{
return drmModeAtomicCommit(gpu()->fd(), m_req.get(), DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, this) == 0;
return doCommit(DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT);
}
bool DrmAtomicCommit::commitModeset()
{
return drmModeAtomicCommit(gpu()->fd(), m_req.get(), DRM_MODE_ATOMIC_ALLOW_MODESET, this) == 0;
return doCommit(DRM_MODE_ATOMIC_ALLOW_MODESET);
}
drmModeAtomicReq *DrmAtomicCommit::req() const
bool DrmAtomicCommit::doCommit(uint32_t flags)
{
return m_req.get();
std::vector<uint32_t> objects;
std::vector<uint32_t> propertyCounts;
std::vector<uint32_t> propertyIds;
std::vector<uint64_t> values;
objects.reserve(m_properties.size());
propertyCounts.reserve(m_properties.size());
uint64_t totalPropertiesCount = 0;
for (const auto &[object, properties] : m_properties) {
objects.push_back(object);
propertyCounts.push_back(properties.size());
totalPropertiesCount += properties.size();
}
propertyIds.reserve(totalPropertiesCount);
values.reserve(totalPropertiesCount);
for (const auto &[object, properties] : m_properties) {
for (const auto &[property, value] : properties) {
propertyIds.push_back(property);
values.push_back(value);
}
}
drm_mode_atomic commitData{
.flags = flags,
.count_objs = uint32_t(objects.size()),
.objs_ptr = reinterpret_cast<uint64_t>(objects.data()),
.count_props_ptr = reinterpret_cast<uint64_t>(propertyCounts.data()),
.props_ptr = reinterpret_cast<uint64_t>(propertyIds.data()),
.prop_values_ptr = reinterpret_cast<uint64_t>(values.data()),
.reserved = 0,
.user_data = reinterpret_cast<uint64_t>(this),
};
return drmIoctl(m_gpu->fd(), DRM_IOCTL_MODE_ATOMIC, &commitData) == 0;
}
void DrmAtomicCommit::pageFlipped(std::chrono::nanoseconds timestamp) const

@ -67,17 +67,17 @@ public:
void pageFlipped(std::chrono::nanoseconds timestamp) const override;
drmModeAtomicReq *req() const;
bool areBuffersReadable() const;
bool isVrr() const;
private:
bool doCommit(uint32_t flags);
const QVector<DrmPipeline *> m_pipelines;
DrmUniquePtr<drmModeAtomicReq> m_req;
QHash<const DrmProperty *, std::shared_ptr<DrmBlob>> m_blobs;
std::unordered_map<DrmPlane *, std::shared_ptr<DrmFramebuffer>> m_buffers;
bool m_vrr = false;
std::unordered_map<uint32_t /* object */, std::unordered_map<uint32_t /* property */, uint64_t /* value */>> m_properties;
};
class DrmLegacyCommit : public DrmCommit

Loading…
Cancel
Save