From d93791e25d83df1624c524960cba29d832615a68 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 20 Jun 2024 18:05:35 +0200 Subject: [PATCH 001/113] Core: Move to aquamarine --- CMakeLists.txt | 1 + Makefile | 2 +- src/Compositor.cpp | 312 ++++++++++++-------- src/Compositor.hpp | 29 +- src/config/ConfigManager.cpp | 19 +- src/debug/HyprCtl.cpp | 156 ++++------ src/devices/IKeyboard.cpp | 207 +++++++++++-- src/devices/IKeyboard.hpp | 57 +++- src/devices/IPointer.hpp | 10 +- src/devices/ITouch.hpp | 10 +- src/devices/Keyboard.cpp | 63 ++-- src/devices/Keyboard.hpp | 22 +- src/devices/Mouse.cpp | 182 +++++------- src/devices/Mouse.hpp | 41 +-- src/devices/TouchDevice.cpp | 78 ++--- src/devices/TouchDevice.hpp | 26 +- src/devices/VirtualKeyboard.cpp | 67 ++--- src/devices/VirtualKeyboard.hpp | 21 +- src/devices/VirtualPointer.cpp | 176 ++--------- src/devices/VirtualPointer.hpp | 37 +-- src/events/Devices.cpp | 6 +- src/events/Monitors.cpp | 138 ++------- src/helpers/Format.hpp | 2 +- src/helpers/Monitor.cpp | 158 ++++------ src/helpers/Monitor.hpp | 120 ++++---- src/macros.hpp | 5 + src/managers/CursorManager.cpp | 87 +++--- src/managers/CursorManager.hpp | 47 +-- src/managers/KeybindManager.cpp | 13 +- src/managers/PointerManager.cpp | 242 +++++---------- src/managers/PointerManager.hpp | 51 ++-- src/managers/SeatManager.cpp | 10 +- src/managers/eventLoop/EventLoopManager.cpp | 11 + src/managers/eventLoop/EventLoopManager.hpp | 7 +- src/managers/input/InputManager.cpp | 169 +++-------- src/managers/input/InputManager.hpp | 10 +- src/protocols/GammaControl.cpp | 14 +- src/protocols/InputMethodV2.cpp | 21 +- src/protocols/InputMethodV2.hpp | 7 +- src/protocols/LinuxDMABUF.cpp | 6 +- src/protocols/LinuxDMABUF.hpp | 14 +- src/protocols/MesaDRM.cpp | 6 +- src/protocols/MesaDRM.hpp | 2 +- src/protocols/OutputManagement.cpp | 56 ++-- src/protocols/OutputManagement.hpp | 15 +- src/protocols/OutputPower.cpp | 2 +- src/protocols/PresentationTime.cpp | 13 +- src/protocols/Screencopy.cpp | 47 +-- src/protocols/Screencopy.hpp | 8 +- src/protocols/ToplevelExport.cpp | 17 +- src/protocols/ToplevelExport.hpp | 2 +- src/protocols/VirtualKeyboard.cpp | 60 ++-- src/protocols/VirtualKeyboard.hpp | 13 +- src/protocols/VirtualPointer.cpp | 80 ++--- src/protocols/VirtualPointer.hpp | 31 +- src/protocols/XDGOutput.cpp | 6 +- src/protocols/core/Compositor.hpp | 2 +- src/protocols/core/Output.cpp | 10 +- src/protocols/core/Output.hpp | 3 + src/protocols/core/Seat.cpp | 4 +- src/protocols/core/Shm.cpp | 21 +- src/protocols/core/Shm.hpp | 8 +- src/protocols/types/Buffer.cpp | 40 +-- src/protocols/types/Buffer.hpp | 81 +---- src/protocols/types/DMABuffer.cpp | 12 +- src/protocols/types/DMABuffer.hpp | 12 +- src/protocols/types/WLBuffer.hpp | 6 +- src/render/OpenGL.cpp | 228 ++++++++++++-- src/render/OpenGL.hpp | 20 +- src/render/Renderbuffer.cpp | 49 +-- src/render/Renderbuffer.hpp | 24 +- src/render/Renderer.cpp | 293 +++++++++--------- src/render/Renderer.hpp | 14 +- src/render/Texture.cpp | 77 +++-- src/render/Texture.hpp | 11 +- 75 files changed, 1882 insertions(+), 2045 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 07fa8cf67cc..f7adcb5df21 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,6 +109,7 @@ endif() find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) pkg_check_modules(deps REQUIRED IMPORTED_TARGET + aquamarine xkbcommon uuid wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo pixman-1 diff --git a/Makefile b/Makefile index 493a67848d7..aff2a25a236 100644 --- a/Makefile +++ b/Makefile @@ -88,7 +88,7 @@ asan: @pidof Hyprland > /dev/null && exit 1 || echo "" rm -rf ./wayland - git reset --hard + #git reset --hard @echo -en "If you want to apply a patch, input its path (leave empty for none):\n" @read patchvar diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 7ffccf3651e..07843d92bc1 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -25,13 +25,16 @@ #include "xwayland/XWayland.hpp" #include -using namespace Hyprutils::String; +#include #include #include #include #include +using namespace Hyprutils::String; +using namespace Aquamarine; + int handleCritSignal(int signo, void* data) { Debug::log(LOG, "Hyprland received signal {}", signo); @@ -72,6 +75,23 @@ void handleUserSignal(int sig) { } } +static LogLevel aqLevelToHl(Aquamarine::eBackendLogLevel level) { + switch (level) { + case Aquamarine::eBackendLogLevel::AQ_LOG_TRACE: return TRACE; + case Aquamarine::eBackendLogLevel::AQ_LOG_DEBUG: return LOG; + case Aquamarine::eBackendLogLevel::AQ_LOG_ERROR: return ERR; + case Aquamarine::eBackendLogLevel::AQ_LOG_WARNING: return WARN; + case Aquamarine::eBackendLogLevel::AQ_LOG_CRITICAL: return CRIT; + default: break; + } + + return NONE; +} + +void aqLog(Aquamarine::eBackendLogLevel level, std::string msg) { + Debug::log(aqLevelToHl(level), "[AQ] {}", msg); +} + void CCompositor::bumpNofile() { if (!getrlimit(RLIMIT_NOFILE, &m_sOriginalNofile)) Debug::log(LOG, "Old rlimit: soft -> {}, hard -> {}", m_sOriginalNofile.rlim_cur, m_sOriginalNofile.rlim_max); @@ -180,6 +200,9 @@ void CCompositor::setRandomSplash() { m_szCurrentSplash = SPLASHES[distribution(engine)]; } +static std::vector> pendingOutputs; + +// void CCompositor::initServer() { m_sWLDisplay = wl_display_create(); @@ -200,102 +223,91 @@ void CCompositor::initServer() { if (envEnabled("HYPRLAND_TRACE")) Debug::trace = true; - wlr_log_init(WLR_INFO, NULL); + Aquamarine::SBackendOptions options; + options.logFunction = aqLog; - if (envEnabled("HYPRLAND_LOG_WLR")) - wlr_log_init(WLR_DEBUG, Debug::wlrLog); - else - wlr_log_init(WLR_ERROR, Debug::wlrLog); - - m_sWLRBackend = wlr_backend_autocreate(m_sWLEventLoop, &m_sWLRSession); - - if (!m_sWLRBackend) { - Debug::log(CRIT, "m_sWLRBackend was NULL! This usually means wlroots could not find a GPU or enountered some issues."); - throwError("wlr_backend_autocreate() failed!"); - } - - bool isHeadlessOnly = true; - wlr_multi_for_each_backend( - m_sWLRBackend, - [](wlr_backend* backend, void* isHeadlessOnly) { - if (!wlr_backend_is_headless(backend) && !wlr_backend_is_libinput(backend)) - *(bool*)isHeadlessOnly = false; - }, - &isHeadlessOnly); + std::vector implementations; + Aquamarine::SBackendImplementationOptions waylandOptions; + waylandOptions.backendType = Aquamarine::eBackendType::AQ_BACKEND_WAYLAND; + waylandOptions.backendRequestMode = Aquamarine::eBackendRequestMode::AQ_BACKEND_REQUEST_IF_AVAILABLE; + implementations.emplace_back(waylandOptions); - if (isHeadlessOnly) { - m_sWLRRenderer = wlr_renderer_autocreate(m_sWLRBackend); // TODO: remove this, it's barely needed now. - } else { - m_iDRMFD = wlr_backend_get_drm_fd(m_sWLRBackend); - if (m_iDRMFD < 0) { - Debug::log(CRIT, "Couldn't query the DRM FD!"); - throwError("wlr_backend_get_drm_fd() failed!"); - } + m_pAqBackend = CBackend::create(implementations, options); - m_sWLRRenderer = wlr_gles2_renderer_create_with_drm_fd(m_iDRMFD); + if (!m_pAqBackend) { + Debug::log(CRIT, + "m_pAqBackend was null! This usually means aquamarine could not find a GPU or enountered some issues. Make sure you're running either on a tty or on a Wayland " + "session, NOT an X11 one."); + throwError("CBackend::create() failed!"); } - if (!m_sWLRRenderer) { - Debug::log(CRIT, "m_sWLRRenderer was NULL! This usually means wlroots could not find a GPU or enountered some issues."); - throwError("wlr_gles2_renderer_create_with_drm_fd() failed!"); - } + // TODO: headless only - m_sWLRAllocator = wlr_allocator_autocreate(m_sWLRBackend, m_sWLRRenderer); + initAllSignals(); - if (!m_sWLRAllocator) { - Debug::log(CRIT, "m_sWLRAllocator was NULL!"); - throwError("wlr_allocator_autocreate() failed!"); + if (!m_pAqBackend->start()) { + Debug::log(CRIT, + "m_pAqBackend couldn't start! This usually means aquamarine could not find a GPU or enountered some issues. Make sure you're running either on a tty or on a " + "Wayland session, NOT an X11 one."); + throwError("CBackend::create() failed!"); } - m_sWLREGL = wlr_gles2_renderer_get_egl(m_sWLRRenderer); + m_bInitialized = true; - if (!m_sWLREGL) { - Debug::log(CRIT, "m_sWLREGL was NULL!"); - throwError("wlr_gles2_renderer_get_egl() failed!"); - } + m_iDRMFD = m_pAqBackend->drmFD(); initManagers(STAGE_BASICINIT); - m_sWRLDRMLeaseMgr = wlr_drm_lease_v1_manager_create(m_sWLDisplay, m_sWLRBackend); - if (!m_sWRLDRMLeaseMgr) { - Debug::log(INFO, "Failed to create wlr_drm_lease_v1_manager"); - Debug::log(INFO, "VR will not be available"); - } - - m_sWLRHeadlessBackend = wlr_headless_backend_create(m_sWLEventLoop); + initManagers(STAGE_LATE); - if (!m_sWLRHeadlessBackend) { - Debug::log(CRIT, "Couldn't create the headless backend"); - throwError("wlr_headless_backend_create() failed!"); + for (auto& o : pendingOutputs) { + onNewMonitor(o); } - - wlr_multi_backend_add(m_sWLRBackend, m_sWLRHeadlessBackend); - - initManagers(STAGE_LATE); + pendingOutputs.clear(); } void CCompositor::initAllSignals() { - addWLSignal(&m_sWLRBackend->events.new_output, &Events::listen_newOutput, m_sWLRBackend, "Backend"); - addWLSignal(&m_sWLRBackend->events.new_input, &Events::listen_newInput, m_sWLRBackend, "Backend"); - addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer"); - - if (m_sWRLDRMLeaseMgr) - addWLSignal(&m_sWRLDRMLeaseMgr->events.request, &Events::listen_leaseRequest, &m_sWRLDRMLeaseMgr, "DRM"); - - if (m_sWLRSession) - addWLSignal(&m_sWLRSession->events.active, &Events::listen_sessionActive, m_sWLRSession, "Session"); + m_pAqBackend->events.newOutput.registerStaticListener( + [this](void* p, std::any data) { + auto output = std::any_cast>(data); + Debug::log(LOG, "New aquamarine output with name {}", output->name); + if (m_bInitialized) + onNewMonitor(output); + else + pendingOutputs.emplace_back(output); + }, + nullptr); + + m_pAqBackend->events.newPointer.registerStaticListener( + [](void* data, std::any d) { + auto dev = std::any_cast>(d); + Debug::log(LOG, "New aquamarine pointer with name {}", dev->getName()); + g_pInputManager->newMouse(dev); + g_pInputManager->updateCapabilities(); + }, + nullptr); + + m_pAqBackend->events.newKeyboard.registerStaticListener( + [](void* data, std::any d) { + auto dev = std::any_cast>(d); + Debug::log(LOG, "New aquamarine keyboard with name {}", dev->getName()); + g_pInputManager->newKeyboard(dev); + g_pInputManager->updateCapabilities(); + }, + nullptr); + + m_pAqBackend->events.newTouch.registerStaticListener( + [](void* data, std::any d) { + auto dev = std::any_cast>(d); + Debug::log(LOG, "New aquamarine touch with name {}", dev->getName()); + g_pInputManager->newTouchDevice(dev); + g_pInputManager->updateCapabilities(); + }, + nullptr); } void CCompositor::removeAllSignals() { - removeWLSignal(&Events::listen_newOutput); - removeWLSignal(&Events::listen_newInput); - removeWLSignal(&Events::listen_RendererDestroy); - - if (m_sWRLDRMLeaseMgr) - removeWLSignal(&Events::listen_leaseRequest); - - if (m_sWLRSession) - removeWLSignal(&Events::listen_sessionActive); + ; } void CCompositor::cleanEnvironment() { @@ -309,7 +321,7 @@ void CCompositor::cleanEnvironment() { unsetenv("XDG_BACKEND"); unsetenv("XDG_CURRENT_DESKTOP"); - if (m_sWLRSession) { + if (false /* TODO: */) { const auto CMD = #ifdef USES_SYSTEMD "systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " @@ -352,7 +364,7 @@ void CCompositor::cleanup() { for (auto& m : m_vMonitors) { g_pHyprOpenGL->destroyMonitorResources(m.get()); - wlr_output_state_set_enabled(m->state.wlr(), false); + m->output->state->setEnabled(false); m->state.commit(); } @@ -389,14 +401,8 @@ void CCompositor::cleanup() { g_pHyprCtl.reset(); g_pEventLoopManager.reset(); - if (m_sWLRRenderer) - wlr_renderer_destroy(m_sWLRRenderer); - - if (m_sWLRAllocator) - wlr_allocator_destroy(m_sWLRAllocator); - - if (m_sWLRBackend) - wlr_backend_destroy(m_sWLRBackend); + if (m_pAqBackend) + m_pAqBackend.reset(); if (m_critSigSource) wl_event_source_remove(m_critSigSource); @@ -442,6 +448,9 @@ void CCompositor::initManagers(eManagersInitStage stage) { Debug::log(LOG, "Creating the PointerManager!"); g_pPointerManager = std::make_unique(); + + Debug::log(LOG, "Creating the EventManager!"); + g_pEventManager = std::make_unique(); } break; case STAGE_BASICINIT: { Debug::log(LOG, "Creating the CHyprOpenGLImpl!"); @@ -472,9 +481,6 @@ void CCompositor::initManagers(eManagersInitStage stage) { Debug::log(LOG, "Creating the SessionLockManager!"); g_pSessionLockManager = std::make_unique(); - Debug::log(LOG, "Creating the EventManager!"); - g_pEventManager = std::make_unique(); - Debug::log(LOG, "Creating the HyprDebugOverlay!"); g_pDebugOverlay = std::make_unique(); @@ -516,22 +522,23 @@ void CCompositor::removeLockFile() { } void CCompositor::prepareFallbackOutput() { - // create a backup monitor - wlr_backend* headless = nullptr; - wlr_multi_for_each_backend( - m_sWLRBackend, - [](wlr_backend* b, void* data) { - if (wlr_backend_is_headless(b)) - *((wlr_backend**)data) = b; - }, - &headless); + // TODO: + // // create a backup monitor + // wlr_backend* headless = nullptr; + // wlr_multi_for_each_backend( + // m_sWLRBackend, + // [](wlr_backend* b, void* data) { + // if (wlr_backend_is_headless(b)) + // *((wlr_backend**)data) = b; + // }, + // &headless); - if (!headless) { - Debug::log(WARN, "Unsafe state will be ineffective, no fallback output"); - return; - } + // if (!headless) { + // Debug::log(WARN, "Unsafe state will be ineffective, no fallback output"); + // return; + // } - wlr_headless_add_output(headless, 1920, 1080); + // wlr_headless_add_output(headless, 1920, 1080); } void CCompositor::startCompositor(std::string socketName, int socketFd) { @@ -568,7 +575,6 @@ void CCompositor::startCompositor(std::string socketName, int socketFd) { if (m_szWLDisplaySocket.empty()) { Debug::log(CRIT, "m_szWLDisplaySocket NULL!"); - wlr_backend_destroy(m_sWLRBackend); throwError("m_szWLDisplaySocket was null! (wl_display_add_socket and wl_display_add_socket_auto failed)"); } @@ -576,7 +582,8 @@ void CCompositor::startCompositor(std::string socketName, int socketFd) { signal(SIGPIPE, SIG_IGN); - if (m_sWLRSession /* Session-less Hyprland usually means a nest, don't update the env in that case */) { + // TODO: + if (false /* Session-less Hyprland usually means a nest, don't update the env in that case */) { const auto CMD = #ifdef USES_SYSTEMD "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " @@ -588,13 +595,6 @@ void CCompositor::startCompositor(std::string socketName, int socketFd) { Debug::log(LOG, "Running on WAYLAND_DISPLAY: {}", m_szWLDisplaySocket); - if (!wlr_backend_start(m_sWLRBackend)) { - Debug::log(CRIT, "Backend did not start!"); - wlr_backend_destroy(m_sWLRBackend); - wl_display_destroy(m_sWLDisplay); - throwError("The backend could not start!"); - } - prepareFallbackOutput(); g_pHyprRenderer->setCursorFromName("left_ptr"); @@ -882,7 +882,7 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindo return vec - pWindow->m_vRealPosition.goal() - std::get<1>(iterData) + Vector2D{geom.x, geom.y}; } -CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) { +CMonitor* CCompositor::getMonitorFromOutput(SP out) { for (auto& m : m_vMonitors) { if (m->output == out) { return m.get(); @@ -892,7 +892,7 @@ CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) { return nullptr; } -CMonitor* CCompositor::getRealMonitorFromOutput(wlr_output* out) { +CMonitor* CCompositor::getRealMonitorFromOutput(SP out) { for (auto& m : m_vRealMonitors) { if (m->output == out) { return m.get(); @@ -2283,8 +2283,9 @@ void CCompositor::updateWorkspaceWindowData(const int& id) { } void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor) { - if ((m_sWLRSession && !m_sWLRSession->active) || !m_bSessionActive) - return; + // FIXME: + // if ((m_sWLRSession && !m_sWLRSession->active) || !m_bSessionActive) + // return; if (!pMonitor->m_bEnabled) return; @@ -2292,7 +2293,7 @@ void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor) { if (pMonitor->renderingActive) pMonitor->pendingFrame = true; - wlr_output_schedule_frame(pMonitor->output); + pMonitor->output->scheduleFrame(); } PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp) { @@ -2808,3 +2809,80 @@ PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) { return {}; } + +static void checkDefaultCursorWarp(SP PNEWMONITOR, std::string monitorName) { + static auto PCURSORMONITOR = CConfigValue("cursor:default_monitor"); + static auto firstMonitorAdded = std::chrono::system_clock::now(); + static bool cursorDefaultDone = false; + static bool firstLaunch = true; + + const auto POS = PNEWMONITOR->middle(); + + // by default, cursor should be set to first monitor detected + // this is needed as a default if the monitor given in config above doesn't exist + if (firstLaunch) { + firstLaunch = false; + g_pCompositor->warpCursorTo(POS, true); + g_pInputManager->refocus(); + } + + if (cursorDefaultDone || *PCURSORMONITOR == STRVAL_EMPTY) + return; + + // after 10s, don't set cursor to default monitor + auto timePassedSec = std::chrono::duration_cast(std::chrono::system_clock::now() - firstMonitorAdded); + if (timePassedSec.count() > 10) { + cursorDefaultDone = true; + return; + } + + if (*PCURSORMONITOR == monitorName) { + cursorDefaultDone = true; + g_pCompositor->warpCursorTo(POS, true); + g_pInputManager->refocus(); + } +} + +void CCompositor::onNewMonitor(SP output) { + // add it to real + auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared()); + if (std::string("HEADLESS-1") == output->name) + g_pCompositor->m_pUnsafeOutput = PNEWMONITOR.get(); + + PNEWMONITOR->szName = output->name; + PNEWMONITOR->output = output; + PNEWMONITOR->self = PNEWMONITOR; + const bool FALLBACK = g_pCompositor->m_pUnsafeOutput ? output == g_pCompositor->m_pUnsafeOutput->output : false; + PNEWMONITOR->ID = FALLBACK ? -1 : g_pCompositor->getNextAvailableMonitorID(output->name); + PNEWMONITOR->isUnsafeFallback = FALLBACK; + + EMIT_HOOK_EVENT("newMonitor", PNEWMONITOR); + + if (!FALLBACK) + PNEWMONITOR->onConnect(false); + + if (!PNEWMONITOR->m_bEnabled || FALLBACK) + return; + + // ready to process if we have a real monitor + + if ((!g_pHyprRenderer->m_pMostHzMonitor || PNEWMONITOR->refreshRate > g_pHyprRenderer->m_pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled) + g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR.get(); + + g_pCompositor->m_bReadyToProcess = true; + + g_pConfigManager->m_bWantsMonitorReload = true; + g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get()); + + checkDefaultCursorWarp(PNEWMONITOR, output->name); + + for (auto& w : g_pCompositor->m_vWindows) { + if (w->m_iMonitorID == PNEWMONITOR->ID) { + w->m_iLastSurfaceMonitorID = -1; + w->updateSurfaceScaleTransformDetails(); + } + } + + g_pHyprRenderer->damageMonitor(PNEWMONITOR.get()); + Events::listener_monitorFrame(PNEWMONITOR.get(), nullptr); +} diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 4aec323f35d..3f85229cf03 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -30,6 +30,9 @@ #include "plugins/PluginSystem.hpp" #include "helpers/Watchdog.hpp" +#include +#include + class CWLSurfaceResource; enum eManagersInitStage { @@ -43,22 +46,11 @@ class CCompositor { CCompositor(); ~CCompositor(); - // ------------------ WLR BASICS ------------------ // - wl_display* m_sWLDisplay; - wl_event_loop* m_sWLEventLoop; - wlr_backend* m_sWLRBackend; - wlr_session* m_sWLRSession; - wlr_renderer* m_sWLRRenderer; - wlr_allocator* m_sWLRAllocator; - wlr_compositor* m_sWLRCompositor; - wlr_subcompositor* m_sWLRSubCompositor; - wlr_drm* m_sWRLDRM; - wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr; - wlr_egl* m_sWLREGL; - int m_iDRMFD; - wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf; - wlr_backend* m_sWLRHeadlessBackend; - // ------------------------------------------------- // + wl_display* m_sWLDisplay; + wl_event_loop* m_sWLEventLoop; + int m_iDRMFD = -1; + bool m_bInitialized = false; + SP m_pAqBackend; std::string m_szHyprTempDataRoot = ""; @@ -116,8 +108,8 @@ class CCompositor { SP vectorToLayerPopupSurface(const Vector2D&, CMonitor* monitor, Vector2D*, PHLLS*); SP vectorWindowToSurface(const Vector2D&, PHLWINDOW, Vector2D& sl); Vector2D vectorToSurfaceLocal(const Vector2D&, PHLWINDOW, SP); - CMonitor* getMonitorFromOutput(wlr_output*); - CMonitor* getRealMonitorFromOutput(wlr_output*); + CMonitor* getMonitorFromOutput(SP); + CMonitor* getRealMonitorFromOutput(SP); PHLWINDOW getWindowFromSurface(SP); PHLWINDOW getWindowFromHandle(uint32_t); bool isWorkspaceVisible(PHLWORKSPACE); @@ -182,6 +174,7 @@ class CCompositor { void setPreferredTransformForSurface(SP pSurface, wl_output_transform transform); void updateSuspendedStates(); PHLWINDOW windowForCPointer(CWindow*); + void onNewMonitor(SP output); std::string explicitConfigPath; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 71349068a18..af1608f9b70 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1285,7 +1285,7 @@ void CConfigManager::dispatchExecOnce() { return; // update dbus env - if (g_pCompositor->m_sWLRSession) + if (g_pCompositor->m_pAqBackend->hasSession()) handleRawExec("", #ifdef USES_SYSTEMD "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " @@ -1410,7 +1410,8 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) { if (USEVRR == 0) { if (m->vrrActive) { - wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 0); + + m->output->state->setAdaptiveSync(false); if (!m->state.commit()) Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> false", m->output->name); @@ -1419,11 +1420,11 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) { return; } else if (USEVRR == 1) { if (!m->vrrActive) { - wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 1); + m->output->state->setAdaptiveSync(true); if (!m->state.test()) { Debug::log(LOG, "Pending output {} does not accept VRR.", m->output->name); - wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 0); + m->output->state->setAdaptiveSync(false); } if (!m->state.commit()) @@ -1442,19 +1443,19 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) { const auto WORKSPACEFULL = PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL; - if (WORKSPACEFULL && m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED) { - wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 1); + if (WORKSPACEFULL) { + m->output->state->setAdaptiveSync(true); if (!m->state.test()) { Debug::log(LOG, "Pending output {} does not accept VRR.", m->output->name); - wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 0); + m->output->state->setAdaptiveSync(false); } if (!m->state.commit()) Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> true", m->output->name); - } else if (!WORKSPACEFULL && m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED) { - wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 0); + } else if (!WORKSPACEFULL) { + m->output->state->setAdaptiveSync(false); if (!m->state.commit()) Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> false", m->output->name); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 08d2bb571a8..459860376bd 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -20,6 +20,7 @@ #include using namespace Hyprutils::String; +#include #include "../config/ConfigDataValues.hpp" #include "../config/ConfigValue.hpp" @@ -53,18 +54,11 @@ static std::string formatToString(uint32_t drmFormat) { static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFormat format) { std::string result; - if (!wl_list_empty(&pMonitor->output->modes)) { - wlr_output_mode* mode; - - wl_list_for_each(mode, &pMonitor->output->modes, link) { - - if (format == FORMAT_NORMAL) - result += std::format("{}x{}@{:.2f}Hz ", mode->width, mode->height, mode->refresh / 1000.0); - else - result += std::format("\"{}x{}@{:.2f}Hz\",", mode->width, mode->height, mode->refresh / 1000.0); - } - - result.pop_back(); + for (auto& m : pMonitor->output->modes) { + if (format == FORMAT_NORMAL) + result += std::format("{}x{}@{:.2f}Hz ", m->pixelSize.x, m->pixelSize.y, m->refreshRate / 1000.0); + else + result += std::format("\"{}x{}@{:.2f}Hz\",", m->pixelSize.x, m->pixelSize.y, m->refreshRate / 1000.0); } return result; @@ -75,8 +69,11 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer if (!m->output || m->ID == -1ull) return ""; - result += std::format( - R"#({{ + if (format == eHyprCtlOutputFormat::FORMAT_JSON) { + result += "["; + + result += std::format( + R"#({{ "id": {}, "name": "{}", "description": "{}", @@ -107,54 +104,28 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer "currentFormat": "{}", "availableModes": [{}] }},)#", - m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->szShortDescription), escapeJSONStrings(m->output->make ? m->output->make : ""), - escapeJSONStrings(m->output->model ? m->output->model : ""), escapeJSONStrings(m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, - m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : escapeJSONStrings(m->activeWorkspace->m_szName)), - m->activeSpecialWorkspaceID(), escapeJSONStrings(m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, - (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, - (m == g_pCompositor->m_pLastMonitor ? "true" : "false"), (m->dpmsStatus ? "true" : "false"), - (m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED ? "true" : "false"), (m->tearingState.activelyTearing ? "true" : "false"), - (m->m_bEnabled ? "false" : "true"), formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); - return result; -} -std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { - CVarList vars(request, 0, ' '); - auto allMonitors = false; - - if (vars.size() > 2) - return "too many args"; - - if (vars.size() == 2 && vars[1] == "all") - allMonitors = true; - - std::string result = ""; - if (format == eHyprCtlOutputFormat::FORMAT_JSON) { - result += "["; - - for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) { - result += CHyprCtl::getMonitorData(m, format); - } + m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->szShortDescription), escapeJSONStrings(m->output->make), escapeJSONStrings(m->output->model), + escapeJSONStrings(m->output->serial), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, + m->activeWorkspaceID(), (!m->activeWorkspace ? "" : escapeJSONStrings(m->activeWorkspace->m_szName)), m->activeSpecialWorkspaceID(), + escapeJSONStrings(m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, + (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "true" : "false"), + (m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (m->tearingState.activelyTearing ? "true" : "false"), + (m->m_bEnabled ? "false" : "true"), formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); trimTrailingComma(result); result += "]"; } else { - for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) { - if (!m->output || m->ID == -1ull) - continue; - - result += std::format( - "Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" - "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" - "dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n", - m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription, - (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), m->activeWorkspaceID(), - (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), - (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, - (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, (int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED), - m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); - } + result += std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" + "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" + "dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n", + m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription, + m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), + m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, + (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, + (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, m->output->state->state().adaptiveSync, m->tearingState.activelyTearing, + !m->m_bEnabled, formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); } return result; @@ -552,8 +523,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { "defaultSpeed": {:.5f} }},)#", (uintptr_t)m.get(), escapeJSONStrings(m->hlName), - wlr_input_device_is_libinput(&m->wlr()->base) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(&m->wlr()->base)) : - 0.f); + m->aq() && m->aq()->getLibinputHandle() ? libinput_device_config_accel_get_default_speed(m->aq()->getLibinputHandle()) : 0.f); } trimTrailingComma(result); @@ -654,9 +624,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { for (auto& m : g_pInputManager->m_vPointers) { result += std::format("\tMouse at {:x}:\n\t\t{}\n\t\t\tdefault speed: {:.5f}\n", (uintptr_t)m.get(), m->hlName, - (wlr_input_device_is_libinput(&m->wlr()->base) ? - libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(&m->wlr()->base)) : - 0.f)); + (m->aq() && m->aq()->getLibinputHandle() ? libinput_device_config_accel_get_default_speed(m->aq()->getLibinputHandle()) : 0.f)); } result += "\n\nKeyboards:\n"; @@ -1125,24 +1093,22 @@ std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string requ if (PKEYBOARD == g_pInputManager->m_vKeyboards.end()) return "device not found"; - const auto PWLRKEYBOARD = (*PKEYBOARD)->wlr(); - const auto LAYOUTS = xkb_keymap_num_layouts(PWLRKEYBOARD->keymap); + const auto KEEB = *PKEYBOARD; + + const auto LAYOUTS = xkb_keymap_num_layouts(KEEB->xkbKeymap); xkb_layout_index_t activeLayout = 0; while (activeLayout < LAYOUTS) { - if (xkb_state_layout_index_is_active(PWLRKEYBOARD->xkb_state, activeLayout, XKB_STATE_LAYOUT_EFFECTIVE) == 1) + if (xkb_state_layout_index_is_active(KEEB->xkbTranslationState, activeLayout, XKB_STATE_LAYOUT_EFFECTIVE) == 1) break; activeLayout++; } - if (CMD == "next") { - wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked, - activeLayout > LAYOUTS ? 0 : activeLayout + 1); - } else if (CMD == "prev") { - wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked, - activeLayout == 0 ? LAYOUTS - 1 : activeLayout - 1); - } else { - + if (CMD == "next") + KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, activeLayout > LAYOUTS ? 0 : activeLayout + 1); + else if (CMD == "prev") + KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, activeLayout == 0 ? LAYOUTS - 1 : activeLayout - 1); + else { int requestedLayout = 0; try { requestedLayout = std::stoi(CMD); @@ -1152,7 +1118,7 @@ std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string requ return "layout idx out of range of " + std::to_string(LAYOUTS); } - wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked, requestedLayout); + KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, requestedLayout); } return "ok"; @@ -1368,26 +1334,26 @@ std::string decorationRequest(eHyprCtlOutputFormat format, std::string request) return result; } -static bool addOutput(wlr_backend* backend, const std::string& type, const std::string& name) { - wlr_output* output = nullptr; +// static bool addOutput(wlr_backend* backend, const std::string& type, const std::string& name) { +// wlr_output* output = nullptr; - if (type.empty() || type == "auto") { - if (wlr_backend_is_wl(backend)) - output = wlr_wl_output_create(backend); - else if (wlr_backend_is_headless(backend)) - output = wlr_headless_add_output(backend, 1920, 1080); - } else { - if (wlr_backend_is_wl(backend) && type == "wayland") - output = wlr_wl_output_create(backend); - else if (wlr_backend_is_headless(backend) && type == "headless") - output = wlr_headless_add_output(backend, 1920, 1080); - } +// if (type.empty() || type == "auto") { +// if (wlr_backend_is_wl(backend)) +// output = wlr_wl_output_create(backend); +// else if (wlr_backend_is_headless(backend)) +// output = wlr_headless_add_output(backend, 1920, 1080); +// } else { +// if (wlr_backend_is_wl(backend) && type == "wayland") +// output = wlr_wl_output_create(backend); +// else if (wlr_backend_is_headless(backend) && type == "headless") +// output = wlr_headless_add_output(backend, 1920, 1080); +// } - if (output && !name.empty()) - g_pCompositor->getMonitorFromOutput(output)->szName = name; +// if (output && !name.empty()) +// g_pCompositor->getMonitorFromOutput(output)->szName = name; - return output != nullptr; -} +// return output != nullptr; +// } struct outputData { std::string type; @@ -1401,8 +1367,8 @@ void createOutputIter(wlr_backend* backend, void* data) { if (DATA->added) return; - if (addOutput(backend, DATA->type, DATA->name)) - DATA->added = true; + // if (addOutput(backend, DATA->type, DATA->name)) + // DATA->added = true; } std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) { @@ -1413,13 +1379,15 @@ std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) { const auto MODE = vars[1]; + // FIXME: + if (MODE == "create" || MODE == "add") { if (g_pCompositor->getMonitorFromName(vars[3])) return "A real monitor already uses that name."; outputData result{vars[2], vars[3], false}; - wlr_multi_for_each_backend(g_pCompositor->m_sWLRBackend, createOutputIter, &result); + // wlr_multi_for_each_backend(g_pCompositor->m_sWLRBackend, createOutputIter, &result); if (!result.added) return "no backend replied to the request"; @@ -1433,7 +1401,7 @@ std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) { if (!PMONITOR->createdByUser) return "cannot remove a real display. Use the monitor keyword."; - wlr_output_destroy(PMONITOR->output); + //wlr_output_destroy(PMONITOR->output); } return "ok"; diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index cb294d1a2fc..5ecba556e55 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -2,7 +2,16 @@ #include "../defines.hpp" #include "../helpers/varlist/VarList.hpp" #include "../managers/input/InputManager.hpp" +#include +#include +constexpr static std::array MODNAMES = { + XKB_MOD_NAME_SHIFT, XKB_MOD_NAME_CAPS, XKB_MOD_NAME_CTRL, XKB_MOD_NAME_ALT, XKB_MOD_NAME_NUM, "Mod3", XKB_MOD_NAME_LOGO, "Mod5", +}; + +constexpr static std::array LEDNAMES = {XKB_LED_NAME_NUM, XKB_LED_NAME_CAPS, XKB_LED_NAME_SCROLL}; + +// uint32_t IKeyboard::getCapabilities() { return HID_INPUT_CAPABILITY_KEYBOARD; } @@ -14,11 +23,130 @@ eHIDType IKeyboard::getType() { IKeyboard::~IKeyboard() { events.destroy.emit(); - if (!xkbTranslationState) - return; + clearManuallyAllocd(); +} + +void IKeyboard::clearManuallyAllocd() { + if (xkbTranslationState) + xkb_state_unref(xkbTranslationState); + + if (xkbInternalTranslationState) + xkb_state_unref(xkbInternalTranslationState); - xkb_state_unref(xkbTranslationState); + if (xkbKeymap) + xkb_keymap_unref(xkbKeymap); + + if (xkbKeymapFD >= 0) + close(xkbKeymapFD); + + xkbKeymap = nullptr; xkbTranslationState = nullptr; + xkbKeymapFD = -1; +} + +void IKeyboard::setKeymap(const SStringRuleNames& rules) { + currentRules = rules; + xkb_rule_names XKBRULES = { + .rules = rules.rules.c_str(), + .model = rules.model.c_str(), + .layout = rules.layout.c_str(), + .variant = rules.variant.c_str(), + .options = rules.options.c_str(), + }; + + const auto CONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + + if (!CONTEXT) { + Debug::log(ERR, "setKeymap: CONTEXT null??"); + return; + } + + clearManuallyAllocd(); + + Debug::log(LOG, "Attempting to create a keymap for layout {} with variant {} (rules: {}, model: {}, options: {})", rules.layout, rules.variant, rules.rules, rules.model, + rules.options); + + if (!xkbFilePath.empty()) { + auto path = absolutePath(xkbFilePath, g_pConfigManager->configCurrentPath); + + if (FILE* const KEYMAPFILE = fopen(path.c_str(), "r"); !KEYMAPFILE) + Debug::log(ERR, "Cannot open input:kb_file= file for reading"); + else { + xkbKeymap = xkb_keymap_new_from_file(CONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); + fclose(KEYMAPFILE); + } + } + + if (!xkbKeymap) + xkbKeymap = xkb_keymap_new_from_names(CONTEXT, &XKBRULES, XKB_KEYMAP_COMPILE_NO_FLAGS); + + if (!xkbKeymap) { + g_pConfigManager->addParseError("Invalid keyboard layout passed. ( rules: " + rules.rules + ", model: " + rules.model + ", variant: " + rules.variant + + ", options: " + rules.options + ", layout: " + rules.layout + " )"); + + Debug::log(ERR, "Keyboard layout {} with variant {} (rules: {}, model: {}, options: {}) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, + rules.options); + memset(&XKBRULES, 0, sizeof(XKBRULES)); + + currentRules.rules = ""; + currentRules.model = ""; + currentRules.variant = ""; + currentRules.options = ""; + currentRules.layout = "us"; + + xkbKeymap = xkb_keymap_new_from_names(CONTEXT, &XKBRULES, XKB_KEYMAP_COMPILE_NO_FLAGS); + } + + // set internal translation state + // demo sunao ni ienai + xkbInternalTranslationState = xkb_state_new(xkbKeymap); + + updateXKBTranslationState(); + + const auto NUMLOCKON = g_pConfigManager->getDeviceInt(hlName, "numlock_by_default", "input:numlock_by_default"); + + if (NUMLOCKON == 1) { + // lock numlock + const auto IDX = xkb_map_mod_get_index(xkbKeymap, XKB_MOD_NAME_NUM); + + if (IDX != XKB_MOD_INVALID) + modifiersState.locked |= (uint32_t)1 << IDX; + } + + if (modifiersState.locked != 0) + keyboardEvents.modifiers.emit(SModifiersEvent{.locked = modifiersState.locked}); + + for (size_t i = 0; i < LEDNAMES.size(); ++i) { + ledIndexes.at(i) = xkb_map_led_get_index(xkbKeymap, LEDNAMES.at(i)); + Debug::log(LOG, "xkb: LED index {} (name {}) got index {}", i, LEDNAMES.at(i), modIndexes.at(i)); + } + + for (size_t i = 0; i < MODNAMES.size(); ++i) { + modIndexes.at(i) = xkb_map_mod_get_index(xkbKeymap, MODNAMES.at(i)); + Debug::log(LOG, "xkb: Mod index {} (name {}) got index {}", i, MODNAMES.at(i), modIndexes.at(i)); + } + + auto cKeymapStr = xkb_keymap_get_as_string(xkbKeymap, XKB_KEYMAP_FORMAT_TEXT_V1); + xkbKeymapString = cKeymapStr; + free(cKeymapStr); + + int rw, ro; + if (!allocateSHMFilePair(xkbKeymapString.length() + 1, &rw, &ro)) + Debug::log(ERR, "IKeyboard: failed to allocate shm pair for the keymap"); + else { + auto keymapFDDest = mmap(nullptr, xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, rw, 0); + close(rw); + if (keymapFDDest == MAP_FAILED) { + Debug::log(ERR, "IKeyboard: failed to mmap a shm pair for the keymap"); + close(ro); + } else { + memcpy(keymapFDDest, xkbKeymapString.c_str(), xkbKeymapString.length()); + munmap(keymapFDDest, xkbKeymapString.length() + 1); + xkbKeymapFD = ro; + } + } + + xkb_context_unref(CONTEXT); } void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { @@ -32,9 +160,8 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { return; } - const auto WLRKB = wlr(); - const auto KEYMAP = WLRKB->keymap; - const auto STATE = WLRKB->xkb_state; + const auto KEYMAP = xkbKeymap; + const auto STATE = xkbInternalTranslationState; const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); @@ -101,9 +228,8 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { } std::string IKeyboard::getActiveLayout() { - const auto WLRKB = wlr(); - const auto KEYMAP = WLRKB->keymap; - const auto STATE = WLRKB->xkb_state; + const auto KEYMAP = xkbKeymap; + const auto STATE = xkbTranslationState; const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); for (uint32_t i = 0; i < LAYOUTSNUM; ++i) { @@ -120,14 +246,12 @@ std::string IKeyboard::getActiveLayout() { } void IKeyboard::updateLEDs() { - auto keyboard = wlr(); - - if (!keyboard || keyboard->xkb_state == nullptr) + if (xkbTranslationState == nullptr) return; uint32_t leds = 0; for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { - if (xkb_state_led_index_is_active(keyboard->xkb_state, keyboard->led_indexes[i])) + if (xkb_state_led_index_is_active(xkbTranslationState, ledIndexes.at(i))) leds |= (1 << i); } @@ -135,13 +259,62 @@ void IKeyboard::updateLEDs() { } void IKeyboard::updateLEDs(uint32_t leds) { - auto keyboard = wlr(); - - if (!keyboard || keyboard->xkb_state == nullptr) + if (!xkbTranslationState) return; if (isVirtual() && g_pInputManager->shouldIgnoreVirtualKeyboard(self.lock())) return; - wlr_keyboard_led_update(keyboard, leds); + if (!aq()) + return; + + aq()->updateLEDs(leds); +} + +uint32_t IKeyboard::getModifiers() { + uint32_t modMask = modifiersState.depressed | modifiersState.latched; + uint32_t mods = 0; + for (size_t i = 0; i < modIndexes.size(); ++i) { + if (modIndexes.at(i) == XKB_MOD_INVALID) + continue; + + if (!(modMask & (1 << modIndexes.at(i)))) + continue; + + mods |= (1 << i); + } + + return mods; +} + +void IKeyboard::updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) { + if (!xkbTranslationState) + return; + + xkb_state_update_mask(xkbTranslationState, depressed, latched, locked, 0, 0, group); + + if (!updateModifiersState()) + return; + + updateLEDs(); +} + +bool IKeyboard::updateModifiersState() { + if (!xkbTranslationState) + return false; + + auto depressed = xkb_state_serialize_mods(xkbTranslationState, XKB_STATE_MODS_DEPRESSED); + auto latched = xkb_state_serialize_mods(xkbTranslationState, XKB_STATE_MODS_LATCHED); + auto locked = xkb_state_serialize_mods(xkbTranslationState, XKB_STATE_MODS_LOCKED); + auto group = xkb_state_serialize_layout(xkbTranslationState, XKB_STATE_LAYOUT_EFFECTIVE); + + if (depressed == modifiersState.depressed && latched == modifiersState.latched && locked == modifiersState.locked && group == modifiersState.group) + return false; + + modifiersState.depressed = depressed; + modifiersState.latched = latched; + modifiersState.locked = locked; + modifiersState.group = group; + + return true; } diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index b1757a1863f..fec856061da 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -7,15 +7,15 @@ #include -struct wlr_keyboard; +AQUAMARINE_FORWARD(IKeyboard); class IKeyboard : public IHID { public: virtual ~IKeyboard(); - virtual uint32_t getCapabilities(); - virtual eHIDType getType(); - virtual bool isVirtual() = 0; - virtual wlr_keyboard* wlr() = 0; + virtual uint32_t getCapabilities(); + virtual eHIDType getType(); + virtual bool isVirtual() = 0; + virtual SP aq() = 0; struct SKeyEvent { uint32_t timeMs = 0; @@ -24,6 +24,17 @@ class IKeyboard : public IHID { wl_keyboard_key_state state = WL_KEYBOARD_KEY_STATE_PRESSED; }; + struct SKeymapEvent { + xkb_keymap* keymap = nullptr; + }; + + struct SModifiersEvent { + uint32_t depressed = 0; + uint32_t latched = 0; + uint32_t locked = 0; + uint32_t group = 0; + }; + struct { CSignal key; CSignal modifiers; @@ -39,25 +50,43 @@ class IKeyboard : public IHID { std::string rules = ""; }; + void setKeymap(const SStringRuleNames& rules); void updateXKBTranslationState(xkb_keymap* const keymap = nullptr); std::string getActiveLayout(); void updateLEDs(); void updateLEDs(uint32_t leds); + uint32_t getModifiers(); + void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); bool active = false; bool enabled = true; xkb_layout_index_t activeLayout = 0; - xkb_state* xkbTranslationState = nullptr; + xkb_state * xkbTranslationState = nullptr, *xkbInternalTranslationState = nullptr; + xkb_keymap* xkbKeymap = nullptr; + + struct { + uint32_t depressed = 0, latched = 0, locked = 0, group = 0; + } modifiersState; + + std::array ledIndexes; + std::array modIndexes; + uint32_t leds = 0; + + std::string hlName = ""; + std::string xkbFilePath = ""; + std::string xkbKeymapString = ""; + int xkbKeymapFD = -1; - std::string hlName = ""; - std::string xkbFilePath = ""; + SStringRuleNames currentRules; + int repeatRate = 0; + int repeatDelay = 0; + int numlockOn = -1; + bool resolveBindsBySym = false; - SStringRuleNames currentRules; - int repeatRate = 0; - int repeatDelay = 0; - int numlockOn = -1; - bool resolveBindsBySym = false; + WP self; - WP self; + private: + void clearManuallyAllocd(); + bool updateModifiersState(); // rets whether changed }; diff --git a/src/devices/IPointer.hpp b/src/devices/IPointer.hpp index b2995b2f7b0..5df47c04f18 100644 --- a/src/devices/IPointer.hpp +++ b/src/devices/IPointer.hpp @@ -5,17 +5,17 @@ #include "../macros.hpp" #include "../helpers/math/Math.hpp" -struct wlr_pointer; +AQUAMARINE_FORWARD(IPointer); /* Base class for a pointer. */ class IPointer : public IHID { public: - virtual uint32_t getCapabilities(); - virtual eHIDType getType(); - virtual bool isVirtual() = 0; - virtual wlr_pointer* wlr() = 0; + virtual uint32_t getCapabilities(); + virtual eHIDType getType(); + virtual bool isVirtual() = 0; + virtual SP aq() = 0; struct SMotionEvent { uint32_t timeMs = 0; diff --git a/src/devices/ITouch.hpp b/src/devices/ITouch.hpp index b9cbf2aebfd..cb8a6e9077e 100644 --- a/src/devices/ITouch.hpp +++ b/src/devices/ITouch.hpp @@ -5,14 +5,14 @@ #include "../macros.hpp" #include "../helpers/math/Math.hpp" -struct wlr_touch; +AQUAMARINE_FORWARD(ITouch); class ITouch : public IHID { public: - virtual uint32_t getCapabilities(); - virtual eHIDType getType(); - virtual bool isVirtual() = 0; - virtual wlr_touch* wlr() = 0; + virtual uint32_t getCapabilities(); + virtual eHIDType getType(); + virtual bool isVirtual() = 0; + virtual SP aq() = 0; struct SDownEvent { uint32_t timeMs = 0; diff --git a/src/devices/Keyboard.cpp b/src/devices/Keyboard.cpp index 17357edb1c9..514bef2b89c 100644 --- a/src/devices/Keyboard.cpp +++ b/src/devices/Keyboard.cpp @@ -1,7 +1,9 @@ #include "Keyboard.hpp" #include "../defines.hpp" -SP CKeyboard::create(wlr_keyboard* keeb) { +#include + +SP CKeyboard::create(SP keeb) { SP pKeeb = SP(new CKeyboard(keeb)); pKeeb->self = pKeeb; @@ -13,52 +15,41 @@ bool CKeyboard::isVirtual() { return false; } -wlr_keyboard* CKeyboard::wlr() { - return keyboard; +SP CKeyboard::aq() { + return keyboard.lock(); } -CKeyboard::CKeyboard(wlr_keyboard* keeb) : keyboard(keeb) { +CKeyboard::CKeyboard(SP keeb) : keyboard(keeb) { if (!keeb) return; - // clang-format off - hyprListener_destroy.initCallback(&keeb->base.events.destroy, [this] (void* owner, void* data) { - disconnectCallbacks(); - keyboard = nullptr; - events.destroy.emit(); - }, this, "CKeyboard"); + listeners.destroy = keeb->events.destroy.registerListener([this](std::any d) { + keyboard.reset(); + events.destroy.emit(); + }); - hyprListener_key.initCallback(&keeb->events.key, [this] (void* owner, void* data) { - auto E = (wlr_keyboard_key_event*)data; + listeners.key = keeb->events.key.registerListener([this](std::any d) { + auto E = std::any_cast(d); keyboardEvents.key.emit(SKeyEvent{ - .timeMs = E->time_msec, - .keycode = E->keycode, - .updateMods = E->update_state, - .state = E->state, + .timeMs = E.timeMs, + .keycode = E.key, + .state = E.pressed ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED, }); - }, this, "CKeyboard"); - - hyprListener_keymap.initCallback(&keeb->events.keymap, [this] (void* owner, void* data) { - keyboardEvents.keymap.emit(); - }, this, "CKeyboard"); + }); - hyprListener_modifiers.initCallback(&keeb->events.modifiers, [this] (void* owner, void* data) { - keyboardEvents.modifiers.emit(); - }, this, "CKeyboard"); + listeners.modifiers = keeb->events.modifiers.registerListener([this](std::any d) { + auto E = std::any_cast(d); - hyprListener_repeatInfo.initCallback(&keeb->events.repeat_info, [this] (void* owner, void* data) { - keyboardEvents.repeatInfo.emit(); - }, this, "CKeyboard"); - // clang-format on + updateModifiers(E.depressed, E.latched, E.locked, E.group); - deviceName = keeb->base.name ? keeb->base.name : "UNKNOWN"; -} + keyboardEvents.modifiers.emit(SModifiersEvent{ + .depressed = modifiersState.depressed, + .latched = modifiersState.latched, + .locked = modifiersState.locked, + .group = modifiersState.group, + }); + }); -void CKeyboard::disconnectCallbacks() { - hyprListener_destroy.removeCallback(); - hyprListener_key.removeCallback(); - hyprListener_keymap.removeCallback(); - hyprListener_repeatInfo.removeCallback(); - hyprListener_modifiers.removeCallback(); + deviceName = keeb->getName(); } diff --git a/src/devices/Keyboard.hpp b/src/devices/Keyboard.hpp index cf01a9a7a66..f6de43cb5d0 100644 --- a/src/devices/Keyboard.hpp +++ b/src/devices/Keyboard.hpp @@ -4,21 +4,19 @@ class CKeyboard : public IKeyboard { public: - static SP create(wlr_keyboard* keeb); + static SP create(SP keeb); - virtual bool isVirtual(); - virtual wlr_keyboard* wlr(); + virtual bool isVirtual(); + virtual SP aq(); private: - CKeyboard(wlr_keyboard* keeb); + CKeyboard(SP keeb); - wlr_keyboard* keyboard = nullptr; + WP keyboard; - void disconnectCallbacks(); - - DYNLISTENER(destroy); - DYNLISTENER(key); - DYNLISTENER(modifiers); - DYNLISTENER(keymap); - DYNLISTENER(repeatInfo); + struct { + CHyprSignalListener destroy; + CHyprSignalListener key; + CHyprSignalListener modifiers; + } listeners; }; \ No newline at end of file diff --git a/src/devices/Mouse.cpp b/src/devices/Mouse.cpp index b860298cd17..ae89ed92f72 100644 --- a/src/devices/Mouse.cpp +++ b/src/devices/Mouse.cpp @@ -1,7 +1,8 @@ #include "Mouse.hpp" #include "../defines.hpp" +#include -SP CMouse::create(wlr_pointer* mouse) { +SP CMouse::create(SP mouse) { SP pMouse = SP(new CMouse(mouse)); pMouse->self = pMouse; @@ -9,166 +10,143 @@ SP CMouse::create(wlr_pointer* mouse) { return pMouse; } -CMouse::CMouse(wlr_pointer* mouse_) : mouse(mouse_) { +CMouse::CMouse(SP mouse_) : mouse(mouse_) { if (!mouse) return; - // clang-format off - hyprListener_destroy.initCallback(&mouse->base.events.destroy, [this] (void* owner, void* data) { - disconnectCallbacks(); - mouse = nullptr; + listeners.destroy = mouse->events.destroy.registerListener([this](std::any d) { + mouse.reset(); events.destroy.emit(); - }, this, "CMouse"); + }); - hyprListener_motion.initCallback(&mouse->events.motion, [this] (void* owner, void* data) { - auto E = (wlr_pointer_motion_event*)data; + listeners.motion = mouse->events.move.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.motion.emit(SMotionEvent{ - .timeMs = E->time_msec, - .delta = {E->delta_x, E->delta_y}, - .unaccel = {E->unaccel_dx, E->unaccel_dy}, + .timeMs = E.timeMs, + .delta = E.delta, + .unaccel = E.unaccel, }); - }, this, "CMouse"); + }); - hyprListener_motionAbsolute.initCallback(&mouse->events.motion_absolute, [this] (void* owner, void* data) { - auto E = (wlr_pointer_motion_absolute_event*)data; + listeners.motionAbsolute = mouse->events.warp.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.motionAbsolute.emit(SMotionAbsoluteEvent{ - .timeMs = E->time_msec, - .absolute = {E->x, E->y}, + .timeMs = E.timeMs, + .absolute = E.absolute, .device = self.lock(), }); - }, this, "CMouse"); + }); - hyprListener_button.initCallback(&mouse->events.button, [this] (void* owner, void* data) { - auto E = (wlr_pointer_button_event*)data; + listeners.button = mouse->events.button.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.button.emit(SButtonEvent{ - .timeMs = E->time_msec, - .button = E->button, - .state = (wl_pointer_button_state)E->state, + .timeMs = E.timeMs, + .button = E.button, + .state = E.pressed ? WL_POINTER_BUTTON_STATE_PRESSED : WL_POINTER_BUTTON_STATE_RELEASED, }); - }, this, "CMouse"); + }); - hyprListener_axis.initCallback(&mouse->events.axis, [this] (void* owner, void* data) { - auto E = (wlr_pointer_axis_event*)data; + listeners.axis = mouse->events.axis.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.axis.emit(SAxisEvent{ - .timeMs = E->time_msec, - .source = E->source, - .axis = E->orientation, - .relativeDirection = E->relative_direction, - .delta = E->delta, - .deltaDiscrete = E->delta_discrete, + .timeMs = E.timeMs, + .source = (wl_pointer_axis_source)E.source, + .axis = (wl_pointer_axis)E.axis, + .relativeDirection = (wl_pointer_axis_relative_direction)E.direction, + .delta = E.delta, + .deltaDiscrete = E.discrete, }); - }, this, "CMouse"); + }); - hyprListener_frame.initCallback(&mouse->events.frame, [this] (void* owner, void* data) { - pointerEvents.frame.emit(); - }, this, "CMouse"); + listeners.frame = mouse->events.frame.registerListener([this](std::any d) { pointerEvents.frame.emit(); }); - hyprListener_swipeBegin.initCallback(&mouse->events.swipe_begin, [this] (void* owner, void* data) { - auto E = (wlr_pointer_swipe_begin_event*)data; + listeners.swipeBegin = mouse->events.swipeBegin.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.swipeBegin.emit(SSwipeBeginEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, + .timeMs = E.timeMs, + .fingers = E.fingers, }); - }, this, "CMouse"); + }); - hyprListener_swipeEnd.initCallback(&mouse->events.swipe_end, [this] (void* owner, void* data) { - auto E = (wlr_pointer_swipe_end_event*)data; + listeners.swipeEnd = mouse->events.swipeEnd.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.swipeEnd.emit(SSwipeEndEvent{ - .timeMs = E->time_msec, - .cancelled = E->cancelled, + .timeMs = E.timeMs, + .cancelled = E.cancelled, }); - }, this, "CMouse"); + }); - hyprListener_swipeUpdate.initCallback(&mouse->events.swipe_update, [this] (void* owner, void* data) { - auto E = (wlr_pointer_swipe_update_event*)data; + listeners.swipeUpdate = mouse->events.swipeUpdate.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.swipeUpdate.emit(SSwipeUpdateEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, - .delta = {E->dx, E->dy}, + .timeMs = E.timeMs, + .fingers = E.fingers, + .delta = E.delta, }); - }, this, "CMouse"); + }); - hyprListener_pinchBegin.initCallback(&mouse->events.pinch_begin, [this] (void* owner, void* data) { - auto E = (wlr_pointer_pinch_begin_event*)data; + listeners.pinchBegin = mouse->events.pinchBegin.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.pinchBegin.emit(SPinchBeginEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, + .timeMs = E.timeMs, + .fingers = E.fingers, }); - }, this, "CMouse"); + }); - hyprListener_pinchEnd.initCallback(&mouse->events.pinch_end, [this] (void* owner, void* data) { - auto E = (wlr_pointer_pinch_end_event*)data; + listeners.pinchEnd = mouse->events.pinchEnd.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.pinchEnd.emit(SPinchEndEvent{ - .timeMs = E->time_msec, - .cancelled = E->cancelled, + .timeMs = E.timeMs, + .cancelled = E.cancelled, }); - }, this, "CMouse"); + }); - hyprListener_pinchUpdate.initCallback(&mouse->events.pinch_update, [this] (void* owner, void* data) { - auto E = (wlr_pointer_pinch_update_event*)data; + listeners.pinchUpdate = mouse->events.pinchUpdate.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.pinchUpdate.emit(SPinchUpdateEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, - .delta = {E->dx, E->dy}, - .scale = E->scale, - .rotation = E->rotation, + .timeMs = E.timeMs, + .fingers = E.fingers, + .delta = E.delta, + .scale = E.scale, + .rotation = E.rotation, }); - }, this, "CMouse"); + }); - hyprListener_holdBegin.initCallback(&mouse->events.hold_begin, [this] (void* owner, void* data) { - auto E = (wlr_pointer_hold_begin_event*)data; + listeners.holdBegin = mouse->events.holdBegin.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.holdBegin.emit(SHoldBeginEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, + .timeMs = E.timeMs, + .fingers = E.fingers, }); - }, this, "CMouse"); + }); - hyprListener_holdEnd.initCallback(&mouse->events.hold_end, [this] (void* owner, void* data) { - auto E = (wlr_pointer_hold_end_event*)data; + listeners.holdEnd = mouse->events.holdEnd.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.holdEnd.emit(SHoldEndEvent{ - .timeMs = E->time_msec, - .cancelled = E->cancelled, + .timeMs = E.timeMs, + .cancelled = E.cancelled, }); - }, this, "CMouse"); + }); - // clang-format on - - deviceName = mouse->base.name ? mouse->base.name : "UNKNOWN"; -} - -void CMouse::disconnectCallbacks() { - hyprListener_destroy.removeCallback(); - hyprListener_motion.removeCallback(); - hyprListener_motionAbsolute.removeCallback(); - hyprListener_button.removeCallback(); - hyprListener_axis.removeCallback(); - hyprListener_frame.removeCallback(); - hyprListener_swipeBegin.removeCallback(); - hyprListener_swipeEnd.removeCallback(); - hyprListener_swipeUpdate.removeCallback(); - hyprListener_pinchBegin.removeCallback(); - hyprListener_pinchEnd.removeCallback(); - hyprListener_pinchUpdate.removeCallback(); - hyprListener_holdBegin.removeCallback(); - hyprListener_holdEnd.removeCallback(); + deviceName = mouse->getName(); } bool CMouse::isVirtual() { return false; } -wlr_pointer* CMouse::wlr() { - return mouse; +SP CMouse::aq() { + return mouse.lock(); } diff --git a/src/devices/Mouse.hpp b/src/devices/Mouse.hpp index 40a65ca8fbd..2b51fbe945b 100644 --- a/src/devices/Mouse.hpp +++ b/src/devices/Mouse.hpp @@ -4,33 +4,34 @@ class CMouse : public IPointer { public: - static SP create(wlr_pointer* mouse); + static SP create(SP mouse); - virtual bool isVirtual(); - virtual wlr_pointer* wlr(); + virtual bool isVirtual(); + virtual SP aq(); private: - CMouse(wlr_pointer* mouse); + CMouse(SP mouse); - wlr_pointer* mouse = nullptr; + WP mouse; - void disconnectCallbacks(); + struct { + CHyprSignalListener destroy; - DYNLISTENER(destroy); - DYNLISTENER(motion); - DYNLISTENER(motionAbsolute); - DYNLISTENER(button); - DYNLISTENER(axis); - DYNLISTENER(frame); + CHyprSignalListener motion; + CHyprSignalListener motionAbsolute; + CHyprSignalListener button; + CHyprSignalListener axis; + CHyprSignalListener frame; - DYNLISTENER(swipeBegin); - DYNLISTENER(swipeEnd); - DYNLISTENER(swipeUpdate); + CHyprSignalListener swipeBegin; + CHyprSignalListener swipeEnd; + CHyprSignalListener swipeUpdate; - DYNLISTENER(pinchBegin); - DYNLISTENER(pinchEnd); - DYNLISTENER(pinchUpdate); + CHyprSignalListener pinchBegin; + CHyprSignalListener pinchEnd; + CHyprSignalListener pinchUpdate; - DYNLISTENER(holdBegin); - DYNLISTENER(holdEnd); + CHyprSignalListener holdBegin; + CHyprSignalListener holdEnd; + } listeners; }; diff --git a/src/devices/TouchDevice.cpp b/src/devices/TouchDevice.cpp index 64c521a23f9..25b7b503b02 100644 --- a/src/devices/TouchDevice.cpp +++ b/src/devices/TouchDevice.cpp @@ -1,7 +1,8 @@ #include "TouchDevice.hpp" #include "../defines.hpp" +#include -SP CTouchDevice::create(wlr_touch* touch) { +SP CTouchDevice::create(SP touch) { SP pTouch = SP(new CTouchDevice(touch)); pTouch->self = pTouch; @@ -9,78 +10,63 @@ SP CTouchDevice::create(wlr_touch* touch) { return pTouch; } -CTouchDevice::CTouchDevice(wlr_touch* touch_) : touch(touch_) { +CTouchDevice::CTouchDevice(SP touch_) : touch(touch_) { if (!touch) return; - // clang-format off - hyprListener_destroy.initCallback(&touch->base.events.destroy, [this] (void* owner, void* data) { + listeners.destroy = touch->events.destroy.registerListener([this](std::any d) { events.destroy.emit(); - disconnectCallbacks(); - touch = nullptr; - }, this, "CTouchDevice"); + touch.reset(); + }); - hyprListener_down.initCallback(&touch->events.down, [this] (void* owner, void* data) { - auto E = (wlr_touch_down_event*)data; + listeners.down = touch->events.down.registerListener([this](std::any d) { + auto E = std::any_cast(d); touchEvents.down.emit(SDownEvent{ - .timeMs = E->time_msec, - .touchID = E->touch_id, - .pos = {E->x, E->y}, + .timeMs = E.timeMs, + .touchID = E.touchID, + .pos = E.pos, .device = self.lock(), }); - }, this, "CTouchDevice"); + }); - hyprListener_up.initCallback(&touch->events.up, [this] (void* owner, void* data) { - auto E = (wlr_touch_up_event*)data; + listeners.up = touch->events.up.registerListener([this](std::any d) { + auto E = std::any_cast(d); touchEvents.up.emit(SUpEvent{ - .timeMs = E->time_msec, - .touchID = E->touch_id + .timeMs = E.timeMs, + .touchID = E.touchID, }); - }, this, "CTouchDevice"); + }); - hyprListener_motion.initCallback(&touch->events.motion, [this] (void* owner, void* data) { - auto E = (wlr_touch_motion_event*)data; + listeners.motion = touch->events.move.registerListener([this](std::any d) { + auto E = std::any_cast(d); touchEvents.motion.emit(SMotionEvent{ - .timeMs = E->time_msec, - .touchID = E->touch_id, - .pos = {E->x, E->y}, + .timeMs = E.timeMs, + .touchID = E.touchID, + .pos = E.pos, }); - }, this, "CTouchDevice"); + }); - hyprListener_cancel.initCallback(&touch->events.cancel, [this] (void* owner, void* data) { - auto E = (wlr_touch_cancel_event*)data; + listeners.cancel = touch->events.cancel.registerListener([this](std::any d) { + auto E = std::any_cast(d); touchEvents.cancel.emit(SCancelEvent{ - .timeMs = E->time_msec, - .touchID = E->touch_id + .timeMs = E.timeMs, + .touchID = E.touchID, }); - }, this, "CTouchDevice"); + }); - hyprListener_frame.initCallback(&touch->events.frame, [this] (void* owner, void* data) { - touchEvents.frame.emit(); - }, this, "CTouchDevice"); + listeners.frame = touch->events.frame.registerListener([this](std::any d) { touchEvents.frame.emit(); }); - // clang-format on - - deviceName = touch->base.name ? touch->base.name : "UNKNOWN"; + deviceName = touch->getName(); } bool CTouchDevice::isVirtual() { return false; } -wlr_touch* CTouchDevice::wlr() { - return touch; -} - -void CTouchDevice::disconnectCallbacks() { - hyprListener_destroy.removeCallback(); - hyprListener_down.removeCallback(); - hyprListener_up.removeCallback(); - hyprListener_motion.removeCallback(); - hyprListener_cancel.removeCallback(); - hyprListener_frame.removeCallback(); +SP CTouchDevice::aq() { + return touch.lock(); } diff --git a/src/devices/TouchDevice.hpp b/src/devices/TouchDevice.hpp index 51eb76d47bf..b18df2d01ba 100644 --- a/src/devices/TouchDevice.hpp +++ b/src/devices/TouchDevice.hpp @@ -4,22 +4,22 @@ class CTouchDevice : public ITouch { public: - static SP create(wlr_touch* touch); + static SP create(SP touch); - virtual bool isVirtual(); - virtual wlr_touch* wlr(); + virtual bool isVirtual(); + virtual SP aq(); private: - CTouchDevice(wlr_touch* touch); + CTouchDevice(SP touch); - wlr_touch* touch = nullptr; + WP touch; - void disconnectCallbacks(); - - DYNLISTENER(destroy); - DYNLISTENER(down); - DYNLISTENER(up); - DYNLISTENER(motion); - DYNLISTENER(cancel); - DYNLISTENER(frame); + struct { + CHyprSignalListener destroy; + CHyprSignalListener down; + CHyprSignalListener up; + CHyprSignalListener motion; + CHyprSignalListener cancel; + CHyprSignalListener frame; + } listeners; }; \ No newline at end of file diff --git a/src/devices/VirtualKeyboard.cpp b/src/devices/VirtualKeyboard.cpp index e2be0078101..654ca9f5cbd 100644 --- a/src/devices/VirtualKeyboard.cpp +++ b/src/devices/VirtualKeyboard.cpp @@ -14,58 +14,37 @@ CVirtualKeyboard::CVirtualKeyboard(SP keeb_) : keybo if (!keeb_) return; - auto keeb = keeb_->wlr(); - - // clang-format off - hyprListener_destroy.initCallback(&keeb->base.events.destroy, [this] (void* owner, void* data) { - disconnectCallbacks(); + listeners.destroy = keeb_->events.destroy.registerListener([this](std::any d) { keyboard.reset(); - events.destroy.emit(); - }, this, "CVirtualKeyboard"); - - hyprListener_key.initCallback(&keeb->events.key, [this] (void* owner, void* data) { - auto E = (wlr_keyboard_key_event*)data; - - keyboardEvents.key.emit(SKeyEvent{ - .timeMs = E->time_msec, - .keycode = E->keycode, - .updateMods = E->update_state, - .state = E->state, + events.destroy.emit(); + }); + + listeners.key = keeb_->events.key.registerListener([this](std::any d) { keyboardEvents.key.emit(d); }); + listeners.modifiers = keeb_->events.modifiers.registerListener([this](std::any d) { + auto E = std::any_cast(d); + updateModifiers(E.depressed, E.latched, E.locked, E.group); + keyboardEvents.modifiers.emit(SModifiersEvent{ + .depressed = modifiersState.depressed, + .latched = modifiersState.latched, + .locked = modifiersState.locked, + .group = modifiersState.group, }); - }, this, "CVirtualKeyboard"); - - hyprListener_keymap.initCallback(&keeb->events.keymap, [this] (void* owner, void* data) { - keyboardEvents.keymap.emit(); - }, this, "CVirtualKeyboard"); - - hyprListener_modifiers.initCallback(&keeb->events.modifiers, [this] (void* owner, void* data) { - keyboardEvents.modifiers.emit(); - }, this, "CVirtualKeyboard"); - - hyprListener_repeatInfo.initCallback(&keeb->events.repeat_info, [this] (void* owner, void* data) { - keyboardEvents.repeatInfo.emit(); - }, this, "CVirtualKeyboard"); - // clang-format on - - deviceName = keeb->base.name ? keeb->base.name : "UNKNOWN"; + }); + listeners.keymap = keeb_->events.keymap.registerListener([this](std::any d) { + auto E = std::any_cast(d); + xkbKeymap = xkb_keymap_ref(E.keymap); + keyboardEvents.keymap.emit(d); + }); + + deviceName = keeb_->name; } bool CVirtualKeyboard::isVirtual() { return true; } -wlr_keyboard* CVirtualKeyboard::wlr() { - if (keyboard.expired()) - return nullptr; - return keyboard->wlr(); -} - -void CVirtualKeyboard::disconnectCallbacks() { - hyprListener_destroy.removeCallback(); - hyprListener_key.removeCallback(); - hyprListener_keymap.removeCallback(); - hyprListener_repeatInfo.removeCallback(); - hyprListener_modifiers.removeCallback(); +SP CVirtualKeyboard::aq() { + return nullptr; } wl_client* CVirtualKeyboard::getClient() { diff --git a/src/devices/VirtualKeyboard.hpp b/src/devices/VirtualKeyboard.hpp index 5ef88dd3f3e..12a3907c90c 100644 --- a/src/devices/VirtualKeyboard.hpp +++ b/src/devices/VirtualKeyboard.hpp @@ -6,23 +6,22 @@ class CVirtualKeyboardV1Resource; class CVirtualKeyboard : public IKeyboard { public: - static SP create(SP keeb); + static SP create(SP keeb); - virtual bool isVirtual(); - virtual wlr_keyboard* wlr(); + virtual bool isVirtual(); + virtual SP aq(); - wl_client* getClient(); + wl_client* getClient(); private: CVirtualKeyboard(SP keeb); WP keyboard; - void disconnectCallbacks(); - - DYNLISTENER(destroy); - DYNLISTENER(key); - DYNLISTENER(modifiers); - DYNLISTENER(keymap); - DYNLISTENER(repeatInfo); + struct { + CHyprSignalListener destroy; + CHyprSignalListener key; + CHyprSignalListener modifiers; + CHyprSignalListener keymap; + } listeners; }; diff --git a/src/devices/VirtualPointer.cpp b/src/devices/VirtualPointer.cpp index c8ee33325cf..faca27dc343 100644 --- a/src/devices/VirtualPointer.cpp +++ b/src/devices/VirtualPointer.cpp @@ -1,5 +1,6 @@ #include "VirtualPointer.hpp" #include "../protocols/VirtualPointer.hpp" +#include SP CVirtualPointer::create(SP resource) { SP pPointer = SP(new CVirtualPointer(resource)); @@ -13,165 +14,32 @@ CVirtualPointer::CVirtualPointer(SP resource) : point if (!resource->good()) return; - auto mouse = resource->wlr(); - - // clang-format off - hyprListener_destroy.initCallback(&mouse->base.events.destroy, [this] (void* owner, void* data) { - disconnectCallbacks(); + listeners.destroy = pointer->events.destroy.registerListener([this](std::any d) { + pointer.reset(); events.destroy.emit(); - }, this, "CVirtualPointer"); - - hyprListener_motion.initCallback(&mouse->events.motion, [this] (void* owner, void* data) { - auto E = (wlr_pointer_motion_event*)data; - - pointerEvents.motion.emit(SMotionEvent{ - .timeMs = E->time_msec, - .delta = {E->delta_x, E->delta_y}, - .unaccel = {E->unaccel_dx, E->unaccel_dy}, - }); - }, this, "CVirtualPointer"); - - hyprListener_motionAbsolute.initCallback(&mouse->events.motion_absolute, [this] (void* owner, void* data) { - auto E = (wlr_pointer_motion_absolute_event*)data; - - pointerEvents.motionAbsolute.emit(SMotionAbsoluteEvent{ - .timeMs = E->time_msec, - .absolute = {E->x, E->y}, - .device = self.lock(), - }); - }, this, "CVirtualPointer"); - - hyprListener_button.initCallback(&mouse->events.button, [this] (void* owner, void* data) { - auto E = (wlr_pointer_button_event*)data; - - pointerEvents.button.emit(SButtonEvent{ - .timeMs = E->time_msec, - .button = E->button, - .state = (wl_pointer_button_state)E->state, - }); - }, this, "CVirtualPointer"); - - hyprListener_axis.initCallback(&mouse->events.axis, [this] (void* owner, void* data) { - auto E = (wlr_pointer_axis_event*)data; - - pointerEvents.axis.emit(SAxisEvent{ - .timeMs = E->time_msec, - .source = E->source, - .axis = E->orientation, - .relativeDirection = E->relative_direction, - .delta = E->delta, - .deltaDiscrete = E->delta_discrete, - }); - }, this, "CVirtualPointer"); - - hyprListener_frame.initCallback(&mouse->events.frame, [this] (void* owner, void* data) { - pointerEvents.frame.emit(); - }, this, "CVirtualPointer"); - - hyprListener_swipeBegin.initCallback(&mouse->events.swipe_begin, [this] (void* owner, void* data) { - auto E = (wlr_pointer_swipe_begin_event*)data; - - pointerEvents.swipeBegin.emit(SSwipeBeginEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, - }); - }, this, "CVirtualPointer"); - - hyprListener_swipeEnd.initCallback(&mouse->events.swipe_end, [this] (void* owner, void* data) { - auto E = (wlr_pointer_swipe_end_event*)data; - - pointerEvents.swipeEnd.emit(SSwipeEndEvent{ - .timeMs = E->time_msec, - .cancelled = E->cancelled, - }); - }, this, "CVirtualPointer"); - - hyprListener_swipeUpdate.initCallback(&mouse->events.swipe_update, [this] (void* owner, void* data) { - auto E = (wlr_pointer_swipe_update_event*)data; - - pointerEvents.swipeUpdate.emit(SSwipeUpdateEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, - .delta = {E->dx, E->dy}, - }); - }, this, "CVirtualPointer"); - - hyprListener_pinchBegin.initCallback(&mouse->events.pinch_begin, [this] (void* owner, void* data) { - auto E = (wlr_pointer_pinch_begin_event*)data; - - pointerEvents.pinchBegin.emit(SPinchBeginEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, - }); - }, this, "CVirtualPointer"); - - hyprListener_pinchEnd.initCallback(&mouse->events.pinch_end, [this] (void* owner, void* data) { - auto E = (wlr_pointer_pinch_end_event*)data; - - pointerEvents.pinchEnd.emit(SPinchEndEvent{ - .timeMs = E->time_msec, - .cancelled = E->cancelled, - }); - }, this, "CVirtualPointer"); - - hyprListener_pinchUpdate.initCallback(&mouse->events.pinch_update, [this] (void* owner, void* data) { - auto E = (wlr_pointer_pinch_update_event*)data; - - pointerEvents.pinchUpdate.emit(SPinchUpdateEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, - .delta = {E->dx, E->dy}, - .scale = E->scale, - .rotation = E->rotation, - }); - }, this, "CVirtualPointer"); - - hyprListener_holdBegin.initCallback(&mouse->events.hold_begin, [this] (void* owner, void* data) { - auto E = (wlr_pointer_hold_begin_event*)data; - - pointerEvents.holdBegin.emit(SHoldBeginEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, - }); - }, this, "CVirtualPointer"); - - hyprListener_holdEnd.initCallback(&mouse->events.hold_end, [this] (void* owner, void* data) { - auto E = (wlr_pointer_hold_end_event*)data; - - pointerEvents.holdEnd.emit(SHoldEndEvent{ - .timeMs = E->time_msec, - .cancelled = E->cancelled, - }); - }, this, "CVirtualPointer"); - - // clang-format on - - deviceName = mouse->base.name ? mouse->base.name : "UNKNOWN"; + }); + + listeners.motion = pointer->events.move.registerListener([this](std::any d) { pointerEvents.motion.emit(d); }); + listeners.motionAbsolute = pointer->events.warp.registerListener([this](std::any d) { pointerEvents.motionAbsolute.emit(d); }); + listeners.button = pointer->events.button.registerListener([this](std::any d) { pointerEvents.button.emit(d); }); + listeners.axis = pointer->events.axis.registerListener([this](std::any d) { pointerEvents.axis.emit(d); }); + listeners.frame = pointer->events.frame.registerListener([this](std::any d) { pointerEvents.frame.emit(); }); + listeners.swipeBegin = pointer->events.swipeBegin.registerListener([this](std::any d) { pointerEvents.swipeBegin.emit(d); }); + listeners.swipeEnd = pointer->events.swipeEnd.registerListener([this](std::any d) { pointerEvents.swipeEnd.emit(d); }); + listeners.swipeUpdate = pointer->events.swipeUpdate.registerListener([this](std::any d) { pointerEvents.swipeUpdate.emit(d); }); + listeners.pinchBegin = pointer->events.pinchBegin.registerListener([this](std::any d) { pointerEvents.pinchBegin.emit(d); }); + listeners.pinchEnd = pointer->events.pinchEnd.registerListener([this](std::any d) { pointerEvents.pinchEnd.emit(d); }); + listeners.pinchUpdate = pointer->events.pinchUpdate.registerListener([this](std::any d) { pointerEvents.pinchUpdate.emit(d); }); + listeners.holdBegin = pointer->events.holdBegin.registerListener([this](std::any d) { pointerEvents.holdBegin.emit(d); }); + listeners.holdEnd = pointer->events.holdEnd.registerListener([this](std::any d) { pointerEvents.holdEnd.emit(d); }); + + deviceName = pointer->name; } bool CVirtualPointer::isVirtual() { return true; } -void CVirtualPointer::disconnectCallbacks() { - hyprListener_destroy.removeCallback(); - hyprListener_motion.removeCallback(); - hyprListener_motionAbsolute.removeCallback(); - hyprListener_button.removeCallback(); - hyprListener_axis.removeCallback(); - hyprListener_frame.removeCallback(); - hyprListener_swipeBegin.removeCallback(); - hyprListener_swipeEnd.removeCallback(); - hyprListener_swipeUpdate.removeCallback(); - hyprListener_pinchBegin.removeCallback(); - hyprListener_pinchEnd.removeCallback(); - hyprListener_pinchUpdate.removeCallback(); - hyprListener_holdBegin.removeCallback(); - hyprListener_holdEnd.removeCallback(); -} - -wlr_pointer* CVirtualPointer::wlr() { - if (pointer.expired()) - return nullptr; - return pointer->wlr(); +SP CVirtualPointer::aq() { + return nullptr; } diff --git a/src/devices/VirtualPointer.hpp b/src/devices/VirtualPointer.hpp index b22c8bf2d08..1ecfd8426ff 100644 --- a/src/devices/VirtualPointer.hpp +++ b/src/devices/VirtualPointer.hpp @@ -6,33 +6,34 @@ class CVirtualPointerV1Resource; class CVirtualPointer : public IPointer { public: - static SP create(SP resource); + static SP create(SP resource); - virtual bool isVirtual(); - virtual wlr_pointer* wlr(); + virtual bool isVirtual(); + virtual SP aq(); private: CVirtualPointer(SP); WP pointer; - void disconnectCallbacks(); + struct { + CHyprSignalListener destroy; - DYNLISTENER(destroy); - DYNLISTENER(motion); - DYNLISTENER(motionAbsolute); - DYNLISTENER(button); - DYNLISTENER(axis); - DYNLISTENER(frame); + CHyprSignalListener motion; + CHyprSignalListener motionAbsolute; + CHyprSignalListener button; + CHyprSignalListener axis; + CHyprSignalListener frame; - DYNLISTENER(swipeBegin); - DYNLISTENER(swipeEnd); - DYNLISTENER(swipeUpdate); + CHyprSignalListener swipeBegin; + CHyprSignalListener swipeEnd; + CHyprSignalListener swipeUpdate; - DYNLISTENER(pinchBegin); - DYNLISTENER(pinchEnd); - DYNLISTENER(pinchUpdate); + CHyprSignalListener pinchBegin; + CHyprSignalListener pinchEnd; + CHyprSignalListener pinchUpdate; - DYNLISTENER(holdBegin); - DYNLISTENER(holdEnd); + CHyprSignalListener holdBegin; + CHyprSignalListener holdEnd; + } listeners; }; \ No newline at end of file diff --git a/src/events/Devices.cpp b/src/events/Devices.cpp index fedc844e06c..752e51f7242 100644 --- a/src/events/Devices.cpp +++ b/src/events/Devices.cpp @@ -21,15 +21,15 @@ void Events::listener_newInput(wl_listener* listener, void* data) { switch (DEVICE->type) { case WLR_INPUT_DEVICE_KEYBOARD: Debug::log(LOG, "Attached a keyboard with name {}", DEVICE->name); - g_pInputManager->newKeyboard(DEVICE); + //g_pInputManager->newKeyboard(DEVICE); break; case WLR_INPUT_DEVICE_POINTER: Debug::log(LOG, "Attached a mouse with name {}", DEVICE->name); - g_pInputManager->newMouse(DEVICE); + //g_pInputManager->newMouse(DEVICE); break; case WLR_INPUT_DEVICE_TOUCH: Debug::log(LOG, "Attached a touch device with name {}", DEVICE->name); - g_pInputManager->newTouchDevice(DEVICE); + // g_pInputManager->newTouchDevice(DEVICE); break; case WLR_INPUT_DEVICE_TABLET: Debug::log(LOG, "Attached a tablet with name {}", DEVICE->name); diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 2536e1f748a..4217e27945a 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -16,88 +16,6 @@ // // // --------------------------------------------------------- // -static void checkDefaultCursorWarp(SP PNEWMONITOR, std::string monitorName) { - - static auto PCURSORMONITOR = CConfigValue("cursor:default_monitor"); - static auto firstMonitorAdded = std::chrono::steady_clock::now(); - static bool cursorDefaultDone = false; - static bool firstLaunch = true; - - const auto POS = PNEWMONITOR->middle(); - - // by default, cursor should be set to first monitor detected - // this is needed as a default if the monitor given in config above doesn't exist - if (firstLaunch) { - firstLaunch = false; - g_pCompositor->warpCursorTo(POS, true); - g_pInputManager->refocus(); - } - - if (cursorDefaultDone || *PCURSORMONITOR == STRVAL_EMPTY) - return; - - // after 10s, don't set cursor to default monitor - auto timePassedSec = std::chrono::duration_cast(std::chrono::steady_clock::now() - firstMonitorAdded); - if (timePassedSec.count() > 10) { - cursorDefaultDone = true; - return; - } - - if (*PCURSORMONITOR == monitorName) { - cursorDefaultDone = true; - g_pCompositor->warpCursorTo(POS, true); - g_pInputManager->refocus(); - } -} - -void Events::listener_newOutput(wl_listener* listener, void* data) { - // new monitor added, let's accommodate for that. - const auto OUTPUT = (wlr_output*)data; - - if (!OUTPUT->name) { - Debug::log(ERR, "New monitor has no name?? Ignoring"); - return; - } - - // add it to real - auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared()); - if (std::string("HEADLESS-1") == OUTPUT->name) - g_pCompositor->m_pUnsafeOutput = PNEWMONITOR.get(); - - PNEWMONITOR->output = OUTPUT; - PNEWMONITOR->self = PNEWMONITOR; - const bool FALLBACK = g_pCompositor->m_pUnsafeOutput ? OUTPUT == g_pCompositor->m_pUnsafeOutput->output : false; - PNEWMONITOR->ID = FALLBACK ? -1 : g_pCompositor->getNextAvailableMonitorID(OUTPUT->name); - PNEWMONITOR->isUnsafeFallback = FALLBACK; - - EMIT_HOOK_EVENT("newMonitor", PNEWMONITOR); - - if (!FALLBACK) - PNEWMONITOR->onConnect(false); - - if (!PNEWMONITOR->m_bEnabled || FALLBACK) - return; - - // ready to process if we have a real monitor - - if ((!g_pHyprRenderer->m_pMostHzMonitor || PNEWMONITOR->refreshRate > g_pHyprRenderer->m_pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled) - g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR.get(); - - g_pCompositor->m_bReadyToProcess = true; - - g_pConfigManager->m_bWantsMonitorReload = true; - g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get()); - - checkDefaultCursorWarp(PNEWMONITOR, OUTPUT->name); - - for (auto& w : g_pCompositor->m_vWindows) { - if (w->m_iMonitorID == PNEWMONITOR->ID) { - w->m_iLastSurfaceMonitorID = -1; - w->updateSurfaceScaleTransformDetails(); - } - } -} - void Events::listener_monitorFrame(void* owner, void* data) { if (g_pCompositor->m_bExitTriggered) { // Only signal cleanup once @@ -108,18 +26,19 @@ void Events::listener_monitorFrame(void* owner, void* data) { CMonitor* const PMONITOR = (CMonitor*)owner; - if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) { - Debug::log(WARN, "Attempted to render frame on inactive session!"); + // FIXME: + // if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) { + // Debug::log(WARN, "Attempted to render frame on inactive session!"); - if (g_pCompositor->m_bUnsafeState && std::ranges::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& m) { - return m->output != g_pCompositor->m_pUnsafeOutput->output; - })) { - // restore from unsafe state - g_pCompositor->leaveUnsafeState(); - } + // if (g_pCompositor->m_bUnsafeState && std::ranges::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& m) { + // return m->output != g_pCompositor->m_pUnsafeOutput->output; + // })) { + // // restore from unsafe state + // g_pCompositor->leaveUnsafeState(); + // } - return; // cannot draw on session inactive (different tty) - } + // return; // cannot draw on session inactive (different tty) + // } if (!PMONITOR->m_bEnabled) return; @@ -172,12 +91,10 @@ void Events::listener_monitorFrame(void* owner, void* data) { } void Events::listener_monitorDestroy(void* owner, void* data) { - const auto OUTPUT = (wlr_output*)data; - - CMonitor* pMonitor = nullptr; + CMonitor* pMonitor = nullptr; for (auto& m : g_pCompositor->m_vRealMonitors) { - if (m->output == OUTPUT) { + if (m->output == pMonitor->output) { pMonitor = m.get(); break; } @@ -188,9 +105,6 @@ void Events::listener_monitorDestroy(void* owner, void* data) { Debug::log(LOG, "Destroy called for monitor {}", pMonitor->output->name); - if (pMonitor->output->idle_frame) - wl_event_source_remove(pMonitor->output->idle_frame); - pMonitor->onDisconnect(true); pMonitor->output = nullptr; @@ -202,20 +116,20 @@ void Events::listener_monitorDestroy(void* owner, void* data) { } void Events::listener_monitorStateRequest(void* owner, void* data) { - const auto PMONITOR = (CMonitor*)owner; - const auto E = (wlr_output_event_request_state*)data; + // const auto PMONITOR = (CMonitor*)owner; + // const auto E = (wlr_output_event_request_state*)data; - if (!PMONITOR->createdByUser) - return; + // if (!PMONITOR->createdByUser) + // return; - const auto SIZE = E->state->mode ? Vector2D{E->state->mode->width, E->state->mode->height} : Vector2D{E->state->custom_mode.width, E->state->custom_mode.height}; + // const auto SIZE = E->state->mode ? Vector2D{E->state->mode->width, E->state->mode->height} : Vector2D{E->state->custom_mode.width, E->state->custom_mode.height}; - PMONITOR->forceSize = SIZE; + // PMONITOR->forceSize = SIZE; - SMonitorRule rule = PMONITOR->activeMonitorRule; - rule.resolution = SIZE; + // SMonitorRule rule = PMONITOR->activeMonitorRule; + // rule.resolution = SIZE; - g_pHyprRenderer->applyMonitorRule(PMONITOR, &rule); + // g_pHyprRenderer->applyMonitorRule(PMONITOR, &rule); } void Events::listener_monitorDamage(void* owner, void* data) { @@ -234,11 +148,9 @@ void Events::listener_monitorNeedsFrame(void* owner, void* data) { void Events::listener_monitorCommit(void* owner, void* data) { const auto PMONITOR = (CMonitor*)owner; - const auto E = (wlr_output_event_commit*)data; - - if (E->state->committed & WLR_OUTPUT_STATE_BUFFER) { - g_pProtocolManager->m_pScreencopyProtocolManager->onOutputCommit(PMONITOR, E); - g_pProtocolManager->m_pToplevelExportProtocolManager->onOutputCommit(PMONITOR, E); + if (true) { // FIXME: E->state->committed & WLR_OUTPUT_STATE_BUFFER + g_pProtocolManager->m_pScreencopyProtocolManager->onOutputCommit(PMONITOR); + g_pProtocolManager->m_pToplevelExportProtocolManager->onOutputCommit(PMONITOR); } } diff --git a/src/helpers/Format.hpp b/src/helpers/Format.hpp index a1ef53f51b0..c0dabdd5e61 100644 --- a/src/helpers/Format.hpp +++ b/src/helpers/Format.hpp @@ -19,7 +19,7 @@ struct SPixelFormat { }; struct SDRMFormat { - uint32_t format = 0; + DRMFormat format = 0; /* DRM_FORMAT_INVALID */ std::vector mods; }; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 20c2e81e5a3..2912d734414 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -6,6 +6,7 @@ #include "../devices/ITouch.hpp" #include "../protocols/LayerShell.hpp" #include "../protocols/PresentationTime.hpp" +#include "../protocols/core/Output.hpp" #include "../managers/PointerManager.hpp" #include using namespace Hyprutils::String; @@ -21,14 +22,6 @@ CMonitor::CMonitor() : state(this) { } CMonitor::~CMonitor() { - hyprListener_monitorDestroy.removeCallback(); - hyprListener_monitorFrame.removeCallback(); - hyprListener_monitorStateRequest.removeCallback(); - hyprListener_monitorDamage.removeCallback(); - hyprListener_monitorNeedsFrame.removeCallback(); - hyprListener_monitorCommit.removeCallback(); - hyprListener_monitorBind.removeCallback(); - events.destroy.emit(); } @@ -40,43 +33,48 @@ static void onPresented(void* owner, void* data) { } void CMonitor::onConnect(bool noRule) { - hyprListener_monitorDestroy.removeCallback(); - hyprListener_monitorFrame.removeCallback(); - hyprListener_monitorStateRequest.removeCallback(); - hyprListener_monitorDamage.removeCallback(); - hyprListener_monitorNeedsFrame.removeCallback(); - hyprListener_monitorCommit.removeCallback(); - hyprListener_monitorBind.removeCallback(); - hyprListener_monitorPresented.removeCallback(); - hyprListener_monitorFrame.initCallback(&output->events.frame, &Events::listener_monitorFrame, this, "CMonitor"); - hyprListener_monitorDestroy.initCallback(&output->events.destroy, &Events::listener_monitorDestroy, this, "CMonitor"); - hyprListener_monitorStateRequest.initCallback(&output->events.request_state, &Events::listener_monitorStateRequest, this, "CMonitor"); - hyprListener_monitorDamage.initCallback(&output->events.damage, &Events::listener_monitorDamage, this, "CMonitor"); - hyprListener_monitorNeedsFrame.initCallback(&output->events.needs_frame, &Events::listener_monitorNeedsFrame, this, "CMonitor"); - hyprListener_monitorCommit.initCallback(&output->events.commit, &Events::listener_monitorCommit, this, "CMonitor"); - hyprListener_monitorBind.initCallback(&output->events.bind, &Events::listener_monitorBind, this, "CMonitor"); - hyprListener_monitorPresented.initCallback(&output->events.present, ::onPresented, this, "CMonitor"); - - tearingState.canTear = wlr_backend_is_drm(output->backend); // tearing only works on drm + + listeners.frame = output->events.frame.registerListener([this](std::any d) { Events::listener_monitorFrame(this, nullptr); }); + listeners.destroy = output->events.destroy.registerListener([this](std::any d) { Events::listener_monitorDestroy(this, nullptr); }); + listeners.commit = output->events.commit.registerListener([this](std::any d) { Events::listener_monitorCommit(this, nullptr); }); + listeners.needsFrame = output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(this); }); + + listeners.state = output->events.state.registerListener([this](std::any d) { + if (!createdByUser) + return; + + auto E = std::any_cast(d); + + const auto SIZE = E.size; + + forceSize = SIZE; + + SMonitorRule rule = activeMonitorRule; + rule.resolution = SIZE; + + g_pHyprRenderer->applyMonitorRule(this, &rule); + }); + + tearingState.canTear = output->getBackend()->type() == Aquamarine::AQ_BACKEND_DRM; if (m_bEnabled) { - wlr_output_state_set_enabled(state.wlr(), true); + output->state->setEnabled(true); state.commit(); return; } szName = output->name; - szDescription = output->description ? output->description : ""; + szDescription = output->description; // remove comma character from description. This allow monitor specific rules to work on monitor with comma on their description std::erase(szDescription, ','); // field is backwards-compatible with intended usage of `szDescription` but excludes the parenthesized DRM node name suffix - szShortDescription = trim(std::format("{} {} {}", output->make ? output->make : "", output->model ? output->model : "", output->serial ? output->serial : "")); + szShortDescription = trim(std::format("{} {} {}", output->make, output->model, output->serial)); std::erase(szShortDescription, ','); - if (!wlr_backend_is_drm(output->backend)) - createdByUser = true; // should be true. WL, X11 and Headless backends should be addable / removable + if (output->getBackend()->type() != Aquamarine::AQ_BACKEND_DRM) + createdByUser = true; // should be true. WL and Headless backends should be addable / removable // get monitor rule that matches SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(*this); @@ -84,56 +82,26 @@ void CMonitor::onConnect(bool noRule) { // if it's disabled, disable and ignore if (monitorRule.disabled) { - wlr_output_state_set_scale(state.wlr(), 1); - wlr_output_state_set_transform(state.wlr(), WL_OUTPUT_TRANSFORM_NORMAL); - - auto PREFSTATE = wlr_output_preferred_mode(output); - - if (!PREFSTATE) { - wlr_output_mode* mode; - - wl_list_for_each(mode, &output->modes, link) { - wlr_output_state_set_mode(state.wlr(), mode); - - if (!wlr_output_test_state(output, state.wlr())) - continue; - - PREFSTATE = mode; - break; - } - } - - if (PREFSTATE) - wlr_output_state_set_mode(state.wlr(), PREFSTATE); - else - Debug::log(WARN, "No mode found for disabled output {}", output->name); - - wlr_output_state_set_enabled(state.wlr(), 0); + output->state->setEnabled(false); if (!state.commit()) Debug::log(ERR, "Couldn't commit disabled state on output {}", output->name); m_bEnabled = false; - hyprListener_monitorFrame.removeCallback(); + listeners.frame.reset(); return; } - if (output->non_desktop) { + if (output->nonDesktop) { Debug::log(LOG, "Not configuring non-desktop output"); - if (g_pCompositor->m_sWRLDRMLeaseMgr) { - wlr_drm_lease_v1_manager_offer_output(g_pCompositor->m_sWRLDRMLeaseMgr, output); - } + // TODO: + // if (g_pCompositor->m_sWRLDRMLeaseMgr) { + // wlr_drm_lease_v1_manager_offer_output(g_pCompositor->m_sWRLDRMLeaseMgr, output); + // } return; } - if (!m_bRenderingInitPassed) { - output->allocator = nullptr; - output->renderer = nullptr; - wlr_output_init_render(output, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer); - m_bRenderingInitPassed = true; - } - SP* thisWrapper = nullptr; // find the wrap @@ -151,7 +119,7 @@ void CMonitor::onConnect(bool noRule) { m_bEnabled = true; - wlr_output_state_set_enabled(state.wlr(), 1); + output->state->setEnabled(true); // set mode, also applies if (!noRule) @@ -261,12 +229,10 @@ void CMonitor::onDisconnect(bool destroy) { g_pConfigManager->m_bWantsMonitorReload = true; } - hyprListener_monitorFrame.removeCallback(); - hyprListener_monitorPresented.removeCallback(); - hyprListener_monitorDamage.removeCallback(); - hyprListener_monitorNeedsFrame.removeCallback(); - hyprListener_monitorCommit.removeCallback(); - hyprListener_monitorBind.removeCallback(); + listeners.frame.reset(); + listeners.presented.reset(); + listeners.needsFrame.reset(); + listeners.commit.reset(); for (size_t i = 0; i < 4; ++i) { for (auto& ls : m_aLayerSurfaceLayers[i]) { @@ -316,10 +282,10 @@ void CMonitor::onDisconnect(bool destroy) { activeWorkspace->m_bVisible = false; activeWorkspace.reset(); - wlr_output_state_set_enabled(state.wlr(), false); + output->state->setEnabled(false); if (!state.commit()) - Debug::log(WARN, "wlr_output_commit_state failed in CMonitor::onDisconnect"); + Debug::log(WARN, "state.commit() failed in CMonitor::onDisconnect"); if (g_pCompositor->m_pLastMonitor.get() == this) g_pCompositor->setActiveMonitor(BACKUPMON ? BACKUPMON : g_pCompositor->m_pUnsafeOutput); @@ -369,8 +335,8 @@ bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() { static auto PMINRR = CConfigValue("cursor:min_refresh_rate"); // skip scheduling extra frames for fullsreen apps with vrr - bool shouldSkip = *PNOBREAK && output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED && activeWorkspace && activeWorkspace->m_bHasFullscreenWindow && - activeWorkspace->m_efFullscreenMode == FULLSCREEN_FULL; + bool shouldSkip = + *PNOBREAK && output->state->state().adaptiveSync && activeWorkspace && activeWorkspace->m_bHasFullscreenWindow && activeWorkspace->m_efFullscreenMode == FULLSCREEN_FULL; // keep requested minimum refresh rate if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000 / *PMINRR) { @@ -563,7 +529,7 @@ float CMonitor::getDefaultScale() { static constexpr double MMPERINCH = 25.4; const auto DIAGONALPX = sqrt(pow(vecPixelSize.x, 2) + pow(vecPixelSize.y, 2)); - const auto DIAGONALIN = sqrt(pow(output->phys_width / MMPERINCH, 2) + pow(output->phys_height / MMPERINCH, 2)); + const auto DIAGONALIN = sqrt(pow(output->physicalSize.x / MMPERINCH, 2) + pow(output->physicalSize.y / MMPERINCH, 2)); const auto PPI = DIAGONALPX / DIAGONALIN; @@ -787,31 +753,35 @@ CBox CMonitor::logicalBox() { return {vecPosition, vecSize}; } -CMonitorState::CMonitorState(CMonitor* owner) { - m_pOwner = owner; - wlr_output_state_init(&m_state); +static void onDoneSource(void* data) { + auto pMonitor = (CMonitor*)data; + + if (!PROTO::outputs.contains(pMonitor->szName)) + return; + + PROTO::outputs.at(pMonitor->szName)->sendDone(); } -CMonitorState::~CMonitorState() { - wlr_output_state_finish(&m_state); +void CMonitor::scheduleDone() { + if (doneSource) + return; + + doneSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, ::onDoneSource, this); } -wlr_output_state* CMonitorState::wlr() { - return &m_state; +CMonitorState::CMonitorState(CMonitor* owner) { + m_pOwner = owner; } -void CMonitorState::clear() { - wlr_output_state_finish(&m_state); - m_state = {0}; - wlr_output_state_init(&m_state); +CMonitorState::~CMonitorState() { + ; } bool CMonitorState::commit() { - bool ret = wlr_output_commit_state(m_pOwner->output, &m_state); - clear(); + bool ret = m_pOwner->output->commit(); return ret; } bool CMonitorState::test() { - return wlr_output_test_state(m_pOwner->output, &m_state); + return m_pOwner->output->test(); } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 8a2acdaf0a1..87c73a148df 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -12,6 +12,8 @@ #include #include "signal/Signal.hpp" #include "DamageRing.hpp" +#include +#include // Enum for the different types of auto directions, e.g. auto-left, auto-up. enum eAutoDirs { @@ -45,15 +47,11 @@ class CMonitorState { CMonitorState(CMonitor* owner); ~CMonitorState(); - wlr_output_state* wlr(); - void clear(); - // commit() will also clear() bool commit(); bool test(); private: - wlr_output_state m_state = {0}; - CMonitor* m_pOwner; + CMonitor* m_pOwner; }; class CMonitor { @@ -61,61 +59,62 @@ class CMonitor { CMonitor(); ~CMonitor(); - Vector2D vecPosition = Vector2D(-1, -1); // means unset - Vector2D vecXWaylandPosition = Vector2D(-1, -1); // means unset - Vector2D vecSize = Vector2D(0, 0); - Vector2D vecPixelSize = Vector2D(0, 0); - Vector2D vecTransformedSize = Vector2D(0, 0); + Vector2D vecPosition = Vector2D(-1, -1); // means unset + Vector2D vecXWaylandPosition = Vector2D(-1, -1); // means unset + Vector2D vecSize = Vector2D(0, 0); + Vector2D vecPixelSize = Vector2D(0, 0); + Vector2D vecTransformedSize = Vector2D(0, 0); - bool primary = false; + bool primary = false; - uint64_t ID = -1; - PHLWORKSPACE activeWorkspace = nullptr; - PHLWORKSPACE activeSpecialWorkspace = nullptr; - float setScale = 1; // scale set by cfg - float scale = 1; // real scale + uint64_t ID = -1; + PHLWORKSPACE activeWorkspace = nullptr; + PHLWORKSPACE activeSpecialWorkspace = nullptr; + float setScale = 1; // scale set by cfg + float scale = 1; // real scale - std::string szName = ""; - std::string szDescription = ""; - std::string szShortDescription = ""; + std::string szName = ""; + std::string szDescription = ""; + std::string szShortDescription = ""; - Vector2D vecReservedTopLeft = Vector2D(0, 0); - Vector2D vecReservedBottomRight = Vector2D(0, 0); + Vector2D vecReservedTopLeft = Vector2D(0, 0); + Vector2D vecReservedBottomRight = Vector2D(0, 0); - drmModeModeInfo customDrmMode = {}; + drmModeModeInfo customDrmMode = {}; - CMonitorState state; - CDamageRing damage; + CMonitorState state; + CDamageRing damage; - wlr_output* output = nullptr; - float refreshRate = 60; - int framesToSkip = 0; - int forceFullFrames = 0; - bool noFrameSchedule = false; - bool scheduledRecalc = false; - wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; - float xwaylandScale = 1.f; - std::array projMatrix = {0}; - std::optional forceSize; - wlr_output_mode* currentMode = nullptr; + SP output; + float refreshRate = 60; + int framesToSkip = 0; + int forceFullFrames = 0; + bool noFrameSchedule = false; + bool scheduledRecalc = false; + wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; + float xwaylandScale = 1.f; + std::array projMatrix = {0}; + std::optional forceSize; + SP currentMode; + SP cursorSwapchain; - bool dpmsStatus = true; - bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. - bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed. - bool createdByUser = false; - uint32_t drmFormat = DRM_FORMAT_INVALID; - bool isUnsafeFallback = false; + bool dpmsStatus = true; + bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. + bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed. + bool createdByUser = false; + uint32_t drmFormat = DRM_FORMAT_INVALID; + bool isUnsafeFallback = false; - bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after - bool renderingActive = false; + bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after + bool renderingActive = false; - wl_event_source* renderTimer = nullptr; // for RAT - bool RATScheduled = false; - CTimer lastPresentationTimer; + wl_event_source* renderTimer = nullptr; // for RAT + bool RATScheduled = false; + CTimer lastPresentationTimer; - SMonitorRule activeMonitorRule; + SMonitorRule activeMonitorRule; - WP self; + WP self; // mirroring CMonitor* pMirrorOf = nullptr; @@ -143,15 +142,6 @@ class CMonitor { std::array, 4> m_aLayerSurfaceLayers; - DYNLISTENER(monitorFrame); - DYNLISTENER(monitorDestroy); - DYNLISTENER(monitorStateRequest); - DYNLISTENER(monitorDamage); - DYNLISTENER(monitorNeedsFrame); - DYNLISTENER(monitorCommit); - DYNLISTENER(monitorBind); - DYNLISTENER(monitorPresented); - // methods void onConnect(bool noRule); void onDisconnect(bool destroy = false); @@ -173,6 +163,7 @@ class CMonitor { int64_t activeWorkspaceID(); int64_t activeSpecialWorkspaceID(); CBox logicalBox(); + void scheduleDone(); bool m_bEnabled = false; bool m_bRenderingInitPassed = false; @@ -184,6 +175,17 @@ class CMonitor { } private: - void setupDefaultWS(const SMonitorRule&); - int findAvailableDefaultWS(); + void setupDefaultWS(const SMonitorRule&); + int findAvailableDefaultWS(); + + wl_event_source* doneSource = nullptr; + + struct { + CHyprSignalListener frame; + CHyprSignalListener destroy; + CHyprSignalListener state; + CHyprSignalListener needsFrame; + CHyprSignalListener presented; + CHyprSignalListener commit; + } listeners; }; diff --git a/src/macros.hpp b/src/macros.hpp index f1393cbd796..b2adb03698f 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -105,3 +105,8 @@ class name; \ } \ } + +#define AQUAMARINE_FORWARD(name) \ + namespace Aquamarine { \ + class name; \ + } diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index daa4f4be953..5a14ec3ac8f 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -67,54 +67,61 @@ void CCursorManager::dropBufferRef(CCursorManager::CCursorBuffer* ref) { std::erase_if(m_vCursorBuffers, [ref](const auto& buf) { return buf.get() == ref; }); } -static void cursorBufferDestroy(struct wlr_buffer* wlr_buffer) { - CCursorManager::CCursorBuffer::SCursorWlrBuffer* buffer = wl_container_of(wlr_buffer, buffer, base); - g_pCursorManager->dropBufferRef(buffer->parent); +CCursorManager::CCursorBuffer::CCursorBuffer(cairo_surface_t* surf, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) { + surface = surf; + size = size_; + stride = cairo_image_surface_get_stride(surf); } -static bool cursorBufferBeginDataPtr(struct wlr_buffer* wlr_buffer, uint32_t flags, void** data, uint32_t* format, size_t* stride) { - CCursorManager::CCursorBuffer::SCursorWlrBuffer* buffer = wl_container_of(wlr_buffer, buffer, base); +CCursorManager::CCursorBuffer::CCursorBuffer(uint8_t* pixelData_, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) { + pixelData = pixelData_; + size = size_; + stride = 4 * size_.x; +} + +CCursorManager::CCursorBuffer::~CCursorBuffer() { + ; +} - if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) - return false; +Aquamarine::eBufferCapability CCursorManager::CCursorBuffer::caps() { + return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR; +} - *data = buffer->pixelData ? buffer->pixelData : cairo_image_surface_get_data(buffer->surface); - *stride = buffer->stride; - *format = DRM_FORMAT_ARGB8888; - return true; +Aquamarine::eBufferType CCursorManager::CCursorBuffer::type() { + return Aquamarine::eBufferType::BUFFER_TYPE_SHM; } -static void cursorBufferEndDataPtr(struct wlr_buffer* wlr_buffer) { +void CCursorManager::CCursorBuffer::update(const Hyprutils::Math::CRegion& damage) { ; } -// -static const wlr_buffer_impl bufferImpl = { - .destroy = cursorBufferDestroy, - .begin_data_ptr_access = cursorBufferBeginDataPtr, - .end_data_ptr_access = cursorBufferEndDataPtr, -}; - -CCursorManager::CCursorBuffer::CCursorBuffer(cairo_surface_t* surf, const Vector2D& size_, const Vector2D& hot_) : size(size_), hotspot(hot_) { - wlrBuffer.surface = surf; - wlr_buffer_init(&wlrBuffer.base, &bufferImpl, size.x, size.y); - wlrBuffer.parent = this; - wlrBuffer.stride = cairo_image_surface_get_stride(surf); +bool CCursorManager::CCursorBuffer::isSynchronous() { + return true; } -CCursorManager::CCursorBuffer::CCursorBuffer(uint8_t* pixelData, const Vector2D& size_, const Vector2D& hot_) : size(size_), hotspot(hot_) { - wlrBuffer.pixelData = pixelData; - wlr_buffer_init(&wlrBuffer.base, &bufferImpl, size.x, size.y); - wlrBuffer.parent = this; - wlrBuffer.stride = 4 * size_.x; +bool CCursorManager::CCursorBuffer::good() { + return true; } -CCursorManager::CCursorBuffer::~CCursorBuffer() { - ; // will be freed in .destroy +Aquamarine::SSHMAttrs CCursorManager::CCursorBuffer::shm() { + Aquamarine::SSHMAttrs attrs; + attrs.success = true; + attrs.format = DRM_FORMAT_ARGB8888; + attrs.size = size; + attrs.stride = stride; + return attrs; +} + +std::tuple CCursorManager::CCursorBuffer::beginDataPtr(uint32_t flags) { + return {pixelData ? pixelData : cairo_image_surface_get_data(surface), DRM_FORMAT_ARGB8888, stride}; +} + +void CCursorManager::CCursorBuffer::endDataPtr() { + ; } -wlr_buffer* CCursorManager::getCursorBuffer() { - return !m_vCursorBuffers.empty() ? &m_vCursorBuffers.back()->wlrBuffer.base : nullptr; +SP CCursorManager::getCursorBuffer() { + return !m_vCursorBuffers.empty() ? m_vCursorBuffers.back() : nullptr; } void CCursorManager::setCursorSurface(SP surf, const Vector2D& hotspot) { @@ -150,11 +157,11 @@ void CCursorManager::setXCursor(const std::string& name) { auto image = xcursor->images[0]; m_vCursorBuffers.emplace_back( - std::make_unique(image->buffer, Vector2D{(int)image->width, (int)image->height}, Vector2D{(double)image->hotspot_x, (double)image->hotspot_y})); + makeShared(image->buffer, Vector2D{(int)image->width, (int)image->height}, Vector2D{(double)image->hotspot_x, (double)image->hotspot_y})); g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{(double)image->hotspot_x, (double)image->hotspot_y} / scale, scale); if (m_vCursorBuffers.size() > 1) - wlr_buffer_drop(&m_vCursorBuffers.front()->wlrBuffer.base); + dropBufferRef(m_vCursorBuffers.at(0).get()); m_bOurBufferConnected = true; } @@ -196,14 +203,14 @@ void CCursorManager::setCursorFromName(const std::string& name) { } } - m_vCursorBuffers.emplace_back(std::make_unique(m_sCurrentCursorShapeData.images[0].surface, - Vector2D{m_sCurrentCursorShapeData.images[0].size, m_sCurrentCursorShapeData.images[0].size}, - Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY})); + m_vCursorBuffers.emplace_back(makeShared(m_sCurrentCursorShapeData.images[0].surface, + Vector2D{m_sCurrentCursorShapeData.images[0].size, m_sCurrentCursorShapeData.images[0].size}, + Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY})); g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY} / m_fCursorScale, m_fCursorScale); if (m_vCursorBuffers.size() > 1) - wlr_buffer_drop(&m_vCursorBuffers.front()->wlrBuffer.base); + dropBufferRef(m_vCursorBuffers.at(0).get()); m_bOurBufferConnected = true; @@ -225,7 +232,7 @@ void CCursorManager::tickAnimatedCursor() { if ((size_t)m_iCurrentAnimationFrame >= m_sCurrentCursorShapeData.images.size()) m_iCurrentAnimationFrame = 0; - m_vCursorBuffers.emplace_back(std::make_unique( + m_vCursorBuffers.emplace_back(makeShared( m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].surface, Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size}, Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY})); diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index 3ee98ca6823..6a042743c5b 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -7,46 +7,49 @@ #include "../helpers/math/Math.hpp" #include "../helpers/memory/Memory.hpp" -struct wlr_buffer; struct wlr_xcursor_manager; class CWLSurface; +AQUAMARINE_FORWARD(IBuffer); + class CCursorManager { public: CCursorManager(); ~CCursorManager(); - wlr_buffer* getCursorBuffer(); + SP getCursorBuffer(); - void setCursorFromName(const std::string& name); - void setCursorSurface(SP surf, const Vector2D& hotspot); - void setXCursor(const std::string& name); + void setCursorFromName(const std::string& name); + void setCursorSurface(SP surf, const Vector2D& hotspot); + void setXCursor(const std::string& name); - bool changeTheme(const std::string& name, const int size); - void updateTheme(); - SCursorImageData dataFor(const std::string& name); // for xwayland - void setXWaylandCursor(); + bool changeTheme(const std::string& name, const int size); + void updateTheme(); + SCursorImageData dataFor(const std::string& name); // for xwayland + void setXWaylandCursor(); - void tickAnimatedCursor(); + void tickAnimatedCursor(); - class CCursorBuffer { + class CCursorBuffer : public Aquamarine::IBuffer { public: CCursorBuffer(cairo_surface_t* surf, const Vector2D& size, const Vector2D& hotspot); CCursorBuffer(uint8_t* pixelData, const Vector2D& size, const Vector2D& hotspot); ~CCursorBuffer(); - struct SCursorWlrBuffer { - wlr_buffer base; - cairo_surface_t* surface = nullptr; - bool dropped = false; - CCursorBuffer* parent = nullptr; - uint8_t* pixelData = nullptr; - size_t stride = 0; - } wlrBuffer; + virtual Aquamarine::eBufferCapability caps(); + virtual Aquamarine::eBufferType type(); + virtual void update(const Hyprutils::Math::CRegion& damage); + virtual bool isSynchronous(); // whether the updates to this buffer are synchronous, aka happen over cpu + virtual bool good(); + virtual Aquamarine::SSHMAttrs shm(); + virtual std::tuple beginDataPtr(uint32_t flags); + virtual void endDataPtr(); private: - Vector2D size; - Vector2D hotspot; + Vector2D hotspot; + cairo_surface_t* surface = nullptr; + uint8_t* pixelData = nullptr; + size_t stride = 0; friend class CCursorManager; }; @@ -56,7 +59,7 @@ class CCursorManager { bool m_bOurBufferConnected = false; private: - std::vector> m_vCursorBuffers; + std::vector> m_vCursorBuffers; std::unique_ptr m_pHyprcursor; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index eb8a3232a7d..54c13f87499 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -367,7 +367,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { const auto KEYCODE = e.keycode + 8; // Because to xkbcommon it's +8 from libinput const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbTranslationState : m_pXKBTranslationState, KEYCODE); - const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->wlr()->xkb_state, KEYCODE); + const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->xkbInternalTranslationState, KEYCODE); if (handleInternalKeybinds(internalKeysym)) return true; @@ -554,7 +554,7 @@ int repeatKeyHandler(void* data) { Debug::log(LOG, "Keybind repeat triggered, calling dispatcher."); DISPATCHER->second((*ppActiveKeybind)->arg); - wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pSeatManager->keyboard->wlr()->repeat_info.rate); + wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pSeatManager->keyboard->repeatRate); return 0; } @@ -786,7 +786,7 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) { // beyond this point, return true to not handle anything else. // we'll avoid printing shit to active windows. - if (g_pCompositor->m_sWLRSession) { + if (g_pCompositor->m_pAqBackend->hasSession()) { const unsigned int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1; // vtnr is bugged for some reason. @@ -810,7 +810,8 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) { Debug::log(LOG, "Switching from VT {} to VT {}", ttynum, TTY); - wlr_session_change_vt(g_pCompositor->m_sWLRSession, TTY); + // FIXME: + //wlr_session_change_vt(g_pCompositor->m_sWLRSession, TTY); return true; } @@ -2121,7 +2122,7 @@ void CKeybindManager::sendshortcut(std::string args) { const auto KEYPAIRSTRING = std::format("{}{}", (uintptr_t)KB.get(), KEY); if (!g_pKeybindManager->m_mKeyToCodeCache.contains(KEYPAIRSTRING)) { - xkb_keymap* km = KB->wlr()->keymap; + xkb_keymap* km = KB->xkbKeymap; xkb_state* ks = KB->xkbTranslationState; xkb_keycode_t keycode_min, keycode_max; @@ -2259,7 +2260,7 @@ void CKeybindManager::dpms(std::string arg) { if (!port.empty() && m->szName != port) continue; - wlr_output_state_set_enabled(m->state.wlr(), enable); + m->output->state->setEnabled(enable); m->dpmsStatus = enable; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 7090645fc99..0b52d1328a3 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -10,128 +10,26 @@ #include #include -// 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); +static Aquamarine::SDRMFormat pickCursorFormat(SP output) { - 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 auto fmts = output->getBackend()->getCursorFormats(); - 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; - } + if (fmts.empty()) + return {}; - 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; - } + // try to use common formats in their order + std::vector PREFERRED_FORMATS = {DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888}; - 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); + for (auto& pf : PREFERRED_FORMATS) { + for (auto& fmt : fmts) { + if (pf != fmt.drmFormat) + continue; - 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; + return fmt; } } - // 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; + return fmts.at(0); } CPointerManager::CPointerManager() { @@ -201,6 +99,11 @@ void CPointerManager::unlockSoftwareForMonitor(SP mon) { updateCursorBackend(); } +bool CPointerManager::softwareLockedFor(SP mon) { + auto state = stateFor(mon); + return state->softwareLocks > 0 || state->hardwareFailed; +} + Vector2D CPointerManager::position() { return pointerPos; } @@ -216,7 +119,7 @@ SP CPointerManager::stateFor(SP return *it; } -void CPointerManager::setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, const float& scale) { +void CPointerManager::setCursorBuffer(SP buf, const Vector2D& hotspot, const float& scale) { damageIfSoftware(); if (buf == currentCursorImage.pBuffer) { if (hotspot != currentCursorImage.hotspot || scale != currentCursorImage.scale) { @@ -232,10 +135,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 +218,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 +240,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 +266,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 +313,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 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 +354,68 @@ bool CPointerManager::attemptHardwareCursor(SP state, wlr_buffer* buf) { - if (!state->monitor->output->impl->set_cursor) +bool CPointerManager::setHWCursorBuffer(SP state, SP 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); - return true; } -wlr_buffer* CPointerManager::renderHWCursorBuffer(SP state, SP texture) { +SP CPointerManager::renderHWCursorBuffer(SP state, SP 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->maxCursorSize(); + + 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); + if (cursorSize == Vector2D{}) + return nullptr; + + // error + if (maxSize == Vector2D{}) + return nullptr; + + 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; } } - if (w <= 0 || h <= 0) { - Debug::log(TRACE, "hw cursor for output {} failed the size checks ({}x{} is invalid)", state->monitor->szName, w, h); - return nullptr; - } + if (!state->monitor->cursorSwapchain || cursorSize != state->monitor->cursorSwapchain->currentOptions().size) { + auto format = pickCursorFormat(output); - 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 (format.drmFormat == DRM_FORMAT_INVALID) { + Debug::log(TRACE, "Failed to pick an output format for hw cursor"); return nullptr; } - 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 = makeShared(g_pCompositor->m_pAqBackend->allocator); - if (!output->cursor_swapchain) { - Debug::log(TRACE, "Failed to create cursor swapchain"); + auto options = state->monitor->cursorSwapchain->currentOptions(); + options.size = cursorSize; + options.length = 2; + options.format = format.drmFormat; + + 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 +424,16 @@ wlr_buffer* CPointerManager::renderHWCursorBuffer(SPmakeEGLCurrent(); - g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get(); // has to be set cuz allocs + g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get(); - const auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, DRM_FORMAT_ARGB8888); + const auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format); 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); @@ -545,8 +444,6 @@ wlr_buffer* CPointerManager::renderHWCursorBuffer(SPonRenderbufferDestroy(RBO); - wlr_buffer_unlock(buf); - return buf; } @@ -593,11 +490,12 @@ Vector2D CPointerManager::getCursorPosForMonitor(SP pMonitor) { } Vector2D CPointerManager::transformedHotspot(SP 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(wlr_output_transform_invert(pMonitor->transform)), pMonitor->cursorSwapchain->currentOptions().size.x, + pMonitor->cursorSwapchain->currentOptions().size.y) .pos(); } @@ -799,10 +697,8 @@ SP 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(currentCursorImage.pBufferTexture); - } + if (!currentCursorImage.bufferTex) + currentCursorImage.bufferTex = makeShared(currentCursorImage.pBuffer); return currentCursorImage.bufferTex; } diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index da639340e1e..68596ab7c5a 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -9,10 +9,11 @@ #include class CMonitor; -struct wlr_input_device; class IHID; class CTexture; +AQUAMARINE_FORWARD(IBuffer); + /* The naming here is a bit confusing. CPointerManager manages the _position_ and _displaying_ of the cursor, @@ -37,7 +38,7 @@ class CPointerManager { void move(const Vector2D& deltaLogical); void warpAbsolute(Vector2D abs, SP dev); - void setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, const float& scale); + void setCursorBuffer(SP buf, const Vector2D& hotspot, const float& scale); void setCursorSurface(SP buf, const Vector2D& hotspot); void resetCursorImage(bool apply = true); @@ -47,6 +48,7 @@ class CPointerManager { void unlockSoftwareForMonitor(CMonitor* pMonitor); void lockSoftwareAll(); void unlockSoftwareAll(); + bool softwareLockedFor(SP pMonitor); void renderSoftwareCursorsFor(SP pMonitor, timespec* now, CRegion& damage /* logical */, std::optional overridePos = {} /* monitor-local */); @@ -135,45 +137,40 @@ class CPointerManager { } currentMonitorLayout; struct { - wlr_buffer* pBuffer = nullptr; - SP bufferTex; - WP surface; - wlr_texture* pBufferTexture = nullptr; - - Vector2D hotspot; - Vector2D size; - float scale = 1.F; - - CHyprSignalListener destroySurface; - CHyprSignalListener commitSurface; - DYNLISTENER(destroyBuffer); + SP pBuffer; + SP bufferTex; + WP surface; + + Vector2D hotspot; + Vector2D size; + float scale = 1.F; + + CHyprSignalListener destroySurface; + CHyprSignalListener commitSurface; } currentCursorImage; // TODO: support various sizes per-output so we can have pixel-perfect cursors Vector2D pointerPos = {0, 0}; struct SMonitorPointerState { SMonitorPointerState(SP m) : monitor(m) {} - ~SMonitorPointerState() { - if (cursorFrontBuffer) - wlr_buffer_unlock(cursorFrontBuffer); - } + ~SMonitorPointerState() {} - WP monitor; + WP monitor; - int softwareLocks = 0; - bool hardwareFailed = false; - CBox box; // logical - bool entered = false; - bool hwApplied = false; + int softwareLocks = 0; + bool hardwareFailed = false; + CBox box; // logical + bool entered = false; + bool hwApplied = false; - wlr_buffer* cursorFrontBuffer = nullptr; + SP cursorFrontBuffer; }; std::vector> monitorStates; SP stateFor(SP mon); bool attemptHardwareCursor(SP state); - wlr_buffer* renderHWCursorBuffer(SP state, SP texture); - bool setHWCursorBuffer(SP state, wlr_buffer* buf); + SP renderHWCursorBuffer(SP state, SP texture); + bool setHWCursorBuffer(SP state, SP buf); struct { SP monitorAdded; diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp index 6589c4bf9fe..801ae55adf1 100644 --- a/src/managers/SeatManager.cpp +++ b/src/managers/SeatManager.cpp @@ -94,8 +94,8 @@ void CSeatManager::setKeyboard(SP KEEB) { } void CSeatManager::updateActiveKeyboardData() { - if (keyboard && keyboard->wlr()) - PROTO::seat->updateRepeatInfo(keyboard->wlr()->repeat_info.rate, keyboard->wlr()->repeat_info.delay); + if (keyboard) + PROTO::seat->updateRepeatInfo(keyboard->repeatRate, keyboard->repeatDelay); PROTO::seat->updateKeymap(); } @@ -103,7 +103,7 @@ void CSeatManager::setKeyboardFocus(SP surf) { if (state.keyboardFocus == surf) return; - if (!keyboard || !keyboard->wlr()) { + if (!keyboard) { Debug::log(ERR, "BUG THIS: setKeyboardFocus without a valid keyboard set"); return; } @@ -144,7 +144,7 @@ void CSeatManager::setKeyboardFocus(SP surf) { continue; k->sendEnter(surf); - k->sendMods(keyboard->wlr()->modifiers.depressed, keyboard->wlr()->modifiers.latched, keyboard->wlr()->modifiers.locked, keyboard->wlr()->modifiers.group); + k->sendMods(keyboard->modifiersState.depressed, keyboard->modifiersState.latched, keyboard->modifiersState.locked, keyboard->modifiersState.group); } } @@ -196,7 +196,7 @@ void CSeatManager::setPointerFocus(SP surf, const Vector2D& return; } - if (!mouse || !mouse->wlr()) { + if (!mouse) { Debug::log(ERR, "BUG THIS: setPointerFocus without a valid mouse set"); return; } diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index 0d1b02239e7..dd52b9681d8 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -1,5 +1,6 @@ #include "EventLoopManager.hpp" #include "../../debug/Log.hpp" +#include "../../Compositor.hpp" #include #include @@ -25,9 +26,19 @@ static int timerWrite(int fd, uint32_t mask, void* data) { return 1; } +static int aquamarineFDWrite(int fd, uint32_t mask, void* data) { + g_pCompositor->m_pAqBackend->dispatchEventsAsync(); + return 1; +} + void CEventLoopManager::enterLoop() { m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd, WL_EVENT_READABLE, timerWrite, nullptr); + auto aqFDs = g_pCompositor->m_pAqBackend->getPollFDs(); + for (auto& fd : aqFDs) { + m_sWayland.aqEventSources.emplace_back(wl_event_loop_add_fd(m_sWayland.loop, fd, WL_EVENT_READABLE, aquamarineFDWrite, nullptr)); + } + wl_display_run(m_sWayland.display); Debug::log(LOG, "Kicked off the event loop! :("); diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp index 0b2f9578046..7758bdf62a8 100644 --- a/src/managers/eventLoop/EventLoopManager.hpp +++ b/src/managers/eventLoop/EventLoopManager.hpp @@ -33,9 +33,10 @@ class CEventLoopManager { private: struct { - wl_event_loop* loop = nullptr; - wl_display* display = nullptr; - wl_event_source* eventSource = nullptr; + wl_event_loop* loop = nullptr; + wl_display* display = nullptr; + wl_event_source* eventSource = nullptr; + std::vector aqEventSources; } m_sWayland; struct { diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 23e183d050d..6388327c62c 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -28,6 +28,8 @@ #include "../../managers/PointerManager.hpp" #include "../../managers/SeatManager.hpp" +#include + CInputManager::CInputManager() { m_sListeners.setCursorShape = PROTO::cursorShape->events.setShape.registerListener([this](std::any data) { if (!cursorImageUnlocked()) @@ -189,7 +191,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { bool skipFrameSchedule = PMONITOR->shouldSkipScheduleFrameOnMouseEvent(); - if (!PMONITOR->solitaryClient.lock() && g_pHyprRenderer->shouldRenderCursor() && PMONITOR->output->software_cursor_locks > 0 && !skipFrameSchedule) + if (!PMONITOR->solitaryClient.lock() && g_pHyprRenderer->shouldRenderCursor() && g_pPointerManager->softwareLockedFor(PMONITOR->self.lock()) && !skipFrameSchedule) g_pCompositor->scheduleFrameForMonitor(PMONITOR); PHLWINDOW forcedFocus = m_pForcedFocus.lock(); @@ -372,7 +374,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords, &pFoundLayerSurface); - if (g_pCompositor->m_pLastMonitor->output->software_cursor_locks > 0 && !skipFrameSchedule) + if (g_pPointerManager->softwareLockedFor(PMONITOR->self.lock()) > 0 && !skipFrameSchedule) g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get()); // grabs @@ -843,8 +845,8 @@ Vector2D CInputManager::getMouseCoordsInternal() { return g_pPointerManager->position(); } -void CInputManager::newKeyboard(wlr_input_device* keyboard) { - const auto PNEWKEYBOARD = m_vKeyboards.emplace_back(CKeyboard::create(wlr_keyboard_from_input_device(keyboard))); +void CInputManager::newKeyboard(SP keyboard) { + const auto PNEWKEYBOARD = m_vKeyboards.emplace_back(CKeyboard::create(keyboard)); setupKeyboard(PNEWKEYBOARD); @@ -856,14 +858,14 @@ void CInputManager::newVirtualKeyboard(SP keyboard) setupKeyboard(PNEWKEYBOARD); - Debug::log(LOG, "New virtual keyboard created, pointers Hypr: {:x} and WLR: {:x}", (uintptr_t)PNEWKEYBOARD.get(), (uintptr_t)keyboard->wlr()); + Debug::log(LOG, "New virtual keyboard created at {:x}", (uintptr_t)PNEWKEYBOARD.get()); } void CInputManager::setupKeyboard(SP keeb) { m_vHIDs.push_back(keeb); try { - keeb->hlName = getNameForNewDevice(keeb->wlr()->base.name); + keeb->hlName = getNameForNewDevice(keeb->deviceName); } catch (std::exception& e) { Debug::log(ERR, "Keyboard had no name???"); // logic error } @@ -962,83 +964,12 @@ void CInputManager::applyConfigToKeyboard(SP pKeyboard) { // we can ignore those and just apply } - wlr_keyboard_set_repeat_info(pKeyboard->wlr(), std::max(0, REPEATRATE), std::max(0, REPEATDELAY)); - - pKeyboard->repeatDelay = REPEATDELAY; - pKeyboard->repeatRate = REPEATRATE; + pKeyboard->repeatRate = std::max(0, REPEATRATE); + pKeyboard->repeatDelay = std::max(0, REPEATDELAY); pKeyboard->numlockOn = NUMLOCKON; pKeyboard->xkbFilePath = FILEPATH; - xkb_rule_names rules = {.rules = RULES.c_str(), .model = MODEL.c_str(), .layout = LAYOUT.c_str(), .variant = VARIANT.c_str(), .options = OPTIONS.c_str()}; - - pKeyboard->currentRules.rules = RULES; - pKeyboard->currentRules.model = MODEL; - pKeyboard->currentRules.variant = VARIANT; - pKeyboard->currentRules.options = OPTIONS; - pKeyboard->currentRules.layout = LAYOUT; - - const auto CONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - - if (!CONTEXT) { - Debug::log(ERR, "applyConfigToKeyboard: CONTEXT null??"); - return; - } - - Debug::log(LOG, "Attempting to create a keymap for layout {} with variant {} (rules: {}, model: {}, options: {})", rules.layout, rules.variant, rules.rules, rules.model, - rules.options); - - xkb_keymap* KEYMAP = NULL; - - if (!FILEPATH.empty()) { - auto path = absolutePath(FILEPATH, g_pConfigManager->configCurrentPath); - - if (FILE* const KEYMAPFILE = fopen(path.c_str(), "r"); !KEYMAPFILE) - Debug::log(ERR, "Cannot open input:kb_file= file for reading"); - else { - KEYMAP = xkb_keymap_new_from_file(CONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); - fclose(KEYMAPFILE); - } - } - - if (!KEYMAP) - KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); - - if (!KEYMAP) { - g_pConfigManager->addParseError("Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS + - ", layout: " + LAYOUT + " )"); - - Debug::log(ERR, "Keyboard layout {} with variant {} (rules: {}, model: {}, options: {}) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, - rules.options); - memset(&rules, 0, sizeof(rules)); - - pKeyboard->currentRules.rules = ""; - pKeyboard->currentRules.model = ""; - pKeyboard->currentRules.variant = ""; - pKeyboard->currentRules.options = ""; - pKeyboard->currentRules.layout = "us"; - - KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); - } - - wlr_keyboard_set_keymap(pKeyboard->wlr(), KEYMAP); - - pKeyboard->updateXKBTranslationState(); - - wlr_keyboard_modifiers wlrMods = {0}; - - if (NUMLOCKON == 1) { - // lock numlock - const auto IDX = xkb_map_mod_get_index(KEYMAP, XKB_MOD_NAME_NUM); - - if (IDX != XKB_MOD_INVALID) - wlrMods.locked |= (uint32_t)1 << IDX; - } - - if (wlrMods.locked != 0) - wlr_keyboard_notify_modifiers(pKeyboard->wlr(), 0, 0, wlrMods.locked, 0); - - xkb_keymap_unref(KEYMAP); - xkb_context_unref(CONTEXT); + pKeyboard->setKeymap(IKeyboard::SStringRuleNames{LAYOUT, MODEL, VARIANT, OPTIONS, RULES}); const auto LAYOUTSTR = pKeyboard->getActiveLayout(); @@ -1053,11 +984,11 @@ void CInputManager::newVirtualMouse(SP mouse) { setupMouse(PMOUSE); - Debug::log(LOG, "New virtual mouse created, pointer WLR: {:x}", (uintptr_t)mouse->wlr()); + Debug::log(LOG, "New virtual mouse created"); } -void CInputManager::newMouse(wlr_input_device* mouse) { - const auto PMOUSE = m_vPointers.emplace_back(CMouse::create(wlr_pointer_from_input_device(mouse))); +void CInputManager::newMouse(SP mouse) { + const auto PMOUSE = m_vPointers.emplace_back(CMouse::create(mouse)); setupMouse(PMOUSE); @@ -1068,13 +999,13 @@ void CInputManager::setupMouse(SP mauz) { m_vHIDs.push_back(mauz); try { - mauz->hlName = getNameForNewDevice(mauz->wlr()->base.name); + mauz->hlName = getNameForNewDevice(mauz->deviceName); } catch (std::exception& e) { Debug::log(ERR, "Mouse had no name???"); // logic error } - if (wlr_input_device_is_libinput(&mauz->wlr()->base)) { - const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&mauz->wlr()->base); + if (mauz->aq() && mauz->aq()->getLibinputHandle()) { + const auto LIBINPUTDEV = mauz->aq()->getLibinputHandle(); Debug::log(LOG, "New mouse has libinput sens {:.2f} ({:.2f}) with accel profile {} ({})", libinput_device_config_accel_get_speed(LIBINPUTDEV), libinput_device_config_accel_get_default_speed(LIBINPUTDEV), (int)libinput_device_config_accel_get_profile(LIBINPUTDEV), @@ -1120,8 +1051,8 @@ void CInputManager::setPointerConfigs() { } } - if (wlr_input_device_is_libinput(&m->wlr()->base)) { - const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&m->wlr()->base); + if (m->aq() && m->aq()->getLibinputHandle()) { + const auto LIBINPUTDEV = m->aq()->getLibinputHandle(); double touchw = 0, touchh = 0; const auto ISTOUCHPAD = libinput_device_has_capability(LIBINPUTDEV, LIBINPUT_DEVICE_CAP_POINTER) && @@ -1270,7 +1201,7 @@ void CInputManager::destroyKeyboard(SP pKeyboard) { if (m_vKeyboards.size() > 0) { bool found = false; for (auto& k : m_vKeyboards | std::views::reverse) { - if (!k->wlr()) + if (!k) continue; g_pSeatManager->setKeyboard(k); @@ -1330,23 +1261,19 @@ void CInputManager::destroyTabletPad(SP pad) { } void CInputManager::updateKeyboardsLeds(SP pKeyboard) { - if (!pKeyboard) - return; - - auto keyboard = pKeyboard->wlr(); - - if (!keyboard || keyboard->xkb_state == nullptr) + if (!pKeyboard || !pKeyboard->xkbTranslationState) return; - uint32_t leds = 0; - for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { - if (xkb_state_led_index_is_active(keyboard->xkb_state, keyboard->led_indexes[i])) - leds |= (1 << i); - } + // FIXME: + // uint32_t leds = 0; + // for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { + // if (xkb_state_led_index_is_active(pKeyboard->xkbTranslationState, keyboard->led_indexes[i])) + // leds |= (1 << i); + // } - for (auto& k : m_vKeyboards) { - k->updateLEDs(leds); - } + // for (auto& k : m_vKeyboards) { + // k->updateLEDs(leds); + // } } void CInputManager::onKeyboardKey(std::any event, SP pKeyboard) { @@ -1374,7 +1301,7 @@ void CInputManager::onKeyboardKey(std::any event, SP pKeyboard) { const auto IME = m_sIMERelay.m_pIME.lock(); if (IME && IME->hasGrab() && !DISALLOWACTION) { - IME->setKeyboard(pKeyboard->wlr()); + IME->setKeyboard(pKeyboard); IME->sendKey(e.timeMs, e.keycode, e.state); } else { g_pSeatManager->setKeyboard(pKeyboard); @@ -1392,15 +1319,14 @@ void CInputManager::onKeyboardMod(SP pKeyboard) { const bool DISALLOWACTION = pKeyboard->isVirtual() && shouldIgnoreVirtualKeyboard(pKeyboard); const auto ALLMODS = accumulateModsFromAllKBs(); - const auto PWLRKB = pKeyboard->wlr(); - auto MODS = PWLRKB->modifiers; + auto MODS = pKeyboard->modifiersState; MODS.depressed = ALLMODS; const auto IME = m_sIMERelay.m_pIME.lock(); if (IME && IME->hasGrab() && !DISALLOWACTION) { - IME->setKeyboard(PWLRKB); + IME->setKeyboard(pKeyboard); IME->sendMods(MODS.depressed, MODS.latched, MODS.locked, MODS.group); } else { g_pSeatManager->setKeyboard(pKeyboard); @@ -1409,8 +1335,8 @@ void CInputManager::onKeyboardMod(SP pKeyboard) { updateKeyboardsLeds(pKeyboard); - if (PWLRKB->modifiers.group != pKeyboard->activeLayout) { - pKeyboard->activeLayout = PWLRKB->modifiers.group; + if (pKeyboard->modifiersState.group != pKeyboard->activeLayout) { + pKeyboard->activeLayout = pKeyboard->modifiersState.group; const auto LAYOUT = pKeyboard->getActiveLayout(); @@ -1524,10 +1450,10 @@ uint32_t CInputManager::accumulateModsFromAllKBs() { if (kb->isVirtual() && shouldIgnoreVirtualKeyboard(kb)) continue; - if (!kb->enabled || !kb->wlr()) + if (!kb->enabled) continue; - finalMask |= wlr_keyboard_get_modifiers(kb->wlr()); + finalMask |= kb->getModifiers(); } return finalMask; @@ -1543,12 +1469,12 @@ void CInputManager::disableAllKeyboards(bool virt) { } } -void CInputManager::newTouchDevice(wlr_input_device* pDevice) { - const auto PNEWDEV = m_vTouches.emplace_back(CTouchDevice::create(wlr_touch_from_input_device(pDevice))); +void CInputManager::newTouchDevice(SP pDevice) { + const auto PNEWDEV = m_vTouches.emplace_back(CTouchDevice::create(pDevice)); m_vHIDs.push_back(PNEWDEV); try { - PNEWDEV->hlName = getNameForNewDevice(pDevice->name); + PNEWDEV->hlName = getNameForNewDevice(PNEWDEV->deviceName); } catch (std::exception& e) { Debug::log(ERR, "Touch Device had no name???"); // logic error } @@ -1572,8 +1498,8 @@ void CInputManager::newTouchDevice(wlr_input_device* pDevice) { void CInputManager::setTouchDeviceConfigs(SP dev) { auto setConfig = [&](SP PTOUCHDEV) -> void { - if (wlr_input_device_is_libinput(&PTOUCHDEV->wlr()->base)) { - const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&PTOUCHDEV->wlr()->base); + if (dev->aq() && dev->aq()->getLibinputHandle()) { + const auto LIBINPUTDEV = dev->aq()->getLibinputHandle(); const auto ENABLED = g_pConfigManager->getDeviceInt(PTOUCHDEV->hlName, "enabled", "input:touchdevice:enabled"); const auto mode = ENABLED ? LIBINPUT_CONFIG_SEND_EVENTS_ENABLED : LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; @@ -1589,11 +1515,12 @@ void CInputManager::setTouchDeviceConfigs(SP dev) { bool bound = !output.empty() && output != STRVAL_EMPTY; const bool AUTODETECT = output == "[[Auto]]"; if (!bound && AUTODETECT) { - const auto DEFAULTOUTPUT = PTOUCHDEV->wlr()->output_name; - if (DEFAULTOUTPUT) { - output = DEFAULTOUTPUT; - bound = true; - } + // FIXME: + // const auto DEFAULTOUTPUT = PTOUCHDEV->wlr()->output_name; + // if (DEFAULTOUTPUT) { + // output = DEFAULTOUTPUT; + // bound = true; + // } } PTOUCHDEV->boundOutput = bound ? output : ""; const auto PMONITOR = bound ? g_pCompositor->getMonitorFromName(output) : nullptr; diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 85ae61977c4..692b5c27caf 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -18,6 +18,10 @@ class CVirtualKeyboardV1Resource; class CVirtualPointerV1Resource; class IKeyboard; +AQUAMARINE_FORWARD(IPointer); +AQUAMARINE_FORWARD(IKeyboard); +AQUAMARINE_FORWARD(ITouch); + enum eClickBehaviorMode { CLICKMODE_DEFAULT = 0, CLICKMODE_KILL @@ -82,11 +86,11 @@ class CInputManager { void onKeyboardKey(std::any, SP); void onKeyboardMod(SP); - void newKeyboard(wlr_input_device*); + void newKeyboard(SP); void newVirtualKeyboard(SP); - void newMouse(wlr_input_device*); + void newMouse(SP); void newVirtualMouse(SP); - void newTouchDevice(wlr_input_device*); + void newTouchDevice(SP); void newSwitch(wlr_input_device*); void newTabletTool(wlr_tablet_tool*); void newTabletPad(wlr_input_device*); diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index 7c3b39ceafa..c8f423cef2d 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -34,7 +34,7 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out } } - gammaSize = wlr_output_get_gamma_size(pMonitor->output); + gammaSize = pMonitor->output->getGammaSize(); if (gammaSize <= 0) { LOGM(ERR, "Output {} doesn't support gamma", pMonitor->szName); @@ -95,7 +95,7 @@ CGammaControl::~CGammaControl() { return; // reset the LUT if the client dies for whatever reason and doesn't unset the gamma - wlr_output_state_set_gamma_lut(pMonitor->state.wlr(), 0, nullptr, nullptr, nullptr); + pMonitor->output->state->setGammaLut({}); } bool CGammaControl::good() { @@ -109,19 +109,15 @@ void CGammaControl::applyToMonitor() { LOGM(LOG, "setting to monitor {}", pMonitor->szName); if (!gammaTableSet) { - wlr_output_state_set_gamma_lut(pMonitor->state.wlr(), 0, nullptr, nullptr, nullptr); + pMonitor->output->state->setGammaLut({}); return; } - uint16_t* red = &gammaTable.at(0); - uint16_t* green = &gammaTable.at(gammaSize); - uint16_t* blue = &gammaTable.at(gammaSize * 2); - - wlr_output_state_set_gamma_lut(pMonitor->state.wlr(), gammaSize, red, green, blue); + pMonitor->output->state->setGammaLut(gammaTable); if (!pMonitor->state.test()) { LOGM(LOG, "setting to monitor {} failed", pMonitor->szName); - wlr_output_state_set_gamma_lut(pMonitor->state.wlr(), 0, nullptr, nullptr, nullptr); + pMonitor->output->state->setGammaLut({}); } g_pHyprRenderer->damageMonitor(pMonitor); diff --git a/src/protocols/InputMethodV2.cpp b/src/protocols/InputMethodV2.cpp index 24f7ad54067..f70cc4fcca5 100644 --- a/src/protocols/InputMethodV2.cpp +++ b/src/protocols/InputMethodV2.cpp @@ -19,7 +19,7 @@ CInputMethodKeyboardGrabV2::CInputMethodKeyboardGrabV2(SPkeyboard->wlr()); + sendKeyboardData(g_pSeatManager->keyboard.lock()); } CInputMethodKeyboardGrabV2::~CInputMethodKeyboardGrabV2() { @@ -27,37 +27,36 @@ CInputMethodKeyboardGrabV2::~CInputMethodKeyboardGrabV2() { std::erase_if(owner->grabs, [](const auto& g) { return g.expired(); }); } -void CInputMethodKeyboardGrabV2::sendKeyboardData(wlr_keyboard* keyboard) { +void CInputMethodKeyboardGrabV2::sendKeyboardData(SP keyboard) { if (keyboard == pLastKeyboard) return; pLastKeyboard = keyboard; - int keymapFD = allocateSHMFile(keyboard->keymap_size); + int keymapFD = allocateSHMFile(keyboard->xkbKeymapString.length() + 1); if (keymapFD < 0) { LOGM(ERR, "Failed to create a keymap file for keyboard grab"); return; } - void* data = mmap(nullptr, keyboard->keymap_size, PROT_READ | PROT_WRITE, MAP_SHARED, keymapFD, 0); + void* data = mmap(nullptr, keyboard->xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, keymapFD, 0); if (data == MAP_FAILED) { LOGM(ERR, "Failed to mmap a keymap file for keyboard grab"); close(keymapFD); return; } - memcpy(data, keyboard->keymap_string, keyboard->keymap_size); - munmap(data, keyboard->keymap_size); + memcpy(data, keyboard->xkbKeymapString.c_str(), keyboard->xkbKeymapString.length()); + munmap(data, keyboard->xkbKeymapString.length() + 1); - resource->sendKeymap(WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymapFD, keyboard->keymap_size); + resource->sendKeymap(WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymapFD, keyboard->xkbKeymapString.length() + 1); close(keymapFD); - const auto MODS = keyboard->modifiers; - sendMods(MODS.depressed, MODS.latched, MODS.locked, MODS.group); + sendMods(keyboard->modifiersState.depressed, keyboard->modifiersState.latched, keyboard->modifiersState.locked, keyboard->modifiersState.group); - resource->sendRepeatInfo(keyboard->repeat_info.rate, keyboard->repeat_info.delay); + resource->sendRepeatInfo(keyboard->repeatRate, keyboard->repeatDelay); } void CInputMethodKeyboardGrabV2::sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state state) { @@ -316,7 +315,7 @@ void CInputMethodV2::sendMods(uint32_t depressed, uint32_t latched, uint32_t loc } } -void CInputMethodV2::setKeyboard(wlr_keyboard* keyboard) { +void CInputMethodV2::setKeyboard(SP keyboard) { for (auto& gw : grabs) { auto g = gw.lock(); diff --git a/src/protocols/InputMethodV2.hpp b/src/protocols/InputMethodV2.hpp index bc21270c471..0b2c7a49ae9 100644 --- a/src/protocols/InputMethodV2.hpp +++ b/src/protocols/InputMethodV2.hpp @@ -11,6 +11,7 @@ class CInputMethodKeyboardGrabV2; class CInputMethodPopupV2; +class IKeyboard; class CInputMethodV2 { public: @@ -58,7 +59,7 @@ class CInputMethodV2 { bool hasGrab(); void sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state state); void sendMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); - void setKeyboard(wlr_keyboard* keyboard); + void setKeyboard(SP keyboard); wl_client* client(); wl_client* grabClient(); @@ -90,13 +91,13 @@ class CInputMethodKeyboardGrabV2 { void sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state state); void sendMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); - void sendKeyboardData(wlr_keyboard* keyboard); + void sendKeyboardData(SP keyboard); private: SP resource; WP owner; - wlr_keyboard* pLastKeyboard = nullptr; // READ-ONLY + WP pLastKeyboard; }; class CInputMethodPopupV2 { diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index cf8f8730601..6167ec3f3d0 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -73,7 +73,7 @@ CCompiledDMABUFFeedback::~CCompiledDMABUFFeedback() { close(tableFD); } -CLinuxDMABuffer::CLinuxDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs attrs) { +CLinuxDMABuffer::CLinuxDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs) { buffer = makeShared(id, client, attrs); buffer->resource->buffer = buffer; @@ -103,7 +103,7 @@ CLinuxDMABBUFParamsResource::CLinuxDMABBUFParamsResource(SPsetOnDestroy([this](CZwpLinuxBufferParamsV1* r) { PROTO::linuxDma->destroyResource(this); }); resource->setDestroy([this](CZwpLinuxBufferParamsV1* r) { PROTO::linuxDma->destroyResource(this); }); - attrs = makeShared(); + attrs = makeShared(); attrs->success = true; @@ -376,7 +376,7 @@ void CLinuxDMABUFResource::sendMods() { CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = g_pHookSystem->hookDynamic("ready", [this](void* self, SCallbackInfo& info, std::any d) { - int rendererFD = wlr_renderer_get_drm_fd(g_pCompositor->m_sWLRRenderer); + int rendererFD = g_pCompositor->m_iDRMFD; auto dev = devIDFromFD(rendererFD); if (!dev.has_value()) { diff --git a/src/protocols/LinuxDMABUF.hpp b/src/protocols/LinuxDMABUF.hpp index 2b8ce736f4a..e845352c4bd 100644 --- a/src/protocols/LinuxDMABUF.hpp +++ b/src/protocols/LinuxDMABUF.hpp @@ -7,15 +7,15 @@ #include "wayland.hpp" #include "linux-dmabuf-v1.hpp" #include "../helpers/signal/Signal.hpp" +#include class CDMABuffer; struct SDRMFormat; -struct SDMABUFAttrs; class CWLSurfaceResource; class CLinuxDMABuffer { public: - CLinuxDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs attrs); + CLinuxDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs); ~CLinuxDMABuffer(); bool good(); @@ -66,12 +66,12 @@ class CLinuxDMABBUFParamsResource { CLinuxDMABBUFParamsResource(SP resource_); ~CLinuxDMABBUFParamsResource(); - bool good(); - void create(uint32_t id); // 0 means not immed + bool good(); + void create(uint32_t id); // 0 means not immed - SP attrs; - WP createdBuffer; - bool used = false; + SP attrs; + WP createdBuffer; + bool used = false; private: SP resource; diff --git a/src/protocols/MesaDRM.cpp b/src/protocols/MesaDRM.cpp index 0bcf4a9cea4..ab77cb4d39e 100644 --- a/src/protocols/MesaDRM.cpp +++ b/src/protocols/MesaDRM.cpp @@ -7,7 +7,7 @@ #define LOGM PROTO::mesaDRM->protoLog -CMesaDRMBufferResource::CMesaDRMBufferResource(uint32_t id, wl_client* client, SDMABUFAttrs attrs_) { +CMesaDRMBufferResource::CMesaDRMBufferResource(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs_) { LOGM(LOG, "Creating a Mesa dmabuf, with id {}: size {}, fmt {}, planes {}", id, attrs_.size, attrs_.format, attrs_.planes); for (int i = 0; i < attrs_.planes; ++i) { LOGM(LOG, " | plane {}: mod {} fd {} stride {} offset {}", i, attrs_.modifier, attrs_.fds[i], attrs_.strides[i], attrs_.offsets[i]); @@ -60,7 +60,7 @@ CMesaDRMResource::CMesaDRMResource(SP resource_) : resource(resource_) { return; } - SDMABUFAttrs attrs; + Aquamarine::SDMABUFAttrs attrs; attrs.success = true; attrs.size = {w, h}; attrs.modifier = DRM_FORMAT_MOD_INVALID; @@ -97,7 +97,7 @@ bool CMesaDRMResource::good() { CMesaDRMProtocol::CMesaDRMProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { drmDevice* dev = nullptr; - int drmFD = wlr_renderer_get_drm_fd(g_pCompositor->m_sWLRRenderer); + int drmFD = g_pCompositor->m_iDRMFD; if (drmGetDevice2(drmFD, 0, &dev) != 0) { LOGM(ERR, "Failed to get device"); PROTO::mesaDRM.reset(); diff --git a/src/protocols/MesaDRM.hpp b/src/protocols/MesaDRM.hpp index ad31a18225b..46811d68500 100644 --- a/src/protocols/MesaDRM.hpp +++ b/src/protocols/MesaDRM.hpp @@ -10,7 +10,7 @@ class CMesaDRMBufferResource { public: - CMesaDRMBufferResource(uint32_t id, wl_client* client, SDMABUFAttrs attrs); + CMesaDRMBufferResource(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs); ~CMesaDRMBufferResource(); bool good(); diff --git a/src/protocols/OutputManagement.cpp b/src/protocols/OutputManagement.cpp index 68c50193650..66f4c5f00d6 100644 --- a/src/protocols/OutputManagement.cpp +++ b/src/protocols/OutputManagement.cpp @@ -2,6 +2,8 @@ #include #include "../Compositor.hpp" +using namespace Aquamarine; + #define LOGM PROTO::outputManagement->protoLog COutputManager::COutputManager(SP resource_) : resource(resource_) { @@ -123,8 +125,8 @@ void COutputHead::sendAllData() { resource->sendName(pMonitor->szName.c_str()); resource->sendDescription(pMonitor->szDescription.c_str()); - if (pMonitor->output->phys_width > 0 && pMonitor->output->phys_height > 0) - resource->sendPhysicalSize(pMonitor->output->phys_width, pMonitor->output->phys_height); + if (pMonitor->output->physicalSize.x > 0 && pMonitor->output->physicalSize.y > 0) + resource->sendPhysicalSize(pMonitor->output->physicalSize.x, pMonitor->output->physicalSize.y); resource->sendEnabled(pMonitor->m_bEnabled); if (pMonitor->m_bEnabled) { @@ -133,12 +135,12 @@ void COutputHead::sendAllData() { resource->sendScale(wl_fixed_from_double(pMonitor->scale)); } - if (pMonitor->output->make && VERSION >= 2) - resource->sendMake(pMonitor->output->make); - if (pMonitor->output->model && VERSION >= 2) - resource->sendModel(pMonitor->output->model); - if (pMonitor->output->serial && VERSION >= 2) - resource->sendSerialNumber(pMonitor->output->serial); + if (!pMonitor->output->make.empty() && VERSION >= 2) + resource->sendMake(pMonitor->output->make.c_str()); + if (!pMonitor->output->model.empty() && VERSION >= 2) + resource->sendModel(pMonitor->output->model.c_str()); + if (!pMonitor->output->serial.empty() && VERSION >= 2) + resource->sendSerialNumber(pMonitor->output->serial.c_str()); if (VERSION >= 4) resource->sendAdaptiveSync(pMonitor->vrrActive ? ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_ENABLED : ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_DISABLED); @@ -146,12 +148,12 @@ void COutputHead::sendAllData() { // send all available modes if (modes.empty()) { - if (!wl_list_empty(&pMonitor->output->modes)) { - wlr_output_mode* mode; - - wl_list_for_each(mode, &pMonitor->output->modes, link) { - makeAndSendNewMode(mode); + if (!pMonitor->output->modes.empty()) { + for (auto& m : pMonitor->output->modes) { + makeAndSendNewMode(m); } + } else if (pMonitor->output->state->state().customMode) { + makeAndSendNewMode(pMonitor->output->state->state().customMode); } else makeAndSendNewMode(nullptr); } @@ -164,9 +166,9 @@ void COutputHead::sendAllData() { if (!m) continue; - if (m->mode == pMonitor->currentMode) { + if (m->mode == pMonitor->output->state->state().mode) { if (m->mode) - LOGM(LOG, " | sending current mode for {}: {}x{}@{}", pMonitor->szName, m->mode->width, m->mode->height, m->mode->refresh); + LOGM(LOG, " | sending current mode for {}: {}x{}@{}", pMonitor->szName, m->mode->pixelSize.x, m->mode->pixelSize.y, m->mode->refreshRate); else LOGM(LOG, " | sending current mode for {}: null (fake)", pMonitor->szName); resource->sendCurrentMode(m->resource.get()); @@ -197,7 +199,7 @@ void COutputHead::updateMode() { if (m->mode == pMonitor->currentMode) { if (m->mode) - LOGM(LOG, " | sending current mode for {}: {}x{}@{}", pMonitor->szName, m->mode->width, m->mode->height, m->mode->refresh); + LOGM(LOG, " | sending current mode for {}: {}x{}@{}", pMonitor->szName, m->mode->pixelSize.x, m->mode->pixelSize.y, m->mode->refreshRate); else LOGM(LOG, " | sending current mode for {}: null (fake)", pMonitor->szName); resource->sendCurrentMode(m->resource.get()); @@ -207,7 +209,7 @@ void COutputHead::updateMode() { } } -void COutputHead::makeAndSendNewMode(wlr_output_mode* mode) { +void COutputHead::makeAndSendNewMode(SP mode) { const auto RESOURCE = PROTO::outputManagement->m_vModes.emplace_back(makeShared(makeShared(resource->client(), resource->version(), 0), mode)); if (!RESOURCE->good()) { @@ -225,7 +227,7 @@ CMonitor* COutputHead::monitor() { return pMonitor; } -COutputMode::COutputMode(SP resource_, wlr_output_mode* mode_) : resource(resource_), mode(mode_) { +COutputMode::COutputMode(SP resource_, SP mode_) : resource(resource_), mode(mode_) { if (!good()) return; @@ -237,11 +239,11 @@ void COutputMode::sendAllData() { if (!mode) return; - LOGM(LOG, " | sending mode {}x{}@{}mHz, pref: {}", mode->width, mode->height, mode->refresh, mode->preferred); + LOGM(LOG, " | sending mode {}x{}@{}mHz, pref: {}", mode->pixelSize.x, mode->pixelSize.y, mode->refreshRate, mode->preferred); - resource->sendSize(mode->width, mode->height); - if (mode->refresh > 0) - resource->sendRefresh(mode->refresh); + resource->sendSize(mode->pixelSize.x, mode->pixelSize.y); + if (mode->refreshRate > 0) + resource->sendRefresh(mode->refreshRate); if (mode->preferred) resource->sendPreferred(); } @@ -250,8 +252,8 @@ bool COutputMode::good() { return resource->resource(); } -wlr_output_mode* COutputMode::getMode() { - return mode; +SP COutputMode::getMode() { + return mode.lock(); } COutputConfiguration::COutputConfiguration(SP resource_, SP owner_) : resource(resource_), owner(owner_) { @@ -364,8 +366,8 @@ bool COutputConfiguration::applyTestConfiguration(bool test) { newRule.disabled = false; if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE) { - newRule.resolution = {head->state.mode->getMode()->width, head->state.mode->getMode()->height}; - newRule.refreshRate = head->state.mode->getMode()->refresh / 1000.F; + newRule.resolution = head->state.mode->getMode()->pixelSize; + newRule.refreshRate = head->state.mode->getMode()->refreshRate / 1000.F; } else if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_CUSTOM_MODE) { newRule.resolution = head->state.customMode.size; newRule.refreshRate = head->state.customMode.refresh / 1000.F; @@ -425,7 +427,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPszName, MODE->getMode()->width, MODE->getMode()->height, MODE->getMode()->refresh); + LOGM(LOG, " | configHead for {}: set mode to {}x{}@{}", pMonitor->szName, MODE->getMode()->pixelSize.x, MODE->getMode()->pixelSize.y, MODE->getMode()->refreshRate); }); resource->setSetCustomMode([this](CZwlrOutputConfigurationHeadV1* r, int32_t w, int32_t h, int32_t refresh) { diff --git a/src/protocols/OutputManagement.hpp b/src/protocols/OutputManagement.hpp index 81ae9a7156f..36478d0b504 100644 --- a/src/protocols/OutputManagement.hpp +++ b/src/protocols/OutputManagement.hpp @@ -6,6 +6,7 @@ #include "WaylandProtocol.hpp" #include "wlr-output-management-unstable-v1.hpp" #include "../helpers/signal/Signal.hpp" +#include class CMonitor; @@ -34,15 +35,15 @@ class COutputManager { class COutputMode { public: - COutputMode(SP resource_, wlr_output_mode* mode_); + COutputMode(SP resource_, SP mode_); - bool good(); - wlr_output_mode* getMode(); - void sendAllData(); + bool good(); + SP getMode(); + void sendAllData(); private: - SP resource; - wlr_output_mode* mode = nullptr; + SP resource; + WP mode; friend class COutputHead; friend class COutputManagementProtocol; @@ -61,7 +62,7 @@ class COutputHead { SP resource; CMonitor* pMonitor = nullptr; - void makeAndSendNewMode(wlr_output_mode* mode); + void makeAndSendNewMode(SP mode); void sendCurrentMode(); std::vector> modes; diff --git a/src/protocols/OutputPower.cpp b/src/protocols/OutputPower.cpp index ef287cfaa19..597b9871c95 100644 --- a/src/protocols/OutputPower.cpp +++ b/src/protocols/OutputPower.cpp @@ -17,7 +17,7 @@ COutputPower::COutputPower(SP resource_, CMonitor* pMonitor_ pMonitor->dpmsStatus = mode == ZWLR_OUTPUT_POWER_V1_MODE_ON; - wlr_output_state_set_enabled(pMonitor->state.wlr(), pMonitor->dpmsStatus); + pMonitor->output->state->setEnabled(mode == ZWLR_OUTPUT_POWER_V1_MODE_ON); if (!pMonitor->state.commit()) LOGM(ERR, "Couldn't set dpms to {} for {}", pMonitor->dpmsStatus, pMonitor->szName); diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index 3907bf1ed7c..1c92513c81e 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -3,6 +3,7 @@ #include "../helpers/Monitor.hpp" #include "../managers/HookSystemManager.hpp" #include "core/Compositor.hpp" +#include "core/Output.hpp" #define LOGM PROTO::presentation->protoLog @@ -41,13 +42,11 @@ bool CPresentationFeedback::good() { } void CPresentationFeedback::sendQueued(SP data, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) { - auto client = resource->client(); - wl_resource* res; - wl_resource_for_each(res, &data->pMonitor->output->resources) { - if (client == wl_resource_get_client(res)) { - resource->sendSyncOutput(res); - break; - } + auto client = resource->client(); + + if (PROTO::outputs.contains(data->pMonitor->szName)) { + if (auto outputResource = PROTO::outputs.at(data->pMonitor->szName)->outputResourceFrom(client); outputResource) + resource->sendSyncOutput(outputResource->getResource()->resource()); } uint32_t flags = 0; diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 8a6285a1155..fd7bd65c51b 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -266,20 +266,17 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r return; } - if (PFRAME->pMonitor->output->allocator && (PFRAME->pMonitor->output->allocator->buffer_caps & WLR_BUFFER_CAP_DMABUF)) { - PFRAME->dmabufFormat = PFRAME->pMonitor->output->render_format; - } else { - PFRAME->dmabufFormat = DRM_FORMAT_INVALID; - } + PFRAME->dmabufFormat = PFRAME->pMonitor->output->state->state().drmFormat; if (box.width == 0 && box.height == 0) PFRAME->box = {0, 0, (int)(PFRAME->pMonitor->vecSize.x), (int)(PFRAME->pMonitor->vecSize.y)}; else { PFRAME->box = box; } - int ow, oh; - wlr_output_effective_resolution(PFRAME->pMonitor->output, &ow, &oh); - PFRAME->box.transform(wlTransformToHyprutils(PFRAME->pMonitor->transform), ow, oh).scale(PFRAME->pMonitor->scale).round(); + + PFRAME->box.transform(wlTransformToHyprutils(PFRAME->pMonitor->transform), PFRAME->pMonitor->vecTransformedSize.x, PFRAME->pMonitor->vecTransformedSize.y) + .scale(PFRAME->pMonitor->scale) + .round(); PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w); @@ -383,10 +380,10 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou g_pHyprRenderer->damageMonitor(PFRAME->pMonitor); } -void CScreencopyProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e) { - m_pLastMonitorBackBuffer = e->state->buffer; +void CScreencopyProtocolManager::onOutputCommit(CMonitor* pMonitor) { + m_pLastMonitorBackBuffer = pMonitor->output->state->state().buffer; shareAllFrames(pMonitor); - m_pLastMonitorBackBuffer = nullptr; + m_pLastMonitorBackBuffer.reset(); } void CScreencopyProtocolManager::shareAllFrames(CMonitor* pMonitor) { @@ -473,11 +470,7 @@ void CScreencopyProtocolManager::sendFrameDamage(SScreencopyFrame* frame) { } bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* now) { - wlr_texture* sourceTex = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer); - if (!sourceTex) - return false; - - auto TEXTURE = makeShared(sourceTex); + auto TEXTURE = makeShared(m_pLastMonitorBackBuffer); auto shm = frame->buffer->shm(); auto [pixelData, fmt, bufLen] = frame->buffer->beginDataPtr(0); // no need for end, cuz it's shm @@ -489,10 +482,8 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* CFramebuffer fb; fb.alloc(frame->box.w, frame->box.h, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : frame->pMonitor->drmFormat); - if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) { - wlr_texture_destroy(sourceTex); + if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) return false; - } CBox monbox = CBox{0, 0, frame->pMonitor->vecTransformedSize.x, frame->pMonitor->vecTransformedSize.y}.translate({-frame->box.x, -frame->box.y}); g_pHyprOpenGL->setMonitorTransformEnabled(true); @@ -510,7 +501,6 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* const auto PFORMAT = FormatUtils::getPixelFormatFromDRM(shm.format); if (!PFORMAT) { g_pHyprRenderer->endRender(); - wlr_texture_destroy(sourceTex); return false; } @@ -539,27 +529,20 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; - wlr_texture_destroy(sourceTex); - return true; } bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) { - wlr_texture* sourceTex = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer); - if (!sourceTex) - return false; - - auto TEXTURE = makeShared(sourceTex); + auto TEXTURE = makeShared(m_pLastMonitorBackBuffer); CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer.lock(), nullptr, true)) return false; - CBox monbox = - CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y} - .translate({-frame->box.x, -frame->box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. - .transform(wlTransformToHyprutils(wlr_output_transform_invert(frame->pMonitor->output->transform)), frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y); + CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y} + .translate({-frame->box.x, -frame->box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. + .transform(wlTransformToHyprutils(wlr_output_transform_invert(frame->pMonitor->transform)), frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y); g_pHyprOpenGL->setMonitorTransformEnabled(true); g_pHyprOpenGL->setRenderModifEnabled(false); g_pHyprOpenGL->renderTexture(TEXTURE, &monbox, 1); @@ -569,7 +552,5 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) { g_pHyprOpenGL->m_RenderData.blockScreenShader = true; g_pHyprRenderer->endRender(); - wlr_texture_destroy(sourceTex); - return true; } diff --git a/src/protocols/Screencopy.hpp b/src/protocols/Screencopy.hpp index be434285d91..063068b50db 100644 --- a/src/protocols/Screencopy.hpp +++ b/src/protocols/Screencopy.hpp @@ -10,7 +10,7 @@ #include "../managers/eventLoop/EventLoopTimer.hpp" class CMonitor; -class IWLBuffer; +class IHLBuffer; enum eClientOwners { CLIENT_SCREENCOPY = 0, @@ -56,7 +56,7 @@ struct SScreencopyFrame { bool bufferDMA = false; - WP buffer; + WP buffer; CMonitor* pMonitor = nullptr; PHLWINDOWREF pWindow; @@ -79,7 +79,7 @@ class CScreencopyProtocolManager { void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer); - void onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e); + void onOutputCommit(CMonitor* pMonitor); private: wl_global* m_pGlobal = nullptr; @@ -93,7 +93,7 @@ class CScreencopyProtocolManager { std::vector m_vFramesAwaitingWrite; - wlr_buffer* m_pLastMonitorBackBuffer = nullptr; + SP m_pLastMonitorBackBuffer; void shareAllFrames(CMonitor* pMonitor); void shareFrame(SScreencopyFrame* frame); diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index d4c66c3b502..ce74a823bfe 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -193,16 +193,11 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou return; } - if (PMONITOR->output->allocator && (PMONITOR->output->allocator->buffer_caps & WLR_BUFFER_CAP_DMABUF)) { - PFRAME->dmabufFormat = PMONITOR->output->render_format; - } else { - PFRAME->dmabufFormat = DRM_FORMAT_INVALID; - } + PFRAME->dmabufFormat = PMONITOR->output->state->state().drmFormat; PFRAME->box = {0, 0, (int)(pWindow->m_vRealSize.value().x * PMONITOR->scale), (int)(pWindow->m_vRealSize.value().y * PMONITOR->scale)}; - int ow, oh; - wlr_output_effective_resolution(PMONITOR->output, &ow, &oh); - PFRAME->box.transform(wlTransformToHyprutils(PMONITOR->transform), ow, oh).round(); + + PFRAME->box.transform(wlTransformToHyprutils(PMONITOR->transform), PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y).round(); PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w); @@ -289,12 +284,10 @@ void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* r m_vFramesAwaitingWrite.emplace_back(PFRAME); } -void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e) { +void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor) { if (m_vFramesAwaitingWrite.empty()) return; // nothing to share - const auto PMONITOR = g_pCompositor->getMonitorFromOutput(e->output); - std::vector framesToRemove; // share frame if correct output @@ -306,7 +299,7 @@ void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_outp continue; } - if (PMONITOR != g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)) + if (pMonitor != g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)) continue; CBox geometry = {PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y, PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealSize.value().y}; diff --git a/src/protocols/ToplevelExport.hpp b/src/protocols/ToplevelExport.hpp index f044a7816e7..c3620d41c06 100644 --- a/src/protocols/ToplevelExport.hpp +++ b/src/protocols/ToplevelExport.hpp @@ -21,7 +21,7 @@ class CToplevelExportProtocolManager { void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer, int32_t ignore_damage); void displayDestroy(); void onWindowUnmap(PHLWINDOW pWindow); - void onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e); + void onOutputCommit(CMonitor* pMonitor); private: wl_global* m_pGlobal = nullptr; diff --git a/src/protocols/VirtualKeyboard.cpp b/src/protocols/VirtualKeyboard.cpp index 009c277c040..2642ec1174a 100644 --- a/src/protocols/VirtualKeyboard.cpp +++ b/src/protocols/VirtualKeyboard.cpp @@ -1,12 +1,9 @@ #include "VirtualKeyboard.hpp" #include +#include "../devices/IKeyboard.hpp" #define LOGM PROTO::virtualKeyboard->protoLog -static const struct wlr_keyboard_impl virtualKeyboardImpl = { - .name = "virtual-keyboard", -}; - CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP resource_) : resource(resource_) { if (!good()) return; @@ -28,13 +25,17 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP return; } - wlr_keyboard_key_event event = { - .time_msec = timeMs, - .keycode = key, - .update_state = false, - .state = (wl_keyboard_key_state)state, - }; - wlr_keyboard_notify_key(&keyboard, &event); + events.key.emit(IKeyboard::SKeyEvent{ + .timeMs = timeMs, + .keycode = key, + .state = (wl_keyboard_key_state)state, + }); + + const bool CONTAINS = std::find(pressed.begin(), pressed.end(), key) != pressed.end(); + if (state && !CONTAINS) + pressed.emplace_back(key); + else if (!state && CONTAINS) + std::erase(pressed, key); }); resource->setModifiers([this](CZwpVirtualKeyboardV1* r, uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) { @@ -43,7 +44,12 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP return; } - wlr_keyboard_notify_modifiers(&keyboard, depressed, latched, locked, group); + events.modifiers.emit(IKeyboard::SModifiersEvent{ + .depressed = depressed, + .latched = latched, + .locked = locked, + .group = group, + }); }); resource->setKeymap([this](CZwpVirtualKeyboardV1* r, uint32_t fmt, int32_t fd, uint32_t len) { @@ -75,7 +81,9 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP return; } - wlr_keyboard_set_keymap(&keyboard, xkbKeymap); + events.keymap.emit(IKeyboard::SKeymapEvent{ + .keymap = xkbKeymap, + }); hasKeymap = true; xkb_keymap_unref(xkbKeymap); @@ -83,22 +91,17 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP close(fd); }); - wlr_keyboard_init(&keyboard, &virtualKeyboardImpl, "CVirtualKeyboard"); + name = "hl-virtual-keyboard"; } CVirtualKeyboardV1Resource::~CVirtualKeyboardV1Resource() { events.destroy.emit(); - wlr_keyboard_finish(&keyboard); } bool CVirtualKeyboardV1Resource::good() { return resource->resource(); } -wlr_keyboard* CVirtualKeyboardV1Resource::wlr() { - return &keyboard; -} - wl_client* CVirtualKeyboardV1Resource::client() { return resource->resource() ? resource->client() : nullptr; } @@ -106,17 +109,16 @@ wl_client* CVirtualKeyboardV1Resource::client() { void CVirtualKeyboardV1Resource::releasePressed() { timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - size_t keycodesNum = keyboard.num_keycodes; - - for (size_t i = 0; i < keycodesNum; ++i) { - struct wlr_keyboard_key_event event = { - .time_msec = (now.tv_sec * 1000 + now.tv_nsec / 1000000), - .keycode = keyboard.keycodes[keycodesNum - i - 1], - .update_state = false, - .state = WL_KEYBOARD_KEY_STATE_RELEASED, - }; - wlr_keyboard_notify_key(&keyboard, &event); // updates num_keycodes + + for (auto& p : pressed) { + events.key.emit(IKeyboard::SKeyEvent{ + .timeMs = now.tv_sec * 1000 + now.tv_nsec / 1000000, + .keycode = p, + .state = WL_KEYBOARD_KEY_STATE_RELEASED, + }); } + + pressed.clear(); } CVirtualKeyboardProtocol::CVirtualKeyboardProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { diff --git a/src/protocols/VirtualKeyboard.hpp b/src/protocols/VirtualKeyboard.hpp index 447b5db90f0..93b63bb59bd 100644 --- a/src/protocols/VirtualKeyboard.hpp +++ b/src/protocols/VirtualKeyboard.hpp @@ -14,19 +14,24 @@ class CVirtualKeyboardV1Resource { struct { CSignal destroy; + CSignal key; + CSignal modifiers; + CSignal keymap; } events; - bool good(); - wlr_keyboard* wlr(); - wl_client* client(); + bool good(); + wl_client* client(); + + std::string name = ""; private: SP resource; - wlr_keyboard keyboard; void releasePressed(); bool hasKeymap = false; + + std::vector pressed; }; class CVirtualKeyboardProtocol : public IWaylandProtocol { diff --git a/src/protocols/VirtualPointer.cpp b/src/protocols/VirtualPointer.cpp index 1fb83888e1e..bdeec32dfcf 100644 --- a/src/protocols/VirtualPointer.cpp +++ b/src/protocols/VirtualPointer.cpp @@ -2,10 +2,6 @@ #define LOGM PROTO::virtualPointer->protoLog -static const wlr_pointer_impl pointerImpl = { - .name = "virtual-pointer-v1", -}; - CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP resource_) : resource(resource_) { if (!good()) return; @@ -19,41 +15,30 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP r PROTO::virtualPointer->destroyResource(this); }); - wlr_pointer_init(&pointer, &pointerImpl, "CVirtualPointerV1Resource"); - resource->setMotion([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, wl_fixed_t dx, wl_fixed_t dy) { - wlr_pointer_motion_event event = { - .pointer = &pointer, - .time_msec = timeMs, - .delta_x = wl_fixed_to_double(dx), - .delta_y = wl_fixed_to_double(dy), - .unaccel_dx = wl_fixed_to_double(dx), - .unaccel_dy = wl_fixed_to_double(dy), - }; - wl_signal_emit_mutable(&pointer.events.motion, &event); + events.move.emit(IPointer::SMotionEvent{ + .timeMs = timeMs, + .delta = {wl_fixed_to_double(dx), wl_fixed_to_double(dy)}, + .unaccel = {wl_fixed_to_double(dx), wl_fixed_to_double(dy)}, + }); }); resource->setMotionAbsolute([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t x, uint32_t y, uint32_t xExtent, uint32_t yExtent) { if (!xExtent || !yExtent) return; - wlr_pointer_motion_absolute_event event = { - .pointer = &pointer, - .time_msec = timeMs, - .x = (double)x / xExtent, - .y = (double)y / yExtent, - }; - wl_signal_emit_mutable(&pointer.events.motion_absolute, &event); + events.warp.emit(IPointer::SMotionAbsoluteEvent{ + .timeMs = timeMs, + .absolute = {(double)x / xExtent, (double)y / yExtent}, + }); }); resource->setButton([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t button, uint32_t state) { - struct wlr_pointer_button_event event = { - .pointer = &pointer, - .time_msec = timeMs, - .button = button, - .state = (wl_pointer_button_state)state, - }; - wl_signal_emit_mutable(&pointer.events.button, &event); + events.button.emit(IPointer::SButtonEvent{ + .timeMs = timeMs, + .button = button, + .state = (wl_pointer_button_state)state, + }); }); resource->setAxis([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t axis_, wl_fixed_t value) { @@ -63,18 +48,18 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP r } axis = axis_; - axisEvents[axis] = wlr_pointer_axis_event{.pointer = &pointer, .time_msec = timeMs, .orientation = (wl_pointer_axis)axis, .delta = wl_fixed_to_double(value)}; + axisEvents[axis] = IPointer::SAxisEvent{.timeMs = timeMs, .axis = (wl_pointer_axis)axis, .delta = wl_fixed_to_double(value)}; }); resource->setFrame([this](CZwlrVirtualPointerV1* r) { for (auto& e : axisEvents) { - if (!e.pointer) + if (!e.timeMs) continue; - wl_signal_emit_mutable(&pointer.events.axis, &e); - e.pointer = nullptr; + events.axis.emit(e); + e.timeMs = 0; } - wl_signal_emit_mutable(&pointer.events.frame, &pointer); + events.frame.emit(); }); resource->setAxisSource([this](CZwlrVirtualPointerV1* r, uint32_t source) { axisEvents[axis].source = (wl_pointer_axis_source)source; }); @@ -85,12 +70,11 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP r return; } - axis = axis_; - axisEvents[axis].pointer = &pointer; - axisEvents[axis].time_msec = timeMs; - axisEvents[axis].orientation = (wl_pointer_axis)axis; - axisEvents[axis].delta = 0; - axisEvents[axis].delta_discrete = 0; + axis = axis_; + axisEvents[axis].timeMs = timeMs; + axisEvents[axis].axis = (wl_pointer_axis)axis; + axisEvents[axis].delta = 0; + axisEvents[axis].deltaDiscrete = 0; }); resource->setAxisDiscrete([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t axis_, wl_fixed_t value, int32_t discrete) { @@ -99,17 +83,15 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP r return; } - axis = axis_; - axisEvents[axis].pointer = &pointer; - axisEvents[axis].time_msec = timeMs; - axisEvents[axis].orientation = (wl_pointer_axis)axis; - axisEvents[axis].delta = wl_fixed_to_double(value); - axisEvents[axis].delta_discrete = discrete * 120; + axis = axis_; + axisEvents[axis].timeMs = timeMs; + axisEvents[axis].axis = (wl_pointer_axis)axis; + axisEvents[axis].delta = wl_fixed_to_double(value); + axisEvents[axis].deltaDiscrete = discrete * 120; }); } CVirtualPointerV1Resource::~CVirtualPointerV1Resource() { - wlr_pointer_finish(&pointer); events.destroy.emit(); } @@ -117,10 +99,6 @@ bool CVirtualPointerV1Resource::good() { return resource->resource(); } -wlr_pointer* CVirtualPointerV1Resource::wlr() { - return &pointer; -} - wl_client* CVirtualPointerV1Resource::client() { return resource->client(); } diff --git a/src/protocols/VirtualPointer.hpp b/src/protocols/VirtualPointer.hpp index 59a7e7395e5..ee5ee7e2a40 100644 --- a/src/protocols/VirtualPointer.hpp +++ b/src/protocols/VirtualPointer.hpp @@ -7,6 +7,7 @@ #include "WaylandProtocol.hpp" #include "wlr-virtual-pointer-unstable-v1.hpp" #include "../helpers/signal/Signal.hpp" +#include "../devices/IPointer.hpp" class CVirtualPointerV1Resource { public: @@ -15,19 +16,35 @@ class CVirtualPointerV1Resource { struct { CSignal destroy; + CSignal move; + CSignal warp; + CSignal button; + CSignal axis; + CSignal frame; + + CSignal swipeBegin; + CSignal swipeUpdate; + CSignal swipeEnd; + + CSignal pinchBegin; + CSignal pinchUpdate; + CSignal pinchEnd; + + CSignal holdBegin; + CSignal holdEnd; } events; - bool good(); - wlr_pointer* wlr(); - wl_client* client(); + bool good(); + wl_client* client(); + + std::string name; private: - SP resource; - wlr_pointer pointer; + SP resource; - uint32_t axis = 0; + uint32_t axis = 0; - std::array axisEvents; + std::array axisEvents; }; class CVirtualPointerProtocol : public IWaylandProtocol { diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index 03e58956a64..073aa5024b2 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -75,8 +75,8 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32 if (XDGVER >= OUTPUT_NAME_SINCE_VERSION) pXDGOutput->resource->sendName(PMONITOR->szName.c_str()); - if (XDGVER >= OUTPUT_DESCRIPTION_SINCE_VERSION && PMONITOR->output->description) - pXDGOutput->resource->sendDescription(PMONITOR->output->description); + if (XDGVER >= OUTPUT_DESCRIPTION_SINCE_VERSION && !PMONITOR->output->description.empty()) + pXDGOutput->resource->sendDescription(PMONITOR->output->description.c_str()); pXDGOutput->sendDetails(); @@ -93,7 +93,7 @@ void CXDGOutputProtocol::updateAllOutputs() { o->sendDetails(); - wlr_output_schedule_done(o->monitor->output); + o->monitor->scheduleDone(); } } diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index 2f276719a45..a232ac3062a 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -85,7 +85,7 @@ class CWLSurfaceResource { CRegion opaque, input = CBox{{}, {INT32_MAX, INT32_MAX}}, damage, bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}} /* initial damage */; wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; int scale = 1; - SP buffer; + SP buffer; SP texture; Vector2D offset; Vector2D size; diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index 10daa15e485..4ba23cbee72 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -21,8 +21,8 @@ CWLOutputResource::CWLOutputResource(SP resource_, SP pMoni PROTO::outputs.at(monitor->szName)->destroyResource(this); }); - resource->sendGeometry(0, 0, monitor->output->phys_width, monitor->output->phys_height, monitor->output->subpixel, monitor->output->make ? monitor->output->make : "null", - monitor->output->model ? monitor->output->model : "null", monitor->transform); + resource->sendGeometry(0, 0, monitor->output->physicalSize.x, monitor->output->physicalSize.y, (wl_output_subpixel)monitor->output->subpixel, monitor->output->make.c_str(), + monitor->output->model.c_str(), monitor->transform); if (resource->version() >= 4) { resource->sendName(monitor->szName.c_str()); resource->sendDescription(monitor->szDescription.c_str()); @@ -115,3 +115,9 @@ void CWLOutputProtocol::remove() { bool CWLOutputProtocol::isDefunct() { return defunct; } + +void CWLOutputProtocol::sendDone() { + for (auto& r : m_vOutputs) { + r->resource->sendDone(); + } +} diff --git a/src/protocols/core/Output.hpp b/src/protocols/core/Output.hpp index 46981635adf..46e4057b58f 100644 --- a/src/protocols/core/Output.hpp +++ b/src/protocols/core/Output.hpp @@ -26,6 +26,8 @@ class CWLOutputResource { private: SP resource; wl_client* pClient = nullptr; + + friend class CWLOutputProtocol; }; class CWLOutputProtocol : public IWaylandProtocol { @@ -35,6 +37,7 @@ class CWLOutputProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); SP outputResourceFrom(wl_client* client); + void sendDone(); WP monitor; diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index 464a901c4e7..21a47575897 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -254,8 +254,8 @@ void CWLKeyboardResource::sendKeymap(SP keyboard) { int fd; uint32_t size; if (keyboard) { - fd = keyboard->wlr()->keymap_fd; - size = keyboard->wlr()->keymap_size; + fd = keyboard->xkbKeymapFD; + size = keyboard->xkbKeymapString.length() + 1; } else { fd = open("/dev/null", O_RDONLY | O_CLOEXEC); if (fd < 0) { diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp index 4088949f9cd..109a7d04e18 100644 --- a/src/protocols/core/Shm.cpp +++ b/src/protocols/core/Shm.cpp @@ -41,20 +41,20 @@ CWLSHMBuffer::~CWLSHMBuffer() { ; } -eBufferCapability CWLSHMBuffer::caps() { - return BUFFER_CAPABILITY_DATAPTR; +Aquamarine::eBufferCapability CWLSHMBuffer::caps() { + return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR; } -eBufferType CWLSHMBuffer::type() { - return BUFFER_TYPE_SHM; +Aquamarine::eBufferType CWLSHMBuffer::type() { + return Aquamarine::eBufferType::BUFFER_TYPE_SHM; } bool CWLSHMBuffer::isSynchronous() { return true; } -SSHMAttrs CWLSHMBuffer::shm() { - SSHMAttrs attrs; +Aquamarine::SSHMAttrs CWLSHMBuffer::shm() { + Aquamarine::SSHMAttrs attrs; attrs.success = true; attrs.fd = pool->fd; attrs.format = FormatUtils::shmToDRM(fmt); @@ -188,12 +188,11 @@ CWLSHMProtocol::CWLSHMProtocol(const wl_interface* iface, const int& ver, const void CWLSHMProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { if (shmFormats.empty()) { - size_t len = 0; - const uint32_t* formats = wlr_renderer_get_shm_texture_formats(g_pCompositor->m_sWLRRenderer, &len); + size_t len = 0; + // TODO: support 10 bit shm - for (size_t i = 0; i < len; ++i) { - shmFormats.push_back(FormatUtils::drmToShm(formats[i])); - } + shmFormats.push_back(WL_SHM_FORMAT_ARGB8888); + shmFormats.push_back(WL_SHM_FORMAT_XRGB8888); } const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); diff --git a/src/protocols/core/Shm.hpp b/src/protocols/core/Shm.hpp index 70a8b208534..fab325fe936 100644 --- a/src/protocols/core/Shm.hpp +++ b/src/protocols/core/Shm.hpp @@ -29,16 +29,16 @@ class CSHMPool { void resize(size_t size); }; -class CWLSHMBuffer : public IWLBuffer { +class CWLSHMBuffer : public IHLBuffer { public: CWLSHMBuffer(SP pool, uint32_t id, int32_t offset, const Vector2D& size, int32_t stride, uint32_t fmt); virtual ~CWLSHMBuffer(); - virtual eBufferCapability caps(); - virtual eBufferType type(); + virtual Aquamarine::eBufferCapability caps(); + virtual Aquamarine::eBufferType type(); virtual void update(const CRegion& damage); virtual bool isSynchronous(); - virtual SSHMAttrs shm(); + virtual Aquamarine::SSHMAttrs shm(); virtual std::tuple beginDataPtr(uint32_t flags); virtual void endDataPtr(); diff --git a/src/protocols/types/Buffer.cpp b/src/protocols/types/Buffer.cpp index 5ed942e1214..23679ce7ed4 100644 --- a/src/protocols/types/Buffer.cpp +++ b/src/protocols/types/Buffer.cpp @@ -1,41 +1,5 @@ #include "Buffer.hpp" -#include "WLBuffer.hpp" -SDMABUFAttrs IWLBuffer::dmabuf() { - return SDMABUFAttrs{}; -} - -SSHMAttrs IWLBuffer::shm() { - return SSHMAttrs{}; -} - -std::tuple IWLBuffer::beginDataPtr(uint32_t flags) { - return {nullptr, 0, 0}; -} - -void IWLBuffer::endDataPtr() { - ; // empty -} - -void IWLBuffer::sendRelease() { - if (!resource || !resource->resource) - return; - resource->resource->sendRelease(); -} - -void IWLBuffer::lock() { - locks++; -} - -void IWLBuffer::unlock() { - locks--; - - ASSERT(locks >= 0); - - if (locks <= 0) - sendRelease(); -} - -bool IWLBuffer::locked() { - return locks; +void IHLBuffer::sendRelease() { + resource->sendRelease(); } diff --git a/src/protocols/types/Buffer.hpp b/src/protocols/types/Buffer.hpp index 9999a4e9895..0b377bb377c 100644 --- a/src/protocols/types/Buffer.hpp +++ b/src/protocols/types/Buffer.hpp @@ -1,75 +1,24 @@ #pragma once #include "../../defines.hpp" -#include "../../helpers/signal/Signal.hpp" #include "../../render/Texture.hpp" +#include "./WLBuffer.hpp" -#include -#include +#include -enum eBufferCapability { - BUFFER_CAPABILITY_DATAPTR = (1 << 0), -}; - -enum eBufferType { - BUFFER_TYPE_DMABUF = 0, - BUFFER_TYPE_SHM, - BUFFER_TYPE_MISC, -}; - -class CWLBufferResource; - -struct SDMABUFAttrs { - bool success = false; - Vector2D size; - uint32_t format = 0; // fourcc - uint64_t modifier = 0; - - int planes = 1; - std::array offsets = {0}; - std::array strides = {0}; - std::array fds = {-1, -1, -1, -1}; -}; - -struct SSHMAttrs { - bool success = false; - int fd = 0; - uint32_t format = 0; - Vector2D size; - int stride = 0; - int64_t offset = 0; -}; - -class IWLBuffer { +class IHLBuffer : public Aquamarine::IBuffer { public: - virtual ~IWLBuffer() { + virtual ~IHLBuffer() { ; - }; - - virtual eBufferCapability caps() = 0; - virtual eBufferType type() = 0; - virtual void update(const CRegion& damage) = 0; - virtual bool isSynchronous() = 0; // whether the updates to this buffer are synchronous, aka happen over cpu - virtual SDMABUFAttrs dmabuf(); - virtual SSHMAttrs shm(); - virtual std::tuple beginDataPtr(uint32_t flags); - virtual void endDataPtr(); - virtual void sendRelease(); - virtual void lock(); - virtual void unlock(); - virtual bool locked(); - - Vector2D size; - bool opaque = false; - - SP resource; - - SP texture; - - struct { - CSignal destroy; - } events; - - private: - int locks = 0; + } + virtual Aquamarine::eBufferCapability caps() = 0; + virtual Aquamarine::eBufferType type() = 0; + virtual void update(const CRegion& damage) = 0; + virtual bool isSynchronous() = 0; // whether the updates to this buffer are synchronous, aka happen over cpu + virtual bool good() = 0; + virtual void sendRelease(); + + SP texture; + bool opaque = false; + SP resource; }; diff --git a/src/protocols/types/DMABuffer.cpp b/src/protocols/types/DMABuffer.cpp index 7c3a98868d0..63a26c76e05 100644 --- a/src/protocols/types/DMABuffer.cpp +++ b/src/protocols/types/DMABuffer.cpp @@ -3,7 +3,7 @@ #include "../../render/Renderer.hpp" #include "../../helpers/Format.hpp" -CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs const& attrs_) : attrs(attrs_) { +CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs const& attrs_) : attrs(attrs_) { g_pHyprRenderer->makeEGLCurrent(); listeners.resourceDestroy = events.destroy.registerListener([this](std::any d) { @@ -31,12 +31,12 @@ CDMABuffer::~CDMABuffer() { closeFDs(); } -eBufferCapability CDMABuffer::caps() { - return BUFFER_CAPABILITY_DATAPTR; +Aquamarine::eBufferCapability CDMABuffer::caps() { + return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR; } -eBufferType CDMABuffer::type() { - return BUFFER_TYPE_DMABUF; +Aquamarine::eBufferType CDMABuffer::type() { + return Aquamarine::eBufferType::BUFFER_TYPE_DMABUF; } void CDMABuffer::update(const CRegion& damage) { @@ -47,7 +47,7 @@ bool CDMABuffer::isSynchronous() { return false; } -SDMABUFAttrs CDMABuffer::dmabuf() { +Aquamarine::SDMABUFAttrs CDMABuffer::dmabuf() { return attrs; } diff --git a/src/protocols/types/DMABuffer.hpp b/src/protocols/types/DMABuffer.hpp index d07840b7fea..6977df4c1df 100644 --- a/src/protocols/types/DMABuffer.hpp +++ b/src/protocols/types/DMABuffer.hpp @@ -2,16 +2,16 @@ #include "Buffer.hpp" -class CDMABuffer : public IWLBuffer { +class CDMABuffer : public IHLBuffer { public: - CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs const& attrs_); + CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs const& attrs_); virtual ~CDMABuffer(); - virtual eBufferCapability caps(); - virtual eBufferType type(); + virtual Aquamarine::eBufferCapability caps(); + virtual Aquamarine::eBufferType type(); virtual bool isSynchronous(); virtual void update(const CRegion& damage); - virtual SDMABUFAttrs dmabuf(); + virtual Aquamarine::SDMABUFAttrs dmabuf(); virtual std::tuple beginDataPtr(uint32_t flags); virtual void endDataPtr(); bool good(); @@ -21,7 +21,7 @@ class CDMABuffer : public IWLBuffer { bool success = false; private: - SDMABUFAttrs attrs; + Aquamarine::SDMABUFAttrs attrs; struct { CHyprSignalListener resourceDestroy; diff --git a/src/protocols/types/WLBuffer.hpp b/src/protocols/types/WLBuffer.hpp index ac177965a79..83d042cd77a 100644 --- a/src/protocols/types/WLBuffer.hpp +++ b/src/protocols/types/WLBuffer.hpp @@ -7,7 +7,7 @@ #include "wayland.hpp" #include "../../helpers/signal/Signal.hpp" -class IWLBuffer; +class IHLBuffer; class CWLBufferResource { public: @@ -18,7 +18,7 @@ class CWLBufferResource { void sendRelease(); wl_resource* getResource(); - WP buffer; + WP buffer; WP self; @@ -27,5 +27,5 @@ class CWLBufferResource { SP resource; - friend class IWLBuffer; + friend class IHLBuffer; }; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index e127ec2dcaa..8faf693c5e0 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -9,6 +9,8 @@ #include "../protocols/LayerShell.hpp" #include "../protocols/core/Compositor.hpp" #include +#include +#include inline void loadGLProc(void* pProc, const char* name) { void* proc = (void*)eglGetProcAddress(name); @@ -19,24 +21,150 @@ inline void loadGLProc(void* pProc, const char* name) { *(void**)pProc = proc; } -CHyprOpenGLImpl::CHyprOpenGLImpl() { - RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)), - "Couldn't unset current EGL!"); +static enum LogLevel eglLogToLevel(EGLint type) { + switch (type) { + case EGL_DEBUG_MSG_CRITICAL_KHR: return CRIT; + case EGL_DEBUG_MSG_ERROR_KHR: return ERR; + case EGL_DEBUG_MSG_WARN_KHR: return WARN; + case EGL_DEBUG_MSG_INFO_KHR: return LOG; + default: return LOG; + } +} - auto* const EXTENSIONS = (const char*)glGetString(GL_EXTENSIONS); - const std::string EGLEXTENSIONS = (const char*)eglQueryString(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_EXTENSIONS); +static const char* eglErrorToString(EGLint error) { + switch (error) { + case EGL_SUCCESS: return "EGL_SUCCESS"; + case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; + case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; + case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; + case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; + case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; + case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; + case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; + case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; + case EGL_BAD_DEVICE_EXT: return "EGL_BAD_DEVICE_EXT"; + case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; + case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; + case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; + case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; + case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; + case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; + } + return "Unknown"; +} - RASSERT(EXTENSIONS, "Couldn't retrieve openGL extensions!"); +static void eglLog(EGLenum error, const char* command, EGLint type, EGLLabelKHR thread, EGLLabelKHR obj, const char* msg) { + Debug::log(eglLogToLevel(type), "[EGL] Command {} errored out with {} (0x{}): {}", command, eglErrorToString(error), error, msg); +} - m_iDRMFD = g_pCompositor->m_iDRMFD; +static int openRenderNode(int drmFd) { + char* renderName = drmGetRenderDeviceNameFromFd(drmFd); + if (renderName == NULL) { + // This can happen on split render/display platforms, fallback to + // primary node + renderName = drmGetPrimaryDeviceNameFromFd(drmFd); + if (renderName == NULL) { + wlr_log_errno(WLR_ERROR, "drmGetPrimaryDeviceNameFromFd failed"); + return -1; + } + wlr_log(WLR_DEBUG, + "DRM device '%s' has no render node, " + "falling back to primary node", + renderName); + + drmVersion* render_version = drmGetVersion(drmFd); + if (render_version != NULL && render_version->name != NULL) { + wlr_log(WLR_DEBUG, "DRM device version.name '%s'", render_version->name); + if (strcmp(render_version->name, "evdi") == 0) { + free(renderName); + renderName = (char*)malloc(sizeof(char) * 15); + strcpy(renderName, "/dev/dri/card0"); + } + drmFreeVersion(render_version); + } + } - m_szExtensions = EXTENSIONS; + wlr_log(WLR_DEBUG, "open_render_node() DRM device '%s'", renderName); - Debug::log(LOG, "Creating the Hypr OpenGL Renderer!"); - Debug::log(LOG, "Using: {}", (char*)glGetString(GL_VERSION)); - Debug::log(LOG, "Vendor: {}", (char*)glGetString(GL_VENDOR)); - Debug::log(LOG, "Renderer: {}", (char*)glGetString(GL_RENDERER)); - Debug::log(LOG, "Supported extensions: ({}) {}", std::count(m_szExtensions.begin(), m_szExtensions.end(), ' '), m_szExtensions); + int render_fd = open(renderName, O_RDWR | O_CLOEXEC); + if (render_fd < 0) { + wlr_log_errno(WLR_ERROR, "Failed to open DRM node '%s'", renderName); + } + free(renderName); + return render_fd; +} + +void CHyprOpenGLImpl::initEGL(bool gbm) { + std::vector attrs; + if (m_sExts.KHR_display_reference) { + attrs.push_back(EGL_TRACK_REFERENCES_KHR); + attrs.push_back(EGL_TRUE); + } + + attrs.push_back(EGL_NONE); + + m_pEglDisplay = m_sProc.eglGetPlatformDisplayEXT(gbm ? EGL_PLATFORM_GBM_KHR : EGL_PLATFORM_DEVICE_EXT, gbm ? m_pGbmDevice : nullptr, attrs.data()); + if (m_pEglDisplay == EGL_NO_DISPLAY) + RASSERT(false, "EGL: failed to create a platform display"); + + attrs.clear(); + + EGLint major, minor; + if (eglInitialize(m_pEglDisplay, &major, &minor) == EGL_FALSE) + RASSERT(false, "EGL: failed to initialize a platform display"); + + const std::string EGLEXTENSIONS = (const char*)eglQueryString(m_pEglDisplay, EGL_EXTENSIONS); + + m_sExts.IMG_context_priority = EGLEXTENSIONS.contains("IMG_context_priority"); + m_sExts.EXT_create_context_robustness = EGLEXTENSIONS.contains("EXT_create_context_robustness"); + m_sExts.EXT_image_dma_buf_import = EGLEXTENSIONS.contains("EXT_image_dma_buf_import"); + m_sExts.EXT_image_dma_buf_import_modifiers = EGLEXTENSIONS.contains("EXT_image_dma_buf_import_modifiers"); + + if (m_sExts.IMG_context_priority) { + Debug::log(LOG, "EGL: IMG_context_priority supported, requesting high"); + attrs.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG); + attrs.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG); + } + + if (m_sExts.EXT_create_context_robustness) { + Debug::log(LOG, "EGL: EXT_create_context_robustness supported, requesting lose on reset"); + attrs.push_back(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT); + attrs.push_back(EGL_LOSE_CONTEXT_ON_RESET_EXT); + } + + attrs.push_back(EGL_CONTEXT_MAJOR_VERSION); + attrs.push_back(3); + attrs.push_back(EGL_CONTEXT_MINOR_VERSION); + attrs.push_back(2); + attrs.push_back(EGL_CONTEXT_OPENGL_DEBUG); + attrs.push_back(ISDEBUG ? EGL_TRUE : EGL_FALSE); + + attrs.push_back(EGL_NONE); + + m_pEglContext = eglCreateContext(m_pEglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT, attrs.data()); + if (m_pEglContext == EGL_NO_CONTEXT) + RASSERT(false, "EGL: failed to create a context"); + + if (m_sExts.IMG_context_priority) { + EGLint priority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG; + eglQueryContext(m_pEglDisplay, m_pEglContext, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &priority); + if (priority != EGL_CONTEXT_PRIORITY_HIGH_IMG) + Debug::log(ERR, "EGL: Failed to obtain a high priority context"); + else + Debug::log(LOG, "EGL: Got a high priority context"); + } + + eglMakeCurrent(m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, m_pEglContext); +} + +CHyprOpenGLImpl::CHyprOpenGLImpl() { + const std::string EGLEXTENSIONS = (const char*)eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); + + Debug::log(LOG, "Supported EGL extensions: ({}) {}", std::count(EGLEXTENSIONS.begin(), EGLEXTENSIONS.end(), ' '), EGLEXTENSIONS); + + m_iDRMFD = g_pCompositor->m_iDRMFD; + + m_sExts.KHR_display_reference = EGLEXTENSIONS.contains("KHR_display_reference"); loadGLProc(&m_sProc.glEGLImageTargetRenderbufferStorageOES, "glEGLImageTargetRenderbufferStorageOES"); loadGLProc(&m_sProc.eglCreateImageKHR, "eglCreateImageKHR"); @@ -44,10 +172,56 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() { loadGLProc(&m_sProc.eglQueryDmaBufFormatsEXT, "eglQueryDmaBufFormatsEXT"); loadGLProc(&m_sProc.eglQueryDmaBufModifiersEXT, "eglQueryDmaBufModifiersEXT"); loadGLProc(&m_sProc.glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES"); + loadGLProc(&m_sProc.eglDebugMessageControlKHR, "eglDebugMessageControlKHR"); + loadGLProc(&m_sProc.eglGetPlatformDisplayEXT, "eglGetPlatformDisplayEXT"); - m_sExts.EXT_read_format_bgra = m_szExtensions.contains("GL_EXT_read_format_bgra"); - m_sExts.EXT_image_dma_buf_import = EGLEXTENSIONS.contains("EXT_image_dma_buf_import"); - m_sExts.EXT_image_dma_buf_import_modifiers = EGLEXTENSIONS.contains("EXT_image_dma_buf_import_modifiers"); + if (EGLEXTENSIONS.contains("EGL_EXT_device_base") || EGLEXTENSIONS.contains("EGL_EXT_device_enumeration")) + loadGLProc(&m_sProc.eglQueryDevicesEXT, "eglQueryDevicesEXT"); + + if (EGLEXTENSIONS.contains("EGL_EXT_device_base") || EGLEXTENSIONS.contains("EGL_EXT_device_query")) { + loadGLProc(&m_sProc.eglQueryDeviceStringEXT, "eglQueryDeviceStringEXT"); + loadGLProc(&m_sProc.eglQueryDisplayAttribEXT, "eglQueryDisplayAttribEXT"); + } + + if (EGLEXTENSIONS.contains("EGL_KHR_debug")) { + loadGLProc(&m_sProc.eglDebugMessageControlKHR, "eglDebugMessageControlKHR"); + static const EGLAttrib debugAttrs[] = { + EGL_DEBUG_MSG_CRITICAL_KHR, EGL_TRUE, EGL_DEBUG_MSG_ERROR_KHR, EGL_TRUE, EGL_DEBUG_MSG_WARN_KHR, EGL_TRUE, EGL_DEBUG_MSG_INFO_KHR, EGL_TRUE, EGL_NONE, + }; + m_sProc.eglDebugMessageControlKHR(::eglLog, debugAttrs); + } + + RASSERT(eglBindAPI(EGL_OPENGL_ES_API) != EGL_FALSE, "Couldn't bind to EGL's opengl ES API. This means your gpu driver f'd up. This is not a hyprland issue."); + + // if (m_sProc.eglQueryDevicesEXT) { + // // TODO: + // } + + if (EGLEXTENSIONS.contains("KHR_platform_gbm")) { + m_iGBMFD = openRenderNode(m_iDRMFD); + if (m_iGBMFD < 0) + RASSERT(false, "Couldn't open a gbm fd"); + + m_pGbmDevice = gbm_create_device(m_iGBMFD); + if (!m_pGbmDevice) + RASSERT(false, "Couldn't open a gbm device"); + + initEGL(true); + } else + RASSERT(false, "EGL does not support KHR_platform_gbm, this is an issue with your gpu driver."); + + auto* const EXTENSIONS = (const char*)glGetString(GL_EXTENSIONS); + RASSERT(EXTENSIONS, "Couldn't retrieve openGL extensions!"); + + m_szExtensions = EXTENSIONS; + + Debug::log(LOG, "Creating the Hypr OpenGL Renderer!"); + Debug::log(LOG, "Using: {}", (char*)glGetString(GL_VERSION)); + Debug::log(LOG, "Vendor: {}", (char*)glGetString(GL_VENDOR)); + Debug::log(LOG, "Renderer: {}", (char*)glGetString(GL_RENDERER)); + Debug::log(LOG, "Supported extensions: ({}) {}", std::count(m_szExtensions.begin(), m_szExtensions.end(), ' '), m_szExtensions); + + m_sExts.EXT_read_format_bgra = m_szExtensions.contains("GL_EXT_read_format_bgra"); RASSERT(m_szExtensions.contains("GL_EXT_texture_format_BGRA8888"), "GL_EXT_texture_format_BGRA8888 support by the GPU driver is required"); @@ -74,7 +248,7 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() { static auto P = g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any data) { preRender(std::any_cast(data)); }); - RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT), "Couldn't unset current EGL!"); + RASSERT(eglMakeCurrent(m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT), "Couldn't unset current EGL!"); m_tGlobalTimer.reset(); } @@ -86,7 +260,7 @@ std::optional> CHyprOpenGLImpl::getModsForFormat(EGLint fo return std::nullopt; EGLint len = 0; - if (!m_sProc.eglQueryDmaBufModifiersEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), format, 0, nullptr, nullptr, &len)) { + if (!m_sProc.eglQueryDmaBufModifiersEXT(m_pEglDisplay, format, 0, nullptr, nullptr, &len)) { Debug::log(ERR, "EGL: Failed to query mods"); return std::nullopt; } @@ -100,7 +274,7 @@ std::optional> CHyprOpenGLImpl::getModsForFormat(EGLint fo mods.resize(len); external.resize(len); - m_sProc.eglQueryDmaBufModifiersEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), format, len, mods.data(), external.data(), &len); + m_sProc.eglQueryDmaBufModifiersEXT(m_pEglDisplay, format, len, mods.data(), external.data(), &len); std::vector result; bool linearIsExternal = false; @@ -139,9 +313,9 @@ void CHyprOpenGLImpl::initDRMFormats() { Debug::log(WARN, "EGL: No mod support"); } else { EGLint len = 0; - m_sProc.eglQueryDmaBufFormatsEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), 0, nullptr, &len); + m_sProc.eglQueryDmaBufFormatsEXT(m_pEglDisplay, 0, nullptr, &len); formats.resize(len); - m_sProc.eglQueryDmaBufFormatsEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), len, formats.data(), &len); + m_sProc.eglQueryDmaBufFormatsEXT(m_pEglDisplay, len, formats.data(), &len); } if (formats.size() == 0) { @@ -209,7 +383,7 @@ void CHyprOpenGLImpl::initDRMFormats() { drmFormats = dmaFormats; } -EGLImageKHR CHyprOpenGLImpl::createEGLImage(const SDMABUFAttrs& attrs) { +EGLImageKHR CHyprOpenGLImpl::createEGLImage(const Aquamarine::SDMABUFAttrs& attrs) { std::vector attribs; attribs.push_back(EGL_WIDTH); @@ -251,7 +425,7 @@ EGLImageKHR CHyprOpenGLImpl::createEGLImage(const SDMABUFAttrs& attrs) { attribs.push_back(EGL_NONE); - EGLImageKHR image = m_sProc.eglCreateImageKHR(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, (int*)attribs.data()); + EGLImageKHR image = m_sProc.eglCreateImageKHR(m_pEglDisplay, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, (int*)attribs.data()); if (image == EGL_NO_IMAGE_KHR) { Debug::log(ERR, "EGL: EGLCreateImageKHR failed: {}", eglGetError()); return EGL_NO_IMAGE_KHR; @@ -915,11 +1089,8 @@ void CHyprOpenGLImpl::scissor(const CBox* pBox, bool transform) { CBox newBox = *pBox; if (transform) { - int w, h; - wlr_output_transformed_resolution(m_RenderData.pMonitor->output, &w, &h); - const auto TR = wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)); - newBox.transform(TR, w, h); + newBox.transform(TR, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); } glScissor(newBox.x, newBox.y, newBox.width, newBox.height); @@ -2474,6 +2645,9 @@ void CHyprOpenGLImpl::clearWithTex() { void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) { g_pHyprRenderer->makeEGLCurrent(); + if (!g_pHyprOpenGL) + return; + auto RESIT = g_pHyprOpenGL->m_mMonitorRenderResources.find(pMonitor); if (RESIT != g_pHyprOpenGL->m_mMonitorRenderResources.end()) { RESIT->second.mirrorFB.release(); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 814b80fee6c..ed11e3cb5c2 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -19,9 +19,11 @@ #include "Renderbuffer.hpp" #include +#include #include "../debug/TracyDefines.hpp" +struct gbm_device; class CHyprRenderer; inline const float fullVerts[] = { @@ -182,12 +184,17 @@ class CHyprOpenGLImpl { uint32_t getPreferredReadFormat(CMonitor* pMonitor); std::vector getDRMFormats(); - EGLImageKHR createEGLImage(const SDMABUFAttrs& attrs); + EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); SCurrentRenderData m_RenderData; GLint m_iCurrentOutputFb = 0; + int m_iGBMFD = -1; + gbm_device* m_pGbmDevice = nullptr; + EGLContext m_pEglContext = nullptr; + EGLDisplay m_pEglDisplay = nullptr; + bool m_bReloadScreenShader = true; // at launch it can be set PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window @@ -205,12 +212,20 @@ class CHyprOpenGLImpl { PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = nullptr; PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT = nullptr; PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT = nullptr; + PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = nullptr; + PFNEGLDEBUGMESSAGECONTROLKHRPROC eglDebugMessageControlKHR = nullptr; + PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT = nullptr; + PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT = nullptr; + PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT = nullptr; } m_sProc; struct { bool EXT_read_format_bgra = false; bool EXT_image_dma_buf_import = false; bool EXT_image_dma_buf_import_modifiers = false; + bool KHR_display_reference = false; + bool IMG_context_priority = false; + bool EXT_create_context_robustness = false; } m_sExts; private: @@ -220,7 +235,7 @@ class CHyprOpenGLImpl { std::vector drmFormats; bool m_bHasModifiers = false; - int m_iDRMFD; + int m_iDRMFD = -1; std::string m_szExtensions; bool m_bFakeFrame = false; @@ -238,6 +253,7 @@ class CHyprOpenGLImpl { void createBGTextureForMonitor(CMonitor*); void initShaders(); void initDRMFormats(); + void initEGL(bool gbm); // std::optional> getModsForFormat(EGLint format); diff --git a/src/render/Renderbuffer.cpp b/src/render/Renderbuffer.cpp index 3f591d13519..65c64eb9287 100644 --- a/src/render/Renderbuffer.cpp +++ b/src/render/Renderbuffer.cpp @@ -15,53 +15,10 @@ CRenderbuffer::~CRenderbuffer() { m_sFramebuffer.release(); glDeleteRenderbuffers(1, &m_iRBO); - g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(wlr_egl_get_display(g_pCompositor->m_sWLREGL), m_iImage); + g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(g_pHyprOpenGL->m_pEglDisplay, m_iImage); } -CRenderbuffer::CRenderbuffer(wlr_buffer* buffer, uint32_t format) : m_pWlrBuffer(buffer), m_uDrmFormat(format) { - - // EVIL, but we can't include a hidden header because nixos is fucking special - static EGLImageKHR (*PWLREGLCREATEIMAGEFROMDMABUF)(wlr_egl*, wlr_dmabuf_attributes*, bool*); - static bool symbolFound = false; - if (!symbolFound) { - PWLREGLCREATEIMAGEFROMDMABUF = reinterpret_cast(dlsym(RTLD_DEFAULT, "wlr_egl_create_image_from_dmabuf")); - - symbolFound = true; - - RASSERT(PWLREGLCREATEIMAGEFROMDMABUF, "wlr_egl_create_image_from_dmabuf was not found in wlroots!"); - - Debug::log(LOG, "CRenderbuffer: wlr_egl_create_image_from_dmabuf found at {:x}", (uintptr_t)PWLREGLCREATEIMAGEFROMDMABUF); - } - // end evil hack - - struct wlr_dmabuf_attributes dmabuf = {0}; - if (!wlr_buffer_get_dmabuf(buffer, &dmabuf)) - throw std::runtime_error("wlr_buffer_get_dmabuf failed"); - - bool externalOnly; - m_iImage = PWLREGLCREATEIMAGEFROMDMABUF(g_pCompositor->m_sWLREGL, &dmabuf, &externalOnly); - if (m_iImage == EGL_NO_IMAGE_KHR) - throw std::runtime_error("wlr_egl_create_image_from_dmabuf failed"); - - glGenRenderbuffers(1, &m_iRBO); - glBindRenderbuffer(GL_RENDERBUFFER, m_iRBO); - g_pHyprOpenGL->m_sProc.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)m_iImage); - glBindRenderbuffer(GL_RENDERBUFFER, 0); - - glGenFramebuffers(1, &m_sFramebuffer.m_iFb); - m_sFramebuffer.m_vSize = {buffer->width, buffer->height}; - m_sFramebuffer.bind(); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_iRBO); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - throw std::runtime_error("rbo: glCheckFramebufferStatus failed"); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - hyprListener_destroyBuffer.initCallback(&buffer->events.destroy, [this](void* owner, void* data) { g_pHyprRenderer->onRenderbufferDestroy(this); }, this, "CRenderbuffer"); -} - -CRenderbuffer::CRenderbuffer(SP buffer, uint32_t format) : m_pHLBuffer(buffer), m_uDrmFormat(format) { +CRenderbuffer::CRenderbuffer(SP buffer, uint32_t format) : m_pHLBuffer(buffer), m_uDrmFormat(format) { auto dma = buffer->dmabuf(); m_iImage = g_pHyprOpenGL->createEGLImage(dma); @@ -82,6 +39,8 @@ CRenderbuffer::CRenderbuffer(SP buffer, uint32_t format) : m_pHLBuffe throw std::runtime_error("rbo: glCheckFramebufferStatus failed"); glBindFramebuffer(GL_FRAMEBUFFER, 0); + + listeners.destroyBuffer = buffer->events.destroy.registerListener([this](std::any d) { g_pHyprRenderer->onRenderbufferDestroy(this); }); } void CRenderbuffer::bind() { diff --git a/src/render/Renderbuffer.hpp b/src/render/Renderbuffer.hpp index ed7050c5279..94814e23c8b 100644 --- a/src/render/Renderbuffer.hpp +++ b/src/render/Renderbuffer.hpp @@ -1,30 +1,30 @@ #pragma once #include "Framebuffer.hpp" +#include class CMonitor; -class IWLBuffer; class CRenderbuffer { public: - CRenderbuffer(wlr_buffer* buffer, uint32_t format); - CRenderbuffer(SP buffer, uint32_t format); + CRenderbuffer(SP buffer, uint32_t format); ~CRenderbuffer(); - void bind(); - void bindFB(); - void unbind(); - CFramebuffer* getFB(); - uint32_t getFormat(); + void bind(); + void bindFB(); + void unbind(); + CFramebuffer* getFB(); + uint32_t getFormat(); - wlr_buffer* m_pWlrBuffer = nullptr; - WP m_pHLBuffer = {}; - - DYNLISTENER(destroyBuffer); + WP m_pHLBuffer; private: EGLImageKHR m_iImage = 0; GLuint m_iRBO = 0; CFramebuffer m_sFramebuffer; uint32_t m_uDrmFormat = 0; + + struct { + CHyprSignalListener destroyBuffer; + } listeners; }; \ No newline at end of file diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index a7f3c94179e..9b165df185d 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -25,22 +25,23 @@ static int cursorTicker(void* data) { } CHyprRenderer::CHyprRenderer() { - if (g_pCompositor->m_sWLRSession) { - wlr_device* dev; - wl_list_for_each(dev, &g_pCompositor->m_sWLRSession->devices, link) { - const auto DRMV = drmGetVersion(dev->fd); + if (g_pCompositor->m_pAqBackend->hasSession()) { + // wlr_device* dev; + // FIXME: + // wl_list_for_each(dev, &g_pCompositor->m_sWLRSession->devices, link) { + // const auto DRMV = drmGetVersion(dev->fd); - std::string name = std::string{DRMV->name, DRMV->name_len}; - std::transform(name.begin(), name.end(), name.begin(), tolower); + // std::string name = std::string{DRMV->name, DRMV->name_len}; + // std::transform(name.begin(), name.end(), name.begin(), tolower); - if (name.contains("nvidia")) - m_bNvidia = true; + // if (name.contains("nvidia")) + // m_bNvidia = true; - Debug::log(LOG, "DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel, - std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len}); + // Debug::log(LOG, "DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel, + // std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len}); - drmFreeVersion(DRMV); - } + // drmFreeVersion(DRMV); + // } } else { Debug::log(LOG, "m_sWLRSession is null, omitting full DRM node checks"); @@ -1249,7 +1250,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { clock_gettime(CLOCK_MONOTONIC, &now); // check the damage - bool hasChanged = pMonitor->output->needs_frame || pMonitor->damage.hasChanged(); + bool hasChanged = /*pMonitor->output->needs_frame ||*/ pMonitor->damage.hasChanged(); if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->forceFullFrames == 0 && damageBlinkCleanup == 0) return; @@ -1295,7 +1296,6 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { CRegion damage, finalDamage; if (!beginRender(pMonitor, damage, RENDER_MODE_NORMAL)) { Debug::log(ERR, "renderer: couldn't beginRender()!"); - pMonitor->state.clear(); return; } @@ -1398,7 +1398,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { if (!pMonitor->mirrors.empty()) { CRegion frameDamage{}; - const auto TRANSFORM = wlr_output_transform_invert(pMonitor->output->transform); + const auto TRANSFORM = wlr_output_transform_invert(pMonitor->transform); wlr_region_transform(frameDamage.pixman(), finalDamage.pixman(), TRANSFORM, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y); if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR) @@ -1414,7 +1414,8 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { EMIT_HOOK_EVENT("render", RENDER_POST); - pMonitor->state.wlr()->tearing_page_flip = shouldTear; + pMonitor->output->state->setPresentationMode(shouldTear ? Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_IMMEDIATE : + Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC); if (!pMonitor->state.commit()) { pMonitor->damage.damageEntire(); @@ -1869,7 +1870,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } // don't touch VR headsets - if (pMonitor->output->non_desktop) + if (pMonitor->output->nonDesktop) return true; if (!pMonitor->m_bEnabled) { @@ -1910,38 +1911,36 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->scale = DEFAULTSCALE; } - wlr_output_state_set_scale(pMonitor->state.wlr(), pMonitor->scale); - pMonitor->setScale = pMonitor->scale; - - wlr_output_state_set_transform(pMonitor->state.wlr(), RULE->transform); + pMonitor->setScale = pMonitor->scale; pMonitor->transform = RULE->transform; + pMonitor->output->state->setFormat(DRM_FORMAT_XBGR8888); - const auto WLRREFRESHRATE = (wlr_backend_is_wl(pMonitor->output->backend) || wlr_backend_is_x11(pMonitor->output->backend)) ? 0 : RULE->refreshRate * 1000; + const auto WLRREFRESHRATE = pMonitor->output->getBackend()->type() == Aquamarine::eBackendType::AQ_BACKEND_DRM ? RULE->refreshRate * 1000 : 0; // loop over modes and choose an appropriate one. if (RULE->resolution != Vector2D() && RULE->resolution != Vector2D(-1, -1) && RULE->resolution != Vector2D(-1, -2)) { - if (!wl_list_empty(&pMonitor->output->modes) && RULE->drmMode.type != DRM_MODE_TYPE_USERDEF) { - wlr_output_mode* mode; - bool found = false; + if (!pMonitor->output->modes.empty() && RULE->drmMode.type != DRM_MODE_TYPE_USERDEF) { + bool found = false; - wl_list_for_each(mode, &pMonitor->output->modes, link) { + for (auto& mode : pMonitor->output->modes) { // if delta of refresh rate, w and h chosen and mode is < 1 we accept it - if (DELTALESSTHAN(mode->width, RULE->resolution.x, 1) && DELTALESSTHAN(mode->height, RULE->resolution.y, 1) && - DELTALESSTHAN(mode->refresh / 1000.f, RULE->refreshRate, 1)) { - wlr_output_state_set_mode(pMonitor->state.wlr(), mode); + if (DELTALESSTHAN(mode->pixelSize.x, RULE->resolution.x, 1) && DELTALESSTHAN(mode->pixelSize.y, RULE->resolution.y, 1) && + DELTALESSTHAN(mode->refreshRate / 1000.f, RULE->refreshRate, 1)) { + pMonitor->output->state->setMode(mode); - if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) { - Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->width, mode->height, mode->refresh / 1000.f); + if (!pMonitor->state.test()) { + Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->pixelSize.x, mode->pixelSize.y, + mode->refreshRate / 1000.f); continue; } Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, RULE->resolution, - (float)RULE->refreshRate, mode->width, mode->height, mode->refresh); + (float)RULE->refreshRate, mode->pixelSize.x, mode->pixelSize.y, mode->refreshRate); found = true; - pMonitor->refreshRate = mode->refresh / 1000.f; - pMonitor->vecSize = Vector2D(mode->width, mode->height); + pMonitor->refreshRate = mode->refreshRate / 1000.f; + pMonitor->vecSize = mode->pixelSize; pMonitor->currentMode = mode; break; @@ -1949,14 +1948,14 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } if (!found) { - wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)RULE->resolution.x, (int)RULE->resolution.y, WLRREFRESHRATE); + pMonitor->output->state->setCustomMode(makeShared(Aquamarine::SOutputMode{.pixelSize = RULE->resolution, .refreshRate = WLRREFRESHRATE})); pMonitor->vecSize = RULE->resolution; pMonitor->refreshRate = RULE->refreshRate; - if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) { + if (!pMonitor->state.test()) { Debug::log(ERR, "Custom resolution FAILED, falling back to preferred"); - const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output); + const auto PREFERREDMODE = pMonitor->output->preferredMode(); if (!PREFERREDMODE) { Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, RULE->resolution, @@ -1965,13 +1964,13 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } // Preferred is valid - wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE); + pMonitor->output->state->setMode(PREFERREDMODE); Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution, - (float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f); + (float)RULE->refreshRate, PREFERREDMODE->pixelSize.x, PREFERREDMODE->pixelSize.y, PREFERREDMODE->refreshRate / 1000.f); - pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f; - pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height); + pMonitor->refreshRate = PREFERREDMODE->refreshRate / 1000.f; + pMonitor->vecSize = PREFERREDMODE->pixelSize; pMonitor->currentMode = PREFERREDMODE; } else { Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", RULE->resolution, (float)RULE->refreshRate); @@ -1982,30 +1981,30 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR bool fail = false; if (RULE->drmMode.type == DRM_MODE_TYPE_USERDEF) { - if (!wlr_output_is_drm(pMonitor->output)) { + if (pMonitor->output->getBackend()->type() != Aquamarine::eBackendType::AQ_BACKEND_DRM) { Debug::log(ERR, "Tried to set custom modeline on non-DRM output"); fail = true; } else { - auto* mode = wlr_drm_connector_add_mode(pMonitor->output, &RULE->drmMode); - if (mode) { - wlr_output_state_set_mode(pMonitor->state.wlr(), mode); - pMonitor->customDrmMode = RULE->drmMode; - } else { - Debug::log(ERR, "wlr_drm_connector_add_mode failed"); - fail = true; - } + // FIXME: + // auto* mode = wlr_drm_connector_add_mode(pMonitor->output, &RULE->drmMode); + // if (mode) { + // wlr_output_state_set_mode(pMonitor->state.wlr(), mode); + // pMonitor->customDrmMode = RULE->drmMode; + // } else { + // Debug::log(ERR, "wlr_drm_connector_add_mode failed"); + // fail = true; + // } } - } else { - wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)RULE->resolution.x, (int)RULE->resolution.y, WLRREFRESHRATE); - } + } else + pMonitor->output->state->setCustomMode(makeShared(Aquamarine::SOutputMode{.pixelSize = RULE->resolution, .refreshRate = WLRREFRESHRATE})); pMonitor->vecSize = RULE->resolution; pMonitor->refreshRate = RULE->refreshRate; - if (fail || !wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) { + if (fail || !pMonitor->state.test()) { Debug::log(ERR, "Custom resolution FAILED, falling back to preferred"); - const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output); + const auto PREFERREDMODE = pMonitor->output->preferredMode(); if (!PREFERREDMODE) { Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->output->name, RULE->resolution, @@ -2014,48 +2013,47 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } // Preferred is valid - wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE); + pMonitor->output->state->setMode(PREFERREDMODE); Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution, - (float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f); + (float)RULE->refreshRate, PREFERREDMODE->pixelSize.x, PREFERREDMODE->pixelSize.y, PREFERREDMODE->refreshRate / 1000.f); - pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f; - pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height); + pMonitor->refreshRate = PREFERREDMODE->refreshRate / 1000.f; + pMonitor->vecSize = PREFERREDMODE->pixelSize; pMonitor->customDrmMode = {}; - } else { + } else Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", RULE->resolution, (float)RULE->refreshRate); - } } } else if (RULE->resolution != Vector2D()) { - if (!wl_list_empty(&pMonitor->output->modes)) { - wlr_output_mode* mode; - float currentWidth = 0; - float currentHeight = 0; - float currentRefresh = 0; - bool success = false; + if (!pMonitor->output->modes.empty()) { + float currentWidth = 0; + float currentHeight = 0; + float currentRefresh = 0; + bool success = false; //(-1,-1) indicates a preference to refreshrate over resolution, (-1,-2) preference to resolution if (RULE->resolution == Vector2D(-1, -1)) { - wl_list_for_each(mode, &pMonitor->output->modes, link) { - if ((mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= (currentRefresh - 1000.f)) || mode->refresh > (currentRefresh + 3000.f)) { - wlr_output_state_set_mode(pMonitor->state.wlr(), mode); - if (wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) { - currentWidth = mode->width; - currentHeight = mode->height; - currentRefresh = mode->refresh; + for (auto& mode : pMonitor->output->modes) { + if ((mode->pixelSize.x >= currentWidth && mode->pixelSize.y >= currentHeight && mode->refreshRate >= (currentRefresh - 1000.f)) || + mode->refreshRate > (currentRefresh + 3000.f)) { + pMonitor->output->state->setMode(mode); + if (pMonitor->state.test()) { + currentWidth = mode->pixelSize.x; + currentHeight = mode->pixelSize.y; + currentRefresh = mode->refreshRate; success = true; } } } } else { - wl_list_for_each(mode, &pMonitor->output->modes, link) { - if ((mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= (currentRefresh - 1000.f)) || - (mode->width > currentWidth && mode->height > currentHeight)) { - wlr_output_state_set_mode(pMonitor->state.wlr(), mode); - if (wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) { - currentWidth = mode->width; - currentHeight = mode->height; - currentRefresh = mode->refresh; + for (auto& mode : pMonitor->output->modes) { + if ((mode->pixelSize.x >= currentWidth && mode->pixelSize.y >= currentHeight && mode->refreshRate >= (currentRefresh - 1000.f)) || + (mode->pixelSize.x > currentWidth && mode->pixelSize.y > currentHeight)) { + pMonitor->output->state->setMode(mode); + if (pMonitor->state.test()) { + currentWidth = mode->pixelSize.x; + currentHeight = mode->pixelSize.y; + currentRefresh = mode->refreshRate; success = true; } } @@ -2063,10 +2061,12 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } if (!success) { - Debug::log(LOG, "Monitor {}: REJECTED mode: {:X0}@{:2f}! Falling back to preferred: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution, - (float)RULE->refreshRate, mode->width, mode->height, mode->refresh / 1000.f); + if (pMonitor->output->state->state().mode) + Debug::log(LOG, "Monitor {}: REJECTED mode: {:X0}@{:2f}! Falling back to preferred: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution, + (float)RULE->refreshRate, pMonitor->output->state->state().mode->pixelSize.x, pMonitor->output->state->state().mode->pixelSize.y, + pMonitor->output->state->state().mode->refreshRate / 1000.f); - const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output); + const auto PREFERREDMODE = pMonitor->output->preferredMode(); if (!PREFERREDMODE) { Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, RULE->resolution, (float)RULE->refreshRate); @@ -2074,13 +2074,13 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } // Preferred is valid - wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE); + pMonitor->output->state->setMode(PREFERREDMODE); Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution, - (float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f); + (float)RULE->refreshRate, PREFERREDMODE->pixelSize.x, PREFERREDMODE->pixelSize.y, PREFERREDMODE->refreshRate / 1000.f); - pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f; - pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height); + pMonitor->refreshRate = PREFERREDMODE->refreshRate / 1000.f; + pMonitor->vecSize = PREFERREDMODE->pixelSize; pMonitor->currentMode = PREFERREDMODE; } else { @@ -2091,27 +2091,26 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } } } else { - const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output); + const auto PREFERREDMODE = pMonitor->output->preferredMode(); if (!PREFERREDMODE) { Debug::log(ERR, "Monitor {} has NO PREFERRED MODE", pMonitor->output->name); - if (!wl_list_empty(&pMonitor->output->modes)) { - wlr_output_mode* mode; - - wl_list_for_each(mode, &pMonitor->output->modes, link) { - wlr_output_state_set_mode(pMonitor->state.wlr(), mode); + if (!pMonitor->output->modes.empty()) { + for (auto& mode : pMonitor->output->modes) { + pMonitor->output->state->setMode(mode); - if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) { - Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->width, mode->height, mode->refresh / 1000.f); + if (!pMonitor->state.test()) { + Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->pixelSize.x, mode->pixelSize.y, + mode->refreshRate / 1000.f); continue; } Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, RULE->resolution, - (float)RULE->refreshRate, mode->width, mode->height, mode->refresh); + (float)RULE->refreshRate, mode->pixelSize.x, mode->pixelSize.y, mode->refreshRate); - pMonitor->refreshRate = mode->refresh / 1000.f; - pMonitor->vecSize = Vector2D(mode->width, mode->height); + pMonitor->refreshRate = mode->refreshRate / 1000.f; + pMonitor->vecSize = mode->pixelSize; pMonitor->currentMode = mode; break; @@ -2119,18 +2118,18 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } } else { // Preferred is valid - wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE); + pMonitor->output->state->setMode(PREFERREDMODE); - pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height); - pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f; + pMonitor->vecSize = PREFERREDMODE->pixelSize; + pMonitor->refreshRate = PREFERREDMODE->refreshRate / 1000.f; pMonitor->currentMode = PREFERREDMODE; Debug::log(LOG, "Setting preferred mode for {}", pMonitor->output->name); } } - pMonitor->vrrActive = pMonitor->state.wlr()->adaptive_sync_enabled // disabled here, will be tested in CConfigManager::ensureVRR() - || pMonitor->createdByUser; // wayland backend doesn't allow for disabling adaptive_sync + pMonitor->vrrActive = pMonitor->output->state->state().adaptiveSync // disabled here, will be tested in CConfigManager::ensureVRR() + || pMonitor->createdByUser; // wayland backend doesn't allow for disabling adaptive_sync pMonitor->vecPixelSize = pMonitor->vecSize; @@ -2145,10 +2144,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR double scaleZero = searchScale / 120.0; Vector2D logicalZero = pMonitor->vecPixelSize / scaleZero; - if (logicalZero == logicalZero.round()) { + if (logicalZero == logicalZero.round()) pMonitor->scale = scaleZero; - wlr_output_state_set_scale(pMonitor->state.wlr(), pMonitor->scale); - } else { + else { for (size_t i = 1; i < 90; ++i) { double scaleUp = (searchScale + i) / 120.0; double scaleDown = (searchScale - i) / 120.0; @@ -2185,12 +2183,6 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } else pMonitor->scale = searchScale; } - - // for wlroots, that likes flooring, we have to do this. - double logicalX = std::round(pMonitor->vecPixelSize.x / pMonitor->scale); - logicalX += 0.1; - - wlr_output_state_set_scale(pMonitor->state.wlr(), pMonitor->vecPixelSize.x / logicalX); } } @@ -2209,9 +2201,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->drmFormat = DRM_FORMAT_INVALID; for (auto& fmt : formats[(int)!RULE->enable10bit]) { - wlr_output_state_set_render_format(pMonitor->state.wlr(), fmt.second); + pMonitor->output->state->setFormat(fmt.second); - if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) { + if (!pMonitor->state.test()) { Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first); } else { Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first); @@ -2225,17 +2217,18 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->enabled10bit = set10bit; + pMonitor->output->scheduleFrame(); + if (!pMonitor->state.commit()) Debug::log(ERR, "Couldn't commit output named {}", pMonitor->output->name); - int x, y; - wlr_output_transformed_resolution(pMonitor->output, &x, &y); - pMonitor->vecSize = (Vector2D(x, y) / pMonitor->scale).round(); - pMonitor->vecTransformedSize = Vector2D(x, y); + Vector2D xfmd = pMonitor->transform % 2 == 1 ? Vector2D{pMonitor->vecPixelSize.y, pMonitor->vecPixelSize.x} : pMonitor->vecPixelSize; + pMonitor->vecSize = (xfmd / pMonitor->scale).round(); + pMonitor->vecTransformedSize = xfmd; if (pMonitor->createdByUser) { CBox transformedBox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; - transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(pMonitor->output->transform)), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); + transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(pMonitor->transform)), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); pMonitor->vecPixelSize = Vector2D(transformedBox.width, transformedBox.height); } @@ -2260,9 +2253,6 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR // updato us arrangeLayersForMonitor(pMonitor->ID); - // frame skip - pMonitor->framesToSkip = 1; - // reload to fix mirrors g_pConfigManager->m_bWantsMonitorReload = true; @@ -2329,7 +2319,7 @@ void CHyprRenderer::ensureCursorRenderingMode() { Debug::log(LOG, "Hiding the cursor (hl-mandated)"); for (auto& m : g_pCompositor->m_vMonitors) { - if (m->output->software_cursor_locks == 0) + if (!g_pPointerManager->softwareLockedFor(m)) continue; g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area? @@ -2341,7 +2331,7 @@ void CHyprRenderer::ensureCursorRenderingMode() { Debug::log(LOG, "Showing the cursor (hl-mandated)"); for (auto& m : g_pCompositor->m_vMonitors) { - if (m->output->software_cursor_locks == 0) + if (!g_pPointerManager->softwareLockedFor(m)) continue; g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area? @@ -2570,16 +2560,7 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { pMonitor->solitaryClient = PCANDIDATE; } -CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(wlr_buffer* buffer, uint32_t fmt) { - auto it = std::find_if(m_vRenderbuffers.begin(), m_vRenderbuffers.end(), [&](const auto& other) { return other->m_pWlrBuffer == buffer; }); - - if (it != m_vRenderbuffers.end()) - return it->get(); - - return m_vRenderbuffers.emplace_back(std::make_unique(buffer, fmt)).get(); -} - -CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(SP buffer, uint32_t fmt) { +CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(SP buffer, uint32_t fmt) { auto it = std::find_if(m_vRenderbuffers.begin(), m_vRenderbuffers.end(), [&](const auto& other) { return other->m_pHLBuffer == buffer; }); if (it != m_vRenderbuffers.end()) @@ -2589,18 +2570,21 @@ CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(SP buffer, uint } void CHyprRenderer::makeEGLCurrent() { - if (!g_pCompositor) + if (!g_pCompositor || !g_pHyprOpenGL) return; - if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL)) - eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)); + if (eglGetCurrentContext() != g_pHyprOpenGL->m_pEglContext) + eglMakeCurrent(g_pHyprOpenGL->m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, g_pHyprOpenGL->m_pEglContext); } void CHyprRenderer::unsetEGL() { - eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (!g_pHyprOpenGL) + return; + + eglMakeCurrent(g_pHyprOpenGL->m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } -bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, SP buffer, CFramebuffer* fb, bool simple) { +bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, SP buffer, CFramebuffer* fb, bool simple) { makeEGLCurrent(); @@ -2621,27 +2605,18 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode int bufferAge = 0; if (!buffer) { - if (!wlr_output_configure_primary_swapchain(pMonitor->output, pMonitor->state.wlr(), &pMonitor->output->swapchain)) { - Debug::log(ERR, "Failed to configure primary swapchain for {}", pMonitor->szName); - return false; - } - - m_pCurrentWlrBuffer = wlr_swapchain_acquire(pMonitor->output->swapchain, &bufferAge); - if (!m_pCurrentWlrBuffer) { + m_pCurrentBuffer = pMonitor->output->swapchain->next(&bufferAge); + if (!m_pCurrentBuffer) { Debug::log(ERR, "Failed to acquire swapchain buffer for {}", pMonitor->szName); return false; } } else - m_pCurrentHLBuffer = buffer; + m_pCurrentBuffer = buffer; try { - if (m_pCurrentWlrBuffer) - m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentWlrBuffer, pMonitor->drmFormat); - else - m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentHLBuffer.lock(), pMonitor->drmFormat); + m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentBuffer, pMonitor->drmFormat); } catch (std::exception& e) { Debug::log(ERR, "getOrCreateRenderbuffer failed for {}", pMonitor->szName); - wlr_buffer_unlock(m_pCurrentWlrBuffer); return false; } @@ -2679,17 +2654,13 @@ void CHyprRenderer::endRender() { else glFlush(); - if (m_eRenderMode == RENDER_MODE_NORMAL) { - wlr_output_state_set_buffer(PMONITOR->state.wlr(), m_pCurrentWlrBuffer); - unsetEGL(); // flush the context - } - - wlr_buffer_unlock(m_pCurrentWlrBuffer); + if (m_eRenderMode == RENDER_MODE_NORMAL) + PMONITOR->output->state->setBuffer(m_pCurrentBuffer); m_pCurrentRenderbuffer->unbind(); m_pCurrentRenderbuffer = nullptr; - m_pCurrentWlrBuffer = nullptr; + m_pCurrentBuffer = nullptr; } void CHyprRenderer::onRenderbufferDestroy(CRenderbuffer* rb) { diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 8f404c88fa3..81b9e55bd87 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -12,7 +12,7 @@ struct SMonitorRule; class CWorkspace; class CWindow; class CInputPopup; -class IWLBuffer; +class IHLBuffer; // TODO: add fuller damage tracking for updating only parts of a window enum DAMAGETRACKINGMODES { @@ -76,7 +76,7 @@ class CHyprRenderer { // if RENDER_MODE_NORMAL, provided damage will be written to. // otherwise, it will be the one used. - bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP buffer = {}, CFramebuffer* fb = nullptr, bool simple = false); + bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP buffer = {}, CFramebuffer* fb = nullptr, bool simple = false); void endRender(); bool m_bBlockSurfaceFeedback = false; @@ -122,11 +122,10 @@ class CHyprRenderer { bool m_bCursorHidden = false; bool m_bCursorHasSurface = false; CRenderbuffer* m_pCurrentRenderbuffer = nullptr; - wlr_buffer* m_pCurrentWlrBuffer = nullptr; - WP m_pCurrentHLBuffer = {}; - eRenderMode m_eRenderMode = RENDER_MODE_NORMAL; + SP m_pCurrentBuffer; + eRenderMode m_eRenderMode = RENDER_MODE_NORMAL; - bool m_bNvidia = false; + bool m_bNvidia = false; struct { bool hiddenOnTouch = false; @@ -134,8 +133,7 @@ class CHyprRenderer { bool hiddenOnKeyboard = false; } m_sCursorHiddenConditions; - CRenderbuffer* getOrCreateRenderbuffer(wlr_buffer* buffer, uint32_t fmt); - CRenderbuffer* getOrCreateRenderbuffer(SP buffer, uint32_t fmt); + CRenderbuffer* getOrCreateRenderbuffer(SP buffer, uint32_t fmt); std::vector> m_vRenderbuffers; friend class CHyprOpenGLImpl; diff --git a/src/render/Texture.cpp b/src/render/Texture.cpp index 46c501a0679..f72fa3a4b35 100644 --- a/src/render/Texture.cpp +++ b/src/render/Texture.cpp @@ -17,6 +17,62 @@ CTexture::~CTexture() { } CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_) { + createFromShm(drmFormat, pixels, stride, size_); +} + +CTexture::CTexture(wlr_texture* tex) { + RASSERT(wlr_texture_is_gles2(tex), "wlr_texture provided to CTexture that isn't GLES2!"); + wlr_gles2_texture_attribs attrs; + wlr_gles2_texture_get_attribs(tex, &attrs); + + m_iTarget = attrs.target; + m_iTexID = attrs.tex; + m_bNonOwning = true; + + if (m_iTarget == GL_TEXTURE_2D) + m_iType = attrs.has_alpha ? TEXTURE_RGBA : TEXTURE_RGBX; + else + m_iType = TEXTURE_EXTERNAL; + + m_vSize = Vector2D((int)tex->width, (int)tex->height); +} + +CTexture::CTexture(const Aquamarine::SDMABUFAttrs& attrs, void* image) { + createFromDma(attrs, image); +} + +CTexture::CTexture(const SP buffer) { + if (!buffer) + return; + + auto attrs = buffer->dmabuf(); + + if (!attrs.success) { + // attempt shm + auto shm = buffer->shm(); + + if (!shm.success) { + Debug::log(ERR, "Cannot create a texture: buffer has no dmabuf or shm"); + return; + } + + auto [pixelData, fmt, bufLen] = buffer->beginDataPtr(0); + + createFromShm(fmt, pixelData, bufLen, shm.size); + return; + } + + auto image = g_pHyprOpenGL->createEGLImage(buffer->dmabuf()); + + if (!image) { + Debug::log(ERR, "Cannot create a texture: failed to create an EGLImage"); + return; + } + + createFromDma(attrs, image); +} + +void CTexture::createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_) { g_pHyprRenderer->makeEGLCurrent(); const auto format = FormatUtils::getPixelFormatFromDRM(drmFormat); @@ -41,24 +97,7 @@ CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const V GLCALL(glBindTexture(GL_TEXTURE_2D, 0)); } -CTexture::CTexture(wlr_texture* tex) { - RASSERT(wlr_texture_is_gles2(tex), "wlr_texture provided to CTexture that isn't GLES2!"); - wlr_gles2_texture_attribs attrs; - wlr_gles2_texture_get_attribs(tex, &attrs); - - m_iTarget = attrs.target; - m_iTexID = attrs.tex; - m_bNonOwning = true; - - if (m_iTarget == GL_TEXTURE_2D) - m_iType = attrs.has_alpha ? TEXTURE_RGBA : TEXTURE_RGBX; - else - m_iType = TEXTURE_EXTERNAL; - - m_vSize = Vector2D((int)tex->width, (int)tex->height); -} - -CTexture::CTexture(const SDMABUFAttrs& attrs, void* image) { +void CTexture::createFromDma(const Aquamarine::SDMABUFAttrs& attrs, void* image) { if (!g_pHyprOpenGL->m_sProc.glEGLImageTargetTexture2DOES) { Debug::log(ERR, "Cannot create a dmabuf texture: no glEGLImageTargetTexture2DOES"); return; @@ -119,7 +158,7 @@ void CTexture::destroyTexture() { } if (m_pEglImage) - g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(wlr_egl_get_display(g_pCompositor->m_sWLREGL), m_pEglImage); + g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(g_pHyprOpenGL->m_pEglDisplay, m_pEglImage); m_pEglImage = nullptr; } diff --git a/src/render/Texture.hpp b/src/render/Texture.hpp index c80e943daeb..4c5c2c766d5 100644 --- a/src/render/Texture.hpp +++ b/src/render/Texture.hpp @@ -1,9 +1,9 @@ #pragma once #include "../defines.hpp" +#include -class IWLBuffer; -struct SDMABUFAttrs; +class IHLBuffer; HYPRUTILS_FORWARD(Math, CRegion); enum TEXTURETYPE { @@ -25,8 +25,9 @@ class CTexture { CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size); CTexture(wlr_texture*); + CTexture(const SP buffer); // this ctor takes ownership of the eglImage. - CTexture(const SDMABUFAttrs&, void* image); + CTexture(const Aquamarine::SDMABUFAttrs&, void* image); ~CTexture(); void destroyTexture(); @@ -39,4 +40,8 @@ class CTexture { Vector2D m_vSize; void* m_pEglImage = nullptr; bool m_bNonOwning = false; // wlr + + private: + void createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size); + void createFromDma(const Aquamarine::SDMABUFAttrs&, void* image); }; \ No newline at end of file From ac78133b4c5fdc0ad8ade9ae7be7ae57bd0a58aa Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 23 Jun 2024 19:38:56 +0200 Subject: [PATCH 002/113] add drm backend to requests --- src/Compositor.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 07843d92bc1..5cde583f287 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -227,10 +227,13 @@ void CCompositor::initServer() { options.logFunction = aqLog; std::vector implementations; - Aquamarine::SBackendImplementationOptions waylandOptions; - waylandOptions.backendType = Aquamarine::eBackendType::AQ_BACKEND_WAYLAND; - waylandOptions.backendRequestMode = Aquamarine::eBackendRequestMode::AQ_BACKEND_REQUEST_IF_AVAILABLE; - implementations.emplace_back(waylandOptions); + Aquamarine::SBackendImplementationOptions option; + option.backendType = Aquamarine::eBackendType::AQ_BACKEND_DRM; + option.backendRequestMode = Aquamarine::eBackendRequestMode::AQ_BACKEND_REQUEST_IF_AVAILABLE; + implementations.emplace_back(option); + option.backendType = Aquamarine::eBackendType::AQ_BACKEND_WAYLAND; + option.backendRequestMode = Aquamarine::eBackendRequestMode::AQ_BACKEND_REQUEST_FALLBACK; + implementations.emplace_back(option); m_pAqBackend = CBackend::create(implementations, options); From 2dbb77b16bb410ceb91af94d9a473fccf7947947 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 23 Jun 2024 19:43:47 +0200 Subject: [PATCH 003/113] bring back renderer session scan --- src/render/Renderer.cpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 9b165df185d..40edf4ef84d 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -26,24 +26,23 @@ static int cursorTicker(void* data) { CHyprRenderer::CHyprRenderer() { if (g_pCompositor->m_pAqBackend->hasSession()) { - // wlr_device* dev; - // FIXME: - // wl_list_for_each(dev, &g_pCompositor->m_sWLRSession->devices, link) { - // const auto DRMV = drmGetVersion(dev->fd); - - // std::string name = std::string{DRMV->name, DRMV->name_len}; - // std::transform(name.begin(), name.end(), name.begin(), tolower); + for (auto& dev : g_pCompositor->m_pAqBackend->session->sessionDevices) { + const auto DRMV = drmGetVersion(dev->fd); + if (!DRMV) + continue; + std::string name = std::string{DRMV->name, DRMV->name_len}; + std::transform(name.begin(), name.end(), name.begin(), tolower); - // if (name.contains("nvidia")) - // m_bNvidia = true; + if (name.contains("nvidia")) + m_bNvidia = true; - // Debug::log(LOG, "DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel, - // std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len}); + Debug::log(LOG, "DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel, + std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len}); - // drmFreeVersion(DRMV); - // } + drmFreeVersion(DRMV); + } } else { - Debug::log(LOG, "m_sWLRSession is null, omitting full DRM node checks"); + Debug::log(LOG, "Aq backend has no session, omitting full DRM node checks"); const auto DRMV = drmGetVersion(g_pCompositor->m_iDRMFD); From 2b7c89474b97e8faf121b635bf7226fcbecc4c99 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 24 Jun 2024 23:22:27 +0200 Subject: [PATCH 004/113] minor fixes for new drm stuff --- src/Compositor.cpp | 3 +++ src/debug/HyprCtl.cpp | 43 +++++++++++++++++++++++++++++++++++++++++ src/render/Renderer.cpp | 13 +++++++++++-- 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 5cde583f287..a938e4b0a59 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -258,6 +258,7 @@ void CCompositor::initServer() { m_bInitialized = true; m_iDRMFD = m_pAqBackend->drmFD(); + Debug::log(LOG, "Running on DRMFD: {}", m_iDRMFD); initManagers(STAGE_BASICINIT); @@ -2852,6 +2853,8 @@ void CCompositor::onNewMonitor(SP output) { if (std::string("HEADLESS-1") == output->name) g_pCompositor->m_pUnsafeOutput = PNEWMONITOR.get(); + Debug::log(LOG, "New output with name {}", output->name); + PNEWMONITOR->szName = output->name; PNEWMONITOR->output = output; PNEWMONITOR->self = PNEWMONITOR; diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 459860376bd..8e55886b23d 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -131,6 +131,49 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer return result; } +std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { + CVarList vars(request, 0, ' '); + auto allMonitors = false; + + if (vars.size() > 2) + return "too many args"; + + if (vars.size() == 2 && vars[1] == "all") + allMonitors = true; + + std::string result = ""; + if (format == eHyprCtlOutputFormat::FORMAT_JSON) { + result += "["; + + for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) { + result += CHyprCtl::getMonitorData(m, format); + } + + trimTrailingComma(result); + + result += "]"; + } else { + for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) { + if (!m->output || m->ID == -1ull) + continue; + + result += std::format( + "Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" + "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" + "dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n", + m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription, + m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), + (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), + (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, + (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, (int)(m->output->state ? m->output->state->state().adaptiveSync : false), + m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); + } + } + + return result; +} + + static std::string getTagsData(PHLWINDOW w, eHyprCtlOutputFormat format) { const auto tags = w->m_tags.getTags(); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 40edf4ef84d..11a64589704 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -27,7 +27,7 @@ static int cursorTicker(void* data) { CHyprRenderer::CHyprRenderer() { if (g_pCompositor->m_pAqBackend->hasSession()) { for (auto& dev : g_pCompositor->m_pAqBackend->session->sessionDevices) { - const auto DRMV = drmGetVersion(dev->fd); + const auto DRMV = drmGetVersion(dev->fd); if (!DRMV) continue; std::string name = std::string{DRMV->name, DRMV->name_len}; @@ -1249,7 +1249,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { clock_gettime(CLOCK_MONOTONIC, &now); // check the damage - bool hasChanged = /*pMonitor->output->needs_frame ||*/ pMonitor->damage.hasChanged(); + bool hasChanged = pMonitor->output->needsFrame || pMonitor->damage.hasChanged(); if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->forceFullFrames == 0 && damageBlinkCleanup == 0) return; @@ -2604,6 +2604,15 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode int bufferAge = 0; if (!buffer) { + Aquamarine::SSwapchainOptions opts = pMonitor->output->swapchain->currentOptions(); + opts.length = 2; + opts.size = pMonitor->currentMode->pixelSize; + opts.format = pMonitor->drmFormat; + if (!pMonitor->output->swapchain->reconfigure(opts)) { + Debug::log(ERR, "Failed to reconfigure swapchain for {}", pMonitor->szName); + return false; + } + m_pCurrentBuffer = pMonitor->output->swapchain->next(&bufferAge); if (!m_pCurrentBuffer) { Debug::log(ERR, "Failed to acquire swapchain buffer for {}", pMonitor->szName); From 24d8e2cfe39cde538dc2702f16802dfb31c21892 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 25 Jun 2024 13:39:45 +0200 Subject: [PATCH 005/113] restore vt switching --- src/managers/KeybindManager.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 54c13f87499..a98be2c3b51 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -810,9 +810,7 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) { Debug::log(LOG, "Switching from VT {} to VT {}", ttynum, TTY); - // FIXME: - //wlr_session_change_vt(g_pCompositor->m_sWLRSession, TTY); - return true; + g_pCompositor->m_pAqBackend->session->switchVT(TTY); } return true; From c49ab9e9f3c08e9f02847389727677f95b72bf25 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 25 Jun 2024 18:23:27 +0200 Subject: [PATCH 006/113] fix dt issues --- src/render/Renderer.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 11a64589704..7270a14a1b0 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2601,7 +2601,9 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode return true; } - int bufferAge = 0; + /* This is a constant expression, as we always use double-buffering in our swapchain + TODO: Rewrite the CDamageRing to take advantage of that maybe? It's made to support longer swapchains atm because we used to do wlroots */ + static constexpr const int HL_BUFFER_AGE = 2; if (!buffer) { Aquamarine::SSwapchainOptions opts = pMonitor->output->swapchain->currentOptions(); @@ -2613,7 +2615,7 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode return false; } - m_pCurrentBuffer = pMonitor->output->swapchain->next(&bufferAge); + m_pCurrentBuffer = pMonitor->output->swapchain->next(nullptr); if (!m_pCurrentBuffer) { Debug::log(ERR, "Failed to acquire swapchain buffer for {}", pMonitor->szName); return false; @@ -2629,7 +2631,7 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode } if (mode == RENDER_MODE_NORMAL) { - damage = pMonitor->damage.getBufferDamage(bufferAge); + damage = pMonitor->damage.getBufferDamage(HL_BUFFER_AGE); pMonitor->damage.rotate(); } From 9ad03ed23147d886b9124a119115cf73d0c68041 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 25 Jun 2024 18:31:45 +0200 Subject: [PATCH 007/113] update key state on key events to have mods working in drm --- src/devices/IKeyboard.hpp | 2 +- src/devices/Keyboard.cpp | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index fec856061da..f1f355ecc96 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -57,6 +57,7 @@ class IKeyboard : public IHID { void updateLEDs(uint32_t leds); uint32_t getModifiers(); void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); + bool updateModifiersState(); // rets whether changed bool active = false; bool enabled = true; @@ -88,5 +89,4 @@ class IKeyboard : public IHID { private: void clearManuallyAllocd(); - bool updateModifiersState(); // rets whether changed }; diff --git a/src/devices/Keyboard.cpp b/src/devices/Keyboard.cpp index 514bef2b89c..56ec7bfb7cb 100644 --- a/src/devices/Keyboard.cpp +++ b/src/devices/Keyboard.cpp @@ -1,5 +1,6 @@ #include "Keyboard.hpp" #include "../defines.hpp" +#include "../Compositor.hpp" #include @@ -29,7 +30,14 @@ CKeyboard::CKeyboard(SP keeb) : keyboard(keeb) { }); listeners.key = keeb->events.key.registerListener([this](std::any d) { - auto E = std::any_cast(d); + auto E = std::any_cast(d); + + uint32_t xkbKeycode = E.key + 8; + xkb_state_update_key(xkbTranslationState, xkbKeycode, E.pressed ? XKB_KEY_DOWN : XKB_KEY_UP); + + // we have to do this for DRM sessions, as they never send modifiers events + if (g_pCompositor->m_pAqBackend->hasSession()) + updateModifiersState(); keyboardEvents.key.emit(SKeyEvent{ .timeMs = E.timeMs, From 7dee974be8915864e05e1b3cc8bb3eb3fdb7fc90 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 25 Jun 2024 19:59:15 +0200 Subject: [PATCH 008/113] minor fixes for wl --- src/render/Renderer.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 7270a14a1b0..f0a574c03d3 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2606,10 +2606,13 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode static constexpr const int HL_BUFFER_AGE = 2; if (!buffer) { + const auto& MODE = pMonitor->output->state->state().mode ? pMonitor->output->state->state().mode : pMonitor->output->state->state().customMode; + if (!MODE) // no mode?? + return false; Aquamarine::SSwapchainOptions opts = pMonitor->output->swapchain->currentOptions(); opts.length = 2; - opts.size = pMonitor->currentMode->pixelSize; - opts.format = pMonitor->drmFormat; + opts.size = MODE->pixelSize; + opts.format = pMonitor->output->state->state().drmFormat; if (!pMonitor->output->swapchain->reconfigure(opts)) { Debug::log(ERR, "Failed to reconfigure swapchain for {}", pMonitor->szName); return false; From 3cc4387d73afbc79c95768b10dc241fcc296d6d4 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 26 Jun 2024 12:30:03 +0200 Subject: [PATCH 009/113] keyboard mod fixes --- src/debug/HyprCtl.cpp | 2 +- src/devices/IKeyboard.cpp | 65 +++++++++++++++++------------ src/devices/IKeyboard.hpp | 5 ++- src/devices/Keyboard.cpp | 7 +--- src/managers/KeybindManager.cpp | 6 +-- src/managers/input/InputManager.cpp | 17 +------- 6 files changed, 49 insertions(+), 53 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 8e55886b23d..703ff79bbad 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1141,7 +1141,7 @@ std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string requ const auto LAYOUTS = xkb_keymap_num_layouts(KEEB->xkbKeymap); xkb_layout_index_t activeLayout = 0; while (activeLayout < LAYOUTS) { - if (xkb_state_layout_index_is_active(KEEB->xkbTranslationState, activeLayout, XKB_STATE_LAYOUT_EFFECTIVE) == 1) + if (xkb_state_layout_index_is_active(KEEB->xkbState, activeLayout, XKB_STATE_LAYOUT_EFFECTIVE) == 1) break; activeLayout++; diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index 5ecba556e55..eb475b730d4 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -27,11 +27,11 @@ IKeyboard::~IKeyboard() { } void IKeyboard::clearManuallyAllocd() { - if (xkbTranslationState) - xkb_state_unref(xkbTranslationState); + if (xkbStaticState) + xkb_state_unref(xkbStaticState); - if (xkbInternalTranslationState) - xkb_state_unref(xkbInternalTranslationState); + if (xkbState) + xkb_state_unref(xkbState); if (xkbKeymap) xkb_keymap_unref(xkbKeymap); @@ -39,9 +39,10 @@ void IKeyboard::clearManuallyAllocd() { if (xkbKeymapFD >= 0) close(xkbKeymapFD); - xkbKeymap = nullptr; - xkbTranslationState = nullptr; - xkbKeymapFD = -1; + xkbKeymap = nullptr; + xkbState = nullptr; + xkbStaticState = nullptr; + xkbKeymapFD = -1; } void IKeyboard::setKeymap(const SStringRuleNames& rules) { @@ -99,9 +100,9 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) { // set internal translation state // demo sunao ni ienai - xkbInternalTranslationState = xkb_state_new(xkbKeymap); + xkbStaticState = xkb_state_new(xkbKeymap); - updateXKBTranslationState(); + updateXKBTranslationState(xkbKeymap); const auto NUMLOCKON = g_pConfigManager->getDeviceInt(hlName, "numlock_by_default", "input:numlock_by_default"); @@ -151,17 +152,17 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) { void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { - if (xkbTranslationState) - xkb_state_unref(xkbTranslationState); + if (xkbState) + xkb_state_unref(xkbState); if (keymap) { Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this); - xkbTranslationState = xkb_state_new(keymap); + xkbState = xkb_state_new(keymap); return; } const auto KEYMAP = xkbKeymap; - const auto STATE = xkbInternalTranslationState; + const auto STATE = xkbState; const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); @@ -200,7 +201,7 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); } - xkbTranslationState = xkb_state_new(KEYMAP); + xkbState = xkb_state_new(KEYMAP); xkb_keymap_unref(KEYMAP); xkb_context_unref(PCONTEXT); @@ -221,7 +222,7 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { const auto NEWKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); - xkbTranslationState = xkb_state_new(NEWKEYMAP); + xkbState = xkb_state_new(NEWKEYMAP); xkb_keymap_unref(NEWKEYMAP); xkb_context_unref(PCONTEXT); @@ -229,7 +230,7 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { std::string IKeyboard::getActiveLayout() { const auto KEYMAP = xkbKeymap; - const auto STATE = xkbTranslationState; + const auto STATE = xkbState; const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); for (uint32_t i = 0; i < LAYOUTSNUM; ++i) { @@ -246,12 +247,12 @@ std::string IKeyboard::getActiveLayout() { } void IKeyboard::updateLEDs() { - if (xkbTranslationState == nullptr) + if (xkbState == nullptr) return; uint32_t leds = 0; for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { - if (xkb_state_led_index_is_active(xkbTranslationState, ledIndexes.at(i))) + if (xkb_state_led_index_is_active(xkbState, ledIndexes.at(i))) leds |= (1 << i); } @@ -259,7 +260,7 @@ void IKeyboard::updateLEDs() { } void IKeyboard::updateLEDs(uint32_t leds) { - if (!xkbTranslationState) + if (!xkbState) return; if (isVirtual() && g_pInputManager->shouldIgnoreVirtualKeyboard(self.lock())) @@ -288,10 +289,10 @@ uint32_t IKeyboard::getModifiers() { } void IKeyboard::updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) { - if (!xkbTranslationState) + if (!xkbState) return; - xkb_state_update_mask(xkbTranslationState, depressed, latched, locked, 0, 0, group); + xkb_state_update_mask(xkbState, depressed, latched, locked, 0, 0, group); if (!updateModifiersState()) return; @@ -300,13 +301,13 @@ void IKeyboard::updateModifiers(uint32_t depressed, uint32_t latched, uint32_t l } bool IKeyboard::updateModifiersState() { - if (!xkbTranslationState) + if (!xkbState) return false; - auto depressed = xkb_state_serialize_mods(xkbTranslationState, XKB_STATE_MODS_DEPRESSED); - auto latched = xkb_state_serialize_mods(xkbTranslationState, XKB_STATE_MODS_LATCHED); - auto locked = xkb_state_serialize_mods(xkbTranslationState, XKB_STATE_MODS_LOCKED); - auto group = xkb_state_serialize_layout(xkbTranslationState, XKB_STATE_LAYOUT_EFFECTIVE); + auto depressed = xkb_state_serialize_mods(xkbState, XKB_STATE_MODS_DEPRESSED); + auto latched = xkb_state_serialize_mods(xkbState, XKB_STATE_MODS_LATCHED); + auto locked = xkb_state_serialize_mods(xkbState, XKB_STATE_MODS_LOCKED); + auto group = xkb_state_serialize_layout(xkbState, XKB_STATE_LAYOUT_EFFECTIVE); if (depressed == modifiersState.depressed && latched == modifiersState.latched && locked == modifiersState.locked && group == modifiersState.group) return false; @@ -318,3 +319,15 @@ bool IKeyboard::updateModifiersState() { return true; } + +void IKeyboard::updateXkbStateWithKey(uint32_t xkbKey, bool pressed) { + xkb_state_update_key(xkbState, xkbKey, pressed ? XKB_KEY_DOWN : XKB_KEY_UP); + if (updateModifiersState()) { + keyboardEvents.modifiers.emit(SModifiersEvent{ + .depressed = modifiersState.depressed, + .latched = modifiersState.latched, + .locked = modifiersState.locked, + .group = modifiersState.group, + }); + } +} diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index f1f355ecc96..332b8ca058c 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -58,12 +58,13 @@ class IKeyboard : public IHID { uint32_t getModifiers(); void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); bool updateModifiersState(); // rets whether changed + void updateXkbStateWithKey(uint32_t xkbKey, bool pressed); bool active = false; bool enabled = true; - xkb_layout_index_t activeLayout = 0; - xkb_state * xkbTranslationState = nullptr, *xkbInternalTranslationState = nullptr; + xkb_layout_index_t activeLayout = 0; + xkb_state * xkbState = nullptr, *xkbStaticState /* Static state: never gets modifiers or layout changes sent, used for keybinds. */ = nullptr; xkb_keymap* xkbKeymap = nullptr; struct { diff --git a/src/devices/Keyboard.cpp b/src/devices/Keyboard.cpp index 56ec7bfb7cb..867d54a871c 100644 --- a/src/devices/Keyboard.cpp +++ b/src/devices/Keyboard.cpp @@ -32,12 +32,7 @@ CKeyboard::CKeyboard(SP keeb) : keyboard(keeb) { listeners.key = keeb->events.key.registerListener([this](std::any d) { auto E = std::any_cast(d); - uint32_t xkbKeycode = E.key + 8; - xkb_state_update_key(xkbTranslationState, xkbKeycode, E.pressed ? XKB_KEY_DOWN : XKB_KEY_UP); - - // we have to do this for DRM sessions, as they never send modifiers events - if (g_pCompositor->m_pAqBackend->hasSession()) - updateModifiersState(); + updateXkbStateWithKey(E.key + 8, E.pressed); keyboardEvents.key.emit(SKeyEvent{ .timeMs = E.timeMs, diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index a98be2c3b51..22bc4719054 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -366,8 +366,8 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { const auto KEYCODE = e.keycode + 8; // Because to xkbcommon it's +8 from libinput - const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbTranslationState : m_pXKBTranslationState, KEYCODE); - const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->xkbInternalTranslationState, KEYCODE); + const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbStaticState : m_pXKBTranslationState, KEYCODE); + const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->xkbState, KEYCODE); if (handleInternalKeybinds(internalKeysym)) return true; @@ -2121,7 +2121,7 @@ void CKeybindManager::sendshortcut(std::string args) { if (!g_pKeybindManager->m_mKeyToCodeCache.contains(KEYPAIRSTRING)) { xkb_keymap* km = KB->xkbKeymap; - xkb_state* ks = KB->xkbTranslationState; + xkb_state* ks = KB->xkbState; xkb_keycode_t keycode_min, keycode_max; keycode_min = xkb_keymap_min_keycode(km); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 6388327c62c..9e2a16c721f 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1192,10 +1192,6 @@ static void removeFromHIDs(WP hid) { } void CInputManager::destroyKeyboard(SP pKeyboard) { - if (pKeyboard->xkbTranslationState) - xkb_state_unref(pKeyboard->xkbTranslationState); - pKeyboard->xkbTranslationState = nullptr; - std::erase_if(m_vKeyboards, [pKeyboard](const auto& other) { return other == pKeyboard; }); if (m_vKeyboards.size() > 0) { @@ -1261,19 +1257,10 @@ void CInputManager::destroyTabletPad(SP pad) { } void CInputManager::updateKeyboardsLeds(SP pKeyboard) { - if (!pKeyboard || !pKeyboard->xkbTranslationState) + if (!pKeyboard) return; - // FIXME: - // uint32_t leds = 0; - // for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { - // if (xkb_state_led_index_is_active(pKeyboard->xkbTranslationState, keyboard->led_indexes[i])) - // leds |= (1 << i); - // } - - // for (auto& k : m_vKeyboards) { - // k->updateLEDs(leds); - // } + pKeyboard->updateLEDs(); } void CInputManager::onKeyboardKey(std::any event, SP pKeyboard) { From 1cbb7b80c5ef584fb351d3642803164403ce4f15 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 26 Jun 2024 19:26:55 +0200 Subject: [PATCH 010/113] fix hw cursors with new aq stuff --- src/managers/PointerManager.cpp | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 0b52d1328a3..477aba97420 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -375,25 +375,21 @@ bool CPointerManager::setHWCursorBuffer(SP state, SP CPointerManager::renderHWCursorBuffer(SP state, SP texture) { auto output = state->monitor->output; - auto maxSize = output->maxCursorSize(); - + auto maxSize = output->cursorPlaneSize(); auto cursorSize = currentCursorImage.size; - if (cursorSize == Vector2D{}) - return nullptr; - - // error if (maxSize == Vector2D{}) return nullptr; if (maxSize != Vector2D{-1, -1}) { - if (cursorSize.x < maxSize.x || cursorSize.y < maxSize.y) { + 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 || cursorSize != state->monitor->cursorSwapchain->currentOptions().size) { + if (!state->monitor->cursorSwapchain || maxSize != state->monitor->cursorSwapchain->currentOptions().size) { auto format = pickCursorFormat(output); if (format.drmFormat == DRM_FORMAT_INVALID) { @@ -402,12 +398,14 @@ SP CPointerManager::renderHWCursorBuffer(SPmonitor->cursorSwapchain) - state->monitor->cursorSwapchain = makeShared(g_pCompositor->m_pAqBackend->allocator); - - auto options = state->monitor->cursorSwapchain->currentOptions(); - options.size = cursorSize; - options.length = 2; - options.format = format.drmFormat; + state->monitor->cursorSwapchain = Aquamarine::CSwapchain::create(g_pCompositor->m_pAqBackend->allocator, state->monitor->output->getBackend()); + + auto options = state->monitor->cursorSwapchain->currentOptions(); + options.size = maxSize; + options.length = 2; + options.format = format.drmFormat; + options.scanout = true; + options.cursor = true; if (!state->monitor->cursorSwapchain->reconfigure(options)) { Debug::log(TRACE, "Failed to reconfigure cursor swapchain"); From 57e9005abbef8af161ad5a6448e84695eb2259db Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 26 Jun 2024 19:42:50 +0200 Subject: [PATCH 011/113] use auto format for cursor --- src/managers/PointerManager.cpp | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 477aba97420..8225570320c 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -10,28 +10,6 @@ #include #include -static Aquamarine::SDRMFormat pickCursorFormat(SP output) { - - const auto fmts = output->getBackend()->getCursorFormats(); - - if (fmts.empty()) - return {}; - - // try to use common formats in their order - std::vector PREFERRED_FORMATS = {DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888}; - - for (auto& pf : PREFERRED_FORMATS) { - for (auto& fmt : fmts) { - if (pf != fmt.drmFormat) - continue; - - return fmt; - } - } - - return fmts.at(0); -} - CPointerManager::CPointerManager() { hooks.monitorAdded = g_pHookSystem->hookDynamic("newMonitor", [this](void* self, SCallbackInfo& info, std::any data) { auto PMONITOR = std::any_cast>(data); @@ -390,12 +368,6 @@ SP CPointerManager::renderHWCursorBuffer(SPmonitor->cursorSwapchain || maxSize != state->monitor->cursorSwapchain->currentOptions().size) { - auto format = pickCursorFormat(output); - - if (format.drmFormat == DRM_FORMAT_INVALID) { - Debug::log(TRACE, "Failed to pick an output format for hw cursor"); - return nullptr; - } if (!state->monitor->cursorSwapchain) state->monitor->cursorSwapchain = Aquamarine::CSwapchain::create(g_pCompositor->m_pAqBackend->allocator, state->monitor->output->getBackend()); @@ -403,9 +375,10 @@ SP CPointerManager::renderHWCursorBuffer(SPmonitor->cursorSwapchain->currentOptions(); options.size = maxSize; options.length = 2; - options.format = format.drmFormat; options.scanout = true; options.cursor = true; + // 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"); From 1491a853c5d7767822d57d5911004c865d053e35 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 26 Jun 2024 22:21:01 +0200 Subject: [PATCH 012/113] reenable direct scanout --- src/render/Renderer.cpp | 69 +++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index f0a574c03d3..77117241e57 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1080,50 +1080,51 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPmirrors.empty() || pMonitor->isMirror() || m_bDirectScanoutBlocked) + return false; // do not DS if this monitor is being mirrored. Will break the functionality. - // if (!pMonitor->mirrors.empty() || pMonitor->isMirror() || m_bDirectScanoutBlocked) - // return false; // do not DS if this monitor is being mirrored. Will break the functionality. - - // if (!wlr_output_is_direct_scanout_allowed(pMonitor->output)) - // return false; + if (g_pPointerManager->softwareLockedFor(pMonitor->self.lock())) + return false; - // const auto PCANDIDATE = pMonitor->solitaryClient.lock(); + const auto PCANDIDATE = pMonitor->solitaryClient.lock(); - // if (!PCANDIDATE) - // return false; + if (!PCANDIDATE) + return false; - // const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE); + const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE); - // if (!PSURFACE || PSURFACE->current.scale != pMonitor->output->scale || PSURFACE->current.transform != pMonitor->output->transform) - // return false; + if (!PSURFACE || !PSURFACE->current.buffer || PSURFACE->current.buffer->size != pMonitor->vecPixelSize || PSURFACE->current.transform != pMonitor->transform) + return false; - // // finally, we should be GTG. - // wlr_output_state_set_buffer(pMonitor->state.wlr(), &PSURFACE->buffer->base); + // we can't scanout shm buffers. + if (!PSURFACE->current.buffer->dmabuf().success) + return false; - // if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) - // return false; + // FIXME: make sure the buffer actually follows the available scanout dmabuf formats + // and comes from the appropriate device. This may implode on multi-gpu!! - // timespec now; - // clock_gettime(CLOCK_MONOTONIC, &now); - // PSURFACE->frame(&now); - // auto FEEDBACK = makeShared(PSURFACE); - // FEEDBACK->attachMonitor(pMonitor); - // FEEDBACK->presented(); - // FEEDBACK->setPresentationType(true); - // PROTO::presentation->queueData(FEEDBACK); + pMonitor->output->state->setBuffer(PSURFACE->current.buffer); - // if (pMonitor->state.commit()) { - // if (m_pLastScanout.expired()) { - // m_pLastScanout = PCANDIDATE; - // Debug::log(LOG, "Entered a direct scanout to {:x}: \"{}\"", (uintptr_t)PCANDIDATE.get(), PCANDIDATE->m_szTitle); - // } - // } else { - // m_pLastScanout.reset(); - // return false; - // } + timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + PSURFACE->frame(&now); + auto FEEDBACK = makeShared(PSURFACE); + FEEDBACK->attachMonitor(pMonitor); + FEEDBACK->presented(); + FEEDBACK->setPresentationType(true); + PROTO::presentation->queueData(FEEDBACK); + + if (pMonitor->state.commit()) { + if (m_pLastScanout.expired()) { + m_pLastScanout = PCANDIDATE; + Debug::log(LOG, "Entered a direct scanout to {:x}: \"{}\"", (uintptr_t)PCANDIDATE.get(), PCANDIDATE->m_szTitle); + } + } else { + m_pLastScanout.reset(); + return false; + } - // return true; + return true; } void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { From c2b4b2534613754bbb6f7379fd4e0c154dd1a113 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 26 Jun 2024 22:23:18 +0200 Subject: [PATCH 013/113] ye test --- src/render/Renderer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 77117241e57..7d00bbd30fd 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1105,6 +1105,9 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { pMonitor->output->state->setBuffer(PSURFACE->current.buffer); + if (!pMonitor->state.test()) + return false; + timespec now; clock_gettime(CLOCK_MONOTONIC, &now); PSURFACE->frame(&now); From 2b26c738b7e9b5801a0ac62048b6401f4d5630a2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 26 Jun 2024 22:35:22 +0200 Subject: [PATCH 014/113] get dma formats from aq --- src/helpers/Format.hpp | 6 ++---- src/protocols/LinuxDMABUF.cpp | 13 +++++++++---- src/protocols/LinuxDMABUF.hpp | 1 - src/protocols/MesaDRM.cpp | 2 +- src/render/OpenGL.cpp | 4 ++-- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/helpers/Format.hpp b/src/helpers/Format.hpp index c0dabdd5e61..a0ac9c32896 100644 --- a/src/helpers/Format.hpp +++ b/src/helpers/Format.hpp @@ -2,6 +2,7 @@ #include #include "math/Math.hpp" +#include typedef uint32_t DRMFormat; typedef uint32_t SHMFormat; @@ -18,10 +19,7 @@ struct SPixelFormat { Vector2D blockSize; }; -struct SDRMFormat { - DRMFormat format = 0; /* DRM_FORMAT_INVALID */ - std::vector mods; -}; +typedef Aquamarine::SDRMFormat SDRMFormat; namespace FormatUtils { SHMFormat drmToShm(DRMFormat drm); diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 6167ec3f3d0..713ad14e7a6 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -26,8 +26,8 @@ CCompiledDMABUFFeedback::CCompiledDMABUFFeedback(dev_t device, std::vector> formats; for (auto& t : tranches_) { for (auto& fmt : t.formats) { - for (auto& mod : fmt.mods) { - formats.insert(std::make_pair<>(fmt.format, mod)); + for (auto& mod : fmt.modifiers) { + formats.insert(std::make_pair<>(fmt.drmFormat, mod)); } } } @@ -387,11 +387,16 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const mainDevice = *dev; - auto fmts = g_pHyprOpenGL->getDRMFormats(); + // FIXME: this will break on multi-gpu + std::vector aqFormats; + for (auto& impl : g_pCompositor->m_pAqBackend->getImplementations()) { + aqFormats = impl->getRenderFormats(); + break; + } SDMABufTranche tranche = { .device = *dev, - .formats = fmts, + .formats = aqFormats, }; std::vector tches; diff --git a/src/protocols/LinuxDMABUF.hpp b/src/protocols/LinuxDMABUF.hpp index e845352c4bd..4e1636d0b72 100644 --- a/src/protocols/LinuxDMABUF.hpp +++ b/src/protocols/LinuxDMABUF.hpp @@ -10,7 +10,6 @@ #include class CDMABuffer; -struct SDRMFormat; class CWLSurfaceResource; class CLinuxDMABuffer { diff --git a/src/protocols/MesaDRM.cpp b/src/protocols/MesaDRM.cpp index ab77cb4d39e..04a8831cf93 100644 --- a/src/protocols/MesaDRM.cpp +++ b/src/protocols/MesaDRM.cpp @@ -87,7 +87,7 @@ CMesaDRMResource::CMesaDRMResource(SP resource_) : resource(resource_) { auto fmts = g_pHyprOpenGL->getDRMFormats(); for (auto& fmt : fmts) { - resource->sendFormat(fmt.format); + resource->sendFormat(fmt.drmFormat); } } diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 8faf693c5e0..f833f875083 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -344,8 +344,8 @@ void CHyprOpenGLImpl::initDRMFormats() { mods.push_back(DRM_FORMAT_MOD_INVALID); dmaFormats.push_back(SDRMFormat{ - .format = fmt, - .mods = mods, + .drmFormat = fmt, + .modifiers = mods, }); std::vector> modifierData; From 5dd21d0928d402ae0dd9414b2724be2bd05fb8c6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 27 Jun 2024 00:08:12 +0200 Subject: [PATCH 015/113] new event api --- src/managers/eventLoop/EventLoopManager.cpp | 12 ++++++++---- src/managers/eventLoop/EventLoopManager.hpp | 5 +++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index dd52b9681d8..ed7a4f725a1 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -8,6 +8,8 @@ #include #include +#include + #define TIMESPEC_NSEC_PER_SEC 1000000000L CEventLoopManager::CEventLoopManager(wl_display* display, wl_event_loop* wlEventLoop) { @@ -27,16 +29,18 @@ static int timerWrite(int fd, uint32_t mask, void* data) { } static int aquamarineFDWrite(int fd, uint32_t mask, void* data) { - g_pCompositor->m_pAqBackend->dispatchEventsAsync(); + auto POLLFD = (Aquamarine::SPollFD*)data; + POLLFD->onSignal(); return 1; } void CEventLoopManager::enterLoop() { m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd, WL_EVENT_READABLE, timerWrite, nullptr); - auto aqFDs = g_pCompositor->m_pAqBackend->getPollFDs(); - for (auto& fd : aqFDs) { - m_sWayland.aqEventSources.emplace_back(wl_event_loop_add_fd(m_sWayland.loop, fd, WL_EVENT_READABLE, aquamarineFDWrite, nullptr)); + aqPollFDs = g_pCompositor->m_pAqBackend->getPollFDs(); + for (auto& fd : aqPollFDs) { + m_sWayland.aqEventSources.emplace_back(wl_event_loop_add_fd(m_sWayland.loop, fd->fd, WL_EVENT_READABLE, aquamarineFDWrite, fd.get())); + fd->onSignal(); // dispatch outstanding } wl_display_run(m_sWayland.display); diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp index 7758bdf62a8..d5b640a3d6f 100644 --- a/src/managers/eventLoop/EventLoopManager.hpp +++ b/src/managers/eventLoop/EventLoopManager.hpp @@ -7,6 +7,10 @@ #include "EventLoopTimer.hpp" +namespace Aquamarine { + struct SPollFD; +}; + class CEventLoopManager { public: CEventLoopManager(wl_display* display, wl_event_loop* wlEventLoop); @@ -45,6 +49,7 @@ class CEventLoopManager { } m_sTimers; SIdleData m_sIdle; + std::vector> aqPollFDs; }; inline std::unique_ptr g_pEventLoopManager; \ No newline at end of file From bcea65ab0952b2b346f899000eec7e9b26402383 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 27 Jun 2024 21:48:45 +0200 Subject: [PATCH 016/113] stuff I already forgot what I did --- src/helpers/Monitor.cpp | 16 +++++++++++++++- src/helpers/Monitor.hpp | 1 + src/render/Renderer.cpp | 12 ------------ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 2912d734414..2c0038f46fb 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -126,7 +126,7 @@ void CMonitor::onConnect(bool noRule) { g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true); if (!state.commit()) - Debug::log(WARN, "wlr_output_commit_state failed in CMonitor::onCommit"); + Debug::log(WARN, "state.commit() failed in CMonitor::onCommit"); damage.setSize(vecTransformedSize); @@ -778,10 +778,24 @@ CMonitorState::~CMonitorState() { } bool CMonitorState::commit() { + if (!updateSwapchain()) + return false; bool ret = m_pOwner->output->commit(); return ret; } bool CMonitorState::test() { + if (!updateSwapchain()) + return false; return m_pOwner->output->test(); } + +bool CMonitorState::updateSwapchain() { + auto options = m_pOwner->output->swapchain->currentOptions(); + const auto& STATE = m_pOwner->output->state->state(); + options.format = STATE.drmFormat; + options.scanout = true; + options.length = 2; + options.size = STATE.mode ? STATE.mode->pixelSize : STATE.customMode->pixelSize; + return m_pOwner->output->swapchain->reconfigure(options); +} diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 87c73a148df..a221e1e9a44 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -49,6 +49,7 @@ class CMonitorState { bool commit(); bool test(); + bool updateSwapchain(); private: CMonitor* m_pOwner; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 7d00bbd30fd..98e82d501a0 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2610,18 +2610,6 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode static constexpr const int HL_BUFFER_AGE = 2; if (!buffer) { - const auto& MODE = pMonitor->output->state->state().mode ? pMonitor->output->state->state().mode : pMonitor->output->state->state().customMode; - if (!MODE) // no mode?? - return false; - Aquamarine::SSwapchainOptions opts = pMonitor->output->swapchain->currentOptions(); - opts.length = 2; - opts.size = MODE->pixelSize; - opts.format = pMonitor->output->state->state().drmFormat; - if (!pMonitor->output->swapchain->reconfigure(opts)) { - Debug::log(ERR, "Failed to reconfigure swapchain for {}", pMonitor->szName); - return false; - } - m_pCurrentBuffer = pMonitor->output->swapchain->next(nullptr); if (!m_pCurrentBuffer) { Debug::log(ERR, "Failed to acquire swapchain buffer for {}", pMonitor->szName); From 9f761a9590d479487f46cb1690bbf5b44275489a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 28 Jun 2024 14:03:04 +0200 Subject: [PATCH 017/113] stuff --- src/desktop/Window.cpp | 3 ++- src/events/Monitors.cpp | 25 ++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 4ea3415695e..7497957a4ff 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1155,7 +1155,8 @@ int CWindow::getRealBorderSize() { } bool CWindow::canBeTorn() { - return m_sWindowData.tearing.valueOr(m_bTearingHint); + static auto PTEARING = CConfigValue("general:allow_tearing"); + return m_sWindowData.tearing.valueOr(m_bTearingHint) && *PTEARING; } bool CWindow::shouldSendFullscreenState() { diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 4217e27945a..bfa2a20e303 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -26,19 +26,18 @@ void Events::listener_monitorFrame(void* owner, void* data) { CMonitor* const PMONITOR = (CMonitor*)owner; - // FIXME: - // if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) { - // Debug::log(WARN, "Attempted to render frame on inactive session!"); - - // if (g_pCompositor->m_bUnsafeState && std::ranges::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& m) { - // return m->output != g_pCompositor->m_pUnsafeOutput->output; - // })) { - // // restore from unsafe state - // g_pCompositor->leaveUnsafeState(); - // } - - // return; // cannot draw on session inactive (different tty) - // } + if ((g_pCompositor->m_pAqBackend->hasSession() && !g_pCompositor->m_pAqBackend->session->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) { + Debug::log(WARN, "Attempted to render frame on inactive session!"); + + if (g_pCompositor->m_bUnsafeState && std::ranges::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& m) { + return m->output != g_pCompositor->m_pUnsafeOutput->output; + })) { + // restore from unsafe state + g_pCompositor->leaveUnsafeState(); + } + + return; // cannot draw on session inactive (different tty) + } if (!PMONITOR->m_bEnabled) return; From cb3a3a4998046086308bf34fe1ee8536f4d6f6fb Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 29 Jun 2024 18:18:19 +0200 Subject: [PATCH 018/113] switches --- src/Compositor.cpp | 8 +++++ src/debug/HyprCtl.cpp | 4 +-- src/events/Devices.cpp | 2 +- src/helpers/WLClasses.hpp | 14 ++++---- src/managers/input/InputManager.cpp | 50 +++++++++++------------------ src/managers/input/InputManager.hpp | 3 +- 6 files changed, 39 insertions(+), 42 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index a938e4b0a59..d95fcd8dcc7 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -308,6 +308,14 @@ void CCompositor::initAllSignals() { g_pInputManager->updateCapabilities(); }, nullptr); + + m_pAqBackend->events.newSwitch.registerStaticListener( + [](void* data, std::any d) { + auto dev = std::any_cast>(d); + Debug::log(LOG, "New aquamarine switch with name {}", dev->getName()); + g_pInputManager->newSwitch(dev); + }, + nullptr); } void CCompositor::removeAllSignals() { diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 703ff79bbad..c19817402e2 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -654,7 +654,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { "address": "0x{:x}", "name": "{}" }},)#", - (uintptr_t)&d, escapeJSONStrings(d.pWlrDevice ? d.pWlrDevice->name : "")); + (uintptr_t)&d, escapeJSONStrings(d.pDevice ? d.pDevice->getName() : "")); } trimTrailingComma(result); @@ -702,7 +702,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { result += "\n\nSwitches:\n"; for (auto& d : g_pInputManager->m_lSwitches) { - result += std::format("\tSwitch Device at {:x}:\n\t\t{}\n", (uintptr_t)&d, d.pWlrDevice ? d.pWlrDevice->name : ""); + result += std::format("\tSwitch Device at {:x}:\n\t\t{}\n", (uintptr_t)&d, d.pDevice ? d.pDevice->getName() : ""); } } diff --git a/src/events/Devices.cpp b/src/events/Devices.cpp index 752e51f7242..a7c5dd55ef0 100644 --- a/src/events/Devices.cpp +++ b/src/events/Devices.cpp @@ -41,7 +41,7 @@ void Events::listener_newInput(wl_listener* listener, void* data) { break; case WLR_INPUT_DEVICE_SWITCH: Debug::log(LOG, "Attached a switch device with name {}", DEVICE->name); - g_pInputManager->newSwitch(DEVICE); + // g_pInputManager->newSwitch(DEVICE); break; default: Debug::log(WARN, "Unrecognized input device plugged in: {}", DEVICE->name); break; } diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index 6b25e76de0b..51f90166589 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -15,6 +15,8 @@ class IPointer; class IKeyboard; class CWLSurfaceResource; +AQUAMARINE_FORWARD(ISwitch); + struct SRenderData { CMonitor* pMonitor; timespec* when; @@ -70,14 +72,14 @@ struct SSwipeGesture { }; struct SSwitchDevice { - wlr_input_device* pWlrDevice = nullptr; - - int status = -1; // uninitialized + WP pDevice; - DYNLISTENER(destroy); - DYNLISTENER(toggle); + struct { + CHyprSignalListener destroy; + CHyprSignalListener fire; + } listeners; bool operator==(const SSwitchDevice& other) const { - return pWlrDevice == other.pWlrDevice; + return pDevice == other.pDevice; } }; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 9e2a16c721f..6865ebbc17f 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1568,44 +1568,30 @@ void CInputManager::setTabletConfigs() { } } -void CInputManager::newSwitch(wlr_input_device* pDevice) { - const auto PNEWDEV = &m_lSwitches.emplace_back(); - PNEWDEV->pWlrDevice = pDevice; +void CInputManager::newSwitch(SP pDevice) { + const auto PNEWDEV = &m_lSwitches.emplace_back(); + PNEWDEV->pDevice = pDevice; - Debug::log(LOG, "New switch with name \"{}\" added", pDevice->name); + Debug::log(LOG, "New switch with name \"{}\" added", pDevice->getName()); - PNEWDEV->hyprListener_destroy.initCallback(&pDevice->events.destroy, [&](void* owner, void* data) { destroySwitch((SSwitchDevice*)owner); }, PNEWDEV, "SwitchDevice"); + PNEWDEV->listeners.destroy = pDevice->events.destroy.registerListener([this, PNEWDEV](std::any d) { destroySwitch(PNEWDEV); }); - const auto PSWITCH = wlr_switch_from_input_device(pDevice); + PNEWDEV->listeners.fire = pDevice->events.fire.registerListener([PNEWDEV](std::any d) { + const auto NAME = PNEWDEV->pDevice->getName(); + const auto E = std::any_cast(d); - PNEWDEV->hyprListener_toggle.initCallback( - &PSWITCH->events.toggle, - [&](void* owner, void* data) { - const auto PDEVICE = (SSwitchDevice*)owner; - const auto NAME = std::string(PDEVICE->pWlrDevice->name); - const auto E = (wlr_switch_toggle_event*)data; + Debug::log(LOG, "Switch {} fired, triggering binds.", NAME); - if (PDEVICE->status != -1 && PDEVICE->status == E->switch_state) - return; - - Debug::log(LOG, "Switch {} fired, triggering binds.", NAME); - - g_pKeybindManager->onSwitchEvent(NAME); - - switch (E->switch_state) { - case WLR_SWITCH_STATE_ON: - Debug::log(LOG, "Switch {} turn on, triggering binds.", NAME); - g_pKeybindManager->onSwitchOnEvent(NAME); - break; - case WLR_SWITCH_STATE_OFF: - Debug::log(LOG, "Switch {} turn off, triggering binds.", NAME); - g_pKeybindManager->onSwitchOffEvent(NAME); - break; - } + g_pKeybindManager->onSwitchEvent(NAME); - PDEVICE->status = E->switch_state; - }, - PNEWDEV, "SwitchDevice"); + if (E.enable) { + Debug::log(LOG, "Switch {} turn on, triggering binds.", NAME); + g_pKeybindManager->onSwitchOnEvent(NAME); + } else { + Debug::log(LOG, "Switch {} turn off, triggering binds.", NAME); + g_pKeybindManager->onSwitchOffEvent(NAME); + } + }); } void CInputManager::destroySwitch(SSwitchDevice* pDevice) { diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 692b5c27caf..b24bffd7d7f 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -21,6 +21,7 @@ class IKeyboard; AQUAMARINE_FORWARD(IPointer); AQUAMARINE_FORWARD(IKeyboard); AQUAMARINE_FORWARD(ITouch); +AQUAMARINE_FORWARD(ISwitch); enum eClickBehaviorMode { CLICKMODE_DEFAULT = 0, @@ -91,7 +92,7 @@ class CInputManager { void newMouse(SP); void newVirtualMouse(SP); void newTouchDevice(SP); - void newSwitch(wlr_input_device*); + void newSwitch(SP); void newTabletTool(wlr_tablet_tool*); void newTabletPad(wlr_input_device*); void newTablet(wlr_input_device*); From c7e4f24c455244c20dd485dd6099b3238b6185fd Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 29 Jun 2024 23:18:16 +0200 Subject: [PATCH 019/113] fixado --- src/events/Misc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp index 32f894ec427..82790ec575f 100644 --- a/src/events/Misc.cpp +++ b/src/events/Misc.cpp @@ -30,7 +30,7 @@ void Events::listener_RendererDestroy(wl_listener* listener, void* data) { } void Events::listener_sessionActive(wl_listener* listener, void* data) { - if (g_pCompositor->m_sWLRSession->active) { + if (g_pCompositor->m_pAqBackend->session->active) { Debug::log(LOG, "Session got activated!"); g_pCompositor->m_bSessionActive = true; From 93c35602ca3c3a094c1bfad2ef436653e6531353 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 30 Jun 2024 12:23:17 +0200 Subject: [PATCH 020/113] fix nullptr deref --- src/helpers/Monitor.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 2c0038f46fb..ad5b0199e78 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -793,9 +793,12 @@ bool CMonitorState::test() { bool CMonitorState::updateSwapchain() { auto options = m_pOwner->output->swapchain->currentOptions(); const auto& STATE = m_pOwner->output->state->state(); + const auto& MODE = STATE.mode ? STATE.mode : STATE.customMode; + if (!MODE) + return true; options.format = STATE.drmFormat; options.scanout = true; options.length = 2; - options.size = STATE.mode ? STATE.mode->pixelSize : STATE.customMode->pixelSize; + options.size = MODE->pixelSize; return m_pOwner->output->swapchain->reconfigure(options); } From 36ac7e6c76bf5910c61eb37487768925098c6a1c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 1 Jul 2024 13:06:23 +0200 Subject: [PATCH 021/113] avoid crash on monitor unplug --- src/events/Monitors.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index bfa2a20e303..e53401dea35 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -90,7 +90,7 @@ void Events::listener_monitorFrame(void* owner, void* data) { } void Events::listener_monitorDestroy(void* owner, void* data) { - CMonitor* pMonitor = nullptr; + CMonitor* pMonitor = (CMonitor*)owner; for (auto& m : g_pCompositor->m_vRealMonitors) { if (m->output == pMonitor->output) { From bb2b451ad06a429fa8aaa48eb48bc661869f616f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 1 Jul 2024 14:33:20 +0200 Subject: [PATCH 022/113] support headless --- src/Compositor.cpp | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index d95fcd8dcc7..d3c30bdcb60 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -228,6 +228,9 @@ void CCompositor::initServer() { std::vector implementations; Aquamarine::SBackendImplementationOptions option; + option.backendType = Aquamarine::eBackendType::AQ_BACKEND_HEADLESS; + option.backendRequestMode = Aquamarine::eBackendRequestMode::AQ_BACKEND_REQUEST_MANDATORY; + implementations.emplace_back(option); option.backendType = Aquamarine::eBackendType::AQ_BACKEND_DRM; option.backendRequestMode = Aquamarine::eBackendRequestMode::AQ_BACKEND_REQUEST_IF_AVAILABLE; implementations.emplace_back(option); @@ -534,23 +537,21 @@ void CCompositor::removeLockFile() { } void CCompositor::prepareFallbackOutput() { - // TODO: - // // create a backup monitor - // wlr_backend* headless = nullptr; - // wlr_multi_for_each_backend( - // m_sWLRBackend, - // [](wlr_backend* b, void* data) { - // if (wlr_backend_is_headless(b)) - // *((wlr_backend**)data) = b; - // }, - // &headless); - - // if (!headless) { - // Debug::log(WARN, "Unsafe state will be ineffective, no fallback output"); - // return; - // } + // create a backup monitor + SP headless; + for (auto& impl : m_pAqBackend->getImplementations()) { + if (impl->type() == Aquamarine::AQ_BACKEND_HEADLESS) { + headless = impl; + break; + } + } - // wlr_headless_add_output(headless, 1920, 1080); + if (!headless) { + Debug::log(WARN, "No headless in prepareFallbackOutput?!"); + return; + } + + headless->createOutput(); } void CCompositor::startCompositor(std::string socketName, int socketFd) { @@ -2858,8 +2859,10 @@ static void checkDefaultCursorWarp(SP PNEWMONITOR, std::string monitor void CCompositor::onNewMonitor(SP output) { // add it to real auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared()); - if (std::string("HEADLESS-1") == output->name) + if (std::string("HEADLESS-1") == output->name) { g_pCompositor->m_pUnsafeOutput = PNEWMONITOR.get(); + output->name = "FALLBACK"; // we are allowed to do this :) + } Debug::log(LOG, "New output with name {}", output->name); From fe0d464a9c12490dae81cb3d5444cb2e44b93429 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 1 Jul 2024 14:59:47 +0200 Subject: [PATCH 023/113] bring back hyprctl output --- src/debug/HyprCtl.cpp | 66 +++++++++++++++-------------------------- src/events/Monitors.cpp | 24 --------------- 2 files changed, 24 insertions(+), 66 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index c19817402e2..9bef254514e 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1377,43 +1377,6 @@ std::string decorationRequest(eHyprCtlOutputFormat format, std::string request) return result; } -// static bool addOutput(wlr_backend* backend, const std::string& type, const std::string& name) { -// wlr_output* output = nullptr; - -// if (type.empty() || type == "auto") { -// if (wlr_backend_is_wl(backend)) -// output = wlr_wl_output_create(backend); -// else if (wlr_backend_is_headless(backend)) -// output = wlr_headless_add_output(backend, 1920, 1080); -// } else { -// if (wlr_backend_is_wl(backend) && type == "wayland") -// output = wlr_wl_output_create(backend); -// else if (wlr_backend_is_headless(backend) && type == "headless") -// output = wlr_headless_add_output(backend, 1920, 1080); -// } - -// if (output && !name.empty()) -// g_pCompositor->getMonitorFromOutput(output)->szName = name; - -// return output != nullptr; -// } - -struct outputData { - std::string type; - std::string name; - bool added; -}; - -void createOutputIter(wlr_backend* backend, void* data) { - const auto DATA = static_cast(data); - - if (DATA->added) - return; - - // if (addOutput(backend, DATA->type, DATA->name)) - // DATA->added = true; -} - std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) { CVarList vars(request, 0, ' '); @@ -1422,17 +1385,36 @@ std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) { const auto MODE = vars[1]; - // FIXME: + bool added = false; + + if (!vars[3].empty()) { + for (auto& m : g_pCompositor->m_vRealMonitors) { + if (m->szName == vars[3]) + return "Name already taken"; + } + } if (MODE == "create" || MODE == "add") { if (g_pCompositor->getMonitorFromName(vars[3])) return "A real monitor already uses that name."; - outputData result{vars[2], vars[3], false}; + for (auto& impl : g_pCompositor->m_pAqBackend->getImplementations()) { + auto type = impl->type(); - // wlr_multi_for_each_backend(g_pCompositor->m_sWLRBackend, createOutputIter, &result); + if (type == Aquamarine::AQ_BACKEND_HEADLESS && (vars[2] == "headless" || vars[2] == "auto")) { + added = true; + impl->createOutput(vars[3]); + break; + } + + if (type == Aquamarine::AQ_BACKEND_WAYLAND && (vars[2] == "wayland" || vars[2] == "auto")) { + added = true; + impl->createOutput(vars[3]); + break; + } + } - if (!result.added) + if (!added) return "no backend replied to the request"; } else if (MODE == "destroy" || MODE == "remove") { @@ -1444,7 +1426,7 @@ std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) { if (!PMONITOR->createdByUser) return "cannot remove a real display. Use the monitor keyword."; - //wlr_output_destroy(PMONITOR->output); + PMONITOR->output->destroy(); } return "ok"; diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index e53401dea35..3fda165446a 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -114,30 +114,6 @@ void Events::listener_monitorDestroy(void* owner, void* data) { std::erase_if(g_pCompositor->m_vRealMonitors, [&](SP& el) { return el.get() == pMonitor; }); } -void Events::listener_monitorStateRequest(void* owner, void* data) { - // const auto PMONITOR = (CMonitor*)owner; - // const auto E = (wlr_output_event_request_state*)data; - - // if (!PMONITOR->createdByUser) - // return; - - // const auto SIZE = E->state->mode ? Vector2D{E->state->mode->width, E->state->mode->height} : Vector2D{E->state->custom_mode.width, E->state->custom_mode.height}; - - // PMONITOR->forceSize = SIZE; - - // SMonitorRule rule = PMONITOR->activeMonitorRule; - // rule.resolution = SIZE; - - // g_pHyprRenderer->applyMonitorRule(PMONITOR, &rule); -} - -void Events::listener_monitorDamage(void* owner, void* data) { - const auto PMONITOR = (CMonitor*)owner; - const auto E = (wlr_output_event_damage*)data; - - PMONITOR->addDamage(E->damage); -} - void Events::listener_monitorNeedsFrame(void* owner, void* data) { const auto PMONITOR = (CMonitor*)owner; From 9c7c9a47f3407ad7942aacfac3c24e83a0164684 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 1 Jul 2024 15:00:25 +0200 Subject: [PATCH 024/113] ye --- src/debug/HyprCtl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 9bef254514e..631ced9dfbe 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1398,7 +1398,7 @@ std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) { if (g_pCompositor->getMonitorFromName(vars[3])) return "A real monitor already uses that name."; - for (auto& impl : g_pCompositor->m_pAqBackend->getImplementations()) { + for (auto& impl : g_pCompositor->m_pAqBackend->getImplementations() | std::views::reverse) { auto type = impl->type(); if (type == Aquamarine::AQ_BACKEND_HEADLESS && (vars[2] == "headless" || vars[2] == "auto")) { From ef65500874336f05e6b5ee6b9d586218350de55f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 1 Jul 2024 19:23:09 +0200 Subject: [PATCH 025/113] some format fixes --- src/protocols/LinuxDMABUF.cpp | 8 +++----- src/protocols/MesaDRM.cpp | 19 ++++++++++++++++++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 713ad14e7a6..32cace3fef0 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -24,11 +24,9 @@ static std::optional devIDFromFD(int fd) { CCompiledDMABUFFeedback::CCompiledDMABUFFeedback(dev_t device, std::vector tranches_) { std::set> formats; - for (auto& t : tranches_) { - for (auto& fmt : t.formats) { - for (auto& mod : fmt.modifiers) { - formats.insert(std::make_pair<>(fmt.drmFormat, mod)); - } + for (auto& fmt : g_pHyprOpenGL->getDRMFormats()) { + for (auto& mod : fmt.modifiers) { + formats.insert(std::make_pair<>(fmt.drmFormat, mod)); } } diff --git a/src/protocols/MesaDRM.cpp b/src/protocols/MesaDRM.cpp index 04a8831cf93..e585dcecece 100644 --- a/src/protocols/MesaDRM.cpp +++ b/src/protocols/MesaDRM.cpp @@ -60,10 +60,27 @@ CMesaDRMResource::CMesaDRMResource(SP resource_) : resource(resource_) { return; } + uint64_t mod = DRM_FORMAT_MOD_INVALID; + + auto fmts = g_pHyprOpenGL->getDRMFormats(); + for (auto& f : fmts) { + if (f.drmFormat != fmt) + continue; + + for (auto& m : f.modifiers) { + if (m == DRM_FORMAT_MOD_LINEAR) + continue; + + mod = m; + break; + } + break; + } + Aquamarine::SDMABUFAttrs attrs; attrs.success = true; attrs.size = {w, h}; - attrs.modifier = DRM_FORMAT_MOD_INVALID; + attrs.modifier = mod; attrs.planes = 1; attrs.offsets[0] = off0; attrs.strides[0] = str0; From d7855b0349a8110f89229ef4dbce5ba7469a86b6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 2 Jul 2024 12:09:41 +0200 Subject: [PATCH 026/113] fix crasherino --- src/Compositor.cpp | 1 + src/devices/IKeyboard.cpp | 2 ++ src/managers/input/InputManager.cpp | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index d3c30bdcb60..46eb9f39890 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -592,6 +592,7 @@ void CCompositor::startCompositor(std::string socketName, int socketFd) { } setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket.c_str(), 1); + setenv("XDG_SESSION_TYPE", "wayland", 1); signal(SIGPIPE, SIG_IGN); diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index eb475b730d4..4c8f5880f6c 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -155,6 +155,8 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { if (xkbState) xkb_state_unref(xkbState); + xkbState = nullptr; + if (keymap) { Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this); xkbState = xkb_state_new(keymap); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 6865ebbc17f..f166f3776ce 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1327,7 +1327,7 @@ void CInputManager::onKeyboardMod(SP pKeyboard) { const auto LAYOUT = pKeyboard->getActiveLayout(); - pKeyboard->updateXKBTranslationState(); + pKeyboard->updateXKBTranslationState(pKeyboard->xkbKeymap); g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->hlName + "," + LAYOUT}); EMIT_HOOK_EVENT("activeLayout", (std::vector{pKeyboard, LAYOUT})); From 2efac3eb380e9dafbf62e3f849b6e4eff430e5b7 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 2 Jul 2024 12:41:41 +0200 Subject: [PATCH 027/113] gamma done --- src/protocols/GammaControl.cpp | 18 ++++++++++++++++++ src/protocols/GammaControl.hpp | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index c8f423cef2d..494d986289f 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -81,6 +81,24 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out gammaTableSet = true; close(fd); + + // translate the table to AQ format + std::vector red, green, blue; + red.resize(gammaTable.size() / 3); + green.resize(gammaTable.size() / 3); + blue.resize(gammaTable.size() / 3); + for (size_t i = 0; i < gammaTable.size() / 3; ++i) { + red.at(i) = gammaTable.at(i); + green.at(i) = gammaTable.at(gammaTable.size() / 3 + i); + blue.at(i) = gammaTable.at((gammaTable.size() / 3) * 2 + i); + } + + for (size_t i = 0; i < gammaTable.size() / 3; ++i) { + gammaTable.at(i * 3) = red.at(i); + gammaTable.at(i * 3 + 1) = green.at(i); + gammaTable.at(i * 3 + 2) = blue.at(i); + } + applyToMonitor(); }); diff --git a/src/protocols/GammaControl.hpp b/src/protocols/GammaControl.hpp index 93465b81e31..963eea5c192 100644 --- a/src/protocols/GammaControl.hpp +++ b/src/protocols/GammaControl.hpp @@ -23,7 +23,7 @@ class CGammaControl { CMonitor* pMonitor = nullptr; size_t gammaSize = 0; bool gammaTableSet = false; - std::vector gammaTable; + std::vector gammaTable; // [r,g,b]+ void onMonitorDestroy(); From ab9e5bf98a2b1869646d9f346a00216bce36a28b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 2 Jul 2024 14:06:27 +0200 Subject: [PATCH 028/113] fixes --- src/devices/IKeyboard.cpp | 17 +++++++++++++++++ src/devices/IKeyboard.hpp | 4 +++- src/devices/Keyboard.cpp | 4 +--- src/managers/input/InputManager.cpp | 2 +- src/protocols/LinuxDMABUF.cpp | 20 ++++++++++++++++++++ 5 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index 4c8f5880f6c..e07385c5c93 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -2,6 +2,7 @@ #include "../defines.hpp" #include "../helpers/varlist/VarList.hpp" #include "../managers/input/InputManager.hpp" +#include "../managers/SeatManager.hpp" #include #include @@ -148,6 +149,8 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) { } xkb_context_unref(CONTEXT); + + g_pSeatManager->updateActiveKeyboardData(); } void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { @@ -323,7 +326,21 @@ bool IKeyboard::updateModifiersState() { } void IKeyboard::updateXkbStateWithKey(uint32_t xkbKey, bool pressed) { + + const auto contains = std::find(pressedXKB.begin(), pressedXKB.end(), xkbKey) != pressedXKB.end(); + + if (contains && pressed) + return; + if (!contains && !pressed) + return; + + if (contains) + std::erase(pressedXKB, xkbKey); + else + pressedXKB.emplace_back(xkbKey); + xkb_state_update_key(xkbState, xkbKey, pressed ? XKB_KEY_DOWN : XKB_KEY_UP); + if (updateModifiersState()) { keyboardEvents.modifiers.emit(SModifiersEvent{ .depressed = modifiersState.depressed, diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index 332b8ca058c..741a670209d 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -89,5 +89,7 @@ class IKeyboard : public IHID { WP self; private: - void clearManuallyAllocd(); + void clearManuallyAllocd(); + + std::vector pressedXKB; }; diff --git a/src/devices/Keyboard.cpp b/src/devices/Keyboard.cpp index 867d54a871c..f77829a724e 100644 --- a/src/devices/Keyboard.cpp +++ b/src/devices/Keyboard.cpp @@ -42,9 +42,7 @@ CKeyboard::CKeyboard(SP keeb) : keyboard(keeb) { }); listeners.modifiers = keeb->events.modifiers.registerListener([this](std::any d) { - auto E = std::any_cast(d); - - updateModifiers(E.depressed, E.latched, E.locked, E.group); + updateModifiersState(); keyboardEvents.modifiers.emit(SModifiersEvent{ .depressed = modifiersState.depressed, diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index f166f3776ce..ae1dd7ca5a1 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1327,7 +1327,7 @@ void CInputManager::onKeyboardMod(SP pKeyboard) { const auto LAYOUT = pKeyboard->getActiveLayout(); - pKeyboard->updateXKBTranslationState(pKeyboard->xkbKeymap); + Debug::log(LOG, "LAYOUT CHANGED TO {} GROUP {}", LAYOUT, MODS.group); g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->hlName + "," + LAYOUT}); EMIT_HOOK_EVENT("activeLayout", (std::vector{pKeyboard, LAYOUT})); diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 32cace3fef0..994882c81cc 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -288,6 +288,8 @@ CLinuxDMABUFFeedbackResource::CLinuxDMABUFFeedbackResource(SPmainDevice, }; resource->sendMainDevice(&deviceArr); + + // Main tranche resource->sendTrancheTargetDevice(&deviceArr); resource->sendTrancheFlags((zwpLinuxDmabufFeedbackV1TrancheFlags)0); @@ -300,6 +302,24 @@ CLinuxDMABUFFeedbackResource::CLinuxDMABUFFeedbackResource(SPsendTrancheDone(); + // Scanout tranche + // FIXME: jesus fucking christ this SUCKSSSSSS ASSSSSS + resource->sendTrancheTargetDevice(&deviceArr); + resource->sendTrancheFlags(ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT); + + wl_array indices2; + wl_array_init(&indices2); + for (size_t i = 0; i < feedback->tranches.size(); ++i) { + // FIXME: if the monitor gets the wrong format we'll be FUCKED by drm and no scanout will happen + if (feedback->tranches.at(i).first != DRM_FORMAT_XRGB8888 && feedback->tranches.at(i).first != DRM_FORMAT_XRGB2101010) + continue; + + *((uint16_t*)wl_array_add(&indices2, sizeof(uint16_t))) = i; + } + resource->sendTrancheFormats(&indices2); + wl_array_release(&indices2); + resource->sendTrancheDone(); + resource->sendDone(); } From 5051aeaa6275b2a0e7c47f55a3b459c9046a5609 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 3 Jul 2024 19:14:23 +0200 Subject: [PATCH 029/113] tablets and shit --- patch.txt | 84 +++++++++ src/Compositor.cpp | 51 +++++- src/debug/HyprCtl.cpp | 9 +- src/devices/Tablet.cpp | 256 +++++++++++----------------- src/devices/Tablet.hpp | 156 ++++++++--------- src/events/Devices.cpp | 50 ------ src/events/Events.hpp | 31 ---- src/events/Misc.cpp | 54 ------ src/managers/input/InputManager.cpp | 8 +- src/managers/input/InputManager.hpp | 10 +- src/managers/input/Tablets.cpp | 53 +++--- src/protocols/Tablet.cpp | 60 +++---- src/protocols/Tablet.hpp | 5 +- 13 files changed, 381 insertions(+), 446 deletions(-) create mode 100644 patch.txt delete mode 100644 src/events/Devices.cpp delete mode 100644 src/events/Misc.cpp diff --git a/patch.txt b/patch.txt new file mode 100644 index 00000000000..6c79b0fb358 --- /dev/null +++ b/patch.txt @@ -0,0 +1,84 @@ +diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp +index 8b4ba0ee..e34aa54b 100644 +--- a/src/managers/PointerManager.cpp ++++ b/src/managers/PointerManager.cpp +@@ -4,6 +4,7 @@ + #include "../protocols/PointerGestures.hpp" + #include "../protocols/FractionalScale.hpp" + #include "../protocols/core/Compositor.hpp" ++#include "eventLoop/EventLoopManager.hpp" + #include "SeatManager.hpp" + #include + #include +@@ -139,8 +140,8 @@ CPointerManager::CPointerManager() { + + onMonitorLayoutChange(); + +- PMONITOR->events.modeChanged.registerStaticListener([this](void* owner, std::any data) { onMonitorLayoutChange(); }, nullptr); +- PMONITOR->events.disconnect.registerStaticListener([this](void* owner, std::any data) { onMonitorLayoutChange(); }, nullptr); ++ PMONITOR->events.modeChanged.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr); ++ PMONITOR->events.disconnect.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr); + PMONITOR->events.destroy.registerStaticListener( + [this](void* owner, std::any data) { + if (g_pCompositor && !g_pCompositor->m_bIsShuttingDown) +diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp +index 1193ffb8..e2d72f22 100644 +--- a/src/managers/eventLoop/EventLoopManager.cpp ++++ b/src/managers/eventLoop/EventLoopManager.cpp +@@ -86,4 +86,25 @@ void CEventLoopManager::nudgeTimers() { + itimerspec ts = {.it_value = now}; + + timerfd_settime(m_sTimers.timerfd, TFD_TIMER_ABSTIME, &ts, nullptr); +-} +\ No newline at end of file ++} ++ ++void CEventLoopManager::doLater(const std::function& fn) { ++ m_sIdle.fns.emplace_back(fn); ++ ++ if (m_sIdle.eventSource) ++ return; ++ ++ m_sIdle.eventSource = wl_event_loop_add_idle( ++ m_sWayland.loop, ++ [](void* data) { ++ auto IDLE = (CEventLoopManager::SIdleData*)data; ++ auto cpy = IDLE->fns; ++ IDLE->fns.clear(); ++ IDLE->eventSource = nullptr; ++ for (auto& c : cpy) { ++ if (c) ++ c(); ++ } ++ }, ++ &m_sIdle); ++} +diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp +index 7a4fa19e..77e57513 100644 +--- a/src/managers/eventLoop/EventLoopManager.hpp ++++ b/src/managers/eventLoop/EventLoopManager.hpp +@@ -23,6 +23,14 @@ class CEventLoopManager { + // recalculates timers + void nudgeTimers(); + ++ // schedules a function to run later, aka in a wayland idle event. ++ void doLater(const std::function& fn); ++ ++ struct SIdleData { ++ wl_event_source* eventSource = nullptr; ++ std::vector> fns; ++ }; ++ + private: + struct { + wl_event_loop* loop = nullptr; +@@ -34,6 +42,8 @@ class CEventLoopManager { + std::vector> timers; + int timerfd = -1; + } m_sTimers; ++ ++ SIdleData m_sIdle; + }; + + inline std::unique_ptr g_pEventLoopManager; +\ No newline at end of file diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 46eb9f39890..00e7fce1f1a 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -319,6 +319,50 @@ void CCompositor::initAllSignals() { g_pInputManager->newSwitch(dev); }, nullptr); + + m_pAqBackend->events.newTablet.registerStaticListener( + [](void* data, std::any d) { + auto dev = std::any_cast>(d); + Debug::log(LOG, "New aquamarine tablet with name {}", dev->getName()); + g_pInputManager->newTablet(dev); + }, + nullptr); + + m_pAqBackend->events.newTabletPad.registerStaticListener( + [](void* data, std::any d) { + auto dev = std::any_cast>(d); + Debug::log(LOG, "New aquamarine tablet pad with name {}", dev->getName()); + g_pInputManager->newTabletPad(dev); + }, + nullptr); + + if (m_pAqBackend->hasSession()) { + m_pAqBackend->session->events.changeActive.registerStaticListener( + [this](void*, std::any) { + if (m_pAqBackend->session->active) { + Debug::log(LOG, "Session got activated!"); + + m_bSessionActive = true; + + for (auto& m : m_vMonitors) { + scheduleFrameForMonitor(m.get()); + g_pHyprRenderer->applyMonitorRule(m.get(), &m->activeMonitorRule, true); + } + + g_pConfigManager->m_bWantsMonitorReload = true; + } else { + Debug::log(LOG, "Session got deactivated!"); + + m_bSessionActive = false; + + for (auto& m : m_vMonitors) { + m->noFrameSchedule = true; + m->framesToSkip = 1; + } + } + }, + nullptr); + } } void CCompositor::removeAllSignals() { @@ -2297,9 +2341,8 @@ void CCompositor::updateWorkspaceWindowData(const int& id) { } void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor) { - // FIXME: - // if ((m_sWLRSession && !m_sWLRSession->active) || !m_bSessionActive) - // return; + if ((m_pAqBackend->hasSession() && !m_pAqBackend->session->active) || !m_bSessionActive) + return; if (!pMonitor->m_bEnabled) return; @@ -2862,7 +2905,7 @@ void CCompositor::onNewMonitor(SP output) { auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared()); if (std::string("HEADLESS-1") == output->name) { g_pCompositor->m_pUnsafeOutput = PNEWMONITOR.get(); - output->name = "FALLBACK"; // we are allowed to do this :) + output->name = "FALLBACK"; // we are allowed to do this :) } Debug::log(LOG, "New output with name {}", output->name); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 631ced9dfbe..d45ca48d6de 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -624,9 +624,8 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { R"#( {{ "address": "0x{:x}", "type": "tabletTool", - "belongsTo": "0x{:x}" }},)#", - (uintptr_t)d.get(), d->wlr() ? (uintptr_t)d->wlr()->data : 0); + (uintptr_t)d.get()); } trimTrailingComma(result); @@ -686,11 +685,11 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { } for (auto& d : g_pInputManager->m_vTablets) { - result += std::format("\tTablet at {:x}:\n\t\t{}\n\t\t\tsize: {}x{}mm\n", (uintptr_t)d.get(), d->hlName, d->wlr()->width_mm, d->wlr()->height_mm); + result += std::format("\tTablet at {:x}:\n\t\t{}\n\t\t\tsize: {}x{}mm\n", (uintptr_t)d.get(), d->hlName, d->aq()->physicalSize.x, d->aq()->physicalSize.y); } for (auto& d : g_pInputManager->m_vTabletTools) { - result += std::format("\tTablet Tool at {:x} (belongs to {:x})\n", (uintptr_t)d.get(), d->wlr() ? (uintptr_t)d->wlr()->data : 0); + result += std::format("\tTablet Tool at {:x}\n", (uintptr_t)d.get()); } result += "\n\nTouch:\n"; @@ -1385,7 +1384,7 @@ std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) { const auto MODE = vars[1]; - bool added = false; + bool added = false; if (!vars[3].empty()) { for (auto& m : g_pCompositor->m_vRealMonitors) { diff --git a/src/devices/Tablet.cpp b/src/devices/Tablet.cpp index b5ab16c11cc..a1f642dfbb7 100644 --- a/src/devices/Tablet.cpp +++ b/src/devices/Tablet.cpp @@ -2,8 +2,9 @@ #include "../defines.hpp" #include "../protocols/Tablet.hpp" #include "../protocols/core/Compositor.hpp" +#include -SP CTablet::create(wlr_tablet* tablet) { +SP CTablet::create(SP tablet) { SP pTab = SP(new CTablet(tablet)); pTab->self = pTab; @@ -13,7 +14,7 @@ SP CTablet::create(wlr_tablet* tablet) { return pTab; } -SP CTabletTool::create(wlr_tablet_tool* tablet) { +SP CTabletTool::create(SP tablet) { SP pTab = SP(new CTabletTool(tablet)); pTab->self = pTab; @@ -23,7 +24,7 @@ SP CTabletTool::create(wlr_tablet_tool* tablet) { return pTab; } -SP CTabletPad::create(wlr_tablet_pad* tablet) { +SP CTabletPad::create(SP tablet) { SP pTab = SP(new CTabletPad(tablet)); pTab->self = pTab; @@ -33,33 +34,25 @@ SP CTabletPad::create(wlr_tablet_pad* tablet) { return pTab; } -SP CTabletTool::fromWlr(wlr_tablet_tool* tool) { - return ((CTabletTool*)tool->data)->self.lock(); -} - -SP CTablet::fromWlr(wlr_tablet* tablet) { - return ((CTablet*)tablet->data)->self.lock(); -} - -static uint32_t wlrUpdateToHl(uint32_t wlr) { +static uint32_t aqUpdateToHl(uint32_t aq) { uint32_t result = 0; - if (wlr & WLR_TABLET_TOOL_AXIS_X) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_X) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_X; - if (wlr & WLR_TABLET_TOOL_AXIS_Y) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_Y) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_Y; - if (wlr & WLR_TABLET_TOOL_AXIS_DISTANCE) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_DISTANCE) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_DISTANCE; - if (wlr & WLR_TABLET_TOOL_AXIS_PRESSURE) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_PRESSURE) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_PRESSURE; - if (wlr & WLR_TABLET_TOOL_AXIS_TILT_X) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_TILT_X) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_TILT_X; - if (wlr & WLR_TABLET_TOOL_AXIS_TILT_Y) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_TILT_Y) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_TILT_Y; - if (wlr & WLR_TABLET_TOOL_AXIS_ROTATION) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_ROTATION) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_ROTATION; - if (wlr & WLR_TABLET_TOOL_AXIS_SLIDER) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_SLIDER) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_SLIDER; - if (wlr & WLR_TABLET_TOOL_AXIS_WHEEL) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_WHEEL) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_WHEEL; return result; } @@ -68,97 +61,81 @@ uint32_t CTablet::getCapabilities() { return HID_INPUT_CAPABILITY_POINTER | HID_INPUT_CAPABILITY_TABLET; } -wlr_tablet* CTablet::wlr() { - return tablet; +SP CTablet::aq() { + return tablet.lock(); } -CTablet::CTablet(wlr_tablet* tablet_) : tablet(tablet_) { +CTablet::CTablet(SP tablet_) : tablet(tablet_) { if (!tablet) return; - tablet->data = this; - - // clang-format off - hyprListener_destroy.initCallback(&tablet->base.events.destroy, [this] (void* owner, void* data) { - tablet = nullptr; - disconnectCallbacks(); + listeners.destroy = tablet->events.destroy.registerListener([this](std::any d) { + tablet.reset(); events.destroy.emit(); - }, this, "CTablet"); + }); - hyprListener_axis.initCallback(&tablet->events.axis, [this] (void* owner, void* data) { - auto E = (wlr_tablet_tool_axis_event*)data; + listeners.axis = tablet->events.axis.registerListener([this](std::any d) { + auto E = std::any_cast(d); tabletEvents.axis.emit(SAxisEvent{ - .tool = E->tool, + .tool = E.tool, .tablet = self.lock(), - .timeMs = E->time_msec, - .updatedAxes = wlrUpdateToHl(E->updated_axes), - .axis = {E->x, E->y}, - .axisDelta = {E->dx, E->dy}, - .tilt = {E->tilt_x, E->tilt_y}, - .pressure = E->pressure, - .distance = E->distance, - .rotation = E->rotation, - .slider = E->slider, - .wheelDelta = E->wheel_delta, + .timeMs = E.timeMs, + .updatedAxes = aqUpdateToHl(E.updatedAxes), + .axis = E.absolute, + .axisDelta = E.delta, + .tilt = E.tilt, + .pressure = E.pressure, + .distance = E.distance, + .rotation = E.rotation, + .slider = E.slider, + .wheelDelta = E.wheelDelta, }); - }, this, "CTablet"); + }); - hyprListener_proximity.initCallback(&tablet->events.proximity, [this] (void* owner, void* data) { - auto E = (wlr_tablet_tool_proximity_event*)data; + listeners.proximity = tablet->events.proximity.registerListener([this](std::any d) { + auto E = std::any_cast(d); tabletEvents.proximity.emit(SProximityEvent{ - .tool = E->tool, + .tool = E.tool, .tablet = self.lock(), - .timeMs = E->time_msec, - .proximity = {E->x, E->y}, - .in = E->state == WLR_TABLET_TOOL_PROXIMITY_IN, + .timeMs = E.timeMs, + .proximity = E.absolute, + .in = E.in, }); - }, this, "CTablet"); + }); - hyprListener_tip.initCallback(&tablet->events.tip, [this] (void* owner, void* data) { - auto E = (wlr_tablet_tool_tip_event*)data; + listeners.tip = tablet->events.tip.registerListener([this](std::any d) { + auto E = std::any_cast(d); tabletEvents.tip.emit(STipEvent{ - .tool = E->tool, + .tool = E.tool, .tablet = self.lock(), - .timeMs = E->time_msec, - .tip = {E->x, E->y}, - .in = E->state == WLR_TABLET_TOOL_TIP_DOWN, + .timeMs = E.timeMs, + .tip = E.absolute, + .in = E.down, }); - }, this, "CTablet"); + }); - hyprListener_button.initCallback(&tablet->events.button, [this] (void* owner, void* data) { - auto E = (wlr_tablet_tool_button_event*)data; + listeners.button = tablet->events.button.registerListener([this](std::any d) { + auto E = std::any_cast(d); tabletEvents.button.emit(SButtonEvent{ - .tool = E->tool, + .tool = E.tool, .tablet = self.lock(), - .timeMs = E->time_msec, - .button = E->button, - .down = E->state == WLR_BUTTON_PRESSED, + .timeMs = E.timeMs, + .button = E.button, + .down = E.down, }); - }, this, "CTablet"); - // clang-format on + }); - deviceName = tablet->base.name ? tablet->base.name : "UNKNOWN"; + deviceName = tablet->getName(); } CTablet::~CTablet() { - if (tablet) - tablet->data = nullptr; - PROTO::tablet->recheckRegisteredDevices(); } -void CTablet::disconnectCallbacks() { - hyprListener_axis.removeCallback(); - hyprListener_button.removeCallback(); - hyprListener_destroy.removeCallback(); - hyprListener_proximity.removeCallback(); - hyprListener_tip.removeCallback(); -} - eHIDType CTablet::getType() { return HID_TYPE_TABLET; } @@ -167,138 +144,111 @@ uint32_t CTabletPad::getCapabilities() { return HID_INPUT_CAPABILITY_TABLET; } -wlr_tablet_pad* CTabletPad::wlr() { - return pad; +SP CTabletPad::aq() { + return pad.lock(); } eHIDType CTabletPad::getType() { return HID_TYPE_TABLET_PAD; } -CTabletPad::CTabletPad(wlr_tablet_pad* pad_) : pad(pad_) { +CTabletPad::CTabletPad(SP pad_) : pad(pad_) { if (!pad) return; - // clang-format off - hyprListener_destroy.initCallback(&pad->base.events.destroy, [this] (void* owner, void* data) { - pad = nullptr; - disconnectCallbacks(); + listeners.destroy = pad->events.destroy.registerListener([this](std::any d) { + pad.reset(); events.destroy.emit(); - }, this, "CTabletPad"); + }); - hyprListener_button.initCallback(&pad->events.button, [this] (void* owner, void* data) { - auto E = (wlr_tablet_pad_button_event*)data; + listeners.button = pad->events.button.registerListener([this](std::any d) { + auto E = std::any_cast(d); padEvents.button.emit(SButtonEvent{ - .timeMs = E->time_msec, - .button = E->button, - .down = E->state == WLR_BUTTON_PRESSED, - .mode = E->mode, - .group = E->group, + .timeMs = E.timeMs, + .button = E.button, + .down = E.down, + .mode = E.mode, + .group = E.group, }); - }, this, "CTabletPad"); + }); - hyprListener_ring.initCallback(&pad->events.ring, [this] (void* owner, void* data) { - auto E = (wlr_tablet_pad_ring_event*)data; + listeners.ring = pad->events.ring.registerListener([this](std::any d) { + auto E = std::any_cast(d); padEvents.ring.emit(SRingEvent{ - .timeMs = E->time_msec, - .finger = E->source == WLR_TABLET_PAD_RING_SOURCE_FINGER, - .ring = E->ring, - .position = E->position, - .mode = E->mode, + .timeMs = E.timeMs, + .finger = E.source == Aquamarine::ITabletPad::AQ_TABLET_PAD_RING_SOURCE_FINGER, + .ring = E.ring, + .position = E.pos, + .mode = E.mode, }); - }, this, "CTabletPad"); + }); - hyprListener_strip.initCallback(&pad->events.strip, [this] (void* owner, void* data) { - auto E = (wlr_tablet_pad_strip_event*)data; + listeners.strip = pad->events.strip.registerListener([this](std::any d) { + auto E = std::any_cast(d); padEvents.strip.emit(SStripEvent{ - .timeMs = E->time_msec, - .finger = E->source == WLR_TABLET_PAD_STRIP_SOURCE_FINGER, - .strip = E->strip, - .position = E->position, - .mode = E->mode, + .timeMs = E.timeMs, + .finger = E.source == Aquamarine::ITabletPad::AQ_TABLET_PAD_STRIP_SOURCE_FINGER, + .strip = E.strip, + .position = E.pos, + .mode = E.mode, }); - }, this, "CTabletPad"); + }); - hyprListener_attach.initCallback(&pad->events.attach_tablet, [this] (void* owner, void* data) { - if (!data) - return; - - padEvents.attach.emit(CTabletTool::fromWlr((wlr_tablet_tool*)data)); - }, this, "CTabletPad"); - // clang-format on + listeners.attach = pad->events.attach.registerListener([this](std::any d) { + ; // TODO: this doesn't do anything in aq atm + }); - deviceName = pad->base.name ? pad->base.name : "UNKNOWN"; + deviceName = pad->getName(); } CTabletPad::~CTabletPad() { PROTO::tablet->recheckRegisteredDevices(); } -void CTabletPad::disconnectCallbacks() { - hyprListener_ring.removeCallback(); - hyprListener_button.removeCallback(); - hyprListener_destroy.removeCallback(); - hyprListener_strip.removeCallback(); - hyprListener_attach.removeCallback(); -} - uint32_t CTabletTool::getCapabilities() { return HID_INPUT_CAPABILITY_POINTER | HID_INPUT_CAPABILITY_TABLET; } -wlr_tablet_tool* CTabletTool::wlr() { - return tool; +SP CTabletTool::aq() { + return tool.lock(); } eHIDType CTabletTool::getType() { return HID_TYPE_TABLET_TOOL; } -CTabletTool::CTabletTool(wlr_tablet_tool* tool_) : tool(tool_) { +CTabletTool::CTabletTool(SP tool_) : tool(tool_) { if (!tool) return; - // clang-format off - hyprListener_destroy.initCallback(&tool->events.destroy, [this] (void* owner, void* data) { - tool = nullptr; - disconnectCallbacks(); + listeners.destroyTool = tool->events.destroy.registerListener([this] (std::any d) { + tool.reset(); events.destroy.emit(); - }, this, "CTabletTool"); - // clang-format on + }); - if (tool->tilt) + if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_TILT) toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_TILT; - if (tool->pressure) + if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_PRESSURE) toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_PRESSURE; - if (tool->distance) + if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_DISTANCE) toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_DISTANCE; - if (tool->rotation) + if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_ROTATION) toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_ROTATION; - if (tool->slider) + if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_SLIDER) toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_SLIDER; - if (tool->wheel) + if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_WHEEL) toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_WHEEL; - tool->data = this; - - deviceName = std::to_string(tool->hardware_serial) + std::to_string(tool->hardware_wacom); + deviceName = std::format("{:x}-{:x}", tool->serial, tool->id); } CTabletTool::~CTabletTool() { - if (tool) - tool->data = nullptr; - PROTO::tablet->recheckRegisteredDevices(); } -void CTabletTool::disconnectCallbacks() { - hyprListener_destroy.removeCallback(); - listeners.destroySurface.reset(); -} - SP CTabletTool::getSurface() { return pSurface.lock(); } diff --git a/src/devices/Tablet.hpp b/src/devices/Tablet.hpp index ada2cf89905..0efbe79618d 100644 --- a/src/devices/Tablet.hpp +++ b/src/devices/Tablet.hpp @@ -6,9 +6,9 @@ #include "../helpers/math/Math.hpp" #include "../helpers/math/Math.hpp" -struct wlr_tablet; -struct wlr_tablet_tool; -struct wlr_tablet_pad; +AQUAMARINE_FORWARD(ITablet); +AQUAMARINE_FORWARD(ITabletTool); +AQUAMARINE_FORWARD(ITabletPad); class CTabletTool; class CTabletPad; @@ -21,13 +21,12 @@ class CWLSurfaceResource; */ class CTablet : public IHID { public: - static SP create(wlr_tablet* tablet); - static SP fromWlr(wlr_tablet* tablet); + static SP create(SP tablet); ~CTablet(); - virtual uint32_t getCapabilities(); - virtual eHIDType getType(); - wlr_tablet* wlr(); + virtual uint32_t getCapabilities(); + virtual eHIDType getType(); + SP aq(); enum eTabletToolAxes { HID_TABLET_TOOL_AXIS_X = (1 << 0), @@ -42,46 +41,46 @@ class CTablet : public IHID { }; struct SAxisEvent { - wlr_tablet_tool* tool; - SP tablet; - - uint32_t timeMs = 0; - uint32_t updatedAxes = 0; // eTabletToolAxes - Vector2D axis; - Vector2D axisDelta; - Vector2D tilt; - double pressure = 0; - double distance = 0; - double rotation = 0; - double slider = 0; - double wheelDelta = 0; + SP tool; + SP tablet; + + uint32_t timeMs = 0; + uint32_t updatedAxes = 0; // eTabletToolAxes + Vector2D axis; + Vector2D axisDelta; + Vector2D tilt; + double pressure = 0; + double distance = 0; + double rotation = 0; + double slider = 0; + double wheelDelta = 0; }; struct SProximityEvent { - wlr_tablet_tool* tool; - SP tablet; + SP tool; + SP tablet; - uint32_t timeMs = 0; - Vector2D proximity; - bool in = false; + uint32_t timeMs = 0; + Vector2D proximity; + bool in = false; }; struct STipEvent { - wlr_tablet_tool* tool; - SP tablet; + SP tool; + SP tablet; - uint32_t timeMs = 0; - Vector2D tip; - bool in = false; + uint32_t timeMs = 0; + Vector2D tip; + bool in = false; }; struct SButtonEvent { - wlr_tablet_tool* tool; - SP tablet; + SP tool; + SP tablet; - uint32_t timeMs = 0; - uint32_t button; - bool down = false; + uint32_t timeMs = 0; + uint32_t button; + bool down = false; }; struct { @@ -100,27 +99,27 @@ class CTablet : public IHID { CBox boundBox; // output-local private: - CTablet(wlr_tablet* tablet); + CTablet(SP tablet); - void disconnectCallbacks(); + WP tablet; - wlr_tablet* tablet = nullptr; - - DYNLISTENER(destroy); - DYNLISTENER(axis); - DYNLISTENER(proximity); - DYNLISTENER(tip); - DYNLISTENER(button); + struct { + CHyprSignalListener destroy; + CHyprSignalListener axis; + CHyprSignalListener proximity; + CHyprSignalListener tip; + CHyprSignalListener button; + } listeners; }; class CTabletPad : public IHID { public: - static SP create(wlr_tablet_pad* pad); + static SP create(SP pad); ~CTabletPad(); - virtual uint32_t getCapabilities(); - virtual eHIDType getType(); - wlr_tablet_pad* wlr(); + virtual uint32_t getCapabilities(); + virtual eHIDType getType(); + SP aq(); struct SButtonEvent { uint32_t timeMs = 0; @@ -159,23 +158,22 @@ class CTabletPad : public IHID { std::string hlName; private: - CTabletPad(wlr_tablet_pad* pad); + CTabletPad(SP pad); - void disconnectCallbacks(); + WP pad; - wlr_tablet_pad* pad = nullptr; - - DYNLISTENER(destroy); - DYNLISTENER(ring); - DYNLISTENER(strip); - DYNLISTENER(button); - DYNLISTENER(attach); + struct { + CHyprSignalListener destroy; + CHyprSignalListener ring; + CHyprSignalListener strip; + CHyprSignalListener button; + CHyprSignalListener attach; + } listeners; }; class CTabletTool : public IHID { public: - static SP create(wlr_tablet_tool* tool); - static SP fromWlr(wlr_tablet_tool* tool); + static SP create(SP tool); ~CTabletTool(); enum eTabletToolType { @@ -198,35 +196,31 @@ class CTabletTool : public IHID { HID_TABLET_TOOL_CAPABILITY_WHEEL = (1 << 5), }; - virtual uint32_t getCapabilities(); - wlr_tablet_tool* wlr(); - virtual eHIDType getType(); - SP getSurface(); - void setSurface(SP); + virtual uint32_t getCapabilities(); + SP aq(); + virtual eHIDType getType(); + SP getSurface(); + void setSurface(SP); - WP self; - Vector2D tilt; - bool active = false; // true if in proximity - uint32_t toolCapabilities = 0; + WP self; + Vector2D tilt; + bool active = false; // true if in proximity + uint32_t toolCapabilities = 0; - bool isDown = false; - std::vector buttonsDown; - Vector2D absolutePos; // last known absolute position. + bool isDown = false; + std::vector buttonsDown; + Vector2D absolutePos; // last known absolute position. - std::string hlName; + std::string hlName; private: - CTabletTool(wlr_tablet_tool* tool); - - void disconnectCallbacks(); - - WP pSurface; - - wlr_tablet_tool* tool = nullptr; + CTabletTool(SP tool); - DYNLISTENER(destroy); + WP pSurface; + WP tool; struct { CHyprSignalListener destroySurface; + CHyprSignalListener destroyTool; } listeners; }; \ No newline at end of file diff --git a/src/events/Devices.cpp b/src/events/Devices.cpp deleted file mode 100644 index a7c5dd55ef0..00000000000 --- a/src/events/Devices.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "Events.hpp" - -#include "../Compositor.hpp" -#include "../helpers/WLClasses.hpp" -#include "../managers/input/InputManager.hpp" -#include "../render/Renderer.hpp" - -// ---------------------------------------------------- // -// _____ ________ _______ _____ ______ _____ // -// | __ \| ____\ \ / /_ _/ ____| ____|/ ____| // -// | | | | |__ \ \ / / | || | | |__ | (___ // -// | | | | __| \ \/ / | || | | __| \___ \ // -// | |__| | |____ \ / _| || |____| |____ ____) | // -// |_____/|______| \/ |_____\_____|______|_____/ // -// // -// ---------------------------------------------------- // - -void Events::listener_newInput(wl_listener* listener, void* data) { - const auto DEVICE = (wlr_input_device*)data; - - switch (DEVICE->type) { - case WLR_INPUT_DEVICE_KEYBOARD: - Debug::log(LOG, "Attached a keyboard with name {}", DEVICE->name); - //g_pInputManager->newKeyboard(DEVICE); - break; - case WLR_INPUT_DEVICE_POINTER: - Debug::log(LOG, "Attached a mouse with name {}", DEVICE->name); - //g_pInputManager->newMouse(DEVICE); - break; - case WLR_INPUT_DEVICE_TOUCH: - Debug::log(LOG, "Attached a touch device with name {}", DEVICE->name); - // g_pInputManager->newTouchDevice(DEVICE); - break; - case WLR_INPUT_DEVICE_TABLET: - Debug::log(LOG, "Attached a tablet with name {}", DEVICE->name); - g_pInputManager->newTablet(DEVICE); - break; - case WLR_INPUT_DEVICE_TABLET_PAD: - Debug::log(LOG, "Attached a tablet pad with name {}", DEVICE->name); - g_pInputManager->newTabletPad(DEVICE); - break; - case WLR_INPUT_DEVICE_SWITCH: - Debug::log(LOG, "Attached a switch device with name {}", DEVICE->name); - // g_pInputManager->newSwitch(DEVICE); - break; - default: Debug::log(WARN, "Unrecognized input device plugged in: {}", DEVICE->name); break; - } - - g_pInputManager->updateCapabilities(); -} diff --git a/src/events/Events.hpp b/src/events/Events.hpp index f8eb9d2fb23..8e73f54a04c 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -8,16 +8,6 @@ // namespace Events { - // Monitor events - LISTENER(change); - LISTENER(newOutput); - - // DRM events - LISTENER(leaseRequest); - - // Layer events - LISTENER(newLayerSurface); - // Window events DYNLISTENFUNC(commitWindow); DYNLISTENFUNC(mapWindow); @@ -35,15 +25,6 @@ namespace Events { DYNLISTENFUNC(setOverrideRedirect); DYNLISTENFUNC(ackConfigure); - LISTENER(newInput); - - // Virt Ptr - LISTENER(newVirtPtr); - - // Various - LISTENER(requestSetSel); - LISTENER(requestSetPrimarySel); - // Monitor part 2 the sequel DYNLISTENFUNC(monitorFrame); DYNLISTENFUNC(monitorDestroy); @@ -52,16 +33,4 @@ namespace Events { DYNLISTENFUNC(monitorNeedsFrame); DYNLISTENFUNC(monitorCommit); DYNLISTENFUNC(monitorBind); - - // XWayland - LISTENER(surfaceXWayland); - - // Renderer destroy - LISTENER(RendererDestroy); - - // session - LISTENER(sessionActive); - - // Session Lock - LISTENER(newSessionLock); }; diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp deleted file mode 100644 index 82790ec575f..00000000000 --- a/src/events/Misc.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "Events.hpp" - -#include "../Compositor.hpp" -#include "../helpers/WLClasses.hpp" -#include "../managers/input/InputManager.hpp" -#include "../render/Renderer.hpp" -#include "../managers/CursorManager.hpp" - -// ------------------------------ // -// __ __ _____ _____ _____ // -// | \/ |_ _|/ ____|/ ____| // -// | \ / | | | | (___ | | // -// | |\/| | | | \___ \| | // -// | | | |_| |_ ____) | |____ // -// |_| |_|_____|_____/ \_____| // -// // -// ------------------------------ // - -void Events::listener_leaseRequest(wl_listener* listener, void* data) { - const auto REQUEST = (wlr_drm_lease_request_v1*)data; - struct wlr_drm_lease_v1* lease = wlr_drm_lease_request_v1_grant(REQUEST); - if (!lease) { - Debug::log(ERR, "Failed to grant lease request!"); - wlr_drm_lease_request_v1_reject(REQUEST); - } -} - -void Events::listener_RendererDestroy(wl_listener* listener, void* data) { - Debug::log(LOG, "!!Renderer destroyed!!"); -} - -void Events::listener_sessionActive(wl_listener* listener, void* data) { - if (g_pCompositor->m_pAqBackend->session->active) { - Debug::log(LOG, "Session got activated!"); - - g_pCompositor->m_bSessionActive = true; - - for (auto& m : g_pCompositor->m_vMonitors) { - g_pCompositor->scheduleFrameForMonitor(m.get()); - g_pHyprRenderer->applyMonitorRule(m.get(), &m->activeMonitorRule, true); - } - - g_pConfigManager->m_bWantsMonitorReload = true; - } else { - Debug::log(LOG, "Session got inactivated!"); - - g_pCompositor->m_bSessionActive = false; - - for (auto& m : g_pCompositor->m_vMonitors) { - m->noFrameSchedule = true; - m->framesToSkip = 1; - } - } -} diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index ae1dd7ca5a1..13fe0949b34 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1531,9 +1531,9 @@ void CInputManager::setTouchDeviceConfigs(SP dev) { void CInputManager::setTabletConfigs() { for (auto& t : m_vTablets) { - if (wlr_input_device_is_libinput(&t->wlr()->base)) { + if (t->aq()->getLibinputHandle()) { const auto NAME = t->hlName; - const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&t->wlr()->base); + const auto LIBINPUTDEV = t->aq()->getLibinputHandle(); const auto RELINPUT = g_pConfigManager->getDeviceInt(NAME, "relative_input", "input:tablet:relative_input"); t->relativeInput = RELINPUT; @@ -1561,8 +1561,8 @@ void CInputManager::setTabletConfigs() { const auto ACTIVE_AREA_SIZE = g_pConfigManager->getDeviceVec(NAME, "active_area_size", "input:tablet:active_area_size"); const auto ACTIVE_AREA_POS = g_pConfigManager->getDeviceVec(NAME, "active_area_position", "input:tablet:active_area_position"); if (ACTIVE_AREA_SIZE.x != 0 || ACTIVE_AREA_SIZE.y != 0) { - t->activeArea = CBox{ACTIVE_AREA_POS.x / t->wlr()->width_mm, ACTIVE_AREA_POS.y / t->wlr()->height_mm, (ACTIVE_AREA_POS.x + ACTIVE_AREA_SIZE.x) / t->wlr()->width_mm, - (ACTIVE_AREA_POS.y + ACTIVE_AREA_SIZE.y) / t->wlr()->height_mm}; + t->activeArea = CBox{ACTIVE_AREA_POS.x / t->aq()->physicalSize.x, ACTIVE_AREA_POS.y / t->aq()->physicalSize.y, + (ACTIVE_AREA_POS.x + ACTIVE_AREA_SIZE.x) / t->aq()->physicalSize.x, (ACTIVE_AREA_POS.y + ACTIVE_AREA_SIZE.y) / t->aq()->physicalSize.y}; } } } diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index b24bffd7d7f..ebf00b2dfa3 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -22,6 +22,9 @@ AQUAMARINE_FORWARD(IPointer); AQUAMARINE_FORWARD(IKeyboard); AQUAMARINE_FORWARD(ITouch); AQUAMARINE_FORWARD(ISwitch); +AQUAMARINE_FORWARD(ITablet); +AQUAMARINE_FORWARD(ITabletTool); +AQUAMARINE_FORWARD(ITabletPad); enum eClickBehaviorMode { CLICKMODE_DEFAULT = 0, @@ -93,9 +96,8 @@ class CInputManager { void newVirtualMouse(SP); void newTouchDevice(SP); void newSwitch(SP); - void newTabletTool(wlr_tablet_tool*); - void newTabletPad(wlr_input_device*); - void newTablet(wlr_input_device*); + void newTabletPad(SP); + void newTablet(SP); void destroyTouchDevice(SP); void destroyKeyboard(SP); void destroyPointer(SP); @@ -237,7 +239,7 @@ class CInputManager { void mouseMoveUnified(uint32_t, bool refocus = false); - SP ensureTabletToolPresent(wlr_tablet_tool*); + SP ensureTabletToolPresent(SP); void applyConfigToKeyboard(SP); diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index f1157e4b642..5e50e851af8 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -62,7 +62,7 @@ static void refocusTablet(SP tab, SP tool, bool motion = f if (!motion) return; - if (LASTHLSURFACE->constraint() && tool->wlr()->type != WLR_TABLET_TOOL_TYPE_MOUSE) { + if (LASTHLSURFACE->constraint() && tool->aq()->type != Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_MOUSE) { // cursor logic will completely break here as the cursor will be locked. // let's just "map" the desired position to the constraint area. @@ -102,7 +102,7 @@ void CInputManager::onTabletAxis(CTablet::SAxisEvent e) { Vector2D delta = {std::isnan(dx) ? 0.0 : dx, std::isnan(dy) ? 0.0 : dy}; switch (e.tool->type) { - case WLR_TABLET_TOOL_TYPE_MOUSE: { + case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_MOUSE: { g_pPointerManager->move(delta); break; } @@ -205,12 +205,12 @@ void CInputManager::onTabletProximity(CTablet::SProximityEvent e) { PROTO::idle->onActivity(); } -void CInputManager::newTablet(wlr_input_device* pDevice) { - const auto PNEWTABLET = m_vTablets.emplace_back(CTablet::create(wlr_tablet_from_input_device(pDevice))); +void CInputManager::newTablet(SP pDevice) { + const auto PNEWTABLET = m_vTablets.emplace_back(CTablet::create(pDevice)); m_vHIDs.push_back(PNEWTABLET); try { - PNEWTABLET->hlName = deviceNameToInternalString(pDevice->name); + PNEWTABLET->hlName = deviceNameToInternalString(pDevice->getName()); } catch (std::exception& e) { Debug::log(ERR, "Tablet had no name???"); // logic error } @@ -227,28 +227,32 @@ void CInputManager::newTablet(wlr_input_device* pDevice) { setTabletConfigs(); } -SP CInputManager::ensureTabletToolPresent(wlr_tablet_tool* pTool) { - if (pTool->data == nullptr) { - const auto PTOOL = m_vTabletTools.emplace_back(CTabletTool::create(pTool)); - m_vHIDs.push_back(PTOOL); - - PTOOL->events.destroy.registerStaticListener( - [this](void* owner, std::any d) { - auto TOOL = ((CTabletTool*)owner)->self; - destroyTabletTool(TOOL.lock()); - }, - PTOOL.get()); +SP CInputManager::ensureTabletToolPresent(SP pTool) { + + for (auto& t : m_vTabletTools) { + if (t->aq() == pTool) + return t; } - return CTabletTool::fromWlr(pTool); + const auto PTOOL = m_vTabletTools.emplace_back(CTabletTool::create(pTool)); + m_vHIDs.push_back(PTOOL); + + PTOOL->events.destroy.registerStaticListener( + [this](void* owner, std::any d) { + auto TOOL = ((CTabletTool*)owner)->self; + destroyTabletTool(TOOL.lock()); + }, + PTOOL.get()); + + return PTOOL; } -void CInputManager::newTabletPad(wlr_input_device* pDevice) { - const auto PNEWPAD = m_vTabletPads.emplace_back(CTabletPad::create(wlr_tablet_pad_from_input_device(pDevice))); +void CInputManager::newTabletPad(SP pDevice) { + const auto PNEWPAD = m_vTabletPads.emplace_back(CTabletPad::create(pDevice)); m_vHIDs.push_back(PNEWPAD); try { - PNEWPAD->hlName = deviceNameToInternalString(pDevice->name); + PNEWPAD->hlName = deviceNameToInternalString(pDevice->getName()); } catch (std::exception& e) { Debug::log(ERR, "Pad had no name???"); // logic error } @@ -259,7 +263,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) { destroyTabletPad(PAD.lock()); }, PNEWPAD.get()); - PNEWPAD->padEvents.button.registerStaticListener([this](void* owner, std::any e) { + PNEWPAD->padEvents.button.registerStaticListener([](void* owner, std::any e) { const auto E = std::any_cast(e); const auto PPAD = ((CTabletPad*)owner)->self.lock(); @@ -267,26 +271,25 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) { PROTO::tablet->buttonPad(PPAD, E.button, E.timeMs, E.down); }, PNEWPAD.get()); - PNEWPAD->padEvents.strip.registerStaticListener([this](void* owner, std::any e) { + PNEWPAD->padEvents.strip.registerStaticListener([](void* owner, std::any e) { const auto E = std::any_cast(e); const auto PPAD = ((CTabletPad*)owner)->self.lock(); PROTO::tablet->strip(PPAD, E.strip, E.position, E.finger, E.timeMs); }, PNEWPAD.get()); - PNEWPAD->padEvents.ring.registerStaticListener([this](void* owner, std::any e) { + PNEWPAD->padEvents.ring.registerStaticListener([](void* owner, std::any e) { const auto E = std::any_cast(e); const auto PPAD = ((CTabletPad*)owner)->self.lock(); PROTO::tablet->ring(PPAD, E.ring, E.position, E.finger, E.timeMs); }, PNEWPAD.get()); - PNEWPAD->padEvents.attach.registerStaticListener([this](void* owner, std::any e) { + PNEWPAD->padEvents.attach.registerStaticListener([](void* owner, std::any e) { const auto PPAD = ((CTabletPad*)owner)->self.lock(); const auto TOOL = std::any_cast>(e); PPAD->parent = TOOL; }, PNEWPAD.get()); - // clang-format on } diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp index 7b62f2451d6..ca976eaffa6 100644 --- a/src/protocols/Tablet.cpp +++ b/src/protocols/Tablet.cpp @@ -44,17 +44,17 @@ bool CTabletPadGroupV2Resource::good() { return resource->resource(); } -void CTabletPadGroupV2Resource::sendData(SP pad, wlr_tablet_pad_group* group) { - resource->sendModes(group->mode_count); +void CTabletPadGroupV2Resource::sendData(SP pad, SP group) { + resource->sendModes(group->modes); wl_array buttonArr; wl_array_init(&buttonArr); - wl_array_add(&buttonArr, group->button_count * sizeof(int)); - memcpy(buttonArr.data, group->buttons, group->button_count * sizeof(int)); + wl_array_add(&buttonArr, group->buttons.size() * sizeof(int)); + memcpy(buttonArr.data, group->buttons.data(), group->buttons.size() * sizeof(int)); resource->sendButtons(&buttonArr); wl_array_release(&buttonArr); - for (size_t i = 0; i < group->strip_count; ++i) { + for (size_t i = 0; i < group->strips.size(); ++i) { const auto RESOURCE = PROTO::tablet->m_vStrips.emplace_back(makeShared(makeShared(resource->client(), resource->version(), 0), i)); @@ -67,7 +67,7 @@ void CTabletPadGroupV2Resource::sendData(SP pad, wlr_tablet_pad_grou resource->sendStrip(RESOURCE->resource.get()); } - for (size_t i = 0; i < group->ring_count; ++i) { + for (size_t i = 0; i < group->rings.size(); ++i) { const auto RESOURCE = PROTO::tablet->m_vRings.emplace_back(makeShared(makeShared(resource->client(), resource->version(), 0), i)); @@ -97,23 +97,20 @@ bool CTabletPadV2Resource::good() { void CTabletPadV2Resource::sendData() { // this is dodgy as fuck. I hate wl_array. it's expanded wl_array_for_each because C++ would complain about the implicit casts - const char** path_ptr; - for (path_ptr = (const char**)(&pad->wlr()->paths)->data; (const char*)path_ptr < ((const char*)(&pad->wlr()->paths)->data + (&pad->wlr()->paths)->size); (path_ptr)++) { - resource->sendPath(*path_ptr); + for (auto& p : pad->aq()->paths) { + resource->sendPath(p.c_str()); } - resource->sendButtons(pad->wlr()->button_count); + resource->sendButtons(pad->aq()->buttons); - wlr_tablet_pad_group* group; - size_t i = 0; - wl_list_for_each(group, &pad->wlr()->groups, link) { - createGroup(group, i++); + for (size_t i = 0; i < pad->aq()->groups.size(); ++i) { + createGroup(pad->aq()->groups.at(i), i); } resource->sendDone(); } -void CTabletPadV2Resource::createGroup(wlr_tablet_pad_group* group, size_t idx) { +void CTabletPadV2Resource::createGroup(SP group, size_t idx) { const auto RESOURCE = PROTO::tablet->m_vGroups.emplace_back(makeShared(makeShared(resource->client(), resource->version(), 0), idx)); @@ -142,13 +139,10 @@ bool CTabletV2Resource::good() { void CTabletV2Resource::sendData() { resource->sendName(tablet->deviceName.c_str()); - resource->sendId(tablet->wlr()->usb_vendor_id, tablet->wlr()->usb_product_id); + resource->sendId(tablet->aq()->usbVendorID, tablet->aq()->usbProductID); - // this is dodgy as fuck. I hate wl_array. it's expanded wl_array_for_each because C++ would complain about the implicit casts - const char** path_ptr; - for (path_ptr = (const char**)(&tablet->wlr()->paths)->data; (const char*)path_ptr < ((const char*)(&tablet->wlr()->paths)->data + (&tablet->wlr()->paths)->size); - (path_ptr)++) { - resource->sendPath(*path_ptr); + for (auto& p : tablet->aq()->paths) { + resource->sendPath(p.c_str()); } resource->sendDone(); @@ -179,23 +173,23 @@ bool CTabletToolV2Resource::good() { } void CTabletToolV2Resource::sendData() { - static auto WLR_TYPE_TO_PROTO = [](uint32_t wlr) -> zwpTabletToolV2Type { - switch (wlr) { - case WLR_TABLET_TOOL_TYPE_PEN: return ZWP_TABLET_TOOL_V2_TYPE_PEN; - case WLR_TABLET_TOOL_TYPE_ERASER: return ZWP_TABLET_TOOL_V2_TYPE_ERASER; - case WLR_TABLET_TOOL_TYPE_BRUSH: return ZWP_TABLET_TOOL_V2_TYPE_BRUSH; - case WLR_TABLET_TOOL_TYPE_PENCIL: return ZWP_TABLET_TOOL_V2_TYPE_PENCIL; - case WLR_TABLET_TOOL_TYPE_AIRBRUSH: return ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH; - case WLR_TABLET_TOOL_TYPE_MOUSE: return ZWP_TABLET_TOOL_V2_TYPE_MOUSE; - case WLR_TABLET_TOOL_TYPE_LENS: return ZWP_TABLET_TOOL_V2_TYPE_LENS; + static auto AQ_TYPE_TO_PROTO = [](uint32_t aq) -> zwpTabletToolV2Type { + switch (aq) { + case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_PEN: return ZWP_TABLET_TOOL_V2_TYPE_PEN; + case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_ERASER: return ZWP_TABLET_TOOL_V2_TYPE_ERASER; + case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_BRUSH: return ZWP_TABLET_TOOL_V2_TYPE_BRUSH; + case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_PENCIL: return ZWP_TABLET_TOOL_V2_TYPE_PENCIL; + case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_AIRBRUSH: return ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH; + case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_MOUSE: return ZWP_TABLET_TOOL_V2_TYPE_MOUSE; + case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_LENS: return ZWP_TABLET_TOOL_V2_TYPE_LENS; default: ASSERT(false); } UNREACHABLE(); }; - resource->sendType(WLR_TYPE_TO_PROTO(tool->wlr()->type)); - resource->sendHardwareSerial(tool->wlr()->hardware_serial >> 32, tool->wlr()->hardware_serial & 0xFFFFFFFF); - resource->sendHardwareIdWacom(tool->wlr()->hardware_wacom >> 32, tool->wlr()->hardware_wacom & 0xFFFFFFFF); + resource->sendType(AQ_TYPE_TO_PROTO(tool->aq()->type)); + resource->sendHardwareSerial(tool->aq()->serial >> 32, tool->aq()->serial & 0xFFFFFFFF); + resource->sendHardwareIdWacom(tool->aq()->id >> 32, tool->aq()->id & 0xFFFFFFFF); if (tool->toolCapabilities & CTabletTool::eTabletToolCapabilities::HID_TABLET_TOOL_CAPABILITY_DISTANCE) resource->sendCapability(zwpTabletToolV2Capability::ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE); if (tool->toolCapabilities & CTabletTool::eTabletToolCapabilities::HID_TABLET_TOOL_CAPABILITY_PRESSURE) diff --git a/src/protocols/Tablet.hpp b/src/protocols/Tablet.hpp index 58f13c1a279..1ebcb1e53c7 100644 --- a/src/protocols/Tablet.hpp +++ b/src/protocols/Tablet.hpp @@ -6,6 +6,7 @@ #include "WaylandProtocol.hpp" #include "tablet-v2.hpp" #include "../helpers/math/Math.hpp" +#include class CTablet; class CTabletTool; @@ -51,7 +52,7 @@ class CTabletPadGroupV2Resource { CTabletPadGroupV2Resource(SP resource_, size_t idx); bool good(); - void sendData(SP pad, wlr_tablet_pad_group* group); + void sendData(SP pad, SP group); std::vector> rings; std::vector> strips; @@ -83,7 +84,7 @@ class CTabletPadV2Resource { private: SP resource; - void createGroup(wlr_tablet_pad_group* group, size_t idx); + void createGroup(SP group, size_t idx); friend class CTabletSeat; friend class CTabletV2Protocol; From 2fec6f0ab7fd51a49683be62f3c2048ce1d03fc3 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 3 Jul 2024 19:15:23 +0200 Subject: [PATCH 030/113] le oops --- patch.txt | 84 ------------------------------------------------------- 1 file changed, 84 deletions(-) delete mode 100644 patch.txt diff --git a/patch.txt b/patch.txt deleted file mode 100644 index 6c79b0fb358..00000000000 --- a/patch.txt +++ /dev/null @@ -1,84 +0,0 @@ -diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp -index 8b4ba0ee..e34aa54b 100644 ---- a/src/managers/PointerManager.cpp -+++ b/src/managers/PointerManager.cpp -@@ -4,6 +4,7 @@ - #include "../protocols/PointerGestures.hpp" - #include "../protocols/FractionalScale.hpp" - #include "../protocols/core/Compositor.hpp" -+#include "eventLoop/EventLoopManager.hpp" - #include "SeatManager.hpp" - #include - #include -@@ -139,8 +140,8 @@ CPointerManager::CPointerManager() { - - onMonitorLayoutChange(); - -- PMONITOR->events.modeChanged.registerStaticListener([this](void* owner, std::any data) { onMonitorLayoutChange(); }, nullptr); -- PMONITOR->events.disconnect.registerStaticListener([this](void* owner, std::any data) { onMonitorLayoutChange(); }, nullptr); -+ PMONITOR->events.modeChanged.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr); -+ PMONITOR->events.disconnect.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr); - PMONITOR->events.destroy.registerStaticListener( - [this](void* owner, std::any data) { - if (g_pCompositor && !g_pCompositor->m_bIsShuttingDown) -diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp -index 1193ffb8..e2d72f22 100644 ---- a/src/managers/eventLoop/EventLoopManager.cpp -+++ b/src/managers/eventLoop/EventLoopManager.cpp -@@ -86,4 +86,25 @@ void CEventLoopManager::nudgeTimers() { - itimerspec ts = {.it_value = now}; - - timerfd_settime(m_sTimers.timerfd, TFD_TIMER_ABSTIME, &ts, nullptr); --} -\ No newline at end of file -+} -+ -+void CEventLoopManager::doLater(const std::function& fn) { -+ m_sIdle.fns.emplace_back(fn); -+ -+ if (m_sIdle.eventSource) -+ return; -+ -+ m_sIdle.eventSource = wl_event_loop_add_idle( -+ m_sWayland.loop, -+ [](void* data) { -+ auto IDLE = (CEventLoopManager::SIdleData*)data; -+ auto cpy = IDLE->fns; -+ IDLE->fns.clear(); -+ IDLE->eventSource = nullptr; -+ for (auto& c : cpy) { -+ if (c) -+ c(); -+ } -+ }, -+ &m_sIdle); -+} -diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp -index 7a4fa19e..77e57513 100644 ---- a/src/managers/eventLoop/EventLoopManager.hpp -+++ b/src/managers/eventLoop/EventLoopManager.hpp -@@ -23,6 +23,14 @@ class CEventLoopManager { - // recalculates timers - void nudgeTimers(); - -+ // schedules a function to run later, aka in a wayland idle event. -+ void doLater(const std::function& fn); -+ -+ struct SIdleData { -+ wl_event_source* eventSource = nullptr; -+ std::vector> fns; -+ }; -+ - private: - struct { - wl_event_loop* loop = nullptr; -@@ -34,6 +42,8 @@ class CEventLoopManager { - std::vector> timers; - int timerfd = -1; - } m_sTimers; -+ -+ SIdleData m_sIdle; - }; - - inline std::unique_ptr g_pEventLoopManager; -\ No newline at end of file From d087e688a709c6be66f0147e6acf9b3b63f23ba8 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 3 Jul 2024 23:10:58 +0300 Subject: [PATCH 031/113] Nix: add aquamarine --- flake.lock | 30 ++++++++++++++++++++++++++++++ flake.nix | 8 ++++++++ nix/default.nix | 2 ++ nix/overlays.nix | 1 + 4 files changed, 41 insertions(+) diff --git a/flake.lock b/flake.lock index b5f5738a71b..84095f56c73 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,34 @@ { "nodes": { + "aquamarine": { + "inputs": { + "hyprutils": [ + "hyprutils" + ], + "hyprwayland-scanner": [ + "hyprwayland-scanner" + ], + "nixpkgs": [ + "nixpkgs" + ], + "systems": [ + "systems" + ] + }, + "locked": { + "lastModified": 1720028623, + "narHash": "sha256-8TR1sSZlFnA5kxj9oyx9pm7h8kzgM8/VIBhA+sTJIjo=", + "owner": "hyprwm", + "repo": "aquamarine", + "rev": "1844da3814bd97afd3c3f4c4d6c5e318e3552247", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "aquamarine", + "type": "github" + } + }, "hyprcursor": { "inputs": { "hyprlang": [ @@ -141,6 +170,7 @@ }, "root": { "inputs": { + "aquamarine": "aquamarine", "hyprcursor": "hyprcursor", "hyprlang": "hyprlang", "hyprutils": "hyprutils", diff --git a/flake.nix b/flake.nix index 88cb593bcc3..9c20b3f55e4 100644 --- a/flake.nix +++ b/flake.nix @@ -7,6 +7,14 @@ # systems.url = "github:nix-systems/default-linux"; + aquamarine = { + url = "github:hyprwm/aquamarine"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.systems.follows = "systems"; + inputs.hyprutils.follows = "hyprutils"; + inputs.hyprwayland-scanner.follows = "hyprwayland-scanner"; + }; + hyprcursor = { url = "github:hyprwm/hyprcursor"; inputs.nixpkgs.follows = "nixpkgs"; diff --git a/nix/default.nix b/nix/default.nix index a23026888c6..5018146c9cf 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -6,6 +6,7 @@ makeWrapper, cmake, ninja, + aquamarine, binutils, cairo, expat, @@ -104,6 +105,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov buildInputs = lib.concatLists [ [ + aquamarine cairo expat fribidi diff --git a/nix/overlays.nix b/nix/overlays.nix index a4e1df3731f..9d100d51e83 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -21,6 +21,7 @@ in { # Packages for variations of Hyprland, dependencies included. hyprland-packages = lib.composeManyExtensions [ # Dependencies + inputs.aquamarine.overlays.default inputs.hyprcursor.overlays.default inputs.hyprlang.overlays.default inputs.hyprutils.overlays.default From 6229ac01ac8e1c63dac348575135c85f72aef80b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 3 Jul 2024 22:11:57 +0200 Subject: [PATCH 032/113] stuf --- src/Compositor.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 00e7fce1f1a..9866acceef2 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -640,8 +640,7 @@ void CCompositor::startCompositor(std::string socketName, int socketFd) { signal(SIGPIPE, SIG_IGN); - // TODO: - if (false /* Session-less Hyprland usually means a nest, don't update the env in that case */) { + if (m_pAqBackend->hasSession() /* Session-less Hyprland usually means a nest, don't update the env in that case */) { const auto CMD = #ifdef USES_SYSTEMD "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " From 475abb2ff2975e11954b0994e4f8343ce343cbe2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 3 Jul 2024 22:12:28 +0200 Subject: [PATCH 033/113] stuf2 --- src/Compositor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 9866acceef2..54e89999f70 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -380,7 +380,7 @@ void CCompositor::cleanEnvironment() { unsetenv("XDG_BACKEND"); unsetenv("XDG_CURRENT_DESKTOP"); - if (false /* TODO: */) { + if (m_pAqBackend->hasSession()) { const auto CMD = #ifdef USES_SYSTEMD "systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " From 8a21583a8e80a6e583f75827d83cd44f676e49f1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 3 Jul 2024 22:24:29 +0200 Subject: [PATCH 034/113] stuf3 --- src/managers/KeybindManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 22bc4719054..6ee5d4432d6 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -892,6 +892,7 @@ uint64_t CKeybindManager::spawnRaw(std::string args) { for (auto& e : HLENV) { setenv(e.first.c_str(), e.second.c_str(), 1); } + setenv("WAYLAND_DISPLAY", g_pCompositor->m_szWLDisplaySocket.c_str(), 1); close(socket[0]); close(socket[1]); execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr); From 9f28b37e2c9b67f1c69a38d34a7422edcba8f0fb Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 3 Jul 2024 22:31:51 +0200 Subject: [PATCH 035/113] =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E3=82=B9?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/devices/Keyboard.cpp | 2 +- src/devices/Tablet.cpp | 2 +- src/helpers/Monitor.cpp | 12 ++++++------ src/managers/eventLoop/EventLoopManager.hpp | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/devices/Keyboard.cpp b/src/devices/Keyboard.cpp index f77829a724e..ae28c07da1b 100644 --- a/src/devices/Keyboard.cpp +++ b/src/devices/Keyboard.cpp @@ -30,7 +30,7 @@ CKeyboard::CKeyboard(SP keeb) : keyboard(keeb) { }); listeners.key = keeb->events.key.registerListener([this](std::any d) { - auto E = std::any_cast(d); + auto E = std::any_cast(d); updateXkbStateWithKey(E.key + 8, E.pressed); diff --git a/src/devices/Tablet.cpp b/src/devices/Tablet.cpp index a1f642dfbb7..71ca899121d 100644 --- a/src/devices/Tablet.cpp +++ b/src/devices/Tablet.cpp @@ -224,7 +224,7 @@ CTabletTool::CTabletTool(SP tool_) : tool(tool_) { if (!tool) return; - listeners.destroyTool = tool->events.destroy.registerListener([this] (std::any d) { + listeners.destroyTool = tool->events.destroy.registerListener([this](std::any d) { tool.reset(); events.destroy.emit(); }); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index ad5b0199e78..196f44df55e 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -791,14 +791,14 @@ bool CMonitorState::test() { } bool CMonitorState::updateSwapchain() { - auto options = m_pOwner->output->swapchain->currentOptions(); - const auto& STATE = m_pOwner->output->state->state(); - const auto& MODE = STATE.mode ? STATE.mode : STATE.customMode; + auto options = m_pOwner->output->swapchain->currentOptions(); + const auto& STATE = m_pOwner->output->state->state(); + const auto& MODE = STATE.mode ? STATE.mode : STATE.customMode; if (!MODE) return true; - options.format = STATE.drmFormat; + options.format = STATE.drmFormat; options.scanout = true; - options.length = 2; - options.size = MODE->pixelSize; + options.length = 2; + options.size = MODE->pixelSize; return m_pOwner->output->swapchain->reconfigure(options); } diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp index d5b640a3d6f..eff281d6edc 100644 --- a/src/managers/eventLoop/EventLoopManager.hpp +++ b/src/managers/eventLoop/EventLoopManager.hpp @@ -8,7 +8,7 @@ #include "EventLoopTimer.hpp" namespace Aquamarine { - struct SPollFD; + struct SPollFD; }; class CEventLoopManager { From 73dc885e0bec7d96823508280266a6f534c27c9c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 4 Jul 2024 20:52:12 +0200 Subject: [PATCH 036/113] fix trailing comme, thanks VirtCode --- src/debug/HyprCtl.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index d45ca48d6de..4ea53b49bb9 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -61,6 +61,8 @@ static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFor result += std::format("\"{}x{}@{:.2f}Hz\",", m->pixelSize.x, m->pixelSize.y, m->refreshRate / 1000.0); } + trimTrailingComma(result); + return result; } From e5854f851417457d4c15aa232f6faf2fbf2be839 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 4 Jul 2024 22:02:12 +0200 Subject: [PATCH 037/113] stuffZ --- src/Compositor.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 54e89999f70..a7d0c8cbb3b 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -263,6 +263,35 @@ void CCompositor::initServer() { m_iDRMFD = m_pAqBackend->drmFD(); Debug::log(LOG, "Running on DRMFD: {}", m_iDRMFD); + // get socket, avoid using 0 + for (int candidate = 1; candidate <= 32; candidate++) { + const auto CANDIDATESTR = ("wayland-" + std::to_string(candidate)); + const auto RETVAL = wl_display_add_socket(m_sWLDisplay, CANDIDATESTR.c_str()); + if (RETVAL >= 0) { + m_szWLDisplaySocket = CANDIDATESTR; + Debug::log(LOG, "wl_display_add_socket for {} succeeded with {}", CANDIDATESTR, RETVAL); + break; + } else { + Debug::log(WARN, "wl_display_add_socket for {} returned {}: skipping candidate {}", CANDIDATESTR, RETVAL, candidate); + } + } + + if (m_szWLDisplaySocket.empty()) { + Debug::log(WARN, "All candidates failed, trying wl_display_add_socket_auto"); + const auto SOCKETSTR = wl_display_add_socket_auto(m_sWLDisplay); + if (SOCKETSTR) + m_szWLDisplaySocket = SOCKETSTR; + } + + if (m_szWLDisplaySocket.empty()) { + Debug::log(CRIT, "m_szWLDisplaySocket NULL!"); + throwError("m_szWLDisplaySocket was null! (wl_display_add_socket and wl_display_add_socket_auto failed)"); + } + + Debug::log(LOG, "Setting WAYLAND_DISPLAY to {}", m_szWLDisplaySocket); + setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket.c_str(), 1); + setenv("XDG_SESSION_TYPE", "wayland", 1); + initManagers(STAGE_BASICINIT); initManagers(STAGE_LATE); From c1adf83484534293b14987a36e7e67c4c1c1fc9e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 4 Jul 2024 23:15:05 +0200 Subject: [PATCH 038/113] rollback on fail --- src/render/Renderer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 98e82d501a0..a09de65c244 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1421,6 +1421,9 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC); if (!pMonitor->state.commit()) { + // rollback the buffer to avoid writing to the front buffer that is being + // displayed + pMonitor->output->swapchain->rollback(); pMonitor->damage.damageEntire(); return; } From c135fe39e064ada3aa7a9433b833ac49592cfc31 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 5 Jul 2024 14:07:41 +0200 Subject: [PATCH 039/113] dmabuf --- src/protocols/LinuxDMABUF.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 994882c81cc..08faf643b52 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -291,7 +291,6 @@ CLinuxDMABUFFeedbackResource::CLinuxDMABUFFeedbackResource(SPsendTrancheTargetDevice(&deviceArr); - resource->sendTrancheFlags((zwpLinuxDmabufFeedbackV1TrancheFlags)0); wl_array indices; wl_array_init(&indices); @@ -381,7 +380,7 @@ bool CLinuxDMABUFResource::good() { void CLinuxDMABUFResource::sendMods() { for (auto& [fmt, mod] : PROTO::linuxDma->defaultFeedback->tranches) { if (resource->version() < 3) { - if (mod == DRM_FORMAT_MOD_INVALID) + if (mod == DRM_FORMAT_MOD_INVALID || mod == DRM_FORMAT_MOD_LINEAR) resource->sendFormat(fmt); continue; } From 786aef8ac1bf464d7c5429ba346322f5ff47a293 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 5 Jul 2024 14:24:18 +0200 Subject: [PATCH 040/113] fixup presentation feedback --- src/helpers/Monitor.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 196f44df55e..58b4cdd8a62 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -25,19 +25,16 @@ CMonitor::~CMonitor() { events.destroy.emit(); } -static void onPresented(void* owner, void* data) { - const auto PMONITOR = (CMonitor*)owner; - auto E = (wlr_output_event_present*)data; - - PROTO::presentation->onPresented(PMONITOR, E->when, E->refresh, E->seq, E->flags); -} - void CMonitor::onConnect(bool noRule) { listeners.frame = output->events.frame.registerListener([this](std::any d) { Events::listener_monitorFrame(this, nullptr); }); listeners.destroy = output->events.destroy.registerListener([this](std::any d) { Events::listener_monitorDestroy(this, nullptr); }); listeners.commit = output->events.commit.registerListener([this](std::any d) { Events::listener_monitorCommit(this, nullptr); }); listeners.needsFrame = output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(this); }); + listeners.presented = output->events.present.registerListener([this](std::any d) { + auto E = std::any_cast(d); + PROTO::presentation->onPresented(this, E.when, E.refresh, E.seq, E.flags); + }); listeners.state = output->events.state.registerListener([this](std::any d) { if (!createdByUser) From 24672653131e69062e68e99cc88b28015ed565a3 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 5 Jul 2024 19:21:48 +0200 Subject: [PATCH 041/113] leases --- CMakeLists.txt | 1 + src/helpers/Monitor.cpp | 8 +- src/helpers/Monitor.hpp | 2 + src/managers/ProtocolManager.cpp | 2 + src/protocols/DRMLease.cpp | 303 +++++++++++++++++++++++++++++++ src/protocols/DRMLease.hpp | 137 ++++++++++++++ 6 files changed, 449 insertions(+), 4 deletions(-) create mode 100644 src/protocols/DRMLease.cpp create mode 100644 src/protocols/DRMLease.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f7adcb5df21..89dbe9081b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -315,6 +315,7 @@ protocolNew("unstable/primary-selection" "primary-selection-unstable-v1" false) protocolNew("staging/xwayland-shell" "xwayland-shell-v1" false) protocolNew("stable/viewporter" "viewporter" false) protocolNew("stable/linux-dmabuf" "linux-dmabuf-v1" false) +protocolNew("staging/drm-lease" "drm-lease-v1" false) protocolWayland() diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 58b4cdd8a62..fba38f4e094 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -6,6 +6,7 @@ #include "../devices/ITouch.hpp" #include "../protocols/LayerShell.hpp" #include "../protocols/PresentationTime.hpp" +#include "../protocols/DRMLease.hpp" #include "../protocols/core/Output.hpp" #include "../managers/PointerManager.hpp" #include @@ -92,10 +93,9 @@ void CMonitor::onConnect(bool noRule) { if (output->nonDesktop) { Debug::log(LOG, "Not configuring non-desktop output"); - // TODO: - // if (g_pCompositor->m_sWRLDRMLeaseMgr) { - // wlr_drm_lease_v1_manager_offer_output(g_pCompositor->m_sWRLDRMLeaseMgr, output); - // } + if (PROTO::lease) + PROTO::lease->offer(self.lock()); + return; } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index a221e1e9a44..f14ec7d320e 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -113,6 +113,8 @@ class CMonitor { bool RATScheduled = false; CTimer lastPresentationTimer; + bool isBeingLeased = false; + SMonitorRule activeMonitorRule; WP self; diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 74cebd0cb68..90f5294766f 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -35,6 +35,7 @@ #include "../protocols/Viewporter.hpp" #include "../protocols/MesaDRM.hpp" #include "../protocols/LinuxDMABUF.hpp" +#include "../protocols/DRMLease.hpp" #include "../protocols/core/Seat.hpp" #include "../protocols/core/DataDevice.hpp" @@ -130,6 +131,7 @@ CProtocolManager::CProtocolManager() { PROTO::dataWlr = std::make_unique(&zwlr_data_control_manager_v1_interface, 2, "DataDeviceWlr"); PROTO::primarySelection = std::make_unique(&zwp_primary_selection_device_manager_v1_interface, 1, "PrimarySelection"); PROTO::xwaylandShell = std::make_unique(&xwayland_shell_v1_interface, 1, "XWaylandShell"); + PROTO::lease = std::make_unique(&wp_drm_lease_device_v1_interface, 1, "DRMLease"); if (g_pHyprOpenGL->getDRMFormats().size() > 0) { PROTO::mesaDRM = std::make_unique(&wl_drm_interface, 2, "MesaDRM"); diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp new file mode 100644 index 00000000000..36ac09983ef --- /dev/null +++ b/src/protocols/DRMLease.cpp @@ -0,0 +1,303 @@ +#include "DRMLease.hpp" +#include "../Compositor.hpp" +#include +#include + +#define LOGM PROTO::lease->protoLog + +CDRMLeaseResource::CDRMLeaseResource(SP resource_, SP request) : resource(resource_) { + if (!good()) + return; + + resource->setOnDestroy([this](CWpDrmLeaseV1* r) { PROTO::lease->destroyResource(this); }); + resource->setDestroy([this](CWpDrmLeaseV1* r) { PROTO::lease->destroyResource(this); }); + + parent = request->parent; + requested = request->requested; + + for (auto& m : requested) { + if (!m->monitor || m->monitor->isBeingLeased) { + LOGM(ERR, "Rejecting lease: no monitor or monitor is being leased for {}", (m->monitor ? m->monitor->szName : "null")); + resource->sendFinished(); + return; + } + } + + // grant the lease if it is seemingly valid + + LOGM(LOG, "Leasing outputs: {}", [this]() { + std::string roll; + for (auto& o : requested) { + roll += std::format("{} ", o->monitor->szName); + } + return roll; + }()); + + std::vector> outputs; + for (auto& m : requested) { + outputs.emplace_back(m->monitor->output); + } + + auto aqlease = Aquamarine::CDRMLease::create(outputs); + if (!aqlease) { + LOGM(ERR, "Rejecting lease: backend failed to alloc a lease"); + resource->sendFinished(); + return; + } + + LOGM(LOG, "Granting lease, sending fd {}", aqlease->leaseFD); + + resource->sendLeaseFd(aqlease->leaseFD); + + lease = aqlease; + + for (auto& m : requested) { + m->monitor->isBeingLeased = true; + } + + listeners.destroyLease = lease->events.destroy.registerListener([this](std::any d) { + for (auto& m : requested) { + if (m && m->monitor) + m->monitor->isBeingLeased = false; + } + + resource->sendFinished(); + }); + + close(lease->leaseFD); +} + +bool CDRMLeaseResource::good() { + return resource->resource(); +} + +CDRMLeaseRequestResource::CDRMLeaseRequestResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setOnDestroy([this](CWpDrmLeaseRequestV1* r) { PROTO::lease->destroyResource(this); }); + + resource->setRequestConnector([this](CWpDrmLeaseRequestV1* r, wl_resource* conn) { + if (!conn) { + resource->error(-1, "Null connector"); + return; + } + + auto CONNECTOR = CDRMLeaseConnectorResource::fromResource(conn); + + if (std::find(requested.begin(), requested.end(), CONNECTOR) != requested.end()) { + resource->error(WP_DRM_LEASE_REQUEST_V1_ERROR_DUPLICATE_CONNECTOR, "Connector already requested"); + return; + } + + // TODO: when (if) we add multi, make sure this is from the correct device. + + requested.emplace_back(CONNECTOR); + }); + + resource->setSubmit([this](CWpDrmLeaseRequestV1* r, uint32_t id) { + if (requested.empty()) { + resource->error(WP_DRM_LEASE_REQUEST_V1_ERROR_EMPTY_LEASE, "No connectors added"); + return; + } + + auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), -1), self.lock()); + if (!RESOURCE) { + resource->noMemory(); + return; + } + + PROTO::lease->m_vLeases.emplace_back(RESOURCE); + + // per protcol, after submit, this is dead. + PROTO::lease->destroyResource(this); + }); +} + +bool CDRMLeaseRequestResource::good() { + return resource->resource(); +} + +SP CDRMLeaseConnectorResource::fromResource(wl_resource* res) { + auto data = (CDRMLeaseConnectorResource*)(((CWpDrmLeaseConnectorV1*)wl_resource_get_user_data(res))->data()); + return data ? data->self.lock() : nullptr; +} + +CDRMLeaseConnectorResource::CDRMLeaseConnectorResource(SP resource_, SP monitor_) : monitor(monitor_), resource(resource_) { + if (!good()) + return; + + resource->setOnDestroy([this](CWpDrmLeaseConnectorV1* r) { PROTO::lease->destroyResource(this); }); + resource->setDestroy([this](CWpDrmLeaseConnectorV1* r) { PROTO::lease->destroyResource(this); }); + + resource->setData(this); + + listeners.destroyMonitor = monitor->events.destroy.registerListener([this](std::any d) { + resource->sendWithdrawn(); + dead = true; + }); +} + +bool CDRMLeaseConnectorResource::good() { + return resource->resource(); +} + +void CDRMLeaseConnectorResource::sendData() { + resource->sendName(monitor->szName.c_str()); + resource->sendDescription(monitor->szDescription.c_str()); + + auto AQDRMOutput = (Aquamarine::CDRMOutput*)monitor->output.get(); + resource->sendConnectorId(AQDRMOutput->getConnectorID()); + + resource->sendDone(); +} + +CDRMLeaseDeviceResource::CDRMLeaseDeviceResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setOnDestroy([this](CWpDrmLeaseDeviceV1* r) { PROTO::lease->destroyResource(this); }); + resource->setRelease([this](CWpDrmLeaseDeviceV1* r) { PROTO::lease->destroyResource(this); }); + + resource->setCreateLeaseRequest([this](CWpDrmLeaseDeviceV1* r, uint32_t id) { + auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), id)); + if (!RESOURCE) { + resource->noMemory(); + return; + } + + RESOURCE->self = RESOURCE; + + PROTO::lease->m_vRequests.emplace_back(RESOURCE); + + LOGM(LOG, "New lease request {}", id); + + RESOURCE->parent = self; + }); + + int fd = ((Aquamarine::CDRMBackend*)PROTO::lease->primaryDevice->backend.get())->getNonMasterFD(); + if (fd < 0) { + LOGM(ERR, "Failed to dup fd in lease"); + return; + } + + LOGM(LOG, "Sending DRMFD {} to new lease device", fd); + resource->sendDrmFd(fd); + close(fd); + + for (auto& m : PROTO::lease->primaryDevice->offeredOutputs) { + sendConnector(m.lock()); + } + + resource->sendDone(); +} + +bool CDRMLeaseDeviceResource::good() { + return resource->resource(); +} + +void CDRMLeaseDeviceResource::sendConnector(SP monitor) { + if (std::find_if(connectorsSent.begin(), connectorsSent.end(), [monitor](const auto& e) { return e->monitor == monitor; }) != connectorsSent.end()) + return; + + auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), -1), monitor); + if (!RESOURCE) { + resource->noMemory(); + return; + } + + RESOURCE->parent = self; + RESOURCE->self = RESOURCE; + + LOGM(LOG, "Sending new connector {}", monitor->szName); + + connectorsSent.emplace_back(RESOURCE); + PROTO::lease->m_vConnectors.emplace_back(RESOURCE); + + resource->sendConnector(RESOURCE->resource.get()); + + RESOURCE->sendData(); +} + +CDRMLeaseDevice::CDRMLeaseDevice(SP drmBackend) : backend(drmBackend) { + auto drm = (Aquamarine::CDRMBackend*)drmBackend.get(); + + auto fd = drm->getNonMasterFD(); + + if (fd < 0) { + LOGM(ERR, "Failed to dup fd for drm node {}", drm->gpuName); + return; + } + + close(fd); + success = true; + name = drm->gpuName; +} + +CDRMLeaseProtocol::CDRMLeaseProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + for (auto& b : g_pCompositor->m_pAqBackend->getImplementations()) { + if (b->type() != Aquamarine::AQ_BACKEND_DRM) + continue; + + auto drm = ((Aquamarine::CDRMBackend*)b.get())->self.lock(); + + primaryDevice = makeShared(drm); + + if (primaryDevice->success) + break; + } + + if (!primaryDevice || primaryDevice->success) { + LOGM(ERR, "No DRM backend, not creating lease"); + PROTO::lease.reset(); + return; + } +} + +void CDRMLeaseProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } + + RESOURCE->self = RESOURCE; +} + +void CDRMLeaseProtocol::destroyResource(CDRMLeaseDeviceResource* resource) { + std::erase_if(m_vManagers, [resource](const auto& e) { return e.get() == resource; }); +} + +void CDRMLeaseProtocol::destroyResource(CDRMLeaseConnectorResource* resource) { + std::erase_if(m_vConnectors, [resource](const auto& e) { return e.get() == resource; }); +} + +void CDRMLeaseProtocol::destroyResource(CDRMLeaseRequestResource* resource) { + std::erase_if(m_vRequests, [resource](const auto& e) { return e.get() == resource; }); +} + +void CDRMLeaseProtocol::destroyResource(CDRMLeaseResource* resource) { + std::erase_if(m_vLeases, [resource](const auto& e) { return e.get() == resource; }); +} + +void CDRMLeaseProtocol::offer(SP monitor) { + if (std::find(primaryDevice->offeredOutputs.begin(), primaryDevice->offeredOutputs.end(), monitor) != primaryDevice->offeredOutputs.end()) + return; + + if (monitor->output->getBackend()->type() != Aquamarine::AQ_BACKEND_DRM) + return; + + if (monitor->output->getBackend() != primaryDevice->backend) { + LOGM(ERR, "Monitor {} cannot be leased: primaryDevice lease is for a different device", monitor->szName); + return; + } + + primaryDevice->offeredOutputs.emplace_back(monitor); + + for (auto& m : m_vManagers) { + m->sendConnector(monitor); + m->resource->sendDone(); + } +} diff --git a/src/protocols/DRMLease.hpp b/src/protocols/DRMLease.hpp new file mode 100644 index 00000000000..56eaa3db296 --- /dev/null +++ b/src/protocols/DRMLease.hpp @@ -0,0 +1,137 @@ +#pragma once + +#include +#include +#include +#include "WaylandProtocol.hpp" +#include "drm-lease-v1.hpp" +#include "../helpers/signal/Signal.hpp" + +/* + TODO: this protocol is not made for systems with multiple DRM nodes (e.g. multigpu) +*/ + +AQUAMARINE_FORWARD(CDRMBackend); +AQUAMARINE_FORWARD(CDRMLease); +class CDRMLeaseDeviceResource; +class CMonitor; +class CDRMLeaseProtocol; +class CDRMLeaseConnectorResource; +class CDRMLeaseRequestResource; + +class CDRMLeaseResource { + public: + CDRMLeaseResource(SP resource_, SP request); + + bool good(); + + WP parent; + std::vector> requested; + WP lease; + + int leaseFD = -1; + + struct { + CHyprSignalListener destroyLease; + } listeners; + + private: + SP resource; +}; + +class CDRMLeaseRequestResource { + public: + CDRMLeaseRequestResource(SP resource_); + + bool good(); + + WP parent; + WP self; + std::vector> requested; + + private: + SP resource; +}; + +class CDRMLeaseConnectorResource { + public: + CDRMLeaseConnectorResource(SP resource_, SP monitor_); + static SP fromResource(wl_resource*); + + bool good(); + void sendData(); + + WP self; + WP parent; + WP monitor; + bool dead = false; + + private: + SP resource; + + struct { + CHyprSignalListener destroyMonitor; + } listeners; + + friend class CDRMLeaseDeviceResource; +}; + +class CDRMLeaseDeviceResource { + public: + CDRMLeaseDeviceResource(SP resource_); + + bool good(); + void sendConnector(SP monitor); + + std::vector> connectorsSent; + + WP self; + + private: + SP resource; + + friend class CDRMLeaseProtocol; +}; + +class CDRMLeaseDevice { + public: + CDRMLeaseDevice(SP drmBackend); + + std::string name = ""; + bool success = false; + SP backend; + + std::vector> offeredOutputs; +}; + +class CDRMLeaseProtocol : public IWaylandProtocol { + public: + CDRMLeaseProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + void offer(SP monitor); + + private: + void destroyResource(CDRMLeaseDeviceResource* resource); + void destroyResource(CDRMLeaseConnectorResource* resource); + void destroyResource(CDRMLeaseRequestResource* resource); + void destroyResource(CDRMLeaseResource* resource); + + // + std::vector> m_vManagers; + std::vector> m_vConnectors; + std::vector> m_vRequests; + std::vector> m_vLeases; + + SP primaryDevice; + + friend class CDRMLeaseDeviceResource; + friend class CDRMLeaseConnectorResource; + friend class CDRMLeaseRequestResource; + friend class CDRMLeaseResource; +}; + +namespace PROTO { + inline UP lease; +}; From aeb500df17e1b59230718a4a518f47bab3ca2973 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 5 Jul 2024 20:32:36 +0200 Subject: [PATCH 042/113] drop wlroots --- CMakeLists.txt | 33 +--------- src/Compositor.cpp | 1 + src/debug/Log.cpp | 24 ------- src/debug/Log.hpp | 2 - src/devices/IKeyboard.cpp | 5 +- src/devices/IKeyboard.hpp | 11 ++++ src/helpers/MiscFunctions.cpp | 3 + src/helpers/Monitor.cpp | 9 +-- src/helpers/math/Math.cpp | 25 ++++--- src/helpers/math/Math.hpp | 13 +++- src/includes.hpp | 72 -------------------- src/managers/CursorManager.cpp | 91 ++++++++++--------------- src/managers/CursorManager.hpp | 18 ++++- src/managers/KeybindManager.cpp | 40 +++++------ src/managers/KeybindManager.hpp | 1 + src/managers/PointerManager.cpp | 5 +- src/managers/ProtocolManager.cpp | 9 ++- src/protocols/DRMLease.cpp | 1 - src/protocols/InputMethodV2.cpp | 1 + src/protocols/LinuxDMABUF.cpp | 1 + src/protocols/PresentationTime.cpp | 5 +- src/protocols/Screencopy.cpp | 2 +- src/protocols/Tablet.cpp | 1 + src/protocols/XDGShell.cpp | 1 + src/protocols/core/Compositor.cpp | 2 +- src/render/OpenGL.cpp | 102 ++++++++++++++--------------- src/render/OpenGL.hpp | 2 + src/render/Renderbuffer.hpp | 2 +- src/render/Renderer.cpp | 13 ++-- src/render/Texture.cpp | 17 ----- src/render/Texture.hpp | 1 - src/signal-safe.hpp | 1 + src/xwayland/Server.cpp | 10 +-- src/xwayland/XWM.cpp | 6 +- subprojects/wlroots-hyprland | 1 - 35 files changed, 211 insertions(+), 320 deletions(-) delete mode 160000 subprojects/wlroots-hyprland diff --git a/CMakeLists.txt b/CMakeLists.txt index 89dbe9081b8..545c685930f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,9 +31,6 @@ execute_process( # udis add_subdirectory("subprojects/udis86") -# wlroots -message(STATUS "Setting up wlroots") - if(CMAKE_BUILD_TYPE) string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER) if(BUILDTYPE_LOWER STREQUAL "release") @@ -53,18 +50,6 @@ else() set(BUILDTYPE_LOWER "release") endif() -ExternalProject_Add( - wlroots-hyprland - PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland - SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland - CONFIGURE_COMMAND meson setup --reconfigure --clearcache build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dxwayland=$,disabled,enabled> -Dexamples=false -Drenderers=gles2 -Dbackends=drm,libinput $,-Db_sanitize=address,-Db_sanitize=none> - BUILD_COMMAND ninja -C build - BUILD_ALWAYS true - BUILD_IN_SOURCE true - BUILD_BYPRODUCTS ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland/build/libwlroots.a - INSTALL_COMMAND echo "wlroots-hyprland: install not needed" -) - find_package(PkgConfig REQUIRED) pkg_get_variable(WaylandScanner wayland-scanner wayland_scanner) @@ -84,8 +69,6 @@ endif() include_directories( . "src/" - "subprojects/wlroots-hyprland/include/" - "subprojects/wlroots-hyprland/build/include/" "subprojects/udis86/" "protocols/") set(CMAKE_CXX_STANDARD 23) @@ -112,7 +95,7 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET aquamarine xkbcommon uuid wayland-server wayland-client wayland-cursor wayland-protocols - cairo pango pangocairo pixman-1 + cairo pango pangocairo pixman-1 xcursor libdrm libinput hwdata libseat libdisplay-info libliftoff libudev gbm hyprlang>=0.3.2 hyprcursor>=0.1.7 hyprutils>=0.2.0 ) @@ -128,7 +111,6 @@ if(USE_TRACY) endif() add_executable(Hyprland ${SRCFILES} ${TRACY_CPP_FILES}) -add_dependencies(Hyprland wlroots-hyprland) set(USE_GPROF ON) @@ -267,7 +249,6 @@ function(protocolWayland) endfunction() target_link_libraries(Hyprland - ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland/build/libwlroots.a OpenGL::EGL OpenGL::GL Threads::Threads @@ -360,18 +341,6 @@ install(FILES ${MANPAGES} install(FILES ${CMAKE_BINARY_DIR}/hyprland.pc DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig) -# wlroots headers -set(HEADERS_WLR "${CMAKE_CURRENT_SOURCE_DIR}/subprojects/wlroots-hyprland/include/wlr") -install(DIRECTORY ${HEADERS_WLR} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland - FILES_MATCHING PATTERN "*.h") - -# config.h and version.h -set(HEADERS_WLR_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/subprojects/wlroots-hyprland/build/include/wlr") -install(DIRECTORY ${HEADERS_WLR_ROOT}/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland/wlr - FILES_MATCHING PATTERN "*.h") - # protocol headers set(HEADERS_PROTO "${CMAKE_CURRENT_SOURCE_DIR}/protocols") install(DIRECTORY ${HEADERS_PROTO} diff --git a/src/Compositor.cpp b/src/Compositor.cpp index a7d0c8cbb3b..8505e51dbfa 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -7,6 +7,7 @@ #include "managers/SeatManager.hpp" #include "managers/eventLoop/EventLoopManager.hpp" #include +#include #include #include "debug/HyprCtl.hpp" #include "debug/CrashReporter.hpp" diff --git a/src/debug/Log.cpp b/src/debug/Log.cpp index 7547204a7cc..c2939831cc7 100644 --- a/src/debug/Log.cpp +++ b/src/debug/Log.cpp @@ -10,30 +10,6 @@ void Debug::init(const std::string& IS) { logFile = IS + (ISDEBUG ? "/hyprlandd.log" : "/hyprland.log"); } -void Debug::wlrLog(wlr_log_importance level, const char* fmt, va_list args) { - if (level > wlr_log_get_verbosity()) - return; - - char* outputStr = nullptr; - - vasprintf(&outputStr, fmt, args); - - std::string output = std::string(outputStr); - free(outputStr); - - rollingLog += output + "\n"; - - if (!disableLogs || !**disableLogs) { - std::ofstream ofs; - ofs.open(logFile, std::ios::out | std::ios::app); - ofs << "[wlr] " << output << "\n"; - ofs.close(); - } - - if (!disableStdout) - std::cout << output << "\n"; -} - void Debug::log(LogLevel level, std::string str) { if (level == TRACE && !trace) return; diff --git a/src/debug/Log.hpp b/src/debug/Log.hpp index e8cd80cff5b..33f3c9c1186 100644 --- a/src/debug/Log.hpp +++ b/src/debug/Log.hpp @@ -67,6 +67,4 @@ namespace Debug { log(level, logMsg); } - - void wlrLog(wlr_log_importance level, const char* fmt, va_list args); }; diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index e07385c5c93..5325ab0a34c 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -5,6 +5,9 @@ #include "../managers/SeatManager.hpp" #include #include +#include + +#define LED_COUNT 3 constexpr static std::array MODNAMES = { XKB_MOD_NAME_SHIFT, XKB_MOD_NAME_CAPS, XKB_MOD_NAME_CTRL, XKB_MOD_NAME_ALT, XKB_MOD_NAME_NUM, "Mod3", XKB_MOD_NAME_LOGO, "Mod5", @@ -256,7 +259,7 @@ void IKeyboard::updateLEDs() { return; uint32_t leds = 0; - for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { + for (uint32_t i = 0; i < LED_COUNT; ++i) { if (xkb_state_led_index_is_active(xkbState, ledIndexes.at(i))) leds |= (1 << i); } diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index 741a670209d..d288c8bac2b 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -9,6 +9,17 @@ AQUAMARINE_FORWARD(IKeyboard); +enum eKeyboardModifiers { + HL_MODIFIER_SHIFT = (1 << 0), + HL_MODIFIER_CAPS = (1 << 1), + HL_MODIFIER_CTRL = (1 << 2), + HL_MODIFIER_ALT = (1 << 3), + HL_MODIFIER_MOD2 = (1 << 4), + HL_MODIFIER_MOD3 = (1 << 5), + HL_MODIFIER_META = (1 << 6), + HL_MODIFIER_MOD5 = (1 << 7), +}; + class IKeyboard : public IHID { public: virtual ~IKeyboard(); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 712e4e50eaf..53c0dc13b02 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -4,9 +4,12 @@ #include "../Compositor.hpp" #include "../managers/TokenManager.hpp" #include +#include +#include #include #include #include +#include #include #include #include diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index fba38f4e094..accc77834bd 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -1,5 +1,6 @@ #include "Monitor.hpp" #include "MiscFunctions.hpp" +#include "math/Math.hpp" #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" #include "../protocols/GammaControl.hpp" @@ -730,11 +731,11 @@ Vector2D CMonitor::middle() { } void CMonitor::updateMatrix() { - wlr_matrix_identity(projMatrix.data()); + matrixIdentity(projMatrix.data()); if (transform != WL_OUTPUT_TRANSFORM_NORMAL) { - wlr_matrix_translate(projMatrix.data(), vecPixelSize.x / 2.0, vecPixelSize.y / 2.0); - wlr_matrix_transform(projMatrix.data(), transform); - wlr_matrix_translate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0); + matrixTranslate(projMatrix.data(), vecPixelSize.x / 2.0, vecPixelSize.y / 2.0); + matrixTransform(projMatrix.data(), wlTransformToHyprutils(transform)); + matrixTranslate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0); } } diff --git a/src/helpers/math/Math.cpp b/src/helpers/math/Math.cpp index 560f29c9d6b..f8b61bcec36 100644 --- a/src/helpers/math/Math.cpp +++ b/src/helpers/math/Math.cpp @@ -17,14 +17,14 @@ Hyprutils::Math::eTransform wlTransformToHyprutils(wl_output_transform t) { return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_NORMAL; } -static void matrixIdentity(float mat[9]) { +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)); } -static void matrixMultiply(float mat[9], const float a[9], const float b[9]) { +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]; @@ -42,35 +42,35 @@ static void matrixMultiply(float mat[9], const float a[9], const float b[9]) { memcpy(mat, product, sizeof(product)); } -static void matrixTranspose(float mat[9], const float a[9]) { +void matrixTranspose(float mat[9], const float a[9]) { float transposition[9] = { a[0], a[3], a[6], a[1], a[4], a[7], a[2], a[5], a[8], }; memcpy(mat, transposition, sizeof(transposition)); } -static void matrixTranslate(float mat[9], float x, float y) { +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, }; matrixMultiply(mat, mat, translate); } -static void matrixScale(float mat[9], float x, float y) { +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); } -static void matrixRotate(float mat[9], float rad) { +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, }; matrixMultiply(mat, mat, rotate); } -static std::unordered_map> transforms = { +std::unordered_map> transforms = { {HYPRUTILS_TRANSFORM_NORMAL, { 1.0f, @@ -169,11 +169,11 @@ static std::unordered_map> transforms = { }}, }; -static void matrixTransform(float mat[9], eTransform transform) { +void matrixTransform(float mat[9], eTransform transform) { matrixMultiply(mat, mat, transforms.at(transform).data()); } -static void matrixProjection(float mat[9], int width, int height, eTransform transform) { +void matrixProjection(float mat[9], int width, int height, eTransform transform) { memset(mat, 0, sizeof(*mat) * 9); const float* t = transforms.at(transform).data(); @@ -219,3 +219,10 @@ void projectBox(float mat[9], CBox& box, eTransform transform, float rotation, c matrixMultiply(mat, projection, mat); } + +wl_output_transform invertTransform(wl_output_transform tr) { + if ((tr & WL_OUTPUT_TRANSFORM_90) && !(tr & WL_OUTPUT_TRANSFORM_FLIPPED)) + tr = (wl_output_transform)(tr ^ (int)WL_OUTPUT_TRANSFORM_180); + + return tr; +} diff --git a/src/helpers/math/Math.hpp b/src/helpers/math/Math.hpp index 4aa65c939a8..f57cef9316a 100644 --- a/src/helpers/math/Math.hpp +++ b/src/helpers/math/Math.hpp @@ -7,5 +7,14 @@ using namespace Hyprutils::Math; -eTransform wlTransformToHyprutils(wl_output_transform t); -void projectBox(float mat[9], CBox& box, eTransform transform, float rotation, const float projection[9]); +eTransform wlTransformToHyprutils(wl_output_transform t); +void projectBox(float mat[9], CBox& box, eTransform transform, float rotation, const float projection[9]); +void matrixProjection(float mat[9], int width, int height, eTransform transform); +void matrixTransform(float mat[9], eTransform transform); +void matrixRotate(float mat[9], float rad); +void matrixScale(float mat[9], float x, float y); +void matrixTranslate(float mat[9], float x, float y); +void matrixTranspose(float mat[9], const float a[9]); +void matrixMultiply(float mat[9], const float a[9], const float b[9]); +void matrixIdentity(float mat[9]); +wl_output_transform invertTransform(wl_output_transform tr); diff --git a/src/includes.hpp b/src/includes.hpp index afec078ae01..3a1bc4e302b 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -16,78 +16,6 @@ #include #include #include -#include -#include -#include -#include - -#if true -// wlroots uses dumb-ass shit that makes it not compile on C++, let's fix that. -// https://github.com/swaywm/wlroots/issues/682 -// pthread first because it uses class in a C++ way and XWayland includes that... -#include - -#define class _class -#define namespace _namespace -#define static -#define delete delete_ - -extern "C" { -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#if WLR_HAS_X11_BACKEND -#include -#endif -} - -#undef delete -#undef class -#undef namespace -#undef static -#endif #ifdef LEGACY_RENDERER #include diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 5a14ec3ac8f..3dd4394036c 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -3,10 +3,10 @@ #include "../config/ConfigValue.hpp" #include "PointerManager.hpp" #include "../xwayland/XWayland.hpp" +#include extern "C" { -#include -#include +#include } static int cursorAnimTimer(void* data) { @@ -45,8 +45,7 @@ CCursorManager::CCursorManager() { if (m_iSize == 0) m_iSize = 24; - m_pWLRXCursorMgr = wlr_xcursor_manager_create(getenv("XCURSOR_THEME"), m_iSize); - wlr_xcursor_manager_load(m_pWLRXCursorMgr, 1.0); + xcursor.loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "", m_iSize * std::ceil(m_fCursorScale)); m_pAnimationTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, ::cursorAnimTimer, nullptr); @@ -56,9 +55,6 @@ CCursorManager::CCursorManager() { } CCursorManager::~CCursorManager() { - if (m_pWLRXCursorMgr) - wlr_xcursor_manager_destroy(m_pWLRXCursorMgr); - if (m_pAnimationTimer) wl_event_source_remove(m_pAnimationTimer); } @@ -134,32 +130,19 @@ void CCursorManager::setCursorSurface(SP surf, const Vector2D& hotsp } void CCursorManager::setXCursor(const std::string& name) { - if (!m_pWLRXCursorMgr) { - g_pPointerManager->resetCursorImage(); - return; - } - float scale = std::ceil(m_fCursorScale); - wlr_xcursor_manager_load(m_pWLRXCursorMgr, scale); - - auto xcursor = wlr_xcursor_manager_get_xcursor(m_pWLRXCursorMgr, name.c_str(), scale); - if (!xcursor) { - Debug::log(ERR, "XCursor has no shape {}, retrying with left-ptr", name); - xcursor = wlr_xcursor_manager_get_xcursor(m_pWLRXCursorMgr, "left-ptr", scale); - } + xcursor.loadTheme(name.c_str(), m_iSize * scale); - if (!xcursor || !xcursor->images[0]) { - Debug::log(ERR, "XCursor is broken. F this garbage."); + if (!xcursor.themeLoaded) { + Debug::log(ERR, "XCursor failed to find theme in setXCursor"); g_pPointerManager->resetCursorImage(); return; } - auto image = xcursor->images[0]; - m_vCursorBuffers.emplace_back( - makeShared(image->buffer, Vector2D{(int)image->width, (int)image->height}, Vector2D{(double)image->hotspot_x, (double)image->hotspot_y})); + makeShared(xcursor.defaultCursor->pixels.data(), xcursor.defaultCursor->size, xcursor.defaultCursor->hotspot)); - g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{(double)image->hotspot_x, (double)image->hotspot_y} / scale, scale); + g_pPointerManager->setCursorBuffer(getCursorBuffer(), xcursor.defaultCursor->hotspot / scale, scale); if (m_vCursorBuffers.size() > 1) dropBufferRef(m_vCursorBuffers.at(0).get()); @@ -263,10 +246,9 @@ void CCursorManager::setXWaylandCursor() { if (CURSOR.surface) { g_pXWayland->setCursor(cairo_image_surface_get_data(CURSOR.surface), cairo_image_surface_get_stride(CURSOR.surface), {CURSOR.size, CURSOR.size}, {CURSOR.hotspotX, CURSOR.hotspotY}); - } else if (const auto XCURSOR = wlr_xcursor_manager_get_xcursor(m_pWLRXCursorMgr, "left_ptr", 1); XCURSOR) { - g_pXWayland->setCursor(XCURSOR->images[0]->buffer, XCURSOR->images[0]->width * 4, {(int)XCURSOR->images[0]->width, (int)XCURSOR->images[0]->height}, - {(double)XCURSOR->images[0]->hotspot_x, (double)XCURSOR->images[0]->hotspot_y}); - } else + } else if (xcursor.themeLoaded) + g_pXWayland->setCursor(xcursor.defaultCursor->pixels.data(), xcursor.defaultCursor->size.x * 4, xcursor.defaultCursor->size, xcursor.defaultCursor->hotspot); + else Debug::log(ERR, "CursorManager: no valid cursor for xwayland"); } @@ -310,37 +292,36 @@ bool CCursorManager::changeTheme(const std::string& name, const int size) { Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to X.", name); - if (m_pWLRXCursorMgr) - wlr_xcursor_manager_destroy(m_pWLRXCursorMgr); + xcursor.loadTheme(name, size); - m_pWLRXCursorMgr = wlr_xcursor_manager_create(name.empty() ? "" : name.c_str(), size); - bool xSuccess = wlr_xcursor_manager_load(m_pWLRXCursorMgr, 1.0) == 1; + m_szTheme = name; + m_iSize = size; + updateTheme(); + return true; +} - // this basically checks if xcursor changed used theme to default but better - bool diffTheme = false; - wlr_xcursor_manager_theme* theme; - wl_list_for_each(theme, &m_pWLRXCursorMgr->scaled_themes, link) { - if (std::string{theme->theme->name} != name) { - diffTheme = true; - break; - } - } +void CCursorManager::SXCursorManager::loadTheme(const std::string& name, int size) { + themeLoaded = false; + themeName = name.empty() ? "default" : name; - if (xSuccess && !diffTheme) { - m_szTheme = name; - m_iSize = size; - updateTheme(); - return true; - } + auto img = XcursorShapeLoadImage(1, name.c_str(), size); - Debug::log(ERR, "X also failed loading theme \"{}\", falling back to previous theme.", name); + if (!img) { + Debug::log(ERR, "XCursor failed finding theme \"{}\". Trying size 24.", name); + size = 24; + img = XcursorShapeLoadImage(1, name.c_str(), size); + if (!img) { + Debug::log(ERR, "XCursor failed finding theme \"{}\".", name); + return; + } + } - m_pHyprcursor = std::make_unique(m_szTheme.c_str(), hcLogger); + defaultCursor = makeShared(); + defaultCursor->size = {(int)img->width, (int)img->height}; + defaultCursor->hotspot = {(int)img->xhot, (int)img->yhot}; - wlr_xcursor_manager_destroy(m_pWLRXCursorMgr); - m_pWLRXCursorMgr = wlr_xcursor_manager_create(m_szTheme.c_str(), m_iSize); - wlr_xcursor_manager_load(m_pWLRXCursorMgr, 1.0); + defaultCursor->pixels.resize(img->width * img->height); + std::memcpy(defaultCursor->pixels.data(), img->pixels, img->width * img->height); - updateTheme(); - return false; + themeLoaded = true; } diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index 6a042743c5b..67e8d970650 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -7,7 +7,6 @@ #include "../helpers/math/Math.hpp" #include "../helpers/memory/Memory.hpp" -struct wlr_xcursor_manager; class CWLSurface; AQUAMARINE_FORWARD(IBuffer); @@ -73,8 +72,21 @@ class CCursorManager { int m_iCurrentAnimationFrame = 0; Hyprcursor::SCursorShapeData m_sCurrentCursorShapeData; - // xcursor fallback - wlr_xcursor_manager* m_pWLRXCursorMgr = nullptr; + // gangsta bootleg XCursor impl. Whenever Hyprland has to use + // an xcursor, just use the pointer. + struct SXCursor { + Vector2D size; + Vector2D hotspot; + std::vector pixels; + }; + + struct SXCursorManager { + void loadTheme(const std::string& name, int size); + + bool themeLoaded = false; + std::string themeName = ""; + SP defaultCursor; + } xcursor; }; inline std::unique_ptr g_pCursorManager; \ No newline at end of file diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 6ee5d4432d6..19c7bca6ed4 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -4,6 +4,7 @@ #include "../protocols/LayerShell.hpp" #include "../protocols/ShortcutsInhibit.hpp" #include "../render/decorations/CHyprGroupBarDecoration.hpp" +#include "../devices/IKeyboard.hpp" #include "KeybindManager.hpp" #include "PointerManager.hpp" #include "Compositor.hpp" @@ -15,6 +16,7 @@ #include #include #include +#include #include using namespace Hyprutils::String; @@ -157,37 +159,37 @@ uint32_t CKeybindManager::stringToModMask(std::string mods) { uint32_t modMask = 0; std::transform(mods.begin(), mods.end(), mods.begin(), ::toupper); if (mods.contains("SHIFT")) - modMask |= WLR_MODIFIER_SHIFT; + modMask |= HL_MODIFIER_SHIFT; if (mods.contains("CAPS")) - modMask |= WLR_MODIFIER_CAPS; + modMask |= HL_MODIFIER_CAPS; if (mods.contains("CTRL") || mods.contains("CONTROL")) - modMask |= WLR_MODIFIER_CTRL; + modMask |= HL_MODIFIER_CTRL; if (mods.contains("ALT") || mods.contains("MOD1")) - modMask |= WLR_MODIFIER_ALT; + modMask |= HL_MODIFIER_ALT; if (mods.contains("MOD2")) - modMask |= WLR_MODIFIER_MOD2; + modMask |= HL_MODIFIER_MOD2; if (mods.contains("MOD3")) - modMask |= WLR_MODIFIER_MOD3; - if (mods.contains("SUPER") || mods.contains("WIN") || mods.contains("LOGO") || mods.contains("MOD4")) - modMask |= WLR_MODIFIER_LOGO; + modMask |= HL_MODIFIER_MOD3; + if (mods.contains("SUPER") || mods.contains("WIN") || mods.contains("LOGO") || mods.contains("MOD4") || mods.contains("META")) + modMask |= HL_MODIFIER_META; if (mods.contains("MOD5")) - modMask |= WLR_MODIFIER_MOD5; + modMask |= HL_MODIFIER_MOD5; return modMask; } uint32_t CKeybindManager::keycodeToModifier(xkb_keycode_t keycode) { switch (keycode - 8) { - case KEY_LEFTMETA: return WLR_MODIFIER_LOGO; - case KEY_RIGHTMETA: return WLR_MODIFIER_LOGO; - case KEY_LEFTSHIFT: return WLR_MODIFIER_SHIFT; - case KEY_RIGHTSHIFT: return WLR_MODIFIER_SHIFT; - case KEY_LEFTCTRL: return WLR_MODIFIER_CTRL; - case KEY_RIGHTCTRL: return WLR_MODIFIER_CTRL; - case KEY_LEFTALT: return WLR_MODIFIER_ALT; - case KEY_RIGHTALT: return WLR_MODIFIER_ALT; - case KEY_CAPSLOCK: return WLR_MODIFIER_CAPS; - case KEY_NUMLOCK: return WLR_MODIFIER_MOD2; + case KEY_LEFTMETA: return HL_MODIFIER_META; + case KEY_RIGHTMETA: return HL_MODIFIER_META; + case KEY_LEFTSHIFT: return HL_MODIFIER_SHIFT; + case KEY_RIGHTSHIFT: return HL_MODIFIER_SHIFT; + case KEY_LEFTCTRL: return HL_MODIFIER_CTRL; + case KEY_RIGHTCTRL: return HL_MODIFIER_CTRL; + case KEY_LEFTALT: return HL_MODIFIER_ALT; + case KEY_RIGHTALT: return HL_MODIFIER_ALT; + case KEY_CAPSLOCK: return HL_MODIFIER_CAPS; + case KEY_NUMLOCK: return HL_MODIFIER_MOD2; default: return 0; } } diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 2a2567609e3..284280cd033 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -6,6 +6,7 @@ #include "../Compositor.hpp" #include #include +#include #include "../devices/IPointer.hpp" class CInputManager; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 8225570320c..11259632faf 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -6,9 +6,6 @@ #include "../protocols/core/Compositor.hpp" #include "eventLoop/EventLoopManager.hpp" #include "SeatManager.hpp" -#include -#include -#include CPointerManager::CPointerManager() { hooks.monitorAdded = g_pHookSystem->hookDynamic("newMonitor", [this](void* self, SCallbackInfo& info, std::any data) { @@ -465,7 +462,7 @@ Vector2D CPointerManager::transformedHotspot(SP pMonitor) { 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->cursorSwapchain->currentOptions().size.x, + .transform(wlTransformToHyprutils(invertTransform(pMonitor->transform)), pMonitor->cursorSwapchain->currentOptions().size.x, pMonitor->cursorSwapchain->currentOptions().size.y) .pos(); } diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 90f5294766f..47cf1767ebb 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -131,7 +131,14 @@ CProtocolManager::CProtocolManager() { PROTO::dataWlr = std::make_unique(&zwlr_data_control_manager_v1_interface, 2, "DataDeviceWlr"); PROTO::primarySelection = std::make_unique(&zwp_primary_selection_device_manager_v1_interface, 1, "PrimarySelection"); PROTO::xwaylandShell = std::make_unique(&xwayland_shell_v1_interface, 1, "XWaylandShell"); - PROTO::lease = std::make_unique(&wp_drm_lease_device_v1_interface, 1, "DRMLease"); + + for (auto& b : g_pCompositor->m_pAqBackend->getImplementations()) { + if (b->type() != Aquamarine::AQ_BACKEND_DRM) + continue; + + PROTO::lease = std::make_unique(&wp_drm_lease_device_v1_interface, 1, "DRMLease"); + break; + } if (g_pHyprOpenGL->getDRMFormats().size() > 0) { PROTO::mesaDRM = std::make_unique(&wl_drm_interface, 2, "MesaDRM"); diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp index 36ac09983ef..9f5b6312ece 100644 --- a/src/protocols/DRMLease.cpp +++ b/src/protocols/DRMLease.cpp @@ -248,7 +248,6 @@ CDRMLeaseProtocol::CDRMLeaseProtocol(const wl_interface* iface, const int& ver, } if (!primaryDevice || primaryDevice->success) { - LOGM(ERR, "No DRM backend, not creating lease"); PROTO::lease.reset(); return; } diff --git a/src/protocols/InputMethodV2.cpp b/src/protocols/InputMethodV2.cpp index f70cc4fcca5..def4d837986 100644 --- a/src/protocols/InputMethodV2.cpp +++ b/src/protocols/InputMethodV2.cpp @@ -4,6 +4,7 @@ #include "../devices/IKeyboard.hpp" #include #include "core/Compositor.hpp" +#include #define LOGM PROTO::ime->protoLog diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 08faf643b52..1c82687479a 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "core/Compositor.hpp" #include "types/DMABuffer.hpp" #include "types/WLBuffer.hpp" diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index 1c92513c81e..e9472fc32c6 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -4,6 +4,7 @@ #include "../managers/HookSystemManager.hpp" #include "core/Compositor.hpp" #include "core/Output.hpp" +#include #define LOGM PROTO::presentation->protoLog @@ -54,9 +55,9 @@ void CPresentationFeedback::sendQueued(SP data, timespe flags |= WP_PRESENTATION_FEEDBACK_KIND_VSYNC; if (data->zeroCopy) flags |= WP_PRESENTATION_FEEDBACK_KIND_ZERO_COPY; - if (reportedFlags & WLR_OUTPUT_PRESENT_HW_CLOCK) + if (reportedFlags & Aquamarine::IOutput::AQ_OUTPUT_PRESENT_HW_CLOCK) flags |= WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK; - if (reportedFlags & WLR_OUTPUT_PRESENT_HW_COMPLETION) + if (reportedFlags & Aquamarine::IOutput::AQ_OUTPUT_PRESENT_HW_COMPLETION) flags |= WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION; if (data->wasPresented && when) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index fd7bd65c51b..61ac84b1499 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -542,7 +542,7 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) { CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y} .translate({-frame->box.x, -frame->box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. - .transform(wlTransformToHyprutils(wlr_output_transform_invert(frame->pMonitor->transform)), frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y); + .transform(wlTransformToHyprutils(invertTransform(frame->pMonitor->transform)), frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y); g_pHyprOpenGL->setMonitorTransformEnabled(true); g_pHyprOpenGL->setRenderModifEnabled(false); g_pHyprOpenGL->renderTexture(TEXTURE, &monbox, 1); diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp index ca976eaffa6..72c7cfdedaf 100644 --- a/src/protocols/Tablet.cpp +++ b/src/protocols/Tablet.cpp @@ -5,6 +5,7 @@ #include "core/Seat.hpp" #include "core/Compositor.hpp" #include +#include #define LOGM PROTO::tablet->protoLog diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 9c56df93775..8276ed55478 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -4,6 +4,7 @@ #include "../managers/SeatManager.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" +#include #define LOGM PROTO::xdgShell->protoLog diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 691267b0700..5f016918ac1 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -426,7 +426,7 @@ CRegion CWLSurfaceResource::accumulateCurrentBufferDamage() { Vector2D trc = current.transform % 2 == 1 ? Vector2D{current.buffer->size.y, current.buffer->size.x} : current.buffer->size; - return surfaceDamage.scale(current.scale).transform(wlTransformToHyprutils(wlr_output_transform_invert(current.transform)), trc.x, trc.y).add(current.bufferDamage); + return surfaceDamage.scale(current.scale).transform(wlTransformToHyprutils(invertTransform(current.transform)), trc.x, trc.y).add(current.bufferDamage); } CWLCompositorResource::CWLCompositorResource(SP resource_) : resource(resource_) { diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index f833f875083..0d740ed9fc3 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -58,23 +58,20 @@ static void eglLog(EGLenum error, const char* command, EGLint type, EGLLabelKHR } static int openRenderNode(int drmFd) { - char* renderName = drmGetRenderDeviceNameFromFd(drmFd); - if (renderName == NULL) { + auto renderName = drmGetRenderDeviceNameFromFd(drmFd); + if (!renderName) { // This can happen on split render/display platforms, fallback to // primary node renderName = drmGetPrimaryDeviceNameFromFd(drmFd); - if (renderName == NULL) { - wlr_log_errno(WLR_ERROR, "drmGetPrimaryDeviceNameFromFd failed"); + if (!renderName) { + Debug::log(ERR, "drmGetPrimaryDeviceNameFromFd failed"); return -1; } - wlr_log(WLR_DEBUG, - "DRM device '%s' has no render node, " - "falling back to primary node", - renderName); + Debug::log(LOG, "DRM dev {} has no render node, falling back to primary", renderName); drmVersion* render_version = drmGetVersion(drmFd); - if (render_version != NULL && render_version->name != NULL) { - wlr_log(WLR_DEBUG, "DRM device version.name '%s'", render_version->name); + if (render_version && render_version->name) { + Debug::log(LOG, "DRM dev versionName", render_version->name); if (strcmp(render_version->name, "evdi") == 0) { free(renderName); renderName = (char*)malloc(sizeof(char) * 15); @@ -84,14 +81,14 @@ static int openRenderNode(int drmFd) { } } - wlr_log(WLR_DEBUG, "open_render_node() DRM device '%s'", renderName); + Debug::log(LOG, "openRenderNode got drm device {}", renderName); + + int renderFD = open(renderName, O_RDWR | O_CLOEXEC); + if (renderFD < 0) + Debug::log(ERR, "openRenderNode failed to open drm device {}", renderName); - int render_fd = open(renderName, O_RDWR | O_CLOEXEC); - if (render_fd < 0) { - wlr_log_errno(WLR_ERROR, "Failed to open DRM node '%s'", renderName); - } free(renderName); - return render_fd; + return renderFD; } void CHyprOpenGLImpl::initEGL(bool gbm) { @@ -323,7 +320,7 @@ void CHyprOpenGLImpl::initDRMFormats() { return; } - wlr_log(WLR_DEBUG, "Supported DMA-BUF formats:"); + Debug::log(LOG, "Supported DMA-BUF formats:"); std::vector dmaFormats; @@ -646,12 +643,12 @@ void CHyprOpenGLImpl::beginSimple(CMonitor* pMonitor, const CRegion& damage, CRe matrixProjection(m_RenderData.projection, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, WL_OUTPUT_TRANSFORM_NORMAL); - wlr_matrix_identity(m_RenderData.monitorProjection.data()); + matrixIdentity(m_RenderData.monitorProjection.data()); if (pMonitor->transform != WL_OUTPUT_TRANSFORM_NORMAL) { const Vector2D tfmd = pMonitor->transform % 2 == 1 ? Vector2D{FBO->m_vSize.y, FBO->m_vSize.x} : FBO->m_vSize; - wlr_matrix_translate(m_RenderData.monitorProjection.data(), FBO->m_vSize.x / 2.0, FBO->m_vSize.y / 2.0); - wlr_matrix_transform(m_RenderData.monitorProjection.data(), pMonitor->transform); - wlr_matrix_translate(m_RenderData.monitorProjection.data(), -tfmd.x / 2.0, -tfmd.y / 2.0); + matrixTranslate(m_RenderData.monitorProjection.data(), FBO->m_vSize.x / 2.0, FBO->m_vSize.y / 2.0); + matrixTransform(m_RenderData.monitorProjection.data(), wlTransformToHyprutils(pMonitor->transform)); + matrixTranslate(m_RenderData.monitorProjection.data(), -tfmd.x / 2.0, -tfmd.y / 2.0); } m_RenderData.pCurrentMonData = &m_mMonitorRenderResources[pMonitor]; @@ -1089,7 +1086,7 @@ void CHyprOpenGLImpl::scissor(const CBox* pBox, bool transform) { CBox newBox = *pBox; if (transform) { - const auto TR = wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)); + const auto TR = wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)); newBox.transform(TR, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); } @@ -1179,11 +1176,11 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion box = &newBox; float matrix[9]; - projectBox(matrix, newBox, wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, + projectBox(matrix, newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here float glMatrix[9]; - wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); + matrixMultiply(glMatrix, m_RenderData.projection, matrix); glUseProgram(m_RenderData.pCurrentMonData->m_shQUAD.program); @@ -1198,7 +1195,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion glUniform4f(m_RenderData.pCurrentMonData->m_shQUAD.color, col.r * col.a, col.g * col.a, col.b * col.a, col.a); CBox transformedBox = *box; - transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, + transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); @@ -1270,12 +1267,12 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB static auto PDT = CConfigValue("debug:damage_tracking"); // get transform - const auto TRANSFORM = wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); + const auto TRANSFORM = wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); float matrix[9]; projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); float glMatrix[9]; - wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); + matrixMultiply(glMatrix, m_RenderData.projection, matrix); CShader* shader = nullptr; @@ -1358,7 +1355,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB } CBox transformedBox = newBox; - transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, + transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); @@ -1433,12 +1430,12 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, CBox* pBox) { m_RenderData.renderModif.applyToBox(newBox); // get transform - const auto TRANSFORM = wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); + const auto TRANSFORM = wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); float matrix[9]; projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); float glMatrix[9]; - wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); + matrixMultiply(glMatrix, m_RenderData.projection, matrix); CShader* shader = &m_RenderData.pCurrentMonData->m_shPASSTHRURGBA; @@ -1487,12 +1484,12 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, CBox* pBox, CFramebuf m_RenderData.renderModif.applyToBox(newBox); // get transform - const auto TRANSFORM = wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); + const auto TRANSFORM = wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); float matrix[9]; projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); float glMatrix[9]; - wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); + matrixMultiply(glMatrix, m_RenderData.projection, matrix); CShader* shader = &m_RenderData.pCurrentMonData->m_shMATTE; @@ -1545,13 +1542,13 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glDisable(GL_STENCIL_TEST); // get transforms for the full monitor - const auto TRANSFORM = wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)); + const auto TRANSFORM = wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)); float matrix[9]; CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; projectBox(matrix, MONITORBOX, TRANSFORM, 0, m_RenderData.monitorProjection.data()); float glMatrix[9]; - wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); + matrixMultiply(glMatrix, m_RenderData.projection, matrix); // get the config settings static auto PBLURSIZE = CConfigValue("decoration:blur:size"); @@ -1561,9 +1558,8 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o // prep damage CRegion damage{*originalDamage}; - wlr_region_transform(damage.pixman(), damage.pixman(), wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, - m_RenderData.pMonitor->vecTransformedSize.y); - wlr_region_expand(damage.pixman(), damage.pixman(), *PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES)); + damage.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); + damage.expand(*PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES)); // helper const auto PMIRRORFB = &m_RenderData.pCurrentMonData->mirrorFB; @@ -1682,13 +1678,13 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o // and draw for (int i = 1; i <= *PBLURPASSES; ++i) { - wlr_region_scale(tempDamage.pixman(), damage.pixman(), 1.f / (1 << i)); + tempDamage.scale(1.f / (1 << i)); drawPass(&m_RenderData.pCurrentMonData->m_shBLUR1, &tempDamage); // down } for (int i = *PBLURPASSES - 1; i >= 0; --i) { - wlr_region_scale(tempDamage.pixman(), damage.pixman(), 1.f / (1 << i)); // when upsampling we make the region twice as big - drawPass(&m_RenderData.pCurrentMonData->m_shBLUR2, &tempDamage); // up + tempDamage.scale(1.f / (1 << i)); // when upsampling we make the region twice as big + drawPass(&m_RenderData.pCurrentMonData->m_shBLUR2, &tempDamage); // up } // finalize the image @@ -1944,7 +1940,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float inverseOpaque = {0, 0, pBox->width, pBox->height}; } - wlr_region_scale(inverseOpaque.pixman(), inverseOpaque.pixman(), m_RenderData.pMonitor->scale); + inverseOpaque.scale(m_RenderData.pMonitor->scale); // vvv TODO: layered blur fbs? const bool USENEWOPTIMIZE = shouldUseNewBlurOptimizations(m_pCurrentLayer, m_pCurrentWindow.lock()) && !blockBlurOptimization; @@ -2043,11 +2039,11 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in round += round == 0 ? 0 : scaledBorderSize; float matrix[9]; - projectBox(matrix, newBox, wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, + projectBox(matrix, newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here float glMatrix[9]; - wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); + matrixMultiply(glMatrix, m_RenderData.projection, matrix); const auto BLEND = m_bBlend; blend(true); @@ -2069,7 +2065,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a); CBox transformedBox = *box; - transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, + transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); @@ -2349,11 +2345,11 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const const auto col = color; float matrix[9]; - projectBox(matrix, newBox, wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, + projectBox(matrix, newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here float glMatrix[9]; - wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); + matrixMultiply(glMatrix, m_RenderData.projection, matrix); glEnable(GL_BLEND); @@ -2441,11 +2437,11 @@ void CHyprOpenGLImpl::renderMirrored() { return; // replace monitor projection to undo the mirrored monitor's projection - wlr_matrix_identity(monitor->projMatrix.data()); - wlr_matrix_translate(monitor->projMatrix.data(), monitor->vecPixelSize.x / 2.0, monitor->vecPixelSize.y / 2.0); - wlr_matrix_transform(monitor->projMatrix.data(), monitor->transform); - wlr_matrix_transform(monitor->projMatrix.data(), wlr_output_transform_invert(mirrored->transform)); - wlr_matrix_translate(monitor->projMatrix.data(), -monitor->vecTransformedSize.x / 2.0, -monitor->vecTransformedSize.y / 2.0); + matrixIdentity(monitor->projMatrix.data()); + matrixTranslate(monitor->projMatrix.data(), monitor->vecPixelSize.x / 2.0, monitor->vecPixelSize.y / 2.0); + matrixTransform(monitor->projMatrix.data(), wlTransformToHyprutils(monitor->transform)); + matrixTransform(monitor->projMatrix.data(), wlTransformToHyprutils(invertTransform(mirrored->transform))); + matrixTranslate(monitor->projMatrix.data(), -monitor->vecTransformedSize.x / 2.0, -monitor->vecTransformedSize.y / 2.0); // clear stuff outside of mirrored area (e.g. when changing to mirrored) clear(CColor(0, 0, 0, 0)); @@ -2674,8 +2670,8 @@ void CHyprOpenGLImpl::saveMatrix() { } void CHyprOpenGLImpl::setMatrixScaleTranslate(const Vector2D& translate, const float& scale) { - wlr_matrix_scale(m_RenderData.projection, scale, scale); - wlr_matrix_translate(m_RenderData.projection, translate.x, translate.y); + matrixScale(m_RenderData.projection, scale, scale); + matrixTranslate(m_RenderData.projection, translate.x, translate.y); } void CHyprOpenGLImpl::restoreMatrix() { diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index ed11e3cb5c2..4b525b163c4 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -18,6 +18,8 @@ #include "Transformer.hpp" #include "Renderbuffer.hpp" +#include +#include #include #include diff --git a/src/render/Renderbuffer.hpp b/src/render/Renderbuffer.hpp index 94814e23c8b..518b34dae7a 100644 --- a/src/render/Renderbuffer.hpp +++ b/src/render/Renderbuffer.hpp @@ -19,7 +19,7 @@ class CRenderbuffer { WP m_pHLBuffer; private: - EGLImageKHR m_iImage = 0; + void* m_iImage = nullptr; GLuint m_iRBO = 0; CFramebuffer m_sFramebuffer; uint32_t m_uDrmFormat = 0; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index a09de65c244..976cc5e2e05 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2,6 +2,7 @@ #include "../Compositor.hpp" #include "../helpers/math/Math.hpp" #include +#include #include "../config/ConfigValue.hpp" #include "../managers/CursorManager.hpp" #include "../managers/PointerManager.hpp" @@ -1319,11 +1320,11 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { *PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think. // now, prep the damage, get the extended damage region - wlr_region_expand(damage.pixman(), damage.pixman(), BLURRADIUS); // expand for proper blurring + damage.expand(BLURRADIUS); // expand for proper blurring finalDamage = damage; - wlr_region_expand(damage.pixman(), damage.pixman(), BLURRADIUS); // expand for proper blurring 2 + damage.expand(BLURRADIUS); // expand for proper blurring } else finalDamage = damage; } @@ -1401,8 +1402,8 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { if (!pMonitor->mirrors.empty()) { CRegion frameDamage{}; - const auto TRANSFORM = wlr_output_transform_invert(pMonitor->transform); - wlr_region_transform(frameDamage.pixman(), finalDamage.pixman(), TRANSFORM, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y); + const auto TRANSFORM = invertTransform(pMonitor->transform); + frameDamage.transform(wlTransformToHyprutils(TRANSFORM), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR) frameDamage.add(0, 0, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y); @@ -1827,7 +1828,7 @@ void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, const CRegion& pRegion monbox.x = (monitor->vecTransformedSize.x - monbox.w) / 2; monbox.y = (monitor->vecTransformedSize.y - monbox.h) / 2; - wlr_region_scale(transformed.pixman(), transformed.pixman(), scale); + transformed.scale(scale); transformed.transform(wlTransformToHyprutils(mirrored->transform), mirrored->vecPixelSize.x * scale, mirrored->vecPixelSize.y * scale); transformed.translate(Vector2D(monbox.x, monbox.y)); @@ -2234,7 +2235,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR if (pMonitor->createdByUser) { CBox transformedBox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; - transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(pMonitor->transform)), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); + transformedBox.transform(wlTransformToHyprutils(invertTransform(pMonitor->transform)), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); pMonitor->vecPixelSize = Vector2D(transformedBox.width, transformedBox.height); } diff --git a/src/render/Texture.cpp b/src/render/Texture.cpp index f72fa3a4b35..ea8823b61ea 100644 --- a/src/render/Texture.cpp +++ b/src/render/Texture.cpp @@ -20,23 +20,6 @@ CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const V createFromShm(drmFormat, pixels, stride, size_); } -CTexture::CTexture(wlr_texture* tex) { - RASSERT(wlr_texture_is_gles2(tex), "wlr_texture provided to CTexture that isn't GLES2!"); - wlr_gles2_texture_attribs attrs; - wlr_gles2_texture_get_attribs(tex, &attrs); - - m_iTarget = attrs.target; - m_iTexID = attrs.tex; - m_bNonOwning = true; - - if (m_iTarget == GL_TEXTURE_2D) - m_iType = attrs.has_alpha ? TEXTURE_RGBA : TEXTURE_RGBX; - else - m_iType = TEXTURE_EXTERNAL; - - m_vSize = Vector2D((int)tex->width, (int)tex->height); -} - CTexture::CTexture(const Aquamarine::SDMABUFAttrs& attrs, void* image) { createFromDma(attrs, image); } diff --git a/src/render/Texture.hpp b/src/render/Texture.hpp index 4c5c2c766d5..a877acff692 100644 --- a/src/render/Texture.hpp +++ b/src/render/Texture.hpp @@ -23,7 +23,6 @@ class CTexture { CTexture(const CTexture&) = delete; CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size); - CTexture(wlr_texture*); CTexture(const SP buffer); // this ctor takes ownership of the eglImage. diff --git a/src/signal-safe.hpp b/src/signal-safe.hpp index 70320ad1cd4..3a38f043225 100644 --- a/src/signal-safe.hpp +++ b/src/signal-safe.hpp @@ -1,6 +1,7 @@ #pragma once #include "defines.hpp" +#include template class MaxLengthCString { diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index e2dab412470..1d8b0cf5537 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -23,7 +23,7 @@ static bool set_cloexec(int fd, bool cloexec) { int flags = fcntl(fd, F_GETFD); if (flags == -1) { - wlr_log_errno(WLR_ERROR, "fcntl failed"); + Debug::log(ERR, "fcntl failed"); return false; } if (cloexec) { @@ -32,7 +32,7 @@ static bool set_cloexec(int fd, bool cloexec) { flags = flags & ~FD_CLOEXEC; } if (fcntl(fd, F_SETFD, flags) == -1) { - wlr_log_errno(WLR_ERROR, "fcntl failed"); + Debug::log(ERR, "fcntl failed"); return false; } return true; @@ -44,7 +44,7 @@ static int openSocket(struct sockaddr_un* addr, size_t path_size) { fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) { - wlr_log_errno(WLR_ERROR, "Failed to create socket %c%s", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); + Debug::log(ERR, "failed to create socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); return -1; } if (!set_cloexec(fd, true)) { @@ -57,12 +57,12 @@ static int openSocket(struct sockaddr_un* addr, size_t path_size) { } if (bind(fd, (struct sockaddr*)addr, size) < 0) { rc = errno; - wlr_log_errno(WLR_ERROR, "Failed to bind socket %c%s", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); + Debug::log(ERR, "failed to bind socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); goto cleanup; } if (listen(fd, 1) < 0) { rc = errno; - wlr_log_errno(WLR_ERROR, "Failed to listen to socket %c%s", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); + Debug::log(ERR, "failed to listen to socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); goto cleanup; } diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index b34d0cfea10..ea635ac0e73 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -755,7 +755,7 @@ void CXWM::getVisual() { } if (visualtype == NULL) { - wlr_log(WLR_DEBUG, "No 32 bit visualtype\n"); + Debug::log(LOG, "xwm: No 32-bit visualtype"); return; } @@ -768,7 +768,7 @@ void CXWM::getRenderFormat() { xcb_render_query_pict_formats_cookie_t cookie = xcb_render_query_pict_formats(connection); xcb_render_query_pict_formats_reply_t* reply = xcb_render_query_pict_formats_reply(connection, cookie, NULL); if (!reply) { - wlr_log(WLR_ERROR, "Did not get any reply from xcb_render_query_pict_formats"); + Debug::log(LOG, "xwm: No xcb_render_query_pict_formats_reply_t reply"); return; } xcb_render_pictforminfo_iterator_t iter = xcb_render_query_pict_formats_formats_iterator(reply); @@ -783,7 +783,7 @@ void CXWM::getRenderFormat() { } if (format == NULL) { - wlr_log(WLR_DEBUG, "No 32 bit render format"); + Debug::log(LOG, "xwm: No 32-bit render format"); free(reply); return; } diff --git a/subprojects/wlroots-hyprland b/subprojects/wlroots-hyprland deleted file mode 160000 index 422207dbcf0..00000000000 --- a/subprojects/wlroots-hyprland +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 422207dbcf0949e28042403edab539159282885e From c03f25e6fbe701c8ad0b25aea16a815c5259685d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 5 Jul 2024 20:44:54 +0200 Subject: [PATCH 043/113] rid of wlr more --- .gitmodules | 4 ---- CMakeLists.txt | 1 - Makefile | 4 ---- README.md | 9 ++++---- hyprland.pc.in | 2 +- hyprpm/src/core/PluginManager.cpp | 7 +------ src/Compositor.hpp | 2 +- src/helpers/MiscFunctions.hpp | 1 - src/helpers/Monitor.hpp | 1 - src/helpers/X11Stubs.hpp | 7 ------- src/includes.hpp | 4 ---- src/managers/input/InputManager.cpp | 1 - src/protocols/MesaDRM.cpp | 1 - src/render/OpenGL.cpp | 32 ++++++++++++++--------------- src/render/Renderer.cpp | 26 ----------------------- src/render/Texture.cpp | 2 +- src/render/Texture.hpp | 1 - src/xwayland/XWM.cpp | 4 ++-- 18 files changed, 26 insertions(+), 83 deletions(-) delete mode 100644 src/helpers/X11Stubs.hpp diff --git a/.gitmodules b/.gitmodules index 37b48a5a0fa..638f8ba9776 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,7 +7,3 @@ [submodule "subprojects/tracy"] path = subprojects/tracy url = https://github.com/wolfpld/tracy -[submodule "subprojects/wlroots-hyprland"] - path = subprojects/wlroots-hyprland - url = https://github.com/hyprwm/wlroots-hyprland - ignore = dirty diff --git a/CMakeLists.txt b/CMakeLists.txt index 545c685930f..54271fc3d53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,7 +72,6 @@ include_directories( "subprojects/udis86/" "protocols/") set(CMAKE_CXX_STANDARD 23) -add_compile_definitions(WLR_USE_UNSTABLE) add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing -Wno-pointer-arith -fmacro-prefix-map=${CMAKE_SOURCE_DIR}/=) diff --git a/Makefile b/Makefile index aff2a25a236..adf6fbe8b95 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,6 @@ nopch: clear: rm -rf build rm -f ./protocols/*.h ./protocols/*.c ./protocols/*.cpp ./protocols/*.hpp - rm -rf ./subprojects/wlroots-hyprland/build all: $(MAKE) clear @@ -50,14 +49,11 @@ installheaders: rm -fr ${PREFIX}/include/hyprland mkdir -p ${PREFIX}/include/hyprland mkdir -p ${PREFIX}/include/hyprland/protocols - mkdir -p ${PREFIX}/include/hyprland/wlr mkdir -p ${PREFIX}/share/pkgconfig cmake --build ./build --config Release --target generate-protocol-headers find src -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland - cd subprojects/wlroots-hyprland/include/wlr && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlr && cd ../../../.. - cd subprojects/wlroots-hyprland/build/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlr && cd ../../../.. cp ./protocols/*.h* ${PREFIX}/include/hyprland/protocols cp ./build/hyprland.pc ${PREFIX}/share/pkgconfig if [ -d /usr/share/pkgconfig ]; then cp ./build/hyprland.pc /usr/share/pkgconfig 2>/dev/null || true; fi diff --git a/README.md b/README.md index ca44621d2b5..fc2bd206f30 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,10 @@
-Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks. +Hyprland is a 100% independent, dynamic tiling Wayland compositor that doesn't sacrifice on its looks. It provides the latest Wayland features, is highly customizable, has all the eyecandy, the most powerful plugins, -easy IPC, much more QoL stuff than other wlr-based compositors and more... +easy IPC, much more QoL stuff than other compositors and more...

@@ -37,7 +37,7 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more... - All of the eyecandy: gradient borders, blur, animations, shadows and much more - A lot of customization -- Much more QoL stuff than other wlr-based compositors +- 100% independent, no wlroots, no libweston, no kwin, no mutter. - Custom bezier curves for the best animations - Powerful plugin support - Built-in plugin manager @@ -48,7 +48,6 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more... - Config reloaded instantly upon saving - Fully dynamic workspaces - Two built-in layouts and more available as plugins -- Uses forked wlroots with QoL patches - Global keybinds passed to your apps of choice - Tiling/pseudotiling/floating/fullscreen windows - Special workspaces (scratchpads) @@ -86,7 +85,7 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more...
-**[wlroots]** - *For their amazing library* +**[wlroots]** - *For powering Hyprland in the past* **[tinywl]** - *For showing how 2 do stuff* diff --git a/hyprland.pc.in b/hyprland.pc.in index 382fb1e6271..81a0ef11494 100644 --- a/hyprland.pc.in +++ b/hyprland.pc.in @@ -4,4 +4,4 @@ Name: Hyprland URL: https://github.com/hyprwm/Hyprland Description: Hyprland header files Version: @HYPRLAND_VERSION@ -Cflags: -I${prefix} -I${prefix}/hyprland/protocols -I${prefix}/hyprland -I${prefix}/hyprland/wlr +Cflags: -I${prefix} -I${prefix}/hyprland/protocols -I${prefix}/hyprland diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 848b9cab200..7d7cc079c3e 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -356,7 +356,7 @@ eHeadersErrors CPluginManager::headersValid() { else headers = ""; - if (PATH.ends_with("protocols") || PATH.ends_with("wlroots-hyprland")) + if (PATH.ends_with("protocols")) continue; verHeader = trim(PATH.substr(2)) + "/hyprland/src/version.h"; @@ -493,11 +493,6 @@ bool CPluginManager::updateHeaders(bool force) { return false; } - // le hack. Wlroots has to generate its build/include - ret = execAndGet("cd " + WORKINGDIR + "/subprojects/wlroots-hyprland && meson setup -Drenderers=gles2 -Dexamples=false build"); - if (m_bVerbose) - progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "meson returned: " + ret); - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " configured Hyprland"); progress.m_iSteps = 4; progress.m_szCurrentMessage = "Installing sources"; diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 3f85229cf03..d3ac6a30685 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -87,7 +87,7 @@ class CCompositor { bool m_bSessionActive = true; bool m_bDPMSStateON = true; bool m_bUnsafeState = false; // unsafe state is when there is no monitors. - bool m_bNextIsUnsafe = false; // because wlroots + bool m_bNextIsUnsafe = false; CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state bool m_bExitTriggered = false; // For exit dispatcher bool m_bIsShuttingDown = false; diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 33be796599d..49e3bced4d2 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -3,7 +3,6 @@ #include #include #include -#include #include "math/Math.hpp" #include #include diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index f14ec7d320e..640eabe7e71 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -41,7 +41,6 @@ struct SMonitorRule { class CMonitor; -// Class for wrapping the wlr state class CMonitorState { public: CMonitorState(CMonitor* owner); diff --git a/src/helpers/X11Stubs.hpp b/src/helpers/X11Stubs.hpp deleted file mode 100644 index 19bea6f8d77..00000000000 --- a/src/helpers/X11Stubs.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -inline bool wlr_backend_is_x11(void*) { - return false; -} - -inline void wlr_x11_output_create(void*) {} diff --git a/src/includes.hpp b/src/includes.hpp index 3a1bc4e302b..8b3f3fad6a9 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -27,10 +27,6 @@ #include #endif -#if !WLR_HAS_X11_BACKEND -#include "helpers/X11Stubs.hpp" -#endif - #ifdef NO_XWAYLAND #define XWAYLAND false #else diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 13fe0949b34..b6c454b2e44 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1,6 +1,5 @@ #include "InputManager.hpp" #include "../../Compositor.hpp" -#include "wlr/types/wlr_switch.h" #include #include #include "../../config/ConfigValue.hpp" diff --git a/src/protocols/MesaDRM.cpp b/src/protocols/MesaDRM.cpp index e585dcecece..8ceb24a604b 100644 --- a/src/protocols/MesaDRM.cpp +++ b/src/protocols/MesaDRM.cpp @@ -2,7 +2,6 @@ #include #include #include "../Compositor.hpp" -#include #include "types/WLBuffer.hpp" #define LOGM PROTO::mesaDRM->protoLog diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 0d740ed9fc3..3789b7b637c 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -768,7 +768,7 @@ void CHyprOpenGLImpl::end() { TRACY_GPU_ZONE("RenderEnd"); - // end the render, copy the data to the WLR framebuffer + // end the render, copy the data to the main framebuffer if (m_bOffloadedFramebuffer) { m_RenderData.damage = m_RenderData.finalDamage; m_bEndFrame = true; @@ -1177,7 +1177,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion float matrix[9]; projectBox(matrix, newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, - m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here + m_RenderData.monitorProjection.data()); float glMatrix[9]; matrixMultiply(glMatrix, m_RenderData.projection, matrix); @@ -1187,7 +1187,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion #ifndef GLES2 glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_TRUE, glMatrix); #else - wlr_matrix_transpose(glMatrix, glMatrix); + matrixTranspose(glMatrix, glMatrix); glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_FALSE, glMatrix); #endif @@ -1319,7 +1319,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB #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); @@ -1447,7 +1447,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, CBox* pBox) { #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); @@ -1498,7 +1498,7 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, CBox* pBox, CFramebuf #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); @@ -1586,7 +1586,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o #ifndef GLES2 glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_TRUE, glMatrix); #else - wlr_matrix_transpose(glMatrix, glMatrix); + matrixTranspose(glMatrix, glMatrix); glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_FALSE, glMatrix); #endif glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.contrast, *PBLURCONTRAST); @@ -1631,7 +1631,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o #ifndef GLES2 glUniformMatrix3fv(pShader->proj, 1, GL_TRUE, glMatrix); #else - wlr_matrix_transpose(glMatrix, glMatrix); + matrixTranspose(glMatrix, glMatrix); glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix); #endif glUniform1f(pShader->radius, *PBLURSIZE * a); // this makes the blursize change with a @@ -1708,7 +1708,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o #ifndef GLES2 glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_TRUE, glMatrix); #else - wlr_matrix_transpose(glMatrix, glMatrix); + matrixTranspose(glMatrix, glMatrix); glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_FALSE, glMatrix); #endif glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.noise, *PBLURNOISE); @@ -2040,7 +2040,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in float matrix[9]; projectBox(matrix, newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, - m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here + m_RenderData.monitorProjection.data()); float glMatrix[9]; matrixMultiply(glMatrix, m_RenderData.projection, matrix); @@ -2053,7 +2053,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in #ifndef GLES2 glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_TRUE, glMatrix); #else - wlr_matrix_transpose(glMatrix, glMatrix); + matrixTranspose(glMatrix, glMatrix); glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix); #endif @@ -2116,7 +2116,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr // we need to "damage" the entire monitor // so that we render the entire window - // this is temporary, doesnt mess with the actual wlr damage + // this is temporary, doesnt mess with the actual damage CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y}; g_pHyprRenderer->makeEGLCurrent(); @@ -2167,7 +2167,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(PHLWINDOW pWindow) { // we need to "damage" the entire monitor // so that we render the entire window - // this is temporary, doesnt mess with the actual wlr damage + // this is temporary, doesnt mess with the actual damage CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y}; PHLWINDOWREF ref{pWindow}; @@ -2216,7 +2216,7 @@ void CHyprOpenGLImpl::makeLayerSnapshot(PHLLS pLayer) { // we need to "damage" the entire monitor // so that we render the entire window - // this is temporary, doesnt mess with the actual wlr damage + // this is temporary, doesnt mess with the actual damage CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y}; g_pHyprRenderer->makeEGLCurrent(); @@ -2346,7 +2346,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const float matrix[9]; projectBox(matrix, newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, - m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here + m_RenderData.monitorProjection.data()); float glMatrix[9]; matrixMultiply(glMatrix, m_RenderData.projection, matrix); @@ -2358,7 +2358,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const #ifndef GLES2 glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_TRUE, glMatrix); #else - wlr_matrix_transpose(glMatrix, glMatrix); + matrixTranspose(glMatrix, glMatrix); glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_FALSE, glMatrix); #endif glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r, col.g, col.b, col.a * a); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 976cc5e2e05..b336a5f846b 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1490,31 +1490,6 @@ void CHyprRenderer::sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE void CHyprRenderer::setWindowScanoutMode(PHLWINDOW pWindow) { // FIXME: fix when moved to new impl - // if (!g_pCompositor->m_sWLRLinuxDMABuf || g_pSessionLockManager->isSessionLocked()) - // return; - - // if (!pWindow->m_bIsFullscreen) { - // wlr_linux_dmabuf_v1_set_surface_feedback(g_pCompositor->m_sWLRLinuxDMABuf, pWindow->m_pWLSurface->resource(), nullptr); - // Debug::log(LOG, "Scanout mode OFF set for {}", pWindow); - // return; - // } - - // const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); - - // const wlr_linux_dmabuf_feedback_v1_init_options INIT_OPTIONS = { - // .main_renderer = g_pCompositor->m_sWLRRenderer, - // .scanout_primary_output = PMONITOR->output, - // }; - - // wlr_linux_dmabuf_feedback_v1 feedback = {0}; - - // if (!wlr_linux_dmabuf_feedback_v1_init_with_options(&feedback, &INIT_OPTIONS)) - // return; - - // wlr_linux_dmabuf_v1_set_surface_feedback(g_pCompositor->m_sWLRLinuxDMABuf, pWindow->m_pWLSurface->resource(), &feedback); - // wlr_linux_dmabuf_feedback_v1_finish(&feedback); - - // Debug::log(LOG, "Scanout mode ON set for {}", pWindow); } // taken from Sway. @@ -2245,7 +2220,6 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR if (WAS10B != pMonitor->enabled10bit || OLDRES != pMonitor->vecPixelSize) g_pHyprOpenGL->destroyMonitorResources(pMonitor); - // updato wlroots g_pCompositor->arrangeMonitors(); pMonitor->damage.setSize(pMonitor->vecTransformedSize); diff --git a/src/render/Texture.cpp b/src/render/Texture.cpp index ea8823b61ea..0f5b4c4c34c 100644 --- a/src/render/Texture.cpp +++ b/src/render/Texture.cpp @@ -9,7 +9,7 @@ CTexture::CTexture() { } CTexture::~CTexture() { - if (m_bNonOwning || !g_pCompositor || g_pCompositor->m_bIsShuttingDown || !g_pHyprRenderer) + if (!g_pCompositor || g_pCompositor->m_bIsShuttingDown || !g_pHyprRenderer) return; g_pHyprRenderer->makeEGLCurrent(); diff --git a/src/render/Texture.hpp b/src/render/Texture.hpp index a877acff692..07156cc8157 100644 --- a/src/render/Texture.hpp +++ b/src/render/Texture.hpp @@ -38,7 +38,6 @@ class CTexture { GLuint m_iTexID = 0; Vector2D m_vSize; void* m_pEglImage = nullptr; - bool m_bNonOwning = false; // wlr private: void createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size); diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index ea635ac0e73..b55df7fcc5d 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -299,8 +299,8 @@ void CXWM::handleClientMessage(xcb_client_message_event_t* e) { auto id = e->data.data32[0]; auto resource = wl_client_get_object(g_pXWayland->pServer->xwaylandClient, id); if (resource) { - auto wlrSurface = CWLSurfaceResource::fromResource(resource); - associate(XSURF, wlrSurface); + auto surf = CWLSurfaceResource::fromResource(resource); + associate(XSURF, surf); } } else if (e->type == HYPRATOMS["WL_SURFACE_SERIAL"]) { if (XSURF->wlSerial) { From 360673ed624866ffa8166ac98c38fbf29c06eb4e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 5 Jul 2024 20:55:01 +0200 Subject: [PATCH 044/113] fix small ub in keyboard --- src/devices/IKeyboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index 5325ab0a34c..125381bacbb 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -123,7 +123,7 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) { for (size_t i = 0; i < LEDNAMES.size(); ++i) { ledIndexes.at(i) = xkb_map_led_get_index(xkbKeymap, LEDNAMES.at(i)); - Debug::log(LOG, "xkb: LED index {} (name {}) got index {}", i, LEDNAMES.at(i), modIndexes.at(i)); + Debug::log(LOG, "xkb: LED index {} (name {}) got index {}", i, LEDNAMES.at(i), ledIndexes.at(i)); } for (size_t i = 0; i < MODNAMES.size(); ++i) { From 9235728166201964e3a9dd6635dafa768ab9916a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 5 Jul 2024 21:06:23 +0200 Subject: [PATCH 045/113] fix nvidia crasherino lmao --- src/Compositor.hpp | 2 +- src/managers/CursorManager.cpp | 3 +-- src/managers/PointerManager.cpp | 5 ++++- src/render/OpenGL.cpp | 5 +++-- src/render/OpenGL.hpp | 2 +- src/render/Renderbuffer.cpp | 18 +++++++++++++---- src/render/Renderbuffer.hpp | 2 ++ src/render/Renderer.cpp | 14 +++++++++---- src/render/Renderer.hpp | 36 ++++++++++++++++----------------- src/render/Texture.hpp | 2 +- 10 files changed, 55 insertions(+), 34 deletions(-) diff --git a/src/Compositor.hpp b/src/Compositor.hpp index d3ac6a30685..3eaafb47ba4 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -86,7 +86,7 @@ class CCompositor { bool m_bReadyToProcess = false; bool m_bSessionActive = true; bool m_bDPMSStateON = true; - bool m_bUnsafeState = false; // unsafe state is when there is no monitors. + bool m_bUnsafeState = false; // unsafe state is when there is no monitors. bool m_bNextIsUnsafe = false; CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state bool m_bExitTriggered = false; // For exit dispatcher diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 3dd4394036c..176caaa59ec 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -139,8 +139,7 @@ void CCursorManager::setXCursor(const std::string& name) { return; } - m_vCursorBuffers.emplace_back( - makeShared(xcursor.defaultCursor->pixels.data(), xcursor.defaultCursor->size, xcursor.defaultCursor->hotspot)); + m_vCursorBuffers.emplace_back(makeShared(xcursor.defaultCursor->pixels.data(), xcursor.defaultCursor->size, xcursor.defaultCursor->hotspot)); g_pPointerManager->setCursorBuffer(getCursorBuffer(), xcursor.defaultCursor->hotspot / scale, scale); if (m_vCursorBuffers.size() > 1) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 11259632faf..e7c5b42b441 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -395,6 +395,9 @@ SP CPointerManager::renderHWCursorBuffer(SPm_RenderData.pMonitor = state->monitor.get(); const auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format); + if (!RBO) + return nullptr; + RBO->bind(); g_pHyprOpenGL->beginSimple(state->monitor.get(), damage, RBO); @@ -410,7 +413,7 @@ SP CPointerManager::renderHWCursorBuffer(SPm_RenderData.pMonitor = nullptr; - g_pHyprRenderer->onRenderbufferDestroy(RBO); + g_pHyprRenderer->onRenderbufferDestroy(RBO.get()); return buf; } diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 3789b7b637c..8c5adf4ecbf 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -617,7 +617,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { return false; } -void CHyprOpenGLImpl::beginSimple(CMonitor* pMonitor, const CRegion& damage, CRenderbuffer* rb, CFramebuffer* fb) { +void CHyprOpenGLImpl::beginSimple(CMonitor* pMonitor, const CRegion& damage, SP rb, CFramebuffer* fb) { m_RenderData.pMonitor = pMonitor; #ifndef GLES2 @@ -1558,7 +1558,8 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o // prep damage CRegion damage{*originalDamage}; - damage.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); + damage.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, + m_RenderData.pMonitor->vecTransformedSize.y); damage.expand(*PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES)); // helper diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 4b525b163c4..9696c2ccb69 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -130,7 +130,7 @@ class CHyprOpenGLImpl { CHyprOpenGLImpl(); void begin(CMonitor*, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional finalDamage = {}); - void beginSimple(CMonitor*, const CRegion& damage, CRenderbuffer* rb = nullptr, CFramebuffer* fb = nullptr); + void beginSimple(CMonitor*, const CRegion& damage, SP rb = nullptr, CFramebuffer* fb = nullptr); void end(); void renderRect(CBox*, const CColor&, int round = 0); diff --git a/src/render/Renderbuffer.cpp b/src/render/Renderbuffer.cpp index 65c64eb9287..57f4fbd21a3 100644 --- a/src/render/Renderbuffer.cpp +++ b/src/render/Renderbuffer.cpp @@ -22,8 +22,10 @@ CRenderbuffer::CRenderbuffer(SP buffer, uint32_t format) : auto dma = buffer->dmabuf(); m_iImage = g_pHyprOpenGL->createEGLImage(dma); - if (m_iImage == EGL_NO_IMAGE_KHR) - throw std::runtime_error("createEGLImage failed"); + if (m_iImage == EGL_NO_IMAGE_KHR) { + Debug::log(ERR, "rb: createEGLImage failed"); + return; + } glGenRenderbuffers(1, &m_iRBO); glBindRenderbuffer(GL_RENDERBUFFER, m_iRBO); @@ -35,12 +37,20 @@ CRenderbuffer::CRenderbuffer(SP buffer, uint32_t format) : m_sFramebuffer.bind(); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_iRBO); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - throw std::runtime_error("rbo: glCheckFramebufferStatus failed"); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + Debug::log(ERR, "rbo: glCheckFramebufferStatus failed"); + return; + } glBindFramebuffer(GL_FRAMEBUFFER, 0); listeners.destroyBuffer = buffer->events.destroy.registerListener([this](std::any d) { g_pHyprRenderer->onRenderbufferDestroy(this); }); + + m_bGood = true; +} + +bool CRenderbuffer::good() { + return m_bGood; } void CRenderbuffer::bind() { diff --git a/src/render/Renderbuffer.hpp b/src/render/Renderbuffer.hpp index 518b34dae7a..f8155087178 100644 --- a/src/render/Renderbuffer.hpp +++ b/src/render/Renderbuffer.hpp @@ -10,6 +10,7 @@ class CRenderbuffer { CRenderbuffer(SP buffer, uint32_t format); ~CRenderbuffer(); + bool good(); void bind(); void bindFB(); void unbind(); @@ -23,6 +24,7 @@ class CRenderbuffer { GLuint m_iRBO = 0; CFramebuffer m_sFramebuffer; uint32_t m_uDrmFormat = 0; + bool m_bGood = false; struct { CHyprSignalListener destroyBuffer; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index b336a5f846b..f753a626123 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2541,13 +2541,19 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { pMonitor->solitaryClient = PCANDIDATE; } -CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(SP buffer, uint32_t fmt) { +SP CHyprRenderer::getOrCreateRenderbuffer(SP buffer, uint32_t fmt) { auto it = std::find_if(m_vRenderbuffers.begin(), m_vRenderbuffers.end(), [&](const auto& other) { return other->m_pHLBuffer == buffer; }); if (it != m_vRenderbuffers.end()) - return it->get(); + return *it; - return m_vRenderbuffers.emplace_back(std::make_unique(buffer, fmt)).get(); + auto buf = makeShared(buffer, fmt); + + if (!buf->good()) + return nullptr; + + m_vRenderbuffers.emplace_back(buf); + return buf; } void CHyprRenderer::makeEGLCurrent() { @@ -2650,7 +2656,7 @@ void CHyprRenderer::onRenderbufferDestroy(CRenderbuffer* rb) { std::erase_if(m_vRenderbuffers, [&](const auto& rbo) { return rbo.get() == rb; }); } -CRenderbuffer* CHyprRenderer::getCurrentRBO() { +SP CHyprRenderer::getCurrentRBO() { return m_pCurrentRenderbuffer; } diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 81b9e55bd87..ce37f51b24f 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -69,7 +69,7 @@ class CHyprRenderer { void setCursorSurface(SP surf, int hotspotX, int hotspotY, bool force = false); void setCursorFromName(const std::string& name, bool force = false); void onRenderbufferDestroy(CRenderbuffer* rb); - CRenderbuffer* getCurrentRBO(); + SP getCurrentRBO(); bool isNvidia(); void makeEGLCurrent(); void unsetEGL(); @@ -107,21 +107,21 @@ class CHyprRenderer { } m_sLastCursorData; private: - void arrangeLayerArray(CMonitor*, const std::vector&, bool, CBox*); - void renderWorkspaceWindowsFullscreen(CMonitor*, PHLWORKSPACE, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) - void renderWorkspaceWindows(CMonitor*, PHLWORKSPACE, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) - void renderWindow(PHLWINDOW, CMonitor*, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false); - void renderLayer(PHLLS, CMonitor*, timespec*, bool popups = false); - void renderSessionLockSurface(SSessionLockSurface*, CMonitor*, timespec*); - void renderDragIcon(CMonitor*, timespec*); - void renderIMEPopup(CInputPopup*, CMonitor*, timespec*); - void renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry); - void sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now); // sends frame displayed events but doesn't actually render anything - void renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); - - bool m_bCursorHidden = false; - bool m_bCursorHasSurface = false; - CRenderbuffer* m_pCurrentRenderbuffer = nullptr; + void arrangeLayerArray(CMonitor*, const std::vector&, bool, CBox*); + void renderWorkspaceWindowsFullscreen(CMonitor*, PHLWORKSPACE, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) + void renderWorkspaceWindows(CMonitor*, PHLWORKSPACE, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) + void renderWindow(PHLWINDOW, CMonitor*, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false); + void renderLayer(PHLLS, CMonitor*, timespec*, bool popups = false); + void renderSessionLockSurface(SSessionLockSurface*, CMonitor*, timespec*); + void renderDragIcon(CMonitor*, timespec*); + void renderIMEPopup(CInputPopup*, CMonitor*, timespec*); + void renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry); + void sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now); // sends frame displayed events but doesn't actually render anything + void renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); + + bool m_bCursorHidden = false; + bool m_bCursorHasSurface = false; + SP m_pCurrentRenderbuffer = nullptr; SP m_pCurrentBuffer; eRenderMode m_eRenderMode = RENDER_MODE_NORMAL; @@ -133,8 +133,8 @@ class CHyprRenderer { bool hiddenOnKeyboard = false; } m_sCursorHiddenConditions; - CRenderbuffer* getOrCreateRenderbuffer(SP buffer, uint32_t fmt); - std::vector> m_vRenderbuffers; + SP getOrCreateRenderbuffer(SP buffer, uint32_t fmt); + std::vector> m_vRenderbuffers; friend class CHyprOpenGLImpl; friend class CToplevelExportProtocolManager; diff --git a/src/render/Texture.hpp b/src/render/Texture.hpp index 07156cc8157..0da95300cc4 100644 --- a/src/render/Texture.hpp +++ b/src/render/Texture.hpp @@ -37,7 +37,7 @@ class CTexture { GLenum m_iTarget = GL_TEXTURE_2D; GLuint m_iTexID = 0; Vector2D m_vSize; - void* m_pEglImage = nullptr; + void* m_pEglImage = nullptr; private: void createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size); From 590e706cde3fa1637930fa01accfef4889e24024 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 5 Jul 2024 23:13:06 +0200 Subject: [PATCH 046/113] damage oops --- src/render/OpenGL.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 8c5adf4ecbf..9658adb5ba1 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1679,12 +1679,12 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o // and draw for (int i = 1; i <= *PBLURPASSES; ++i) { - tempDamage.scale(1.f / (1 << i)); + tempDamage = damage.copy().scale(1.f / (1 << i)); drawPass(&m_RenderData.pCurrentMonData->m_shBLUR1, &tempDamage); // down } for (int i = *PBLURPASSES - 1; i >= 0; --i) { - tempDamage.scale(1.f / (1 << i)); // when upsampling we make the region twice as big + tempDamage = damage.copy().scale(1.f / (1 << i)); // when upsampling we make the region twice as big drawPass(&m_RenderData.pCurrentMonData->m_shBLUR2, &tempDamage); // up } From 03eb7e37dae8d2f915330d3aa5e6d649f37abb6e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 5 Jul 2024 23:22:20 +0200 Subject: [PATCH 047/113] xcursor stuff --- src/managers/CursorManager.cpp | 39 +++++++++++++++++++++++++++++---- src/managers/CursorManager.hpp | 11 ++++++---- src/protocols/CursorShape.cpp | 40 ---------------------------------- 3 files changed, 42 insertions(+), 48 deletions(-) diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 176caaa59ec..9545201e3be 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -4,6 +4,7 @@ #include "PointerManager.hpp" #include "../xwayland/XWayland.hpp" #include +#include "../helpers/CursorShapes.hpp" extern "C" { #include @@ -139,9 +140,14 @@ void CCursorManager::setXCursor(const std::string& name) { return; } - m_vCursorBuffers.emplace_back(makeShared(xcursor.defaultCursor->pixels.data(), xcursor.defaultCursor->size, xcursor.defaultCursor->hotspot)); + auto& icon = xcursor.defaultCursor; + // try to get an icon we know if we have one + if (xcursor.cursors.contains(name)) + icon = xcursor.cursors.at(name); - g_pPointerManager->setCursorBuffer(getCursorBuffer(), xcursor.defaultCursor->hotspot / scale, scale); + m_vCursorBuffers.emplace_back(makeShared(icon->pixels.data(), icon->size, icon->hotspot)); + + g_pPointerManager->setCursorBuffer(getCursorBuffer(), icon->hotspot / scale, scale); if (m_vCursorBuffers.size() > 1) dropBufferRef(m_vCursorBuffers.at(0).get()); @@ -300,8 +306,12 @@ bool CCursorManager::changeTheme(const std::string& name, const int size) { } void CCursorManager::SXCursorManager::loadTheme(const std::string& name, int size) { - themeLoaded = false; - themeName = name.empty() ? "default" : name; + if (lastLoadSize == size && themeName == name) + return; + + lastLoadSize = size; + themeLoaded = false; + themeName = name.empty() ? "default" : name; auto img = XcursorShapeLoadImage(1, name.c_str(), size); @@ -323,4 +333,25 @@ void CCursorManager::SXCursorManager::loadTheme(const std::string& name, int siz std::memcpy(defaultCursor->pixels.data(), img->pixels, img->width * img->height); themeLoaded = true; + + // gather as many shapes as we can find. + cursors.clear(); + + for (auto& shape : CURSOR_SHAPE_NAMES) { + auto xImage = XcursorShapeLoadImage(1, shape, size); + + if (!xImage) { + Debug::log(LOG, "XCursor failed to find a shape with name {}, skipping", shape); + continue; + } + + auto xcursor = makeShared(); + xcursor->size = {(int)xImage->width, (int)xImage->height}; + xcursor->hotspot = {(int)xImage->xhot, (int)xImage->yhot}; + + xcursor->pixels.resize(xImage->width * xImage->height); + std::memcpy(xcursor->pixels.data(), xImage->pixels, xImage->width * xImage->height); + + cursors.emplace(std::string{shape}, xcursor); + } } diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index 67e8d970650..eeb57197e6b 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -81,11 +81,14 @@ class CCursorManager { }; struct SXCursorManager { - void loadTheme(const std::string& name, int size); + void loadTheme(const std::string& name, int size); - bool themeLoaded = false; - std::string themeName = ""; - SP defaultCursor; + int lastLoadSize = 0; + + bool themeLoaded = false; + std::string themeName = ""; + SP defaultCursor; + std::unordered_map> cursors; } xcursor; }; diff --git a/src/protocols/CursorShape.cpp b/src/protocols/CursorShape.cpp index 2f25b22bc10..9b76b7675fe 100644 --- a/src/protocols/CursorShape.cpp +++ b/src/protocols/CursorShape.cpp @@ -3,46 +3,6 @@ #define LOGM PROTO::cursorShape->protoLog -// clang-format off -constexpr const char* SHAPE_NAMES[] = { - "invalid", - "default", - "context-menu", - "help", - "pointer", - "progress", - "wait", - "cell", - "crosshair", - "text", - "vertical-text", - "alias", - "copy", - "move", - "no-drop", - "not-allowed", - "grab", - "grabbing", - "e-resize", - "n-resize", - "ne-resize", - "nw-resize", - "s-resize", - "se-resize", - "sw-resize", - "w-resize", - "ew-resize", - "ns-resize", - "nesw-resize", - "nwse-resize", - "col-resize", - "row-resize", - "all-scroll", - "zoom-in", - "zoom-out", -}; -// clang-format on - CCursorShapeProtocol::CCursorShapeProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { ; } From cff9b4fdb163e389931c2672aa9de52206ac898b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 5 Jul 2024 23:22:49 +0200 Subject: [PATCH 048/113] missed a file --- src/helpers/CursorShapes.hpp | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/helpers/CursorShapes.hpp diff --git a/src/helpers/CursorShapes.hpp b/src/helpers/CursorShapes.hpp new file mode 100644 index 00000000000..6f3c8a0ea71 --- /dev/null +++ b/src/helpers/CursorShapes.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include + +// clang-format off +constexpr std::array CURSOR_SHAPE_NAMES = { + "invalid", + "default", + "context-menu", + "help", + "pointer", + "progress", + "wait", + "cell", + "crosshair", + "text", + "vertical-text", + "alias", + "copy", + "move", + "no-drop", + "not-allowed", + "grab", + "grabbing", + "e-resize", + "n-resize", + "ne-resize", + "nw-resize", + "s-resize", + "se-resize", + "sw-resize", + "w-resize", + "ew-resize", + "ns-resize", + "nesw-resize", + "nwse-resize", + "col-resize", + "row-resize", + "all-scroll", + "zoom-in", + "zoom-out", +}; +// clang-format on \ No newline at end of file From 74971816dc9afbf939821105cda1e6a217ce6d06 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 5 Jul 2024 23:34:32 +0200 Subject: [PATCH 049/113] fix --- src/protocols/CursorShape.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/protocols/CursorShape.cpp b/src/protocols/CursorShape.cpp index 9b76b7675fe..812afe53d85 100644 --- a/src/protocols/CursorShape.cpp +++ b/src/protocols/CursorShape.cpp @@ -1,5 +1,6 @@ #include "CursorShape.hpp" #include +#include "../helpers/CursorShapes.hpp" #define LOGM PROTO::cursorShape->protoLog @@ -42,7 +43,7 @@ void CCursorShapeProtocol::createCursorShapeDevice(CWpCursorShapeManagerV1* pMgr } void CCursorShapeProtocol::onSetShape(CWpCursorShapeDeviceV1* pMgr, uint32_t serial, wpCursorShapeDeviceV1Shape shape) { - if ((uint32_t)shape == 0 || (uint32_t)shape > sizeof(SHAPE_NAMES)) { + if ((uint32_t)shape == 0 || (uint32_t)shape > CURSOR_SHAPE_NAMES.size()) { pMgr->error(WP_CURSOR_SHAPE_DEVICE_V1_ERROR_INVALID_SHAPE, "The shape is invalid"); return; } @@ -50,7 +51,7 @@ void CCursorShapeProtocol::onSetShape(CWpCursorShapeDeviceV1* pMgr, uint32_t ser SSetShapeEvent event; event.pMgr = pMgr; event.shape = shape; - event.shapeName = SHAPE_NAMES[shape]; + event.shapeName = CURSOR_SHAPE_NAMES.at(shape); events.setShape.emit(event); } \ No newline at end of file From c6b9b292dda55fe3b43f0ef27213f110b0bd7169 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 6 Jul 2024 11:28:24 +0200 Subject: [PATCH 050/113] fix mirrors, thanks virtcode --- src/render/OpenGL.cpp | 12 ++++++------ src/render/Renderer.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 9658adb5ba1..edd3cc921bc 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2438,11 +2438,11 @@ void CHyprOpenGLImpl::renderMirrored() { return; // replace monitor projection to undo the mirrored monitor's projection - matrixIdentity(monitor->projMatrix.data()); - matrixTranslate(monitor->projMatrix.data(), monitor->vecPixelSize.x / 2.0, monitor->vecPixelSize.y / 2.0); - matrixTransform(monitor->projMatrix.data(), wlTransformToHyprutils(monitor->transform)); - matrixTransform(monitor->projMatrix.data(), wlTransformToHyprutils(invertTransform(mirrored->transform))); - matrixTranslate(monitor->projMatrix.data(), -monitor->vecTransformedSize.x / 2.0, -monitor->vecTransformedSize.y / 2.0); + matrixIdentity(m_RenderData.monitorProjection.data()); + matrixTranslate(m_RenderData.monitorProjection.data(), monitor->vecPixelSize.x / 2.0, monitor->vecPixelSize.y / 2.0); + matrixTransform(m_RenderData.monitorProjection.data(), wlTransformToHyprutils(monitor->transform)); + matrixTransform(m_RenderData.monitorProjection.data(), wlTransformToHyprutils(invertTransform(mirrored->transform))); + matrixTranslate(m_RenderData.monitorProjection.data(), -monitor->vecTransformedSize.x / 2.0, -monitor->vecTransformedSize.y / 2.0); // clear stuff outside of mirrored area (e.g. when changing to mirrored) clear(CColor(0, 0, 0, 0)); @@ -2450,7 +2450,7 @@ void CHyprOpenGLImpl::renderMirrored() { renderTexture(PFB->m_cTex, &monbox, 1.f, 0, false, false); // reset matrix for further drawing - monitor->updateMatrix(); + m_RenderData.monitorProjection = monitor->projMatrix; } void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const CAIROSURFACE, double offsetY, const Vector2D& size) { diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index f753a626123..ac6fd8c1e0c 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1400,7 +1400,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { TRACY_GPU_COLLECT; if (!pMonitor->mirrors.empty()) { - CRegion frameDamage{}; + CRegion frameDamage{finalDamage}; const auto TRANSFORM = invertTransform(pMonitor->transform); frameDamage.transform(wlTransformToHyprutils(TRANSFORM), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); From 82e27597db399ac645a8f4990d74d01243de1a07 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 6 Jul 2024 12:06:15 +0200 Subject: [PATCH 051/113] xcursors mmm --- src/managers/CursorManager.cpp | 116 ++++++++++++++++++++++++++++++--- src/managers/CursorManager.hpp | 6 +- src/render/OpenGL.cpp | 2 +- 3 files changed, 111 insertions(+), 13 deletions(-) diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 9545201e3be..2525008376e 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -145,7 +145,7 @@ void CCursorManager::setXCursor(const std::string& name) { if (xcursor.cursors.contains(name)) icon = xcursor.cursors.at(name); - m_vCursorBuffers.emplace_back(makeShared(icon->pixels.data(), icon->size, icon->hotspot)); + m_vCursorBuffers.emplace_back(makeShared((uint8_t*)icon->pixels.data(), icon->size, icon->hotspot)); g_pPointerManager->setCursorBuffer(getCursorBuffer(), icon->hotspot / scale, scale); if (m_vCursorBuffers.size() > 1) @@ -252,7 +252,7 @@ void CCursorManager::setXWaylandCursor() { g_pXWayland->setCursor(cairo_image_surface_get_data(CURSOR.surface), cairo_image_surface_get_stride(CURSOR.surface), {CURSOR.size, CURSOR.size}, {CURSOR.hotspotX, CURSOR.hotspotY}); } else if (xcursor.themeLoaded) - g_pXWayland->setCursor(xcursor.defaultCursor->pixels.data(), xcursor.defaultCursor->size.x * 4, xcursor.defaultCursor->size, xcursor.defaultCursor->hotspot); + g_pXWayland->setCursor((uint8_t*)xcursor.defaultCursor->pixels.data(), xcursor.defaultCursor->size.x * 4, xcursor.defaultCursor->size, xcursor.defaultCursor->hotspot); else Debug::log(ERR, "CursorManager: no valid cursor for xwayland"); } @@ -305,6 +305,91 @@ bool CCursorManager::changeTheme(const std::string& name, const int size) { return true; } +// Taken from https://gitlab.freedesktop.org/xorg/lib/libxcursor/-/blob/master/src/library.c +// however modified to fit wayland cursor shape names better. +// _ -> - +// clang-format off +static std::array XCURSOR_STANDARD_NAMES = { + "X_cursor", + "default", // arrow + "ns-resize", // based-arrow-down + "ns-resize", // based-arrow-up + "boat", + "bogosity", + "sw-resize", // bottom-left-corner + "se-resize", // bottom-right-corner + "s-resize", // bottom-side + "bottom-tee", + "box-spiral", + "center-ptr", + "circle", + "clock", + "coffee-mug", + "cross", + "cross-reverse", + "crosshair", + "diamond-cross", + "dot", + "dotbox", + "double-arrow", + "draft-large", + "draft-small", + "draped-box", + "exchange", + "move", // fleur + "gobbler", + "gumby", + "pointer", // hand1 + "grabbing", // hand2 + "heart", + "icon", + "iron-cross", + "default", // left-ptr + "w-resize", // left-side + "left-tee", + "leftbutton", + "ll-angle", + "lr-angle", + "man", + "middlebutton", + "mouse", + "pencil", + "pirate", + "plus", + "help", // question-arrow + "right-ptr", + "e-resize", // right-side + "right-tee", + "rightbutton", + "rtl-logo", + "sailboat", + "ns-resize", // sb-down-arrow + "ew-resize", // sb-h-double-arrow + "ew-resize", // sb-left-arrow + "ew-resize", // sb-right-arrow + "n-resize", // sb-up-arrow + "s-resize", // sb-v-double-arrow + "shuttle", + "sizing", + "spider", + "spraycan", + "star", + "target", + "cell", // tcross + "nw-resize", // top-left-arrow + "nw-resize", // top-left-corner + "ne-resize", // top-right-corner + "n-resize", // top-side + "top-tee", + "trek", + "ul-angle", + "umbrella", + "ur-angle", + "wait", // watch + "text", // xterm +}; +// clang-format on + void CCursorManager::SXCursorManager::loadTheme(const std::string& name, int size) { if (lastLoadSize == size && themeName == name) return; @@ -313,14 +398,14 @@ void CCursorManager::SXCursorManager::loadTheme(const std::string& name, int siz themeLoaded = false; themeName = name.empty() ? "default" : name; - auto img = XcursorShapeLoadImage(1, name.c_str(), size); + auto img = XcursorShapeLoadImage(2, themeName.c_str(), size); if (!img) { - Debug::log(ERR, "XCursor failed finding theme \"{}\". Trying size 24.", name); + Debug::log(ERR, "XCursor failed finding theme \"{}\". Trying size 24.", themeName); size = 24; - img = XcursorShapeLoadImage(1, name.c_str(), size); + img = XcursorShapeLoadImage(2, themeName.c_str(), size); if (!img) { - Debug::log(ERR, "XCursor failed finding theme \"{}\".", name); + Debug::log(ERR, "XCursor failed finding theme \"{}\".", themeName); return; } } @@ -330,7 +415,7 @@ void CCursorManager::SXCursorManager::loadTheme(const std::string& name, int siz defaultCursor->hotspot = {(int)img->xhot, (int)img->yhot}; defaultCursor->pixels.resize(img->width * img->height); - std::memcpy(defaultCursor->pixels.data(), img->pixels, img->width * img->height); + std::memcpy(defaultCursor->pixels.data(), img->pixels, img->width * img->height * sizeof(uint32_t)); themeLoaded = true; @@ -338,7 +423,20 @@ void CCursorManager::SXCursorManager::loadTheme(const std::string& name, int siz cursors.clear(); for (auto& shape : CURSOR_SHAPE_NAMES) { - auto xImage = XcursorShapeLoadImage(1, shape, size); + int id = -1; + for (size_t i = 0; i < XCURSOR_STANDARD_NAMES.size(); ++i) { + if (XCURSOR_STANDARD_NAMES.at(i) == std::string{shape}) { + id = i; + break; + } + } + + if (id < 0) { + Debug::log(LOG, "XCursor has no shape {}, skipping", shape); + continue; + } + + auto xImage = XcursorShapeLoadImage(id << 1 /* wtf xcursor? */, themeName.c_str(), size); if (!xImage) { Debug::log(LOG, "XCursor failed to find a shape with name {}, skipping", shape); @@ -350,7 +448,7 @@ void CCursorManager::SXCursorManager::loadTheme(const std::string& name, int siz xcursor->hotspot = {(int)xImage->xhot, (int)xImage->yhot}; xcursor->pixels.resize(xImage->width * xImage->height); - std::memcpy(xcursor->pixels.data(), xImage->pixels, xImage->width * xImage->height); + std::memcpy(xcursor->pixels.data(), xImage->pixels, xImage->width * xImage->height * sizeof(uint32_t)); cursors.emplace(std::string{shape}, xcursor); } diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index eeb57197e6b..a2e8af21f3e 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -75,9 +75,9 @@ class CCursorManager { // gangsta bootleg XCursor impl. Whenever Hyprland has to use // an xcursor, just use the pointer. struct SXCursor { - Vector2D size; - Vector2D hotspot; - std::vector pixels; + Vector2D size; + Vector2D hotspot; + std::vector pixels; // XPixel is a u32 }; struct SXCursorManager { diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index edd3cc921bc..467c83f4dbf 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1684,7 +1684,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o } for (int i = *PBLURPASSES - 1; i >= 0; --i) { - tempDamage = damage.copy().scale(1.f / (1 << i)); // when upsampling we make the region twice as big + tempDamage = damage.copy().scale(1.f / (1 << i)); // when upsampling we make the region twice as big drawPass(&m_RenderData.pCurrentMonData->m_shBLUR2, &tempDamage); // up } From f4c8789aec7150c6573ad69927eb53ec9f710dcf Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 6 Jul 2024 17:38:27 +0200 Subject: [PATCH 052/113] explicit sync --- CMakeLists.txt | 1 + src/helpers/Monitor.cpp | 6 + src/helpers/Monitor.hpp | 9 +- src/helpers/sync/SyncTimeline.cpp | 187 ++++++++++++++++++++ src/helpers/sync/SyncTimeline.hpp | 46 +++++ src/managers/ProtocolManager.cpp | 2 + src/managers/eventLoop/EventLoopManager.hpp | 2 + src/protocols/DRMSyncobj.cpp | 182 +++++++++++++++++++ src/protocols/DRMSyncobj.hpp | 82 +++++++++ src/protocols/Viewporter.cpp | 29 +-- src/protocols/Viewporter.hpp | 5 +- src/protocols/core/Compositor.cpp | 133 +++++++++----- src/protocols/core/Compositor.hpp | 12 +- src/render/OpenGL.cpp | 64 +++++++ src/render/OpenGL.hpp | 20 +++ src/render/Renderer.cpp | 61 ++++--- src/render/Renderer.hpp | 2 + 17 files changed, 757 insertions(+), 86 deletions(-) create mode 100644 src/helpers/sync/SyncTimeline.cpp create mode 100644 src/helpers/sync/SyncTimeline.hpp create mode 100644 src/protocols/DRMSyncobj.cpp create mode 100644 src/protocols/DRMSyncobj.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 54271fc3d53..1db303f3885 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -296,6 +296,7 @@ protocolNew("staging/xwayland-shell" "xwayland-shell-v1" false) protocolNew("stable/viewporter" "viewporter" false) protocolNew("stable/linux-dmabuf" "linux-dmabuf-v1" false) protocolNew("staging/drm-lease" "drm-lease-v1" false) +protocolNew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false) protocolWayland() diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index accc77834bd..495e772e2f8 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -10,6 +10,7 @@ #include "../protocols/DRMLease.hpp" #include "../protocols/core/Output.hpp" #include "../managers/PointerManager.hpp" +#include "sync/SyncTimeline.hpp" #include using namespace Hyprutils::String; @@ -29,6 +30,11 @@ CMonitor::~CMonitor() { void CMonitor::onConnect(bool noRule) { + if (output->supportsExplicit) { + inTimeline = CSyncTimeline::create(g_pCompositor->m_iDRMFD); + outTimeline = CSyncTimeline::create(g_pCompositor->m_iDRMFD); + } + listeners.frame = output->events.frame.registerListener([this](std::any d) { Events::listener_monitorFrame(this, nullptr); }); listeners.destroy = output->events.destroy.registerListener([this](std::any d) { Events::listener_monitorDestroy(this, nullptr); }); listeners.commit = output->events.commit.registerListener([this](std::any d) { Events::listener_monitorCommit(this, nullptr); }); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 640eabe7e71..7488d7dcb59 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -40,6 +40,7 @@ struct SMonitorRule { }; class CMonitor; +class CSyncTimeline; class CMonitorState { public: @@ -116,7 +117,13 @@ class CMonitor { SMonitorRule activeMonitorRule; - WP self; + // explicit sync + SP inTimeline; + SP outTimeline; + uint64_t lastWaitPoint = 0; + uint64_t commitSeq = 0; + + WP self; // mirroring CMonitor* pMirrorOf = nullptr; diff --git a/src/helpers/sync/SyncTimeline.cpp b/src/helpers/sync/SyncTimeline.cpp new file mode 100644 index 00000000000..1a7286e00f0 --- /dev/null +++ b/src/helpers/sync/SyncTimeline.cpp @@ -0,0 +1,187 @@ +#include "SyncTimeline.hpp" +#include "../../defines.hpp" +#include "../../managers/eventLoop/EventLoopManager.hpp" + +#include +#include + +SP CSyncTimeline::create(int drmFD_) { + auto timeline = SP(new CSyncTimeline); + timeline->drmFD = drmFD_; + timeline->self = timeline; + + if (drmSyncobjCreate(drmFD_, 0, &timeline->handle)) { + Debug::log(ERR, "CSyncTimeline: failed to create a drm syncobj??"); + return nullptr; + } + + return timeline; +} + +SP CSyncTimeline::create(int drmFD_, int drmSyncobjFD) { + auto timeline = SP(new CSyncTimeline); + timeline->drmFD = drmFD_; + timeline->self = timeline; + + if (drmSyncobjFDToHandle(drmFD_, drmSyncobjFD, &timeline->handle)) { + Debug::log(ERR, "CSyncTimeline: failed to create a drm syncobj from fd??"); + return nullptr; + } + + return timeline; +} + +CSyncTimeline::~CSyncTimeline() { + if (handle == 0) + return; + + drmSyncobjDestroy(drmFD, handle); +} + +std::optional CSyncTimeline::check(uint64_t point, uint32_t flags) { +#ifdef __FreeBSD__ + constexpr int ETIME_ERR = ETIMEDOUT; +#else + constexpr int ETIME_ERR = ETIME; +#endif + + uint32_t signaled = 0; + int ret = drmSyncobjTimelineWait(drmFD, &handle, &point, 1, 0, flags, &signaled); + if (ret != 0 && ret != -ETIME_ERR) { + Debug::log(ERR, "CSyncTimeline::check: drmSyncobjTimelineWait failed"); + return std::nullopt; + } + + return ret == 0; +} + +static int handleWaiterFD(int fd, uint32_t mask, void* data) { + auto waiter = (CSyncTimeline::SWaiter*)data; + + if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) { + Debug::log(ERR, "handleWaiterFD: eventfd error"); + return 0; + } + + if (mask & WL_EVENT_READABLE) { + uint64_t value = 0; + if (read(fd, &value, sizeof(value)) <= 0) + Debug::log(ERR, "handleWaiterFD: failed to read from eventfd"); + } + + wl_event_source_remove(waiter->source); + waiter->source = nullptr; + + if (waiter->fn) + waiter->fn(); + + if (waiter->timeline) + waiter->timeline->removeWaiter(waiter); + + return 0; +} + +bool CSyncTimeline::addWaiter(const std::function& waiter, uint64_t point, uint32_t flags) { + auto w = makeShared(); + w->fn = waiter; + w->timeline = self; + + int eventFD = eventfd(0, EFD_CLOEXEC); + + if (eventFD < 0) { + Debug::log(ERR, "CSyncTimeline::addWaiter: failed to acquire an eventfd"); + return false; + } + + drm_syncobj_eventfd syncobjEventFD = { + .handle = handle, + .flags = flags, + .point = point, + .fd = eventFD, + }; + + if (drmIoctl(drmFD, DRM_IOCTL_SYNCOBJ_EVENTFD, &syncobjEventFD) != 0) { + Debug::log(ERR, "CSyncTimeline::addWaiter: drmIoctl failed"); + close(eventFD); + return false; + } + + w->source = wl_event_loop_add_fd(g_pEventLoopManager->m_sWayland.loop, eventFD, WL_EVENT_READABLE, ::handleWaiterFD, w.get()); + if (!w->source) { + Debug::log(ERR, "CSyncTimeline::addWaiter: wl_event_loop_add_fd failed"); + close(eventFD); + return false; + } + + waiters.emplace_back(w); + + return true; +} + +void CSyncTimeline::removeWaiter(SWaiter* w) { + if (w->source) { + wl_event_source_remove(w->source); + w->source = nullptr; + } + std::erase_if(waiters, [w](const auto& e) { return e.get() == w; }); +} + +int CSyncTimeline::exportAsSyncFileFD(uint64_t src) { + int sync = -1; + + uint32_t syncHandle = 0; + if (drmSyncobjCreate(drmFD, 0, &syncHandle)) { + Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjCreate failed"); + return -1; + } + + if (drmSyncobjTransfer(drmFD, syncHandle, 0, handle, src, 0)) { + Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjTransfer failed"); + drmSyncobjDestroy(drmFD, syncHandle); + return -1; + } + + if (drmSyncobjExportSyncFile(drmFD, syncHandle, &sync)) { + Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjExportSyncFile failed"); + drmSyncobjDestroy(drmFD, syncHandle); + return -1; + } + + drmSyncobjDestroy(drmFD, syncHandle); + return sync; +} + +bool CSyncTimeline::importFromSyncFileFD(uint64_t dst, int fd) { + uint32_t syncHandle = 0; + + if (drmSyncobjCreate(drmFD, 0, &syncHandle)) { + Debug::log(ERR, "importFromSyncFileFD: drmSyncobjCreate failed"); + return false; + } + + if (drmSyncobjImportSyncFile(drmFD, syncHandle, fd)) { + Debug::log(ERR, "importFromSyncFileFD: drmSyncobjImportSyncFile failed"); + drmSyncobjDestroy(drmFD, syncHandle); + return -1; + } + + if (drmSyncobjTransfer(drmFD, handle, dst, syncHandle, 0, 0)) { + Debug::log(ERR, "importFromSyncFileFD: drmSyncobjTransfer failed"); + drmSyncobjDestroy(drmFD, syncHandle); + return -1; + } + + drmSyncobjDestroy(drmFD, syncHandle); + return true; +} + +bool CSyncTimeline::transfer(SP from, uint64_t fromPoint, uint64_t toPoint) { + ASSERT(from->drmFD == drmFD); + + if (drmSyncobjTransfer(drmFD, handle, toPoint, from->handle, fromPoint, 0)) { + Debug::log(ERR, "CSyncTimeline::transfer: drmSyncobjTransfer failed"); + return false; + } + + return true; +} diff --git a/src/helpers/sync/SyncTimeline.hpp b/src/helpers/sync/SyncTimeline.hpp new file mode 100644 index 00000000000..4bb8019b9f1 --- /dev/null +++ b/src/helpers/sync/SyncTimeline.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include +#include +#include +#include + +/* + Hyprland synchronization timelines are based on the wlroots' ones, which + are based on Vk timeline semaphores: https://www.khronos.org/blog/vulkan-timeline-semaphores +*/ + +struct wl_event_source; + +class CSyncTimeline { + public: + static SP create(int drmFD_); + static SP create(int drmFD_, int drmSyncobjFD); + ~CSyncTimeline(); + + struct SWaiter { + std::function fn; + wl_event_source* source = nullptr; + WP timeline; + }; + + // check if the timeline point has been signaled + // flags: DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT or DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE + // std::nullopt on fail + std::optional check(uint64_t point, uint32_t flags); + + bool addWaiter(const std::function& waiter, uint64_t point, uint32_t flags); + void removeWaiter(SWaiter*); + int exportAsSyncFileFD(uint64_t src); + bool importFromSyncFileFD(uint64_t dst, int fd); + bool transfer(SP from, uint64_t fromPoint, uint64_t toPoint); + + int drmFD = -1; + uint32_t handle = 0; + WP self; + + private: + CSyncTimeline() = default; + + std::vector> waiters; +}; diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 47cf1767ebb..db81e0aeb7a 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -36,6 +36,7 @@ #include "../protocols/MesaDRM.hpp" #include "../protocols/LinuxDMABUF.hpp" #include "../protocols/DRMLease.hpp" +#include "../protocols/DRMSyncobj.hpp" #include "../protocols/core/Seat.hpp" #include "../protocols/core/DataDevice.hpp" @@ -131,6 +132,7 @@ CProtocolManager::CProtocolManager() { PROTO::dataWlr = std::make_unique(&zwlr_data_control_manager_v1_interface, 2, "DataDeviceWlr"); PROTO::primarySelection = std::make_unique(&zwp_primary_selection_device_manager_v1_interface, 1, "PrimarySelection"); PROTO::xwaylandShell = std::make_unique(&xwayland_shell_v1_interface, 1, "XWaylandShell"); + PROTO::sync = std::make_unique(&wp_linux_drm_syncobj_manager_v1_interface, 1, "DRMSyncobj"); for (auto& b : g_pCompositor->m_pAqBackend->getImplementations()) { if (b->type() != Aquamarine::AQ_BACKEND_DRM) diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp index eff281d6edc..6f3e8529b7a 100644 --- a/src/managers/eventLoop/EventLoopManager.hpp +++ b/src/managers/eventLoop/EventLoopManager.hpp @@ -50,6 +50,8 @@ class CEventLoopManager { SIdleData m_sIdle; std::vector> aqPollFDs; + + friend class CSyncTimeline; }; inline std::unique_ptr g_pEventLoopManager; \ No newline at end of file diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp new file mode 100644 index 00000000000..69b9fae244b --- /dev/null +++ b/src/protocols/DRMSyncobj.cpp @@ -0,0 +1,182 @@ +#include "DRMSyncobj.hpp" +#include + +#include "core/Compositor.hpp" +#include "../helpers/sync/SyncTimeline.hpp" +#include "../Compositor.hpp" + +#include + +#define LOGM PROTO::sync->protoLog + +CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP resource_, SP surface_) : surface(surface_), resource(resource_) { + if (!good()) + return; + + resource->setData(this); + + resource->setOnDestroy([this](CWpLinuxDrmSyncobjSurfaceV1* r) { PROTO::sync->destroyResource(this); }); + resource->setDestroy([this](CWpLinuxDrmSyncobjSurfaceV1* r) { PROTO::sync->destroyResource(this); }); + + resource->setSetAcquirePoint([this](CWpLinuxDrmSyncobjSurfaceV1* r, wl_resource* timeline_, uint32_t hi, uint32_t lo) { + if (!surface) { + resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_SURFACE, "Surface is gone"); + return; + } + + auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_); + acquireTimeline = timeline; + acquirePoint = ((uint64_t)hi << 32) | (uint64_t)lo; + }); + + resource->setSetReleasePoint([this](CWpLinuxDrmSyncobjSurfaceV1* r, wl_resource* timeline_, uint32_t hi, uint32_t lo) { + if (!surface) { + resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_SURFACE, "Surface is gone"); + return; + } + + auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_); + releaseTimeline = timeline; + releasePoint = ((uint64_t)hi << 32) | (uint64_t)lo; + }); + + listeners.surfacePrecommit = surface->events.precommit.registerListener([this](std::any d) { + if (!!acquireTimeline != !!releaseTimeline) { + resource->error(acquireTimeline ? WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_RELEASE_POINT : WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_ACQUIRE_POINT, "Missing timeline"); + surface->pending.rejected = true; + return; + } + + if ((acquireTimeline || releaseTimeline) && !surface->pending.buffer) { + resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_BUFFER, "Missing buffer"); + surface->pending.rejected = true; + return; + } + + if (!acquireTimeline) + return; + + // wait for the acquire timeline to materialize + auto materialized = acquireTimeline->timeline->check(acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); + if (!materialized.has_value()) { + resource->noMemory(); + return; + } + + if (materialized) + return; + + surface->lockPendingState(); + acquireTimeline->timeline->addWaiter([this]() { surface->unlockPendingState(); }, acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); + }); +} + +bool CDRMSyncobjSurfaceResource::good() { + return resource->resource(); +} + +CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SP resource_, int fd_) : fd(fd_), resource(resource_) { + if (!good()) + return; + + resource->setData(this); + + resource->setOnDestroy([this](CWpLinuxDrmSyncobjTimelineV1* r) { PROTO::sync->destroyResource(this); }); + resource->setDestroy([this](CWpLinuxDrmSyncobjTimelineV1* r) { PROTO::sync->destroyResource(this); }); + + timeline = CSyncTimeline::create(PROTO::sync->drmFD, fd); + + if (!timeline) { + resource->error(WP_LINUX_DRM_SYNCOBJ_MANAGER_V1_ERROR_INVALID_TIMELINE, "Timeline failed importing"); + return; + } +} + +SP CDRMSyncobjTimelineResource::fromResource(wl_resource* res) { + auto data = (CDRMSyncobjTimelineResource*)(((CWpLinuxDrmSyncobjTimelineV1*)wl_resource_get_user_data(res))->data()); + return data ? data->self.lock() : nullptr; +} + +bool CDRMSyncobjTimelineResource::good() { + return resource->resource(); +} + +CDRMSyncobjManagerResource::CDRMSyncobjManagerResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setOnDestroy([this](CWpLinuxDrmSyncobjManagerV1* r) { PROTO::sync->destroyResource(this); }); + resource->setDestroy([this](CWpLinuxDrmSyncobjManagerV1* r) { PROTO::sync->destroyResource(this); }); + + resource->setGetSurface([this](CWpLinuxDrmSyncobjManagerV1* r, uint32_t id, wl_resource* surf) { + if (!surf) { + resource->error(-1, "Invalid surface"); + return; + } + + auto SURF = CWLSurfaceResource::fromResource(surf); + if (!SURF) { + resource->error(-1, "Invalid surface (2)"); + return; + } + + if (SURF->syncobj) { + resource->error(WP_LINUX_DRM_SYNCOBJ_MANAGER_V1_ERROR_SURFACE_EXISTS, "Surface already has a syncobj attached"); + return; + } + + auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), id), SURF); + if (!RESOURCE->good()) { + resource->noMemory(); + return; + } + + PROTO::sync->m_vSurfaces.emplace_back(RESOURCE); + SURF->syncobj = RESOURCE; + + LOGM(LOG, "New linux_syncobj at {:x} for surface {:x}", (uintptr_t)RESOURCE.get(), (uintptr_t)SURF.get()); + }); + + resource->setImportTimeline([this](CWpLinuxDrmSyncobjManagerV1* r, uint32_t id, int32_t fd) { + auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), id), fd); + if (!RESOURCE->good()) { + resource->noMemory(); + return; + } + + PROTO::sync->m_vTimelines.emplace_back(RESOURCE); + RESOURCE->self = RESOURCE; + + LOGM(LOG, "New linux_drm_timeline at {:x}", (uintptr_t)RESOURCE.get()); + }); +} + +bool CDRMSyncobjManagerResource::good() { + return resource->resource(); +} + +CDRMSyncobjProtocol::CDRMSyncobjProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + drmFD = fcntl(g_pCompositor->m_iDRMFD, F_DUPFD_CLOEXEC, 0); +} + +void CDRMSyncobjProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } +} + +void CDRMSyncobjProtocol::destroyResource(CDRMSyncobjManagerResource* resource) { + std::erase_if(m_vManagers, [resource](const auto& e) { return e.get() == resource; }); +} + +void CDRMSyncobjProtocol::destroyResource(CDRMSyncobjTimelineResource* resource) { + std::erase_if(m_vTimelines, [resource](const auto& e) { return e.get() == resource; }); +} + +void CDRMSyncobjProtocol::destroyResource(CDRMSyncobjSurfaceResource* resource) { + std::erase_if(m_vSurfaces, [resource](const auto& e) { return e.get() == resource; }); +} diff --git a/src/protocols/DRMSyncobj.hpp b/src/protocols/DRMSyncobj.hpp new file mode 100644 index 00000000000..c1c884fff66 --- /dev/null +++ b/src/protocols/DRMSyncobj.hpp @@ -0,0 +1,82 @@ +#pragma once + +#include +#include +#include "WaylandProtocol.hpp" +#include "linux-drm-syncobj-v1.hpp" +#include "../helpers/signal/Signal.hpp" + +class CWLSurfaceResource; +class CDRMSyncobjTimelineResource; +class CSyncTimeline; + +class CDRMSyncobjSurfaceResource { + public: + CDRMSyncobjSurfaceResource(SP resource_, SP surface_); + + bool good(); + + WP surface; + WP acquireTimeline, releaseTimeline; + uint64_t acquirePoint = 0, releasePoint = 0; + + private: + SP resource; + + struct { + CHyprSignalListener surfacePrecommit; + } listeners; +}; + +class CDRMSyncobjTimelineResource { + public: + CDRMSyncobjTimelineResource(SP resource_, int fd_); + static SP fromResource(wl_resource*); + + bool good(); + + WP self; + int fd = -1; + SP timeline; + + private: + SP resource; +}; + +class CDRMSyncobjManagerResource { + public: + CDRMSyncobjManagerResource(SP resource_); + + bool good(); + + private: + SP resource; +}; + +class CDRMSyncobjProtocol : public IWaylandProtocol { + public: + CDRMSyncobjProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + private: + void destroyResource(CDRMSyncobjManagerResource* resource); + void destroyResource(CDRMSyncobjTimelineResource* resource); + void destroyResource(CDRMSyncobjSurfaceResource* resource); + + // + std::vector> m_vManagers; + std::vector> m_vTimelines; + std::vector> m_vSurfaces; + + // + int drmFD = -1; + + friend class CDRMSyncobjManagerResource; + friend class CDRMSyncobjTimelineResource; + friend class CDRMSyncobjSurfaceResource; +}; + +namespace PROTO { + inline UP sync; +}; diff --git a/src/protocols/Viewporter.cpp b/src/protocols/Viewporter.cpp index 8cb69dbe388..7fa45e69b09 100644 --- a/src/protocols/Viewporter.cpp +++ b/src/protocols/Viewporter.cpp @@ -52,6 +52,21 @@ CViewportResource::CViewportResource(SP resource_, SPpending.viewport.hasSource = true; surface->pending.viewport.source = {x, y, w, h}; }); + + listeners.surfacePrecommit = surface->events.precommit.registerListener([this](std::any d) { + if (!surface) + return; + + if (surface->pending.viewport.hasSource) { + auto& src = surface->pending.viewport.source; + + if (src.w + src.x > surface->pending.size.x || src.h + src.y > surface->pending.size.y) { + resource->error(WP_VIEWPORT_ERROR_BAD_VALUE, "Box doesn't fit"); + surface->pending.rejected = true; + return; + } + } + }); } CViewportResource::~CViewportResource() { @@ -66,20 +81,6 @@ bool CViewportResource::good() { return resource->resource(); } -void CViewportResource::verify() { - if (!surface) - return; - - if (surface->pending.viewport.hasSource) { - auto& src = surface->pending.viewport.source; - - if (src.w + src.x > surface->pending.size.x || src.h + src.y > surface->pending.size.y) { - resource->error(WP_VIEWPORT_ERROR_BAD_VALUE, "Box doesn't fit"); - return; - } - } -} - CViewporterResource::CViewporterResource(SP resource_) : resource(resource_) { if (!good()) return; diff --git a/src/protocols/Viewporter.hpp b/src/protocols/Viewporter.hpp index 012782036a0..fd0da88e1e5 100644 --- a/src/protocols/Viewporter.hpp +++ b/src/protocols/Viewporter.hpp @@ -15,11 +15,14 @@ class CViewportResource { ~CViewportResource(); bool good(); - void verify(); WP surface; private: SP resource; + + struct { + CHyprSignalListener surfacePrecommit; + } listeners; }; class CViewporterResource { diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 5f016918ac1..165f365cd62 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -6,6 +6,8 @@ #include "Subcompositor.hpp" #include "../Viewporter.hpp" #include "../../helpers/Monitor.hpp" +#include "../PresentationTime.hpp" +#include "../DRMSyncobj.hpp" #define LOGM PROTO::compositor->protoLog @@ -102,58 +104,14 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : resource(reso pending.size = tfs / pending.scale; } - if (viewportResource) - viewportResource->verify(); - pending.damage.intersect(CBox{{}, pending.size}); - auto previousBuffer = current.buffer; - CRegion previousBufferDamage = accumulateCurrentBufferDamage(); - - current = pending; - pending.damage.clear(); - pending.bufferDamage.clear(); - - if (current.buffer && !bufferReleased) { - // without previous dolphin et al are weird vvv - //CRegion surfaceDamage = - // current.damage.copy().scale(current.scale).transform(current.transform, current.size.x, current.size.y).add(current.bufferDamage).add(previousBufferDamage); - current.buffer->update(CBox{{}, {INT32_MAX, INT32_MAX}}); // FIXME: figure this out to not use this hack. QT apps are wonky without this. - - // release the buffer if it's synchronous as update() has done everything thats needed - // so we can let the app know we're done. - if (current.buffer->isSynchronous()) { - current.buffer->sendRelease(); - bufferReleased = true; - } - } - - // TODO: we should _accumulate_ and not replace above if sync - if (role->role() == SURFACE_ROLE_SUBSURFACE) { - auto subsurface = (CWLSubsurfaceResource*)role.get(); - if (subsurface->sync) - return; - - events.commit.emit(); - } else { - // send commit to all synced surfaces in this tree. - breadthfirst( - [](SP surf, const Vector2D& offset, void* data) { - if (surf->role->role() == SURFACE_ROLE_SUBSURFACE) { - auto subsurface = (CWLSubsurfaceResource*)surf->role.get(); - if (!subsurface->sync) - return; - } - surf->events.commit.emit(); - }, - nullptr); - } + events.precommit.emit(); + if (pending.rejected) + return; - // for async buffers, we can only release the buffer once we are unrefing it from current. - if (previousBuffer && !previousBuffer->isSynchronous() && !bufferReleased) { - previousBuffer->sendRelease(); - bufferReleased = true; - } + if (stateLocks <= 0) + commitPendingState(); }); resource->setDamage([this](CWlSurface* r, int32_t x, int32_t y, int32_t w, int32_t h) { pending.damage.add(CBox{x, y, w, h}); }); @@ -429,6 +387,83 @@ CRegion CWLSurfaceResource::accumulateCurrentBufferDamage() { return surfaceDamage.scale(current.scale).transform(wlTransformToHyprutils(invertTransform(current.transform)), trc.x, trc.y).add(current.bufferDamage); } +void CWLSurfaceResource::lockPendingState() { + stateLocks++; +} + +void CWLSurfaceResource::unlockPendingState() { + stateLocks--; + if (stateLocks <= 0) + commitPendingState(); +} + +void CWLSurfaceResource::commitPendingState() { + auto previousBuffer = current.buffer; + CRegion previousBufferDamage = accumulateCurrentBufferDamage(); + + current = pending; + pending.damage.clear(); + pending.bufferDamage.clear(); + + if (current.buffer && !bufferReleased) { + // without previous dolphin et al are weird vvv + //CRegion surfaceDamage = + // current.damage.copy().scale(current.scale).transform(current.transform, current.size.x, current.size.y).add(current.bufferDamage).add(previousBufferDamage); + current.buffer->update(CBox{{}, {INT32_MAX, INT32_MAX}}); // FIXME: figure this out to not use this hack. QT apps are wonky without this. + + // release the buffer if it's synchronous as update() has done everything thats needed + // so we can let the app know we're done. + if (current.buffer->isSynchronous()) { + current.buffer->sendRelease(); + bufferReleased = true; + } + } + + // TODO: we should _accumulate_ and not replace above if sync + if (role->role() == SURFACE_ROLE_SUBSURFACE) { + auto subsurface = (CWLSubsurfaceResource*)role.get(); + if (subsurface->sync) + return; + + events.commit.emit(); + } else { + // send commit to all synced surfaces in this tree. + breadthfirst( + [](SP surf, const Vector2D& offset, void* data) { + if (surf->role->role() == SURFACE_ROLE_SUBSURFACE) { + auto subsurface = (CWLSubsurfaceResource*)surf->role.get(); + if (!subsurface->sync) + return; + } + surf->events.commit.emit(); + }, + nullptr); + } + + // for async buffers, we can only release the buffer once we are unrefing it from current. + if (previousBuffer && !previousBuffer->isSynchronous() && !bufferReleased) { + previousBuffer->sendRelease(); + bufferReleased = true; + } +} + +void CWLSurfaceResource::presentFeedback(timespec* when, CMonitor* pMonitor) { + frame(when); + auto FEEDBACK = makeShared(self.lock()); + FEEDBACK->attachMonitor(pMonitor); + FEEDBACK->discarded(); + PROTO::presentation->queueData(FEEDBACK); + + if (!pMonitor || !pMonitor->outTimeline || !syncobj) + return; + + // attach explicit sync + g_pHyprRenderer->explicitPresented.emplace_back(self.lock()); + + if (syncobj->acquirePoint > pMonitor->lastWaitPoint) + pMonitor->lastWaitPoint = syncobj->acquirePoint; +} + CWLCompositorResource::CWLCompositorResource(SP resource_) : resource(resource_) { if (!good()) return; diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index a232ac3062a..0d85a5c9ed6 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -24,6 +24,7 @@ class CWLSurface; class CWLSurfaceResource; class CWLSubsurfaceResource; class CViewportResource; +class CDRMSyncobjSurfaceResource; class CWLCallbackResource { public: @@ -74,6 +75,7 @@ class CWLSurfaceResource { Vector2D sourceSize(); struct { + CSignal precommit; CSignal commit; CSignal map; CSignal unmap; @@ -81,7 +83,7 @@ class CWLSurfaceResource { CSignal destroy; } events; - struct { + struct SState { CRegion opaque, input = CBox{{}, {INT32_MAX, INT32_MAX}}, damage, bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}} /* initial damage */; wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; int scale = 1; @@ -95,6 +97,7 @@ class CWLSurfaceResource { Vector2D destination; CBox source; } viewport; + bool rejected = false; // void reset() { @@ -115,9 +118,13 @@ class CWLSurfaceResource { std::vector> subsurfaces; WP role; WP viewportResource; + WP syncobj; // may not be present void breadthfirst(std::function, const Vector2D&, void*)> fn, void* data); CRegion accumulateCurrentBufferDamage(); + void presentFeedback(timespec* when, CMonitor* pMonitor); + void lockPendingState(); + void unlockPendingState(); // returns a pair: found surface (null if not found) and surface local coords. // localCoords param is relative to 0,0 of this surface @@ -130,7 +137,10 @@ class CWLSurfaceResource { // tracks whether we should release the buffer bool bufferReleased = false; + int stateLocks = 0; + void destroy(); + void commitPendingState(); void bfHelper(std::vector> nodes, std::function, const Vector2D&, void*)> fn, void* data); }; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 467c83f4dbf..adc45f2cdc2 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -171,6 +171,14 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() { loadGLProc(&m_sProc.glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES"); loadGLProc(&m_sProc.eglDebugMessageControlKHR, "eglDebugMessageControlKHR"); loadGLProc(&m_sProc.eglGetPlatformDisplayEXT, "eglGetPlatformDisplayEXT"); + loadGLProc(&m_sProc.eglCreateSyncKHR, "eglCreateSyncKHR"); + loadGLProc(&m_sProc.eglDestroySyncKHR, "eglDestroySyncKHR"); + loadGLProc(&m_sProc.eglDupNativeFenceFDANDROID, "eglDupNativeFenceFDANDROID"); + loadGLProc(&m_sProc.eglWaitSyncKHR, "eglWaitSyncKHR"); + + RASSERT(m_sProc.eglCreateSyncKHR, "Display driver doesn't support eglCreateSyncKHR"); + RASSERT(m_sProc.eglDupNativeFenceFDANDROID, "Display driver doesn't support eglDupNativeFenceFDANDROID"); + RASSERT(m_sProc.eglWaitSyncKHR, "Display driver doesn't support eglWaitSyncKHR"); if (EGLEXTENSIONS.contains("EGL_EXT_device_base") || EGLEXTENSIONS.contains("EGL_EXT_device_enumeration")) loadGLProc(&m_sProc.eglQueryDevicesEXT, "eglQueryDevicesEXT"); @@ -2727,6 +2735,30 @@ std::vector CHyprOpenGLImpl::getDRMFormats() { return drmFormats; } +SP CHyprOpenGLImpl::createEGLSync(int fenceFD) { + std::vector attribs; + int dupFd = fcntl(fenceFD, F_DUPFD_CLOEXEC, 0); + if (dupFd < 0) { + Debug::log(ERR, "createEGLSync: dup failed"); + return nullptr; + } + + attribs.push_back(EGL_SYNC_NATIVE_FENCE_FD_ANDROID); + attribs.push_back(dupFd); + attribs.push_back(EGL_NONE); + + EGLSyncKHR sync = m_sProc.eglCreateSyncKHR(m_pEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs.data()); + if (sync == EGL_NO_SYNC_KHR) { + Debug::log(ERR, "eglCreateSyncKHR failed"); + close(dupFd); + return nullptr; + } + + auto eglsync = SP(new CEGLSync); + eglsync->sync = sync; + return eglsync; +} + void SRenderModifData::applyToBox(CBox& box) { if (!enabled) return; @@ -2787,3 +2819,35 @@ float SRenderModifData::combinedScale() { } return scale; } + +CEGLSync::~CEGLSync() { + if (sync == EGL_NO_SYNC_KHR) + return; + + if (g_pHyprOpenGL->m_sProc.eglDestroySyncKHR(g_pHyprOpenGL->m_pEglDisplay, sync) != EGL_TRUE) + Debug::log(ERR, "eglDestroySyncKHR failed"); +} + +int CEGLSync::dupFenceFD() { + if (sync == EGL_NO_SYNC_KHR) + return -1; + + int fd = g_pHyprOpenGL->m_sProc.eglDupNativeFenceFDANDROID(g_pHyprOpenGL->m_pEglDisplay, sync); + if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { + Debug::log(ERR, "eglDupNativeFenceFDANDROID failed"); + return -1; + } + + return fd; +} + +bool CEGLSync::wait() { + if (sync == EGL_NO_SYNC_KHR) + return false; + + if (g_pHyprOpenGL->m_sProc.eglWaitSyncKHR(g_pHyprOpenGL->m_pEglDisplay, sync, 0) != EGL_TRUE) { + Debug::log(ERR, "eglWaitSyncKHR failed"); + return false; + } + return true; +} diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 9696c2ccb69..4c972a8f76b 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -123,6 +123,21 @@ struct SCurrentRenderData { float discardOpacity = 0.f; }; +class CEGLSync { + public: + ~CEGLSync(); + + EGLSyncKHR sync = nullptr; + + int dupFenceFD(); + bool wait(); + + private: + CEGLSync() = default; + + friend class CHyprOpenGLImpl; +}; + class CGradientValueData; class CHyprOpenGLImpl { @@ -187,6 +202,7 @@ class CHyprOpenGLImpl { uint32_t getPreferredReadFormat(CMonitor* pMonitor); std::vector getDRMFormats(); EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); + SP createEGLSync(int fenceFD); SCurrentRenderData m_RenderData; @@ -219,6 +235,10 @@ class CHyprOpenGLImpl { PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT = nullptr; PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT = nullptr; PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT = nullptr; + PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR = nullptr; + PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR = nullptr; + PFNEGLDUPNATIVEFENCEFDANDROIDPROC eglDupNativeFenceFDANDROID = nullptr; + PFNEGLWAITSYNCKHRPROC eglWaitSyncKHR = nullptr; } m_sProc; struct { diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index ac6fd8c1e0c..01429573752 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -14,6 +14,8 @@ #include "../protocols/PresentationTime.hpp" #include "../protocols/core/DataDevice.hpp" #include "../protocols/core/Compositor.hpp" +#include "../protocols/DRMSyncobj.hpp" +#include "../helpers/sync/SyncTimeline.hpp" extern "C" { #include @@ -109,6 +111,27 @@ static void renderSurface(SP surface, int x, int y, void* da if (!TEXTURE->m_iTexID) return; + // explicit sync: wait for the timeline, if any + if (surface->syncobj) { + int fd = surface->syncobj->acquireTimeline->timeline->exportAsSyncFileFD(surface->syncobj->acquirePoint); + if (fd < 0) { + Debug::log(ERR, "Renderer: failed to get a fd from explicit timeline"); + return; + } + + auto sync = g_pHyprOpenGL->createEGLSync(fd); + close(fd); + if (!sync) { + Debug::log(ERR, "Renderer: failed to get an eglsync from explicit timeline"); + return; + } + + if (!sync->wait()) { + Debug::log(ERR, "Renderer: failed to wait on an eglsync from explicit timeline"); + return; + } + } + TRACY_GPU_ZONE("RenderSurface"); double outputX = -RDATA->pMonitor->vecPosition.x, outputY = -RDATA->pMonitor->vecPosition.y; @@ -167,13 +190,9 @@ static void renderSurface(SP surface, int x, int y, void* da } if (windowBox.width <= 1 || windowBox.height <= 1) { - if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { - surface->frame(RDATA->when); - auto FEEDBACK = makeShared(surface); - FEEDBACK->attachMonitor(RDATA->pMonitor); - FEEDBACK->discarded(); - PROTO::presentation->queueData(FEEDBACK); - } + if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) + surface->presentFeedback(RDATA->when, RDATA->pMonitor); + return; // invisible } @@ -225,13 +244,8 @@ static void renderSurface(SP surface, int x, int y, void* da g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, false, true); } - if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { - surface->frame(RDATA->when); - auto FEEDBACK = makeShared(surface); - FEEDBACK->attachMonitor(RDATA->pMonitor); - FEEDBACK->presented(); - PROTO::presentation->queueData(FEEDBACK); - } + if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) + surface->presentFeedback(RDATA->when, RDATA->pMonitor); g_pHyprOpenGL->blend(true); @@ -1111,12 +1125,7 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - PSURFACE->frame(&now); - auto FEEDBACK = makeShared(PSURFACE); - FEEDBACK->attachMonitor(pMonitor); - FEEDBACK->presented(); - FEEDBACK->setPresentationType(true); - PROTO::presentation->queueData(FEEDBACK); + PSURFACE->presentFeedback(&now, pMonitor); if (pMonitor->state.commit()) { if (m_pLastScanout.expired()) { @@ -1421,6 +1430,18 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { pMonitor->output->state->setPresentationMode(shouldTear ? Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_IMMEDIATE : Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC); + // apply timelines for explicit sync + pMonitor->output->state->setExplicitInFence(pMonitor->inTimeline->exportAsSyncFileFD(pMonitor->lastWaitPoint)); + + for (auto& e : explicitPresented) { + e->syncobj->releaseTimeline->timeline->transfer(pMonitor->outTimeline, pMonitor->commitSeq, e->syncobj->releasePoint); + } + + pMonitor->lastWaitPoint = 0; + explicitPresented.clear(); + pMonitor->output->state->setExplicitOutFence(pMonitor->outTimeline->exportAsSyncFileFD(pMonitor->commitSeq)); + pMonitor->commitSeq++; + if (!pMonitor->state.commit()) { // rollback the buffer to avoid writing to the front buffer that is being // displayed diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index ce37f51b24f..b15ba04bb4b 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -99,6 +99,8 @@ class CHyprRenderer { CTimer m_tRenderTimer; + std::vector> explicitPresented; + struct { int hotspotX; int hotspotY; From 09af47a4f47a1036ef29f92f6f3ea9a2f7eec9f4 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 6 Jul 2024 17:40:39 +0200 Subject: [PATCH 053/113] cursorsss --- src/managers/PointerManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index e7c5b42b441..02712b8b376 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -455,7 +455,7 @@ void CPointerManager::renderSoftwareCursorsFor(SP pMonitor, timespec* Vector2D CPointerManager::getCursorPosForMonitor(SP 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; } From e09e76aa4a62fe726946b5819639794ad7a64083 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 6 Jul 2024 17:42:45 +0200 Subject: [PATCH 054/113] avoid spam --- src/render/Renderer.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 01429573752..49ac344f60e 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1431,15 +1431,19 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC); // apply timelines for explicit sync - pMonitor->output->state->setExplicitInFence(pMonitor->inTimeline->exportAsSyncFileFD(pMonitor->lastWaitPoint)); + bool anyExplicit = !explicitPresented.empty(); + if (anyExplicit) { + pMonitor->output->state->setExplicitInFence(pMonitor->inTimeline->exportAsSyncFileFD(pMonitor->lastWaitPoint)); - for (auto& e : explicitPresented) { - e->syncobj->releaseTimeline->timeline->transfer(pMonitor->outTimeline, pMonitor->commitSeq, e->syncobj->releasePoint); + for (auto& e : explicitPresented) { + e->syncobj->releaseTimeline->timeline->transfer(pMonitor->outTimeline, pMonitor->commitSeq, e->syncobj->releasePoint); + } + + explicitPresented.clear(); + pMonitor->output->state->setExplicitOutFence(pMonitor->outTimeline->exportAsSyncFileFD(pMonitor->commitSeq)); } pMonitor->lastWaitPoint = 0; - explicitPresented.clear(); - pMonitor->output->state->setExplicitOutFence(pMonitor->outTimeline->exportAsSyncFileFD(pMonitor->commitSeq)); pMonitor->commitSeq++; if (!pMonitor->state.commit()) { From 2fd901321e48e1673e52a02e509553efe2716026 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 6 Jul 2024 18:11:31 +0200 Subject: [PATCH 055/113] dont crash on multigpu lol --- src/helpers/Monitor.cpp | 4 ++-- src/helpers/sync/SyncTimeline.cpp | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 495e772e2f8..e62db7183f7 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -31,8 +31,8 @@ CMonitor::~CMonitor() { void CMonitor::onConnect(bool noRule) { if (output->supportsExplicit) { - inTimeline = CSyncTimeline::create(g_pCompositor->m_iDRMFD); - outTimeline = CSyncTimeline::create(g_pCompositor->m_iDRMFD); + inTimeline = CSyncTimeline::create(output->getBackend()->drmFD()); + outTimeline = CSyncTimeline::create(output->getBackend()->drmFD()); } listeners.frame = output->events.frame.registerListener([this](std::any d) { Events::listener_monitorFrame(this, nullptr); }); diff --git a/src/helpers/sync/SyncTimeline.cpp b/src/helpers/sync/SyncTimeline.cpp index 1a7286e00f0..d3c1b4161f6 100644 --- a/src/helpers/sync/SyncTimeline.cpp +++ b/src/helpers/sync/SyncTimeline.cpp @@ -176,7 +176,10 @@ bool CSyncTimeline::importFromSyncFileFD(uint64_t dst, int fd) { } bool CSyncTimeline::transfer(SP from, uint64_t fromPoint, uint64_t toPoint) { - ASSERT(from->drmFD == drmFD); + if (drmFD != from->drmFD) { + Debug::log(ERR, "CSyncTimeline::transfer: cannot transfer timelines between gpus"); + return false; + } if (drmSyncobjTransfer(drmFD, handle, toPoint, from->handle, fromPoint, 0)) { Debug::log(ERR, "CSyncTimeline::transfer: drmSyncobjTransfer failed"); From 1b4a5fc4fc1f37060c15a2a28439379557df71c8 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 6 Jul 2024 18:34:39 +0200 Subject: [PATCH 056/113] stuf --- src/config/ConfigManager.cpp | 2 ++ src/managers/ProtocolManager.cpp | 7 ++++++- src/protocols/DRMSyncobj.cpp | 1 + src/render/Renderer.cpp | 2 ++ 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index af1608f9b70..56025bc1b87 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -556,6 +556,8 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:groupbar:col.inactive", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0x66777700"}); m_pConfig->addConfigValue("group:groupbar:col.locked_active", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0x66ff5500"}); m_pConfig->addConfigValue("group:groupbar:col.locked_inactive", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0x66775500"}); + + m_pConfig->addConfigValue("experimental:explicit_sync", Hyprlang::INT{0}); // devices m_pConfig->addSpecialCategory("device", {"name"}); diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index db81e0aeb7a..3006468f581 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -1,5 +1,7 @@ #include "ProtocolManager.hpp" +#include "../config/ConfigValue.hpp" + #include "../protocols/TearingControl.hpp" #include "../protocols/FractionalScale.hpp" #include "../protocols/XDGOutput.hpp" @@ -67,6 +69,8 @@ void CProtocolManager::onMonitorModeChange(CMonitor* pMonitor) { CProtocolManager::CProtocolManager() { + static const auto PENABLEEXPLICIT = CConfigValue("experimental:explicit_sync"); + // Outputs are a bit dumb, we have to agree. static auto P = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) { auto M = std::any_cast(param); @@ -132,13 +136,14 @@ CProtocolManager::CProtocolManager() { PROTO::dataWlr = std::make_unique(&zwlr_data_control_manager_v1_interface, 2, "DataDeviceWlr"); PROTO::primarySelection = std::make_unique(&zwp_primary_selection_device_manager_v1_interface, 1, "PrimarySelection"); PROTO::xwaylandShell = std::make_unique(&xwayland_shell_v1_interface, 1, "XWaylandShell"); - PROTO::sync = std::make_unique(&wp_linux_drm_syncobj_manager_v1_interface, 1, "DRMSyncobj"); for (auto& b : g_pCompositor->m_pAqBackend->getImplementations()) { if (b->type() != Aquamarine::AQ_BACKEND_DRM) continue; PROTO::lease = std::make_unique(&wp_drm_lease_device_v1_interface, 1, "DRMLease"); + if (*PENABLEEXPLICIT) + PROTO::sync = std::make_unique(&wp_linux_drm_syncobj_manager_v1_interface, 1, "DRMSyncobj"); break; } diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp index 69b9fae244b..b8ab086a456 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp @@ -59,6 +59,7 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SPtimeline->check(acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); if (!materialized.has_value()) { + LOGM(ERR, "Failed to check the acquire timeline"); resource->noMemory(); return; } diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 49ac344f60e..b0483f7b19a 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1436,6 +1436,8 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { pMonitor->output->state->setExplicitInFence(pMonitor->inTimeline->exportAsSyncFileFD(pMonitor->lastWaitPoint)); for (auto& e : explicitPresented) { + if (!e->syncobj || !e->syncobj->releaseTimeline) + continue; e->syncobj->releaseTimeline->timeline->transfer(pMonitor->outTimeline, pMonitor->commitSeq, e->syncobj->releasePoint); } From e36c1e9bfab041e0cad104d77e187953d27afdc9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 6 Jul 2024 18:37:43 +0200 Subject: [PATCH 057/113] log mismatched fds --- src/helpers/sync/SyncTimeline.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/sync/SyncTimeline.cpp b/src/helpers/sync/SyncTimeline.cpp index d3c1b4161f6..eee2237f0cc 100644 --- a/src/helpers/sync/SyncTimeline.cpp +++ b/src/helpers/sync/SyncTimeline.cpp @@ -177,7 +177,7 @@ bool CSyncTimeline::importFromSyncFileFD(uint64_t dst, int fd) { bool CSyncTimeline::transfer(SP from, uint64_t fromPoint, uint64_t toPoint) { if (drmFD != from->drmFD) { - Debug::log(ERR, "CSyncTimeline::transfer: cannot transfer timelines between gpus"); + Debug::log(ERR, "CSyncTimeline::transfer: cannot transfer timelines between gpus, {} -> {}", from->drmFD, drmFD); return false; } From c9fdf622b6f3a45cb0f18479213cf0de53d8a594 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 6 Jul 2024 19:09:20 +0200 Subject: [PATCH 058/113] fixes --- src/protocols/DRMSyncobj.cpp | 2 +- src/protocols/core/Compositor.cpp | 4 ++-- src/protocols/types/Buffer.cpp | 4 ++++ src/protocols/types/Buffer.hpp | 1 + src/protocols/types/WLBuffer.cpp | 14 ++++++++++++++ src/protocols/types/WLBuffer.hpp | 2 ++ 6 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp index b8ab086a456..41178109d8d 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp @@ -157,7 +157,7 @@ bool CDRMSyncobjManagerResource::good() { } CDRMSyncobjProtocol::CDRMSyncobjProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { - drmFD = fcntl(g_pCompositor->m_iDRMFD, F_DUPFD_CLOEXEC, 0); + drmFD = g_pCompositor->m_iDRMFD; } void CDRMSyncobjProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 165f365cd62..c9095e03c6a 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -414,7 +414,7 @@ void CWLSurfaceResource::commitPendingState() { // release the buffer if it's synchronous as update() has done everything thats needed // so we can let the app know we're done. if (current.buffer->isSynchronous()) { - current.buffer->sendRelease(); + current.buffer->sendReleaseWithSurface(self.lock()); bufferReleased = true; } } @@ -442,7 +442,7 @@ void CWLSurfaceResource::commitPendingState() { // for async buffers, we can only release the buffer once we are unrefing it from current. if (previousBuffer && !previousBuffer->isSynchronous() && !bufferReleased) { - previousBuffer->sendRelease(); + previousBuffer->sendReleaseWithSurface(self.lock()); bufferReleased = true; } } diff --git a/src/protocols/types/Buffer.cpp b/src/protocols/types/Buffer.cpp index 23679ce7ed4..a347a0fc9bd 100644 --- a/src/protocols/types/Buffer.cpp +++ b/src/protocols/types/Buffer.cpp @@ -3,3 +3,7 @@ void IHLBuffer::sendRelease() { resource->sendRelease(); } + +void IHLBuffer::sendReleaseWithSurface(SP surf) { + resource->sendReleaseWithSurface(surf); +} diff --git a/src/protocols/types/Buffer.hpp b/src/protocols/types/Buffer.hpp index 0b377bb377c..2ae542d1bf3 100644 --- a/src/protocols/types/Buffer.hpp +++ b/src/protocols/types/Buffer.hpp @@ -17,6 +17,7 @@ class IHLBuffer : public Aquamarine::IBuffer { virtual bool isSynchronous() = 0; // whether the updates to this buffer are synchronous, aka happen over cpu virtual bool good() = 0; virtual void sendRelease(); + virtual void sendReleaseWithSurface(SP); SP texture; bool opaque = false; diff --git a/src/protocols/types/WLBuffer.cpp b/src/protocols/types/WLBuffer.cpp index e53538cbc05..7034dfc78b8 100644 --- a/src/protocols/types/WLBuffer.cpp +++ b/src/protocols/types/WLBuffer.cpp @@ -1,5 +1,9 @@ #include "WLBuffer.hpp" #include "Buffer.hpp" +#include "../core/Compositor.hpp" +#include "../DRMSyncobj.hpp" +#include "../../helpers/sync/SyncTimeline.hpp" +#include CWLBufferResource::CWLBufferResource(SP resource_) : resource(resource_) { if (!good()) @@ -27,6 +31,16 @@ void CWLBufferResource::sendRelease() { resource->sendRelease(); } +void CWLBufferResource::sendReleaseWithSurface(SP surf) { + sendRelease(); + + if (!surf->syncobj) + return; + + if (drmSyncobjTimelineSignal(g_pCompositor->m_iDRMFD, &surf->syncobj->releaseTimeline->timeline->handle, &surf->syncobj->releasePoint, 1)) + Debug::log(ERR, "sendReleaseWithSurface: drmSyncobjTimelineSignal failed"); +} + wl_resource* CWLBufferResource::getResource() { return resource->resource(); } diff --git a/src/protocols/types/WLBuffer.hpp b/src/protocols/types/WLBuffer.hpp index 83d042cd77a..595121283f3 100644 --- a/src/protocols/types/WLBuffer.hpp +++ b/src/protocols/types/WLBuffer.hpp @@ -8,6 +8,7 @@ #include "../../helpers/signal/Signal.hpp" class IHLBuffer; +class CWLSurfaceResource; class CWLBufferResource { public: @@ -16,6 +17,7 @@ class CWLBufferResource { bool good(); void sendRelease(); + void sendReleaseWithSurface(SP); wl_resource* getResource(); WP buffer; From ab428222c2f3dc4b1773acd162c4933a5e41b7f9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 6 Jul 2024 19:28:57 +0200 Subject: [PATCH 059/113] fix crasheroni --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index b0483f7b19a..45e058fe63e 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -112,7 +112,7 @@ static void renderSurface(SP surface, int x, int y, void* da return; // explicit sync: wait for the timeline, if any - if (surface->syncobj) { + if (surface->syncobj && surface->syncobj->acquireTimeline) { int fd = surface->syncobj->acquireTimeline->timeline->exportAsSyncFileFD(surface->syncobj->acquirePoint); if (fd < 0) { Debug::log(ERR, "Renderer: failed to get a fd from explicit timeline"); From 1a1cc59c5f9272190c75104283c22eebe439f04d Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 7 Jul 2024 16:26:59 +0300 Subject: [PATCH 060/113] flake.lock: update aquamarine --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 84095f56c73..8612554ab23 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1720028623, - "narHash": "sha256-8TR1sSZlFnA5kxj9oyx9pm7h8kzgM8/VIBhA+sTJIjo=", + "lastModified": 1720357840, + "narHash": "sha256-afisBv6SIInBL6q2Os6wlJRiZbYxw6tCUqVwab1cHBk=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "1844da3814bd97afd3c3f4c4d6c5e318e3552247", + "rev": "946c75641414102b5c0aec4b1c27a4bff83fe442", "type": "github" }, "original": { From 8cf770b7be9a603db4b32847c1a9670389946294 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Sun, 7 Jul 2024 05:48:56 +0200 Subject: [PATCH 061/113] meson: unbreak build with aquamarine In file included from ../src/protocols/DRMLease.cpp:1: ../src/protocols/DRMLease.hpp:7:10: fatal error: 'drm-lease-v1.hpp' file not found 7 | #include "drm-lease-v1.hpp" | ^~~~~~~~~~~~~~~~~~ In file included from ../src/render/Renderer.cpp:17: ../src/render/../protocols/DRMSyncobj.hpp:6:10: fatal error: 'linux-drm-syncobj-v1.hpp' file not found 6 | #include "linux-drm-syncobj-v1.hpp" | ^~~~~~~~~~~~~~~~~~~~~~~~~~ ld: error: undefined symbol: Aquamarine::CBackend::hasSession() >>> referenced by Renderer.cpp >>> src/Hyprland.p/render_Renderer.cpp.o:(CHyprRenderer::CHyprRenderer()) >>> referenced by KeybindManager.cpp >>> src/Hyprland.p/managers_KeybindManager.cpp.o:(CKeybindManager::handleVT(unsigned int)) >>> referenced by Monitors.cpp >>> src/Hyprland.p/events_Monitors.cpp.o:(Events::listener_monitorFrame(void*, void*)) >>> referenced 8 more times ld: error: undefined symbol: gbm_create_device >>> referenced by OpenGL.cpp >>> src/Hyprland.p/render_OpenGL.cpp.o:(CHyprOpenGLImpl::CHyprOpenGLImpl()) ld: error: undefined symbol: XcursorShapeLoadImage >>> referenced by CursorManager.cpp >>> src/Hyprland.p/managers_CursorManager.cpp.o:(CCursorManager::SXCursorManager::loadTheme(std::__1::basic_string, std::__1::allocator> const&, int)) >>> referenced by CursorManager.cpp >>> src/Hyprland.p/managers_CursorManager.cpp.o:(CCursorManager::SXCursorManager::loadTheme(std::__1::basic_string, std::__1::allocator> const&, int)) >>> referenced by CursorManager.cpp >>> src/Hyprland.p/managers_CursorManager.cpp.o:(CCursorManager::SXCursorManager::loadTheme(std::__1::basic_string, std::__1::allocator> const&, int)) --- meson.build | 11 ++--------- protocols/meson.build | 2 ++ src/meson.build | 5 +++-- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/meson.build b/meson.build index 49c48c6ce72..b8101f6c040 100644 --- a/meson.build +++ b/meson.build @@ -24,8 +24,6 @@ if cpp_compiler.check_header('execinfo.h') add_project_arguments('-DHAS_EXECINFO', language: 'cpp') endif -wlroots = subproject('wlroots-hyprland', default_options: ['examples=false', 'renderers=gles2']) -have_xwlr = wlroots.get_variable('features').get('xwayland') xcb_dep = dependency('xcb', required: get_option('xwayland')) xcb_composite_dep = dependency('xcb-composite', required: get_option('xwayland')) xcb_errors_dep = dependency('xcb-errors', required: get_option('xwayland')) @@ -38,12 +36,7 @@ cmake = import('cmake') udis = cmake.subproject('udis86') udis86 = udis.dependency('libudis86') -if get_option('xwayland').enabled() and not have_xwlr - error('Cannot enable Xwayland in Hyprland: wlroots has been built without Xwayland support') -endif -have_xwayland = xcb_dep.found() and have_xwlr - -if not have_xwayland +if not xcb_dep.found() add_project_arguments('-DNO_XWAYLAND', language: 'cpp') endif @@ -86,5 +79,5 @@ import('pkgconfig').generate( url: 'https://github.com/hyprwm/Hyprland', description: 'Hyprland header files', install_dir: pkg_install_dir, - subdirs: ['', 'hyprland/protocols', 'hyprland', 'hyprland/wlr'], + subdirs: ['', 'hyprland/protocols', 'hyprland'], ) diff --git a/protocols/meson.build b/protocols/meson.build index 7c508659c4e..5cdeb160a9f 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -66,6 +66,8 @@ new_protocols = [ [wl_protocol_dir, 'staging/xwayland-shell/xwayland-shell-v1.xml'], [wl_protocol_dir, 'stable/viewporter/viewporter.xml'], [wl_protocol_dir, 'stable/linux-dmabuf/linux-dmabuf-v1.xml'], + [wl_protocol_dir, 'staging/drm-lease/drm-lease-v1.xml'], + [wl_protocol_dir, 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml'], ] wl_protos_src = [] diff --git a/src/meson.build b/src/meson.build index f6ae043d775..71854fa40c7 100644 --- a/src/meson.build +++ b/src/meson.build @@ -2,14 +2,15 @@ globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true) src = globber.stdout().strip().split('\n') executable('Hyprland', src, - cpp_args: ['-DWLR_USE_UNSTABLE'], link_args: '-rdynamic', cpp_pch: 'pch/pch.hpp', dependencies: [ server_protos, + dependency('aquamarine'), + dependency('gbm'), + dependency('xcursor'), dependency('wayland-server'), dependency('wayland-client'), - wlroots.get_variable('wlroots'), dependency('cairo'), dependency('hyprcursor', version: '>=0.1.7'), dependency('hyprlang', version: '>= 0.3.2'), From d7aded851be4546069861b1abf74c05b9814f1db Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Sun, 7 Jul 2024 05:54:51 +0200 Subject: [PATCH 062/113] cmake: drop unused include after 758c0b325333 --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1db303f3885..ddd1ad6b28f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,6 @@ cmake_minimum_required(VERSION 3.27) include(CheckIncludeFile) -include(ExternalProject) include(GNUInstallDirs) # Get version From 05f7a239c019afbcebb32a4eacd770aec4b48565 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Sun, 7 Jul 2024 06:02:38 +0200 Subject: [PATCH 063/113] nix: drop unused script after 589f758d947c --- nix/update-wlroots.sh | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100755 nix/update-wlroots.sh diff --git a/nix/update-wlroots.sh b/nix/update-wlroots.sh deleted file mode 100755 index 01f5cd83eb7..00000000000 --- a/nix/update-wlroots.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env -S nix shell nixpkgs#gawk nixpkgs#git nixpkgs#gnused nixpkgs#ripgrep -c bash - -# get wlroots revision from submodule -SUB_REV=$(git submodule status | rg wlroots | awk '{ print substr($1,2) }') -# and from lockfile -CRT_REV=$(rg rev flake.nix | awk '{ print substr($3, 2, 40) }') - -if [ "$SUB_REV" != "$CRT_REV" ]; then - echo "Updating wlroots..." - # update wlroots to submodule revision - sed -Ei "s/\w{40}/$SUB_REV/g" flake.nix - nix flake lock - - echo "wlroots: $CRT_REV -> $SUB_REV" -else - echo "wlroots is up to date!" -fi From bd25149daf01c03712a2ef3ba3ebc3623067eb11 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 7 Jul 2024 17:10:57 +0300 Subject: [PATCH 064/113] Nix: add xcursor dep --- nix/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nix/default.nix b/nix/default.nix index 5018146c9cf..7775b7294d2 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -138,6 +138,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov (lib.optionals stdenv.hostPlatform.isMusl [libexecinfo]) (lib.optionals enableXWayland [ xorg.libxcb + xorg.libXcursor xorg.libXdmcp xorg.xcbutil xorg.xcbutilerrors From 29598f2c503f24177878202d67db8657da36ea5e Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 7 Jul 2024 17:11:07 +0300 Subject: [PATCH 065/113] flake.lock: update nix/overlays: remove xwayland overlay (merged upstream) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 8612554ab23..b40972fc80b 100644 --- a/flake.lock +++ b/flake.lock @@ -93,11 +93,11 @@ ] }, "locked": { - "lastModified": 1720381373, - "narHash": "sha256-lyC/EZdHULsaAKVryK11lgHY9u6pXr7qR4irnxNWC7k=", + "lastModified": 1720261026, + "narHash": "sha256-soPz9ZmBNUPBMN/V1DoVEEQfohqZ5NKDT6lpM9E9Khc=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "5df0174fd09de4ac5475233d65ffc703e89b82eb", + "rev": "db8c528aaca679464a55e774f7b71ffe014508f6", "type": "github" }, "original": { From 4aa77b26e87e1595d18b58648d9e831c415c4b30 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 7 Jul 2024 21:25:09 +0200 Subject: [PATCH 066/113] fixeroni crasheroni --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 45e058fe63e..557838317ca 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1582,7 +1582,7 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vectorvecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y}; for (auto& ls : layerSurfaces) { - if (ls->fadingOut || ls->readyToDelete || !ls->layerSurface || ls->noProcess) + if (!ls || ls->fadingOut || ls->readyToDelete || !ls->layerSurface || ls->noProcess) continue; const auto PLAYER = ls->layerSurface; From 76b8be23494ed13a790bcc234d6f3ae376e24016 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 7 Jul 2024 22:41:47 +0200 Subject: [PATCH 067/113] some fixes to dmabuf --- src/Compositor.cpp | 8 ++- src/helpers/Format.cpp | 15 +++++ src/helpers/Format.hpp | 3 + src/protocols/LinuxDMABUF.cpp | 116 +++++++++++++++++++++++----------- src/protocols/LinuxDMABUF.hpp | 6 +- src/render/Renderer.cpp | 10 ++- src/render/Renderer.hpp | 2 +- 7 files changed, 116 insertions(+), 44 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 8505e51dbfa..dda89d3a1cc 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2327,8 +2327,12 @@ void CCompositor::setWindowFullscreen(PHLWINDOW pWindow, bool on, eFullscreenMod g_pInputManager->recheckIdleInhibitorStatus(); - // DMAbuf stuff for direct scanout - g_pHyprRenderer->setWindowScanoutMode(pWindow); + // further updates require a monitor + if (!PMONITOR) + return; + + // send a scanout tranche if we are entering fullscreen, and send a regular one if we aren't. + g_pHyprRenderer->setSurfaceScanoutMode(pWindow->m_pWLSurface->resource(), on ? PMONITOR->self.lock() : nullptr); g_pConfigManager->ensureVRR(PMONITOR); } diff --git a/src/helpers/Format.cpp b/src/helpers/Format.cpp index 5251002cddb..8d080322b0d 100644 --- a/src/helpers/Format.cpp +++ b/src/helpers/Format.cpp @@ -3,6 +3,7 @@ #include "../includes.hpp" #include "debug/Log.hpp" #include "../macros.hpp" +#include /* DRM formats are LE, while OGL is BE. The two primary formats @@ -309,3 +310,17 @@ uint32_t FormatUtils::glFormatToType(uint32_t gl) { #endif GL_UNSIGNED_BYTE; } + +std::string FormatUtils::drmFormatName(DRMFormat drm) { + auto n = drmGetFormatName(drm); + std::string name = n; + free(n); + return name; +} + +std::string FormatUtils::drmModifierName(uint64_t mod) { + auto n = drmGetFormatModifierName(mod); + std::string name = n; + free(n); + return name; +} diff --git a/src/helpers/Format.hpp b/src/helpers/Format.hpp index a0ac9c32896..8269c5c34bc 100644 --- a/src/helpers/Format.hpp +++ b/src/helpers/Format.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "math/Math.hpp" #include @@ -32,4 +33,6 @@ namespace FormatUtils { int minStride(const SPixelFormat* const fmt, int32_t width); uint32_t drmFormatToGL(DRMFormat drm); uint32_t glFormatToType(uint32_t gl); + std::string drmFormatName(DRMFormat drm); + std::string drmModifierName(uint64_t mod); }; diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 1c82687479a..2d638aad233 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -61,9 +61,9 @@ CCompiledDMABUFFeedback::CCompiledDMABUFFeedback(dev_t device, std::vectorformats = formatsVec; // TODO: maybe calculate indices? currently we send all as available which could be wrong? I ain't no kernel dev tho. } @@ -189,7 +189,7 @@ void CLinuxDMABBUFParamsResource::create(uint32_t id) { return; } - LOGM(LOG, "Creating a dmabuf, with id {}: size {}, fmt {}, planes {}", id, attrs->size, attrs->format, attrs->planes); + LOGM(LOG, "Creating a dmabuf, with id {}: size {}, fmt {}, planes {}", id, attrs->size, FormatUtils::drmFormatName(attrs->format), attrs->planes); for (int i = 0; i < attrs->planes; ++i) { LOGM(LOG, " | plane {}: mod {} fd {} stride {} offset {}", i, attrs->modifier, attrs->fds[i], attrs->strides[i], attrs->offsets[i]); } @@ -276,14 +276,25 @@ CLinuxDMABUFFeedbackResource::CLinuxDMABUFFeedbackResource(SPsetOnDestroy([this](CZwpLinuxDmabufFeedbackV1* r) { PROTO::linuxDma->destroyResource(this); }); resource->setDestroy([this](CZwpLinuxDmabufFeedbackV1* r) { PROTO::linuxDma->destroyResource(this); }); - if (surface) - LOGM(ERR, "FIXME: surface feedback stub"); - auto* feedback = PROTO::linuxDma->defaultFeedback.get(); resource->sendFormatTable(feedback->tableFD, feedback->tableLen); // send default feedback + sendDefault(); +} + +CLinuxDMABUFFeedbackResource::~CLinuxDMABUFFeedbackResource() { + ; +} + +bool CLinuxDMABUFFeedbackResource::good() { + return resource->resource(); +} + +void CLinuxDMABUFFeedbackResource::sendDefault() { + auto* feedback = PROTO::linuxDma->defaultFeedback.get(); + struct wl_array deviceArr = { .size = sizeof(feedback->mainDevice), .data = (void*)&feedback->mainDevice, @@ -295,40 +306,12 @@ CLinuxDMABUFFeedbackResource::CLinuxDMABUFFeedbackResource(SPtranches.size(); ++i) { + for (size_t i = 0; i < feedback->formats.size(); ++i) { *((uint16_t*)wl_array_add(&indices, sizeof(uint16_t))) = i; } resource->sendTrancheFormats(&indices); wl_array_release(&indices); resource->sendTrancheDone(); - - // Scanout tranche - // FIXME: jesus fucking christ this SUCKSSSSSS ASSSSSS - resource->sendTrancheTargetDevice(&deviceArr); - resource->sendTrancheFlags(ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT); - - wl_array indices2; - wl_array_init(&indices2); - for (size_t i = 0; i < feedback->tranches.size(); ++i) { - // FIXME: if the monitor gets the wrong format we'll be FUCKED by drm and no scanout will happen - if (feedback->tranches.at(i).first != DRM_FORMAT_XRGB8888 && feedback->tranches.at(i).first != DRM_FORMAT_XRGB2101010) - continue; - - *((uint16_t*)wl_array_add(&indices2, sizeof(uint16_t))) = i; - } - resource->sendTrancheFormats(&indices2); - wl_array_release(&indices2); - resource->sendTrancheDone(); - - resource->sendDone(); -} - -CLinuxDMABUFFeedbackResource::~CLinuxDMABUFFeedbackResource() { - ; -} - -bool CLinuxDMABUFFeedbackResource::good() { - return resource->resource(); } CLinuxDMABUFResource::CLinuxDMABUFResource(SP resource_) : resource(resource_) { @@ -379,7 +362,7 @@ bool CLinuxDMABUFResource::good() { } void CLinuxDMABUFResource::sendMods() { - for (auto& [fmt, mod] : PROTO::linuxDma->defaultFeedback->tranches) { + for (auto& [fmt, mod] : PROTO::linuxDma->defaultFeedback->formats) { if (resource->version() < 3) { if (mod == DRM_FORMAT_MOD_INVALID || mod == DRM_FORMAT_MOD_LINEAR) resource->sendFormat(fmt); @@ -475,3 +458,62 @@ void CLinuxDMABufV1Protocol::destroyResource(CLinuxDMABBUFParamsResource* resour void CLinuxDMABufV1Protocol::destroyResource(CLinuxDMABuffer* resource) { std::erase_if(m_vBuffers, [&](const auto& other) { return other.get() == resource; }); } + +void CLinuxDMABufV1Protocol::updateScanoutTranche(SP surface, SP pMonitor) { + // TODO: iterating isn't particularly efficient, maybe add a system for addons for surfaces + + SP feedbackResource; + for (auto& f : m_vFeedbacks) { + if (f->surface != surface) + continue; + + feedbackResource = f; + break; + } + + if (!feedbackResource) { + LOGM(LOG, "updateScanoutTranche: surface has no dmabuf_feedback"); + return; + } + + if (!pMonitor) { + LOGM(LOG, "updateScanoutTranche: resetting feedback"); + feedbackResource->sendDefault(); + return; + } + + auto* feedback = PROTO::linuxDma->defaultFeedback.get(); + + LOGM(LOG, "updateScanoutTranche: sending a scanout tranche"); + + // send a dedicated scanout tranche that contains formats that: + // - match the format of the output + // - are not linear or implicit + + struct wl_array deviceArr = { + .size = sizeof(feedback->mainDevice), + .data = (void*)&feedback->mainDevice, + }; + feedbackResource->resource->sendTrancheTargetDevice(&deviceArr); + feedbackResource->resource->sendTrancheFlags(ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT); + + wl_array indices2; + wl_array_init(&indices2); + for (size_t i = 0; i < feedback->formats.size(); ++i) { + if (feedback->formats.at(i).first != pMonitor->output->state->state().drmFormat) + continue; + + if (feedback->formats.at(i).second == DRM_FORMAT_MOD_LINEAR || feedback->formats.at(i).second == DRM_FORMAT_MOD_INVALID) + continue; + + LOGM(TRACE, "updateScanoutTranche: Format {} with modifier {} aka {} passed", FormatUtils::drmFormatName(feedback->formats.at(i).first), feedback->formats.at(i).second, + FormatUtils::drmModifierName(feedback->formats.at(i).second)); + *((uint16_t*)wl_array_add(&indices2, sizeof(uint16_t))) = i; + } + + feedbackResource->resource->sendTrancheFormats(&indices2); + wl_array_release(&indices2); + feedbackResource->resource->sendTrancheDone(); + + feedbackResource->resource->sendDone(); +} diff --git a/src/protocols/LinuxDMABUF.hpp b/src/protocols/LinuxDMABUF.hpp index 4e1636d0b72..7f252588e0a 100644 --- a/src/protocols/LinuxDMABUF.hpp +++ b/src/protocols/LinuxDMABUF.hpp @@ -57,7 +57,7 @@ class CCompiledDMABUFFeedback { dev_t mainDevice = 0; int tableFD = -1; size_t tableLen = 0; - std::vector> tranches; + std::vector> formats; }; class CLinuxDMABBUFParamsResource { @@ -85,11 +85,14 @@ class CLinuxDMABUFFeedbackResource { ~CLinuxDMABUFFeedbackResource(); bool good(); + void sendDefault(); SP surface; // optional, for surface feedbacks private: SP resource; + + friend class CLinuxDMABufV1Protocol; }; class CLinuxDMABUFResource { @@ -109,6 +112,7 @@ class CLinuxDMABufV1Protocol : public IWaylandProtocol { ~CLinuxDMABufV1Protocol(); virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + void updateScanoutTranche(SP surface, SP pMonitor); private: void destroyResource(CLinuxDMABUFResource* resource); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 557838317ca..a2656de16d8 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -15,6 +15,7 @@ #include "../protocols/core/DataDevice.hpp" #include "../protocols/core/Compositor.hpp" #include "../protocols/DRMSyncobj.hpp" +#include "../protocols/LinuxDMABUF.hpp" #include "../helpers/sync/SyncTimeline.hpp" extern "C" { @@ -1440,7 +1441,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { continue; e->syncobj->releaseTimeline->timeline->transfer(pMonitor->outTimeline, pMonitor->commitSeq, e->syncobj->releasePoint); } - + explicitPresented.clear(); pMonitor->output->state->setExplicitOutFence(pMonitor->outTimeline->exportAsSyncFileFD(pMonitor->commitSeq)); } @@ -1515,8 +1516,11 @@ void CHyprRenderer::sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE } } -void CHyprRenderer::setWindowScanoutMode(PHLWINDOW pWindow) { - // FIXME: fix when moved to new impl +void CHyprRenderer::setSurfaceScanoutMode(SP surface, SP monitor) { + if (!PROTO::linuxDma) + return; + + PROTO::linuxDma->updateScanoutTranche(surface, monitor); } // taken from Sway. diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index b15ba04bb4b..6450651e226 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -89,7 +89,7 @@ class CHyprRenderer { damageTrackingModeFromStr(const std::string&); bool attemptDirectScanout(CMonitor*); - void setWindowScanoutMode(PHLWINDOW); + void setSurfaceScanoutMode(SP surface, SP monitor); // nullptr monitor resets void initiateManualCrash(); bool m_bCrashingInProgress = false; From f472dcd67b596f35b97516c76b205593d36375dd Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 8 Jul 2024 12:52:46 +0200 Subject: [PATCH 068/113] ds fixes --- src/protocols/LinuxDMABUF.cpp | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 2d638aad233..e4247b92c1d 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -25,7 +25,7 @@ static std::optional devIDFromFD(int fd) { CCompiledDMABUFFeedback::CCompiledDMABUFFeedback(dev_t device, std::vector tranches_) { std::set> formats; - for (auto& fmt : g_pHyprOpenGL->getDRMFormats()) { + for (auto& fmt : tranches_.at(0).formats /* FIXME: multigpu */) { for (auto& mod : fmt.modifiers) { formats.insert(std::make_pair<>(fmt.drmFormat, mod)); } @@ -48,11 +48,12 @@ CCompiledDMABUFFeedback::CCompiledDMABUFFeedback(dev_t device, std::vector> formatsVec; for (auto& f : formats) { - formatsVec.push_back(f); + formatsVec.emplace_back(f); } size_t i = 0; for (auto& [fmt, mod] : formatsVec) { + LOGM(TRACE, "Feedback: format table index {}: fmt {} mod {}", i, FormatUtils::drmFormatName(fmt), mod); arr[i++] = SDMABUFFeedbackTableEntry{ .fmt = fmt, .modifier = mod, @@ -64,8 +65,6 @@ CCompiledDMABUFFeedback::CCompiledDMABUFFeedback(dev_t device, std::vectorformats = formatsVec; - - // TODO: maybe calculate indices? currently we send all as available which could be wrong? I ain't no kernel dev tho. } CCompiledDMABUFFeedback::~CCompiledDMABUFFeedback() { @@ -312,6 +311,8 @@ void CLinuxDMABUFFeedbackResource::sendDefault() { resource->sendTrancheFormats(&indices); wl_array_release(&indices); resource->sendTrancheDone(); + + resource->sendDone(); } CLinuxDMABUFResource::CLinuxDMABUFResource(SP resource_) : resource(resource_) { @@ -391,6 +392,8 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const // FIXME: this will break on multi-gpu std::vector aqFormats; for (auto& impl : g_pCompositor->m_pAqBackend->getImplementations()) { + if (impl->type() != Aquamarine::AQ_BACKEND_DRM) + continue; aqFormats = impl->getRenderFormats(); break; } @@ -499,15 +502,22 @@ void CLinuxDMABufV1Protocol::updateScanoutTranche(SP surface wl_array indices2; wl_array_init(&indices2); + const auto PRIMARYFORMATS = pMonitor->output->getBackend()->getRenderFormats(); + for (size_t i = 0; i < feedback->formats.size(); ++i) { - if (feedback->formats.at(i).first != pMonitor->output->state->state().drmFormat) + if (feedback->formats.at(i).second == DRM_FORMAT_MOD_LINEAR || feedback->formats.at(i).second == DRM_FORMAT_MOD_INVALID) continue; - if (feedback->formats.at(i).second == DRM_FORMAT_MOD_LINEAR || feedback->formats.at(i).second == DRM_FORMAT_MOD_INVALID) + const auto PRIM_FORMAT = std::find_if(PRIMARYFORMATS.begin(), PRIMARYFORMATS.end(), [&](const auto& e) { return e.drmFormat == feedback->formats.at(i).first; }); + + if (PRIM_FORMAT == PRIMARYFORMATS.end()) + continue; + + if (std::find(PRIM_FORMAT->modifiers.begin(), PRIM_FORMAT->modifiers.end(), feedback->formats.at(i).second) == PRIM_FORMAT->modifiers.end()) continue; - LOGM(TRACE, "updateScanoutTranche: Format {} with modifier {} aka {} passed", FormatUtils::drmFormatName(feedback->formats.at(i).first), feedback->formats.at(i).second, - FormatUtils::drmModifierName(feedback->formats.at(i).second)); + LOGM(TRACE, "updateScanoutTranche: index {}: Format {} with modifier {} aka {} passed", i, FormatUtils::drmFormatName(feedback->formats.at(i).first), + feedback->formats.at(i).second, FormatUtils::drmModifierName(feedback->formats.at(i).second)); *((uint16_t*)wl_array_add(&indices2, sizeof(uint16_t))) = i; } From be4051e923befbfe16c0caef27e1502d2143c23c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 8 Jul 2024 12:55:22 +0200 Subject: [PATCH 069/113] send flag on main tranche --- src/protocols/LinuxDMABUF.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index e4247b92c1d..53d0d9deab5 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -303,6 +303,9 @@ void CLinuxDMABUFFeedbackResource::sendDefault() { // Main tranche resource->sendTrancheTargetDevice(&deviceArr); + // Technically, on a single-gpu system, this is correct I believe. + resource->sendTrancheFlags(ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT); + wl_array indices; wl_array_init(&indices); for (size_t i = 0; i < feedback->formats.size(); ++i) { From 45f726c6bd6792ab022aa044eb7994ab860bf1c2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 8 Jul 2024 14:23:02 +0200 Subject: [PATCH 070/113] dmabufff --- src/protocols/LinuxDMABUF.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 53d0d9deab5..862fb4d7ed6 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -304,7 +304,7 @@ void CLinuxDMABUFFeedbackResource::sendDefault() { resource->sendTrancheTargetDevice(&deviceArr); // Technically, on a single-gpu system, this is correct I believe. - resource->sendTrancheFlags(ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT); + resource->sendTrancheFlags(ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT); wl_array indices; wl_array_init(&indices); @@ -398,7 +398,18 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const if (impl->type() != Aquamarine::AQ_BACKEND_DRM) continue; aqFormats = impl->getRenderFormats(); - break; + if (!aqFormats.empty()) + break; + } + + if (aqFormats.empty()) { + // fallback: use EGL formats + for (auto& fmt : g_pHyprOpenGL->getDRMFormats()) { + aqFormats.emplace_back(Aquamarine::SDRMFormat{ + .drmFormat = fmt.drmFormat, + .modifiers = fmt.modifiers, + }); + } } SDMABufTranche tranche = { From 1d4e51876d24de731135ba75531494cc89023da1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 8 Jul 2024 15:27:56 +0200 Subject: [PATCH 071/113] e --- src/managers/CursorManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 2525008376e..195b0c8813a 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -132,7 +132,6 @@ void CCursorManager::setCursorSurface(SP surf, const Vector2D& hotsp void CCursorManager::setXCursor(const std::string& name) { float scale = std::ceil(m_fCursorScale); - xcursor.loadTheme(name.c_str(), m_iSize * scale); if (!xcursor.themeLoaded) { Debug::log(ERR, "XCursor failed to find theme in setXCursor"); From d13189d8f63d51f8b08b70e40f84e6f40f8eb417 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 8 Jul 2024 15:28:36 +0200 Subject: [PATCH 072/113] no leakeroni --- src/managers/CursorManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 195b0c8813a..8e8cf1db21c 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -418,6 +418,8 @@ void CCursorManager::SXCursorManager::loadTheme(const std::string& name, int siz themeLoaded = true; + XcursorImageDestroy(img); + // gather as many shapes as we can find. cursors.clear(); @@ -450,5 +452,7 @@ void CCursorManager::SXCursorManager::loadTheme(const std::string& name, int siz std::memcpy(xcursor->pixels.data(), xImage->pixels, xImage->width * xImage->height * sizeof(uint32_t)); cursors.emplace(std::string{shape}, xcursor); + + XcursorImageDestroy(xImage); } } From 959e83fd4db4d95db9975eac7e061e14a7bdeb47 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 8 Jul 2024 15:57:21 +0200 Subject: [PATCH 073/113] stuf --- src/helpers/Monitor.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index e62db7183f7..7edf3b4bc32 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -45,10 +45,21 @@ void CMonitor::onConnect(bool noRule) { }); listeners.state = output->events.state.registerListener([this](std::any d) { - if (!createdByUser) + auto E = std::any_cast(d); + + if (E.size == Vector2D{}) { + // an indication to re-set state + // we can't do much for createdByUser displays I think + if (createdByUser) + return; + + Debug::log(LOG, "Reapplying monitor rule for {} from a state request", szName); + g_pHyprRenderer->applyMonitorRule(this, &activeMonitorRule, true); return; + } - auto E = std::any_cast(d); + if (!createdByUser) + return; const auto SIZE = E.size; From 95ddf9e7eb62d617a0f36b87dcab3b9f5a8b892d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 9 Jul 2024 14:11:07 +0200 Subject: [PATCH 074/113] stuff for aq alloc split --- src/config/ConfigManager.cpp | 2 +- src/helpers/Monitor.cpp | 9 +++++---- src/managers/PointerManager.cpp | 18 ++++++++++-------- src/managers/eventLoop/EventLoopManager.hpp | 2 +- src/protocols/Viewporter.hpp | 2 +- src/render/OpenGL.cpp | 11 +++++++++-- src/render/Renderer.hpp | 16 ++++++++-------- 7 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 56025bc1b87..cfbd7ef9e5e 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -556,7 +556,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:groupbar:col.inactive", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0x66777700"}); m_pConfig->addConfigValue("group:groupbar:col.locked_active", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0x66ff5500"}); m_pConfig->addConfigValue("group:groupbar:col.locked_inactive", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0x66775500"}); - + m_pConfig->addConfigValue("experimental:explicit_sync", Hyprlang::INT{0}); // devices diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 7edf3b4bc32..a65492df7cf 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -811,9 +811,10 @@ bool CMonitorState::updateSwapchain() { const auto& MODE = STATE.mode ? STATE.mode : STATE.customMode; if (!MODE) return true; - options.format = STATE.drmFormat; - options.scanout = true; - options.length = 2; - options.size = MODE->pixelSize; + options.format = STATE.drmFormat; + options.scanout = true; + options.length = 2; + options.size = MODE->pixelSize; + options.multigpu = m_pOwner->output->swapchain->getAllocator()->drmFD() != g_pCompositor->m_iDRMFD; return m_pOwner->output->swapchain->reconfigure(options); } diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 02712b8b376..99d1412ffba 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -367,13 +367,14 @@ SP CPointerManager::renderHWCursorBuffer(SPmonitor->cursorSwapchain || maxSize != state->monitor->cursorSwapchain->currentOptions().size) { if (!state->monitor->cursorSwapchain) - state->monitor->cursorSwapchain = Aquamarine::CSwapchain::create(g_pCompositor->m_pAqBackend->allocator, state->monitor->output->getBackend()); - - auto options = state->monitor->cursorSwapchain->currentOptions(); - options.size = maxSize; - options.length = 2; - options.scanout = true; - options.cursor = true; + 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. @@ -455,7 +456,8 @@ void CPointerManager::renderSoftwareCursorsFor(SP pMonitor, timespec* Vector2D CPointerManager::getCursorPosForMonitor(SP pMonitor) { return CBox{pointerPos - pMonitor->vecPosition, {0, 0}} - .transform(wlTransformToHyprutils(invertTransform(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; } diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp index 6f3e8529b7a..39d8bbebafa 100644 --- a/src/managers/eventLoop/EventLoopManager.hpp +++ b/src/managers/eventLoop/EventLoopManager.hpp @@ -48,7 +48,7 @@ class CEventLoopManager { int timerfd = -1; } m_sTimers; - SIdleData m_sIdle; + SIdleData m_sIdle; std::vector> aqPollFDs; friend class CSyncTimeline; diff --git a/src/protocols/Viewporter.hpp b/src/protocols/Viewporter.hpp index fd0da88e1e5..3c2a4eefd79 100644 --- a/src/protocols/Viewporter.hpp +++ b/src/protocols/Viewporter.hpp @@ -21,7 +21,7 @@ class CViewportResource { SP resource; struct { - CHyprSignalListener surfacePrecommit; + CHyprSignalListener surfacePrecommit; } listeners; }; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index adc45f2cdc2..a7e0e2aa25d 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -521,7 +521,8 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool } bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { - // passes requiring introspection are the ones that need to render blur. + // passes requiring introspection are the ones that need to render blur, + // or when we are rendering to a multigpu target static auto PBLUR = CConfigValue("decoration:blur:enabled"); static auto PXRAY = CConfigValue("decoration:blur:xray"); @@ -529,6 +530,12 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { static auto PBLURSPECIAL = CConfigValue("decoration:blur:special"); static auto PBLURPOPUPS = CConfigValue("decoration:blur:popups"); + // multigpu destination + if (pMonitor->output->swapchain->getAllocator()->drmFD() != g_pCompositor->m_iDRMFD) { + Debug::log(TRACE, "passRequiresIntrospection: multigpu target, forcing"); + return true; + } + if (m_RenderData.mouseZoomFactor != 1.0 || g_pHyprRenderer->m_bCrashingInProgress) return true; @@ -2754,7 +2761,7 @@ SP CHyprOpenGLImpl::createEGLSync(int fenceFD) { return nullptr; } - auto eglsync = SP(new CEGLSync); + auto eglsync = SP(new CEGLSync); eglsync->sync = sync; return eglsync; } diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 6450651e226..2eb80d83ad1 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -88,16 +88,16 @@ class CHyprRenderer { DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&); - bool attemptDirectScanout(CMonitor*); - void setSurfaceScanoutMode(SP surface, SP monitor); // nullptr monitor resets - void initiateManualCrash(); + bool attemptDirectScanout(CMonitor*); + void setSurfaceScanoutMode(SP surface, SP monitor); // nullptr monitor resets + void initiateManualCrash(); - bool m_bCrashingInProgress = false; - float m_fCrashingDistort = 0.5f; - wl_event_source* m_pCrashingLoop = nullptr; - wl_event_source* m_pCursorTicker = nullptr; + bool m_bCrashingInProgress = false; + float m_fCrashingDistort = 0.5f; + wl_event_source* m_pCrashingLoop = nullptr; + wl_event_source* m_pCursorTicker = nullptr; - CTimer m_tRenderTimer; + CTimer m_tRenderTimer; std::vector> explicitPresented; From 37a96c6110ee3be22716fc8a951390f7565d73f9 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 9 Jul 2024 12:12:41 +0000 Subject: [PATCH 075/113] [gha] Nix: update inputs --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index b40972fc80b..2f97ecda51f 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1720357840, - "narHash": "sha256-afisBv6SIInBL6q2Os6wlJRiZbYxw6tCUqVwab1cHBk=", + "lastModified": 1720527052, + "narHash": "sha256-ibx5vBellJff0Hu28hDWs8BlHUoxtRuSlVHTEyDNwZI=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "946c75641414102b5c0aec4b1c27a4bff83fe442", + "rev": "e3f2c0d5cc11a22c3f8c9a723823c603f45fa67c", "type": "github" }, "original": { @@ -93,11 +93,11 @@ ] }, "locked": { - "lastModified": 1720261026, - "narHash": "sha256-soPz9ZmBNUPBMN/V1DoVEEQfohqZ5NKDT6lpM9E9Khc=", + "lastModified": 1720381373, + "narHash": "sha256-lyC/EZdHULsaAKVryK11lgHY9u6pXr7qR4irnxNWC7k=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "db8c528aaca679464a55e774f7b71ffe014508f6", + "rev": "5df0174fd09de4ac5475233d65ffc703e89b82eb", "type": "github" }, "original": { From 13af7fb2fb0bc148e6f31d28ef45cdb5cd389fba Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 9 Jul 2024 17:31:04 +0200 Subject: [PATCH 076/113] explicit sync stuff --- src/render/Renderer.cpp | 93 +++++++++++++++++++++++++++++++---------- src/render/Renderer.hpp | 2 + 2 files changed, 73 insertions(+), 22 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index a2656de16d8..fe7cab96cbe 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1431,6 +1431,30 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { pMonitor->output->state->setPresentationMode(shouldTear ? Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_IMMEDIATE : Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC); + commitPendingAndDoExplicitSync(pMonitor); + + if (shouldTear) + pMonitor->tearingState.busy = true; + + if (*PDAMAGEBLINK || *PVFR == 0 || pMonitor->pendingFrame) + g_pCompositor->scheduleFrameForMonitor(pMonitor); + + pMonitor->pendingFrame = false; + + const float µs = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - renderStart).count() / 1000.f; + g_pDebugOverlay->renderData(pMonitor, µs); + + if (*PDEBUGOVERLAY == 1) { + if (pMonitor == g_pCompositor->m_vMonitors.front().get()) { + const float µsNoOverlay = µs - std::chrono::duration_cast(endRenderOverlay - renderStartOverlay).count() / 1000.f; + g_pDebugOverlay->renderDataNoOverlay(pMonitor, µsNoOverlay); + } else { + g_pDebugOverlay->renderDataNoOverlay(pMonitor, µs); + } + } +} + +bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { // apply timelines for explicit sync bool anyExplicit = !explicitPresented.empty(); if (anyExplicit) { @@ -1447,35 +1471,27 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } pMonitor->lastWaitPoint = 0; - pMonitor->commitSeq++; + + const auto COMMITTED_OUT = pMonitor->output->state->state().explicitOutFence; + const auto COMMITTED_IN = pMonitor->output->state->state().explicitInFence; if (!pMonitor->state.commit()) { // rollback the buffer to avoid writing to the front buffer that is being // displayed pMonitor->output->swapchain->rollback(); pMonitor->damage.damageEntire(); - return; + return false; } - if (shouldTear) - pMonitor->tearingState.busy = true; - - if (*PDAMAGEBLINK || *PVFR == 0 || pMonitor->pendingFrame) - g_pCompositor->scheduleFrameForMonitor(pMonitor); - - pMonitor->pendingFrame = false; - - const float µs = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - renderStart).count() / 1000.f; - g_pDebugOverlay->renderData(pMonitor, µs); + if (COMMITTED_IN >= 0) + close(COMMITTED_IN); - if (*PDEBUGOVERLAY == 1) { - if (pMonitor == g_pCompositor->m_vMonitors.front().get()) { - const float µsNoOverlay = µs - std::chrono::duration_cast(endRenderOverlay - renderStartOverlay).count() / 1000.f; - g_pDebugOverlay->renderDataNoOverlay(pMonitor, µsNoOverlay); - } else { - g_pDebugOverlay->renderDataNoOverlay(pMonitor, µs); - } + if (COMMITTED_OUT >= 0) { + pMonitor->outTimeline->importFromSyncFileFD(pMonitor->commitSeq, COMMITTED_OUT); + close(COMMITTED_OUT); } + + return true; } void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry) { @@ -2658,6 +2674,8 @@ void CHyprRenderer::endRender() { const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor; static auto PNVIDIAANTIFLICKER = CConfigValue("opengl:nvidia_anti_flicker"); + PMONITOR->commitSeq++; + if (m_eRenderMode != RENDER_MODE_TO_BUFFER_READ_ONLY) g_pHyprOpenGL->end(); else { @@ -2671,12 +2689,43 @@ void CHyprRenderer::endRender() { if (isNvidia() && *PNVIDIAANTIFLICKER) glFinish(); - else - glFlush(); - if (m_eRenderMode == RENDER_MODE_NORMAL) + if (m_eRenderMode == RENDER_MODE_NORMAL) { PMONITOR->output->state->setBuffer(m_pCurrentBuffer); + if (PMONITOR->output->state->state().explicitOutFence >= 0) { + auto sync = g_pHyprOpenGL->createEGLSync(-1); + if (!sync) { + m_pCurrentRenderbuffer->unbind(); + m_pCurrentRenderbuffer = nullptr; + m_pCurrentBuffer = nullptr; + Debug::log(ERR, "renderer: couldn't create an EGLSync for out in endRender"); + return; + } + + auto dupedfd = sync->dupFenceFD(); + sync.reset(); + if (dupedfd < 0) { + m_pCurrentRenderbuffer->unbind(); + m_pCurrentRenderbuffer = nullptr; + m_pCurrentBuffer = nullptr; + Debug::log(ERR, "renderer: couldn't dup an EGLSync fence for out in endRender"); + return; + } + + bool ok = PMONITOR->outTimeline->importFromSyncFileFD(PMONITOR->commitSeq, dupedfd); + close(dupedfd); + if (!ok) { + m_pCurrentRenderbuffer->unbind(); + m_pCurrentRenderbuffer = nullptr; + m_pCurrentBuffer = nullptr; + Debug::log(ERR, "renderer: couldn't import from sync file fd in endRender"); + return; + } + } else + glFlush(); + } + m_pCurrentRenderbuffer->unbind(); m_pCurrentRenderbuffer = nullptr; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 2eb80d83ad1..6cabf2d075b 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -121,6 +121,8 @@ class CHyprRenderer { void sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now); // sends frame displayed events but doesn't actually render anything void renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); + bool commitPendingAndDoExplicitSync(CMonitor* pMonitor); + bool m_bCursorHidden = false; bool m_bCursorHasSurface = false; SP m_pCurrentRenderbuffer = nullptr; From 8ae38c1e1e3d134c8c7befc9e51690c46e3ef0ce Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 9 Jul 2024 17:36:22 +0200 Subject: [PATCH 077/113] stuff --- src/Compositor.hpp | 1 - src/events/Monitors.cpp | 7 ------- src/managers/KeybindManager.cpp | 3 ++- src/managers/input/InputManager.cpp | 4 ++++ 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 3eaafb47ba4..3773829541a 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -89,7 +89,6 @@ class CCompositor { bool m_bUnsafeState = false; // unsafe state is when there is no monitors. bool m_bNextIsUnsafe = false; CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state - bool m_bExitTriggered = false; // For exit dispatcher bool m_bIsShuttingDown = false; // ------------------------------------------------- // diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 3fda165446a..573eb52d1bc 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -17,13 +17,6 @@ // --------------------------------------------------------- // void Events::listener_monitorFrame(void* owner, void* data) { - if (g_pCompositor->m_bExitTriggered) { - // Only signal cleanup once - g_pCompositor->m_bExitTriggered = false; - g_pCompositor->cleanup(); - return; - } - CMonitor* const PMONITOR = (CMonitor*)owner; if ((g_pCompositor->m_pAqBackend->hasSession() && !g_pCompositor->m_pAqBackend->session->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 19c7bca6ed4..e9dfd1ae61e 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -9,6 +9,7 @@ #include "PointerManager.hpp" #include "Compositor.hpp" #include "TokenManager.hpp" +#include "eventLoop/EventLoopManager.hpp" #include "debug/Log.hpp" #include "helpers/varlist/VarList.hpp" @@ -1661,7 +1662,7 @@ void CKeybindManager::renameWorkspace(std::string args) { } void CKeybindManager::exitHyprland(std::string argz) { - g_pCompositor->m_bExitTriggered = true; + g_pEventLoopManager->doLater([]() { g_pCompositor->cleanup(); }); } void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) { diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index b6c454b2e44..2db9de6f4bf 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1191,6 +1191,8 @@ static void removeFromHIDs(WP hid) { } void CInputManager::destroyKeyboard(SP pKeyboard) { + Debug::log(LOG, "Keyboard at {:x} removed", (uintptr_t)pKeyboard.get()); + std::erase_if(m_vKeyboards, [pKeyboard](const auto& other) { return other == pKeyboard; }); if (m_vKeyboards.size() > 0) { @@ -1213,6 +1215,8 @@ void CInputManager::destroyKeyboard(SP pKeyboard) { } void CInputManager::destroyPointer(SP mouse) { + Debug::log(LOG, "Pointer at {:x} removed", (uintptr_t)mouse.get()); + std::erase_if(m_vPointers, [mouse](const auto& other) { return other == mouse; }); g_pSeatManager->setMouse(m_vPointers.size() > 0 ? m_vPointers.front() : nullptr); From cdd037ec64f5b2f27e3fdfba211fba5b44a0a2b3 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 9 Jul 2024 23:27:07 +0200 Subject: [PATCH 078/113] initialize arrays --- src/devices/IKeyboard.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index d288c8bac2b..2980a5b19db 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -82,8 +82,8 @@ class IKeyboard : public IHID { uint32_t depressed = 0, latched = 0, locked = 0, group = 0; } modifiersState; - std::array ledIndexes; - std::array modIndexes; + std::array ledIndexes = {0}; + std::array modIndexes = {0}; uint32_t leds = 0; std::string hlName = ""; From 4c905b1a8b3c253fdcd26a7177fafd0b8a6abd9d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 9 Jul 2024 23:47:15 +0200 Subject: [PATCH 079/113] ok gulafaran --- src/devices/IKeyboard.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index 2980a5b19db..e538bcd7054 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -82,8 +82,8 @@ class IKeyboard : public IHID { uint32_t depressed = 0, latched = 0, locked = 0, group = 0; } modifiersState; - std::array ledIndexes = {0}; - std::array modIndexes = {0}; + std::array ledIndexes = {XKB_MOD_INVALID}; + std::array modIndexes = {XKB_MOD_INVALID}; uint32_t leds = 0; std::string hlName = ""; From 805a05438981f7bcb2392e0dc653e5f77b5e0e17 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Wed, 10 Jul 2024 22:20:00 +0300 Subject: [PATCH 080/113] Explicit sync fixes (#6829) * explicit sync fixes * more logging * reremove wlroots * close explicit fds on rollback * limit presentFeedback explicit sync to direct scanout mode only * explicit sync for texture render * cursor explicit sync initial * common wait for explicit sync point code * code style fixes --- src/helpers/sync/SyncTimeline.cpp | 4 +- src/managers/PointerManager.cpp | 2 +- src/managers/PointerManager.hpp | 2 + src/protocols/core/Compositor.cpp | 8 ++-- src/protocols/core/Compositor.hpp | 2 +- src/render/OpenGL.cpp | 58 +++++++++++++++++++----- src/render/OpenGL.hpp | 8 +++- src/render/Renderer.cpp | 73 +++++++++++++++++-------------- 8 files changed, 104 insertions(+), 53 deletions(-) diff --git a/src/helpers/sync/SyncTimeline.cpp b/src/helpers/sync/SyncTimeline.cpp index eee2237f0cc..352120eae8e 100644 --- a/src/helpers/sync/SyncTimeline.cpp +++ b/src/helpers/sync/SyncTimeline.cpp @@ -162,13 +162,13 @@ bool CSyncTimeline::importFromSyncFileFD(uint64_t dst, int fd) { if (drmSyncobjImportSyncFile(drmFD, syncHandle, fd)) { Debug::log(ERR, "importFromSyncFileFD: drmSyncobjImportSyncFile failed"); drmSyncobjDestroy(drmFD, syncHandle); - return -1; + return false; } if (drmSyncobjTransfer(drmFD, handle, dst, syncHandle, 0, 0)) { Debug::log(ERR, "importFromSyncFileFD: drmSyncobjTransfer failed"); drmSyncobjDestroy(drmFD, syncHandle); - return -1; + return false; } drmSyncobjDestroy(drmFD, syncHandle); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 99d1412ffba..868376f1edc 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -448,7 +448,7 @@ void CPointerManager::renderSoftwareCursorsFor(SP 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); diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index 68596ab7c5a..6846c382a39 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -147,6 +147,8 @@ class CPointerManager { CHyprSignalListener destroySurface; CHyprSignalListener commitSurface; + SP waitTimeline = nullptr; + uint64_t waitPoint = 0; } currentCursorImage; // TODO: support various sizes per-output so we can have pixel-perfect cursors Vector2D pointerPos = {0, 0}; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index c9095e03c6a..6fad79cca77 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -447,21 +447,23 @@ void CWLSurfaceResource::commitPendingState() { } } -void CWLSurfaceResource::presentFeedback(timespec* when, CMonitor* pMonitor) { +void CWLSurfaceResource::presentFeedback(timespec* when, CMonitor* pMonitor, bool needsExplicitSync) { frame(when); auto FEEDBACK = makeShared(self.lock()); FEEDBACK->attachMonitor(pMonitor); FEEDBACK->discarded(); PROTO::presentation->queueData(FEEDBACK); - if (!pMonitor || !pMonitor->outTimeline || !syncobj) + if (!pMonitor || !pMonitor->outTimeline || !syncobj || !needsExplicitSync) return; // attach explicit sync g_pHyprRenderer->explicitPresented.emplace_back(self.lock()); - if (syncobj->acquirePoint > pMonitor->lastWaitPoint) + if (syncobj->acquirePoint > pMonitor->lastWaitPoint) { + Debug::log(TRACE, "presentFeedback lastWaitPoint {} -> {}", pMonitor->lastWaitPoint, syncobj->acquirePoint); pMonitor->lastWaitPoint = syncobj->acquirePoint; + } } CWLCompositorResource::CWLCompositorResource(SP resource_) : resource(resource_) { diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index 0d85a5c9ed6..5e6413c80f6 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -122,7 +122,7 @@ class CWLSurfaceResource { void breadthfirst(std::function, const Vector2D&, void*)> fn, void* data); CRegion accumulateCurrentBufferDamage(); - void presentFeedback(timespec* when, CMonitor* pMonitor); + void presentFeedback(timespec* when, CMonitor* pMonitor, bool needsExplicitSync = false); void lockPendingState(); void unlockPendingState(); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index a7e0e2aa25d..6a632e200d7 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1255,16 +1255,17 @@ void CHyprOpenGLImpl::renderTexture(SP tex, CBox* pBox, float alpha, i scissor((CBox*)nullptr); } -void CHyprOpenGLImpl::renderTextureWithDamage(SP tex, CBox* pBox, CRegion* damage, float alpha, int round, bool discardActive, bool allowCustomUV) { +void CHyprOpenGLImpl::renderTextureWithDamage(SP tex, CBox* pBox, CRegion* damage, float alpha, int round, bool discardActive, bool allowCustomUV, + SP waitTimeline, uint64_t waitPoint) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); - renderTextureInternalWithDamage(tex, pBox, alpha, damage, round, discardActive, false, allowCustomUV, true); + renderTextureInternalWithDamage(tex, pBox, alpha, damage, round, discardActive, false, allowCustomUV, true, waitTimeline, waitPoint); scissor((CBox*)nullptr); } void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA, bool allowCustomUV, - bool allowDim) { + bool allowDim, SP waitTimeline, uint64_t waitPoint) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT((tex->m_iTexID > 0), "Attempted to draw NULL texture!"); @@ -1289,6 +1290,13 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB float glMatrix[9]; matrixMultiply(glMatrix, m_RenderData.projection, matrix); + if (waitTimeline != nullptr) { + if (!waitForTimelinePoint(waitTimeline, waitPoint)) { + Debug::log(ERR, "renderTextureInternalWithDamage: failed to wait for explicit sync point {}", waitPoint); + return; + } + } + CShader* shader = nullptr; bool usingFinalShader = false; @@ -2744,20 +2752,24 @@ std::vector CHyprOpenGLImpl::getDRMFormats() { SP CHyprOpenGLImpl::createEGLSync(int fenceFD) { std::vector attribs; - int dupFd = fcntl(fenceFD, F_DUPFD_CLOEXEC, 0); - if (dupFd < 0) { - Debug::log(ERR, "createEGLSync: dup failed"); - return nullptr; - } + int dupFd = -1; + if (fenceFD > 0) { + int dupFd = fcntl(fenceFD, F_DUPFD_CLOEXEC, 0); + if (dupFd < 0) { + Debug::log(ERR, "createEGLSync: dup failed"); + return nullptr; + } - attribs.push_back(EGL_SYNC_NATIVE_FENCE_FD_ANDROID); - attribs.push_back(dupFd); - attribs.push_back(EGL_NONE); + attribs.push_back(EGL_SYNC_NATIVE_FENCE_FD_ANDROID); + attribs.push_back(dupFd); + attribs.push_back(EGL_NONE); + } EGLSyncKHR sync = m_sProc.eglCreateSyncKHR(m_pEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs.data()); if (sync == EGL_NO_SYNC_KHR) { Debug::log(ERR, "eglCreateSyncKHR failed"); - close(dupFd); + if (dupFd >= 0) + close(dupFd); return nullptr; } @@ -2766,6 +2778,28 @@ SP CHyprOpenGLImpl::createEGLSync(int fenceFD) { return eglsync; } +bool CHyprOpenGLImpl::waitForTimelinePoint(SP timeline, uint64_t point) { + int fd = timeline->exportAsSyncFileFD(point); + if (fd < 0) { + Debug::log(ERR, "waitForTimelinePoint: failed to get a fd from explicit timeline"); + return false; + } + + auto sync = g_pHyprOpenGL->createEGLSync(fd); + close(fd); + if (!sync) { + Debug::log(ERR, "waitForTimelinePoint: failed to get an eglsync from explicit timeline"); + return false; + } + + if (!sync->wait()) { + Debug::log(ERR, "waitForTimelinePoint: failed to wait on an eglsync from explicit timeline"); + return false; + } + + return true; +} + void SRenderModifData::applyToBox(CBox& box) { if (!enabled) return; diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 4c972a8f76b..712b87f33b8 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -6,6 +6,8 @@ #include "../helpers/Timer.hpp" #include "../helpers/math/Math.hpp" #include "../helpers/Format.hpp" +#include "../helpers/sync/SyncTimeline.hpp" +#include #include #include #include @@ -152,7 +154,8 @@ class CHyprOpenGLImpl { void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f, bool xray = false); void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0); void renderTexture(SP, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); - void renderTextureWithDamage(SP, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); + void renderTextureWithDamage(SP, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false, + SP waitTimeline = nullptr, uint64_t waitPoint = 0); void renderTextureWithBlur(SP, CBox*, float a, SP pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0); void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); @@ -203,6 +206,7 @@ class CHyprOpenGLImpl { std::vector getDRMFormats(); EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); SP createEGLSync(int fenceFD); + bool waitForTimelinePoint(SP timeline, uint64_t point); SCurrentRenderData m_RenderData; @@ -284,7 +288,7 @@ class CHyprOpenGLImpl { CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage); void renderTextureInternalWithDamage(SP, CBox* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false, - bool allowCustomUV = false, bool allowDim = false); + bool allowCustomUV = false, bool allowDim = false, SP = nullptr, uint64_t waitPoint = 0); void renderTexturePrimitive(SP tex, CBox* pBox); void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index fe7cab96cbe..90e3ea652de 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -17,6 +17,7 @@ #include "../protocols/DRMSyncobj.hpp" #include "../protocols/LinuxDMABUF.hpp" #include "../helpers/sync/SyncTimeline.hpp" +#include "debug/Log.hpp" extern "C" { #include @@ -114,21 +115,8 @@ static void renderSurface(SP surface, int x, int y, void* da // explicit sync: wait for the timeline, if any if (surface->syncobj && surface->syncobj->acquireTimeline) { - int fd = surface->syncobj->acquireTimeline->timeline->exportAsSyncFileFD(surface->syncobj->acquirePoint); - if (fd < 0) { - Debug::log(ERR, "Renderer: failed to get a fd from explicit timeline"); - return; - } - - auto sync = g_pHyprOpenGL->createEGLSync(fd); - close(fd); - if (!sync) { - Debug::log(ERR, "Renderer: failed to get an eglsync from explicit timeline"); - return; - } - - if (!sync->wait()) { - Debug::log(ERR, "Renderer: failed to wait on an eglsync from explicit timeline"); + if (!g_pHyprOpenGL->waitForTimelinePoint(surface->syncobj->acquireTimeline->timeline, surface->syncobj->acquirePoint)) { + Debug::log(ERR, "Renderer: failed to wait for explicit timeline"); return; } } @@ -191,8 +179,10 @@ static void renderSurface(SP surface, int x, int y, void* da } if (windowBox.width <= 1 || windowBox.height <= 1) { - if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) + if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { + Debug::log(TRACE, "presentFeedback for invisible surface"); surface->presentFeedback(RDATA->when, RDATA->pMonitor); + } return; // invisible } @@ -245,8 +235,10 @@ static void renderSurface(SP surface, int x, int y, void* da g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, false, true); } - if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) + if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { + Debug::log(TRACE, "presentFeedback for visible surface"); surface->presentFeedback(RDATA->when, RDATA->pMonitor); + } g_pHyprOpenGL->blend(true); @@ -1099,8 +1091,10 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { if (!pMonitor->mirrors.empty() || pMonitor->isMirror() || m_bDirectScanoutBlocked) return false; // do not DS if this monitor is being mirrored. Will break the functionality. - if (g_pPointerManager->softwareLockedFor(pMonitor->self.lock())) + if (g_pPointerManager->softwareLockedFor(pMonitor->self.lock())) { + Debug::log(TRACE, "Direct scanout failed: soft locked / HW cursors failed"); return false; + } const auto PCANDIDATE = pMonitor->solitaryClient.lock(); @@ -1126,7 +1120,8 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - PSURFACE->presentFeedback(&now, pMonitor); + Debug::log(TRACE, "presentFeedback for DS"); + PSURFACE->presentFeedback(&now, pMonitor, true); if (pMonitor->state.commit()) { if (m_pLastScanout.expired()) { @@ -1458,16 +1453,27 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { // apply timelines for explicit sync bool anyExplicit = !explicitPresented.empty(); if (anyExplicit) { - pMonitor->output->state->setExplicitInFence(pMonitor->inTimeline->exportAsSyncFileFD(pMonitor->lastWaitPoint)); + Debug::log(TRACE, "Explicit sync presented begin"); + auto inFence = pMonitor->inTimeline->exportAsSyncFileFD(pMonitor->lastWaitPoint); + if (inFence < 0) + Debug::log(ERR, "Export lastWaitPoint {} as sync explicitInFence failed", pMonitor->lastWaitPoint); + + pMonitor->output->state->setExplicitInFence(inFence); for (auto& e : explicitPresented) { + Debug::log(TRACE, "Explicit sync presented releasePoint {}", e->syncobj && e->syncobj->releaseTimeline ? e->syncobj->releasePoint : -1); if (!e->syncobj || !e->syncobj->releaseTimeline) continue; e->syncobj->releaseTimeline->timeline->transfer(pMonitor->outTimeline, pMonitor->commitSeq, e->syncobj->releasePoint); } explicitPresented.clear(); - pMonitor->output->state->setExplicitOutFence(pMonitor->outTimeline->exportAsSyncFileFD(pMonitor->commitSeq)); + auto outFence = pMonitor->outTimeline->exportAsSyncFileFD(pMonitor->commitSeq); + if (outFence < 0) + Debug::log(ERR, "Export commitSeq {} as sync explicitOutFence failed", pMonitor->commitSeq); + + pMonitor->output->state->setExplicitOutFence(outFence); + Debug::log(TRACE, "Explicit sync presented end"); } pMonitor->lastWaitPoint = 0; @@ -1475,23 +1481,25 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { const auto COMMITTED_OUT = pMonitor->output->state->state().explicitOutFence; const auto COMMITTED_IN = pMonitor->output->state->state().explicitInFence; - if (!pMonitor->state.commit()) { + bool commited = pMonitor->state.commit(); + if (!commited) { + Debug::log(TRACE, "Monitor state commit failed"); // rollback the buffer to avoid writing to the front buffer that is being // displayed pMonitor->output->swapchain->rollback(); pMonitor->damage.damageEntire(); - return false; } if (COMMITTED_IN >= 0) close(COMMITTED_IN); if (COMMITTED_OUT >= 0) { - pMonitor->outTimeline->importFromSyncFileFD(pMonitor->commitSeq, COMMITTED_OUT); + if (commited) + pMonitor->outTimeline->importFromSyncFileFD(pMonitor->commitSeq, COMMITTED_OUT); close(COMMITTED_OUT); } - return true; + return commited; } void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry) { @@ -2687,13 +2695,10 @@ void CHyprRenderer::endRender() { if (m_eRenderMode == RENDER_MODE_FULL_FAKE) return; - if (isNvidia() && *PNVIDIAANTIFLICKER) - glFinish(); - if (m_eRenderMode == RENDER_MODE_NORMAL) { PMONITOR->output->state->setBuffer(m_pCurrentBuffer); - if (PMONITOR->output->state->state().explicitOutFence >= 0) { + if (PMONITOR->inTimeline) { auto sync = g_pHyprOpenGL->createEGLSync(-1); if (!sync) { m_pCurrentRenderbuffer->unbind(); @@ -2713,7 +2718,7 @@ void CHyprRenderer::endRender() { return; } - bool ok = PMONITOR->outTimeline->importFromSyncFileFD(PMONITOR->commitSeq, dupedfd); + bool ok = PMONITOR->inTimeline->importFromSyncFileFD(PMONITOR->commitSeq, dupedfd); close(dupedfd); if (!ok) { m_pCurrentRenderbuffer->unbind(); @@ -2722,8 +2727,12 @@ void CHyprRenderer::endRender() { Debug::log(ERR, "renderer: couldn't import from sync file fd in endRender"); return; } - } else - glFlush(); + } else { + if (isNvidia() && *PNVIDIAANTIFLICKER) + glFinish(); + else + glFlush(); + } } m_pCurrentRenderbuffer->unbind(); From 1fcb8cc1625b07668fb086abe6f89aa2b84c02e4 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 10 Jul 2024 23:51:53 +0200 Subject: [PATCH 081/113] swapchain test stuff --- src/helpers/Monitor.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index a65492df7cf..39aac1fe06e 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -802,6 +802,14 @@ bool CMonitorState::commit() { bool CMonitorState::test() { if (!updateSwapchain()) return false; + + // if it has no buffer, attach one from the swapchain to test it + if (!m_pOwner->output->state->state().buffer) { + Debug::log(LOG, "CMonitorState::test: no buffer, attaching one from the swapchain for modeset being possible"); + m_pOwner->output->state->setBuffer(m_pOwner->output->swapchain->next(nullptr)); + m_pOwner->output->swapchain->rollback(); // restore the counter, don't advance the swapchain + } + return m_pOwner->output->test(); } @@ -809,8 +817,10 @@ bool CMonitorState::updateSwapchain() { auto options = m_pOwner->output->swapchain->currentOptions(); const auto& STATE = m_pOwner->output->state->state(); const auto& MODE = STATE.mode ? STATE.mode : STATE.customMode; - if (!MODE) + if (!MODE) { + Debug::log(WARN, "updateSwapchain: No mode?"); return true; + } options.format = STATE.drmFormat; options.scanout = true; options.length = 2; From 38867021d893ab3a5355519ad1b941ef1eec71cc Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 10 Jul 2024 23:54:24 +0200 Subject: [PATCH 082/113] better --- src/helpers/Monitor.cpp | 28 +++++++++++++++++++++------- src/helpers/Monitor.hpp | 2 ++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 39aac1fe06e..ef3facf6cf5 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -792,9 +792,28 @@ CMonitorState::~CMonitorState() { ; } +void CMonitorState::ensureBufferPresent() { + if (!m_pOwner->output->state->state().enabled) { + Debug::log(TRACE, "CMonitorState::ensureBufferPresent: Ignoring, monitor is not enabled"); + return; + } + + if (m_pOwner->output->state->state().buffer) + return; + + // this is required for modesetting being possible and might be missing in case of first tests in the renderer + // where we test modes and buffers + Debug::log(LOG, "CMonitorState::ensureBufferPresent: no buffer, attaching one from the swapchain for modeset being possible"); + m_pOwner->output->state->setBuffer(m_pOwner->output->swapchain->next(nullptr)); + m_pOwner->output->swapchain->rollback(); // restore the counter, don't advance the swapchain +} + bool CMonitorState::commit() { if (!updateSwapchain()) return false; + + ensureBufferPresent(); + bool ret = m_pOwner->output->commit(); return ret; } @@ -802,13 +821,8 @@ bool CMonitorState::commit() { bool CMonitorState::test() { if (!updateSwapchain()) return false; - - // if it has no buffer, attach one from the swapchain to test it - if (!m_pOwner->output->state->state().buffer) { - Debug::log(LOG, "CMonitorState::test: no buffer, attaching one from the swapchain for modeset being possible"); - m_pOwner->output->state->setBuffer(m_pOwner->output->swapchain->next(nullptr)); - m_pOwner->output->swapchain->rollback(); // restore the counter, don't advance the swapchain - } + + ensureBufferPresent(); return m_pOwner->output->test(); } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 7488d7dcb59..7a4c75af5e6 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -52,6 +52,8 @@ class CMonitorState { bool updateSwapchain(); private: + void ensureBufferPresent(); + CMonitor* m_pOwner; }; From 0f09940c327dc4f3feffc48d256181b9d77746da Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 11 Jul 2024 12:10:45 +0200 Subject: [PATCH 083/113] fix xwayland crash thanks ikalco --- src/devices/IKeyboard.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index 125381bacbb..3e69bfd8e44 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -116,10 +116,9 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) { if (IDX != XKB_MOD_INVALID) modifiersState.locked |= (uint32_t)1 << IDX; - } - if (modifiersState.locked != 0) - keyboardEvents.modifiers.emit(SModifiersEvent{.locked = modifiersState.locked}); + updateModifiers(modifiersState.depressed, modifiersState.latched, modifiersState.locked, modifiersState.group); + } for (size_t i = 0; i < LEDNAMES.size(); ++i) { ledIndexes.at(i) = xkb_map_led_get_index(xkbKeymap, LEDNAMES.at(i)); From 628961295859684dacb7eddb3fd21f5b89ab9b51 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Thu, 11 Jul 2024 17:15:04 +0300 Subject: [PATCH 084/113] reset explicit fences before commit (#6841) --- src/render/Renderer.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 90e3ea652de..01fd1922128 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1451,6 +1451,8 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { // apply timelines for explicit sync + pMonitor->output->state->resetExplicitFences(); + bool anyExplicit = !explicitPresented.empty(); if (anyExplicit) { Debug::log(TRACE, "Explicit sync presented begin"); @@ -1478,10 +1480,7 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { pMonitor->lastWaitPoint = 0; - const auto COMMITTED_OUT = pMonitor->output->state->state().explicitOutFence; - const auto COMMITTED_IN = pMonitor->output->state->state().explicitInFence; - - bool commited = pMonitor->state.commit(); + bool commited = pMonitor->state.commit(); if (!commited) { Debug::log(TRACE, "Monitor state commit failed"); // rollback the buffer to avoid writing to the front buffer that is being @@ -1490,13 +1489,13 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { pMonitor->damage.damageEntire(); } - if (COMMITTED_IN >= 0) - close(COMMITTED_IN); + if (pMonitor->output->state->state().explicitInFence >= 0) + close(pMonitor->output->state->state().explicitInFence); - if (COMMITTED_OUT >= 0) { + if (pMonitor->output->state->state().explicitOutFence >= 0) { if (commited) - pMonitor->outTimeline->importFromSyncFileFD(pMonitor->commitSeq, COMMITTED_OUT); - close(COMMITTED_OUT); + pMonitor->outTimeline->importFromSyncFileFD(pMonitor->commitSeq, pMonitor->output->state->state().explicitOutFence); + close(pMonitor->output->state->state().explicitOutFence); } return commited; From d786094fb9958fb7b8e519461737ac7c50e1872d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 11 Jul 2024 20:42:03 +0200 Subject: [PATCH 085/113] stuff --- src/helpers/Monitor.cpp | 1 - src/render/OpenGL.cpp | 6 ------ 2 files changed, 7 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index ef3facf6cf5..077edff12e6 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -839,6 +839,5 @@ bool CMonitorState::updateSwapchain() { options.scanout = true; options.length = 2; options.size = MODE->pixelSize; - options.multigpu = m_pOwner->output->swapchain->getAllocator()->drmFD() != g_pCompositor->m_iDRMFD; return m_pOwner->output->swapchain->reconfigure(options); } diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 6a632e200d7..5326442d2e0 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -530,12 +530,6 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { static auto PBLURSPECIAL = CConfigValue("decoration:blur:special"); static auto PBLURPOPUPS = CConfigValue("decoration:blur:popups"); - // multigpu destination - if (pMonitor->output->swapchain->getAllocator()->drmFD() != g_pCompositor->m_iDRMFD) { - Debug::log(TRACE, "passRequiresIntrospection: multigpu target, forcing"); - return true; - } - if (m_RenderData.mouseZoomFactor != 1.0 || g_pHyprRenderer->m_bCrashingInProgress) return true; From aa6ae138454ffd350c490d654ea97947eca2a99d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 12 Jul 2024 00:18:33 +0200 Subject: [PATCH 086/113] make explicit sync setting actually disable it --- src/render/Renderer.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 01fd1922128..b6294fc48ea 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1450,6 +1450,8 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { + static auto PENABLEEXPLICIT = CConfigValue("experimental:explicit_sync"); + // apply timelines for explicit sync pMonitor->output->state->resetExplicitFences(); @@ -1480,8 +1482,8 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { pMonitor->lastWaitPoint = 0; - bool commited = pMonitor->state.commit(); - if (!commited) { + bool ok = pMonitor->state.commit(); + if (!ok) { Debug::log(TRACE, "Monitor state commit failed"); // rollback the buffer to avoid writing to the front buffer that is being // displayed @@ -1489,16 +1491,19 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { pMonitor->damage.damageEntire(); } + if (!*PENABLEEXPLICIT) + return ok; + if (pMonitor->output->state->state().explicitInFence >= 0) close(pMonitor->output->state->state().explicitInFence); if (pMonitor->output->state->state().explicitOutFence >= 0) { - if (commited) + if (ok) pMonitor->outTimeline->importFromSyncFileFD(pMonitor->commitSeq, pMonitor->output->state->state().explicitOutFence); close(pMonitor->output->state->state().explicitOutFence); } - return commited; + return ok; } void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry) { @@ -2680,6 +2685,7 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode void CHyprRenderer::endRender() { const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor; static auto PNVIDIAANTIFLICKER = CConfigValue("opengl:nvidia_anti_flicker"); + static auto PENABLEEXPLICIT = CConfigValue("experimental:explicit_sync"); PMONITOR->commitSeq++; @@ -2697,7 +2703,7 @@ void CHyprRenderer::endRender() { if (m_eRenderMode == RENDER_MODE_NORMAL) { PMONITOR->output->state->setBuffer(m_pCurrentBuffer); - if (PMONITOR->inTimeline) { + if (PMONITOR->inTimeline && *PENABLEEXPLICIT) { auto sync = g_pHyprOpenGL->createEGLSync(-1); if (!sync) { m_pCurrentRenderbuffer->unbind(); From 8ea06338f984eff27f06a6df5a19229c135e1c91 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Fri, 12 Jul 2024 10:06:13 +0300 Subject: [PATCH 087/113] add scheduleFrame reasons (#6799) --- src/Compositor.cpp | 7 ++++--- src/Compositor.hpp | 2 +- src/events/Monitors.cpp | 3 ++- src/helpers/Monitor.cpp | 22 ++++++++++++---------- src/managers/AnimationManager.cpp | 2 +- src/managers/CursorManager.cpp | 2 +- src/managers/PointerManager.cpp | 2 +- src/managers/input/InputManager.cpp | 5 +++-- src/render/Renderer.cpp | 9 +++++---- 9 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index dda89d3a1cc..41d6d848d49 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -6,6 +6,7 @@ #include "managers/PointerManager.hpp" #include "managers/SeatManager.hpp" #include "managers/eventLoop/EventLoopManager.hpp" +#include #include #include #include @@ -2373,7 +2374,7 @@ void CCompositor::updateWorkspaceWindowData(const int& id) { } } -void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor) { +void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor, IOutput::scheduleFrameReason reason) { if ((m_pAqBackend->hasSession() && !m_pAqBackend->session->active) || !m_bSessionActive) return; @@ -2383,7 +2384,7 @@ void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor) { if (pMonitor->renderingActive) pMonitor->pendingFrame = true; - pMonitor->output->scheduleFrame(); + pMonitor->output->scheduleFrame(reason); } PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp) { @@ -2966,7 +2967,7 @@ void CCompositor::onNewMonitor(SP output) { g_pCompositor->m_bReadyToProcess = true; g_pConfigManager->m_bWantsMonitorReload = true; - g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get()); + g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get(), IOutput::AQ_SCHEDULE_NEW_MONITOR); checkDefaultCursorWarp(PNEWMONITOR, output->name); diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 3773829541a..58c5b33d42a 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -148,7 +148,7 @@ class CCompositor { void setWindowFullscreen(PHLWINDOW, bool, eFullscreenMode mode = FULLSCREEN_INVALID); void updateFullscreenFadeOnWorkspace(PHLWORKSPACE); PHLWINDOW getX11Parent(PHLWINDOW); - void scheduleFrameForMonitor(CMonitor*); + void scheduleFrameForMonitor(CMonitor*, Aquamarine::IOutput::scheduleFrameReason reason = Aquamarine::IOutput::AQ_SCHEDULE_CLIENT_UNKNOWN); void addToFadingOutSafe(PHLLS); void removeFromFadingOutSafe(PHLLS); void addToFadingOutSafe(PHLWINDOW); diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 573eb52d1bc..40b6f17ef1b 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -5,6 +5,7 @@ #include "Events.hpp" #include "../debug/HyprCtl.hpp" #include "../config/ConfigValue.hpp" +#include // --------------------------------------------------------- // // __ __ ____ _ _ _____ _______ ____ _____ _____ // @@ -110,7 +111,7 @@ void Events::listener_monitorDestroy(void* owner, void* data) { void Events::listener_monitorNeedsFrame(void* owner, void* data) { const auto PMONITOR = (CMonitor*)owner; - g_pCompositor->scheduleFrameForMonitor(PMONITOR); + g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); } void Events::listener_monitorCommit(void* owner, void* data) { diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 077edff12e6..77145c612cd 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -11,6 +11,7 @@ #include "../protocols/core/Output.hpp" #include "../managers/PointerManager.hpp" #include "sync/SyncTimeline.hpp" +#include #include using namespace Hyprutils::String; @@ -35,11 +36,12 @@ void CMonitor::onConnect(bool noRule) { outTimeline = CSyncTimeline::create(output->getBackend()->drmFD()); } - listeners.frame = output->events.frame.registerListener([this](std::any d) { Events::listener_monitorFrame(this, nullptr); }); - listeners.destroy = output->events.destroy.registerListener([this](std::any d) { Events::listener_monitorDestroy(this, nullptr); }); - listeners.commit = output->events.commit.registerListener([this](std::any d) { Events::listener_monitorCommit(this, nullptr); }); - listeners.needsFrame = output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(this); }); - listeners.presented = output->events.present.registerListener([this](std::any d) { + listeners.frame = output->events.frame.registerListener([this](std::any d) { Events::listener_monitorFrame(this, nullptr); }); + listeners.destroy = output->events.destroy.registerListener([this](std::any d) { Events::listener_monitorDestroy(this, nullptr); }); + listeners.commit = output->events.commit.registerListener([this](std::any d) { Events::listener_monitorCommit(this, nullptr); }); + listeners.needsFrame = + output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); }); + listeners.presented = output->events.present.registerListener([this](std::any d) { auto E = std::any_cast(d); PROTO::presentation->onPresented(this, E.when, E.refresh, E.seq, E.flags); }); @@ -197,7 +199,7 @@ void CMonitor::onConnect(bool noRule) { renderTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, ratHandler, this); - g_pCompositor->scheduleFrameForMonitor(this); + g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_NEW_MONITOR); PROTO::gamma->applyGammaToState(this); @@ -325,9 +327,9 @@ void CMonitor::addDamage(const pixman_region32_t* rg) { static auto PZOOMFACTOR = CConfigValue("cursor:zoom_factor"); if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { damage.damageEntire(); - g_pCompositor->scheduleFrameForMonitor(this); + g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } else if (damage.damage(rg)) - g_pCompositor->scheduleFrameForMonitor(this); + g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } void CMonitor::addDamage(const CRegion* rg) { @@ -338,11 +340,11 @@ void CMonitor::addDamage(const CBox* box) { static auto PZOOMFACTOR = CConfigValue("cursor:zoom_factor"); if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { damage.damageEntire(); - g_pCompositor->scheduleFrameForMonitor(this); + g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } if (damage.damage(*box)) - g_pCompositor->scheduleFrameForMonitor(this); + g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() { diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 677b2109447..dcc7a45ff26 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -259,7 +259,7 @@ void CAnimationManager::tick() { // manually schedule a frame if (PMONITOR) - g_pCompositor->scheduleFrameForMonitor(PMONITOR); + g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); } // do it here, because if this alters the animation vars deque we would be in trouble above. diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 8e8cf1db21c..3a13d10bfed 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -277,7 +277,7 @@ void CCursorManager::updateTheme() { for (auto& m : g_pCompositor->m_vMonitors) { m->forceFullFrames = 5; - g_pCompositor->scheduleFrameForMonitor(m.get()); + g_pCompositor->scheduleFrameForMonitor(m.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); } } diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 868376f1edc..950032a4cb3 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -342,7 +342,7 @@ bool CPointerManager::setHWCursorBuffer(SP state, SPcursorFrontBuffer = buf; - g_pCompositor->scheduleFrameForMonitor(state->monitor.get()); + g_pCompositor->scheduleFrameForMonitor(state->monitor.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); return true; } diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 2db9de6f4bf..255023b9255 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1,5 +1,6 @@ #include "InputManager.hpp" #include "../../Compositor.hpp" +#include #include #include #include "../../config/ConfigValue.hpp" @@ -191,7 +192,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { bool skipFrameSchedule = PMONITOR->shouldSkipScheduleFrameOnMouseEvent(); if (!PMONITOR->solitaryClient.lock() && g_pHyprRenderer->shouldRenderCursor() && g_pPointerManager->softwareLockedFor(PMONITOR->self.lock()) && !skipFrameSchedule) - g_pCompositor->scheduleFrameForMonitor(PMONITOR); + g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_MOVE); PHLWINDOW forcedFocus = m_pForcedFocus.lock(); @@ -374,7 +375,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords, &pFoundLayerSurface); if (g_pPointerManager->softwareLockedFor(PMONITOR->self.lock()) > 0 && !skipFrameSchedule) - g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get()); + g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_MOVE); // grabs if (g_pSeatManager->seatGrab && !g_pSeatManager->seatGrab->accepts(foundSurface)) { diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index b6294fc48ea..00c488e350b 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2,6 +2,7 @@ #include "../Compositor.hpp" #include "../helpers/math/Math.hpp" #include +#include #include #include "../config/ConfigValue.hpp" #include "../managers/CursorManager.hpp" @@ -1187,7 +1188,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { pMonitor->framesToSkip -= 1; if (!pMonitor->noFrameSchedule) - g_pCompositor->scheduleFrameForMonitor(pMonitor); + g_pCompositor->scheduleFrameForMonitor(pMonitor, Aquamarine::IOutput::AQ_SCHEDULE_RENDER_MONITOR); else Debug::log(LOG, "NoFrameSchedule hit for {}.", pMonitor->szName); @@ -1432,7 +1433,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { pMonitor->tearingState.busy = true; if (*PDAMAGEBLINK || *PVFR == 0 || pMonitor->pendingFrame) - g_pCompositor->scheduleFrameForMonitor(pMonitor); + g_pCompositor->scheduleFrameForMonitor(pMonitor, Aquamarine::IOutput::AQ_SCHEDULE_RENDER_MONITOR); pMonitor->pendingFrame = false; @@ -1750,7 +1751,7 @@ void CHyprRenderer::damageSurface(SP pSurface, double x, dou damageBox.scale(scale); // schedule frame events - g_pCompositor->scheduleFrameForMonitor(g_pCompositor->getMonitorFromVector(Vector2D(x, y))); + g_pCompositor->scheduleFrameForMonitor(g_pCompositor->getMonitorFromVector(Vector2D(x, y)), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); if (damageBox.empty()) return; @@ -1868,7 +1869,7 @@ void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, const CRegion& pRegion mirror->addDamage(&transformed); - g_pCompositor->scheduleFrameForMonitor(mirror); + g_pCompositor->scheduleFrameForMonitor(mirror, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } } From fe2fe1f3594361ec76d0f360c9872283dc9a599f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 12 Jul 2024 18:46:37 +0200 Subject: [PATCH 088/113] viewporter stuff --- src/protocols/Viewporter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocols/Viewporter.cpp b/src/protocols/Viewporter.cpp index 7fa45e69b09..03c5775ee4e 100644 --- a/src/protocols/Viewporter.cpp +++ b/src/protocols/Viewporter.cpp @@ -54,13 +54,13 @@ CViewportResource::CViewportResource(SP resource_, SPevents.precommit.registerListener([this](std::any d) { - if (!surface) + if (!surface || !surface->pending.buffer) return; if (surface->pending.viewport.hasSource) { auto& src = surface->pending.viewport.source; - if (src.w + src.x > surface->pending.size.x || src.h + src.y > surface->pending.size.y) { + if (src.w + src.x > surface->pending.buffer->size.x || src.h + src.y > surface->pending.buffer->size.y) { resource->error(WP_VIEWPORT_ERROR_BAD_VALUE, "Box doesn't fit"); surface->pending.rejected = true; return; From 955ee5f1bb6d81689898e315c92ee59fd6ba8b2e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 12 Jul 2024 18:52:08 +0200 Subject: [PATCH 089/113] thanks ikalco --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ddd1ad6b28f..e951b8740b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -308,8 +308,8 @@ install(TARGETS Hyprland) install(CODE "execute_process( \ COMMAND ${CMAKE_COMMAND} -E create_symlink \ - ${CMAKE_INSTALL_BINDIR}/Hyprland \ - ${CMAKE_INSTALL_BINDIR}/hyprland + ${CMAKE_INSTALL_FULL_BINDIR}/Hyprland \ + ${CMAKE_INSTALL_FULL_BINDIR}/hyprland )" ) From af4a13452bc4046e2ad64abbc9ae3447192dbbf2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 13 Jul 2024 12:30:16 +0200 Subject: [PATCH 090/113] thanks ikalco --- src/protocols/LinuxDMABUF.cpp | 20 ++--------- src/render/OpenGL.cpp | 18 +--------- src/render/Renderer.cpp | 66 +++++++++++++++++------------------ 3 files changed, 36 insertions(+), 68 deletions(-) diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 862fb4d7ed6..1b4391a65e8 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -393,25 +393,9 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const mainDevice = *dev; // FIXME: this will break on multi-gpu - std::vector aqFormats; - for (auto& impl : g_pCompositor->m_pAqBackend->getImplementations()) { - if (impl->type() != Aquamarine::AQ_BACKEND_DRM) - continue; - aqFormats = impl->getRenderFormats(); - if (!aqFormats.empty()) - break; - } - - if (aqFormats.empty()) { - // fallback: use EGL formats - for (auto& fmt : g_pHyprOpenGL->getDRMFormats()) { - aqFormats.emplace_back(Aquamarine::SDRMFormat{ - .drmFormat = fmt.drmFormat, - .modifiers = fmt.modifiers, - }); - } - } + std::vector aqFormats = g_pHyprOpenGL->getDRMFormats(); + // SDMABufTranche tranche = { .device = *dev, .formats = aqFormats, diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 5326442d2e0..be449dfe7d9 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2721,23 +2721,7 @@ void CHyprOpenGLImpl::setRenderModifEnabled(bool enabled) { } uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) { - GLint glf = -1, glt = -1, as = 0; - /*glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf); - glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glt); - glGetIntegerv(GL_ALPHA_BITS, &as);*/ - - if (glf == 0 || glt == 0) { - glf = FormatUtils::drmFormatToGL(pMonitor->drmFormat); - glt = FormatUtils::glFormatToType(glf); - } - - if (const auto FMT = FormatUtils::getPixelFormatFromGL(glf, glt, as > 0); FMT) - return FMT->drmFormat; - - if (m_sExts.EXT_read_format_bgra) - return DRM_FORMAT_XRGB8888; - - return DRM_FORMAT_XBGR8888; + return pMonitor->output->state->state().drmFormat; } std::vector CHyprOpenGLImpl::getDRMFormats() { diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 00c488e350b..274813d6dde 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1943,7 +1943,39 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR // Needed in case we are switching from a custom modeline to a standard mode pMonitor->customDrmMode = {}; pMonitor->currentMode = nullptr; - bool autoScale = false; + + // clang-format off + static const std::array>, 2> formats{ + std::vector>{ /* 10-bit */ + {"DRM_FORMAT_XRGB2101010", DRM_FORMAT_XRGB2101010}, {"DRM_FORMAT_XBGR2101010", DRM_FORMAT_XBGR2101010}, {"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}, {"DRM_FORMAT_INVALID", DRM_FORMAT_INVALID} + }, + std::vector>{ /* 8-bit */ + {"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}, {"DRM_FORMAT_INVALID", DRM_FORMAT_INVALID} + } + }; + // clang-format on + + bool set10bit = false; + pMonitor->drmFormat = DRM_FORMAT_INVALID; + + for (auto& fmt : formats[(int)!RULE->enable10bit]) { + pMonitor->output->state->setFormat(fmt.second); + + if (!pMonitor->state.test()) { + Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first); + } else { + Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first); + if (RULE->enable10bit && fmt.first.contains("101010")) + set10bit = true; + + pMonitor->drmFormat = fmt.second; + break; + } + } + + pMonitor->enabled10bit = set10bit; + + bool autoScale = false; if (RULE->scale > 0.1) { pMonitor->scale = RULE->scale; @@ -1955,7 +1987,6 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->setScale = pMonitor->scale; pMonitor->transform = RULE->transform; - pMonitor->output->state->setFormat(DRM_FORMAT_XBGR8888); const auto WLRREFRESHRATE = pMonitor->output->getBackend()->type() == Aquamarine::eBackendType::AQ_BACKEND_DRM ? RULE->refreshRate * 1000 : 0; @@ -2228,37 +2259,6 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } } - // clang-format off - static const std::array>, 2> formats{ - std::vector>{ /* 10-bit */ - {"DRM_FORMAT_XRGB2101010", DRM_FORMAT_XRGB2101010}, {"DRM_FORMAT_XBGR2101010", DRM_FORMAT_XBGR2101010}, {"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}, {"DRM_FORMAT_INVALID", DRM_FORMAT_INVALID} - }, - std::vector>{ /* 8-bit */ - {"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}, {"DRM_FORMAT_INVALID", DRM_FORMAT_INVALID} - } - }; - // clang-format on - - bool set10bit = false; - pMonitor->drmFormat = DRM_FORMAT_INVALID; - - for (auto& fmt : formats[(int)!RULE->enable10bit]) { - pMonitor->output->state->setFormat(fmt.second); - - if (!pMonitor->state.test()) { - Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first); - } else { - Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first); - if (RULE->enable10bit && fmt.first.contains("101010")) - set10bit = true; - - pMonitor->drmFormat = fmt.second; - break; - } - } - - pMonitor->enabled10bit = set10bit; - pMonitor->output->scheduleFrame(); if (!pMonitor->state.commit()) From e444d2a1a624f8c1f60f1e51a045cb38801a5bc8 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Sat, 13 Jul 2024 13:31:42 +0300 Subject: [PATCH 091/113] Hw cursors fix for nvidia (#6847) * logging * fallback to dump cursor copy * unmap gbm buffer when done Signed-off-by: Vaxry --- src/config/ConfigManager.cpp | 1 + src/managers/PointerManager.cpp | 34 ++++++++++++++++++++++++++++++--- src/render/Renderer.cpp | 4 +--- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index cfbd7ef9e5e..1681dea1269 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -539,6 +539,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("cursor:enable_hyprcursor", Hyprlang::INT{1}); m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1}); + m_pConfig->addConfigValue("cursor:allow_dumb_copy", Hyprlang::INT{0}); m_pConfig->addConfigValue("autogenerated", Hyprlang::INT{0}); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 950032a4cb3..cf10db71db3 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -6,6 +6,8 @@ #include "../protocols/core/Compositor.hpp" #include "eventLoop/EventLoopManager.hpp" #include "SeatManager.hpp" +#include +#include CPointerManager::CPointerManager() { hooks.monitorAdded = g_pHookSystem->hookDynamic("newMonitor", [this](void* self, SCallbackInfo& info, std::any data) { @@ -395,9 +397,35 @@ SP CPointerManager::renderHWCursorBuffer(SPmakeEGLCurrent(); g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get(); - const auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format); - if (!RBO) - return nullptr; + 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("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; + } RBO->bind(); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 274813d6dde..616904791fb 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1092,10 +1092,8 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { if (!pMonitor->mirrors.empty() || pMonitor->isMirror() || m_bDirectScanoutBlocked) return false; // do not DS if this monitor is being mirrored. Will break the functionality. - if (g_pPointerManager->softwareLockedFor(pMonitor->self.lock())) { - Debug::log(TRACE, "Direct scanout failed: soft locked / HW cursors failed"); + if (g_pPointerManager->softwareLockedFor(pMonitor->self.lock())) return false; - } const auto PCANDIDATE = pMonitor->solitaryClient.lock(); From b59c159d57f9e0fffa88bf53e92a68732b1e0219 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 13 Jul 2024 16:00:37 +0200 Subject: [PATCH 092/113] thanks virt --- src/debug/HyprCtl.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 4ea53b49bb9..76ef82180ce 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -72,7 +72,6 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer return ""; if (format == eHyprCtlOutputFormat::FORMAT_JSON) { - result += "["; result += std::format( R"#({{ @@ -115,9 +114,6 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer (m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (m->tearingState.activelyTearing ? "true" : "false"), (m->m_bEnabled ? "false" : "true"), formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); - trimTrailingComma(result); - - result += "]"; } else { result += std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" From b8192420bacf4d3b0235cdbd7fd727ff3ff1d7b6 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 14 Jul 2024 14:12:30 +0300 Subject: [PATCH 093/113] flake.lock: update --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 2f97ecda51f..04c592e50a5 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1720527052, - "narHash": "sha256-ibx5vBellJff0Hu28hDWs8BlHUoxtRuSlVHTEyDNwZI=", + "lastModified": 1720947973, + "narHash": "sha256-YbVKSB5g0UsZJKOvuigDuwJPfcJd5H0ykJWsgvyDpNo=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "e3f2c0d5cc11a22c3f8c9a723823c603f45fa67c", + "rev": "ad8261ba99f75c739deb3242913fe10da1e5aa4c", "type": "github" }, "original": { From 648b7b3b6d58caa472c76d3f7e99d332b92df0eb Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 14 Jul 2024 14:13:44 +0300 Subject: [PATCH 094/113] CI/Arch: add libxcursor --- .github/actions/setup_base/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/setup_base/action.yml b/.github/actions/setup_base/action.yml index a7b9994ca65..307cdb3f73b 100644 --- a/.github/actions/setup_base/action.yml +++ b/.github/actions/setup_base/action.yml @@ -34,6 +34,7 @@ runs: libglvnd \ libinput \ libliftoff \ + libxcursor \ libxcvt \ libxfont2 \ libxkbcommon \ From c4913662e111e87e3c0784e607f94fdff7f1c58a Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Mon, 15 Jul 2024 20:01:48 +0200 Subject: [PATCH 095/113] Aquamarine headers for no pch build and a heap use after free (#6892) * build: add includes for no precompiled headers missing includes for no precompiled headers/lto usage. * math: avoid heap use after free on destruction of hyprland transforms gets double freed in aquamarine and hyprland, instead of a global use a function-local static variable which avoids any issues related to initialization order across different translation units. --- src/Compositor.cpp | 2 + src/config/ConfigManager.cpp | 1 + src/debug/CrashReporter.cpp | 1 + src/debug/HyprCtl.cpp | 2 + src/devices/IKeyboard.cpp | 1 + src/helpers/Format.cpp | 1 + src/helpers/math/Math.cpp | 115 ++++-------------------------- src/helpers/sync/SyncTimeline.hpp | 1 + src/managers/CursorManager.hpp | 2 + src/managers/PointerManager.hpp | 1 + src/managers/ProtocolManager.cpp | 4 ++ src/plugins/PluginAPI.cpp | 1 + src/protocols/LinuxDMABUF.hpp | 2 + src/protocols/Screencopy.hpp | 1 + src/protocols/core/Compositor.cpp | 1 + src/protocols/types/WLBuffer.cpp | 1 + src/render/OpenGL.cpp | 1 + src/render/Renderbuffer.cpp | 2 + src/render/Renderbuffer.hpp | 3 + src/xwayland/Server.cpp | 1 + 20 files changed, 44 insertions(+), 100 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 41d6d848d49..7fdb906c0af 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "debug/HyprCtl.hpp" #include "debug/CrashReporter.hpp" @@ -24,6 +25,7 @@ #include "protocols/core/Compositor.hpp" #include "protocols/core/Subcompositor.hpp" #include "desktop/LayerSurface.hpp" +#include "render/Renderer.hpp" #include "xwayland/XWayland.hpp" #include diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 1681dea1269..a5f18693bcb 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -24,6 +24,7 @@ #include #include #include +#include using namespace Hyprutils::String; extern "C" char** environ; diff --git a/src/debug/CrashReporter.cpp b/src/debug/CrashReporter.cpp index ce1a92ba06f..c25212fecc7 100644 --- a/src/debug/CrashReporter.cpp +++ b/src/debug/CrashReporter.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "../plugins/PluginSystem.hpp" #include "../signal-safe.hpp" diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 76ef82180ce..61c3e4b0696 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index 3e69bfd8e44..284a8295b95 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -3,6 +3,7 @@ #include "../helpers/varlist/VarList.hpp" #include "../managers/input/InputManager.hpp" #include "../managers/SeatManager.hpp" +#include "../config/ConfigManager.hpp" #include #include #include diff --git a/src/helpers/Format.cpp b/src/helpers/Format.cpp index 8d080322b0d..afc8b1c58b7 100644 --- a/src/helpers/Format.cpp +++ b/src/helpers/Format.cpp @@ -4,6 +4,7 @@ #include "debug/Log.hpp" #include "../macros.hpp" #include +#include /* DRM formats are LE, while OGL is BE. The two primary formats diff --git a/src/helpers/math/Math.cpp b/src/helpers/math/Math.cpp index f8b61bcec36..fccfd6366a8 100644 --- a/src/helpers/math/Math.cpp +++ b/src/helpers/math/Math.cpp @@ -70,113 +70,28 @@ void matrixRotate(float mat[9], float rad) { matrixMultiply(mat, mat, rotate); } -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, - }}, -}; +const std::unordered_map>& getTransforms() { + 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}}, + }; + return transforms; +} void matrixTransform(float mat[9], eTransform transform) { - matrixMultiply(mat, mat, transforms.at(transform).data()); + matrixMultiply(mat, mat, getTransforms().at(transform).data()); } void matrixProjection(float mat[9], int width, int height, eTransform transform) { memset(mat, 0, sizeof(*mat) * 9); - const float* t = transforms.at(transform).data(); + const float* t = getTransforms().at(transform).data(); float x = 2.0f / width; float y = 2.0f / height; diff --git a/src/helpers/sync/SyncTimeline.hpp b/src/helpers/sync/SyncTimeline.hpp index 4bb8019b9f1..3d868a95892 100644 --- a/src/helpers/sync/SyncTimeline.hpp +++ b/src/helpers/sync/SyncTimeline.hpp @@ -4,6 +4,7 @@ #include #include #include +#include "../memory/Memory.hpp" /* Hyprland synchronization timelines are based on the wlroots' ones, which diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index a2e8af21f3e..4324dfb4bb8 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -6,6 +6,8 @@ #include "../includes.hpp" #include "../helpers/math/Math.hpp" #include "../helpers/memory/Memory.hpp" +#include "../macros.hpp" +#include class CWLSurface; diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index 6846c382a39..cf4f1a94cae 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -6,6 +6,7 @@ #include "../helpers/math/Math.hpp" #include "../helpers/math/Math.hpp" #include "../desktop/WLSurface.hpp" +#include "../helpers/sync/SyncTimeline.hpp" #include class CMonitor; diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 3006468f581..387cac8fb0f 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -49,6 +49,10 @@ #include "../helpers/Monitor.hpp" #include "../render/Renderer.hpp" +#include "../Compositor.hpp" + +#include +#include void CProtocolManager::onMonitorModeChange(CMonitor* pMonitor) { const bool ISMIRROR = pMonitor->isMirror(); diff --git a/src/plugins/PluginAPI.cpp b/src/plugins/PluginAPI.cpp index 6e09ba2c56f..098e3f12783 100644 --- a/src/plugins/PluginAPI.cpp +++ b/src/plugins/PluginAPI.cpp @@ -2,6 +2,7 @@ #include "../Compositor.hpp" #include "../debug/HyprCtl.hpp" #include +#include #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) #include diff --git a/src/protocols/LinuxDMABUF.hpp b/src/protocols/LinuxDMABUF.hpp index 7f252588e0a..449b4ac9ce5 100644 --- a/src/protocols/LinuxDMABUF.hpp +++ b/src/protocols/LinuxDMABUF.hpp @@ -7,6 +7,8 @@ #include "wayland.hpp" #include "linux-dmabuf-v1.hpp" #include "../helpers/signal/Signal.hpp" +#include "../helpers/Format.hpp" +#include "../helpers/Monitor.hpp" #include class CDMABuffer; diff --git a/src/protocols/Screencopy.hpp b/src/protocols/Screencopy.hpp index 063068b50db..4999773bbf5 100644 --- a/src/protocols/Screencopy.hpp +++ b/src/protocols/Screencopy.hpp @@ -8,6 +8,7 @@ #include "../managers/HookSystemManager.hpp" #include "../helpers/Timer.hpp" #include "../managers/eventLoop/EventLoopTimer.hpp" +#include class CMonitor; class IHLBuffer; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 6fad79cca77..a038bf088c8 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -8,6 +8,7 @@ #include "../../helpers/Monitor.hpp" #include "../PresentationTime.hpp" #include "../DRMSyncobj.hpp" +#include "../../render/Renderer.hpp" #define LOGM PROTO::compositor->protoLog diff --git a/src/protocols/types/WLBuffer.cpp b/src/protocols/types/WLBuffer.cpp index 7034dfc78b8..cc24546daf2 100644 --- a/src/protocols/types/WLBuffer.cpp +++ b/src/protocols/types/WLBuffer.cpp @@ -3,6 +3,7 @@ #include "../core/Compositor.hpp" #include "../DRMSyncobj.hpp" #include "../../helpers/sync/SyncTimeline.hpp" +#include "../../Compositor.hpp" #include CWLBufferResource::CWLBufferResource(SP resource_) : resource(resource_) { diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index be449dfe7d9..7870bf6d60f 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -11,6 +11,7 @@ #include #include #include +#include inline void loadGLProc(void* pProc, const char* name) { void* proc = (void*)eglGetProcAddress(name); diff --git a/src/render/Renderbuffer.cpp b/src/render/Renderbuffer.cpp index 57f4fbd21a3..58ed88d655c 100644 --- a/src/render/Renderbuffer.cpp +++ b/src/render/Renderbuffer.cpp @@ -2,6 +2,8 @@ #include "OpenGL.hpp" #include "../Compositor.hpp" #include "../protocols/types/Buffer.hpp" +#include +#include #include diff --git a/src/render/Renderbuffer.hpp b/src/render/Renderbuffer.hpp index f8155087178..e6bfa909133 100644 --- a/src/render/Renderbuffer.hpp +++ b/src/render/Renderbuffer.hpp @@ -1,5 +1,8 @@ #pragma once +#include "../helpers/signal/Signal.hpp" +#include "../helpers/memory/Memory.hpp" +#include "../helpers/WLListener.hpp" #include "Framebuffer.hpp" #include diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index 1d8b0cf5537..3f4e7b43223 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -18,6 +18,7 @@ #include #include #include +#include // TODO: cleanup static bool set_cloexec(int fd, bool cloexec) { From 65b041ddc64da5350ca3347b6b4a0a0e22525a97 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 17 Jul 2024 21:16:42 +0200 Subject: [PATCH 096/113] format --- src/debug/HyprCtl.cpp | 21 ++++++++++----------- src/devices/IKeyboard.hpp | 2 +- src/helpers/Monitor.cpp | 8 ++++---- src/helpers/Monitor.hpp | 2 +- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 61c3e4b0696..15c272d7e2e 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -157,23 +157,22 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { if (!m->output || m->ID == -1ull) continue; - result += std::format( - "Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" - "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" - "dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n", - m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription, - m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), - (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), - (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, - (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, (int)(m->output->state ? m->output->state->state().adaptiveSync : false), - m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); + result += + std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" + "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" + "dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n", + m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription, + m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), + m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, + (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, + (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, (int)(m->output->state ? m->output->state->state().adaptiveSync : false), + m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); } } return result; } - static std::string getTagsData(PHLWINDOW w, eHyprCtlOutputFormat format) { const auto tags = w->m_tags.getTags(); diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index e538bcd7054..1ae6c7bc521 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -84,7 +84,7 @@ class IKeyboard : public IHID { std::array ledIndexes = {XKB_MOD_INVALID}; std::array modIndexes = {XKB_MOD_INVALID}; - uint32_t leds = 0; + uint32_t leds = 0; std::string hlName = ""; std::string xkbFilePath = ""; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 77145c612cd..b6d2c761487 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -837,9 +837,9 @@ bool CMonitorState::updateSwapchain() { Debug::log(WARN, "updateSwapchain: No mode?"); return true; } - options.format = STATE.drmFormat; - options.scanout = true; - options.length = 2; - options.size = MODE->pixelSize; + options.format = STATE.drmFormat; + options.scanout = true; + options.length = 2; + options.size = MODE->pixelSize; return m_pOwner->output->swapchain->reconfigure(options); } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 7a4c75af5e6..6a70fc6c272 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -52,7 +52,7 @@ class CMonitorState { bool updateSwapchain(); private: - void ensureBufferPresent(); + void ensureBufferPresent(); CMonitor* m_pOwner; }; From f059851ce5b963e8d77a6164df2ecc03a3ca2299 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 17 Jul 2024 22:17:01 +0300 Subject: [PATCH 097/113] flake.lock: update --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 04c592e50a5..33112a827ba 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1720947973, - "narHash": "sha256-YbVKSB5g0UsZJKOvuigDuwJPfcJd5H0ykJWsgvyDpNo=", + "lastModified": 1721209245, + "narHash": "sha256-DPmXHln87FjuBO7ElzrmV6mChJCz0ZA7IxHfM4gi/tg=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "ad8261ba99f75c739deb3242913fe10da1e5aa4c", + "rev": "cebcba4e107fde332ff023119f9a8758aa6fd120", "type": "github" }, "original": { From 557d2ab3ed0393ef815cbe837e4c97ca88a42754 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 17 Jul 2024 21:17:23 +0200 Subject: [PATCH 098/113] ci: add aq --- .github/actions/setup_base/action.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/actions/setup_base/action.yml b/.github/actions/setup_base/action.yml index 307cdb3f73b..26660ce6df0 100644 --- a/.github/actions/setup_base/action.yml +++ b/.github/actions/setup_base/action.yml @@ -74,6 +74,11 @@ runs: run: | git clone https://github.com/hyprwm/hyprutils && cd hyprutils && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -B build && cmake --build build --target hyprutils && cmake --install build + - name: Get aquamarine-git + shell: bash + run: | + git clone https://github.com/hyprwm/aquamarine && cd aquamarine && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -B build && cmake --build build --target aquamarine && cmake --install build + - name: Get Xorg pacman pkgs shell: bash if: inputs.INSTALL_XORG_PKGS == 'true' From ed8b4b73d26cdff2414b4ad6dc1ccd26ceee55af Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 18 Jul 2024 12:35:44 +0200 Subject: [PATCH 099/113] shm drm woo --- src/protocols/core/Shm.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp index 109a7d04e18..75c2134a3e3 100644 --- a/src/protocols/core/Shm.cpp +++ b/src/protocols/core/Shm.cpp @@ -188,11 +188,19 @@ CWLSHMProtocol::CWLSHMProtocol(const wl_interface* iface, const int& ver, const void CWLSHMProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { if (shmFormats.empty()) { - size_t len = 0; - // TODO: support 10 bit shm - shmFormats.push_back(WL_SHM_FORMAT_ARGB8888); shmFormats.push_back(WL_SHM_FORMAT_XRGB8888); + + static const std::array supportedShmFourccFormats = { + DRM_FORMAT_XBGR8888, DRM_FORMAT_ABGR8888, DRM_FORMAT_XRGB2101010, DRM_FORMAT_ARGB2101010, DRM_FORMAT_XBGR2101010, DRM_FORMAT_ABGR2101010, + }; + + for (auto& fmt : g_pHyprOpenGL->getDRMFormats()) { + if (std::find(supportedShmFourccFormats.begin(), supportedShmFourccFormats.end(), fmt.drmFormat) == supportedShmFourccFormats.end()) + continue; + + shmFormats.push_back(fmt.drmFormat); + } } const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); From a0ec9261224aa54e14753f01bed47a6a0555eb58 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 18 Jul 2024 13:27:17 +0200 Subject: [PATCH 100/113] logs --- src/protocols/Screencopy.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 61ac84b1499..cdbff129b2b 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -482,8 +482,10 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* CFramebuffer fb; fb.alloc(frame->box.w, frame->box.h, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : frame->pMonitor->drmFormat); - if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) + if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) { + Debug::log(ERR, "Screencopy: can't copy: failed to begin rendering"); return false; + } CBox monbox = CBox{0, 0, frame->pMonitor->vecTransformedSize.x, frame->pMonitor->vecTransformedSize.y}.translate({-frame->box.x, -frame->box.y}); g_pHyprOpenGL->setMonitorTransformEnabled(true); @@ -500,6 +502,7 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* const auto PFORMAT = FormatUtils::getPixelFormatFromDRM(shm.format); if (!PFORMAT) { + Debug::log(ERR, "Screencopy: can't copy: failed to find a pixel format"); g_pHyprRenderer->endRender(); return false; } @@ -529,6 +532,8 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; + Debug::log(TRACE, "Screencopy: copied frame via shm"); + return true; } @@ -537,8 +542,10 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) { CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; - if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer.lock(), nullptr, true)) + if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer.lock(), nullptr, true)) { + Debug::log(ERR, "Screencopy: can't copy: failed to begin rendering to dma frame"); return false; + } CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y} .translate({-frame->box.x, -frame->box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. @@ -552,5 +559,7 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) { g_pHyprOpenGL->m_RenderData.blockScreenShader = true; g_pHyprRenderer->endRender(); + Debug::log(TRACE, "Screencopy: copied frame via dma"); + return true; } From a3770ab8b2d6bc3e837c9ac5d53edd1c60fc6403 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 18 Jul 2024 14:22:42 +0200 Subject: [PATCH 101/113] use output state format --- src/debug/HyprCtl.cpp | 6 +++--- src/helpers/Monitor.hpp | 1 - src/protocols/Screencopy.cpp | 2 +- src/protocols/ToplevelExport.cpp | 2 +- src/render/OpenGL.cpp | 22 ++++++++++++---------- src/render/Renderer.cpp | 7 ++----- 6 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 15c272d7e2e..b81cfeffd4f 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -114,7 +114,7 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer escapeJSONStrings(m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "true" : "false"), (m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (m->tearingState.activelyTearing ? "true" : "false"), - (m->m_bEnabled ? "false" : "true"), formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); + (m->m_bEnabled ? "false" : "true"), formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format)); } else { result += std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" @@ -125,7 +125,7 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, m->output->state->state().adaptiveSync, m->tearingState.activelyTearing, - !m->m_bEnabled, formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); + !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format)); } return result; @@ -166,7 +166,7 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, (int)(m->output->state ? m->output->state->state().adaptiveSync : false), - m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); + m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format)); } } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 6a70fc6c272..6a56b458c4b 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -105,7 +105,6 @@ class CMonitor { bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed. bool createdByUser = false; - uint32_t drmFormat = DRM_FORMAT_INVALID; bool isUnsafeFallback = false; bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index cdbff129b2b..5d1c9332d7c 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -480,7 +480,7 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* g_pHyprRenderer->makeEGLCurrent(); CFramebuffer fb; - fb.alloc(frame->box.w, frame->box.h, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : frame->pMonitor->drmFormat); + fb.alloc(frame->box.w, frame->box.h, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : frame->pMonitor->output->state->state().drmFormat); if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) { Debug::log(ERR, "Screencopy: can't copy: failed to begin rendering"); diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index ce74a823bfe..0e78e5f74e4 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -363,7 +363,7 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times g_pHyprRenderer->makeEGLCurrent(); CFramebuffer outFB; - outFB.alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : PMONITOR->drmFormat); + outFB.alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : PMONITOR->output->state->state().drmFormat); if (frame->overlayCursor) { g_pPointerManager->lockSoftwareForMonitor(PMONITOR->self.lock()); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 7870bf6d60f..b2b046ce5ce 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -726,10 +726,10 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, const CRegion& damage_, CFramebu m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; m_RenderData.pCurrentMonData->offMainFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; - m_RenderData.pCurrentMonData->offloadFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); - m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); - m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); - m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); + m_RenderData.pCurrentMonData->offloadFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); + m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); + m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); + m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); } if (m_RenderData.pCurrentMonData->monitorMirrorFB.isAllocated() && m_RenderData.pMonitor->mirrors.empty()) @@ -1865,7 +1865,8 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() { const auto POUTFB = blurMainFramebufferWithDamage(1, &fakeDamage); // render onto blurFB - m_RenderData.pCurrentMonData->blurFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y, m_RenderData.pMonitor->drmFormat); + m_RenderData.pCurrentMonData->blurFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y, + m_RenderData.pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->blurFB.bind(); clear(CColor(0, 0, 0, 0)); @@ -2142,7 +2143,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr pFramebuffer->m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; - pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat); + pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->output->state->state().drmFormat); g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, pFramebuffer); @@ -2195,7 +2196,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(PHLWINDOW pWindow) { const auto PFRAMEBUFFER = &m_mWindowFramebuffers[ref]; - PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat); + PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->output->state->state().drmFormat); g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, PFRAMEBUFFER); @@ -2242,7 +2243,7 @@ void CHyprOpenGLImpl::makeLayerSnapshot(PHLLS pLayer) { const auto PFRAMEBUFFER = &m_mLayerFramebuffers[pLayer]; - PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat); + PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->output->state->state().drmFormat); g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, PFRAMEBUFFER); @@ -2424,7 +2425,8 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const void CHyprOpenGLImpl::saveBufferForMirror(CBox* box) { if (!m_RenderData.pCurrentMonData->monitorMirrorFB.isAllocated()) - m_RenderData.pCurrentMonData->monitorMirrorFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y, m_RenderData.pMonitor->drmFormat); + m_RenderData.pCurrentMonData->monitorMirrorFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y, + m_RenderData.pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->monitorMirrorFB.bind(); @@ -2524,7 +2526,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { const auto PFB = &m_mMonitorBGFBs[pMonitor]; PFB->release(); - PFB->alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); + PFB->alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); Debug::log(LOG, "Allocated texture for BGTex"); // TODO: use relative paths to the installation diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 616904791fb..c14175a246f 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1953,8 +1953,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR }; // clang-format on - bool set10bit = false; - pMonitor->drmFormat = DRM_FORMAT_INVALID; + bool set10bit = false; for (auto& fmt : formats[(int)!RULE->enable10bit]) { pMonitor->output->state->setFormat(fmt.second); @@ -1965,8 +1964,6 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first); if (RULE->enable10bit && fmt.first.contains("101010")) set10bit = true; - - pMonitor->drmFormat = fmt.second; break; } } @@ -2661,7 +2658,7 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode m_pCurrentBuffer = buffer; try { - m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentBuffer, pMonitor->drmFormat); + m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentBuffer, pMonitor->output->state->state().drmFormat); } catch (std::exception& e) { Debug::log(ERR, "getOrCreateRenderbuffer failed for {}", pMonitor->szName); return false; From 0de9568da5beecac94cc64420c524bd92a2d2e17 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 18 Jul 2024 17:31:30 +0200 Subject: [PATCH 102/113] eee --- src/render/Renderer.cpp | 56 +++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index c14175a246f..2a2a3da162f 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1942,33 +1942,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->customDrmMode = {}; pMonitor->currentMode = nullptr; - // clang-format off - static const std::array>, 2> formats{ - std::vector>{ /* 10-bit */ - {"DRM_FORMAT_XRGB2101010", DRM_FORMAT_XRGB2101010}, {"DRM_FORMAT_XBGR2101010", DRM_FORMAT_XBGR2101010}, {"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}, {"DRM_FORMAT_INVALID", DRM_FORMAT_INVALID} - }, - std::vector>{ /* 8-bit */ - {"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}, {"DRM_FORMAT_INVALID", DRM_FORMAT_INVALID} - } - }; - // clang-format on - - bool set10bit = false; - - for (auto& fmt : formats[(int)!RULE->enable10bit]) { - pMonitor->output->state->setFormat(fmt.second); - - if (!pMonitor->state.test()) { - Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first); - } else { - Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first); - if (RULE->enable10bit && fmt.first.contains("101010")) - set10bit = true; - break; - } - } - - pMonitor->enabled10bit = set10bit; + pMonitor->output->state->setFormat(DRM_FORMAT_XRGB8888); bool autoScale = false; @@ -2201,6 +2175,34 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->vecPixelSize = pMonitor->vecSize; + // clang-format off + static const std::array>, 2> formats{ + std::vector>{ /* 10-bit */ + {"DRM_FORMAT_XRGB2101010", DRM_FORMAT_XRGB2101010}, {"DRM_FORMAT_XBGR2101010", DRM_FORMAT_XBGR2101010}, {"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}, {"DRM_FORMAT_INVALID", DRM_FORMAT_INVALID} + }, + std::vector>{ /* 8-bit */ + {"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}, {"DRM_FORMAT_INVALID", DRM_FORMAT_INVALID} + } + }; + // clang-format on + + bool set10bit = false; + + for (auto& fmt : formats[(int)!RULE->enable10bit]) { + pMonitor->output->state->setFormat(fmt.second); + + if (!pMonitor->state.test()) { + Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first); + } else { + Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first); + if (RULE->enable10bit && fmt.first.contains("101010")) + set10bit = true; + break; + } + } + + pMonitor->enabled10bit = set10bit; + Vector2D logicalSize = pMonitor->vecPixelSize / pMonitor->scale; if (!*PDISABLESCALECHECKS && (logicalSize.x != std::round(logicalSize.x) || logicalSize.y != std::round(logicalSize.y))) { // invalid scale, will produce fractional pixels. From 1f844610d1045a4b3c492c88cf364de1c2466a09 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Fri, 19 Jul 2024 10:56:13 -0500 Subject: [PATCH 103/113] [aquamarine] try to fix direct scanout (#6875) * make linux-dmabuf use monitor primary plane formats for ds * add support for monitor connects/disconnects in linux-dmabuf * the weird bug was because ds was global, and disabled on one monitor but enabled on the other * forgot to remove attemptDirectScanout from hyprRenderer * add renderer fallback tranche on ds and a few other improvements * use set when making format table * mitigate ds artifacting and update linux-dmabuf comments with this commit artifacting now only occurs when the client's fps is above the refresh rate of the monitor * use new backend release infra * revert earlier artifacting mitigation that broke stuff ;) * ... i should test before push ;-; --------- Co-authored-by: Vaxry --- src/helpers/Monitor.cpp | 49 +++++ src/helpers/Monitor.hpp | 4 + src/protocols/LinuxDMABUF.cpp | 285 +++++++++++++++++++----------- src/protocols/LinuxDMABUF.hpp | 33 ++-- src/protocols/core/Compositor.cpp | 10 +- src/protocols/types/Buffer.cpp | 3 +- src/protocols/types/Buffer.hpp | 4 + src/render/Renderer.cpp | 56 +----- src/render/Renderer.hpp | 14 +- 9 files changed, 281 insertions(+), 177 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index b6d2c761487..a23b98610b2 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -10,6 +10,7 @@ #include "../protocols/DRMLease.hpp" #include "../protocols/core/Output.hpp" #include "../managers/PointerManager.hpp" +#include "../protocols/core/Compositor.hpp" #include "sync/SyncTimeline.hpp" #include #include @@ -786,6 +787,54 @@ void CMonitor::scheduleDone() { doneSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, ::onDoneSource, this); } +bool CMonitor::attemptDirectScanout() { + if (!mirrors.empty() || isMirror() || g_pHyprRenderer->m_bDirectScanoutBlocked) + return false; // do not DS if this monitor is being mirrored. Will break the functionality. + + if (g_pPointerManager->softwareLockedFor(self.lock())) + return false; + + const auto PCANDIDATE = solitaryClient.lock(); + + if (!PCANDIDATE) + return false; + + const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE); + + if (!PSURFACE || !PSURFACE->current.buffer || PSURFACE->current.buffer->size != vecPixelSize || PSURFACE->current.transform != transform) + return false; + + // we can't scanout shm buffers. + if (!PSURFACE->current.buffer->dmabuf().success) + return false; + + // FIXME: make sure the buffer actually follows the available scanout dmabuf formats + // and comes from the appropriate device. This may implode on multi-gpu!! + + output->state->setBuffer(PSURFACE->current.buffer); + output->state->setPresentationMode(Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC); + + if (!state.test()) + return false; + + timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + Debug::log(TRACE, "presentFeedback for DS"); + PSURFACE->presentFeedback(&now, this, true); + + if (state.commit()) { + if (lastScanout.expired()) { + lastScanout = PCANDIDATE; + Debug::log(LOG, "Entered a direct scanout to {:x}: \"{}\"", (uintptr_t)PCANDIDATE.get(), PCANDIDATE->m_szTitle); + } + } else { + lastScanout.reset(); + return false; + } + + return true; +} + CMonitorState::CMonitorState(CMonitor* owner) { m_pOwner = owner; } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 6a56b458c4b..32fc768a16f 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -133,6 +133,9 @@ class CMonitor { // for tearing PHLWINDOWREF solitaryClient; + // for direct scanout + PHLWINDOWREF lastScanout; + struct { bool canTear = false; bool nextRenderTorn = false; @@ -174,6 +177,7 @@ class CMonitor { int64_t activeSpecialWorkspaceID(); CBox logicalBox(); void scheduleDone(); + bool attemptDirectScanout(); bool m_bEnabled = false; bool m_bRenderingInitPassed = false; diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 1b4391a65e8..0f9b67a3b62 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -23,19 +23,66 @@ static std::optional devIDFromFD(int fd) { return stat.st_rdev; } -CCompiledDMABUFFeedback::CCompiledDMABUFFeedback(dev_t device, std::vector tranches_) { +CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vector, SDMABUFTranche>> tranches_) : + rendererTranche(_rendererTranche), monitorTranches(tranches_) { + + std::vector formatsVec; std::set> formats; - for (auto& fmt : tranches_.at(0).formats /* FIXME: multigpu */) { + + // insert formats into vec if they got inserted into set, meaning they're unique + size_t i = 0; + + rendererTranche.indicies.clear(); + for (auto& fmt : rendererTranche.formats) { for (auto& mod : fmt.modifiers) { - formats.insert(std::make_pair<>(fmt.drmFormat, mod)); + auto format = std::make_pair<>(fmt.drmFormat, mod); + auto [_, inserted] = formats.insert(format); + if (inserted) { + // if it was inserted into set, then its unique and will have a new index in vec + rendererTranche.indicies.push_back(i++); + formatsVec.push_back(SDMABUFFormatTableEntry{ + .fmt = fmt.drmFormat, + .modifier = mod, + }); + } else { + // if it wasn't inserted then find its index in vec + auto it = + std::find_if(formatsVec.begin(), formatsVec.end(), [fmt, mod](const SDMABUFFormatTableEntry& oth) { return oth.fmt == fmt.drmFormat && oth.modifier == mod; }); + rendererTranche.indicies.push_back(it - formatsVec.begin()); + } + } + } + + for (auto& [monitor, tranche] : monitorTranches) { + tranche.indicies.clear(); + for (auto& fmt : tranche.formats) { + for (auto& mod : fmt.modifiers) { + // apparently these can implode on planes, so dont use them + if (mod == DRM_FORMAT_MOD_INVALID || mod == DRM_FORMAT_MOD_LINEAR) + continue; + auto format = std::make_pair<>(fmt.drmFormat, mod); + auto [_, inserted] = formats.insert(format); + if (inserted) { + tranche.indicies.push_back(i++); + formatsVec.push_back(SDMABUFFormatTableEntry{ + .fmt = fmt.drmFormat, + .modifier = mod, + }); + } else { + auto it = std::find_if(formatsVec.begin(), formatsVec.end(), + [fmt, mod](const SDMABUFFormatTableEntry& oth) { return oth.fmt == fmt.drmFormat && oth.modifier == mod; }); + tranche.indicies.push_back(it - formatsVec.begin()); + } + } } } - tableLen = formats.size() * sizeof(SDMABUFFeedbackTableEntry); + tableSize = formatsVec.size() * sizeof(SDMABUFFormatTableEntry); + int fds[2] = {0}; - allocateSHMFilePair(tableLen, &fds[0], &fds[1]); + allocateSHMFilePair(tableSize, &fds[0], &fds[1]); - auto arr = (SDMABUFFeedbackTableEntry*)mmap(nullptr, tableLen, PROT_READ | PROT_WRITE, MAP_SHARED, fds[0], 0); + auto arr = (SDMABUFFormatTableEntry*)mmap(nullptr, tableSize, PROT_READ | PROT_WRITE, MAP_SHARED, fds[0], 0); if (arr == MAP_FAILED) { LOGM(ERR, "mmap failed"); @@ -46,28 +93,14 @@ CCompiledDMABUFFeedback::CCompiledDMABUFFeedback(dev_t device, std::vector> formatsVec; - for (auto& f : formats) { - formatsVec.emplace_back(f); - } + std::copy(formatsVec.begin(), formatsVec.end(), arr); - size_t i = 0; - for (auto& [fmt, mod] : formatsVec) { - LOGM(TRACE, "Feedback: format table index {}: fmt {} mod {}", i, FormatUtils::drmFormatName(fmt), mod); - arr[i++] = SDMABUFFeedbackTableEntry{ - .fmt = fmt, - .modifier = mod, - }; - } + munmap(arr, tableSize); - munmap(arr, tableLen); - - mainDevice = device; - tableFD = fds[1]; - this->formats = formatsVec; + tableFD = fds[1]; } -CCompiledDMABUFFeedback::~CCompiledDMABUFFeedback() { +CDMABUFFormatTable::~CDMABUFFormatTable() { close(tableFD); } @@ -275,12 +308,9 @@ CLinuxDMABUFFeedbackResource::CLinuxDMABUFFeedbackResource(SPsetOnDestroy([this](CZwpLinuxDmabufFeedbackV1* r) { PROTO::linuxDma->destroyResource(this); }); resource->setDestroy([this](CZwpLinuxDmabufFeedbackV1* r) { PROTO::linuxDma->destroyResource(this); }); - auto* feedback = PROTO::linuxDma->defaultFeedback.get(); - - resource->sendFormatTable(feedback->tableFD, feedback->tableLen); - - // send default feedback - sendDefault(); + auto& formatTable = PROTO::linuxDma->formatTable; + resource->sendFormatTable(formatTable->tableFD, formatTable->tableSize); + sendDefaultFeedback(); } CLinuxDMABUFFeedbackResource::~CLinuxDMABUFFeedbackResource() { @@ -291,31 +321,39 @@ bool CLinuxDMABUFFeedbackResource::good() { return resource->resource(); } -void CLinuxDMABUFFeedbackResource::sendDefault() { - auto* feedback = PROTO::linuxDma->defaultFeedback.get(); - +void CLinuxDMABUFFeedbackResource::sendTranche(SDMABUFTranche& tranche) { struct wl_array deviceArr = { - .size = sizeof(feedback->mainDevice), - .data = (void*)&feedback->mainDevice, + .size = sizeof(tranche.device), + .data = (void*)&tranche.device, }; - resource->sendMainDevice(&deviceArr); - - // Main tranche resource->sendTrancheTargetDevice(&deviceArr); - // Technically, on a single-gpu system, this is correct I believe. - resource->sendTrancheFlags(ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT); + resource->sendTrancheFlags((zwpLinuxDmabufFeedbackV1TrancheFlags)tranche.flags); - wl_array indices; - wl_array_init(&indices); - for (size_t i = 0; i < feedback->formats.size(); ++i) { - *((uint16_t*)wl_array_add(&indices, sizeof(uint16_t))) = i; - } + wl_array indices = { + .size = tranche.indicies.size() * sizeof(tranche.indicies.at(0)), + .data = tranche.indicies.data(), + }; resource->sendTrancheFormats(&indices); - wl_array_release(&indices); resource->sendTrancheDone(); +} + +// default tranche is based on renderer (egl) +void CLinuxDMABUFFeedbackResource::sendDefaultFeedback() { + auto mainDevice = PROTO::linuxDma->mainDevice; + auto& formatTable = PROTO::linuxDma->formatTable; + + struct wl_array deviceArr = { + .size = sizeof(mainDevice), + .data = (void*)&mainDevice, + }; + resource->sendMainDevice(&deviceArr); + + sendTranche(formatTable->rendererTranche); resource->sendDone(); + + lastFeedbackWasScanout = false; } CLinuxDMABUFResource::CLinuxDMABUFResource(SP resource_) : resource(resource_) { @@ -366,16 +404,18 @@ bool CLinuxDMABUFResource::good() { } void CLinuxDMABUFResource::sendMods() { - for (auto& [fmt, mod] : PROTO::linuxDma->defaultFeedback->formats) { - if (resource->version() < 3) { - if (mod == DRM_FORMAT_MOD_INVALID || mod == DRM_FORMAT_MOD_LINEAR) - resource->sendFormat(fmt); - continue; - } + for (auto& fmt : PROTO::linuxDma->formatTable->rendererTranche.formats) { + for (auto& mod : fmt.modifiers) { + if (resource->version() < 3) { + if (mod == DRM_FORMAT_MOD_INVALID || mod == DRM_FORMAT_MOD_LINEAR) + resource->sendFormat(fmt.drmFormat); + continue; + } - // TODO: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1166 + // TODO: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1166 - resource->sendModifier(fmt, mod >> 32, mod & 0xFFFFFFFF); + resource->sendModifier(fmt.drmFormat, mod >> 32, mod & 0xFFFFFFFF); + } } } @@ -392,19 +432,48 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const mainDevice = *dev; - // FIXME: this will break on multi-gpu - std::vector aqFormats = g_pHyprOpenGL->getDRMFormats(); - - // - SDMABufTranche tranche = { - .device = *dev, - .formats = aqFormats, + SDMABUFTranche eglTranche = { + .device = mainDevice, + .flags = 0, // renderer isnt for ds so dont set flag + .formats = g_pHyprOpenGL->getDRMFormats(), }; - std::vector tches; - tches.push_back(tranche); + std::vector, SDMABUFTranche>> tches; - defaultFeedback = std::make_unique(*dev, tches); + if (g_pCompositor->m_pAqBackend->hasSession()) { + // this assumes there's only 1 device used for both scanout and rendering + // also that each monitor never changes its primary plane + + for (auto& mon : g_pCompositor->m_vMonitors) { + auto tranche = SDMABUFTranche{ + .device = mainDevice, + .flags = ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT, + .formats = mon->output->getRenderFormats(), + }; + tches.push_back(std::make_pair<>(mon, tranche)); + } + + static auto monitorAdded = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) { + auto pMonitor = std::any_cast(param); + auto mon = pMonitor->self.lock(); + auto tranche = SDMABUFTranche{ + .device = mainDevice, + .flags = ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT, + .formats = mon->output->getRenderFormats(), + }; + formatTable->monitorTranches.push_back(std::make_pair<>(mon, tranche)); + resetFormatTable(); + }); + + static auto monitorRemoved = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { + auto pMonitor = std::any_cast(param); + auto mon = pMonitor->self.lock(); + std::erase_if(formatTable->monitorTranches, [mon](std::pair, SDMABUFTranche> pair) { return pair.first == mon; }); + resetFormatTable(); + }); + } + + formatTable = std::make_unique(eglTranche, tches); drmDevice* device = nullptr; if (drmGetDeviceFromDevId(mainDevice, 0, &device) != 0) { @@ -429,6 +498,39 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const }); } +void CLinuxDMABufV1Protocol::resetFormatTable() { + if (!formatTable) + return; + + LOGM(LOG, "Resetting format table"); + + // this might be a big copy + auto newFormatTable = std::make_unique(formatTable->rendererTranche, formatTable->monitorTranches); + + for (auto& feedback : m_vFeedbacks) { + feedback->resource->sendFormatTable(newFormatTable->tableFD, newFormatTable->tableSize); + if (feedback->lastFeedbackWasScanout) { + SP mon; + auto HLSurface = CWLSurface::fromResource(feedback->surface); + if (auto w = HLSurface->getWindow(); w) + if (auto m = g_pCompositor->getMonitorFromID(w->m_iMonitorID); m) + mon = m->self.lock(); + + if (!mon) { + feedback->sendDefaultFeedback(); + return; + } + + updateScanoutTranche(feedback->surface, mon); + } else { + feedback->sendDefaultFeedback(); + } + } + + // delete old table after we sent new one + formatTable = std::move(newFormatTable); +} + CLinuxDMABufV1Protocol::~CLinuxDMABufV1Protocol() { if (mainDeviceFD >= 0) close(mainDeviceFD); @@ -461,8 +563,6 @@ void CLinuxDMABufV1Protocol::destroyResource(CLinuxDMABuffer* resource) { } void CLinuxDMABufV1Protocol::updateScanoutTranche(SP surface, SP pMonitor) { - // TODO: iterating isn't particularly efficient, maybe add a system for addons for surfaces - SP feedbackResource; for (auto& f : m_vFeedbacks) { if (f->surface != surface) @@ -479,49 +579,34 @@ void CLinuxDMABufV1Protocol::updateScanoutTranche(SP surface if (!pMonitor) { LOGM(LOG, "updateScanoutTranche: resetting feedback"); - feedbackResource->sendDefault(); + feedbackResource->sendDefaultFeedback(); return; } - auto* feedback = PROTO::linuxDma->defaultFeedback.get(); + const auto& monitorTranchePair = std::find_if(formatTable->monitorTranches.begin(), formatTable->monitorTranches.end(), + [pMonitor](std::pair, SDMABUFTranche> pair) { return pair.first == pMonitor; }); - LOGM(LOG, "updateScanoutTranche: sending a scanout tranche"); + if (monitorTranchePair == formatTable->monitorTranches.end()) { + LOGM(LOG, "updateScanoutTranche: monitor has no tranche"); + return; + } - // send a dedicated scanout tranche that contains formats that: - // - match the format of the output - // - are not linear or implicit + auto& monitorTranche = (*monitorTranchePair).second; + + LOGM(LOG, "updateScanoutTranche: sending a scanout tranche"); struct wl_array deviceArr = { - .size = sizeof(feedback->mainDevice), - .data = (void*)&feedback->mainDevice, + .size = sizeof(mainDevice), + .data = (void*)&mainDevice, }; - feedbackResource->resource->sendTrancheTargetDevice(&deviceArr); - feedbackResource->resource->sendTrancheFlags(ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT); - - wl_array indices2; - wl_array_init(&indices2); - const auto PRIMARYFORMATS = pMonitor->output->getBackend()->getRenderFormats(); - - for (size_t i = 0; i < feedback->formats.size(); ++i) { - if (feedback->formats.at(i).second == DRM_FORMAT_MOD_LINEAR || feedback->formats.at(i).second == DRM_FORMAT_MOD_INVALID) - continue; - - const auto PRIM_FORMAT = std::find_if(PRIMARYFORMATS.begin(), PRIMARYFORMATS.end(), [&](const auto& e) { return e.drmFormat == feedback->formats.at(i).first; }); + feedbackResource->resource->sendMainDevice(&deviceArr); - if (PRIM_FORMAT == PRIMARYFORMATS.end()) - continue; - - if (std::find(PRIM_FORMAT->modifiers.begin(), PRIM_FORMAT->modifiers.end(), feedback->formats.at(i).second) == PRIM_FORMAT->modifiers.end()) - continue; - - LOGM(TRACE, "updateScanoutTranche: index {}: Format {} with modifier {} aka {} passed", i, FormatUtils::drmFormatName(feedback->formats.at(i).first), - feedback->formats.at(i).second, FormatUtils::drmModifierName(feedback->formats.at(i).second)); - *((uint16_t*)wl_array_add(&indices2, sizeof(uint16_t))) = i; - } - - feedbackResource->resource->sendTrancheFormats(&indices2); - wl_array_release(&indices2); - feedbackResource->resource->sendTrancheDone(); + // prioritize scnaout tranche but have renderer fallback tranche + // also yes formats can be duped here because different tranche flags (ds and no ds) + feedbackResource->sendTranche(monitorTranche); + feedbackResource->sendTranche(formatTable->rendererTranche); feedbackResource->resource->sendDone(); + + feedbackResource->lastFeedbackWasScanout = true; } diff --git a/src/protocols/LinuxDMABUF.hpp b/src/protocols/LinuxDMABUF.hpp index 449b4ac9ce5..0e25cdc6091 100644 --- a/src/protocols/LinuxDMABUF.hpp +++ b/src/protocols/LinuxDMABUF.hpp @@ -32,34 +32,29 @@ class CLinuxDMABuffer { }; #pragma pack(push, 1) -struct SDMABUFFeedbackTableEntry { +struct SDMABUFFormatTableEntry { uint32_t fmt = 0; char pad[4]; uint64_t modifier = 0; }; #pragma pack(pop) -class SCompiledDMABUFTranche { - dev_t device = 0; - uint32_t flags = 0; - std::vector indices; -}; - -struct SDMABufTranche { +struct SDMABUFTranche { dev_t device = 0; uint32_t flags = 0; std::vector formats; + std::vector indicies; }; -class CCompiledDMABUFFeedback { +class CDMABUFFormatTable { public: - CCompiledDMABUFFeedback(dev_t device, std::vector tranches); - ~CCompiledDMABUFFeedback(); + CDMABUFFormatTable(SDMABUFTranche rendererTranche, std::vector, SDMABUFTranche>> tranches); + ~CDMABUFFormatTable(); - dev_t mainDevice = 0; - int tableFD = -1; - size_t tableLen = 0; - std::vector> formats; + int tableFD = -1; + size_t tableSize = 0; + SDMABUFTranche rendererTranche; + std::vector, SDMABUFTranche>> monitorTranches; }; class CLinuxDMABBUFParamsResource { @@ -87,12 +82,14 @@ class CLinuxDMABUFFeedbackResource { ~CLinuxDMABUFFeedbackResource(); bool good(); - void sendDefault(); + void sendDefaultFeedback(); + void sendTranche(SDMABUFTranche& tranche); SP surface; // optional, for surface feedbacks private: SP resource; + bool lastFeedbackWasScanout = false; friend class CLinuxDMABufV1Protocol; }; @@ -122,13 +119,15 @@ class CLinuxDMABufV1Protocol : public IWaylandProtocol { void destroyResource(CLinuxDMABBUFParamsResource* resource); void destroyResource(CLinuxDMABuffer* resource); + void resetFormatTable(); + // std::vector> m_vManagers; std::vector> m_vFeedbacks; std::vector> m_vParams; std::vector> m_vBuffers; - UP defaultFeedback; + UP formatTable; dev_t mainDevice; int mainDeviceFD = -1; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index a038bf088c8..4a5592aee6f 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -443,7 +443,15 @@ void CWLSurfaceResource::commitPendingState() { // for async buffers, we can only release the buffer once we are unrefing it from current. if (previousBuffer && !previousBuffer->isSynchronous() && !bufferReleased) { - previousBuffer->sendReleaseWithSurface(self.lock()); + if (previousBuffer->lockedByBackend) { + previousBuffer->hlEvents.backendRelease = previousBuffer->events.backendRelease.registerListener([this, previousBuffer](std::any data) { + previousBuffer->sendReleaseWithSurface(self.lock()); + previousBuffer->hlEvents.backendRelease.reset(); + bufferReleased = true; + }); + } else + previousBuffer->sendReleaseWithSurface(self.lock()); + bufferReleased = true; } } diff --git a/src/protocols/types/Buffer.cpp b/src/protocols/types/Buffer.cpp index a347a0fc9bd..0217f7e2fa3 100644 --- a/src/protocols/types/Buffer.cpp +++ b/src/protocols/types/Buffer.cpp @@ -5,5 +5,6 @@ void IHLBuffer::sendRelease() { } void IHLBuffer::sendReleaseWithSurface(SP surf) { - resource->sendReleaseWithSurface(surf); + if (resource && resource->good()) + resource->sendReleaseWithSurface(surf); } diff --git a/src/protocols/types/Buffer.hpp b/src/protocols/types/Buffer.hpp index 2ae542d1bf3..ba8278f3a6d 100644 --- a/src/protocols/types/Buffer.hpp +++ b/src/protocols/types/Buffer.hpp @@ -22,4 +22,8 @@ class IHLBuffer : public Aquamarine::IBuffer { SP texture; bool opaque = false; SP resource; + + struct { + CHyprSignalListener backendRelease; + } hlEvents; }; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 2a2a3da162f..2d4612273d4 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1088,53 +1088,6 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPmirrors.empty() || pMonitor->isMirror() || m_bDirectScanoutBlocked) - return false; // do not DS if this monitor is being mirrored. Will break the functionality. - - if (g_pPointerManager->softwareLockedFor(pMonitor->self.lock())) - return false; - - const auto PCANDIDATE = pMonitor->solitaryClient.lock(); - - if (!PCANDIDATE) - return false; - - const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE); - - if (!PSURFACE || !PSURFACE->current.buffer || PSURFACE->current.buffer->size != pMonitor->vecPixelSize || PSURFACE->current.transform != pMonitor->transform) - return false; - - // we can't scanout shm buffers. - if (!PSURFACE->current.buffer->dmabuf().success) - return false; - - // FIXME: make sure the buffer actually follows the available scanout dmabuf formats - // and comes from the appropriate device. This may implode on multi-gpu!! - - pMonitor->output->state->setBuffer(PSURFACE->current.buffer); - - if (!pMonitor->state.test()) - return false; - - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - Debug::log(TRACE, "presentFeedback for DS"); - PSURFACE->presentFeedback(&now, pMonitor, true); - - if (pMonitor->state.commit()) { - if (m_pLastScanout.expired()) { - m_pLastScanout = PCANDIDATE; - Debug::log(LOG, "Entered a direct scanout to {:x}: \"{}\"", (uintptr_t)PCANDIDATE.get(), PCANDIDATE->m_szTitle); - } - } else { - m_pLastScanout.reset(); - return false; - } - - return true; -} - void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { static std::chrono::high_resolution_clock::time_point renderStart = std::chrono::high_resolution_clock::now(); static std::chrono::high_resolution_clock::time_point renderStartOverlay = std::chrono::high_resolution_clock::now(); @@ -1214,6 +1167,9 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitor->ID); } + if (!pMonitor->output->needsFrame && pMonitor->forceFullFrames == 0) + return; + // tearing and DS first bool shouldTear = false; if (pMonitor->tearingState.nextRenderTorn) { @@ -1239,11 +1195,11 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } if (!*PNODIRECTSCANOUT && !shouldTear) { - if (attemptDirectScanout(pMonitor)) { + if (pMonitor->attemptDirectScanout()) { return; - } else if (!m_pLastScanout.expired()) { + } else if (!pMonitor->lastScanout.expired()) { Debug::log(LOG, "Left a direct scanout."); - m_pLastScanout.reset(); + pMonitor->lastScanout.reset(); } } diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 6cabf2d075b..72efe8c40c7 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -76,19 +76,17 @@ class CHyprRenderer { // if RENDER_MODE_NORMAL, provided damage will be written to. // otherwise, it will be the one used. - bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP buffer = {}, CFramebuffer* fb = nullptr, bool simple = false); - void endRender(); + bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP buffer = {}, CFramebuffer* fb = nullptr, bool simple = false); + void endRender(); - bool m_bBlockSurfaceFeedback = false; - bool m_bRenderingSnapshot = false; - PHLWINDOWREF m_pLastScanout; - CMonitor* m_pMostHzMonitor = nullptr; - bool m_bDirectScanoutBlocked = false; + bool m_bBlockSurfaceFeedback = false; + bool m_bRenderingSnapshot = false; + CMonitor* m_pMostHzMonitor = nullptr; + bool m_bDirectScanoutBlocked = false; DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&); - bool attemptDirectScanout(CMonitor*); void setSurfaceScanoutMode(SP surface, SP monitor); // nullptr monitor resets void initiateManualCrash(); From 85cf0972bf08fc6f7c97643f8c0594751a1a18eb Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Fri, 19 Jul 2024 23:35:25 +0300 Subject: [PATCH 104/113] flake.lock: update aq --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 33112a827ba..ab12dc5d5de 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1721209245, - "narHash": "sha256-DPmXHln87FjuBO7ElzrmV6mChJCz0ZA7IxHfM4gi/tg=", + "lastModified": 1721381390, + "narHash": "sha256-99hmBZkb2PaIhlt9oSpydTX/J5JwtT/Xv64ikhCa/n0=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "cebcba4e107fde332ff023119f9a8758aa6fd120", + "rev": "35e00a4a9dc35a44a3031b6f8f219a96f46e6451", "type": "github" }, "original": { From 70e4670185a5a50c0f91e22d7dba8e6ce11c0c99 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 20 Jul 2024 00:36:45 +0200 Subject: [PATCH 105/113] oopsie daisy --- src/desktop/Popup.cpp | 5 +++-- src/desktop/Popup.hpp | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index f0fd556c543..131a26b5ac9 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -55,7 +55,7 @@ void CPopup::initAllSignals() { } void CPopup::onNewPopup(SP popup) { - const auto POPUP = m_vChildren.emplace_back(std::make_unique(popup, this)).get(); + const auto POPUP = m_vChildren.emplace_back(makeShared(popup, this)).get(); Debug::log(LOG, "New popup at {:x}", (uintptr_t)POPUP); } @@ -250,7 +250,8 @@ void CPopup::recheckTree() { } void CPopup::recheckChildrenRecursive() { - for (auto& c : m_vChildren) { + auto cpy = m_vChildren; + for (auto& c : cpy) { c->onCommit(true); c->recheckChildrenRecursive(); } diff --git a/src/desktop/Popup.hpp b/src/desktop/Popup.hpp index 47e180a8c24..d045cd41578 100644 --- a/src/desktop/Popup.hpp +++ b/src/desktop/Popup.hpp @@ -60,8 +60,8 @@ class CPopup { bool m_bMapped = false; // - std::vector> m_vChildren; - std::unique_ptr m_pSubsurfaceHead; + std::vector> m_vChildren; + std::unique_ptr m_pSubsurfaceHead; struct { CHyprSignalListener newPopup; From 8aff97135bb90d6944f388860647ba7676b98dfc Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 20 Jul 2024 12:39:18 +0200 Subject: [PATCH 106/113] fix crashas --- src/protocols/core/Compositor.cpp | 5 ++++- src/protocols/types/WLBuffer.cpp | 2 +- src/render/Renderer.cpp | 5 +++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 4a5592aee6f..5cd6005a762 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -445,7 +445,10 @@ void CWLSurfaceResource::commitPendingState() { if (previousBuffer && !previousBuffer->isSynchronous() && !bufferReleased) { if (previousBuffer->lockedByBackend) { previousBuffer->hlEvents.backendRelease = previousBuffer->events.backendRelease.registerListener([this, previousBuffer](std::any data) { - previousBuffer->sendReleaseWithSurface(self.lock()); + if (!self.expired()) // could be dead in the dtor + previousBuffer->sendReleaseWithSurface(self.lock()); + else + previousBuffer->sendRelease(); previousBuffer->hlEvents.backendRelease.reset(); bufferReleased = true; }); diff --git a/src/protocols/types/WLBuffer.cpp b/src/protocols/types/WLBuffer.cpp index cc24546daf2..d34a867d958 100644 --- a/src/protocols/types/WLBuffer.cpp +++ b/src/protocols/types/WLBuffer.cpp @@ -35,7 +35,7 @@ void CWLBufferResource::sendRelease() { void CWLBufferResource::sendReleaseWithSurface(SP surf) { sendRelease(); - if (!surf->syncobj) + if (!surf || !surf->syncobj) return; if (drmSyncobjTimelineSignal(g_pCompositor->m_iDRMFD, &surf->syncobj->releaseTimeline->timeline->handle, &surf->syncobj->releasePoint, 1)) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 2d4612273d4..82dfc8879ec 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2622,6 +2622,11 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode return false; } + if (!m_pCurrentRenderbuffer) { + Debug::log(ERR, "failed to start a render pass for output {}, no RBO could be obtained", pMonitor->szName); + return false; + } + if (mode == RENDER_MODE_NORMAL) { damage = pMonitor->damage.getBufferDamage(HL_BUFFER_AGE); pMonitor->damage.rotate(); From 1d933293b0d8ced9a2cbf33b167c4e5b8d3fb380 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 20 Jul 2024 14:45:14 +0200 Subject: [PATCH 107/113] fix --- src/Compositor.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 7fdb906c0af..c7a0cfb1270 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -632,8 +632,6 @@ void CCompositor::prepareFallbackOutput() { } void CCompositor::startCompositor(std::string socketName, int socketFd) { - initAllSignals(); - if (!socketName.empty() && socketFd != -1) { fcntl(socketFd, F_SETFD, FD_CLOEXEC); const auto RETVAL = wl_display_add_socket_fd(m_sWLDisplay, socketFd); From 8dbaef2982d0b9fc695fc055b7b1027f4404bd66 Mon Sep 17 00:00:00 2001 From: diniamo Date: Sat, 20 Jul 2024 16:01:33 +0200 Subject: [PATCH 108/113] flake: update aquamarine --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index ab12dc5d5de..1f3fcbf1c40 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1721381390, - "narHash": "sha256-99hmBZkb2PaIhlt9oSpydTX/J5JwtT/Xv64ikhCa/n0=", + "lastModified": 1721483718, + "narHash": "sha256-AoKIFlsYd/rjkJr+QfQvmd2R/YLGxkiilxYT0FAcezg=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "35e00a4a9dc35a44a3031b6f8f219a96f46e6451", + "rev": "af219a0a2c575adf576fa4d39f88df992180fe21", "type": "github" }, "original": { From 1c5c905c25267b6281517bb985a06e77240adf0b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 20 Jul 2024 17:58:49 +0200 Subject: [PATCH 109/113] fix crash --- src/protocols/MesaDRM.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/protocols/MesaDRM.cpp b/src/protocols/MesaDRM.cpp index 8ceb24a604b..b4df1e291d8 100644 --- a/src/protocols/MesaDRM.cpp +++ b/src/protocols/MesaDRM.cpp @@ -124,6 +124,14 @@ CMesaDRMProtocol::CMesaDRMProtocol(const wl_interface* iface, const int& ver, co nodeName = dev->nodes[DRM_NODE_RENDER]; } else { ASSERT(dev->available_nodes & (1 << DRM_NODE_PRIMARY)); + + if (!dev->nodes[DRM_NODE_PRIMARY]) { + LOGM(ERR, "No DRM render node available, both render and primary are null, disabling MesaDRM"); + drmFreeDevice(&dev); + removeGlobal(); + return; + } + LOGM(WARN, "No DRM render node, falling back to primary {}", dev->nodes[DRM_NODE_PRIMARY]); nodeName = dev->nodes[DRM_NODE_PRIMARY]; } From 78d11c456a7fda3a6178f3c73a9d3ab65ffb9143 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 20 Jul 2024 17:59:27 +0200 Subject: [PATCH 110/113] fix possible crash 2 --- src/protocols/LinuxDMABUF.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 0f9b67a3b62..ef533551409 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -492,7 +492,7 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const return; } } else { - LOGM(ERR, "DRM device {} has no render node!!", device->nodes[DRM_NODE_PRIMARY]); + LOGM(ERR, "DRM device {} has no render node!!", device->nodes[DRM_NODE_PRIMARY] ? device->nodes[DRM_NODE_PRIMARY] : "null"); drmFreeDevice(&device); } }); From aa1ebc51fcca1f6ad3303b18a059277247924cd8 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 20 Jul 2024 18:14:17 +0200 Subject: [PATCH 111/113] fix possible crash 3 --- src/protocols/LinuxDMABUF.cpp | 15 ++++++++------- src/protocols/MesaDRM.cpp | 8 ++++---- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index ef533551409..3fbd4204f1f 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -425,8 +425,8 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const auto dev = devIDFromFD(rendererFD); if (!dev.has_value()) { - LOGM(ERR, "failed to get drm dev"); - PROTO::linuxDma.reset(); + protoLog(ERR, "failed to get drm dev, disabling linux dmabuf"); + removeGlobal(); return; } @@ -477,8 +477,8 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const drmDevice* device = nullptr; if (drmGetDeviceFromDevId(mainDevice, 0, &device) != 0) { - LOGM(ERR, "failed to get drm dev"); - PROTO::linuxDma.reset(); + protoLog(ERR, "failed to get drm dev, disabling linux dmabuf"); + removeGlobal(); return; } @@ -487,13 +487,14 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const mainDeviceFD = open(name, O_RDWR | O_CLOEXEC); drmFreeDevice(&device); if (mainDeviceFD < 0) { - LOGM(ERR, "failed to open drm dev"); - PROTO::linuxDma.reset(); + protoLog(ERR, "failed to open drm dev, disabling linux dmabuf"); + removeGlobal(); return; } } else { - LOGM(ERR, "DRM device {} has no render node!!", device->nodes[DRM_NODE_PRIMARY] ? device->nodes[DRM_NODE_PRIMARY] : "null"); + protoLog(ERR, "DRM device {} has no render node, disabling linux dmabuf", device->nodes[DRM_NODE_PRIMARY] ? device->nodes[DRM_NODE_PRIMARY] : "null"); drmFreeDevice(&device); + removeGlobal(); } }); } diff --git a/src/protocols/MesaDRM.cpp b/src/protocols/MesaDRM.cpp index b4df1e291d8..ed4125552a2 100644 --- a/src/protocols/MesaDRM.cpp +++ b/src/protocols/MesaDRM.cpp @@ -115,8 +115,8 @@ CMesaDRMProtocol::CMesaDRMProtocol(const wl_interface* iface, const int& ver, co drmDevice* dev = nullptr; int drmFD = g_pCompositor->m_iDRMFD; if (drmGetDevice2(drmFD, 0, &dev) != 0) { - LOGM(ERR, "Failed to get device"); - PROTO::mesaDRM.reset(); + protoLog(ERR, "Failed to get device, disabling MesaDRM"); + removeGlobal(); return; } @@ -126,13 +126,13 @@ CMesaDRMProtocol::CMesaDRMProtocol(const wl_interface* iface, const int& ver, co ASSERT(dev->available_nodes & (1 << DRM_NODE_PRIMARY)); if (!dev->nodes[DRM_NODE_PRIMARY]) { - LOGM(ERR, "No DRM render node available, both render and primary are null, disabling MesaDRM"); + protoLog(ERR, "No DRM render node available, both render and primary are null, disabling MesaDRM"); drmFreeDevice(&dev); removeGlobal(); return; } - LOGM(WARN, "No DRM render node, falling back to primary {}", dev->nodes[DRM_NODE_PRIMARY]); + protoLog(WARN, "No DRM render node, falling back to primary {}", dev->nodes[DRM_NODE_PRIMARY]); nodeName = dev->nodes[DRM_NODE_PRIMARY]; } drmFreeDevice(&dev); From cedac20c1ee33056701651a455ba4764b54c2817 Mon Sep 17 00:00:00 2001 From: diniamo Date: Sat, 20 Jul 2024 17:47:04 +0200 Subject: [PATCH 112/113] flake: update aquamarine --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 1f3fcbf1c40..b2cc9703086 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1721483718, - "narHash": "sha256-AoKIFlsYd/rjkJr+QfQvmd2R/YLGxkiilxYT0FAcezg=", + "lastModified": 1721487522, + "narHash": "sha256-aF3uwUwUK2CgbItoMe3IJF0yidIEWcDx47AiH5y8VKk=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "af219a0a2c575adf576fa4d39f88df992180fe21", + "rev": "acfea3bd1d9e756c7152e639240d52c6628844b0", "type": "github" }, "original": { From 4b84029655b788f0f805c03feedfa849f290ffbd Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 21 Jul 2024 12:53:58 +0200 Subject: [PATCH 113/113] rerun pipeline --- src/protocols/LinuxDMABUF.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 3fbd4204f1f..0fbf832e5e9 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -434,7 +434,7 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const SDMABUFTranche eglTranche = { .device = mainDevice, - .flags = 0, // renderer isnt for ds so dont set flag + .flags = 0, // renderer isnt for ds so dont set flag. .formats = g_pHyprOpenGL->getDRMFormats(), };