diff --git a/README.md b/README.md index ff59843..5e81d18 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ This plugin is still very early in its development. There are also multiple thin - [ ] pendulum simulation - [X] per-shape length and starting angle (if possible) - [X] cursor shake to find -- [ ] overdue refactoring (wait for aquamarine merge) +- [X] overdue refactoring (wait for aquamarine merge) - [ ] ~~inverted cursor?~~ (i think out of scope here, but see the [inverted branch](https://github.com/VirtCode/hypr-dynamic-cursors/tree/inverted)) - [ ] hyprcursor magified shape @@ -57,8 +57,6 @@ hyprpm add https://github.com/virtcode/hypr-dynamic-cursors hyprpm enable dynamic-cursors ``` -Compatibility with other plugins is not guaranteed. It probably should work with most plugins, unless they also change your cursor's behaviour. It will however work with any cursor theme. - ### NixOS Add this flake to your inputs, note that using a mismatched/unsupported Hyprland release will fail to build or load the plugin: @@ -228,6 +226,11 @@ To rotate the cursor smoothly, the cursor shape needs to be changed quite often. If you have any ideas to improve performance, let me know! +## compatibility +Compatibility with other plugins is not guaranteed. It probably should work with most plugins, unless they also change your cursor's behaviour. It will however work with any cursor theme. + +Also, this plugin won't work if your hardware cusors rely on `cursor:allow_dumb_copy = true`, which is probably the case if you are on nvidia. You'll probably have to wait until hardware cursors are correctly supported on Hyprland. + ## development To work on this plugin, you can clone this repository and use the Makefile to build it. I suggest opening a nested Hyprland session, and loading the plugin there: diff --git a/hyprpm.toml b/hyprpm.toml index 0f17cde..dcbc707 100644 --- a/hyprpm.toml +++ b/hyprpm.toml @@ -7,5 +7,5 @@ build = [ ] commit_pins = [ # v Hyprland v hypr-dynamic-cursors - ["918d8340afd652b011b937d29d5eea0be08467f5", "359a66967c631e53a233628d85aa6f08be4d9269"], # v0.41.2 + ["918d8340afd652b011b937d29d5eea0be08467f5", "f0409be76564171a97a792deabab3bd0528fe40c"], # v0.41.2 ] diff --git a/src/cursor.cpp b/src/cursor.cpp index 06e3d09..e73c556 100644 --- a/src/cursor.cpp +++ b/src/cursor.cpp @@ -1,12 +1,14 @@ #include "config/config.hpp" #include "mode/Mode.hpp" #include "src/debug/Log.hpp" +#include "src/helpers/math/Math.hpp" #include "src/managers/eventLoop/EventLoopManager.hpp" #include #include #include #include +#include #define private public #include @@ -15,13 +17,8 @@ #undef private #include -#include "hyprland/cursor.hpp" #include -#include -#include -#include - #include "cursor.hpp" #include "renderer.hpp" @@ -97,7 +94,7 @@ void CDynamicCursors::renderSoftware(CPointerManager* pointers, SP pMo box.rot = resultShown.rotation; // now pass the hotspot to rotate around - renderCursorTextureInternalWithDamage(texture, &box, &damage, 1.F, pointers->currentCursorImage.hotspot * state->monitor->scale * zoom, zoom > 1 && **PNEAREST, resultShown.stretch.angle, resultShown.stretch.magnitude); + renderCursorTextureInternalWithDamage(texture, &box, &damage, 1.F, nullptr, 0, pointers->currentCursorImage.hotspot * state->monitor->scale * zoom, zoom > 1 && **PNEAREST, resultShown.stretch.angle, resultShown.stretch.magnitude); if (pointers->currentCursorImage.surface) pointers->currentCursorImage.surface->resource()->frame(now); @@ -134,56 +131,52 @@ void CDynamicCursors::damageSoftware(CPointerManager* pointers) { This function reimplements the hardware cursor buffer drawing. It is largely copied from hyprland, but adjusted to allow the cursor to be rotated. */ -wlr_buffer* CDynamicCursors::renderHardware(CPointerManager* pointers, SP state, SP texture) { - static auto* const* PHW_DEBUG= (Hyprlang::INT* const*) getConfig(CONFIG_HW_DEBUG); +SP CDynamicCursors::renderHardware(CPointerManager* pointers, SP state, SP texture) { + static auto* const* PHW_DEBUG = (Hyprlang::INT* const*) getConfig(CONFIG_HW_DEBUG); static auto* const* PNEAREST = (Hyprlang::INT* const*) getConfig(CONFIG_SHAKE_NEAREST); auto output = state->monitor->output; + + auto maxSize = output->cursorPlaneSize(); auto zoom = resultShown.scale; - auto size = pointers->currentCursorImage.size * zoom; - int diagonal = size.size(); - Vector2D padding = {diagonal, diagonal}; + auto cursorSize = pointers->currentCursorImage.size * zoom; + int cursorDiagonal = cursorSize.size(); + auto cursorPadding = Vector2D{cursorDiagonal, cursorDiagonal}; + auto targetSize = cursorSize + cursorPadding * 2; - // we try to allocate a buffer with padding, see software damage - auto target = size + padding * 2; - - if (output->impl->get_cursor_size) { - int w, h; - output->impl->get_cursor_size(output, &w, &h); - - if (w < target.x || h < target.y) { - Debug::log(TRACE, "hardware cursor too big! {} > {}x{}", pointers->currentCursorImage.size, w, h); - return nullptr; - } - - target.x = w; - target.y = h; - } - - if (target.x <= 0 || target.y <= 0) { - Debug::log(TRACE, "hw cursor for output {} failed the size checks ({}x{} is invalid)", state->monitor->szName, target.x, target.y); + if (maxSize == Vector2D{}) return nullptr; - } - if (!output->cursor_swapchain || target != 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 (targetSize.x > maxSize.x || targetSize.y > maxSize.y) { + Debug::log(TRACE, "hardware cursor too big! {} > {}", pointers->currentCursorImage.size, maxSize); return nullptr; } + } else + maxSize = targetSize; - wlr_swapchain_destroy(output->cursor_swapchain); - output->cursor_swapchain = wlr_swapchain_create(output->allocator, target.x, target.y, &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; @@ -192,9 +185,40 @@ wlr_buffer* CDynamicCursors::renderHardware(CPointerManager* pointers, SPmakeEGLCurrent(); - 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) { + + // dumb copy won't work with this plugin, as we just copy the buffer, and can't apply transformations to it + Debug::log(TRACE, "Failed to create cursor RB with format {}, mod {}", buf->dmabuf().format, buf->dmabuf().modifier); + static auto PDUMB = CConfigValue("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 = pointers->currentCursorImage.pBuffer ? pointers->currentCursorImage.pBuffer : pointers->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); @@ -204,18 +228,19 @@ wlr_buffer* CDynamicCursors::renderHardware(CPointerManager* pointers, SPclear(CColor{0.F, 0.F, 0.F, 0.F}); + // the box should start in the middle portion, rotate by our calculated amount - CBox xbox = {padding, Vector2D{pointers->currentCursorImage.size / pointers->currentCursorImage.scale * state->monitor->scale * zoom}.round()}; + CBox xbox = {cursorPadding, Vector2D{pointers->currentCursorImage.size / pointers->currentCursorImage.scale * state->monitor->scale * zoom}.round()}; xbox.rot = resultShown.rotation; // use our custom draw function - renderCursorTextureInternalWithDamage(texture, &xbox, &damage, 1.F, pointers->currentCursorImage.hotspot * state->monitor->scale * zoom, zoom > 1 && **PNEAREST, resultShown.stretch.angle, resultShown.stretch.magnitude); + renderCursorTextureInternalWithDamage(texture, &xbox, &damage, 1.F, pointers->currentCursorImage.waitTimeline, pointers->currentCursorImage.waitPoint, pointers->currentCursorImage.hotspot * state->monitor->scale * zoom, zoom > 1 && **PNEAREST, resultShown.stretch.angle, resultShown.stretch.magnitude); g_pHyprOpenGL->end(); glFlush(); g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; - wlr_buffer_unlock(buf); + g_pHyprRenderer->onRenderbufferDestroy(RBO.get()); return buf; } @@ -224,33 +249,28 @@ wlr_buffer* CDynamicCursors::renderHardware(CPointerManager* pointers, SP state, wlr_buffer* buf) { - if (!state->monitor->output->impl->set_cursor) +bool CDynamicCursors::setHardware(CPointerManager* pointers, SP state, SP buf) { + if (!(state->monitor->output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER)) return false; - auto P_MONITOR = state->monitor.lock(); - if (!P_MONITOR->output->cursor_swapchain) return false; + auto PMONITOR = state->monitor.lock(); // we need to transform the hotspot manually as we need to indent it by the padding int diagonal = pointers->currentCursorImage.size.size(); Vector2D padding = {diagonal, diagonal}; - const auto HOTSPOT = CBox{((pointers->currentCursorImage.hotspot * P_MONITOR->scale) + padding) * resultShown.scale, {0, 0}} - .transform(wlTransformToHyprutils(wlr_output_transform_invert(P_MONITOR->transform)), P_MONITOR->output->cursor_swapchain->width, P_MONITOR->output->cursor_swapchain->height) + const auto HOTSPOT = CBox{((pointers->currentCursorImage.hotspot * PMONITOR->scale) + padding) * resultShown.scale, {0, 0}} + .transform(wlTransformToHyprutils(invertTransform(PMONITOR->transform)), PMONITOR->cursorSwapchain->currentOptions().size.x, PMONITOR->cursorSwapchain->currentOptions().size.y) .pos(); 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; } @@ -271,7 +291,7 @@ void CDynamicCursors::onCursorMoved(CPointerManager* pointers) { continue; const auto CURSORPOS = pointers->getCursorPosForMonitor(m); - m->output->impl->move_cursor(m->output, CURSORPOS.x, CURSORPOS.y); + m->output->moveCursor(CURSORPOS); } calculate(MOVE); diff --git a/src/cursor.hpp b/src/cursor.hpp index d421ce7..6bcca4d 100644 --- a/src/cursor.hpp +++ b/src/cursor.hpp @@ -26,9 +26,9 @@ class CDynamicCursors { /* hook on damageIfSoftware*/ void damageSoftware(CPointerManager* pointers); /* hook on renderHWCursorBuffer */ - wlr_buffer* renderHardware(CPointerManager* pointers, SP state, SP texture); + SP renderHardware(CPointerManager* pointers, SP state, SP texture); /* hook on setHWCursorBuffer */ - bool setHardware(CPointerManager* pointers, SP state, wlr_buffer* buf); + bool setHardware(CPointerManager* pointers, SP state, SP buf); /* hook on setCursorFromName */ void setShape(const std::string& name); diff --git a/src/hyprland/cursor.cpp b/src/hyprland/cursor.cpp deleted file mode 100644 index 1d5bc4e..0000000 --- a/src/hyprland/cursor.cpp +++ /dev/null @@ -1,137 +0,0 @@ - -#include -#include - -#include -#include -#include - -/* -The following functions are copied 1:1 from the hyprland codebase. -This is nessecary, as these are static interop functions which wlroots which are not accessible through headers. -Will probably be obsolete anyway after https://github.com/hyprwm/Hyprland/pull/6608 -*/ - -// TODO: make nicer -// this will come with the eventual rewrite of wlr_drm, etc... -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; -} - -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; -} - -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); -} - -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; -} - -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; -} diff --git a/src/hyprland/cursor.hpp b/src/hyprland/cursor.hpp deleted file mode 100644 index cf6f0ce..0000000 --- a/src/hyprland/cursor.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#include - -/* -The following functions are copied 1:1 from the hyprland codebase. -This is nessecary, as these are static interop functions which wlroots which are not accessible through headers. -Will probably be obsolete anyway after https://github.com/hyprwm/Hyprland/pull/6608 -*/ - -bool wlr_drm_format_intersect(wlr_drm_format* dst, const wlr_drm_format* a, const wlr_drm_format* b); -bool wlr_drm_format_copy(wlr_drm_format* dst, const wlr_drm_format* src); -const wlr_drm_format_set* wlr_renderer_get_render_formats(wlr_renderer* r); -bool output_pick_format(wlr_output* output, const wlr_drm_format_set* display_formats, wlr_drm_format* format, uint32_t fmt); -bool output_pick_cursor_format(struct wlr_output* output, struct wlr_drm_format* format); diff --git a/src/hyprland/math.cpp b/src/hyprland/math.cpp deleted file mode 100644 index 98d8ebd..0000000 --- a/src/hyprland/math.cpp +++ /dev/null @@ -1,155 +0,0 @@ -#include - -/* -The following functions are copied 1:1 from the hyprland codebase. -This is nessecary because we cannot use functions which are not declared in any header. -*/ - -void matrixIdentity(float mat[9]) { - static const float identity[9] = { - 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - }; - memcpy(mat, identity, sizeof(identity)); -} - -void matrixMultiply(float mat[9], const float a[9], const float b[9]) { - float product[9]; - - product[0] = a[0] * b[0] + a[1] * b[3] + a[2] * b[6]; - product[1] = a[0] * b[1] + a[1] * b[4] + a[2] * b[7]; - product[2] = a[0] * b[2] + a[1] * b[5] + a[2] * b[8]; - - product[3] = a[3] * b[0] + a[4] * b[3] + a[5] * b[6]; - product[4] = a[3] * b[1] + a[4] * b[4] + a[5] * b[7]; - product[5] = a[3] * b[2] + a[4] * b[5] + a[5] * b[8]; - - product[6] = a[6] * b[0] + a[7] * b[3] + a[8] * b[6]; - product[7] = a[6] * b[1] + a[7] * b[4] + a[8] * b[7]; - product[8] = a[6] * b[2] + a[7] * b[5] + a[8] * b[8]; - - memcpy(mat, product, sizeof(product)); -} - -void matrixTranslate(float mat[9], float x, float y) { - float translate[9] = { - 1.0f, 0.0f, x, 0.0f, 1.0f, y, 0.0f, 0.0f, 1.0f, - }; - wlr_matrix_multiply(mat, mat, translate); -} - -void matrixScale(float mat[9], float x, float y) { - float scale[9] = { - x, 0.0f, 0.0f, 0.0f, y, 0.0f, 0.0f, 0.0f, 1.0f, - }; - matrixMultiply(mat, mat, scale); -} - -void matrixRotate(float mat[9], float rad) { - float rotate[9] = { - cos(rad), -sin(rad), 0.0f, sin(rad), cos(rad), 0.0f, 0.0f, 0.0f, 1.0f, - }; - wlr_matrix_multiply(mat, mat, rotate); -} - -static std::unordered_map> transforms = { - {HYPRUTILS_TRANSFORM_NORMAL, - { - 1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }}, - {HYPRUTILS_TRANSFORM_90, - { - 0.0f, - 1.0f, - 0.0f, - -1.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }}, - {HYPRUTILS_TRANSFORM_180, - { - -1.0f, - 0.0f, - 0.0f, - 0.0f, - -1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }}, - {HYPRUTILS_TRANSFORM_270, - { - 0.0f, - -1.0f, - 0.0f, - 1.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }}, - {HYPRUTILS_TRANSFORM_FLIPPED, - { - -1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }}, - {HYPRUTILS_TRANSFORM_FLIPPED_90, - { - 0.0f, - 1.0f, - 0.0f, - 1.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }}, - {HYPRUTILS_TRANSFORM_FLIPPED_180, - { - 1.0f, - 0.0f, - 0.0f, - 0.0f, - -1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }}, - {HYPRUTILS_TRANSFORM_FLIPPED_270, - { - 0.0f, - -1.0f, - 0.0f, - -1.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }}, -}; - -void matrixTransform(float mat[9], eTransform transform) { - matrixMultiply(mat, mat, transforms.at(transform).data()); -} diff --git a/src/hyprland/math.hpp b/src/hyprland/math.hpp deleted file mode 100644 index 9d32447..0000000 --- a/src/hyprland/math.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -/* -The following functions are copied 1:1 from the hyprland codebase. -This is nessecary because we cannot use functions which are not declared in any header. -*/ - -void matrixTransform(float mat[9], eTransform transform); -void matrixTranslate(float mat[9], float x, float y); -void matrixScale(float mat[9], float x, float y); -void matrixMultiply(float mat[9], const float a[9], const float b[9]); -void matrixIdentity(float mat[9]); -void matrixRotate(float mat[9], float rad); diff --git a/src/main.cpp b/src/main.cpp index aa4a5d4..3c52a1d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -32,16 +32,16 @@ void hkDamageIfSoftware(void* thisptr) { else (*(origDamageIfSoftware)g_pDamageIfSoftwareHook->m_pOriginal)(thisptr); } -typedef wlr_buffer* (*origRenderHWCursorBuffer)(void*, SP, SP); +typedef SP (*origRenderHWCursorBuffer)(void*, SP, SP); inline CFunctionHook* g_pRenderHWCursorBufferHook = nullptr; -wlr_buffer* hkRenderHWCursorBuffer(void* thisptr, SP state, SP texture) { +SP hkRenderHWCursorBuffer(void* thisptr, SP state, SP texture) { if (isEnabled()) return g_pDynamicCursors->renderHardware((CPointerManager*) thisptr, state, texture); else return (*(origRenderHWCursorBuffer)g_pRenderHWCursorBufferHook->m_pOriginal)(thisptr, state, texture); } -typedef bool (*origSetHWCursorBuffer)(void*, SP, wlr_buffer*); +typedef bool (*origSetHWCursorBuffer)(void*, SP, SP); inline CFunctionHook* g_pSetHWCursorBufferHook = nullptr; -bool hkSetHWCursorBuffer(void* thisptr, SP state, wlr_buffer* buffer) { +bool hkSetHWCursorBuffer(void* thisptr, SP state, SP buffer) { if (isEnabled()) return g_pDynamicCursors->setHardware((CPointerManager*) thisptr, state, buffer); else return (*(origSetHWCursorBuffer)g_pSetHWCursorBufferHook->m_pOriginal)(thisptr, state, buffer); } diff --git a/src/renderer.cpp b/src/renderer.cpp index 2663376..301a48f 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -11,7 +11,6 @@ #include #include "renderer.hpp" -#include "hyprland/math.hpp" /* This is the projectBox method from hyprland, but with support for rotation around a point, the hotspot. @@ -44,7 +43,7 @@ void projectCursorBox(float mat[9], CBox& box, eTransform transform, float rotat matrixTranslate(mat, -hotspot.x, -hotspot.y); } - wlr_matrix_scale(mat, width, height); + matrixScale(mat, width, height); if (transform != HYPRUTILS_TRANSFORM_NORMAL) { matrixTranslate(mat, 0.5, 0.5); @@ -58,9 +57,16 @@ void projectCursorBox(float mat[9], CBox& box, eTransform transform, float rotat /* This renders a texture with damage but rotates the texture around a given hotspot. */ -void renderCursorTextureInternalWithDamage(SP tex, CBox* pBox, CRegion* damage, float alpha, Vector2D hotspot, bool nearest, float stretchAngle, Vector2D stretch) { +void renderCursorTextureInternalWithDamage(SP tex, CBox* pBox, CRegion* damage, float alpha, SP waitTimeline, uint64_t waitPoint, Vector2D hotspot, bool nearest, float stretchAngle, Vector2D stretch) { TRACY_GPU_ZONE("RenderDynamicCursor"); + if (waitTimeline != nullptr) { + if (!g_pHyprOpenGL->waitForTimelinePoint(waitTimeline, waitPoint)) { + Debug::log(ERR, "renderTextureInternalWithDamage: failed to wait for explicit sync point {}", waitPoint); + return; + } + } + alpha = std::clamp(alpha, 0.f, 1.f); if (damage->empty()) @@ -70,12 +76,12 @@ void renderCursorTextureInternalWithDamage(SP tex, CBox* pBox, CRegion g_pHyprOpenGL->m_RenderData.renderModif.applyToBox(newBox); // get transform - const auto TRANSFORM = wlTransformToHyprutils(wlr_output_transform_invert(!g_pHyprOpenGL->m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : g_pHyprOpenGL->m_RenderData.pMonitor->transform)); + const auto TRANSFORM = wlTransformToHyprutils(invertTransform(!g_pHyprOpenGL->m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : g_pHyprOpenGL->m_RenderData.pMonitor->transform)); float matrix[9]; projectCursorBox(matrix, newBox, TRANSFORM, newBox.rot, g_pHyprOpenGL->m_RenderData.monitorProjection.data(), hotspot, stretchAngle, stretch); float glMatrix[9]; - wlr_matrix_multiply(glMatrix, g_pHyprOpenGL->m_RenderData.projection, matrix); + matrixMultiply(glMatrix, g_pHyprOpenGL->m_RenderData.projection, matrix); CShader* shader = nullptr; @@ -102,7 +108,7 @@ void renderCursorTextureInternalWithDamage(SP tex, CBox* pBox, CRegion #ifndef GLES2 glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix); #else - wlr_matrix_transpose(glMatrix, glMatrix); + matrixTranspose(glMatrix, glMatrix); glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix); #endif glUniform1i(shader->tex, 0); @@ -111,7 +117,7 @@ void renderCursorTextureInternalWithDamage(SP tex, CBox* pBox, CRegion glUniform1i(shader->discardAlpha, 0); CBox transformedBox = newBox; - transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(g_pHyprOpenGL->m_RenderData.pMonitor->transform)), g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y); + transformedBox.transform(wlTransformToHyprutils(invertTransform(g_pHyprOpenGL->m_RenderData.pMonitor->transform)), g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height); diff --git a/src/renderer.hpp b/src/renderer.hpp index c392acf..81dc1ff 100644 --- a/src/renderer.hpp +++ b/src/renderer.hpp @@ -1,4 +1,4 @@ #include #include -void renderCursorTextureInternalWithDamage(SP tex, CBox* pBox, CRegion* damage, float alpha, Vector2D hotspot, bool nearest, float stretchAngle, Vector2D stretch); +void renderCursorTextureInternalWithDamage(SP tex, CBox* pBox, CRegion* damage, float alpha, SP waitTimeline, uint64_t waitPoint, Vector2D hotspot, bool nearest, float stretchAngle, Vector2D stretch);