From abd58530c378c10904570f0f763b017646ecbea9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 17:56:49 +0000 Subject: [PATCH 1/8] add a drm_dumb allocator --- include/aquamarine/allocator/Allocator.hpp | 1 + include/aquamarine/allocator/DRMDumb.hpp | 69 ++++++++++ include/aquamarine/backend/Backend.hpp | 25 ++-- include/aquamarine/backend/DRM.hpp | 48 +++---- include/aquamarine/backend/Headless.hpp | 30 +++-- include/aquamarine/backend/Wayland.hpp | 29 +++-- include/aquamarine/buffer/Buffer.hpp | 1 + src/allocator/DRMDumb.cpp | 142 +++++++++++++++++++++ src/backend/Headless.cpp | 4 + src/backend/Wayland.cpp | 4 + src/backend/drm/DRM.cpp | 119 ++++++++++------- src/buffer/Buffer.cpp | 4 + 12 files changed, 369 insertions(+), 107 deletions(-) create mode 100644 include/aquamarine/allocator/DRMDumb.hpp create mode 100644 src/allocator/DRMDumb.cpp diff --git a/include/aquamarine/allocator/Allocator.hpp b/include/aquamarine/allocator/Allocator.hpp index 5ca54af..02552f2 100644 --- a/include/aquamarine/allocator/Allocator.hpp +++ b/include/aquamarine/allocator/Allocator.hpp @@ -16,6 +16,7 @@ namespace Aquamarine { enum eAllocatorType { AQ_ALLOCATOR_TYPE_GBM = 0, + AQ_ALLOCATOR_TYPE_DRM_DUMB, }; class IAllocator { diff --git a/include/aquamarine/allocator/DRMDumb.hpp b/include/aquamarine/allocator/DRMDumb.hpp new file mode 100644 index 0000000..65d8173 --- /dev/null +++ b/include/aquamarine/allocator/DRMDumb.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include "Allocator.hpp" + +namespace Aquamarine { + class CDRMDumbAllocator; + class CBackend; + class CSwapchain; + + class CDRMDumbBuffer : public IBuffer { + public: + virtual ~CDRMDumbBuffer(); + + virtual eBufferCapability caps(); + virtual eBufferType type(); + virtual void update(const Hyprutils::Math::CRegion& damage); + virtual bool isSynchronous(); + virtual bool good(); + virtual SSHMAttrs shm(); + virtual std::tuple beginDataPtr(uint32_t flags); + virtual void endDataPtr(); + virtual uint32_t drmHandle(); + + private: + CDRMDumbBuffer(const SAllocatorBufferParams& params, Hyprutils::Memory::CWeakPointer allocator_, + Hyprutils::Memory::CSharedPointer swapchain); + + Hyprutils::Memory::CWeakPointer allocator; + + // + uint32_t drmID = 0; + Hyprutils::Math::Vector2D pixelSize; + uint32_t stride = 0, handle = 0; + uint64_t size = 0; + uint8_t* data = nullptr; + + // + SSHMAttrs attrs{.success = false}; + + friend class CDRMDumbAllocator; + }; + + class CDRMDumbAllocator : public IAllocator { + public: + ~CDRMDumbAllocator(); + static Hyprutils::Memory::CSharedPointer create(int drmfd_, Hyprutils::Memory::CWeakPointer backend_); + + virtual Hyprutils::Memory::CSharedPointer acquire(const SAllocatorBufferParams& params, Hyprutils::Memory::CSharedPointer swapchain_); + virtual Hyprutils::Memory::CSharedPointer getBackend(); + virtual int drmFD(); + virtual eAllocatorType type(); + + // + Hyprutils::Memory::CWeakPointer self; + + private: + CDRMDumbAllocator(int fd_, Hyprutils::Memory::CWeakPointer backend_); + + // a vector purely for tracking (debugging) the buffers and nothing more + std::vector> buffers; + + Hyprutils::Memory::CWeakPointer backend; + + int drmfd = -1; + + friend class CDRMDumbBuffer; + friend class CDRMRenderer; + }; +}; diff --git a/include/aquamarine/backend/Backend.hpp b/include/aquamarine/backend/Backend.hpp index 6e40d62..2dd039c 100644 --- a/include/aquamarine/backend/Backend.hpp +++ b/include/aquamarine/backend/Backend.hpp @@ -66,18 +66,19 @@ namespace Aquamarine { AQ_BACKEND_CAPABILITY_POINTER = (1 << 0), }; - virtual eBackendType type() = 0; - virtual bool start() = 0; - virtual std::vector> pollFDs() = 0; - virtual int drmFD() = 0; - virtual bool dispatchEvents() = 0; - virtual uint32_t capabilities() = 0; - virtual void onReady() = 0; - virtual std::vector getRenderFormats() = 0; - virtual std::vector getCursorFormats() = 0; - virtual bool createOutput(const std::string& name = "") = 0; // "" means auto - virtual Hyprutils::Memory::CSharedPointer preferredAllocator() = 0; - virtual std::vector getRenderableFormats(); // empty = use getRenderFormats + virtual eBackendType type() = 0; + virtual bool start() = 0; + virtual std::vector> pollFDs() = 0; + virtual int drmFD() = 0; + virtual bool dispatchEvents() = 0; + virtual uint32_t capabilities() = 0; + virtual void onReady() = 0; + virtual std::vector getRenderFormats() = 0; + virtual std::vector getCursorFormats() = 0; + virtual bool createOutput(const std::string& name = "") = 0; // "" means auto + virtual Hyprutils::Memory::CSharedPointer preferredAllocator() = 0; + virtual std::vector getRenderableFormats(); // empty = use getRenderFormats + virtual std::vector> getAllocators() = 0; }; class CBackend { diff --git a/include/aquamarine/backend/DRM.hpp b/include/aquamarine/backend/DRM.hpp index 40ea97a..3347cda 100644 --- a/include/aquamarine/backend/DRM.hpp +++ b/include/aquamarine/backend/DRM.hpp @@ -15,6 +15,7 @@ namespace Aquamarine { class CDRMOutput; struct SDRMConnector; class CDRMRenderer; + class CDRMDumbAllocator; typedef std::function FIdleCallback; @@ -340,28 +341,29 @@ namespace Aquamarine { class CDRMBackend : public IBackendImplementation { public: virtual ~CDRMBackend(); - virtual eBackendType type(); - virtual bool start(); - virtual std::vector> pollFDs(); - virtual int drmFD(); - virtual bool dispatchEvents(); - virtual uint32_t capabilities(); - virtual bool setCursor(Hyprutils::Memory::CSharedPointer buffer, const Hyprutils::Math::Vector2D& hotspot); - virtual void onReady(); - virtual std::vector getRenderFormats(); - virtual std::vector getCursorFormats(); - virtual bool createOutput(const std::string& name = ""); - virtual Hyprutils::Memory::CSharedPointer preferredAllocator(); - virtual std::vector getRenderableFormats(); - - Hyprutils::Memory::CWeakPointer self; - - void log(eBackendLogLevel, const std::string&); - bool sessionActive(); - int getNonMasterFD(); - - std::vector idleCallbacks; - std::string gpuName; + virtual eBackendType type(); + virtual bool start(); + virtual std::vector> pollFDs(); + virtual int drmFD(); + virtual bool dispatchEvents(); + virtual uint32_t capabilities(); + virtual bool setCursor(Hyprutils::Memory::CSharedPointer buffer, const Hyprutils::Math::Vector2D& hotspot); + virtual void onReady(); + virtual std::vector getRenderFormats(); + virtual std::vector getCursorFormats(); + virtual bool createOutput(const std::string& name = ""); + virtual Hyprutils::Memory::CSharedPointer preferredAllocator(); + virtual std::vector getRenderableFormats(); + virtual std::vector> getAllocators(); + + Hyprutils::Memory::CWeakPointer self; + + void log(eBackendLogLevel, const std::string&); + bool sessionActive(); + int getNonMasterFD(); + + std::vector idleCallbacks; + std::string gpuName; private: CDRMBackend(Hyprutils::Memory::CSharedPointer backend); @@ -396,6 +398,8 @@ namespace Aquamarine { std::vector formats; std::vector glFormats; + Hyprutils::Memory::CSharedPointer dumbAllocator; + bool atomic = false; struct { diff --git a/include/aquamarine/backend/Headless.hpp b/include/aquamarine/backend/Headless.hpp index d619528..aee26a4 100644 --- a/include/aquamarine/backend/Headless.hpp +++ b/include/aquamarine/backend/Headless.hpp @@ -8,6 +8,7 @@ namespace Aquamarine { class CBackend; class CHeadlessBackend; + class IAllocator; class CHeadlessOutput : public IOutput { public: @@ -35,20 +36,21 @@ namespace Aquamarine { class CHeadlessBackend : public IBackendImplementation { public: virtual ~CHeadlessBackend(); - virtual eBackendType type(); - virtual bool start(); - virtual std::vector> pollFDs(); - virtual int drmFD(); - virtual bool dispatchEvents(); - virtual uint32_t capabilities(); - virtual bool setCursor(Hyprutils::Memory::CSharedPointer buffer, const Hyprutils::Math::Vector2D& hotspot); - virtual void onReady(); - virtual std::vector getRenderFormats(); - virtual std::vector getCursorFormats(); - virtual bool createOutput(const std::string& name = ""); - virtual Hyprutils::Memory::CSharedPointer preferredAllocator(); - - Hyprutils::Memory::CWeakPointer self; + virtual eBackendType type(); + virtual bool start(); + virtual std::vector> pollFDs(); + virtual int drmFD(); + virtual bool dispatchEvents(); + virtual uint32_t capabilities(); + virtual bool setCursor(Hyprutils::Memory::CSharedPointer buffer, const Hyprutils::Math::Vector2D& hotspot); + virtual void onReady(); + virtual std::vector getRenderFormats(); + virtual std::vector getCursorFormats(); + virtual bool createOutput(const std::string& name = ""); + virtual Hyprutils::Memory::CSharedPointer preferredAllocator(); + virtual std::vector> getAllocators(); + + Hyprutils::Memory::CWeakPointer self; private: CHeadlessBackend(Hyprutils::Memory::CSharedPointer backend_); diff --git a/include/aquamarine/backend/Wayland.hpp b/include/aquamarine/backend/Wayland.hpp index ea71a0b..33d6502 100644 --- a/include/aquamarine/backend/Wayland.hpp +++ b/include/aquamarine/backend/Wayland.hpp @@ -123,20 +123,21 @@ namespace Aquamarine { class CWaylandBackend : public IBackendImplementation { public: virtual ~CWaylandBackend(); - virtual eBackendType type(); - virtual bool start(); - virtual std::vector> pollFDs(); - virtual int drmFD(); - virtual bool dispatchEvents(); - virtual uint32_t capabilities(); - virtual bool setCursor(Hyprutils::Memory::CSharedPointer buffer, const Hyprutils::Math::Vector2D& hotspot); - virtual void onReady(); - virtual std::vector getRenderFormats(); - virtual std::vector getCursorFormats(); - virtual bool createOutput(const std::string& name = ""); - virtual Hyprutils::Memory::CSharedPointer preferredAllocator(); - - Hyprutils::Memory::CWeakPointer self; + virtual eBackendType type(); + virtual bool start(); + virtual std::vector> pollFDs(); + virtual int drmFD(); + virtual bool dispatchEvents(); + virtual uint32_t capabilities(); + virtual bool setCursor(Hyprutils::Memory::CSharedPointer buffer, const Hyprutils::Math::Vector2D& hotspot); + virtual void onReady(); + virtual std::vector getRenderFormats(); + virtual std::vector getCursorFormats(); + virtual bool createOutput(const std::string& name = ""); + virtual Hyprutils::Memory::CSharedPointer preferredAllocator(); + virtual std::vector> getAllocators(); + + Hyprutils::Memory::CWeakPointer self; private: CWaylandBackend(Hyprutils::Memory::CSharedPointer backend); diff --git a/include/aquamarine/buffer/Buffer.hpp b/include/aquamarine/buffer/Buffer.hpp index 99c21bf..158ee9e 100644 --- a/include/aquamarine/buffer/Buffer.hpp +++ b/include/aquamarine/buffer/Buffer.hpp @@ -60,6 +60,7 @@ namespace Aquamarine { virtual void lock(); virtual void unlock(); virtual bool locked(); + virtual uint32_t drmHandle(); Hyprutils::Math::Vector2D size; bool opaque = false; diff --git a/src/allocator/DRMDumb.cpp b/src/allocator/DRMDumb.cpp new file mode 100644 index 0000000..bb673e3 --- /dev/null +++ b/src/allocator/DRMDumb.cpp @@ -0,0 +1,142 @@ +#include +#include +#include +#include +#include "FormatUtils.hpp" +#include "Shared.hpp" +#include +#include +#include +#include +#include "../backend/drm/Renderer.hpp" + +using namespace Aquamarine; +using namespace Hyprutils::Memory; +#define SP CSharedPointer +#define WP CWeakPointer + +Aquamarine::CDRMDumbBuffer::CDRMDumbBuffer(const SAllocatorBufferParams& params, Hyprutils::Memory::CWeakPointer allocator_, + Hyprutils::Memory::CSharedPointer swapchain) : allocator(allocator_) { + attrs.format = params.format; + + drm_mode_create_dumb request = { + .height = (uint32_t)params.size.y, + .width = (uint32_t)params.size.x, + .bpp = 32, + }; + + if (int ret = drmIoctl(allocator->drmFD(), DRM_IOCTL_MODE_CREATE_DUMB, &request); ret < 0) { + allocator->backend->log(AQ_LOG_ERROR, std::format("failed to create a drm_dumb buffer: {}", strerror(-ret))); + return; + } + + stride = request.pitch; + handle = request.handle; + size = request.size; + pixelSize = {(double)request.width, (double)request.height}; + + attrs.size = pixelSize; + attrs.fd = request.handle; + + drm_mode_map_dumb request2 = { + .handle = handle, + }; + + if (int ret = drmIoctl(allocator->drmFD(), DRM_IOCTL_MODE_MAP_DUMB, &request2); ret < 0) { + allocator->backend->log(AQ_LOG_ERROR, std::format("failed to map a drm_dumb buffer: {}", strerror(-ret))); + return; + } + + data = (uint8_t*)mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, allocator->drmFD(), request2.offset); + if (!data) { + allocator->backend->log(AQ_LOG_ERROR, "failed to mmmap a drm_dumb buffer"); + return; + } + + // null the entire buffer so we dont get garbage + memset(data, 0x00, size); + + attrs.success = true; +} + +Aquamarine::CDRMDumbBuffer::~CDRMDumbBuffer() { + events.destroy.emit(); + + if (handle == 0) + return; + + if (data) + munmap(data, size); + + drm_mode_destroy_dumb request = { + .handle = handle, + }; + drmIoctl(allocator->drmFD(), DRM_IOCTL_MODE_DESTROY_DUMB, &request); +} + +eBufferCapability Aquamarine::CDRMDumbBuffer::caps() { + return eBufferCapability::BUFFER_CAPABILITY_DATAPTR; +} + +eBufferType Aquamarine::CDRMDumbBuffer::type() { + return eBufferType::BUFFER_TYPE_SHM; +} + +void Aquamarine::CDRMDumbBuffer::update(const Hyprutils::Math::CRegion& damage) { + ; // nothing to do +} + +bool Aquamarine::CDRMDumbBuffer::isSynchronous() { + return true; +} + +bool Aquamarine::CDRMDumbBuffer::good() { + return attrs.success && data; +} + +SSHMAttrs Aquamarine::CDRMDumbBuffer::shm() { + return attrs; +} + +std::tuple Aquamarine::CDRMDumbBuffer::beginDataPtr(uint32_t flags) { + return {data, attrs.format, size}; +} + +void Aquamarine::CDRMDumbBuffer::endDataPtr() { + ; // nothing to do +} + +uint32_t Aquamarine::CDRMDumbBuffer::drmHandle() { + return handle; +} + +Aquamarine::CDRMDumbAllocator::~CDRMDumbAllocator() { + ; // nothing to do +} + +SP Aquamarine::CDRMDumbAllocator::create(int drmfd_, Hyprutils::Memory::CWeakPointer backend_) { + return SP(new CDRMDumbAllocator(drmfd_, backend_)); +} + +SP Aquamarine::CDRMDumbAllocator::acquire(const SAllocatorBufferParams& params, SP swapchain_) { + auto buf = SP(new CDRMDumbBuffer(params, self, swapchain_)); + if (!buf->good()) + return nullptr; + return buf; +} + +SP Aquamarine::CDRMDumbAllocator::getBackend() { + return backend.lock(); +} + +int Aquamarine::CDRMDumbAllocator::drmFD() { + return drmfd; +} + +eAllocatorType Aquamarine::CDRMDumbAllocator::type() { + return eAllocatorType::AQ_ALLOCATOR_TYPE_DRM_DUMB; +} + +Aquamarine::CDRMDumbAllocator::CDRMDumbAllocator(int fd_, Hyprutils::Memory::CWeakPointer backend_) : drmfd(fd_), backend(backend_) { + ; // nothing to do +} diff --git a/src/backend/Headless.cpp b/src/backend/Headless.cpp index 16fd5d9..b556a07 100644 --- a/src/backend/Headless.cpp +++ b/src/backend/Headless.cpp @@ -187,6 +187,10 @@ SP Aquamarine::CHeadlessBackend::preferredAllocator() { return backend->primaryAllocator; } +std::vector> Aquamarine::CHeadlessBackend::getAllocators() { + return {backend->primaryAllocator}; +} + bool Aquamarine::CHeadlessBackend::CTimer::expired() { return std::chrono::steady_clock::now() > when; } diff --git a/src/backend/Wayland.cpp b/src/backend/Wayland.cpp index e622fc0..ec81b07 100644 --- a/src/backend/Wayland.cpp +++ b/src/backend/Wayland.cpp @@ -442,6 +442,10 @@ SP Aquamarine::CWaylandBackend::preferredAllocator() { return backend->primaryAllocator; } +std::vector> Aquamarine::CWaylandBackend::getAllocators() { + return {backend->primaryAllocator}; +} + Aquamarine::CWaylandOutput::CWaylandOutput(const std::string& name_, Hyprutils::Memory::CWeakPointer backend_) : backend(backend_) { name = name_; diff --git a/src/backend/drm/DRM.cpp b/src/backend/drm/DRM.cpp index f4de19e..d4d0e78 100644 --- a/src/backend/drm/DRM.cpp +++ b/src/backend/drm/DRM.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -961,6 +962,10 @@ SP Aquamarine::CDRMBackend::preferredAllocator() { return backend->primaryAllocator; } +std::vector> Aquamarine::CDRMBackend::getAllocators() { + return {backend->primaryAllocator, dumbAllocator}; +} + bool Aquamarine::SDRMPlane::init(drmModePlane* plane) { id = plane->plane_id; @@ -1647,8 +1652,10 @@ SP Aquamarine::CDRMOutput::getBackend() { } bool Aquamarine::CDRMOutput::setCursor(SP buffer, const Vector2D& hotspot) { - if (buffer && !buffer->dmabuf().success) { - backend->backend->log(AQ_LOG_ERROR, "drm: Cursor buffer has to be a dmabuf"); + auto bufferType = buffer->type(); + + if ((bufferType == eBufferType::BUFFER_TYPE_SHM && !buffer->shm().success) || (bufferType == eBufferType::BUFFER_TYPE_DMABUF && !buffer->dmabuf().success)) { + backend->backend->log(AQ_LOG_ERROR, "drm: Invalid buffer passed to setCursor"); return false; } @@ -1663,18 +1670,23 @@ bool Aquamarine::CDRMOutput::setCursor(SP buffer, const Vector2D& hotsp if (backend->primary) { TRACE(backend->backend->log(AQ_LOG_TRACE, "drm: Backend requires cursor blit, blitting")); + // TODO: will this not implode on drm_dumb?! + if (!mgpu.cursorSwapchain) { TRACE(backend->backend->log(AQ_LOG_TRACE, "drm: No cursorSwapchain for blit, creating")); mgpu.cursorSwapchain = CSwapchain::create(backend->rendererState.allocator, backend.lock()); } - auto OPTIONS = mgpu.cursorSwapchain->currentOptions(); - OPTIONS.multigpu = false; - OPTIONS.scanout = true; - OPTIONS.cursor = true; - OPTIONS.format = buffer->dmabuf().format; - OPTIONS.size = buffer->dmabuf().size; - OPTIONS.length = 2; + const auto FORMAT = bufferType == eBufferType::BUFFER_TYPE_SHM ? buffer->shm().format : buffer->dmabuf().format; + const auto SIZE = bufferType == eBufferType::BUFFER_TYPE_SHM ? buffer->shm().size : buffer->dmabuf().size; + + auto OPTIONS = mgpu.cursorSwapchain->currentOptions(); + OPTIONS.multigpu = false; + OPTIONS.scanout = true; + OPTIONS.cursor = true; + OPTIONS.format = FORMAT; + OPTIONS.size = SIZE; + OPTIONS.length = 2; if (!mgpu.cursorSwapchain->reconfigure(OPTIONS)) { backend->backend->log(AQ_LOG_ERROR, "drm: Backend requires blit, but the mgpu cursorSwapchain failed reconfiguring"); @@ -1807,8 +1819,8 @@ Aquamarine::CDRMFB::CDRMFB(SP buffer_, Hyprutils::Memory::CWeakPointer< void Aquamarine::CDRMFB::import() { auto attrs = buffer->dmabuf(); - if (!attrs.success) { - backend->backend->log(AQ_LOG_ERROR, "drm: Buffer submitted has no dmabuf"); + if (!attrs.success && !buffer->drmHandle()) { + backend->backend->log(AQ_LOG_ERROR, "drm: Buffer submitted has no dmabuf or a drm handle"); return; } @@ -1819,16 +1831,19 @@ void Aquamarine::CDRMFB::import() { // TODO: check format - for (int i = 0; i < attrs.planes; ++i) { - int ret = drmPrimeFDToHandle(backend->gpu->fd, attrs.fds.at(i), &boHandles[i]); - if (ret) { - backend->backend->log(AQ_LOG_ERROR, "drm: drmPrimeFDToHandle failed"); - drop(); - return; - } + if (!buffer->drmHandle()) { + for (int i = 0; i < attrs.planes; ++i) { + int ret = drmPrimeFDToHandle(backend->gpu->fd, attrs.fds.at(i), &boHandles[i]); + if (ret) { + backend->backend->log(AQ_LOG_ERROR, "drm: drmPrimeFDToHandle failed"); + drop(); + return; + } - TRACE(backend->backend->log(AQ_LOG_TRACE, std::format("drm: CDRMFB: plane {} has fd {}, got handle {}", i, attrs.fds.at(i), boHandles.at(i)))); - } + TRACE(backend->backend->log(AQ_LOG_TRACE, std::format("drm: CDRMFB: plane {} has fd {}, got handle {}", i, attrs.fds.at(i), boHandles.at(i)))); + } + } else + boHandles = {buffer->drmHandle(), 0, 0, 0}; id = submitBuffer(); if (!id) { @@ -1915,34 +1930,48 @@ void Aquamarine::CDRMFB::drop() { } uint32_t Aquamarine::CDRMFB::submitBuffer() { - auto attrs = buffer->dmabuf(); - uint32_t newID = 0; - std::array mods = {0, 0, 0, 0}; - for (size_t i = 0; i < attrs.planes; ++i) { - mods[i] = attrs.modifier; - } - - if (backend->drmProps.supportsAddFb2Modifiers && attrs.modifier != DRM_FORMAT_MOD_INVALID) { - TRACE(backend->backend->log(AQ_LOG_TRACE, - std::format("drm: Using drmModeAddFB2WithModifiers to import buffer into KMS: Size {} with format {} and mod {}", attrs.size, - fourccToName(attrs.format), attrs.modifier))); - if (drmModeAddFB2WithModifiers(backend->gpu->fd, attrs.size.x, attrs.size.y, attrs.format, boHandles.data(), attrs.strides.data(), attrs.offsets.data(), mods.data(), - &newID, DRM_MODE_FB_MODIFIERS)) { - backend->backend->log(AQ_LOG_ERROR, "drm: Failed to submit a buffer with drmModeAddFB2WithModifiers"); - return 0; - } - } else { - if (attrs.modifier != DRM_FORMAT_MOD_INVALID && attrs.modifier != DRM_FORMAT_MOD_LINEAR) { - backend->backend->log(AQ_LOG_ERROR, "drm: drmModeAddFB2WithModifiers unsupported and buffer has explicit modifiers"); - return 0; + uint32_t newID = 0; + + if (buffer->type() == eBufferType::BUFFER_TYPE_DMABUF) { + + auto attrs = buffer->dmabuf(); + + std::array mods = {0, 0, 0, 0}; + for (size_t i = 0; i < attrs.planes; ++i) { + mods[i] = attrs.modifier; } - TRACE(backend->backend->log( - AQ_LOG_TRACE, - std::format("drm: Using drmModeAddFB2 to import buffer into KMS: Size {} with format {} and mod {}", attrs.size, fourccToName(attrs.format), attrs.modifier))); + if (backend->drmProps.supportsAddFb2Modifiers && attrs.modifier != DRM_FORMAT_MOD_INVALID) { + TRACE(backend->backend->log(AQ_LOG_TRACE, + std::format("drm: Using drmModeAddFB2WithModifiers to import buffer into KMS: Size {} with format {} and mod {}", attrs.size, + fourccToName(attrs.format), attrs.modifier))); + if (drmModeAddFB2WithModifiers(backend->gpu->fd, attrs.size.x, attrs.size.y, attrs.format, boHandles.data(), attrs.strides.data(), attrs.offsets.data(), mods.data(), + &newID, DRM_MODE_FB_MODIFIERS)) { + backend->backend->log(AQ_LOG_ERROR, "drm: Failed to submit a buffer with drmModeAddFB2WithModifiers"); + return 0; + } + } else { + if (attrs.modifier != DRM_FORMAT_MOD_INVALID && attrs.modifier != DRM_FORMAT_MOD_LINEAR) { + backend->backend->log(AQ_LOG_ERROR, "drm: drmModeAddFB2WithModifiers unsupported and buffer has explicit modifiers"); + return 0; + } + + TRACE(backend->backend->log( + AQ_LOG_TRACE, + std::format("drm: Using drmModeAddFB2 to import buffer into KMS: Size {} with format {} and mod {}", attrs.size, fourccToName(attrs.format), attrs.modifier))); + + if (drmModeAddFB2(backend->gpu->fd, attrs.size.x, attrs.size.y, attrs.format, boHandles.data(), attrs.strides.data(), attrs.offsets.data(), &newID, 0)) { + backend->backend->log(AQ_LOG_ERROR, "drm: Failed to submit a buffer with drmModeAddFB2"); + return 0; + } + } + } else { + auto attrs = buffer->shm(); + const uint32_t strides[4] = {(uint32_t)attrs.stride, 0, 0, 0}; + const uint32_t offsets[4] = {0, 0, 0, 0}; - if (drmModeAddFB2(backend->gpu->fd, attrs.size.x, attrs.size.y, attrs.format, boHandles.data(), attrs.strides.data(), attrs.offsets.data(), &newID, 0)) { - backend->backend->log(AQ_LOG_ERROR, "drm: Failed to submit a buffer with drmModeAddFB2"); + if (drmModeAddFB2(backend->gpu->fd, attrs.size.x, attrs.size.y, attrs.format, boHandles.data(), strides, offsets, &newID, 0)) { + backend->backend->log(AQ_LOG_ERROR, "drm: Failed to submit a shm buffer with drmModeAddFB2"); return 0; } } diff --git a/src/buffer/Buffer.cpp b/src/buffer/Buffer.cpp index 8197742..e0b0243 100644 --- a/src/buffer/Buffer.cpp +++ b/src/buffer/Buffer.cpp @@ -39,3 +39,7 @@ void Aquamarine::IBuffer::unlock() { bool Aquamarine::IBuffer::locked() { return locks; } + +uint32_t Aquamarine::IBuffer::drmHandle() { + return 0; +} From 588893c07b1e674e18686e0867341b071b8f6936 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 18:49:15 +0000 Subject: [PATCH 2/8] work --- src/allocator/DRMDumb.cpp | 9 ++++++--- src/backend/drm/DRM.cpp | 25 +++++++++++++++---------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/allocator/DRMDumb.cpp b/src/allocator/DRMDumb.cpp index bb673e3..4edff96 100644 --- a/src/allocator/DRMDumb.cpp +++ b/src/allocator/DRMDumb.cpp @@ -35,8 +35,9 @@ Aquamarine::CDRMDumbBuffer::CDRMDumbBuffer(const SAllocatorBufferParams& params, size = request.size; pixelSize = {(double)request.width, (double)request.height}; - attrs.size = pixelSize; - attrs.fd = request.handle; + attrs.size = pixelSize; + attrs.fd = request.handle; + attrs.stride = stride; drm_mode_map_dumb request2 = { .handle = handle, @@ -115,7 +116,9 @@ Aquamarine::CDRMDumbAllocator::~CDRMDumbAllocator() { } SP Aquamarine::CDRMDumbAllocator::create(int drmfd_, Hyprutils::Memory::CWeakPointer backend_) { - return SP(new CDRMDumbAllocator(drmfd_, backend_)); + auto a = SP(new CDRMDumbAllocator(drmfd_, backend_)); + a->self = a; + return a; } SP Aquamarine::CDRMDumbAllocator::acquire(const SAllocatorBufferParams& params, SP swapchain_) { diff --git a/src/backend/drm/DRM.cpp b/src/backend/drm/DRM.cpp index d4d0e78..1290980 100644 --- a/src/backend/drm/DRM.cpp +++ b/src/backend/drm/DRM.cpp @@ -256,6 +256,8 @@ std::vector> Aquamarine::CDRMBackend::attempt(SP backe newPrimary = drmBackend; } + drmBackend->dumbAllocator = CDRMDumbAllocator::create(gpu->fd, backend); + backends.emplace_back(drmBackend); // so that session can handle udev change/remove events for this gpu @@ -1652,19 +1654,24 @@ SP Aquamarine::CDRMOutput::getBackend() { } bool Aquamarine::CDRMOutput::setCursor(SP buffer, const Vector2D& hotspot) { - auto bufferType = buffer->type(); - - if ((bufferType == eBufferType::BUFFER_TYPE_SHM && !buffer->shm().success) || (bufferType == eBufferType::BUFFER_TYPE_DMABUF && !buffer->dmabuf().success)) { - backend->backend->log(AQ_LOG_ERROR, "drm: Invalid buffer passed to setCursor"); - return false; - } - if (!connector->crtc) return false; if (!buffer) setCursorVisible(false); else { + auto bufferType = buffer->type(); + + if (!buffer->good()) { + backend->backend->log(AQ_LOG_ERROR, "drm: bad buffer passed to setCursor"); + return false; + } + + if ((bufferType == eBufferType::BUFFER_TYPE_SHM && !buffer->shm().success) || (bufferType == eBufferType::BUFFER_TYPE_DMABUF && !buffer->dmabuf().success)) { + backend->backend->log(AQ_LOG_ERROR, "drm: Invalid buffer passed to setCursor"); + return false; + } + SP fb; if (backend->primary) { @@ -1933,10 +1940,8 @@ uint32_t Aquamarine::CDRMFB::submitBuffer() { uint32_t newID = 0; if (buffer->type() == eBufferType::BUFFER_TYPE_DMABUF) { - auto attrs = buffer->dmabuf(); - - std::array mods = {0, 0, 0, 0}; + std::array mods = {0, 0, 0, 0}; for (size_t i = 0; i < attrs.planes; ++i) { mods[i] = attrs.modifier; } From e844282d1d6e4b6295c331ac2617d0a78a46fff9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 18:49:41 +0000 Subject: [PATCH 3/8] work --- src/allocator/DRMDumb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/allocator/DRMDumb.cpp b/src/allocator/DRMDumb.cpp index 4edff96..9c54f72 100644 --- a/src/allocator/DRMDumb.cpp +++ b/src/allocator/DRMDumb.cpp @@ -50,7 +50,7 @@ Aquamarine::CDRMDumbBuffer::CDRMDumbBuffer(const SAllocatorBufferParams& params, data = (uint8_t*)mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, allocator->drmFD(), request2.offset); if (!data) { - allocator->backend->log(AQ_LOG_ERROR, "failed to mmmap a drm_dumb buffer"); + allocator->backend->log(AQ_LOG_ERROR, "failed to mmap a drm_dumb buffer"); return; } From cac883a39c777ff2609f52881132ca0a7eecd7a6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 19:00:02 +0000 Subject: [PATCH 4/8] maybe dont kill the kernel --- include/aquamarine/allocator/DRMDumb.hpp | 4 ++-- include/aquamarine/buffer/Buffer.hpp | 2 +- src/allocator/DRMDumb.cpp | 15 ++++++++++++++- src/backend/drm/DRM.cpp | 9 +++++---- src/buffer/Buffer.cpp | 2 +- 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/include/aquamarine/allocator/DRMDumb.hpp b/include/aquamarine/allocator/DRMDumb.hpp index 65d8173..8006fed 100644 --- a/include/aquamarine/allocator/DRMDumb.hpp +++ b/include/aquamarine/allocator/DRMDumb.hpp @@ -19,7 +19,7 @@ namespace Aquamarine { virtual SSHMAttrs shm(); virtual std::tuple beginDataPtr(uint32_t flags); virtual void endDataPtr(); - virtual uint32_t drmHandle(); + virtual uint32_t drmID(); private: CDRMDumbBuffer(const SAllocatorBufferParams& params, Hyprutils::Memory::CWeakPointer allocator_, @@ -28,7 +28,7 @@ namespace Aquamarine { Hyprutils::Memory::CWeakPointer allocator; // - uint32_t drmID = 0; + uint32_t idrmID = 0; Hyprutils::Math::Vector2D pixelSize; uint32_t stride = 0, handle = 0; uint64_t size = 0; diff --git a/include/aquamarine/buffer/Buffer.hpp b/include/aquamarine/buffer/Buffer.hpp index 158ee9e..eba2558 100644 --- a/include/aquamarine/buffer/Buffer.hpp +++ b/include/aquamarine/buffer/Buffer.hpp @@ -60,7 +60,7 @@ namespace Aquamarine { virtual void lock(); virtual void unlock(); virtual bool locked(); - virtual uint32_t drmHandle(); + virtual uint32_t drmID(); Hyprutils::Math::Vector2D size; bool opaque = false; diff --git a/src/allocator/DRMDumb.cpp b/src/allocator/DRMDumb.cpp index 9c54f72..e93c9aa 100644 --- a/src/allocator/DRMDumb.cpp +++ b/src/allocator/DRMDumb.cpp @@ -39,6 +39,16 @@ Aquamarine::CDRMDumbBuffer::CDRMDumbBuffer(const SAllocatorBufferParams& params, attrs.fd = request.handle; attrs.stride = stride; + uint32_t handles[4] = {handle, 0, 0, 0}; + uint32_t strides[4] = {stride, 0, 0, 0}; + uint32_t offsets[4] = {0, 0, 0, 0}; + + // these buffers are tied to drm... we need to import them here. CDRMFB will not be clean anymore... weeee... + if (int ret = drmModeAddFB2(allocator->drmFD(), params.size.x, params.size.y, params.format, handles, strides, offsets, &idrmID, 0); ret < 0) { + allocator->backend->log(AQ_LOG_ERROR, std::format("failed to drmModeAddFB2 a drm_dumb buffer: {}", strerror(-ret))); + return; + } + drm_mode_map_dumb request2 = { .handle = handle, }; @@ -69,6 +79,9 @@ Aquamarine::CDRMDumbBuffer::~CDRMDumbBuffer() { if (data) munmap(data, size); + if (idrmID) + drmModeRmFB(allocator->drmFD(), idrmID); + drm_mode_destroy_dumb request = { .handle = handle, }; @@ -107,7 +120,7 @@ void Aquamarine::CDRMDumbBuffer::endDataPtr() { ; // nothing to do } -uint32_t Aquamarine::CDRMDumbBuffer::drmHandle() { +uint32_t Aquamarine::CDRMDumbBuffer::drmID() { return handle; } diff --git a/src/backend/drm/DRM.cpp b/src/backend/drm/DRM.cpp index 1290980..3032c8a 100644 --- a/src/backend/drm/DRM.cpp +++ b/src/backend/drm/DRM.cpp @@ -1826,7 +1826,7 @@ Aquamarine::CDRMFB::CDRMFB(SP buffer_, Hyprutils::Memory::CWeakPointer< void Aquamarine::CDRMFB::import() { auto attrs = buffer->dmabuf(); - if (!attrs.success && !buffer->drmHandle()) { + if (!attrs.success && !buffer->drmID()) { backend->backend->log(AQ_LOG_ERROR, "drm: Buffer submitted has no dmabuf or a drm handle"); return; } @@ -1838,7 +1838,7 @@ void Aquamarine::CDRMFB::import() { // TODO: check format - if (!buffer->drmHandle()) { + if (!buffer->drmID()) { for (int i = 0; i < attrs.planes; ++i) { int ret = drmPrimeFDToHandle(backend->gpu->fd, attrs.fds.at(i), &boHandles[i]); if (ret) { @@ -1849,10 +1849,11 @@ void Aquamarine::CDRMFB::import() { TRACE(backend->backend->log(AQ_LOG_TRACE, std::format("drm: CDRMFB: plane {} has fd {}, got handle {}", i, attrs.fds.at(i), boHandles.at(i)))); } + + id = submitBuffer(); } else - boHandles = {buffer->drmHandle(), 0, 0, 0}; + id = buffer->drmID(); - id = submitBuffer(); if (!id) { backend->backend->log(AQ_LOG_ERROR, "drm: Failed to submit a buffer to KMS"); buffer->attachments.add(makeShared()); diff --git a/src/buffer/Buffer.cpp b/src/buffer/Buffer.cpp index e0b0243..2ef5b41 100644 --- a/src/buffer/Buffer.cpp +++ b/src/buffer/Buffer.cpp @@ -40,6 +40,6 @@ bool Aquamarine::IBuffer::locked() { return locks; } -uint32_t Aquamarine::IBuffer::drmHandle() { +uint32_t Aquamarine::IBuffer::drmID() { return 0; } From 1cdd74c967696fd49324a3a60b4372ed8789127e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 19:21:41 +0000 Subject: [PATCH 5/8] fixes but kernel dies again :( --- src/allocator/DRMDumb.cpp | 10 +++++++--- src/backend/drm/DRM.cpp | 3 +-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/allocator/DRMDumb.cpp b/src/allocator/DRMDumb.cpp index e93c9aa..4d812f8 100644 --- a/src/allocator/DRMDumb.cpp +++ b/src/allocator/DRMDumb.cpp @@ -64,15 +64,19 @@ Aquamarine::CDRMDumbBuffer::CDRMDumbBuffer(const SAllocatorBufferParams& params, return; } - // null the entire buffer so we dont get garbage - memset(data, 0x00, size); + // set the entire buffer so we dont get garbage + memset(data, 0xFF, size); attrs.success = true; + + allocator->backend->log(AQ_LOG_DEBUG, std::format("DRM Dumb: Allocated a new buffer with drm id {}, size {} and format {}", idrmID, attrs.size, fourccToName(attrs.format))); } Aquamarine::CDRMDumbBuffer::~CDRMDumbBuffer() { events.destroy.emit(); + TRACE(allocator->backend->log(AQ_LOG_TRACE, std::format("DRM Dumb: dropping buffer {}", idrmID))); + if (handle == 0) return; @@ -121,7 +125,7 @@ void Aquamarine::CDRMDumbBuffer::endDataPtr() { } uint32_t Aquamarine::CDRMDumbBuffer::drmID() { - return handle; + return idrmID; } Aquamarine::CDRMDumbAllocator::~CDRMDumbAllocator() { diff --git a/src/backend/drm/DRM.cpp b/src/backend/drm/DRM.cpp index 3032c8a..1a0916a 100644 --- a/src/backend/drm/DRM.cpp +++ b/src/backend/drm/DRM.cpp @@ -1863,7 +1863,6 @@ void Aquamarine::CDRMFB::import() { TRACE(backend->backend->log(AQ_LOG_TRACE, std::format("drm: new buffer {}", id))); - // FIXME: why does this implode when it doesnt on wlroots or kwin? closeHandles(); listeners.destroyBuffer = buffer->events.destroy.registerListener([this](std::any d) { @@ -1922,7 +1921,7 @@ void Aquamarine::CDRMFB::drop() { dropped = true; - if (!id) + if (!id || buffer->drmID() /* drmID means the buffer manages itself */) return; closeHandles(); From d3b58683cc6933d5252c37d0405edebb910a8b08 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 19:35:51 +0000 Subject: [PATCH 6/8] life is a piece of shit --- include/aquamarine/allocator/DRMDumb.hpp | 11 ++--- include/aquamarine/buffer/Buffer.hpp | 1 - src/allocator/DRMDumb.cpp | 63 ++++++++---------------- src/backend/drm/DRM.cpp | 28 +++++------ src/buffer/Buffer.cpp | 4 -- 5 files changed, 38 insertions(+), 69 deletions(-) diff --git a/include/aquamarine/allocator/DRMDumb.hpp b/include/aquamarine/allocator/DRMDumb.hpp index 8006fed..1ca37bc 100644 --- a/include/aquamarine/allocator/DRMDumb.hpp +++ b/include/aquamarine/allocator/DRMDumb.hpp @@ -16,10 +16,9 @@ namespace Aquamarine { virtual void update(const Hyprutils::Math::CRegion& damage); virtual bool isSynchronous(); virtual bool good(); - virtual SSHMAttrs shm(); + virtual SDMABUFAttrs dmabuf(); virtual std::tuple beginDataPtr(uint32_t flags); virtual void endDataPtr(); - virtual uint32_t drmID(); private: CDRMDumbBuffer(const SAllocatorBufferParams& params, Hyprutils::Memory::CWeakPointer allocator_, @@ -28,14 +27,14 @@ namespace Aquamarine { Hyprutils::Memory::CWeakPointer allocator; // - uint32_t idrmID = 0; Hyprutils::Math::Vector2D pixelSize; uint32_t stride = 0, handle = 0; - uint64_t size = 0; - uint8_t* data = nullptr; + uint64_t size = 0; + uint8_t* data = nullptr; + int primeFD = -1; // - SSHMAttrs attrs{.success = false}; + SDMABUFAttrs attrs{.success = false}; friend class CDRMDumbAllocator; }; diff --git a/include/aquamarine/buffer/Buffer.hpp b/include/aquamarine/buffer/Buffer.hpp index eba2558..99c21bf 100644 --- a/include/aquamarine/buffer/Buffer.hpp +++ b/include/aquamarine/buffer/Buffer.hpp @@ -60,7 +60,6 @@ namespace Aquamarine { virtual void lock(); virtual void unlock(); virtual bool locked(); - virtual uint32_t drmID(); Hyprutils::Math::Vector2D size; bool opaque = false; diff --git a/src/allocator/DRMDumb.cpp b/src/allocator/DRMDumb.cpp index 4d812f8..09cb37a 100644 --- a/src/allocator/DRMDumb.cpp +++ b/src/allocator/DRMDumb.cpp @@ -4,7 +4,9 @@ #include #include "FormatUtils.hpp" #include "Shared.hpp" +#include #include +#include #include #include #include @@ -19,47 +21,24 @@ Aquamarine::CDRMDumbBuffer::CDRMDumbBuffer(const SAllocatorBufferParams& params, Hyprutils::Memory::CSharedPointer swapchain) : allocator(allocator_) { attrs.format = params.format; - drm_mode_create_dumb request = { - .height = (uint32_t)params.size.y, - .width = (uint32_t)params.size.x, - .bpp = 32, - }; - - if (int ret = drmIoctl(allocator->drmFD(), DRM_IOCTL_MODE_CREATE_DUMB, &request); ret < 0) { + if (int ret = drmModeCreateDumbBuffer(allocator->drmFD(), params.size.x, params.size.y, 32, 0, &handle, &stride, &size); ret < 0) { allocator->backend->log(AQ_LOG_ERROR, std::format("failed to create a drm_dumb buffer: {}", strerror(-ret))); return; } - stride = request.pitch; - handle = request.handle; - size = request.size; - pixelSize = {(double)request.width, (double)request.height}; - - attrs.size = pixelSize; - attrs.fd = request.handle; - attrs.stride = stride; + pixelSize = {(double)params.size.x, (double)params.size.y}; - uint32_t handles[4] = {handle, 0, 0, 0}; - uint32_t strides[4] = {stride, 0, 0, 0}; - uint32_t offsets[4] = {0, 0, 0, 0}; - - // these buffers are tied to drm... we need to import them here. CDRMFB will not be clean anymore... weeee... - if (int ret = drmModeAddFB2(allocator->drmFD(), params.size.x, params.size.y, params.format, handles, strides, offsets, &idrmID, 0); ret < 0) { - allocator->backend->log(AQ_LOG_ERROR, std::format("failed to drmModeAddFB2 a drm_dumb buffer: {}", strerror(-ret))); - return; - } - - drm_mode_map_dumb request2 = { - .handle = handle, - }; + attrs.size = pixelSize; + attrs.strides.at(0) = stride; - if (int ret = drmIoctl(allocator->drmFD(), DRM_IOCTL_MODE_MAP_DUMB, &request2); ret < 0) { + uint64_t offset = 0; + if (int ret = drmModeMapDumbBuffer(allocator->drmFD(), handle, &offset); ret < 0) { allocator->backend->log(AQ_LOG_ERROR, std::format("failed to map a drm_dumb buffer: {}", strerror(-ret))); return; } - data = (uint8_t*)mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, allocator->drmFD(), request2.offset); - if (!data) { + data = (uint8_t*)mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, allocator->drmFD(), offset); + if (data == MAP_FAILED) { allocator->backend->log(AQ_LOG_ERROR, "failed to mmap a drm_dumb buffer"); return; } @@ -67,15 +46,22 @@ Aquamarine::CDRMDumbBuffer::CDRMDumbBuffer(const SAllocatorBufferParams& params, // set the entire buffer so we dont get garbage memset(data, 0xFF, size); + if (int ret = drmPrimeHandleToFD(allocator->drmFD(), handle, DRM_CLOEXEC, &primeFD); ret < 0) { + allocator->backend->log(AQ_LOG_ERROR, std::format("failed to map a drm_dumb buffer: {}", strerror(-ret))); + return; + } + + attrs.fds.at(0) = primeFD; + attrs.success = true; - allocator->backend->log(AQ_LOG_DEBUG, std::format("DRM Dumb: Allocated a new buffer with drm id {}, size {} and format {}", idrmID, attrs.size, fourccToName(attrs.format))); + allocator->backend->log(AQ_LOG_DEBUG, std::format("DRM Dumb: Allocated a new buffer with primeFD {}, size {} and format {}", primeFD, attrs.size, fourccToName(attrs.format))); } Aquamarine::CDRMDumbBuffer::~CDRMDumbBuffer() { events.destroy.emit(); - TRACE(allocator->backend->log(AQ_LOG_TRACE, std::format("DRM Dumb: dropping buffer {}", idrmID))); + TRACE(allocator->backend->log(AQ_LOG_TRACE, std::format("DRM Dumb: dropping buffer {}", primeFD))); if (handle == 0) return; @@ -83,9 +69,6 @@ Aquamarine::CDRMDumbBuffer::~CDRMDumbBuffer() { if (data) munmap(data, size); - if (idrmID) - drmModeRmFB(allocator->drmFD(), idrmID); - drm_mode_destroy_dumb request = { .handle = handle, }; @@ -97,7 +80,7 @@ eBufferCapability Aquamarine::CDRMDumbBuffer::caps() { } eBufferType Aquamarine::CDRMDumbBuffer::type() { - return eBufferType::BUFFER_TYPE_SHM; + return eBufferType::BUFFER_TYPE_DMABUF; } void Aquamarine::CDRMDumbBuffer::update(const Hyprutils::Math::CRegion& damage) { @@ -112,7 +95,7 @@ bool Aquamarine::CDRMDumbBuffer::good() { return attrs.success && data; } -SSHMAttrs Aquamarine::CDRMDumbBuffer::shm() { +SDMABUFAttrs Aquamarine::CDRMDumbBuffer::dmabuf() { return attrs; } @@ -124,10 +107,6 @@ void Aquamarine::CDRMDumbBuffer::endDataPtr() { ; // nothing to do } -uint32_t Aquamarine::CDRMDumbBuffer::drmID() { - return idrmID; -} - Aquamarine::CDRMDumbAllocator::~CDRMDumbAllocator() { ; // nothing to do } diff --git a/src/backend/drm/DRM.cpp b/src/backend/drm/DRM.cpp index 1a0916a..592f6f0 100644 --- a/src/backend/drm/DRM.cpp +++ b/src/backend/drm/DRM.cpp @@ -1826,7 +1826,7 @@ Aquamarine::CDRMFB::CDRMFB(SP buffer_, Hyprutils::Memory::CWeakPointer< void Aquamarine::CDRMFB::import() { auto attrs = buffer->dmabuf(); - if (!attrs.success && !buffer->drmID()) { + if (!attrs.success) { backend->backend->log(AQ_LOG_ERROR, "drm: Buffer submitted has no dmabuf or a drm handle"); return; } @@ -1837,22 +1837,18 @@ void Aquamarine::CDRMFB::import() { } // TODO: check format - - if (!buffer->drmID()) { - for (int i = 0; i < attrs.planes; ++i) { - int ret = drmPrimeFDToHandle(backend->gpu->fd, attrs.fds.at(i), &boHandles[i]); - if (ret) { - backend->backend->log(AQ_LOG_ERROR, "drm: drmPrimeFDToHandle failed"); - drop(); - return; - } - - TRACE(backend->backend->log(AQ_LOG_TRACE, std::format("drm: CDRMFB: plane {} has fd {}, got handle {}", i, attrs.fds.at(i), boHandles.at(i)))); + for (int i = 0; i < attrs.planes; ++i) { + int ret = drmPrimeFDToHandle(backend->gpu->fd, attrs.fds.at(i), &boHandles[i]); + if (ret) { + backend->backend->log(AQ_LOG_ERROR, "drm: drmPrimeFDToHandle failed"); + drop(); + return; } - id = submitBuffer(); - } else - id = buffer->drmID(); + TRACE(backend->backend->log(AQ_LOG_TRACE, std::format("drm: CDRMFB: plane {} has fd {}, got handle {}", i, attrs.fds.at(i), boHandles.at(i)))); + } + + id = submitBuffer(); if (!id) { backend->backend->log(AQ_LOG_ERROR, "drm: Failed to submit a buffer to KMS"); @@ -1921,7 +1917,7 @@ void Aquamarine::CDRMFB::drop() { dropped = true; - if (!id || buffer->drmID() /* drmID means the buffer manages itself */) + if (!id) return; closeHandles(); diff --git a/src/buffer/Buffer.cpp b/src/buffer/Buffer.cpp index 2ef5b41..8197742 100644 --- a/src/buffer/Buffer.cpp +++ b/src/buffer/Buffer.cpp @@ -39,7 +39,3 @@ void Aquamarine::IBuffer::unlock() { bool Aquamarine::IBuffer::locked() { return locks; } - -uint32_t Aquamarine::IBuffer::drmID() { - return 0; -} From ce8047e19e635050cef1e94dc41f5f17e67194fb Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 19:52:00 +0000 Subject: [PATCH 7/8] e --- src/allocator/DRMDumb.cpp | 25 ++++++++++++++--- src/backend/drm/DRM.cpp | 58 +++++++++++++++++---------------------- 2 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/allocator/DRMDumb.cpp b/src/allocator/DRMDumb.cpp index 09cb37a..9170e4b 100644 --- a/src/allocator/DRMDumb.cpp +++ b/src/allocator/DRMDumb.cpp @@ -30,6 +30,7 @@ Aquamarine::CDRMDumbBuffer::CDRMDumbBuffer(const SAllocatorBufferParams& params, attrs.size = pixelSize; attrs.strides.at(0) = stride; + attrs.planes = 1; uint64_t offset = 0; if (int ret = drmModeMapDumbBuffer(allocator->drmFD(), handle, &offset); ret < 0) { @@ -69,10 +70,7 @@ Aquamarine::CDRMDumbBuffer::~CDRMDumbBuffer() { if (data) munmap(data, size); - drm_mode_destroy_dumb request = { - .handle = handle, - }; - drmIoctl(allocator->drmFD(), DRM_IOCTL_MODE_DESTROY_DUMB, &request); + drmModeDestroyDumbBuffer(allocator->drmFD(), handle); } eBufferCapability Aquamarine::CDRMDumbBuffer::caps() { @@ -112,8 +110,27 @@ Aquamarine::CDRMDumbAllocator::~CDRMDumbAllocator() { } SP Aquamarine::CDRMDumbAllocator::create(int drmfd_, Hyprutils::Memory::CWeakPointer backend_) { + if (drmGetNodeTypeFromFd(drmfd_) != DRM_NODE_PRIMARY) { + backend_->log(AQ_LOG_ERROR, "DRM Dumb: Cannot create allocator when drmfd is not the primary node"); + return nullptr; + } + + uint64_t hasDumb = 0; + if (drmGetCap(drmfd_, DRM_CAP_DUMB_BUFFER, &hasDumb) < 0) { + backend_->log(AQ_LOG_ERROR, "DRM Dumb: Failed to query hasDumb"); + return nullptr; + } + + if (!hasDumb) { + backend_->log(AQ_LOG_ERROR, "DRM Dumb: hasDumb is false, gpu driver doesn't support dumb buffers!"); + return nullptr; + } + auto a = SP(new CDRMDumbAllocator(drmfd_, backend_)); a->self = a; + + backend_->log(AQ_LOG_DEBUG, "DRM Dumb: created a dumb allocator"); + return a; } diff --git a/src/backend/drm/DRM.cpp b/src/backend/drm/DRM.cpp index 592f6f0..f69a444 100644 --- a/src/backend/drm/DRM.cpp +++ b/src/backend/drm/DRM.cpp @@ -1935,44 +1935,36 @@ void Aquamarine::CDRMFB::drop() { uint32_t Aquamarine::CDRMFB::submitBuffer() { uint32_t newID = 0; - if (buffer->type() == eBufferType::BUFFER_TYPE_DMABUF) { - auto attrs = buffer->dmabuf(); - std::array mods = {0, 0, 0, 0}; - for (size_t i = 0; i < attrs.planes; ++i) { - mods[i] = attrs.modifier; - } - - if (backend->drmProps.supportsAddFb2Modifiers && attrs.modifier != DRM_FORMAT_MOD_INVALID) { - TRACE(backend->backend->log(AQ_LOG_TRACE, - std::format("drm: Using drmModeAddFB2WithModifiers to import buffer into KMS: Size {} with format {} and mod {}", attrs.size, - fourccToName(attrs.format), attrs.modifier))); - if (drmModeAddFB2WithModifiers(backend->gpu->fd, attrs.size.x, attrs.size.y, attrs.format, boHandles.data(), attrs.strides.data(), attrs.offsets.data(), mods.data(), - &newID, DRM_MODE_FB_MODIFIERS)) { - backend->backend->log(AQ_LOG_ERROR, "drm: Failed to submit a buffer with drmModeAddFB2WithModifiers"); - return 0; - } - } else { - if (attrs.modifier != DRM_FORMAT_MOD_INVALID && attrs.modifier != DRM_FORMAT_MOD_LINEAR) { - backend->backend->log(AQ_LOG_ERROR, "drm: drmModeAddFB2WithModifiers unsupported and buffer has explicit modifiers"); - return 0; - } + if (!buffer->dmabuf().success) + return 0; - TRACE(backend->backend->log( - AQ_LOG_TRACE, - std::format("drm: Using drmModeAddFB2 to import buffer into KMS: Size {} with format {} and mod {}", attrs.size, fourccToName(attrs.format), attrs.modifier))); + auto attrs = buffer->dmabuf(); + std::array mods = {0, 0, 0, 0}; + for (size_t i = 0; i < attrs.planes; ++i) { + mods[i] = attrs.modifier; + } - if (drmModeAddFB2(backend->gpu->fd, attrs.size.x, attrs.size.y, attrs.format, boHandles.data(), attrs.strides.data(), attrs.offsets.data(), &newID, 0)) { - backend->backend->log(AQ_LOG_ERROR, "drm: Failed to submit a buffer with drmModeAddFB2"); - return 0; - } + if (backend->drmProps.supportsAddFb2Modifiers && attrs.modifier != DRM_FORMAT_MOD_INVALID) { + TRACE(backend->backend->log(AQ_LOG_TRACE, + std::format("drm: Using drmModeAddFB2WithModifiers to import buffer into KMS: Size {} with format {} and mod {}", attrs.size, + fourccToName(attrs.format), attrs.modifier))); + if (drmModeAddFB2WithModifiers(backend->gpu->fd, attrs.size.x, attrs.size.y, attrs.format, boHandles.data(), attrs.strides.data(), attrs.offsets.data(), mods.data(), + &newID, DRM_MODE_FB_MODIFIERS)) { + backend->backend->log(AQ_LOG_ERROR, "drm: Failed to submit a buffer with drmModeAddFB2WithModifiers"); + return 0; } } else { - auto attrs = buffer->shm(); - const uint32_t strides[4] = {(uint32_t)attrs.stride, 0, 0, 0}; - const uint32_t offsets[4] = {0, 0, 0, 0}; + if (attrs.modifier != DRM_FORMAT_MOD_INVALID && attrs.modifier != DRM_FORMAT_MOD_LINEAR) { + backend->backend->log(AQ_LOG_ERROR, "drm: drmModeAddFB2WithModifiers unsupported and buffer has explicit modifiers"); + return 0; + } + + TRACE(backend->backend->log( + AQ_LOG_TRACE, + std::format("drm: Using drmModeAddFB2 to import buffer into KMS: Size {} with format {} and mod {}", attrs.size, fourccToName(attrs.format), attrs.modifier))); - if (drmModeAddFB2(backend->gpu->fd, attrs.size.x, attrs.size.y, attrs.format, boHandles.data(), strides, offsets, &newID, 0)) { - backend->backend->log(AQ_LOG_ERROR, "drm: Failed to submit a shm buffer with drmModeAddFB2"); + if (drmModeAddFB2(backend->gpu->fd, attrs.size.x, attrs.size.y, attrs.format, boHandles.data(), attrs.strides.data(), attrs.offsets.data(), &newID, 0)) { + backend->backend->log(AQ_LOG_ERROR, "drm: Failed to submit a buffer with drmModeAddFB2"); return 0; } } From da616406088ffaac67cc35fbca94d27828d2156a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 10 Nov 2024 22:43:49 +0000 Subject: [PATCH 8/8] reer --- include/aquamarine/allocator/DRMDumb.hpp | 6 +++--- src/allocator/DRMDumb.cpp | 11 ++++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/aquamarine/allocator/DRMDumb.hpp b/include/aquamarine/allocator/DRMDumb.hpp index 1ca37bc..a5eca2c 100644 --- a/include/aquamarine/allocator/DRMDumb.hpp +++ b/include/aquamarine/allocator/DRMDumb.hpp @@ -29,9 +29,9 @@ namespace Aquamarine { // Hyprutils::Math::Vector2D pixelSize; uint32_t stride = 0, handle = 0; - uint64_t size = 0; - uint8_t* data = nullptr; - int primeFD = -1; + uint64_t bufferLen = 0; + uint8_t* data = nullptr; + int primeFD = -1; // SDMABUFAttrs attrs{.success = false}; diff --git a/src/allocator/DRMDumb.cpp b/src/allocator/DRMDumb.cpp index 9170e4b..e1fb32f 100644 --- a/src/allocator/DRMDumb.cpp +++ b/src/allocator/DRMDumb.cpp @@ -21,7 +21,7 @@ Aquamarine::CDRMDumbBuffer::CDRMDumbBuffer(const SAllocatorBufferParams& params, Hyprutils::Memory::CSharedPointer swapchain) : allocator(allocator_) { attrs.format = params.format; - if (int ret = drmModeCreateDumbBuffer(allocator->drmFD(), params.size.x, params.size.y, 32, 0, &handle, &stride, &size); ret < 0) { + if (int ret = drmModeCreateDumbBuffer(allocator->drmFD(), params.size.x, params.size.y, 32, 0, &handle, &stride, &bufferLen); ret < 0) { allocator->backend->log(AQ_LOG_ERROR, std::format("failed to create a drm_dumb buffer: {}", strerror(-ret))); return; } @@ -31,6 +31,7 @@ Aquamarine::CDRMDumbBuffer::CDRMDumbBuffer(const SAllocatorBufferParams& params, attrs.size = pixelSize; attrs.strides.at(0) = stride; attrs.planes = 1; + size = pixelSize; uint64_t offset = 0; if (int ret = drmModeMapDumbBuffer(allocator->drmFD(), handle, &offset); ret < 0) { @@ -38,14 +39,14 @@ Aquamarine::CDRMDumbBuffer::CDRMDumbBuffer(const SAllocatorBufferParams& params, return; } - data = (uint8_t*)mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, allocator->drmFD(), offset); + data = (uint8_t*)mmap(nullptr, bufferLen, PROT_READ | PROT_WRITE, MAP_SHARED, allocator->drmFD(), offset); if (data == MAP_FAILED) { allocator->backend->log(AQ_LOG_ERROR, "failed to mmap a drm_dumb buffer"); return; } // set the entire buffer so we dont get garbage - memset(data, 0xFF, size); + memset(data, 0xFF, bufferLen); if (int ret = drmPrimeHandleToFD(allocator->drmFD(), handle, DRM_CLOEXEC, &primeFD); ret < 0) { allocator->backend->log(AQ_LOG_ERROR, std::format("failed to map a drm_dumb buffer: {}", strerror(-ret))); @@ -68,7 +69,7 @@ Aquamarine::CDRMDumbBuffer::~CDRMDumbBuffer() { return; if (data) - munmap(data, size); + munmap(data, bufferLen); drmModeDestroyDumbBuffer(allocator->drmFD(), handle); } @@ -98,7 +99,7 @@ SDMABUFAttrs Aquamarine::CDRMDumbBuffer::dmabuf() { } std::tuple Aquamarine::CDRMDumbBuffer::beginDataPtr(uint32_t flags) { - return {data, attrs.format, size}; + return {data, attrs.format, bufferLen}; } void Aquamarine::CDRMDumbBuffer::endDataPtr() {