damageRing: move to hyprland impl

A small wlroots utility we were still using.
This commit is contained in:
Vaxry 2024-06-19 18:25:20 +02:00
parent 65f04f265c
commit def5fcb212
6 changed files with 111 additions and 38 deletions

View File

@ -0,0 +1,52 @@
#include "DamageRing.hpp"
void CDamageRing::setSize(const Vector2D& size_) {
if (size_ == size)
return;
size = size_;
damageEntire();
}
bool CDamageRing::damage(const CRegion& rg) {
CRegion clipped = rg.copy().intersect(CBox{{}, size});
if (clipped.empty())
return false;
current.add(clipped);
return true;
}
void CDamageRing::damageEntire() {
damage(CBox{{}, size});
}
void CDamageRing::rotate() {
previousIdx = (previousIdx + DAMAGE_RING_PREVIOUS_LEN - 1) % DAMAGE_RING_PREVIOUS_LEN;
previous[previousIdx] = current;
current.clear();
}
CRegion CDamageRing::getBufferDamage(int age) {
if (age <= 0 || age > DAMAGE_RING_PREVIOUS_LEN + 1)
return CBox{{}, size};
CRegion damage = current;
for (int i = 0; i < age - 1; ++i) {
int j = (previousIdx + i) % DAMAGE_RING_PREVIOUS_LEN;
damage.add(previous.at(j));
}
// don't return a ludicrous amount of rects
if (damage.getRects().size() > 8)
return damage.getExtents();
return damage;
}
bool CDamageRing::hasChanged() {
return !current.empty();
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "./math/Math.hpp"
#include <array>
constexpr static int DAMAGE_RING_PREVIOUS_LEN = 2;
class CDamageRing {
public:
void setSize(const Vector2D& size_);
bool damage(const CRegion& rg);
void damageEntire();
void rotate();
CRegion getBufferDamage(int age);
bool hasChanged();
private:
Vector2D size;
CRegion current;
std::array<CRegion, DAMAGE_RING_PREVIOUS_LEN> previous;
size_t previousIdx = 0;
};

View File

@ -17,12 +17,10 @@ int ratHandler(void* data) {
} }
CMonitor::CMonitor() : state(this) { CMonitor::CMonitor() : state(this) {
wlr_damage_ring_init(&damage); ;
} }
CMonitor::~CMonitor() { CMonitor::~CMonitor() {
wlr_damage_ring_finish(&damage);
hyprListener_monitorDestroy.removeCallback(); hyprListener_monitorDestroy.removeCallback();
hyprListener_monitorFrame.removeCallback(); hyprListener_monitorFrame.removeCallback();
hyprListener_monitorStateRequest.removeCallback(); hyprListener_monitorStateRequest.removeCallback();
@ -162,7 +160,7 @@ void CMonitor::onConnect(bool noRule) {
if (!state.commit()) if (!state.commit())
Debug::log(WARN, "wlr_output_commit_state failed in CMonitor::onCommit"); Debug::log(WARN, "wlr_output_commit_state failed in CMonitor::onCommit");
wlr_damage_ring_set_bounds(&damage, vecTransformedSize.x, vecTransformedSize.y); damage.setSize(vecTransformedSize);
Debug::log(LOG, "Added new monitor with name {} at {:j0} with size {:j0}, pointer {:x}", output->name, vecPosition, vecPixelSize, (uintptr_t)output); Debug::log(LOG, "Added new monitor with name {} at {:j0} with size {:j0}, pointer {:x}", output->name, vecPosition, vecPixelSize, (uintptr_t)output);
@ -345,9 +343,9 @@ void CMonitor::onDisconnect(bool destroy) {
void CMonitor::addDamage(const pixman_region32_t* rg) { void CMonitor::addDamage(const pixman_region32_t* rg) {
static auto PZOOMFACTOR = CConfigValue<Hyprlang::FLOAT>("cursor:zoom_factor"); static auto PZOOMFACTOR = CConfigValue<Hyprlang::FLOAT>("cursor:zoom_factor");
if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
wlr_damage_ring_add_whole(&damage); damage.damageEntire();
g_pCompositor->scheduleFrameForMonitor(this); g_pCompositor->scheduleFrameForMonitor(this);
} else if (wlr_damage_ring_add(&damage, rg)) } else if (damage.damage(rg))
g_pCompositor->scheduleFrameForMonitor(this); g_pCompositor->scheduleFrameForMonitor(this);
} }
@ -358,13 +356,11 @@ void CMonitor::addDamage(const CRegion* rg) {
void CMonitor::addDamage(const CBox* box) { void CMonitor::addDamage(const CBox* box) {
static auto PZOOMFACTOR = CConfigValue<Hyprlang::FLOAT>("cursor:zoom_factor"); static auto PZOOMFACTOR = CConfigValue<Hyprlang::FLOAT>("cursor:zoom_factor");
if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
wlr_damage_ring_add_whole(&damage); damage.damageEntire();
g_pCompositor->scheduleFrameForMonitor(this); g_pCompositor->scheduleFrameForMonitor(this);
} }
wlr_box damageBox = {(int)box->x, (int)box->y, (int)box->w, (int)box->h}; if (damage.damage(*box))
if (wlr_damage_ring_add_box(&damage, &damageBox))
g_pCompositor->scheduleFrameForMonitor(this); g_pCompositor->scheduleFrameForMonitor(this);
} }
@ -379,7 +375,7 @@ bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() {
// keep requested minimum refresh rate // keep requested minimum refresh rate
if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000 / *PMINRR) { if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000 / *PMINRR) {
// damage whole screen because some previous cursor box damages were skipped // damage whole screen because some previous cursor box damages were skipped
wlr_damage_ring_add_whole(&damage); damage.damageEntire();
return false; return false;
} }

