From 2b99f9cae7f7722fb01e1df071438e0215390d53 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Tue, 22 Nov 2022 21:50:20 +0000 Subject: initial tearing stuff, disabled cuz broken for now --- Makefile | 22 +++++++++++++++++++++- src/Compositor.cpp | 5 +++++ src/Compositor.hpp | 1 + src/Window.cpp | 5 +++++ src/Window.hpp | 5 +++++ src/config/ConfigManager.cpp | 1 + src/debug/Log.cpp | 2 ++ src/events/Events.hpp | 5 +++++ src/events/Misc.cpp | 29 +++++++++++++++++++++++++++++ src/events/Monitors.cpp | 10 ++++++++++ src/events/Windows.cpp | 6 +++--- src/helpers/Monitor.cpp | 6 ++++++ src/helpers/Monitor.hpp | 4 ++++ src/helpers/SubsurfaceTree.cpp | 12 ++++++++++++ src/helpers/WLClasses.hpp | 11 +++++++++++ src/includes.hpp | 1 + src/main.cpp | 5 ++++- src/render/Renderer.cpp | 7 ++++--- src/render/Renderer.hpp | 2 ++ 19 files changed, 131 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 1a193086..b8f27fcc 100644 --- a/Makefile +++ b/Makefile @@ -81,6 +81,16 @@ idle-protocol.c: idle-protocol.o: idle-protocol.h +tearing-control-v1-protocol.h: + $(WAYLAND_SCANNER) server-header \ + $(WAYLAND_PROTOCOLS)/staging/tearing-control/tearing-control-v1.xml $@ + +tearing-control-v1-protocol.c: + $(WAYLAND_SCANNER) private-code \ + $(WAYLAND_PROTOCOLS)/staging/tearing-control/tearing-control-v1.xml $@ + +tearing-control-v1-protocol.o: tearing-control-v1-protocol.h + wlr-output-power-management-unstable-v1-protocol.h: $(WAYLAND_SCANNER) server-header \ protocols/wlr-output-power-management-unstable-v1.xml $@ @@ -179,7 +189,7 @@ uninstall: rm -f ${PREFIX}/share/man/man1/Hyprland.1 rm -f ${PREFIX}/share/man/man1/hyprctl.1 -protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o linux-dmabuf-unstable-v1-protocol.o +protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o linux-dmabuf-unstable-v1-protocol.o tearing-control-v1-protocol.o fixwlr: sed -i -E 's/(soversion = 12)([^032]|$$)/soversion = 12032/g' subprojects/wlroots/meson.build @@ -196,6 +206,16 @@ config: cd subprojects/wlroots && ninja -C build/ install +configdebug: + make protocols + + make fixwlr + + cd subprojects/wlroots && meson ./build --prefix=/usr --buildtype=debug -Dwerror=false -Dexamples=false + cd subprojects/wlroots && ninja -C build/ + + cd subprojects/wlroots && ninja -C build/ install + man: pandoc ./docs/Hyprland.1.rst \ --standalone \ diff --git a/src/Compositor.cpp b/src/Compositor.cpp index f698f05a..baa97bd3 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -179,6 +179,8 @@ CCompositor::CCompositor() { m_sWLRActivation = wlr_xdg_activation_v1_create(m_sWLDisplay); + m_sWLRTearingMgr = wlr_tearing_control_manager_v1_create(m_sWLDisplay, 1); + m_sWLRHeadlessBackend = wlr_headless_backend_create(m_sWLDisplay); if (!m_sWLRHeadlessBackend) { @@ -244,6 +246,7 @@ void CCompositor::initAllSignals() { addWLSignal(&m_sWLRIMEMgr->events.input_method, &Events::listen_newIME, m_sWLRIMEMgr, "IMEMgr"); addWLSignal(&m_sWLRTextInputMgr->events.text_input, &Events::listen_newTextInput, m_sWLRTextInputMgr, "TextInputMgr"); addWLSignal(&m_sWLRActivation->events.request_activate, &Events::listen_activateXDG, m_sWLRActivation, "ActivationV1"); + addWLSignal(&m_sWLRTearingMgr->events.new_object, &Events::listen_tearingNew, m_sWLRTearingMgr, "TearingMgr"); if(m_sWRLDRMLeaseMgr) addWLSignal(&m_sWRLDRMLeaseMgr->events.request, &Events::listen_leaseRequest, &m_sWRLDRMLeaseMgr, "DRM"); @@ -1759,6 +1762,8 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode // DMAbuf stuff for direct scanout g_pHyprRenderer->setWindowScanoutMode(pWindow); + + g_pHyprRenderer->damageMonitor(PMONITOR); } void CCompositor::moveUnmanagedX11ToWindows(CWindow* pWindow) { diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 9cf73acc..87f648ef 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -72,6 +72,7 @@ public: wlr_xdg_activation_v1* m_sWLRActivation; wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf; wlr_backend* m_sWLRHeadlessBackend; + wlr_tearing_control_manager_v1* m_sWLRTearingMgr; // ------------------------------------------------- // diff --git a/src/Window.cpp b/src/Window.cpp index e98193e1..083c676b 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -379,3 +379,8 @@ void CWindow::updateDynamicRules() { applyDynamicRule(r); } } + +bool CWindow::shouldImmediate() { + return false; // safeguard. Disabled for now. + return m_bTearingHint == 1 || m_sAdditionalConfigData.forceTearing; +} diff --git a/src/Window.hpp b/src/Window.hpp index b0014af9..01483d62 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -37,6 +37,7 @@ struct SWindowAdditionalConfigData { bool forceNoBorder = false; bool forceNoShadow = false; bool windowDanceCompat = false; + bool forceTearing = false; }; struct SWindowRule { @@ -180,6 +181,9 @@ public: // for idle inhibiting windows eIdleInhibitMode m_eIdleInhibitMode = IDLEINHIBIT_NONE; + // tearing hints + bool m_bTearingHint = false; + // For the list lookup bool operator==(const CWindow& rhs) { return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize && m_bFadingOut == rhs.m_bFadingOut; @@ -204,6 +208,7 @@ public: bool isHidden(); void applyDynamicRule(const SWindowRule& r); void updateDynamicRules(); + bool shouldImmediate(); private: // For hidden windows and stuff diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 1b5ee4ae..d1f8cd19 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -681,6 +681,7 @@ bool windowRuleValid(const std::string& RULE) { && RULE != "pin" && RULE != "noanim" && RULE != "windowdance" + && RULE != "immediate" && RULE.find("animation") != 0 && RULE.find("rounding") != 0 && RULE.find("workspace") != 0 diff --git a/src/debug/Log.cpp b/src/debug/Log.cpp index dab8f0a7..2f1bc0b3 100644 --- a/src/debug/Log.cpp +++ b/src/debug/Log.cpp @@ -23,6 +23,8 @@ void Debug::wlrLog(wlr_log_importance level, const char* fmt, va_list args) { ofs << "[wlr] " << output << "\n"; ofs.close(); + + std::cout << "[wlr] " << output << "\n"; } void Debug::log(LogLevel level, const char* fmt, ...) { diff --git a/src/events/Events.hpp b/src/events/Events.hpp index e3088110..e8b862fe 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -157,4 +157,9 @@ namespace Events { LISTENER(holdBegin); LISTENER(holdEnd); + + // Tearing + LISTENER(tearingNew); + DYNLISTENFUNC(tearingSet); + DYNLISTENFUNC(tearingDestroy); }; diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp index 1edea5ba..cf7b27f6 100644 --- a/src/events/Misc.cpp +++ b/src/events/Misc.cpp @@ -213,3 +213,32 @@ void Events::listener_newTextInput(wl_listener* listener, void* data) { g_pInputManager->m_sIMERelay.onNewTextInput((wlr_text_input_v3*)data); } + +void Events::listener_tearingNew(wl_listener* listener, void* data) { + Debug::log(LOG, "New tearing object at %x", data); + + const auto foundHint = wlr_tearing_control_manager_v1_surface_hint_from_surface(g_pCompositor->m_sWLRTearingMgr, ((wlr_tearing_control_v1*)data)->surface); + + Debug::log(LOG, "Surface associated: %x, check 2: %i", ((wlr_tearing_control_v1*)data)->surface, foundHint); + + const auto NEWCTRL = &g_pHyprRenderer->m_lTearingControllers.emplace_back(); + NEWCTRL->pWlrHint = (wlr_tearing_control_v1*)data; + + NEWCTRL->hyprListener_destroy.initCallback(&NEWCTRL->pWlrHint->events.destroy, [&] (void* owner, void* data) { + Debug::log(LOG, "Destroyed %x tearing", ((STearingController*)owner)->pWlrHint); + + g_pHyprRenderer->m_lTearingControllers.remove(*((STearingController*)owner)); + }, NEWCTRL, "TearingController"); + + NEWCTRL->hyprListener_set.initCallback(&NEWCTRL->pWlrHint->events.set_hint, [&] (void* owner, void* data) { + const auto TEARINGHINT = (STearingController*)owner; + + const auto PWINDOW = g_pCompositor->getWindowFromSurface(TEARINGHINT->pWlrHint->surface); + + if (PWINDOW) { + PWINDOW->m_bTearingHint = TEARINGHINT->pWlrHint->hint; + + Debug::log(LOG, "Hint %x (window %x) set tearing hint to %d", TEARINGHINT->pWlrHint, PWINDOW, TEARINGHINT->pWlrHint->hint); + } + }, NEWCTRL, "TearingController"); +} \ No newline at end of file diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 4414187a..116a6f32 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -168,6 +168,10 @@ void Events::listener_monitorFrame(void* owner, void* data) { } } + // check if we have a solitary client. If so, reject any draws not queued by our client (passed in data) + if (PMONITOR->solitaryClient && data != PMONITOR->solitaryClient && PMONITOR->solitaryClient->shouldImmediate()) + return; + timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -188,6 +192,12 @@ void Events::listener_monitorFrame(void* owner, void* data) { return; } + if (PMONITOR->solitaryClient) { + // force damage + hasChanged = true; + pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x * 10, (int)PMONITOR->vecTransformedSize.y * 10); + } + // we need to cleanup fading out when rendering the appropriate context g_pCompositor->cleanupFadingOut(PMONITOR->ID); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 24a3fcd4..fe414ec8 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -183,6 +183,8 @@ void Events::listener_mapWindow(void* owner, void* data) { } else { Debug::log(ERR, "Rule idleinhibit: unknown mode %s", IDLERULE.c_str()); } + } else if (r.szRule == "immediate") { + PWINDOW->m_sAdditionalConfigData.forceTearing = true; } PWINDOW->applyDynamicRule(r); } @@ -659,12 +661,10 @@ void Events::listener_unmapWindow(void* owner, void* data) { void Events::listener_commitWindow(void* owner, void* data) { CWindow* PWINDOW = (CWindow*)owner; - if (!PWINDOW->m_bMappedX11 || PWINDOW->isHidden() || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11)) + if (!PWINDOW->m_bIsMapped || PWINDOW->isHidden()) return; g_pHyprRenderer->damageSurface(g_pXWaylandManager->getWindowSurface(PWINDOW), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y); - - // Debug::log(LOG, "Window %x committed", PWINDOW); // SPAM! } void Events::listener_destroyWindow(void* owner, void* data) { diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index eb481748..a05c27e5 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -229,10 +229,16 @@ void CMonitor::onDisconnect() { } void CMonitor::addDamage(pixman_region32_t* rg) { + if (solitaryClient) // when there is a solitary client, we adjust to its commits. + return; + wlr_output_damage_add(damage, rg); } void CMonitor::addDamage(wlr_box* box) { + if (solitaryClient) + return; + wlr_output_damage_add_box(damage, box); } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index c2cc179b..19fd476e 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -42,6 +42,9 @@ public: bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed. bool createdByUser = false; + // will attempt DS + CWindow* solitaryClient = nullptr; // used for stuff like tearing / VRR + // mirroring CMonitor* pMirrorOf = nullptr; std::vector mirrors; @@ -68,6 +71,7 @@ public: void onDisconnect(); void addDamage(pixman_region32_t* rg); void addDamage(wlr_box* box); + void forceDamageEntire(); void setMirror(const std::string&); bool isMirror(); diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp index a41030f5..3b3a3432 100644 --- a/src/helpers/SubsurfaceTree.cpp +++ b/src/helpers/SubsurfaceTree.cpp @@ -224,6 +224,18 @@ void Events::listener_commitSubsurface(void* owner, void* data) { } } + // check window if X11, we have a special case + if (pNode->pWindowOwner) { + const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->pWindowOwner->m_iMonitorID); + + if (PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->shouldImmediate()) { + // TODO: we should do an asynchronous flip here. wlr patch needed. + listener_monitorFrame(PMONITOR, pNode->pWindowOwner); + + Debug::log(LOG, "damage commit!"); + } + } + g_pHyprRenderer->damageSurface(pNode->pSurface, lx, ly); } diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index c340a516..dde1ee5d 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -349,3 +349,14 @@ struct SSwitchDevice { return pWlrDevice == other.pWlrDevice; } }; + +struct STearingController { + wlr_tearing_control_v1* pWlrHint = nullptr; + + DYNLISTENER(set); + DYNLISTENER(destroy); + + bool operator==(const STearingController& other) { + return pWlrHint == other.pWlrHint; + } +}; diff --git a/src/includes.hpp b/src/includes.hpp index 55c795f5..1c0558f8 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -103,6 +103,7 @@ extern "C" { #include #include #include +#include #include diff --git a/src/main.cpp b/src/main.cpp index 9f34c088..92b09577 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,6 +23,7 @@ int main(int argc, char** argv) { setenv("_JAVA_AWT_WM_NONREPARENTING", "1", 0); // parse some args + bool logWlr = false; std::string configPath; for (int i = 1; i < argc; ++i) { if (!strcmp(argv[i], "--i-am-really-stupid")) @@ -30,6 +31,8 @@ int main(int argc, char** argv) { else if ((!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config")) && argc >= i + 2) { configPath = std::string(argv[++i]); Debug::log(LOG, "Using config location %s.", configPath.c_str()); + } else if (!strcmp(argv[i], "--log-wlr")) { + logWlr = true; } else { std::cout << "Hyprland usage: Hyprland [arg [...]].\n\nArguments:\n" << "--help -h | Show this help message\n" << @@ -53,7 +56,7 @@ int main(int argc, char** argv) { std::cout << "Welcome to Hyprland!\n"; const auto LOGWLR = getenv("HYPRLAND_LOG_WLR"); - if (LOGWLR && std::string(LOGWLR) == "1") + if ((LOGWLR && std::string(LOGWLR) == "1") || logWlr) wlr_log_init(WLR_DEBUG, Debug::wlrLog); // let's init the compositor. diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 4ede58b4..38fa386a 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -556,6 +556,8 @@ void countSubsurfacesIter(wlr_surface* pSurface, int x, int y, void* data) { } bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { + pMonitor->solitaryClient = nullptr; + if (!pMonitor->mirrors.empty()) return false; // do not DS if this monitor is being mirrored. Will break the functionality. @@ -609,6 +611,7 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { // finally, we should be GTG. wlr_output_attach_buffer(pMonitor->output, &PSURFACE->buffer->base); + pMonitor->solitaryClient = PCANDIDATE; if (!wlr_output_test(pMonitor->output)) { return false; @@ -620,10 +623,8 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, PSURFACE, pMonitor->output); if (wlr_output_commit(pMonitor->output)) { - if (!m_pLastScanout) { + if (!m_pLastScanout) m_pLastScanout = PCANDIDATE; - Debug::log(LOG, "Entered a direct scanout to %x: \"%s\"", PCANDIDATE, PCANDIDATE->m_szTitle.c_str()); - } } else { m_pLastScanout = nullptr; return false; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 8bd65418..c2cd9518 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -51,6 +51,8 @@ public: bool attemptDirectScanout(CMonitor*); void setWindowScanoutMode(CWindow*); + std::list m_lTearingControllers; + private: void arrangeLayerArray(CMonitor*, const std::vector>&, bool, wlr_box*); void renderWorkspaceWithFullscreenWindow(CMonitor*, CWorkspace*, timespec*); -- cgit v1.2.3