summaryrefslogtreecommitdiff
path: root/src/managers/PointerManager.cpp
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2024-07-21 13:09:54 +0200
committerGitHub <noreply@github.com>2024-07-21 13:09:54 +0200
commit016da234d0e852de3ef20eb2e89ac58d2a85f6e7 (patch)
tree496085987176551b0794fffc069877d44943e2f1 /src/managers/PointerManager.cpp
parentf642fb97df5c69267a03452533de383ff8023570 (diff)
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>
Diffstat (limited to 'src/managers/PointerManager.cpp')
-rw-r--r--src/managers/PointerManager.cpp283
1 files changed, 90 insertions, 193 deletions
diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp
index 7090645f..cf10db71 100644
--- a/src/managers/PointerManager.cpp
+++ b/src/managers/PointerManager.cpp
@@ -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);
-
- if (w < currentCursorImage.size.x || h < currentCursorImage.size.y) {
- Debug::log(TRACE, "hardware cursor too big! {} > {}x{}", currentCursorImage.size, w, h);
- return nullptr;
- }
- }
+ auto maxSize = output->cursorPlaneSize();
+ auto cursorSize = currentCursorImage.size;
- 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;
+
+ if (!state->monitor->cursorSwapchain || maxSize != state->monitor->cursorSwapchain->currentOptions().size) {
- 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)
+ state->monitor->cursorSwapchain = Aquamarine::CSwapchain::create(state->monitor->output->getBackend()->preferredAllocator(), state->monitor->output->getBackend());
- if (!output->cursor_swapchain) {
- Debug::log(TRACE, "Failed to create cursor swapchain");
+ 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;
}