View File

@ -11,6 +11,7 @@
#include "math/Math.hpp" #include "math/Math.hpp"
#include <optional> #include <optional>
#include "signal/Signal.hpp" #include "signal/Signal.hpp"
#include "DamageRing.hpp"
// Enum for the different types of auto directions, e.g. auto-left, auto-up. // Enum for the different types of auto directions, e.g. auto-left, auto-up.
enum eAutoDirs { enum eAutoDirs {
@ -84,9 +85,8 @@ class CMonitor {
drmModeModeInfo customDrmMode = {}; drmModeModeInfo customDrmMode = {};
CMonitorState state; CMonitorState state;
CDamageRing damage;
// WLR stuff
wlr_damage_ring damage;
wlr_output* output = nullptr; wlr_output* output = nullptr;
float refreshRate = 60; float refreshRate = 60;
int framesToSkip = 0; int framesToSkip = 0;

View File

@ -53,7 +53,6 @@ extern "C" {
#include <wlr/types/wlr_primary_selection_v1.h> #include <wlr/types/wlr_primary_selection_v1.h>
#include <wlr/types/wlr_viewporter.h> #include <wlr/types/wlr_viewporter.h>
#include <wlr/types/wlr_subcompositor.h> #include <wlr/types/wlr_subcompositor.h>
#include <wlr/types/wlr_damage_ring.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include <wlr/util/region.h> #include <wlr/util/region.h>
#include <wlr/util/edges.h> #include <wlr/util/edges.h>

View File

@ -1246,7 +1246,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
// check the damage // check the damage
bool hasChanged = pMonitor->output->needs_frame || pixman_region32_not_empty(&pMonitor->damage.current); bool hasChanged = pMonitor->output->needs_frame || pMonitor->damage.hasChanged();
if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->forceFullFrames == 0 && damageBlinkCleanup == 0) if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->forceFullFrames == 0 && damageBlinkCleanup == 0)
return; return;
@ -1414,7 +1414,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
pMonitor->state.wlr()->tearing_page_flip = shouldTear; pMonitor->state.wlr()->tearing_page_flip = shouldTear;
if (!pMonitor->state.commit()) { if (!pMonitor->state.commit()) {
wlr_damage_ring_add_whole(&pMonitor->damage); pMonitor->damage.damageEntire();
return; return;
} }
@ -2245,7 +2245,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
// updato wlroots // updato wlroots
g_pCompositor->arrangeMonitors(); g_pCompositor->arrangeMonitors();
wlr_damage_ring_set_bounds(&pMonitor->damage, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); pMonitor->damage.setSize(pMonitor->vecTransformedSize);
// Set scale for all surfaces on this monitor, needed for some clients // Set scale for all surfaces on this monitor, needed for some clients
// but not on unsafe state to avoid crashes // but not on unsafe state to avoid crashes
@ -2609,13 +2609,15 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode
return true; return true;
} }
int bufferAge = 0;
if (!buffer) { if (!buffer) {
if (!wlr_output_configure_primary_swapchain(pMonitor->output, pMonitor->state.wlr(), &pMonitor->output->swapchain)) { 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); Debug::log(ERR, "Failed to configure primary swapchain for {}", pMonitor->szName);
return false; return false;
} }
m_pCurrentWlrBuffer = wlr_swapchain_acquire(pMonitor->output->swapchain, nullptr); m_pCurrentWlrBuffer = wlr_swapchain_acquire(pMonitor->output->swapchain, &bufferAge);
if (!m_pCurrentWlrBuffer) { if (!m_pCurrentWlrBuffer) {
Debug::log(ERR, "Failed to acquire swapchain buffer for {}", pMonitor->szName); Debug::log(ERR, "Failed to acquire swapchain buffer for {}", pMonitor->szName);
return false; return false;
@ -2634,8 +2636,10 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode
return false; return false;
} }
if (mode == RENDER_MODE_NORMAL) if (mode == RENDER_MODE_NORMAL) {
wlr_damage_ring_rotate_buffer(&pMonitor->damage, m_pCurrentWlrBuffer, damage.pixman()); damage = pMonitor->damage.getBufferDamage(bufferAge);
pMonitor->damage.rotate();
}
m_pCurrentRenderbuffer->bind(); m_pCurrentRenderbuffer->bind();
if (simple) if (simple)