mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-03 05:31:59 -07:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user