mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-23 23:05:58 +01:00
first attempt
This commit is contained in:
parent
5115f1993c
commit
0a95440131
2 changed files with 86 additions and 22 deletions
|
@ -399,8 +399,10 @@ int CMonitor::findAvailableDefaultWS() {
|
||||||
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) {
|
||||||
if (!swapchain || size != swapchain->currentOptions().size) {
|
if (!swapchain || size != swapchain->currentOptions().size) {
|
||||||
|
|
||||||
if (!swapchain)
|
if (!swapchain) {
|
||||||
|
Debug::log(TRACE, "creating new cursor {} swapchain", isCursor);
|
||||||
swapchain = Aquamarine::CSwapchain::create(output->getBackend()->preferredAllocator(), output->getBackend());
|
swapchain = Aquamarine::CSwapchain::create(output->getBackend()->preferredAllocator(), output->getBackend());
|
||||||
|
}
|
||||||
|
|
||||||
auto options = swapchain->currentOptions();
|
auto options = swapchain->currentOptions();
|
||||||
options.size = size;
|
options.size = size;
|
||||||
|
@ -408,6 +410,8 @@ SP<Aquamarine::CSwapchain> CMonitor::resizeSwapchain(SP<Aquamarine::CSwapchain>
|
||||||
options.scanout = true;
|
options.scanout = true;
|
||||||
options.cursor = isCursor;
|
options.cursor = isCursor;
|
||||||
options.multigpu = output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_iDRMFD;
|
options.multigpu = 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,
|
// 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.
|
// but if it's set, we don't wanna change it.
|
||||||
|
|
||||||
|
@ -860,6 +864,7 @@ bool CMonitor::attemptDirectScanout() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMonitor::resizeCursorSwapchain(Vector2D size) {
|
bool CMonitor::resizeCursorSwapchain(Vector2D size) {
|
||||||
|
Debug::log(TRACE, "resizeCursorSwapchain");
|
||||||
auto swapchain = resizeSwapchain(cursorSwapchain, size, true);
|
auto swapchain = resizeSwapchain(cursorSwapchain, size, true);
|
||||||
if (!cursorSwapchain)
|
if (!cursorSwapchain)
|
||||||
cursorSwapchain = swapchain;
|
cursorSwapchain = swapchain;
|
||||||
|
@ -868,6 +873,7 @@ bool CMonitor::resizeCursorSwapchain(Vector2D size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMonitor::resizeCursorFallbackSwapchain(Vector2D size) {
|
bool CMonitor::resizeCursorFallbackSwapchain(Vector2D size) {
|
||||||
|
Debug::log(TRACE, "resizeCursorFallbackSwapchain");
|
||||||
auto swapchain = resizeSwapchain(cursorFallbackSwapchain, size, false);
|
auto swapchain = resizeSwapchain(cursorFallbackSwapchain, size, false);
|
||||||
if (!cursorFallbackSwapchain)
|
if (!cursorFallbackSwapchain)
|
||||||
cursorFallbackSwapchain = swapchain;
|
cursorFallbackSwapchain = swapchain;
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
#include "../protocols/core/Compositor.hpp"
|
#include "../protocols/core/Compositor.hpp"
|
||||||
#include "eventLoop/EventLoopManager.hpp"
|
#include "eventLoop/EventLoopManager.hpp"
|
||||||
#include "SeatManager.hpp"
|
#include "SeatManager.hpp"
|
||||||
|
#include "render/OpenGL.hpp"
|
||||||
|
#include <GLES3/gl32.h>
|
||||||
|
#include <aquamarine/buffer/Buffer.hpp>
|
||||||
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <gbm.h>
|
#include <gbm.h>
|
||||||
|
|
||||||
|
@ -396,35 +400,34 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
|
||||||
g_pHyprRenderer->makeEGLCurrent();
|
g_pHyprRenderer->makeEGLCurrent();
|
||||||
g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get();
|
g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get();
|
||||||
|
|
||||||
auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format);
|
bool needsFallback = false;
|
||||||
|
SP<Aquamarine::IBuffer> fallback;
|
||||||
|
|
||||||
|
auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format);
|
||||||
if (!RBO) {
|
if (!RBO) {
|
||||||
Debug::log(TRACE, "Failed to create cursor RB with format {}, mod {}", buf->dmabuf().format, buf->dmabuf().modifier);
|
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");
|
static auto PDUMB = CConfigValue<Hyprlang::INT>("cursor:allow_dumb_copy");
|
||||||
if (!*PDUMB)
|
if (!*PDUMB)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto bufData = buf->beginDataPtr(0);
|
needsFallback = true;
|
||||||
auto bufPtr = std::get<0>(bufData);
|
|
||||||
|
|
||||||
// clear buffer
|
if (!state->monitor->resizeCursorFallbackSwapchain(maxSize))
|
||||||
memset(bufPtr, 0, std::get<2>(bufData));
|
return nullptr;
|
||||||
|
|
||||||
auto texBuffer = currentCursorImage.pBuffer ? currentCursorImage.pBuffer : currentCursorImage.surface->resource()->current.buffer;
|
fallback = state->monitor->cursorFallbackSwapchain->next(nullptr);
|
||||||
|
if (!fallback) {
|
||||||
if (texBuffer) {
|
Debug::log(TRACE, "Failed to acquire a buffer from the cursor fallback swapchain");
|
||||||
auto textAttrs = texBuffer->shm();
|
return nullptr;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
RBO = g_pHyprRenderer->getOrCreateRenderbuffer(fallback, state->monitor->cursorFallbackSwapchain->currentOptions().format);
|
||||||
buf->endDataPtr();
|
if (!RBO) {
|
||||||
|
Debug::log(TRACE, "Failed to create cursor RB with format {}, mod {}", fallback->dmabuf().format, fallback->dmabuf().modifier);
|
||||||
return buf;
|
return nullptr;
|
||||||
}
|
} else
|
||||||
|
Debug::log(TRACE, "Created cursor RB with format {}, mod {}", fallback->dmabuf().format, fallback->dmabuf().modifier);
|
||||||
|
} else
|
||||||
|
Debug::log(TRACE, "Created cursor RB with format {}, mod {}", buf->dmabuf().format, buf->dmabuf().modifier);
|
||||||
|
|
||||||
RBO->bind();
|
RBO->bind();
|
||||||
|
|
||||||
|
@ -438,11 +441,66 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
|
||||||
g_pHyprOpenGL->renderTexture(texture, &xbox, 1.F);
|
g_pHyprOpenGL->renderTexture(texture, &xbox, 1.F);
|
||||||
|
|
||||||
g_pHyprOpenGL->end();
|
g_pHyprOpenGL->end();
|
||||||
glFlush();
|
if (needsFallback)
|
||||||
|
glFinish();
|
||||||
|
else
|
||||||
|
glFlush();
|
||||||
g_pHyprOpenGL->m_RenderData.pMonitor = nullptr;
|
g_pHyprOpenGL->m_RenderData.pMonitor = nullptr;
|
||||||
|
|
||||||
g_pHyprRenderer->onRenderbufferDestroy(RBO.get());
|
g_pHyprRenderer->onRenderbufferDestroy(RBO.get());
|
||||||
|
|
||||||
|
if (needsFallback) {
|
||||||
|
// wlroots tries to blit here but it'll fail the same way we've got here in the first place
|
||||||
|
auto bufAttrs = buf->dmabuf();
|
||||||
|
Debug::log(TRACE, "mapping cursor buffer for writing");
|
||||||
|
auto bufData = buf->beginDataPtr(GBM_BO_TRANSFER_WRITE);
|
||||||
|
auto bufPtr = std::get<0>(bufData);
|
||||||
|
|
||||||
|
auto textAttrs = fallback->dmabuf();
|
||||||
|
Debug::log(TRACE, "mapping cursor fallback buffer for reading");
|
||||||
|
auto texData = fallback->beginDataPtr(GBM_BO_TRANSFER_WRITE);
|
||||||
|
auto texPtr = std::get<0>(texData);
|
||||||
|
Debug::log(TRACE, "cursor buffer {}x{} {} format={}({}) stride={}({})", bufAttrs.size.x, bufAttrs.size.y, (void*)bufPtr, bufAttrs.format, std::get<1>(bufData),
|
||||||
|
bufAttrs.strides[0], std::get<2>(bufData));
|
||||||
|
Debug::log(TRACE, "cursor fallback buffer {}x{} {} format={}({}) stride={}({})", textAttrs.size.x, textAttrs.size.y, (void*)texPtr, textAttrs.format, std::get<1>(texData),
|
||||||
|
textAttrs.strides[0], std::get<2>(texData));
|
||||||
|
|
||||||
|
const auto dma = fallback->dmabuf();
|
||||||
|
|
||||||
|
auto image = g_pHyprOpenGL->createEGLImage(dma);
|
||||||
|
if (image == EGL_NO_IMAGE_KHR) {
|
||||||
|
Debug::log(TRACE, "texture fallback failed");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint id;
|
||||||
|
|
||||||
|
GLCALL(glGenTextures(1, &id));
|
||||||
|
|
||||||
|
GLCALL(glBindTexture(GL_TEXTURE_2D, id));
|
||||||
|
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||||
|
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||||
|
GLCALL(g_pHyprOpenGL->m_sProc.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image));
|
||||||
|
GLCALL(glBindTexture(GL_TEXTURE_2D, 0));
|
||||||
|
|
||||||
|
Debug::log(TRACE, "texture fallback got {}", image);
|
||||||
|
if (!texPtr)
|
||||||
|
texPtr = (uint8_t*)image;
|
||||||
|
|
||||||
|
if (!bufPtr || !texPtr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// copy rendered cursor
|
||||||
|
for (int i = 0; i < textAttrs.size.y; i++) {
|
||||||
|
Debug::log(TRACE, "copying {}/{} dst start={}, src start={}, length={}", i + 1, textAttrs.size.y, (void*)(bufPtr + i * bufAttrs.strides[0]),
|
||||||
|
(void*)(texPtr + i * textAttrs.strides[0]), textAttrs.strides[0]);
|
||||||
|
memcpy(bufPtr + i * bufAttrs.strides[0], texPtr + i * textAttrs.strides[0], textAttrs.strides[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf->endDataPtr();
|
||||||
|
fallback->endDataPtr();
|
||||||
|
}
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue