Skip to content

Commit

Permalink
dmabuf: make use of AQ CFileDescriptor
Browse files Browse the repository at this point in the history
change dmabuf usage for AQ's now CFileDescriptor
  • Loading branch information
gulafaran committed Feb 2, 2025
1 parent 7df2050 commit e7734c2
Show file tree
Hide file tree
Showing 15 changed files with 56 additions and 60 deletions.
4 changes: 2 additions & 2 deletions src/helpers/Monitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1286,7 +1286,7 @@ bool CMonitor::attemptDirectScanout() {
// FIXME: make sure the buffer actually follows the available scanout dmabuf formats
// and comes from the appropriate device. This may implode on multi-gpu!!

const auto params = PSURFACE->current.buffer->buffer->dmabuf();
const auto& params = PSURFACE->current.buffer->buffer->dmabuf();
// scanout buffer isn't dmabuf, so no scanout
if (!params.success)
return false;
Expand Down Expand Up @@ -1450,7 +1450,7 @@ void CMonitorState::ensureBufferPresent() {
}

if (STATE.buffer) {
if (const auto params = STATE.buffer->dmabuf(); params.success && params.format == m_pOwner->drmFormat)
if (const auto& params = STATE.buffer->dmabuf(); params.success && params.format == m_pOwner->drmFormat)
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/managers/PointerManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager

// then, we just yeet it into the dumb buffer

const auto DMABUF = buf->dmabuf();
const auto& DMABUF = buf->dmabuf();
auto [data, fmt, size] = buf->beginDataPtr(0);

auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, DMABUF.size.x, DMABUF.size.y);
Expand Down
23 changes: 12 additions & 11 deletions src/protocols/LinuxDMABUF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vec
tableFD = std::move(fds[1]);
}

