Core: Move to aquamarine (#6608)

Moves Hyprland from wlroots to aquamarine for the backend.

---------

Signed-off-by: Vaxry <vaxry@vaxry.net>
Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
Co-authored-by: Jan Beich <jbeich@FreeBSD.org>
Co-authored-by: vaxerski <vaxerski@users.noreply.github.com>
Co-authored-by: UjinT34 <41110182+UjinT34@users.noreply.github.com>
Co-authored-by: Tom Englund <tomenglund26@gmail.com>
Co-authored-by: Ikalco <73481042+ikalco@users.noreply.github.com>
Co-authored-by: diniamo <diniamo53@gmail.com>
This commit is contained in:
Vaxry
2024-07-21 13:09:54 +02:00
committed by GitHub
parent f642fb97df
commit 016da234d0
131 changed files with 4755 additions and 3460 deletions

View File

@@ -6,133 +6,8 @@
#include "../protocols/core/Compositor.hpp"
#include "eventLoop/EventLoopManager.hpp"
#include "SeatManager.hpp"
#include <wlr/interfaces/wlr_output.h>
#include <wlr/render/interface.h>
#include <wlr/render/wlr_renderer.h>
// TODO: make nicer
// this will come with the eventual rewrite of wlr_drm, etc...
static bool wlr_drm_format_intersect(wlr_drm_format* dst, const wlr_drm_format* a, const wlr_drm_format* b) {
ASSERT(a->format == b->format);
size_t capacity = a->len < b->len ? a->len : b->len;
uint64_t* modifiers = (uint64_t*)malloc(sizeof(*modifiers) * capacity);
if (!modifiers)
return false;
struct wlr_drm_format fmt = {
.format = a->format,
.len = 0,
.capacity = capacity,
.modifiers = modifiers,
};
for (size_t i = 0; i < a->len; i++) {
for (size_t j = 0; j < b->len; j++) {
if (a->modifiers[i] == b->modifiers[j]) {
ASSERT(fmt.len < fmt.capacity);
fmt.modifiers[fmt.len++] = a->modifiers[i];
break;
}
}
}
wlr_drm_format_finish(dst);
*dst = fmt;
return true;
}
static bool wlr_drm_format_copy(wlr_drm_format* dst, const wlr_drm_format* src) {
ASSERT(src->len <= src->capacity);
uint64_t* modifiers = (uint64_t*)malloc(sizeof(*modifiers) * src->len);
if (!modifiers)
return false;
memcpy(modifiers, src->modifiers, sizeof(*modifiers) * src->len);
wlr_drm_format_finish(dst);
dst->capacity = src->len;
dst->len = src->len;
dst->format = src->format;
dst->modifiers = modifiers;
return true;
}
static const wlr_drm_format_set* wlr_renderer_get_render_formats(wlr_renderer* r) {
if (!r->impl->get_render_formats)
return nullptr;
return r->impl->get_render_formats(r);
}
static bool output_pick_format(wlr_output* output, const wlr_drm_format_set* display_formats, wlr_drm_format* format, uint32_t fmt) {
const wlr_drm_format_set* render_formats = wlr_renderer_get_render_formats(g_pCompositor->m_sWLRRenderer);
if (render_formats == NULL) {
wlr_log(WLR_ERROR, "Failed to get render formats");
return false;
}
const wlr_drm_format* render_format = wlr_drm_format_set_get(render_formats, fmt);
if (render_format == NULL) {
wlr_log(WLR_DEBUG, "Renderer doesn't support format 0x%" PRIX32, fmt);
return false;
}
if (display_formats != NULL) {
const wlr_drm_format* display_format = wlr_drm_format_set_get(display_formats, fmt);
if (display_format == NULL) {
wlr_log(WLR_DEBUG, "Output doesn't support format 0x%" PRIX32, fmt);
return false;
}
if (!wlr_drm_format_intersect(format, display_format, render_format)) {
wlr_log(WLR_DEBUG,
"Failed to intersect display and render "
"modifiers for format 0x%" PRIX32 " on output %s",
fmt, output->name);
return false;
}
} else {
// The output can display any format
if (!wlr_drm_format_copy(format, render_format))
return false;
}
if (format->len == 0) {
wlr_drm_format_finish(format);
wlr_log(WLR_DEBUG, "Failed to pick output format");
return false;
}
return true;
}
static bool output_pick_cursor_format(struct wlr_output* output, struct wlr_drm_format* format) {
struct wlr_allocator* allocator = output->allocator;
ASSERT(allocator != NULL);
const struct wlr_drm_format_set* display_formats = NULL;
if (output->impl->get_cursor_formats) {
display_formats = output->impl->get_cursor_formats(output, allocator->buffer_caps);
if (display_formats == NULL) {
wlr_log(WLR_DEBUG, "Failed to get cursor display formats");
return false;
}
}
// Note: taken from https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4596/diffs#diff-content-e3ea164da86650995728d70bd118f6aa8c386797
// If this fails to find a shared modifier try to use a linear
// modifier. This avoids a scenario where the hardware cannot render to
// linear textures but only linear textures are supported for cursors,
// as is the case with Nvidia and VmWare GPUs
if (!output_pick_format(output, display_formats, format, DRM_FORMAT_ARGB8888)) {
// Clear the format as output_pick_format doesn't zero it
memset(format, 0, sizeof(*format));
return output_pick_format(output, NULL, format, DRM_FORMAT_ARGB8888);
}
return true;
}
#include <cstring>
#include <gbm.h>
CPointerManager::CPointerManager() {
hooks.monitorAdded = g_pHookSystem->hookDynamic("newMonitor", [this](void* self, SCallbackInfo& info, std::any data) {
@@ -201,6 +76,11 @@ void CPointerManager::unlockSoftwareForMonitor(SP<CMonitor> mon) {
updateCursorBackend();
}
bool CPointerManager::softwareLockedFor(SP<CMonitor> mon) {
auto state = stateFor(mon);
return state->softwareLocks > 0 || state->hardwareFailed;
}
Vector2D CPointerManager::position() {
return pointerPos;
}
@@ -216,7 +96,7 @@ SP<CPointerManager::SMonitorPointerState> CPointerManager::stateFor(SP<CMonitor>
return *it;
}
void CPointerManager::setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, const float& scale) {
void CPointerManager::setCursorBuffer(SP<Aquamarine::IBuffer> buf, const Vector2D& hotspot, const float& scale) {
damageIfSoftware();
if (buf == currentCursorImage.pBuffer) {
if (hotspot != currentCursorImage.hotspot || scale != currentCursorImage.scale) {
@@ -232,10 +112,8 @@ void CPointerManager::setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot,
resetCursorImage(false);
if (buf) {
currentCursorImage.size = {buf->width, buf->height};
currentCursorImage.pBuffer = wlr_buffer_lock(buf);
currentCursorImage.hyprListener_destroyBuffer.initCallback(&buf->events.destroy, [this](void* owner, void* data) { resetCursorImage(); }, this, "CPointerManager");
currentCursorImage.size = buf->size;
currentCursorImage.pBuffer = buf;
}
currentCursorImage.hotspot = hotspot;
@@ -317,8 +195,8 @@ void CPointerManager::recheckEnteredOutputs() {
// if we are using hw cursors, prevent
// the cursor from being stuck at the last point.
// if we are leaving it, move it to narnia.
if (!s->hardwareFailed && s->monitor->output->impl->move_cursor)
s->monitor->output->impl->move_cursor(s->monitor->output, -1337, -420);
if (!s->hardwareFailed && (s->monitor->output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER))
s->monitor->output->moveCursor({-1337, -420});
if (!currentCursorImage.surface)
continue;
@@ -339,16 +217,11 @@ void CPointerManager::resetCursorImage(bool apply) {
currentCursorImage.destroySurface.reset();
currentCursorImage.commitSurface.reset();
currentCursorImage.surface.reset();
} else if (currentCursorImage.pBuffer) {
wlr_buffer_unlock(currentCursorImage.pBuffer);
currentCursorImage.hyprListener_destroyBuffer.removeCallback();
} else if (currentCursorImage.pBuffer)
currentCursorImage.pBuffer = nullptr;
}
if (currentCursorImage.pBufferTexture) {
wlr_texture_destroy(currentCursorImage.pBufferTexture);
currentCursorImage.pBufferTexture = nullptr;
}
if (currentCursorImage.bufferTex)
currentCursorImage.bufferTex = nullptr;
currentCursorImage.scale = 1.F;
currentCursorImage.hotspot = {0, 0};
@@ -370,9 +243,8 @@ void CPointerManager::resetCursorImage(bool apply) {
}
if (ms->cursorFrontBuffer) {
if (ms->monitor->output->impl->set_cursor)
ms->monitor->output->impl->set_cursor(ms->monitor->output, nullptr, 0, 0);
wlr_buffer_unlock(ms->cursorFrontBuffer);
if (ms->monitor->output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER)
ms->monitor->output->setCursor(nullptr, {});
ms->cursorFrontBuffer = nullptr;
}
}
@@ -418,18 +290,18 @@ void CPointerManager::onCursorMoved() {
continue;
const auto CURSORPOS = getCursorPosForMonitor(m);
m->output->impl->move_cursor(m->output, CURSORPOS.x, CURSORPOS.y);
m->output->moveCursor(CURSORPOS);
}
}
bool CPointerManager::attemptHardwareCursor(SP<CPointerManager::SMonitorPointerState> state) {
auto output = state->monitor->output;
if (!output->impl->set_cursor)
if (!(output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER))
return false;
const auto CURSORPOS = getCursorPosForMonitor(state->monitor.lock());
state->monitor->output->impl->move_cursor(state->monitor->output, CURSORPOS.x, CURSORPOS.y);
state->monitor->output->moveCursor(CURSORPOS);
auto texture = getCurrentCursorTexture();
@@ -459,64 +331,62 @@ bool CPointerManager::attemptHardwareCursor(SP<CPointerManager::SMonitorPointerS
return success;
}
bool CPointerManager::setHWCursorBuffer(SP<SMonitorPointerState> state, wlr_buffer* buf) {
if (!state->monitor->output->impl->set_cursor)
bool CPointerManager::setHWCursorBuffer(SP<SMonitorPointerState> state, SP<Aquamarine::IBuffer> buf) {
if (!(state->monitor->output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER))
return false;
const auto HOTSPOT = transformedHotspot(state->monitor.lock());
Debug::log(TRACE, "[pointer] hw transformed hotspot for {}: {}", state->monitor->szName, HOTSPOT);
if (!state->monitor->output->impl->set_cursor(state->monitor->output, buf, HOTSPOT.x, HOTSPOT.y))
if (!state->monitor->output->setCursor(buf, HOTSPOT))
return false;
wlr_buffer_unlock(state->cursorFrontBuffer);
state->cursorFrontBuffer = buf;
g_pCompositor->scheduleFrameForMonitor(state->monitor.get());
if (buf)
wlr_buffer_lock(buf);
g_pCompositor->scheduleFrameForMonitor(state->monitor.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE);
return true;
}
wlr_buffer* CPointerManager::renderHWCursorBuffer(SP<CPointerManager::SMonitorPointerState> state, SP<CTexture> texture) {
SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager::SMonitorPointerState> state, SP<CTexture> texture) {
auto output = state->monitor->output;
int w = currentCursorImage.size.x, h = currentCursorImage.size.y;
if (output->impl->get_cursor_size) {
output->impl->get_cursor_size(output, &w, &h);
auto maxSize = output->cursorPlaneSize();
auto cursorSize = currentCursorImage.size;
if (w < currentCursorImage.size.x || h < currentCursorImage.size.y) {
Debug::log(TRACE, "hardware cursor too big! {} > {}x{}", currentCursorImage.size, w, h);
return nullptr;
}
}
if (w <= 0 || h <= 0) {
Debug::log(TRACE, "hw cursor for output {} failed the size checks ({}x{} is invalid)", state->monitor->szName, w, h);
if (maxSize == Vector2D{})
return nullptr;
}
if (!output->cursor_swapchain || Vector2D{w, h} != Vector2D{output->cursor_swapchain->width, output->cursor_swapchain->height}) {
wlr_drm_format fmt = {0};
if (!output_pick_cursor_format(output, &fmt)) {
Debug::log(TRACE, "Failed to pick cursor format");
if (maxSize != Vector2D{-1, -1}) {
if (cursorSize.x > maxSize.x || cursorSize.y > maxSize.y) {
Debug::log(TRACE, "hardware cursor too big! {} > {}", currentCursorImage.size, maxSize);
return nullptr;
}
} else
maxSize = cursorSize;
wlr_swapchain_destroy(output->cursor_swapchain);
output->cursor_swapchain = wlr_swapchain_create(output->allocator, w, h, &fmt);
wlr_drm_format_finish(&fmt);
if (!state->monitor->cursorSwapchain || maxSize != state->monitor->cursorSwapchain->currentOptions().size) {
if (!output->cursor_swapchain) {
Debug::log(TRACE, "Failed to create cursor swapchain");
if (!state->monitor->cursorSwapchain)
state->monitor->cursorSwapchain = Aquamarine::CSwapchain::create(state->monitor->output->getBackend()->preferredAllocator(), state->monitor->output->getBackend());
auto options = state->monitor->cursorSwapchain->currentOptions();
options.size = maxSize;
options.length = 2;
options.scanout = true;
options.cursor = true;
options.multigpu = state->monitor->output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_iDRMFD;
// We do not set the format. If it's unset (DRM_FORMAT_INVALID) then the swapchain will pick for us,
// but if it's set, we don't wanna change it.
if (!state->monitor->cursorSwapchain->reconfigure(options)) {
Debug::log(TRACE, "Failed to reconfigure cursor swapchain");
return nullptr;
}
}
wlr_buffer* buf = wlr_swapchain_acquire(output->cursor_swapchain, nullptr);
auto buf = state->monitor->cursorSwapchain->next(nullptr);
if (!buf) {
Debug::log(TRACE, "Failed to acquire a buffer from the cursor swapchain");
return nullptr;
@@ -525,16 +395,45 @@ wlr_buffer* CPointerManager::renderHWCursorBuffer(SP<CPointerManager::SMonitorPo
CRegion damage = {0, 0, INT16_MAX, INT16_MAX};
g_pHyprRenderer->makeEGLCurrent();
g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get(); // has to be set cuz allocs
g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get();
auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format);
if (!RBO) {
Debug::log(TRACE, "Failed to create cursor RB with format {}, mod {}", buf->dmabuf().format, buf->dmabuf().modifier);
static auto PDUMB = CConfigValue<Hyprlang::INT>("cursor:allow_dumb_copy");
if (!*PDUMB)
return nullptr;
auto bufData = buf->beginDataPtr(0);
auto bufPtr = std::get<0>(bufData);
// clear buffer
memset(bufPtr, 0, std::get<2>(bufData));
auto texBuffer = currentCursorImage.pBuffer ? currentCursorImage.pBuffer : currentCursorImage.surface->resource()->current.buffer;
if (texBuffer) {
auto textAttrs = texBuffer->shm();
auto texData = texBuffer->beginDataPtr(GBM_BO_TRANSFER_WRITE);
auto texPtr = std::get<0>(texData);
Debug::log(TRACE, "cursor texture {}x{} {} {} {}", textAttrs.size.x, textAttrs.size.y, (void*)texPtr, textAttrs.format, textAttrs.stride);
// copy cursor texture
for (int i = 0; i < texBuffer->shm().size.y; i++)
memcpy(bufPtr + i * buf->dmabuf().strides[0], texPtr + i * textAttrs.stride, textAttrs.stride);
}
buf->endDataPtr();
return buf;
}
const auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, DRM_FORMAT_ARGB8888);
RBO->bind();
g_pHyprOpenGL->beginSimple(state->monitor.get(), damage, RBO);
g_pHyprOpenGL->clear(CColor{0.F, 0.F, 0.F, 0.F});
CBox xbox = {{}, Vector2D{currentCursorImage.size / currentCursorImage.scale * state->monitor->scale}.round()};
Debug::log(TRACE, "[pointer] monitor: {}, size: {}, hw buf: {}, scale: {:.2f}, monscale: {:.2f}, xbox: {}", state->monitor->szName, currentCursorImage.size, Vector2D{w, h},
Debug::log(TRACE, "[pointer] monitor: {}, size: {}, hw buf: {}, scale: {:.2f}, monscale: {:.2f}, xbox: {}", state->monitor->szName, currentCursorImage.size, cursorSize,
currentCursorImage.scale, state->monitor->scale, xbox.size());
g_pHyprOpenGL->renderTexture(texture, &xbox, 1.F);
@@ -543,9 +442,7 @@ wlr_buffer* CPointerManager::renderHWCursorBuffer(SP<CPointerManager::SMonitorPo
glFlush();
g_pHyprOpenGL->m_RenderData.pMonitor = nullptr;
g_pHyprRenderer->onRenderbufferDestroy(RBO);
wlr_buffer_unlock(buf);
g_pHyprRenderer->onRenderbufferDestroy(RBO.get());
return buf;
}
@@ -579,7 +476,7 @@ void CPointerManager::renderSoftwareCursorsFor(SP<CMonitor> pMonitor, timespec*
box.x = std::round(box.x);
box.y = std::round(box.y);
g_pHyprOpenGL->renderTextureWithDamage(texture, &box, &damage, 1.F);
g_pHyprOpenGL->renderTextureWithDamage(texture, &box, &damage, 1.F, 0, false, false, currentCursorImage.waitTimeline, currentCursorImage.waitPoint);
if (currentCursorImage.surface)
currentCursorImage.surface->resource()->frame(now);
@@ -587,17 +484,19 @@ void CPointerManager::renderSoftwareCursorsFor(SP<CMonitor> pMonitor, timespec*
Vector2D CPointerManager::getCursorPosForMonitor(SP<CMonitor> pMonitor) {
return CBox{pointerPos - pMonitor->vecPosition, {0, 0}}
//.transform(pMonitor->transform, pMonitor->vecTransformedSize.x / pMonitor->scale, pMonitor->vecTransformedSize.y / pMonitor->scale)
.transform(wlTransformToHyprutils(invertTransform(pMonitor->transform)), pMonitor->vecTransformedSize.x / pMonitor->scale,
pMonitor->vecTransformedSize.y / pMonitor->scale)
.pos() *
pMonitor->scale;
}
Vector2D CPointerManager::transformedHotspot(SP<CMonitor> pMonitor) {
if (!pMonitor->output->cursor_swapchain)
if (!pMonitor->cursorSwapchain)
return {}; // doesn't matter, we have no hw cursor, and this is only for hw cursors
return CBox{currentCursorImage.hotspot * pMonitor->scale, {0, 0}}
.transform(wlTransformToHyprutils(wlr_output_transform_invert(pMonitor->transform)), pMonitor->output->cursor_swapchain->width, pMonitor->output->cursor_swapchain->height)
.transform(wlTransformToHyprutils(invertTransform(pMonitor->transform)), pMonitor->cursorSwapchain->currentOptions().size.x,
pMonitor->cursorSwapchain->currentOptions().size.y)
.pos();
}
@@ -799,10 +698,8 @@ SP<CTexture> CPointerManager::getCurrentCursorTexture() {
return nullptr;
if (currentCursorImage.pBuffer) {
if (!currentCursorImage.pBufferTexture) {
currentCursorImage.pBufferTexture = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, currentCursorImage.pBuffer);
currentCursorImage.bufferTex = makeShared<CTexture>(currentCursorImage.pBufferTexture);
}
if (!currentCursorImage.bufferTex)
currentCursorImage.bufferTex = makeShared<CTexture>(currentCursorImage.pBuffer);
return currentCursorImage.bufferTex;
}