167 lines
7.1 KiB
C++
167 lines
7.1 KiB
C++
#include "aquamarine/output/Output.hpp"
|
|
#include <aquamarine/backend/drm/Legacy.hpp>
|
|
#include <cstring>
|
|
#include <xf86drm.h>
|
|
#include <xf86drmMode.h>
|
|
#include <sys/mman.h>
|
|
|
|
using namespace Aquamarine;
|
|
using namespace Hyprutils::Memory;
|
|
using namespace Hyprutils::Math;
|
|
#define SP CSharedPointer
|
|
|
|
Aquamarine::CDRMLegacyImpl::CDRMLegacyImpl(Hyprutils::Memory::CSharedPointer<CDRMBackend> backend_) : backend(backend_) {
|
|
;
|
|
}
|
|
|
|
bool Aquamarine::CDRMLegacyImpl::moveCursor(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector) {
|
|
if (!connector->output->cursorVisible || !connector->output->state->state().enabled || !connector->crtc || !connector->crtc->cursor)
|
|
return true;
|
|
|
|
connector->output->needsFrame = true;
|
|
connector->output->scheduleFrame(IOutput::AQ_SCHEDULE_CURSOR_MOVE);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Aquamarine::CDRMLegacyImpl::commitInternal(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data) {
|
|
const auto& STATE = connector->output->state->state();
|
|
SP<CDRMFB> mainFB;
|
|
bool enable = STATE.enabled;
|
|
|
|
if (enable) {
|
|
if (!data.mainFB)
|
|
connector->backend->backend->log(AQ_LOG_WARNING, "legacy drm: No buffer, will fall back to only modeset (if present)");
|
|
else
|
|
mainFB = data.mainFB;
|
|
}
|
|
|
|
if (data.modeset) {
|
|
connector->backend->backend->log(AQ_LOG_DEBUG, std::format("legacy drm: Modesetting CRTC {}", connector->crtc->id));
|
|
|
|
uint32_t dpms = enable ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF;
|
|
if (drmModeConnectorSetProperty(connector->backend->gpu->fd, connector->id, connector->props.dpms, dpms)) {
|
|
connector->backend->backend->log(AQ_LOG_ERROR, "legacy drm: Failed to set dpms");
|
|
return false;
|
|
}
|
|
|
|
std::vector<uint32_t> connectors;
|
|
drmModeModeInfo* mode = nullptr;
|
|
if (enable) {
|
|
connectors.push_back(connector->id);
|
|
mode = (drmModeModeInfo*)&data.modeInfo;
|
|
}
|
|
|
|
if (mode) {
|
|
connector->backend->backend->log(
|
|
AQ_LOG_DEBUG,
|
|
std::format("legacy drm: Modesetting CRTC, mode: clock {} hdisplay {} vdisplay {} vrefresh {}", mode->clock, mode->hdisplay, mode->vdisplay, mode->vrefresh));
|
|
} else
|
|
connector->backend->backend->log(AQ_LOG_DEBUG, "legacy drm: Modesetting CRTC, mode null");
|
|
|
|
if (auto ret = drmModeSetCrtc(connector->backend->gpu->fd, connector->crtc->id, mainFB ? mainFB->id : -1, 0, 0, connectors.data(), connectors.size(), mode); ret) {
|
|
connector->backend->backend->log(AQ_LOG_ERROR, std::format("legacy drm: drmModeSetCrtc failed: {}", strerror(-ret)));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (STATE.committed & COutputState::eOutputStateProperties::AQ_OUTPUT_STATE_ADAPTIVE_SYNC) {
|
|
if (STATE.adaptiveSync && !connector->canDoVrr) {
|
|
connector->backend->backend->log(AQ_LOG_ERROR, std::format("legacy drm: connector {} can't do vrr", connector->id));
|
|
return false;
|
|
}
|
|
|
|
if (connector->crtc->props.vrr_enabled) {
|
|
if (auto ret = drmModeObjectSetProperty(backend->gpu->fd, connector->crtc->id, DRM_MODE_OBJECT_CRTC, connector->crtc->props.vrr_enabled, (uint64_t)STATE.adaptiveSync);
|
|
ret) {
|
|
connector->backend->backend->log(AQ_LOG_ERROR, std::format("legacy drm: drmModeObjectSetProperty: vrr -> {} failed: {}", STATE.adaptiveSync, strerror(-ret)));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
connector->output->vrrActive = STATE.adaptiveSync;
|
|
connector->backend->backend->log(AQ_LOG_DEBUG, std::format("legacy drm: connector {} vrr -> {}", connector->id, STATE.adaptiveSync));
|
|
}
|
|
|
|
// TODO: gamma
|
|
|
|
if (data.cursorFB && connector->crtc->cursor && connector->output->cursorVisible && enable) {
|
|
uint32_t boHandle = 0;
|
|
auto attrs = data.cursorFB->buffer->dmabuf();
|
|
|
|
if (int ret = drmPrimeFDToHandle(connector->backend->gpu->fd, attrs.fds.at(0), &boHandle); ret) {
|
|
connector->backend->backend->log(AQ_LOG_ERROR, std::format("legacy drm: drmPrimeFDToHandle failed: {}", strerror(-ret)));
|
|
return false;
|
|
}
|
|
|
|
connector->backend->backend->log(AQ_LOG_DEBUG,
|
|
std::format("legacy drm: cursor fb: {} with bo handle {} from fd {}, size {}", connector->backend->gpu->fd, boHandle,
|
|
data.cursorFB->buffer->dmabuf().fds.at(0), data.cursorFB->buffer->size));
|
|
|
|
Vector2D cursorPos = connector->output->cursorPos;
|
|
|
|
struct drm_mode_cursor2 request = {
|
|
.flags = DRM_MODE_CURSOR_BO | DRM_MODE_CURSOR_MOVE,
|
|
.crtc_id = connector->crtc->id,
|
|
.x = (int32_t)cursorPos.x,
|
|
.y = (int32_t)cursorPos.y,
|
|
.width = (uint32_t)data.cursorFB->buffer->size.x,
|
|
.height = (uint32_t)data.cursorFB->buffer->size.y,
|
|
.handle = boHandle,
|
|
.hot_x = (int32_t)connector->output->cursorHotspot.x,
|
|
.hot_y = (int32_t)connector->output->cursorHotspot.y,
|
|
};
|
|
|
|
int ret = drmIoctl(connector->backend->gpu->fd, DRM_IOCTL_MODE_CURSOR2, &request);
|
|
|
|
if (boHandle && drmCloseBufferHandle(connector->backend->gpu->fd, boHandle))
|
|
connector->backend->backend->log(AQ_LOG_ERROR, "legacy drm: drmCloseBufferHandle in cursor failed");
|
|
|
|
if (ret) {
|
|
connector->backend->backend->log(AQ_LOG_ERROR, std::format("legacy drm: cursor drmIoctl failed: {}", strerror(errno)));
|
|
return false;
|
|
}
|
|
} else if (drmModeSetCursor(connector->backend->gpu->fd, connector->crtc->id, 0, 0, 0))
|
|
connector->backend->backend->log(AQ_LOG_ERROR, "legacy drm: cursor null failed");
|
|
|
|
if (!enable)
|
|
return true;
|
|
|
|
if (!(data.flags & DRM_MODE_PAGE_FLIP_EVENT))
|
|
return true;
|
|
|
|
if (int ret = drmModePageFlip(connector->backend->gpu->fd, connector->crtc->id, mainFB ? mainFB->id : -1, data.flags, &connector->pendingPageFlip); ret) {
|
|
connector->backend->backend->log(AQ_LOG_ERROR, std::format("legacy drm: drmModePageFlip failed: {}", strerror(-ret)));
|
|
return false;
|
|
}
|
|
|
|
connector->isPageFlipPending = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Aquamarine::CDRMLegacyImpl::testInternal(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data) {
|
|
return true; // TODO: lol
|
|
}
|
|
|
|
bool Aquamarine::CDRMLegacyImpl::commit(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data) {
|
|
if (!testInternal(connector, data))
|
|
return false;
|
|
|
|
return commitInternal(connector, data);
|
|
}
|
|
|
|
bool Aquamarine::CDRMLegacyImpl::reset() {
|
|
bool ok = true;
|
|
for (auto& connector : backend->connectors) {
|
|
if (!connector->crtc)
|
|
continue;
|
|
|
|
if (int ret = drmModeSetCrtc(backend->gpu->fd, connector->crtc->id, 0, 0, 0, nullptr, 0, nullptr); ret) {
|
|
connector->backend->backend->log(AQ_LOG_ERROR, std::format("legacy drm: reset failed: {}", strerror(-ret)));
|
|
ok = false;
|
|
}
|
|
}
|
|
|
|
return ok;
|
|
} |