fix dumb cursor buffers

This commit is contained in:
UjinT34 2024-07-26 13:57:22 +03:00
parent 7238dd9d38
commit c120740a43
3 changed files with 42 additions and 12 deletions

View file

@ -396,25 +396,27 @@ int CMonitor::findAvailableDefaultWS() {
return INT32_MAX; // shouldn't be reachable
}
SP<Aquamarine::CSwapchain> CMonitor::resizeSwapchain(SP<Aquamarine::CSwapchain> swapchain, Vector2D size, bool isCursor) {
SP<Aquamarine::CSwapchain> CMonitor::resizeSwapchain(SP<Aquamarine::CSwapchain> swapchain, Vector2D size, bool isCursor, bool isDumb) {
if (!swapchain || size != swapchain->currentOptions().size) {
if (!swapchain)
swapchain = Aquamarine::CSwapchain::create(output->getBackend()->preferredAllocator(), output->getBackend());
if (!swapchain) {
auto allocator = isDumb && output->getBackend()->fallbackAllocator() ? output->getBackend()->fallbackAllocator() : output->getBackend()->preferredAllocator();
swapchain = Aquamarine::CSwapchain::create(allocator, output->getBackend());
}
auto options = swapchain->currentOptions();
options.size = size;
options.length = 2;
options.scanout = true;
options.cursor = isCursor;
options.multigpu = output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_iDRMFD;
options.multigpu = !isDumb && output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_iDRMFD;
if (!isCursor && cursorSwapchain)
options.format = cursorSwapchain->currentOptions().format;
// 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 (!swapchain->reconfigure(options)) {
Debug::log(TRACE, "Failed to reconfigure {} swapchain", isCursor ? "cursor" : "cursor fallback");
Debug::log(TRACE, "Failed to reconfigure{} {} swapchain", isCursor ? "cursor" : "cursor fallback", isDumb ? " dumb" : "");
return nullptr;
}
}
@ -862,13 +864,21 @@ bool CMonitor::attemptDirectScanout() {
}
bool CMonitor::resizeCursorSwapchain(Vector2D size) {
auto swapchain = resizeSwapchain(cursorSwapchain, size, true);
auto swapchain = resizeSwapchain(cursorSwapchain, size, true, useDumbCursorBuffer);
if (!cursorSwapchain)
cursorSwapchain = swapchain;
return !!swapchain;
}
bool CMonitor::resizeCursorSwapchain(Vector2D size, bool useDumb) {
if (useDumbCursorBuffer != useDumb && cursorSwapchain) {
useDumbCursorBuffer = useDumb;
cursorSwapchain = nullptr; // recreate swapchain with a different allocator
}
return resizeCursorSwapchain(size);
}
bool CMonitor::resizeCursorFallbackSwapchain(Vector2D size) {
auto swapchain = resizeSwapchain(cursorFallbackSwapchain, size, false);
if (!cursorFallbackSwapchain)

View file

@ -180,6 +180,7 @@ class CMonitor {
void scheduleDone();
bool attemptDirectScanout();
bool resizeCursorSwapchain(Vector2D size);
bool resizeCursorSwapchain(Vector2D size, bool useDumb);
bool resizeCursorFallbackSwapchain(Vector2D size);
bool m_bEnabled = false;
@ -194,9 +195,10 @@ class CMonitor {
private:
void setupDefaultWS(const SMonitorRule&);
int findAvailableDefaultWS();
SP<Aquamarine::CSwapchain> resizeSwapchain(SP<Aquamarine::CSwapchain> swapchain, Vector2D size, bool isCursor);
SP<Aquamarine::CSwapchain> resizeSwapchain(SP<Aquamarine::CSwapchain> swapchain, Vector2D size, bool isCursor, bool isDumb = false);
wl_event_source* doneSource = nullptr;
wl_event_source* doneSource = nullptr;
bool useDumbCursorBuffer = false;
struct {
CHyprSignalListener frame;

View file

@ -411,10 +411,25 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
static auto PDUMB = CConfigValue<Hyprlang::INT>("cursor:allow_dumb_copy");
static auto PSLOW = CConfigValue<Hyprlang::INT>("cursor:allow_slow_copy");
auto isDumb = buf->type() == Aquamarine::BUFFER_TYPE_DMABUF_DUMB;
if (isDumb != *PDUMB) {
Debug::log(TRACE, "[pointer] switching swapchain to {}", *PDUMB ? "dumb" : "gbm");
if (!state->monitor->resizeCursorSwapchain(maxSize, *PDUMB))
return nullptr;
buf = state->monitor->cursorSwapchain->next(nullptr);
if (!buf) {
Debug::log(TRACE, "Failed to acquire a buffer from the cursor swapchain");
return nullptr;
}
isDumb = buf->type() == Aquamarine::BUFFER_TYPE_DMABUF_DUMB;
}
if (!*PDUMB && !*PSLOW)
return nullptr;
if (*PSLOW) {
// slow copy will fail with dumb buffer
if (*PSLOW && !*PDUMB) {
Debug::log(TRACE, "[pointer] performing slow copy");
needsFallback = true;
@ -437,8 +452,11 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
auto bufData = buf->beginDataPtr(0);
auto bufPtr = std::get<0>(bufData);
auto bufSize = isDumb ? buf->shm().size : buf->dmabuf().size;
auto bufStride = isDumb ? buf->shm().stride : buf->dmabuf().strides[0];
// clear buffer
memset(bufPtr, 0, buf->type() == Aquamarine::BUFFER_TYPE_DMABUF_DUMB ? std::get<2>(bufData) * buf->dmabuf().size.y : std::get<2>(bufData));
memset(bufPtr, 0, bufStride * bufSize.y);
auto texBuffer = currentCursorImage.pBuffer ? currentCursorImage.pBuffer : currentCursorImage.surface->resource()->current.buffer;
if (texBuffer) {
@ -448,11 +466,11 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
Debug::log(TRACE, "cursor texture {}x{} {} {} {}", textAttrs.size.x, textAttrs.size.y, (void*)texPtr, textAttrs.format, textAttrs.stride);
// copy cursor texture
if (buf->dmabuf().strides[0] == textAttrs.stride && buf->dmabuf().size == textAttrs.size)
if (bufStride == textAttrs.stride && bufSize == textAttrs.size)
memcpy(bufPtr, texPtr, textAttrs.stride * textAttrs.size.y);
else
for (int i = 0; i < texBuffer->shm().size.y; i++)
memcpy(bufPtr + i * buf->dmabuf().strides[0], texPtr + i * textAttrs.stride, textAttrs.stride);
memcpy(bufPtr + i * bufStride, texPtr + i * textAttrs.stride, textAttrs.stride);
}
buf->endDataPtr();