summaryrefslogtreecommitdiff
path: root/src/render/Renderer.cpp
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2023-09-28 21:48:33 +0100
committerGitHub <noreply@github.com>2023-09-28 21:48:33 +0100
commit88b63a00b68350d6d001445357a2582ab5975f9c (patch)
treea730d59c70e5987eae8006fd5b0eb4ef531113dc /src/render/Renderer.cpp
parent1e513e25d5645260a2ebdfbe8dbf3b8df487339c (diff)
renderer: Tearing implementation (#3441)
Diffstat (limited to 'src/render/Renderer.cpp')
-rw-r--r--src/render/Renderer.cpp137
1 files changed, 92 insertions, 45 deletions
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 6dcf0b44..982edd4b 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -3,6 +3,13 @@
#include "linux-dmabuf-unstable-v1-protocol.h"
#include "../helpers/Region.hpp"
+CHyprRenderer::CHyprRenderer() {
+ const auto ENV = getenv("WLR_DRM_NO_ATOMIC");
+
+ if (ENV && std::string(ENV) == "1")
+ m_bTearingEnvSatisfied = true;
+}
+
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;
@@ -702,51 +709,12 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) {
if (!wlr_output_is_direct_scanout_allowed(pMonitor->output))
return false;
- 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;
-
- const auto PCANDIDATE = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
+ const auto PCANDIDATE = pMonitor->solitaryClient;
if (!PCANDIDATE)
- return false; // ????
-
- if (PCANDIDATE->m_fAlpha.fl() != 1.f || PCANDIDATE->m_fActiveInactiveAlpha.fl() != 1.f || PWORKSPACE->m_fAlpha.fl() != 1.f)
return false;
- if (PCANDIDATE->m_vRealSize.vec() != pMonitor->vecSize || PCANDIDATE->m_vRealPosition.vec() != pMonitor->vecPosition || PCANDIDATE->m_vRealPosition.isBeingAnimated() ||
- PCANDIDATE->m_vRealSize.isBeingAnimated())
- return false;
-
- if (!pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY].empty())
- return false;
-
- for (auto& topls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
- if (topls->alpha.fl() != 0.f)
- return false;
- }
-
- // check if it did not open any subsurfaces or shit
- int surfaceCount = 0;
- if (PCANDIDATE->m_bIsX11) {
- surfaceCount = 1;
-
- // check opaque
- if (PCANDIDATE->m_uSurface.xwayland->has_alpha)
- return false;
- } 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;
- }
-
- if (surfaceCount != 1)
- return false;
-
- const auto PSURFACE = PCANDIDATE->m_pWLSurface.wlr();
+ const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE);
if (!PSURFACE || PSURFACE->current.scale != pMonitor->output->scale || PSURFACE->current.transform != pMonitor->output->transform)
return false;
@@ -754,9 +722,8 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) {
// finally, we should be GTG.
wlr_output_attach_buffer(pMonitor->output, &PSURFACE->buffer->base);
- if (!wlr_output_test(pMonitor->output)) {
+ if (!wlr_output_test(pMonitor->output))
return false;
- }
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
@@ -790,6 +757,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
static auto* const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue;
static auto* const PBACKGROUNDCOLOR = &g_pConfigManager->getConfigValuePtr("misc:background_color")->intValue;
static auto* const PANIMENABLED = &g_pConfigManager->getConfigValuePtr("animations:enabled")->intValue;
+ static auto* const PTEARINGENABLED = &g_pConfigManager->getConfigValuePtr("general:allow_tearing")->intValue;
static int damageBlinkCleanup = 0; // because double-buffered
@@ -876,8 +844,38 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
}
}
- // Direct scanout first
- if (!*PNODIRECTSCANOUT) {
+ // tearing and DS first
+ bool shouldTear = false;
+ bool canTear = *PTEARINGENABLED && g_pHyprOpenGL->m_RenderData.mouseZoomFactor == 1.0;
+ recheckSolitaryForMonitor(pMonitor);
+ if (pMonitor->nextRenderTorn) {
+ pMonitor->nextRenderTorn = false;
+
+ if (!*PTEARINGENABLED) {
+ Debug::log(WARN, "Tearing commit requested but the master switch general:allow_tearing is off, ignoring");
+ return;
+ }
+
+ if (g_pHyprOpenGL->m_RenderData.mouseZoomFactor != 1.0) {
+ Debug::log(WARN, "Tearing commit requested but scale factor is not 1, ignoring");
+ return;
+ }
+
+ if (!pMonitor->canTear) {
+ Debug::log(WARN, "Tearing commit requested but monitor doesn't support it, ignoring");
+ return;
+ }
+
+ if (pMonitor->solitaryClient)
+ shouldTear = true;
+ } else {
+ // if this is a non-tearing commit, and we are in a state where we should tear
+ // then this is a vblank commit that we should ignore
+ if (canTear && pMonitor->solitaryClient && pMonitor->canTear && pMonitor->solitaryClient->canBeTorn() && pMonitor->renderingFromVblankEvent)
+ return;
+ }
+
+ if (!*PNODIRECTSCANOUT && !shouldTear) {
if (attemptDirectScanout(pMonitor)) {
return;
} else if (m_pLastScanout) {
@@ -1061,6 +1059,8 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
EMIT_HOOK_EVENT("render", RENDER_POST);
+ pMonitor->output->pending.tearing_page_flip = shouldTear;
+
if (!wlr_output_commit(pMonitor->output)) {
if (UNLOCK_SC)
wlr_output_lock_software_cursors(pMonitor->output, false);
@@ -1068,6 +1068,9 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
return;
}
+ if (shouldTear)
+ pMonitor->ignoreNextFlipEvent = true;
+
wlr_damage_ring_rotate(&pMonitor->damage);
if (UNLOCK_SC)
@@ -1986,3 +1989,47 @@ bool CHyprRenderer::canSkipBackBufferClear(CMonitor* pMonitor) {
return false;
}
+
+void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) {
+ pMonitor->solitaryClient = nullptr; // reset it, if we find one it will be set.
+
+ 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;
+
+ const auto PCANDIDATE = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
+
+ if (!PCANDIDATE)
+ return; // ????
+
+ if (!PCANDIDATE->opaque())
+ return;
+
+ if (PCANDIDATE->m_vRealSize.vec() != pMonitor->vecSize || PCANDIDATE->m_vRealPosition.vec() != pMonitor->vecPosition || PCANDIDATE->m_vRealPosition.isBeingAnimated() ||
+ PCANDIDATE->m_vRealSize.isBeingAnimated())
+ return;
+
+ if (!pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY].empty())
+ return;
+
+ for (auto& topls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
+ if (topls->alpha.fl() != 0.f)
+ return;
+ }
+
+ // check if it did not open any subsurfaces or shit
+ int surfaceCount = 0;
+ if (PCANDIDATE->m_bIsX11) {
+ surfaceCount = 1;
+ } 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 (surfaceCount != 1)
+ Debug::log(LOG, "fuf: >1 surf");
+
+ // found one!
+ pMonitor->solitaryClient = PCANDIDATE;
+}