drm: reimport buffers when on a secondary gpu

This commit is contained in:
Vaxry 2024-06-28 20:14:56 +02:00
parent 8ecf8773db
commit 320a6d40a7
2 changed files with 46 additions and 13 deletions

View file

@ -45,11 +45,14 @@ namespace Aquamarine {
public: public:
~CDRMFB(); ~CDRMFB();
static Hyprutils::Memory::CSharedPointer<CDRMFB> create(Hyprutils::Memory::CSharedPointer<IBuffer> buffer_, Hyprutils::Memory::CWeakPointer<CDRMBackend> backend_); static Hyprutils::Memory::CSharedPointer<CDRMFB> create(Hyprutils::Memory::CSharedPointer<IBuffer> buffer_, Hyprutils::Memory::CWeakPointer<CDRMBackend> backend_, bool* isNew = nullptr);
void closeHandles(); void closeHandles();
// drops the buffer from KMS // 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; uint32_t id = 0;
Hyprutils::Memory::CWeakPointer<IBuffer> buffer; Hyprutils::Memory::CWeakPointer<IBuffer> buffer;
@ -59,6 +62,7 @@ namespace Aquamarine {
private: private:
CDRMFB(Hyprutils::Memory::CSharedPointer<IBuffer> buffer_, Hyprutils::Memory::CWeakPointer<CDRMBackend> backend_); CDRMFB(Hyprutils::Memory::CSharedPointer<IBuffer> buffer_, Hyprutils::Memory::CWeakPointer<CDRMBackend> backend_);
uint32_t submitBuffer(); uint32_t submitBuffer();
void import();
bool dropped = false, handlesClosed = false; bool dropped = false, handlesClosed = false;
}; };

View file

