Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dumb allocator #31

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions include/aquamarine/allocator/Dumb.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#pragma once

#include "Allocator.hpp"

namespace Aquamarine {
class CDumbAllocator;
class CBackend;
class CSwapchain;

class CDumbBuffer : public IBuffer {
public:
virtual ~CDumbBuffer();

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<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
virtual void endDataPtr();

private:
CDumbBuffer(const SAllocatorBufferParams& params, Hyprutils::Memory::CWeakPointer<CDumbAllocator> allocator_, Hyprutils::Memory::CSharedPointer<CSwapchain> swapchain);

Hyprutils::Memory::CWeakPointer<CDumbAllocator> allocator;

// dumb stuff
int drmFd = -1;
uint32_t handle = 0;
void* data = nullptr;
size_t length = 0;

SSHMAttrs attrs{.success = false};

friend class CDumbAllocator;
};

class CDumbAllocator : public IAllocator {
public:
~CDumbAllocator();
static Hyprutils::Memory::CSharedPointer<CDumbAllocator> create(int drmfd_, Hyprutils::Memory::CWeakPointer<CBackend> backend_);

virtual Hyprutils::Memory::CSharedPointer<IBuffer> acquire(const SAllocatorBufferParams& params, Hyprutils::Memory::CSharedPointer<CSwapchain> swapchain_);
virtual Hyprutils::Memory::CSharedPointer<CBackend> getBackend();
virtual int drmFD();

//
Hyprutils::Memory::CWeakPointer<CDumbAllocator> self;

private:
CDumbAllocator(int drmfd_, Hyprutils::Memory::CWeakPointer<CBackend> backend_);

// a vector purely for tracking (debugging) the buffers and nothing more
std::vector<Hyprutils::Memory::CWeakPointer<CDumbBuffer>> buffers;

int fd = -1;
Hyprutils::Memory::CWeakPointer<CBackend> backend;

friend class CDumbBuffer;
friend class CDRMRenderer;
};
};
1 change: 1 addition & 0 deletions include/aquamarine/allocator/Swapchain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@ namespace Aquamarine {
int lastAcquired = 0;

friend class CGBMBuffer;
friend class CDumbBuffer;
};
};
6 changes: 5 additions & 1 deletion include/aquamarine/backend/Backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ namespace Aquamarine {
virtual std::vector<SDRMFormat> getCursorFormats() = 0;
virtual bool createOutput(const std::string& name = "") = 0; // "" means auto
virtual Hyprutils::Memory::CSharedPointer<IAllocator> preferredAllocator() = 0;
virtual std::vector<SDRMFormat> getRenderableFormats(); // empty = use getRenderFormats
virtual Hyprutils::Memory::CSharedPointer<IAllocator> fallbackAllocator() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, no, no. The dumb allocator doesn't really hold any big allocs, so it should be per-drm-backend (can be always present, no big deal)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't really understand what needs to be done here. How HL should get access to dumb allocator?

Copy link
Member

@vaxerski vaxerski Jul 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in CDRMBackend SP<CDumbAllocator>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then it can ->output->backend, cast that to drm and ->dumballocator

return nullptr;
};
virtual std::vector<SDRMFormat> getRenderableFormats(); // empty = use getRenderFormats
};