CLinuxDMABuffer::CLinuxDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs) {
buffer = makeShared<CDMABuffer>(id, client, attrs);
CLinuxDMABuffer::CLinuxDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs&& attrs) {
buffer = makeShared<CDMABuffer>(id, client, std::move(attrs));

buffer->resource->buffer = buffer;

Expand Down Expand Up @@ -139,12 +139,12 @@ CLinuxDMABUFParamsResource::CLinuxDMABUFParamsResource(UP<CZwpLinuxBufferParamsV
return;
}

if (m_attrs.fds.at(plane) != -1) {
if (m_attrs.fds.at(plane).isValid()) {
r->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX, "plane used");
return;
}

m_attrs.fds[plane] = fd;
m_attrs.fds[plane] = CFileDescriptor{fd};
m_attrs.strides[plane] = stride;
m_attrs.offsets[plane] = offset;
m_attrs.modifier = ((uint64_t)modHi << 32) | modLo;
Expand Down Expand Up @@ -189,7 +189,7 @@ void CLinuxDMABUFParamsResource::create(uint32_t id, Vector2D size, uint32_t for
used = true;
m_attrs.size = size;
m_attrs.format = format;
m_attrs.planes = 4 - std::count(m_attrs.fds.begin(), m_attrs.fds.end(), -1);
m_attrs.planes = 4 - std::count_if(m_attrs.fds.begin(), m_attrs.fds.end(), [](const auto& fd) { return !fd.isValid(); });

if UNLIKELY (!verify()) {
LOGM(ERR, "Failed creating a dmabuf: verify() said no");
Expand All @@ -204,10 +204,11 @@ void CLinuxDMABUFParamsResource::create(uint32_t id, Vector2D size, uint32_t for

LOGM(LOG, "Creating a dmabuf, with id {}: size {}, fmt {}, planes {}", id, m_attrs.size, NFormatUtils::drmFormatName(m_attrs.format), m_attrs.planes);
for (int i = 0; i < m_attrs.planes; ++i) {
LOGM(LOG, " | plane {}: mod {} fd {} stride {} offset {}", i, m_attrs.modifier, m_attrs.fds[i], m_attrs.strides[i], m_attrs.offsets[i]);
LOGM(LOG, " | plane {}: mod {} fd {} stride {} offset {}", i, m_attrs.modifier, m_attrs.fds[i].get(), m_attrs.strides[i], m_attrs.offsets[i]);
}

auto& buf = PROTO::linuxDma->m_vBuffers.emplace_back(makeUnique<CLinuxDMABuffer>(id, resource->client(), m_attrs));
auto& buf = PROTO::linuxDma->m_vBuffers.emplace_back(makeUnique<CLinuxDMABuffer>(id, resource->client(), std::move(m_attrs)));
m_attrs = {};

if UNLIKELY (!buf->good() || !buf->buffer->success) {
resource->sendFailed();
Expand All @@ -227,7 +228,7 @@ bool CLinuxDMABUFParamsResource::commence() {
for (int i = 0; i < m_attrs.planes; i++) {
uint32_t handle = 0;

if (drmPrimeFDToHandle(PROTO::linuxDma->mainDeviceFD.get(), m_attrs.fds.at(i), &handle)) {
if (drmPrimeFDToHandle(PROTO::linuxDma->mainDeviceFD.get(), m_attrs.fds.at(i).get(), &handle)) {
LOGM(ERR, "Failed to import dmabuf fd");
return false;
}
Expand All @@ -247,19 +248,19 @@ bool CLinuxDMABUFParamsResource::verify() {
return false;
}

if UNLIKELY (m_attrs.fds.at(0) < 0) {
if UNLIKELY (!m_attrs.fds.at(0).isValid()) {
resource->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, "No plane 0");
return false;
}

bool empty = false;
for (auto const& plane : m_attrs.fds) {
if (empty && plane != -1) {
if (empty && plane.isValid()) {
resource->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT, "Gap in planes");
return false;
}

if (plane == -1) {
if (!plane.isValid()) {
empty = true;
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion src/protocols/LinuxDMABUF.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class CWLSurfaceResource;

class CLinuxDMABuffer {
public:
CLinuxDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs);
CLinuxDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs&& attrs);
~CLinuxDMABuffer();

bool good();
Expand Down
12 changes: 7 additions & 5 deletions src/protocols/MesaDRM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
#include "types/WLBuffer.hpp"
#include "../render/OpenGL.hpp"

CMesaDRMBufferResource::CMesaDRMBufferResource(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs_) {
using namespace Hyprutils::OS;

CMesaDRMBufferResource::CMesaDRMBufferResource(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs&& attrs_) {
LOGM(LOG, "Creating a Mesa dmabuf, with id {}: size {}, fmt {}, planes {}", id, attrs_.size, attrs_.format, attrs_.planes);
for (int i = 0; i < attrs_.planes; ++i) {
LOGM(LOG, " | plane {}: mod {} fd {} stride {} offset {}", i, attrs_.modifier, attrs_.fds[i], attrs_.strides[i], attrs_.offsets[i]);
LOGM(LOG, " | plane {}: mod {} fd {} stride {} offset {}", i, attrs_.modifier, attrs_.fds[i].get(), attrs_.strides[i], attrs_.offsets[i]);
}

buffer = makeShared<CDMABuffer>(id, client, attrs_);
buffer = makeShared<CDMABuffer>(id, client, std::move(attrs_));
buffer->resource->buffer = buffer;

listeners.bufferResourceDestroy = buffer->events.destroy.registerListener([this](std::any d) {
Expand Down Expand Up @@ -82,10 +84,10 @@ CMesaDRMResource::CMesaDRMResource(SP<CWlDrm> resource_) : resource(resource_) {
attrs.planes = 1;
attrs.offsets[0] = off0;
attrs.strides[0] = str0;
attrs.fds[0] = nameFd;
attrs.fds[0] = CFileDescriptor{nameFd};
attrs.format = fmt;

const auto RESOURCE = PROTO::mesaDRM->m_vBuffers.emplace_back(makeShared<CMesaDRMBufferResource>(id, resource->client(), attrs));
const auto RESOURCE = PROTO::mesaDRM->m_vBuffers.emplace_back(makeShared<CMesaDRMBufferResource>(id, resource->client(), std::move(attrs)));

if UNLIKELY (!RESOURCE->good()) {
r->noMemory();
Expand Down
3 changes: 2 additions & 1 deletion src/protocols/MesaDRM.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

#include <vector>
#include <cstdint>
#include <hyprutils/os/FileDescriptor.hpp>
#include "WaylandProtocol.hpp"
#include "wayland-drm.hpp"
#include "types/Buffer.hpp"
#include "types/DMABuffer.hpp"

class CMesaDRMBufferResource {
public:
CMesaDRMBufferResource(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs);
CMesaDRMBufferResource(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs&& attrs);
~CMesaDRMBufferResource();

bool good();
Expand Down
4 changes: 2 additions & 2 deletions src/protocols/Screencopy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ void CScreencopyFrame::copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer_
return;
}

if (auto attrs = PBUFFER->buffer->dmabuf(); attrs.success) {
if (const auto& attrs = PBUFFER->buffer->dmabuf(); attrs.success) {
bufferDMA = true;

if (attrs.format != dmabufFormat) {
Expand All @@ -126,7 +126,7 @@ void CScreencopyFrame::copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer_
PROTO::screencopy->destroyResource(this);
return;
}
} else if (auto attrs = PBUFFER->buffer->shm(); attrs.success) {
} else if (const auto& attrs = PBUFFER->buffer->shm(); attrs.success) {
if (attrs.format != shmFormat) {
LOGM(ERR, "Invalid buffer shm format in {:x}", (uintptr_t)pFrame);
resource->error(ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format");
Expand Down
4 changes: 2 additions & 2 deletions src/protocols/SinglePixel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ void CSinglePixelBuffer::update(const CRegion& damage) {
;
}

Aquamarine::SDMABUFAttrs CSinglePixelBuffer::dmabuf() {
return {.success = false};
const Aquamarine::SDMABUFAttrs& CSinglePixelBuffer::dmabuf() const {
return m_attrs;
}

std::tuple<uint8_t*, uint32_t, size_t> CSinglePixelBuffer::beginDataPtr(uint32_t flags) {
Expand Down
5 changes: 3 additions & 2 deletions src/protocols/SinglePixel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@ class CSinglePixelBuffer : public IHLBuffer {
virtual Aquamarine::eBufferType type();
virtual bool isSynchronous();
virtual void update(const CRegion& damage);
virtual Aquamarine::SDMABUFAttrs dmabuf();
virtual const Aquamarine::SDMABUFAttrs& dmabuf() const;
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
virtual void endDataPtr();
//
bool good();
bool success = false;

private:
uint32_t color = 0x00000000;
uint32_t color = 0x00000000;
const Aquamarine::SDMABUFAttrs m_attrs = {.success = false};

struct {
CHyprSignalListener resourceDestroy;
Expand Down
4 changes: 2 additions & 2 deletions src/protocols/ToplevelExport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,15 +172,15 @@ void CToplevelExportFrame::copy(CHyprlandToplevelExportFrameV1* pFrame, wl_resou
return;
}

if (auto attrs = PBUFFER->buffer->dmabuf(); attrs.success) {
if (const auto& attrs = PBUFFER->buffer->dmabuf(); attrs.success) {
bufferDMA = true;

if (attrs.format != dmabufFormat) {
resource->error(HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format");
PROTO::toplevelExport->destroyResource(this);
return;
}
} else if (auto attrs = PBUFFER->buffer->shm(); attrs.success) {
} else if (const auto& attrs = PBUFFER->buffer->shm(); attrs.success) {
if (attrs.format != shmFormat) {
resource->error(HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format");
PROTO::toplevelExport->destroyResource(this);
Expand Down
38 changes: 15 additions & 23 deletions src/protocols/types/DMABuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,29 @@
#include "../../render/Renderer.hpp"
#include "../../helpers/Format.hpp"

CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs const& attrs_) : attrs(attrs_) {
CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs&& attrs_) : attrs(std::move(attrs_)) {
g_pHyprRenderer->makeEGLCurrent();

listeners.resourceDestroy = events.destroy.registerListener([this](std::any d) {
closeFDs();
listeners.resourceDestroy.reset();
});
listeners.resourceDestroy = events.destroy.registerListener([this](std::any d) { listeners.resourceDestroy.reset(); });

size = attrs.size;
resource = CWLBufferResource::create(makeShared<CWlBuffer>(client, 1, id));

auto eglImage = g_pHyprOpenGL->createEGLImage(attrs);

if UNLIKELY (!eglImage) {
Debug::log(ERR, "CDMABuffer: failed to import EGLImage, retrying as implicit");
attrs.modifier = DRM_FORMAT_MOD_INVALID;
eglImage = g_pHyprOpenGL->createEGLImage(attrs);
// TODO: feels like this breaks.
Aquamarine::SDMABUFAttrs implicit{.success = attrs.success,
.size = attrs.size,
.format = attrs.format,
.modifier = DRM_FORMAT_MOD_INVALID,
.planes = attrs.planes,
.offsets = attrs.offsets,
.strides = attrs.strides};
for (auto i = 0; i < attrs.planes; i++)
implicit.fds.at(i) = attrs.fds.at(i).duplicate();

eglImage = g_pHyprOpenGL->createEGLImage(implicit);
if UNLIKELY (!eglImage) {
Debug::log(ERR, "CDMABuffer: failed to import EGLImage");
return;
Expand All @@ -35,10 +41,6 @@ CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs
Debug::log(ERR, "Failed to create a dmabuf: texture is null");
}

CDMABuffer::~CDMABuffer() {
closeFDs();
}

Aquamarine::eBufferCapability CDMABuffer::caps() {
return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR;
}
Expand All @@ -55,7 +57,7 @@ bool CDMABuffer::isSynchronous() {
return false;
}

Aquamarine::SDMABUFAttrs CDMABuffer::dmabuf() {
const Aquamarine::SDMABUFAttrs& CDMABuffer::dmabuf() const {
return attrs;
}

Expand All @@ -71,13 +73,3 @@ void CDMABuffer::endDataPtr() {
bool CDMABuffer::good() {
return success;
}

void CDMABuffer::closeFDs() {
for (int i = 0; i < attrs.planes; ++i) {
if (attrs.fds[i] == -1)
continue;
close(attrs.fds[i]);
attrs.fds[i] = -1;
}
attrs.planes = 0;
}
9 changes: 4 additions & 5 deletions src/protocols/types/DMABuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,22 @@

class CDMABuffer : public IHLBuffer {
public:
CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs const& attrs_);
virtual ~CDMABuffer();
CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs&& attrs_);
virtual ~CDMABuffer() = default;

virtual Aquamarine::eBufferCapability caps();
virtual Aquamarine::eBufferType type();
virtual bool isSynchronous();
virtual void update(const CRegion& damage);
virtual Aquamarine::SDMABUFAttrs dmabuf();
virtual const Aquamarine::SDMABUFAttrs& dmabuf() const;
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
virtual void endDataPtr();
bool good();
void closeFDs();

bool success = false;

private:
Aquamarine::SDMABUFAttrs attrs;
const Aquamarine::SDMABUFAttrs attrs;

struct {
CHyprSignalListener resourceDestroy;
Expand Down
2 changes: 1 addition & 1 deletion src/render/OpenGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ EGLImageKHR CHyprOpenGLImpl::createEGLImage(const Aquamarine::SDMABUFAttrs& attr

for (int i = 0; i < attrs.planes; i++) {
attribs.push_back(attrNames[i].fd);
attribs.push_back(attrs.fds[i]);
attribs.push_back(attrs.fds[i].get());
attribs.push_back(attrNames[i].offset);
attribs.push_back(attrs.offsets[i]);
attribs.push_back(attrNames[i].pitch);
Expand Down
2 changes: 1 addition & 1 deletion src/render/Renderbuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ CRenderbuffer::~CRenderbuffer() {
}

CRenderbuffer::CRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t format) : m_pHLBuffer(buffer), m_uDrmFormat(format) {
auto dma = buffer->dmabuf();
const auto& dma = buffer->dmabuf();

m_iImage = g_pHyprOpenGL->createEGLImage(dma);
if (m_iImage == EGL_NO_IMAGE_KHR) {
Expand Down
2 changes: 1 addition & 1 deletion src/render/Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ CTexture::CTexture(const SP<Aquamarine::IBuffer> buffer, bool keepDataCopy) : m_

m_bOpaque = buffer->opaque;

auto attrs = buffer->dmabuf();
const auto& attrs = buffer->dmabuf();

if (!attrs.success) {
// attempt shm
Expand Down

0 comments on commit e7734c2

Please sign in to comment.