diff --git a/include/aquamarine/backend/DRM.hpp b/include/aquamarine/backend/DRM.hpp index 0b0925a..795944d 100644 --- a/include/aquamarine/backend/DRM.hpp +++ b/include/aquamarine/backend/DRM.hpp @@ -45,11 +45,14 @@ namespace Aquamarine { public: ~CDRMFB(); - static Hyprutils::Memory::CSharedPointer create(Hyprutils::Memory::CSharedPointer buffer_, Hyprutils::Memory::CWeakPointer backend_); + static Hyprutils::Memory::CSharedPointer create(Hyprutils::Memory::CSharedPointer buffer_, Hyprutils::Memory::CWeakPointer backend_, bool* isNew = nullptr); void closeHandles(); // drops the buffer from KMS - void drop(); + void drop(); + + // re-imports the buffer into KMS. Essentially drop and import. + void reimport(); uint32_t id = 0; Hyprutils::Memory::CWeakPointer buffer; @@ -59,6 +62,7 @@ namespace Aquamarine { private: CDRMFB(Hyprutils::Memory::CSharedPointer buffer_, Hyprutils::Memory::CWeakPointer backend_); uint32_t submitBuffer(); + void import(); bool dropped = false, handlesClosed = false; }; diff --git a/src/backend/drm/DRM.cpp b/src/backend/drm/DRM.cpp index 02458e1..79912c1 100644 --- a/src/backend/drm/DRM.cpp +++ b/src/backend/drm/DRM.cpp @@ -192,15 +192,13 @@ std::vector> Aquamarine::CDRMBackend::attempt(SP backe backend->log(AQ_LOG_DEBUG, std::format("drm: Found {} GPUs", gpus.size())); std::vector> backends; - SP primary; + SP newPrimary; for (auto& gpu : gpus) { auto drmBackend = SP(new CDRMBackend(backend)); drmBackend->self = drmBackend; - if (primary) - drmBackend->primary = primary; - if (!drmBackend->registerGPU(gpu)) { + if (!drmBackend->registerGPU(gpu, newPrimary)) { backend->log(AQ_LOG_ERROR, std::format("drm: Failed to register gpu {}", gpu->path)); continue; } else @@ -225,9 +223,9 @@ std::vector> Aquamarine::CDRMBackend::attempt(SP backe drmBackend->scanConnectors(); - if (!primary) { + if (!newPrimary) { backend->log(AQ_LOG_DEBUG, std::format("drm: gpu {} becomes primary drm", gpu->path)); - primary = drmBackend; + newPrimary = drmBackend; } backends.emplace_back(drmBackend); @@ -441,7 +439,9 @@ bool Aquamarine::CDRMBackend::registerGPU(SP gpu_, SPlog(AQ_LOG_DEBUG, std::format("drm: Starting backend for {}, with driver {}", drmName ? drmName : "unknown", drmVer->name ? drmVer->name : "unknown")); + backend->log(AQ_LOG_DEBUG, + std::format("drm: Starting backend for {}, with driver {}{}", drmName ? drmName : "unknown", drmVer->name ? drmVer->name : "unknown", + (primary ? std::format(" with primary {}", primary->gpu->path) : ""))); drmFreeVersion(drmVer); @@ -1111,15 +1111,23 @@ bool Aquamarine::CDRMOutput::commitState(bool onlyTest) { backend->backend->log(AQ_LOG_TRACE, "drm: Committed a buffer, updating state"); SP drmFB; - auto buf = STATE.buffer; + auto buf = STATE.buffer; + bool isNew = false; - drmFB = CDRMFB::create(buf, backend); // will return attachment if present + drmFB = CDRMFB::create(buf, backend, &isNew); // will return attachment if present if (!drmFB) { backend->backend->log(AQ_LOG_ERROR, "drm: Buffer failed to import to KMS"); return false; } + if (!isNew && backend->primary) { + // this is not a new buffer, and we are not on a primary GPU, which means + // this buffer lives on the primary. We need to re-import it to update + // the contents that have possibly (probably) changed + drmFB->reimport(); + } + data.mainFB = drmFB; } @@ -1197,18 +1205,24 @@ Aquamarine::CDRMOutput::CDRMOutput(const std::string& name_, Hyprutils::Memory:: name = name_; } -SP Aquamarine::CDRMFB::create(SP buffer_, Hyprutils::Memory::CWeakPointer backend_) { +SP Aquamarine::CDRMFB::create(SP buffer_, Hyprutils::Memory::CWeakPointer backend_, bool* isNew) { SP fb; + if (isNew) + *isNew = true; + if (buffer_->attachments.has(AQ_ATTACHMENT_DRM_BUFFER)) { auto at = (CDRMBufferAttachment*)buffer_->attachments.get(AQ_ATTACHMENT_DRM_BUFFER).get(); fb = at->fb; backend_->log(AQ_LOG_TRACE, std::format("drm: CDRMFB: buffer has drmfb attachment with fb {:x}", (uintptr_t)fb.get())); } - if (fb) + if (fb) { + if (isNew) + *isNew = false; return fb; + } fb = SP(new CDRMFB(buffer_, backend_)); @@ -1221,6 +1235,10 @@ SP Aquamarine::CDRMFB::create(SP buffer_, Hyprutils::Memory::CW } Aquamarine::CDRMFB::CDRMFB(SP buffer_, Hyprutils::Memory::CWeakPointer backend_) : buffer(buffer_), backend(backend_) { + import(); +} + +void Aquamarine::CDRMFB::import() { auto attrs = buffer->dmabuf(); if (!attrs.success) { backend->backend->log(AQ_LOG_ERROR, "drm: Buffer submitted has no dmabuf"); @@ -1259,6 +1277,15 @@ Aquamarine::CDRMFB::CDRMFB(SP buffer_, Hyprutils::Memory::CWeakPointer< // closeHandles(); } +void Aquamarine::CDRMFB::reimport() { + drop(); + dropped = false; + handlesClosed = false; + boHandles = {0, 0, 0, 0}; + + import(); +} + Aquamarine::CDRMFB::~CDRMFB() { drop(); } @@ -1299,6 +1326,8 @@ void Aquamarine::CDRMFB::drop() { if (!id) return; + closeHandles(); + backend->backend->log(AQ_LOG_TRACE, std::format("drm: dropping buffer {}", id)); int ret = drmModeCloseFB(backend->gpu->fd, id);