@ -192,15 +192,13 @@ std::vector<SP<CDRMBackend>> Aquamarine::CDRMBackend::attempt(SP<CBackend> backe
backend->log(AQ_LOG_DEBUG, std::format("drm: Found {} GPUs", gpus.size())); backend->log(AQ_LOG_DEBUG, std::format("drm: Found {} GPUs", gpus.size()));
std::vector<SP<CDRMBackend>> backends; std::vector<SP<CDRMBackend>> backends;
SP<CDRMBackend> primary; SP<CDRMBackend> newPrimary;
for (auto& gpu : gpus) { for (auto& gpu : gpus) {
auto drmBackend = SP<CDRMBackend>(new CDRMBackend(backend)); auto drmBackend = SP<CDRMBackend>(new CDRMBackend(backend));
drmBackend->self = drmBackend; 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)); backend->log(AQ_LOG_ERROR, std::format("drm: Failed to register gpu {}", gpu->path));
continue; continue;
} else } else
@ -225,9 +223,9 @@ std::vector<SP<CDRMBackend>> Aquamarine::CDRMBackend::attempt(SP<CBackend> backe
drmBackend->scanConnectors(); drmBackend->scanConnectors();
if (!primary) { if (!newPrimary) {
backend->log(AQ_LOG_DEBUG, std::format("drm: gpu {} becomes primary drm", gpu->path)); backend->log(AQ_LOG_DEBUG, std::format("drm: gpu {} becomes primary drm", gpu->path));
primary = drmBackend; newPrimary = drmBackend;
} }
backends.emplace_back(drmBackend); backends.emplace_back(drmBackend);
@ -441,7 +439,9 @@ bool Aquamarine::CDRMBackend::registerGPU(SP<CSessionDevice> gpu_, SP<CDRMBacken
gpuName = drmName; gpuName = drmName;
backend->log(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); drmFreeVersion(drmVer);
@ -1111,15 +1111,23 @@ bool Aquamarine::CDRMOutput::commitState(bool onlyTest) {
backend->backend->log(AQ_LOG_TRACE, "drm: Committed a buffer, updating state"); backend->backend->log(AQ_LOG_TRACE, "drm: Committed a buffer, updating state");
SP<CDRMFB> drmFB; SP<CDRMFB> 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) { if (!drmFB) {
backend->backend->log(AQ_LOG_ERROR, "drm: Buffer failed to import to KMS"); backend->backend->log(AQ_LOG_ERROR, "drm: Buffer failed to import to KMS");
return false; 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; data.mainFB = drmFB;
} }
@ -1197,18 +1205,24 @@ Aquamarine::CDRMOutput::CDRMOutput(const std::string& name_, Hyprutils::Memory::
name = name_; name = name_;
} }
SP<CDRMFB> Aquamarine::CDRMFB::create(SP<IBuffer> buffer_, Hyprutils::Memory::CWeakPointer<CDRMBackend> backend_) { SP<CDRMFB> Aquamarine::CDRMFB::create(SP<IBuffer> buffer_, Hyprutils::Memory::CWeakPointer<CDRMBackend> backend_, bool* isNew) {
SP<CDRMFB> fb; SP<CDRMFB> fb;
if (isNew)
*isNew = true;
if (buffer_->attachments.has(AQ_ATTACHMENT_DRM_BUFFER)) { if (buffer_->attachments.has(AQ_ATTACHMENT_DRM_BUFFER)) {
auto at = (CDRMBufferAttachment*)buffer_->attachments.get(AQ_ATTACHMENT_DRM_BUFFER).get(); auto at = (CDRMBufferAttachment*)buffer_->attachments.get(AQ_ATTACHMENT_DRM_BUFFER).get();
fb = at->fb; fb = at->fb;
backend_->log(AQ_LOG_TRACE, std::format("drm: CDRMFB: buffer has drmfb attachment with fb {:x}", (uintptr_t)fb.get())); 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; return fb;
}
fb = SP<CDRMFB>(new CDRMFB(buffer_, backend_)); fb = SP<CDRMFB>(new CDRMFB(buffer_, backend_));
@ -1221,6 +1235,10 @@ SP<CDRMFB> Aquamarine::CDRMFB::create(SP<IBuffer> buffer_, Hyprutils::Memory::CW
} }
Aquamarine::CDRMFB::CDRMFB(SP<IBuffer> buffer_, Hyprutils::Memory::CWeakPointer<CDRMBackend> backend_) : buffer(buffer_), backend(backend_) { Aquamarine::CDRMFB::CDRMFB(SP<IBuffer> buffer_, Hyprutils::Memory::CWeakPointer<CDRMBackend> backend_) : buffer(buffer_), backend(backend_) {
import();
}
void Aquamarine::CDRMFB::import() {
auto attrs = buffer->dmabuf(); auto attrs = buffer->dmabuf();
if (!attrs.success) { if (!attrs.success) {
backend->backend->log(AQ_LOG_ERROR, "drm: Buffer submitted has no dmabuf"); backend->backend->log(AQ_LOG_ERROR, "drm: Buffer submitted has no dmabuf");
@ -1259,6 +1277,15 @@ Aquamarine::CDRMFB::CDRMFB(SP<IBuffer> buffer_, Hyprutils::Memory::CWeakPointer<
// closeHandles(); // closeHandles();
} }
void Aquamarine::CDRMFB::reimport() {
drop();
dropped = false;
handlesClosed = false;
boHandles = {0, 0, 0, 0};
import();
}
Aquamarine::CDRMFB::~CDRMFB() { Aquamarine::CDRMFB::~CDRMFB() {
drop(); drop();
} }
@ -1299,6 +1326,8 @@ void Aquamarine::CDRMFB::drop() {
if (!id) if (!id)
return; return;
closeHandles();
backend->backend->log(AQ_LOG_TRACE, std::format("drm: dropping buffer {}", id)); backend->backend->log(AQ_LOG_TRACE, std::format("drm: dropping buffer {}", id));
int ret = drmModeCloseFB(backend->gpu->fd, id); int ret = drmModeCloseFB(backend->gpu->fd, id);