mirror of
https://github.com/hyprwm/aquamarine.git
synced 2024-12-22 11:39:49 +01:00
drm: very initial work on multigpu
This commit is contained in:
parent
944b0465fa
commit
40f6fa5173
4 changed files with 116 additions and 40 deletions
|
@ -291,7 +291,7 @@ namespace Aquamarine {
|
|||
private:
|
||||
CDRMBackend(Hyprutils::Memory::CSharedPointer<CBackend> backend);
|
||||
|
||||
static Hyprutils::Memory::CSharedPointer<CDRMBackend> attempt(Hyprutils::Memory::CSharedPointer<CBackend> backend);
|
||||
static std::vector<Hyprutils::Memory::CSharedPointer<CDRMBackend>> attempt(Hyprutils::Memory::CSharedPointer<CBackend> backend);
|
||||
bool registerGPU(Hyprutils::Memory::CSharedPointer<CSessionDevice> gpu_, Hyprutils::Memory::CSharedPointer<CDRMBackend> primary_ = {});
|
||||
bool checkFeatures();
|
||||
bool initResources();
|
||||
|
|
|
@ -52,12 +52,15 @@ Hyprutils::Memory::CSharedPointer<CBackend> Aquamarine::CBackend::create(const s
|
|||
ref->self = ref;
|
||||
} else if (b.backendType == AQ_BACKEND_DRM) {
|
||||
auto ref = CDRMBackend::attempt(backend);
|
||||
if (!ref) {
|
||||
if (ref.empty()) {
|
||||
backend->log(AQ_LOG_ERROR, "DRM Backend failed");
|
||||
continue;
|
||||
}
|
||||
backend->implementations.emplace_back(ref);
|
||||
ref->self = ref;
|
||||
|
||||
for (auto& r : ref) {
|
||||
backend->implementations.emplace_back(r);
|
||||
}
|
||||
|
||||
} else {
|
||||
backend->log(AQ_LOG_ERROR, std::format("Unknown backend id: {}", (int)b.backendType));
|
||||
continue;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <aquamarine/backend/DRM.hpp>
|
||||
#include <aquamarine/backend/drm/Legacy.hpp>
|
||||
#include <aquamarine/backend/drm/Atomic.hpp>
|
||||
#include <hyprutils/string/VarList.hpp>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <deque>
|
||||
|
@ -50,8 +51,6 @@ static udev_enumerate* enumDRMCards(udev* udev) {
|
|||
}
|
||||
|
||||
static std::vector<SP<CSessionDevice>> scanGPUs(SP<CBackend> backend) {
|
||||
// FIXME: This provides no explicit way to set a preferred gpu
|
||||
|
||||
auto enumerate = enumDRMCards(backend->session->udevHandle);
|
||||
|
||||
if (!enumerate) {
|
||||
|
@ -123,20 +122,43 @@ static std::vector<SP<CSessionDevice>> scanGPUs(SP<CBackend> backend) {
|
|||
udev_enumerate_unref(enumerate);
|
||||
|
||||
std::vector<SP<CSessionDevice>> vecDevices;
|
||||
for (auto& d : devices) {
|
||||
vecDevices.push_back(d);
|
||||
|
||||
auto explicitGpus = getenv("AQ_DRM_DEVICES");
|
||||
if (explicitGpus) {
|
||||
backend->log(AQ_LOG_DEBUG, std::format("drm: Explicit device list {}", explicitGpus));
|
||||
Hyprutils::String::CVarList explicitDevices(explicitGpus, ';', true);
|
||||
|
||||
for (auto& d : explicitDevices) {
|
||||
bool found = false;
|
||||
for (auto& vd : devices) {
|
||||
if (vd->path == d) {
|
||||
vecDevices.emplace_back(vd);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
backend->log(AQ_LOG_DEBUG, std::format("drm: Explicit device {} found", d));
|
||||
else
|
||||
backend->log(AQ_LOG_ERROR, std::format("drm: Explicit device {} not found", d));
|
||||
}
|
||||
} else {
|
||||
for (auto& d : devices) {
|
||||
vecDevices.push_back(d);
|
||||
}
|
||||
}
|
||||
|
||||
return vecDevices;
|
||||
}
|
||||
|
||||
SP<CDRMBackend> Aquamarine::CDRMBackend::attempt(SP<CBackend> backend) {
|
||||
std::vector<SP<CDRMBackend>> Aquamarine::CDRMBackend::attempt(SP<CBackend> backend) {
|
||||
if (!backend->session)
|
||||
backend->session = CSession::attempt(backend);
|
||||
|
||||
if (!backend->session) {
|
||||
backend->log(AQ_LOG_ERROR, "Failed to open a session");
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!backend->session->active) {
|
||||
|
@ -156,7 +178,7 @@ SP<CDRMBackend> Aquamarine::CDRMBackend::attempt(SP<CBackend> backend) {
|
|||
|
||||
if (!backend->session->active) {
|
||||
backend->log(AQ_LOG_DEBUG, "Session could not be activated in time");
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,41 +186,54 @@ SP<CDRMBackend> Aquamarine::CDRMBackend::attempt(SP<CBackend> backend) {
|
|||
|
||||
if (gpus.empty()) {
|
||||
backend->log(AQ_LOG_ERROR, "drm: Found no gpus to use, cannot continue");
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
backend->log(AQ_LOG_DEBUG, std::format("drm: Found {} GPUs", gpus.size()));
|
||||
|
||||
// FIXME: this will ignore multi-gpu setups and only create one backend
|
||||
auto drmBackend = SP<CDRMBackend>(new CDRMBackend(backend));
|
||||
drmBackend->self = drmBackend;
|
||||
std::vector<SP<CDRMBackend>> backends;
|
||||
SP<CDRMBackend> primary;
|
||||
|
||||
if (!drmBackend->registerGPU(gpus.at(0))) {
|
||||
backend->log(AQ_LOG_ERROR, std::format("drm: Failed to register gpu at fd {}", gpus[0]->fd));
|
||||
return nullptr;
|
||||
} else
|
||||
backend->log(AQ_LOG_DEBUG, std::format("drm: Registered gpu at fd {}", gpus[0]->fd));
|
||||
for (auto& gpu : gpus) {
|
||||
auto drmBackend = SP<CDRMBackend>(new CDRMBackend(backend));
|
||||
drmBackend->self = drmBackend;
|
||||
if (primary)
|
||||
drmBackend->primary = primary;
|
||||
|
||||
// TODO: consider listening for new devices
|
||||
// But if you expect me to handle gpu hotswaps you are probably insane LOL
|
||||
if (!drmBackend->registerGPU(gpus.at(0))) {
|
||||
backend->log(AQ_LOG_ERROR, std::format("drm: Failed to register gpu {}", gpu->path));
|
||||
continue;
|
||||
} else
|
||||
backend->log(AQ_LOG_DEBUG, std::format("drm: Registered gpu {}", gpu->path));
|
||||
|
||||
if (!drmBackend->checkFeatures()) {
|
||||
backend->log(AQ_LOG_ERROR, "drm: Failed checking features");
|
||||
return nullptr;
|
||||
// TODO: consider listening for new devices
|
||||
// But if you expect me to handle gpu hotswaps you are probably insane LOL
|
||||
|
||||
if (!drmBackend->checkFeatures()) {
|
||||
backend->log(AQ_LOG_ERROR, "drm: Failed checking features");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!drmBackend->initResources()) {
|
||||
backend->log(AQ_LOG_ERROR, "drm: Failed initializing resources");
|
||||
continue;
|
||||
}
|
||||
|
||||
backend->log(AQ_LOG_DEBUG, std::format("drm: Basic init pass for gpu {}", gpu->path));
|
||||
|
||||
drmBackend->grabFormats();
|
||||
|
||||
drmBackend->scanConnectors();
|
||||
|
||||
if (!primary) {
|
||||
backend->log(AQ_LOG_DEBUG, std::format("drm: gpu {} becomes primary drm", gpu->path));
|
||||
primary = drmBackend;
|
||||
}
|
||||
|
||||
backends.emplace_back(drmBackend);
|
||||
}
|
||||
|
||||
if (!drmBackend->initResources()) {
|
||||
backend->log(AQ_LOG_ERROR, "drm: Failed initializing resources");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
backend->log(AQ_LOG_DEBUG, std::format("drm: Basic init pass for gpu {}", gpus[0]->path));
|
||||
|
||||
drmBackend->grabFormats();
|
||||
|
||||
drmBackend->scanConnectors();
|
||||
|
||||
return drmBackend;
|
||||
return backends;
|
||||
}
|
||||
|
||||
Aquamarine::CDRMBackend::~CDRMBackend() {
|
||||
|
@ -587,6 +622,19 @@ std::vector<SDRMFormat> Aquamarine::CDRMBackend::getRenderFormats() {
|
|||
if (p->type != DRM_PLANE_TYPE_PRIMARY)
|
||||
continue;
|
||||
|
||||
if (primary) {
|
||||
backend->log(AQ_LOG_TRACE, std::format("drm: getRenderFormats on secondary {}", gpu->path));
|
||||
|
||||
// this is a secondary GPU renderer. In order to receive buffers,
|
||||
// we'll force linear modifiers.
|
||||
// TODO: don't. Find a common maybe?
|
||||
auto fmts = p->formats;
|
||||
for (auto& fmt : fmts) {
|
||||
fmt.modifiers = {DRM_FORMAT_MOD_LINEAR};
|
||||
}
|
||||
return fmts;
|
||||
}
|
||||
|
||||
return p->formats;
|
||||
}
|
||||
|
||||
|
@ -598,6 +646,19 @@ std::vector<SDRMFormat> Aquamarine::CDRMBackend::getCursorFormats() {
|
|||
if (p->type != DRM_PLANE_TYPE_CURSOR)
|
||||
continue;
|
||||
|
||||
if (primary) {
|
||||
backend->log(AQ_LOG_TRACE, std::format("drm: getCursorFormats on secondary {}", gpu->path));
|
||||
|
||||
// this is a secondary GPU renderer. In order to receive buffers,
|
||||
// we'll force linear modifiers.
|
||||
// TODO: don't. Find a common maybe?
|
||||
auto fmts = p->formats;
|
||||
for (auto& fmt : fmts) {
|
||||
fmt.modifiers = {DRM_FORMAT_MOD_LINEAR};
|
||||
}
|
||||
return fmts;
|
||||
}
|
||||
|
||||
return p->formats;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@ void Aquamarine::CDRMAtomicRequest::add(uint32_t id, uint32_t prop, uint64_t val
|
|||
if (failed)
|
||||
return;
|
||||
|
||||
backend->log(AQ_LOG_TRACE, std::format("atomic drm request: adding id {} prop {} with value {}", id, prop, val));
|
||||
|
||||
if (id == 0 || prop == 0) {
|
||||
backend->log(AQ_LOG_ERROR, "atomic drm request: failed to add prop: id / prop == 0");
|
||||
return;
|
||||
|
@ -45,7 +47,9 @@ void Aquamarine::CDRMAtomicRequest::planeProps(Hyprutils::Memory::CSharedPointer
|
|||
// Disable the plane
|
||||
backend->log(AQ_LOG_TRACE, std::format("atomic planeProps: disabling plane {}", plane->id));
|
||||
add(plane->id, plane->props.fb_id, 0);
|
||||
add(plane->id, plane->props.crtc_id, 0);
|
||||
add(plane->id, plane->props.crtc_id, crtc);
|
||||
add(plane->id, plane->props.crtc_x, (uint64_t)pos.x);
|
||||
add(plane->id, plane->props.crtc_y, (uint64_t)pos.y);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -69,7 +73,7 @@ void Aquamarine::CDRMAtomicRequest::planeProps(Hyprutils::Memory::CSharedPointer
|
|||
|
||||
void Aquamarine::CDRMAtomicRequest::addConnector(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data) {
|
||||
const auto& STATE = connector->output->state->state();
|
||||
const bool enable = STATE.enabled && data.mainFB;
|
||||
const bool enable = STATE.enabled;
|
||||
|
||||
backend->log(AQ_LOG_TRACE,
|
||||
std::format("atomic addConnector blobs: mode_id {}, active {}, crtc_id {}, link_status {}, content_type {}", connector->crtc->props.mode_id,
|
||||
|
@ -77,6 +81,11 @@ void Aquamarine::CDRMAtomicRequest::addConnector(Hyprutils::Memory::CSharedPoint
|
|||
|
||||
add(connector->id, connector->props.crtc_id, enable ? connector->crtc->id : 0);
|
||||
|
||||
if (data.modeset && enable) {
|
||||
backend->log(AQ_LOG_TRACE, std::format("atomic: mode blob {}", data.atomic.modeBlob));
|
||||
add(connector->crtc->id, connector->crtc->props.mode_id, data.atomic.modeBlob);
|
||||
}
|
||||
|
||||
if (data.modeset && enable && connector->props.link_status)
|
||||
add(connector->id, connector->props.link_status, DRM_MODE_LINK_STATUS_GOOD);
|
||||
|
||||
|
@ -87,7 +96,6 @@ void Aquamarine::CDRMAtomicRequest::addConnector(Hyprutils::Memory::CSharedPoint
|
|||
if (data.modeset && enable && connector->props.max_bpc && connector->maxBpcBounds.at(1))
|
||||
add(connector->id, connector->props.max_bpc, 8); // FIXME: this isnt always 8
|
||||
|
||||
// add(connector->crtc->id, connector->crtc->props.mode_id, data.atomic.modeBlob);
|
||||
add(connector->crtc->id, connector->crtc->props.active, enable);
|
||||
|
||||
if (enable) {
|
||||
|
@ -210,6 +218,10 @@ bool Aquamarine::CDRMAtomicImpl::prepareConnector(Hyprutils::Memory::CSharedPoin
|
|||
connector->backend->backend->log(AQ_LOG_ERROR, "atomic drm: failed to create a modeset blob");
|
||||
return false;
|
||||
}
|
||||
|
||||
connector->backend->log(AQ_LOG_TRACE,
|
||||
std::format("Connector blob id {}: clock {}, {}x{}, vrefresh {}, name: {}", data.atomic.modeBlob, data.modeInfo.clock, data.modeInfo.hdisplay,
|
||||
data.modeInfo.vdisplay, data.modeInfo.vrefresh, data.modeInfo.name));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue