diff options
author | vaxerski <[email protected]> | 2023-03-25 18:40:15 +0000 |
---|---|---|
committer | vaxerski <[email protected]> | 2023-03-25 18:40:15 +0000 |
commit | 1990c7cd2a585aa88380f155d0b0aaf04311392d (patch) | |
tree | 23c2819e3f77558b4c649580c215f727415bae6c | |
parent | 41f7736c8521162cb3ea5f3c003e0643c1bcf616 (diff) | |
download | Hyprland-1990c7cd2a585aa88380f155d0b0aaf04311392d.tar.gz Hyprland-1990c7cd2a585aa88380f155d0b0aaf04311392d.zip |
Implement tearing v2
-rw-r--r-- | src/Compositor.cpp | 3 | ||||
-rw-r--r-- | src/Compositor.hpp | 1 | ||||
-rw-r--r-- | src/Window.cpp | 12 | ||||
-rw-r--r-- | src/Window.hpp | 7 | ||||
-rw-r--r-- | src/config/ConfigManager.cpp | 2 | ||||
-rw-r--r-- | src/debug/HyprCtl.cpp | 2 | ||||
-rw-r--r-- | src/events/Events.hpp | 3 | ||||
-rw-r--r-- | src/events/Misc.cpp | 29 | ||||
-rw-r--r-- | src/events/Monitors.cpp | 3 | ||||
-rw-r--r-- | src/events/Windows.cpp | 2 | ||||
-rw-r--r-- | src/helpers/Monitor.hpp | 3 | ||||
-rw-r--r-- | src/helpers/SubsurfaceTree.cpp | 20 | ||||
-rw-r--r-- | src/helpers/WLClasses.hpp | 11 | ||||
-rw-r--r-- | src/includes.hpp | 1 | ||||
-rw-r--r-- | src/render/Renderer.cpp | 69 | ||||
-rw-r--r-- | src/render/Renderer.hpp | 8 |
16 files changed, 153 insertions, 23 deletions
diff --git a/src/Compositor.cpp b/src/Compositor.cpp index b145022c..ec6dc0f9 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -242,6 +242,8 @@ void CCompositor::initServer() { m_sWLRSessionLockMgr = wlr_session_lock_manager_v1_create(m_sWLDisplay); + m_sWLRTearingMgr = wlr_tearing_control_manager_v1_create(m_sWLDisplay, 1); + if (!m_sWLRHeadlessBackend) { Debug::log(CRIT, "Couldn't create the headless backend"); throw std::runtime_error("wlr_headless_backend_create() failed!"); @@ -298,6 +300,7 @@ void CCompositor::initAllSignals() { 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_sWLRSessionLockMgr->events.new_lock, &Events::listen_newSessionLock, m_sWLRSessionLockMgr, "SessionLockMgr"); + addWLSignal(&m_sWLRTearingMgr->events.new_object, &Events::listen_newTearingObject, m_sWLRTearingMgr, "TearingMgr"); if (m_sWRLDRMLeaseMgr) addWLSignal(&m_sWRLDRMLeaseMgr->events.request, &Events::listen_leaseRequest, &m_sWRLDRMLeaseMgr, "DRM"); diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 7bae7672..64efb527 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -83,6 +83,7 @@ class CCompositor { wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf; wlr_backend* m_sWLRHeadlessBackend; wlr_session_lock_manager_v1* m_sWLRSessionLockMgr; + wlr_tearing_control_manager_v1* m_sWLRTearingMgr; // ------------------------------------------------- // std::string m_szWLDisplaySocket = ""; diff --git a/src/Window.cpp b/src/Window.cpp index 840944d4..ca206a1c 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -338,6 +338,11 @@ void CWindow::onUnmap() { std::erase_if(g_pCompositor->m_vWindowFocusHistory, [&](const auto& other) { return other == this; }); m_pWLSurface.unassign(); + + const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + + if (PMONITOR && PMONITOR->m_pSolitaryClient == this) + PMONITOR->m_pSolitaryClient = nullptr; } void CWindow::onMap() { @@ -409,6 +414,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { } else if (r.szRule == "opaque") { if (!m_sAdditionalConfigData.forceOpaqueOverriden) m_sAdditionalConfigData.forceOpaque = true; + } else if (r.szRule == "immediate") { + m_sAdditionalConfigData.forceTearing = true; } else if (r.szRule.find("rounding") == 0) { try { m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1)); @@ -470,6 +477,7 @@ void CWindow::updateDynamicRules() { m_sAdditionalConfigData.animationStyle = std::string(""); m_sAdditionalConfigData.rounding = -1; m_sAdditionalConfigData.dimAround = false; + m_sAdditionalConfigData.forceTearing = false; const auto WINDOWRULES = g_pConfigManager->getMatchingRules(this); for (auto& r : WINDOWRULES) { @@ -640,4 +648,8 @@ void CWindow::updateGroupOutputs() { curr = curr->m_sGroupData.pNextWindow; } +} + +bool CWindow::canBeTorn() { + return (m_sAdditionalConfigData.forceTearing.toUnderlying() || m_bTearingHint) && g_pHyprRenderer->m_bTearingSupported; }
\ No newline at end of file diff --git a/src/Window.hpp b/src/Window.hpp index 6cada8c8..7462138b 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -119,6 +119,7 @@ struct SWindowAdditionalConfigData { CWindowOverridableVar<bool> windowDanceCompat = false; CWindowOverridableVar<bool> noMaxSize = false; CWindowOverridableVar<bool> dimAround = false; + CWindowOverridableVar<bool> forceTearing = false; }; struct SWindowRule { @@ -284,6 +285,10 @@ class CWindow { bool head = false; } m_sGroupData; + // for tearing + bool m_bTearingHint = false; + uint32_t m_iLastTearingSeq = 0; + // 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 && @@ -323,6 +328,8 @@ class CWindow { void insertWindowToGroup(CWindow* pWindow); void updateGroupOutputs(); + bool canBeTorn(); + private: // For hidden windows and stuff bool m_bHidden = false; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index c6a3abd1..b82dc47d 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -780,7 +780,7 @@ bool windowRuleValid(const std::string& RULE) { RULE.find("maxsize") != 0 && RULE.find("pseudo") != 0 && RULE.find("monitor") != 0 && RULE.find("idleinhibit") != 0 && RULE != "nofocus" && RULE != "noblur" && RULE != "noshadow" && RULE != "noborder" && RULE != "center" && RULE != "opaque" && RULE != "forceinput" && RULE != "fullscreen" && RULE != "nofullscreenrequest" && RULE != "nomaxsize" && RULE != "pin" && RULE != "noanim" && RULE != "dimaround" && RULE != "windowdance" && RULE != "maximize" && RULE.find("animation") != 0 && - RULE.find("rounding") != 0 && RULE.find("workspace") != 0 && RULE.find("bordercolor") != 0); + RULE.find("rounding") != 0 && RULE.find("workspace") != 0 && RULE.find("bordercolor") != 0 && RULE != "immediate"); } bool layerRuleValid(const std::string& RULE) { diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index c9b8a25d..778138e9 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -960,6 +960,8 @@ std::string dispatchSetProp(std::string request) { PWINDOW->m_sSpecialRenderData.activeBorderColor.forceSetIgnoreLocked(configStringToInt(VAL), lock); } else if (PROP == "inactivebordercolor") { PWINDOW->m_sSpecialRenderData.inactiveBorderColor.forceSetIgnoreLocked(configStringToInt(VAL), lock); + } else if (PROP == "immediate") { + PWINDOW->m_sAdditionalConfigData.forceTearing.forceSetIgnoreLocked(configStringToInt(VAL), lock); } else { return "prop not found"; } diff --git a/src/events/Events.hpp b/src/events/Events.hpp index ae441fbb..db072793 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -161,4 +161,7 @@ namespace Events { // Session Lock LISTENER(newSessionLock); + + // Tearing + LISTENER(newTearingObject); }; diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp index 8d1b9c00..f6b3d628 100644 --- a/src/events/Misc.cpp +++ b/src/events/Misc.cpp @@ -230,3 +230,32 @@ void Events::listener_newSessionLock(wl_listener* listener, void* data) { g_pSessionLockManager->onNewSessionLock((wlr_session_lock_v1*)data); } + +void Events::listener_newTearingObject(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 ad0e416b..02d1c4eb 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -131,6 +131,9 @@ void Events::listener_monitorFrame(void* owner, void* data) { PMONITOR->lastPresentationTimer.reset(); + if (PMONITOR->m_pSolitaryClient && PMONITOR->m_pSolitaryClient->canBeTorn()) + return; // the client shall schedule repaints + if (*PENABLERAT) { if (!PMONITOR->RATScheduled) { // render diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index adbd2118..050b9999 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -709,8 +709,6 @@ void Events::listener_commitWindow(void* owner, void* data) { PWINDOW->updateSurfaceOutputs(); g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), 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.hpp b/src/helpers/Monitor.hpp index 0707d79f..04f4a23d 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -49,6 +49,7 @@ class CMonitor { wl_event_source* renderTimer = nullptr; // for RAT bool RATScheduled = false; CTimer lastPresentationTimer; + CTimer lastFrameTimer; // mirroring CMonitor* pMirrorOf = nullptr; @@ -57,6 +58,8 @@ class CMonitor { // for the special workspace. 0 means not open. int specialWorkspaceID = 0; + CWindow* m_pSolitaryClient = nullptr; + std::array<std::vector<std::unique_ptr<SLayerSurface>>, 4> m_aLayerSurfaceLayers; DYNLISTENER(monitorFrame); diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp index 43ff3be7..f5c47adb 100644 --- a/src/helpers/SubsurfaceTree.cpp +++ b/src/helpers/SubsurfaceTree.cpp @@ -235,8 +235,26 @@ void Events::listener_commitSubsurface(void* owner, void* data) { } } - if (pNode->pSurface && pNode->pSurface->exists()) + if (pNode->pSurface && pNode->pSurface->exists()) { g_pHyprRenderer->damageSurface(pNode->pSurface->wlr(), lx, ly); + + if (pNode->pWindowOwner && &pNode->pWindowOwner->m_pWLSurface == pNode->pSurface && pNode->pSurface->wlr()->current.committed & WLR_SURFACE_STATE_BUFFER + && pNode->pWindowOwner->m_iLastTearingSeq != pNode->pSurface->wlr()->current.seq) { + const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->pWindowOwner->m_iMonitorID); + pNode->pWindowOwner->m_iLastTearingSeq = pNode->pSurface->wlr()->current.seq; + + if (!PMONITOR) + return; + + g_pHyprRenderer->updateSolitaryClient(PMONITOR); + + if (PMONITOR->m_pSolitaryClient != pNode->pWindowOwner) + return; + + if (pNode->pWindowOwner->canBeTorn()) + g_pHyprRenderer->renderMonitor(PMONITOR, true); + } + } } void Events::listener_destroySubsurface(void* owner, void* data) { diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index 0e5138b3..10b27edc 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -375,3 +375,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 83d4b71f..3a578f58 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -104,6 +104,7 @@ extern "C" { #include <wlr/backend/wayland.h> #include <wlr/types/wlr_session_lock_v1.h> #include <wlr/types/wlr_single_pixel_buffer_v1.h> +#include <wlr/types/wlr_tearing_control_v1.h> #include <drm_fourcc.h> diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index a5a576d3..cb5f25a3 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2,6 +2,17 @@ #include "../Compositor.hpp" #include "linux-dmabuf-unstable-v1-protocol.h" +void backendTearIter(wlr_backend* b, void* data) { + if (wlr_backend_is_drm(b) && wlr_drm_supports_async_page_flips(b)) { + ((CHyprRenderer*)data)->m_bTearingSupported = true; + return; + } +} + +CHyprRenderer::CHyprRenderer() { + wlr_multi_for_each_backend(g_pCompositor->m_sWLRBackend, backendTearIter, this); +} + void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { const auto TEXTURE = wlr_surface_get_texture(surface); const auto RDATA = (SRenderData*)data; @@ -662,33 +673,40 @@ void countSubsurfacesIter(wlr_surface* pSurface, int x, int y, void* data) { *(int*)data += 1; } -bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { +void CHyprRenderer::updateSolitaryClient(CMonitor* pMonitor) { + pMonitor->m_pSolitaryClient = nullptr; + if (!pMonitor->mirrors.empty() || pMonitor->isMirror()) - return false; // do not DS if this monitor is being mirrored. Will break the functionality. + return; // do not DS if this monitor is being mirrored. Will break the functionality. const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace); if (!PWORKSPACE || !PWORKSPACE->m_bHasFullscreenWindow || g_pInputManager->m_sDrag.drag || g_pCompositor->m_sSeat.exclusiveClient || pMonitor->specialWorkspaceID) - return false; + return; const auto PCANDIDATE = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); if (!PCANDIDATE) - return false; // ???? + return; // ???? if (PCANDIDATE->m_fAlpha.fl() != 1.f || PCANDIDATE->m_fActiveInactiveAlpha.fl() != 1.f || PWORKSPACE->m_fAlpha.fl() != 1.f) - return false; + return; if (PCANDIDATE->m_vRealSize.vec() != pMonitor->vecSize || PCANDIDATE->m_vRealPosition.vec() != pMonitor->vecPosition || PCANDIDATE->m_vRealPosition.isBeingAnimated() || PCANDIDATE->m_vRealSize.isBeingAnimated()) - return false; + return; if (!pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY].empty()) - return false; + return; for (auto& topls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { if (topls->alpha.fl() != 0.f) - return false; + return; + } + + for (auto& w : g_pCompositor->m_vWindows) { + if (w->m_bIsMapped && !w->isHidden() && w->m_iWorkspaceID == PCANDIDATE->m_iWorkspaceID && w->m_bCreatedOverFullscreen && w->m_bIsFloating) + return; } // check if it did not open any subsurfaces or shit @@ -698,25 +716,32 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { // check opaque if (PCANDIDATE->m_uSurface.xwayland->has_alpha) - return false; + return; } else { wlr_xdg_surface_for_each_surface(PCANDIDATE->m_uSurface.xdg, countSubsurfacesIter, &surfaceCount); wlr_xdg_surface_for_each_popup_surface(PCANDIDATE->m_uSurface.xdg, countSubsurfacesIter, &surfaceCount); if (!PCANDIDATE->m_uSurface.xdg->surface->opaque) - return false; + return; } if (surfaceCount != 1) - return false; + return; const auto PSURFACE = PCANDIDATE->m_pWLSurface.wlr(); if (!PSURFACE || PSURFACE->current.scale != pMonitor->output->scale || PSURFACE->current.transform != pMonitor->output->transform) + return; + + pMonitor->m_pSolitaryClient = PCANDIDATE; +} + +bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { + if (!pMonitor->m_pSolitaryClient) return false; // finally, we should be GTG. - wlr_output_attach_buffer(pMonitor->output, &PSURFACE->buffer->base); + wlr_output_attach_buffer(pMonitor->output, &pMonitor->m_pSolitaryClient->m_pWLSurface.wlr()->buffer->base); if (!wlr_output_test(pMonitor->output)) { return false; @@ -724,13 +749,13 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - wlr_surface_send_frame_done(PSURFACE, &now); - wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, PSURFACE, pMonitor->output); + wlr_surface_send_frame_done(pMonitor->m_pSolitaryClient->m_pWLSurface.wlr(), &now); + wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, pMonitor->m_pSolitaryClient->m_pWLSurface.wlr(), pMonitor->output); if (wlr_output_commit(pMonitor->output)) { if (!m_pLastScanout) { - m_pLastScanout = PCANDIDATE; - Debug::log(LOG, "Entered a direct scanout to %x: \"%s\"", PCANDIDATE, PCANDIDATE->m_szTitle.c_str()); + m_pLastScanout = pMonitor->m_pSolitaryClient; + Debug::log(LOG, "Entered a direct scanout to %x: \"%s\"", pMonitor->m_pSolitaryClient, pMonitor->m_pSolitaryClient->m_szTitle.c_str()); } } else { m_pLastScanout = nullptr; @@ -740,7 +765,7 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { return true; } -void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { +void CHyprRenderer::renderMonitor(CMonitor* pMonitor, bool async) { static std::chrono::high_resolution_clock::time_point startRender = std::chrono::high_resolution_clock::now(); static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now(); static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now(); @@ -797,6 +822,8 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } // Direct scanout first + updateSolitaryClient(pMonitor); + if (!*PNODIRECTSCANOUT) { if (attemptDirectScanout(pMonitor)) { return; @@ -943,6 +970,12 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { pMonitor->renderingActive = false; + if (m_bTearingSupported && async) { + wlr_output_state_set_async_page_flip(&pMonitor->output->pending, true); + } + + pMonitor->lastFrameTimer.reset(); + if (!wlr_output_commit(pMonitor->output)) return; @@ -1769,4 +1802,4 @@ std::tuple<float, float, float> CHyprRenderer::getRenderTimes(CMonitor* pMonitor avgRenderTime /= POVERLAY->m_dLastRenderTimes.size() == 0 ? 1 : POVERLAY->m_dLastRenderTimes.size(); return std::make_tuple<>(avgRenderTime, maxRenderTime, minRenderTime); -} +}
\ No newline at end of file diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 4ce0f6dc..d58d1fd2 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -31,7 +31,9 @@ struct SSessionLockSurface; class CHyprRenderer { public: - void renderMonitor(CMonitor* pMonitor); + CHyprRenderer(); + + void renderMonitor(CMonitor* pMonitor, bool async = false); void renderAllClientsForMonitor(const int&, timespec*); void outputMgrApplyTest(wlr_output_configuration_v1*, bool); void arrangeLayersForMonitor(const int&); @@ -53,14 +55,18 @@ class CHyprRenderer { bool m_bWindowRequestedCursorHide = false; bool m_bBlockSurfaceFeedback = false; bool m_bRenderingSnapshot = false; + bool m_bTearingSupported = false; CWindow* m_pLastScanout = nullptr; CMonitor* m_pMostHzMonitor = nullptr; DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&); bool attemptDirectScanout(CMonitor*); + void updateSolitaryClient(CMonitor*); void setWindowScanoutMode(CWindow*); + std::list<STearingController> m_lTearingControllers; + private: void arrangeLayerArray(CMonitor*, const std::vector<std::unique_ptr<SLayerSurface>>&, bool, wlr_box*); void renderWorkspaceWithFullscreenWindow(CMonitor*, CWorkspace*, timespec*); |