class CBackend {
Expand Down Expand Up @@ -128,6 +131,7 @@ namespace Aquamarine {
} events;

Hyprutils::Memory::CSharedPointer<IAllocator> primaryAllocator;
Hyprutils::Memory::CSharedPointer<IAllocator> fallbackAllocator;
bool ready = false;
Hyprutils::Memory::CSharedPointer<CSession> session;

Expand Down
1 change: 1 addition & 0 deletions include/aquamarine/backend/DRM.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ namespace Aquamarine {
virtual std::vector<SDRMFormat> getCursorFormats();
virtual bool createOutput(const std::string& name = "");
virtual Hyprutils::Memory::CSharedPointer<IAllocator> preferredAllocator();
virtual Hyprutils::Memory::CSharedPointer<IAllocator> fallbackAllocator();
virtual std::vector<SDRMFormat> getRenderableFormats();

Hyprutils::Memory::CWeakPointer<CDRMBackend> self;
Expand Down
1 change: 1 addition & 0 deletions include/aquamarine/buffer/Buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace Aquamarine {
BUFFER_TYPE_DMABUF = 0,
BUFFER_TYPE_SHM,
BUFFER_TYPE_MISC,
BUFFER_TYPE_DUMB,
};

class CWLBufferResource;
Expand Down
169 changes: 169 additions & 0 deletions src/allocator/Dumb.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#include <aquamarine/allocator/Dumb.hpp>
#include <aquamarine/backend/Backend.hpp>
#include <aquamarine/allocator/Swapchain.hpp>
#include "FormatUtils.hpp"
#include "Shared.hpp"
#include "aquamarine/buffer/Buffer.hpp"
#include <cstring>
#include <fcntl.h>
#include <sys/mman.h>
#include <xf86drm.h>
#include <unistd.h>

using namespace Aquamarine;
using namespace Hyprutils::Memory;
#define SP CSharedPointer

Aquamarine::CDumbBuffer::CDumbBuffer(const SAllocatorBufferParams& params, Hyprutils::Memory::CWeakPointer<CDumbAllocator> allocator_,
Hyprutils::Memory::CSharedPointer<CSwapchain> swapchain) : allocator(allocator_) {
if (!allocator)
return;

drm_mode_create_dumb createArgs{
.height = uint32_t(params.size.x),
.width = uint32_t(params.size.y),
.bpp = 32,
};

TRACE(allocator->backend->log(AQ_LOG_TRACE, std::format("DUMB: Allocating a dumb buffer: size {}, format {}", params.size, fourccToName(params.format))));
if (drmIoctl(allocator->drmFD(), DRM_IOCTL_MODE_CREATE_DUMB, &createArgs) != 0) {
allocator->backend->log(AQ_LOG_ERROR, std::format("DUMB: DRM_IOCTL_MODE_CREATE_DUMB failed {}", strerror(errno)));
return;
}

int primeFd;
if (drmPrimeHandleToFD(allocator->drmFD(), createArgs.handle, DRM_CLOEXEC, &primeFd) != 0) {
allocator->backend->log(AQ_LOG_ERROR, std::format("DUMB: drmPrimeHandleToFD() failed {}", strerror(errno)));
drm_mode_destroy_dumb destroyArgs{
.handle = createArgs.handle,
};
drmIoctl(allocator->drmFD(), DRM_IOCTL_MODE_DESTROY_DUMB, &destroyArgs);
return;
}

drmFd = allocator->drmFD();
handle = createArgs.handle;
length = createArgs.pitch * params.size.y;

attrs.size = params.size;
attrs.format = DRM_FORMAT_ARGB8888;
attrs.offset = 0;
attrs.fd = primeFd;
attrs.stride = createArgs.pitch;

attrs.success = true;

allocator->backend->log(AQ_LOG_DEBUG, std::format("DUMB: Allocated a new dumb buffer with size {} and format {}", attrs.size, fourccToName(attrs.format)));
}

Aquamarine::CDumbBuffer::~CDumbBuffer() {
events.destroy.emit();

endDataPtr();

if (handle) {
drm_mode_destroy_dumb destroyArgs{
.handle = handle,
};
drmIoctl(drmFd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroyArgs);
}
}

eBufferCapability Aquamarine::CDumbBuffer::caps() {
return BUFFER_CAPABILITY_DATAPTR;
}

eBufferType Aquamarine::CDumbBuffer::type() {
return Aquamarine::eBufferType::BUFFER_TYPE_DUMB;
}

void Aquamarine::CDumbBuffer::update(const Hyprutils::Math::CRegion& damage) {
;
}

bool Aquamarine::CDumbBuffer::isSynchronous() {
return true;
}

bool Aquamarine::CDumbBuffer::good() {
return true;
}

SSHMAttrs Aquamarine::CDumbBuffer::shm() {
return attrs;
}

std::tuple<uint8_t*, uint32_t, size_t> Aquamarine::CDumbBuffer::beginDataPtr(uint32_t flags) {
if (!data) {
drm_mode_map_dumb mapArgs{
.handle = handle,
};
if (drmIoctl(drmFd, DRM_IOCTL_MODE_MAP_DUMB, &mapArgs) != 0) {
allocator->backend->log(AQ_LOG_ERROR, std::format("DUMB: DRM_IOCTL_MODE_MAP_DUMB failed {}", strerror(errno)));
return {};
}

void* address = mmap(nullptr, length, PROT_READ | PROT_WRITE, MAP_SHARED, drmFd, mapArgs.offset);
if (address == MAP_FAILED) {
allocator->backend->log(AQ_LOG_ERROR, std::format("DUMB: mmap failed {}", strerror(errno)));
return {};
}

data = address;
}

// FIXME: assumes a 32-bit pixel format
return {(uint8_t*)data, attrs.format, attrs.stride};
}

void Aquamarine::CDumbBuffer::endDataPtr() {
if (data) {
munmap(data, length);
data = nullptr;
}
}

CDumbAllocator::~CDumbAllocator() {}

SP<CDumbAllocator> Aquamarine::CDumbAllocator::create(int drmfd_, Hyprutils::Memory::CWeakPointer<CBackend> backend_) {
auto allocator = SP<CDumbAllocator>(new CDumbAllocator(drmfd_, backend_));

if (allocator->drmFD() < 0) {
backend_->log(AQ_LOG_ERROR, "Cannot create a Dumb Allocator: drm fd is required.");
return nullptr;
}

backend_->log(AQ_LOG_DEBUG, std::format("Created a Dumb Allocator"));

allocator->self = allocator;

return allocator;
}

Aquamarine::CDumbAllocator::CDumbAllocator(int drmfd_, Hyprutils::Memory::CWeakPointer<CBackend> backend_) : fd(drmfd_), backend(backend_) {}

SP<IBuffer> Aquamarine::CDumbAllocator::acquire(const SAllocatorBufferParams& params, Hyprutils::Memory::CSharedPointer<CSwapchain> swapchain_) {
if (params.size.x < 1 || params.size.y < 1) {
backend->log(AQ_LOG_ERROR, std::format("Couldn't allocate a dumb buffer with invalid size {}", params.size));
return nullptr;
}

auto newBuffer = SP<CDumbBuffer>(new CDumbBuffer(params, self, swapchain_));

if (!newBuffer->good()) {
backend->log(AQ_LOG_ERROR, std::format("Couldn't allocate a dumb buffer with size {} and format {}", params.size, fourccToName(params.format)));
return nullptr;
}

buffers.emplace_back(newBuffer);
std::erase_if(buffers, [](const auto& b) { return b.expired(); });
return newBuffer;
}

Hyprutils::Memory::CSharedPointer<CBackend> Aquamarine::CDumbAllocator::getBackend() {
return backend.lock();
}

int Aquamarine::CDumbAllocator::drmFD() {
return fd;
}
7 changes: 3 additions & 4 deletions src/allocator/GBM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ static SDRMFormat guessFormatFrom(std::vector<SDRMFormat> formats, bool cursor)
}

Aquamarine::CGBMBuffer::CGBMBuffer(const SAllocatorBufferParams& params, Hyprutils::Memory::CWeakPointer<CGBMAllocator> allocator_,
Hyprutils::Memory::CSharedPointer<CSwapchain> swapchain) :
allocator(allocator_) {
Hyprutils::Memory::CSharedPointer<CSwapchain> swapchain) : allocator(allocator_) {
if (!allocator)
return;

Expand Down Expand Up @@ -199,7 +198,7 @@ Aquamarine::CGBMBuffer::~CGBMBuffer() {
}

eBufferCapability Aquamarine::CGBMBuffer::caps() {
return (Aquamarine::eBufferCapability)0;
return BUFFER_CAPABILITY_DATAPTR;
}

eBufferType Aquamarine::CGBMBuffer::type() {
Expand All @@ -215,7 +214,7 @@ bool Aquamarine::CGBMBuffer::isSynchronous() {
}

bool Aquamarine::CGBMBuffer::good() {
return true;
return attrs.success;
}

SDMABUFAttrs Aquamarine::CGBMBuffer::dmabuf() {
Expand Down
4 changes: 3 additions & 1 deletion src/backend/Backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <aquamarine/backend/Headless.hpp>
#include <aquamarine/backend/DRM.hpp>
#include <aquamarine/allocator/GBM.hpp>
#include <aquamarine/allocator/Dumb.hpp>
#include <sys/poll.h>
#include <thread>
#include <chrono>
Expand Down Expand Up @@ -153,7 +154,8 @@ bool Aquamarine::CBackend::start() {
log(AQ_LOG_CRITICAL, "Failed to create an allocator (reopenDRMNode failed)");
return false;
}
primaryAllocator = CGBMAllocator::create(fd, self);
primaryAllocator = CGBMAllocator::create(fd, self);
fallbackAllocator = CDumbAllocator::create(fd, self);
break;
}
}
Expand Down
30 changes: 21 additions & 9 deletions src/backend/drm/DRM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,10 @@ SP<IAllocator> Aquamarine::CDRMBackend::preferredAllocator() {
return backend->primaryAllocator;
}

SP<IAllocator> Aquamarine::CDRMBackend::fallbackAllocator() {
return backend->fallbackAllocator;
}

bool Aquamarine::SDRMPlane::init(drmModePlane* plane) {
id = plane->plane_id;

Expand Down Expand Up @@ -1546,14 +1550,14 @@ SP<IBackendImplementation> Aquamarine::CDRMOutput::getBackend() {
}

bool Aquamarine::CDRMOutput::setCursor(SP<IBuffer> buffer, const Vector2D& hotspot) {
if (buffer && !buffer->dmabuf().success) {
backend->backend->log(AQ_LOG_ERROR, "drm: Cursor buffer has to be a dmabuf");
return false;
}

if (!buffer)
setCursorVisible(false);
else {
auto isDumb = buffer->type() == BUFFER_TYPE_DUMB;
if (!(buffer->dmabuf().success || (isDumb && buffer->shm().success))) {
backend->backend->log(AQ_LOG_ERROR, "drm: Cursor buffer has to be a dmabuf or dumb");
return false;
}
SP<CDRMFB> fb;

if (backend->primary) {
Expand All @@ -1568,8 +1572,8 @@ bool Aquamarine::CDRMOutput::setCursor(SP<IBuffer> buffer, const Vector2D& hotsp
OPTIONS.multigpu = false;
OPTIONS.scanout = true;
OPTIONS.cursor = true;
OPTIONS.format = buffer->dmabuf().format;
OPTIONS.size = buffer->dmabuf().size;
OPTIONS.format = isDumb ? buffer->shm().format : buffer->dmabuf().format;
OPTIONS.size = isDumb ? buffer->shm().size : buffer->dmabuf().size;
OPTIONS.length = 2;

if (!mgpu.cursorSwapchain->reconfigure(OPTIONS)) {
Expand Down Expand Up @@ -1698,7 +1702,11 @@ Aquamarine::CDRMFB::CDRMFB(SP<IBuffer> buffer_, Hyprutils::Memory::CWeakPointer<
}

void Aquamarine::CDRMFB::import() {
auto attrs = buffer->dmabuf();
// FIXME easier to pretend that we are a dmabuf then to change everything. shm and dmabuf should have the same offset and stride types?
auto attrs = buffer->type() == BUFFER_TYPE_DUMB ?
SDMABUFAttrs{buffer->shm().success, buffer->shm().size, buffer->shm().format, 0, 1, {(uint32_t)buffer->shm().offset}, {(uint32_t)buffer->shm().stride},
{buffer->shm().fd, -1, -1, -1}} :
buffer->dmabuf();
if (!attrs.success) {
backend->backend->log(AQ_LOG_ERROR, "drm: Buffer submitted has no dmabuf");
return;
Expand Down Expand Up @@ -1807,7 +1815,11 @@ void Aquamarine::CDRMFB::drop() {
}

uint32_t Aquamarine::CDRMFB::submitBuffer() {
auto attrs = buffer->dmabuf();
// FIXME easier to pretend that we are a dmabuf then to change everything. shm and dmabuf should have the same offset and stride types?
auto attrs = buffer->type() == BUFFER_TYPE_DUMB ?
SDMABUFAttrs{buffer->shm().success, buffer->shm().size, buffer->shm().format, 0, 1, {(uint32_t)buffer->shm().offset}, {(uint32_t)buffer->shm().stride},
{buffer->shm().fd, -1, -1, -1}} :
buffer->dmabuf();
uint32_t newID = 0;
std::array<uint64_t, 4> mods = {0, 0, 0, 0};
for (size_t i = 0; i < attrs.planes; ++i) {
Expand Down
Loading