mirror of
https://github.com/hyprwm/aquamarine.git
synced 2024-11-17 06:06:00 +01:00
drm: handle monitor hotplugs and fix a few bugs that it revealed (#14)
* handle monitor hotplugs and fix a few bugs that it revealed * fix cursorFB uaf and other stuf
This commit is contained in:
parent
ad8261ba99
commit
db417a49e8
3 changed files with 55 additions and 45 deletions
|
@ -287,7 +287,7 @@ namespace Aquamarine {
|
||||||
SDRMPageFlip pendingPageFlip;
|
SDRMPageFlip pendingPageFlip;
|
||||||
bool frameEventScheduled = false;
|
bool frameEventScheduled = false;
|
||||||
|
|
||||||
drmModeModeInfo fallbackModeInfo;
|
Hyprutils::Memory::CSharedPointer<SOutputMode> fallbackMode;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool vrrEnabled = false;
|
bool vrrEnabled = false;
|
||||||
|
|
|
@ -303,48 +303,51 @@ void Aquamarine::CSession::dispatchUdevEvents() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action == std::string{"add"})
|
dev_t deviceNum = udev_device_get_devnum(device);
|
||||||
events.addDrmCard.emit(SAddDrmCardEvent{.path = devnode});
|
SP<CSessionDevice> sessionDevice;
|
||||||
else if (action == std::string{"change"} || action == std::string{"remove"}) {
|
for (auto& sDev : sessionDevices) {
|
||||||
dev_t deviceNum = udev_device_get_devnum(device);
|
if (sDev->dev == deviceNum) {
|
||||||
|
sessionDevice = sDev;
|
||||||
for (auto& d : sessionDevices) {
|
|
||||||
if (d->dev != deviceNum)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (action == std::string{"change"}) {
|
|
||||||
backend->log(AQ_LOG_DEBUG, std::format("udev: DRM device {} changed", sysname ? sysname : "unknown"));
|
|
||||||
|
|
||||||
CSessionDevice::SChangeEvent event;
|
|
||||||
|
|
||||||
auto prop = udev_device_get_property_value(device, "HOTPLUG");
|
|
||||||
if (prop && prop == std::string{"1"}) {
|
|
||||||
event.type = CSessionDevice::AQ_SESSION_EVENT_CHANGE_HOTPLUG;
|
|
||||||
|
|
||||||
prop = udev_device_get_property_value(device, "CONNECTOR");
|
|
||||||
if (prop)
|
|
||||||
event.hotplug.connectorID = std::stoull(prop);
|
|
||||||
|
|
||||||
prop = udev_device_get_property_value(device, "PROPERTY");
|
|
||||||
if (prop)
|
|
||||||
event.hotplug.propID = std::stoull(prop);
|
|
||||||
} else if (prop = udev_device_get_property_value(device, "LEASE"); prop && prop == std::string{"1"}) {
|
|
||||||
event.type = CSessionDevice::AQ_SESSION_EVENT_CHANGE_LEASE;
|
|
||||||
} else {
|
|
||||||
backend->log(AQ_LOG_DEBUG, std::format("udev: DRM device {} change event unrecognized", sysname ? sysname : "unknown"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->events.change.emit(event);
|
|
||||||
} else if (action == std::string{"remove"}) {
|
|
||||||
backend->log(AQ_LOG_DEBUG, std::format("udev: DRM device {} removed", sysname ? sysname : "unknown"));
|
|
||||||
d->events.remove.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!sessionDevice) {
|
||||||
|
udev_device_unref(device);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == std::string{"add"})
|
||||||
|
events.addDrmCard.emit(SAddDrmCardEvent{.path = devnode});
|
||||||
|
else if (action == std::string{"change"}) {
|
||||||
|
backend->log(AQ_LOG_DEBUG, std::format("udev: DRM device {} changed", sysname ? sysname : "unknown"));
|
||||||
|
|
||||||
|
CSessionDevice::SChangeEvent event;
|
||||||
|
|
||||||
|
//
|
||||||
|
auto prop = udev_device_get_property_value(device, "HOTPLUG");
|
||||||
|
if (prop && prop == std::string{"1"}) {
|
||||||
|
event.type = CSessionDevice::AQ_SESSION_EVENT_CHANGE_HOTPLUG;
|
||||||
|
|
||||||
|
prop = udev_device_get_property_value(device, "CONNECTOR");
|
||||||
|
if (prop)
|
||||||
|
event.hotplug.connectorID = std::stoull(prop);
|
||||||
|
|
||||||
|
prop = udev_device_get_property_value(device, "PROPERTY");
|
||||||
|
if (prop)
|
||||||
|
event.hotplug.propID = std::stoull(prop);
|
||||||
|
} else if (prop = udev_device_get_property_value(device, "LEASE"); prop && prop == std::string{"1"}) {
|
||||||
|
event.type = CSessionDevice::AQ_SESSION_EVENT_CHANGE_LEASE;
|
||||||
|
} else {
|
||||||
|
backend->log(AQ_LOG_DEBUG, std::format("udev: DRM device {} change event unrecognized", sysname ? sysname : "unknown"));
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionDevice->events.change.emit(event);
|
||||||
|
} else if (action == std::string{"remove"}) {
|
||||||
|
backend->log(AQ_LOG_DEBUG, std::format("udev: DRM device {} removed", sysname ? sysname : "unknown"));
|
||||||
|
sessionDevice->events.remove.emit();
|
||||||
|
}
|
||||||
|
|
||||||
udev_device_unref(device);
|
udev_device_unref(device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,6 +238,9 @@ std::vector<SP<CDRMBackend>> Aquamarine::CDRMBackend::attempt(SP<CBackend> backe
|
||||||
}
|
}
|
||||||
|
|
||||||
backends.emplace_back(drmBackend);
|
backends.emplace_back(drmBackend);
|
||||||
|
|
||||||
|
// so that session can handle udev change/remove events for this gpu
|
||||||
|
backend->session->sessionDevices.push_back(gpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
return backends;
|
return backends;
|
||||||
|
@ -1024,7 +1027,6 @@ drmModeModeInfo* Aquamarine::SDRMConnector::getCurrentMode() {
|
||||||
if (crtc->props.mode_id) {
|
if (crtc->props.mode_id) {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
return (drmModeModeInfo*)getDRMPropBlob(backend->gpu->fd, crtc->id, crtc->props.mode_id, &size);
|
return (drmModeModeInfo*)getDRMPropBlob(backend->gpu->fd, crtc->id, crtc->props.mode_id, &size);
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto drmCrtc = drmModeGetCrtc(backend->gpu->fd, crtc->id);
|
auto drmCrtc = drmModeGetCrtc(backend->gpu->fd, crtc->id);
|
||||||
|
@ -1095,15 +1097,15 @@ void Aquamarine::SDRMConnector::connect(drmModeConnector* connector) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == 1)
|
|
||||||
fallbackModeInfo = drmMode;
|
|
||||||
|
|
||||||
auto aqMode = makeShared<SOutputMode>();
|
auto aqMode = makeShared<SOutputMode>();
|
||||||
aqMode->pixelSize = {drmMode.hdisplay, drmMode.vdisplay};
|
aqMode->pixelSize = {drmMode.hdisplay, drmMode.vdisplay};
|
||||||
aqMode->refreshRate = calculateRefresh(drmMode);
|
aqMode->refreshRate = calculateRefresh(drmMode);
|
||||||
aqMode->preferred = (drmMode.type & DRM_MODE_TYPE_PREFERRED);
|
aqMode->preferred = (drmMode.type & DRM_MODE_TYPE_PREFERRED);
|
||||||
aqMode->modeInfo = drmMode;
|
aqMode->modeInfo = drmMode;
|
||||||
|
|
||||||
|
if (i == 1)
|
||||||
|
fallbackMode = aqMode;
|
||||||
|
|
||||||
output->modes.emplace_back(aqMode);
|
output->modes.emplace_back(aqMode);
|
||||||
|
|
||||||
if (currentModeInfo && std::memcmp(&drmMode, currentModeInfo, sizeof(drmModeModeInfo))) {
|
if (currentModeInfo && std::memcmp(&drmMode, currentModeInfo, sizeof(drmModeModeInfo))) {
|
||||||
|
@ -1120,6 +1122,11 @@ void Aquamarine::SDRMConnector::connect(drmModeConnector* connector) {
|
||||||
aqMode->preferred ? " (preferred)" : ""));
|
aqMode->preferred ? " (preferred)" : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!currentModeInfo) {
|
||||||
|
output->state->setMode(fallbackMode);
|
||||||
|
crtc->refresh = calculateRefresh(fallbackMode->modeInfo.value());
|
||||||
|
}
|
||||||
|
|
||||||
output->physicalSize = {(double)connector->mmWidth, (double)connector->mmHeight};
|
output->physicalSize = {(double)connector->mmWidth, (double)connector->mmHeight};
|
||||||
|
|
||||||
backend->backend->log(AQ_LOG_DEBUG, std::format("drm: Physical size {} (mm)", output->physicalSize));
|
backend->backend->log(AQ_LOG_DEBUG, std::format("drm: Physical size {} (mm)", output->physicalSize));
|
||||||
|
@ -1181,7 +1188,7 @@ void Aquamarine::SDRMConnector::connect(drmModeConnector* connector) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
output->swapchain = CSwapchain::create(backend->backend->primaryAllocator, backend->self.lock());
|
output->swapchain = CSwapchain::create(backend->backend->primaryAllocator, backend->self.lock());
|
||||||
backend->backend->events.newOutput.emit(output);
|
backend->backend->events.newOutput.emit(SP<IOutput>(output));
|
||||||
output->scheduleFrame(IOutput::AQ_SCHEDULE_NEW_CONNECTOR);
|
output->scheduleFrame(IOutput::AQ_SCHEDULE_NEW_CONNECTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1400,7 +1407,7 @@ bool Aquamarine::CDRMOutput::commitState(bool onlyTest) {
|
||||||
// fail to be created from gbm
|
// fail to be created from gbm
|
||||||
// TODO: add an API to detect this and request drm_dumb linear buffers. Or do something,
|
// TODO: add an API to detect this and request drm_dumb linear buffers. Or do something,
|
||||||
// idk
|
// idk
|
||||||
if (data.cursorFB->buffer->dmabuf().modifier == DRM_FORMAT_MOD_INVALID) {
|
if (data.cursorFB->dead || data.cursorFB->buffer->dmabuf().modifier == DRM_FORMAT_MOD_INVALID) {
|
||||||
TRACE(backend->backend->log(AQ_LOG_TRACE, "drm: Dropping invalid buffer for cursor plane"));
|
TRACE(backend->backend->log(AQ_LOG_TRACE, "drm: Dropping invalid buffer for cursor plane"));
|
||||||
data.cursorFB = nullptr;
|
data.cursorFB = nullptr;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue