From abd58530c378c10904570f0f763b017646ecbea9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 17:56:49 +0000 Subject: [PATCH] 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 | 42 +++--- include/aquamarine/backend/Headless.hpp | 28 ++-- include/aquamarine/backend/Wayland.hpp | 27 ++-- 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 | 117 ++++++++++------- src/buffer/Buffer.cpp | 4 + 12 files changed, 363 insertions(+), 101 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(); + 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; + Hyprutils::Memory::CWeakPointer self; - void log(eBackendLogLevel, const std::string&); - bool sessionActive(); - int getNonMasterFD(); + void log(eBackendLogLevel, const std::string&); + bool sessionActive(); + int getNonMasterFD(); - std::vector idleCallbacks; - std::string gpuName; + 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(); + 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; + 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(); + 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; + 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; - } + uint32_t newID = 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; + 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; + } + + 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 { - 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; - } + 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}; - 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"); + 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; +}