mirror of
https://github.com/hyprwm/Hyprland.git
synced 2026-09-26 00:50:59 -04:00
renderer: reduce per-frame heap allocations (#14932)
* renderer: reduce per-frame heap allocations * renderer: avoid temporary traversal allocations * renderer: avoid read-only hot-path copies * config/actions: guard workspace change without active workspace * config/lua: release owned state on shutdown --------- Co-authored-by: Pppp1116 <pcaiadoguerreiro@gmail.com>
This commit is contained in:
@@ -201,6 +201,17 @@ CConfigManager::CConfigManager() : m_mainConfigPath(Supplementary::Jeremy::getMa
|
||||
});
|
||||
}
|
||||
|
||||
CConfigManager::~CConfigManager() {
|
||||
m_eventHandler.reset();
|
||||
|
||||
cleanTimers();
|
||||
clearLuaLayoutProviders();
|
||||
clearHeldLuaRefs();
|
||||
|
||||
if (m_lua && m_ownsLuaState)
|
||||
lua_close(m_lua);
|
||||
}
|
||||
|
||||
CConfigManager* CConfigManager::fromLuaState(lua_State* L) {
|
||||
if (!L)
|
||||
return nullptr;
|
||||
@@ -281,12 +292,13 @@ void CConfigManager::reinitLuaState() {
|
||||
cleanTimers();
|
||||
clearLuaLayoutProviders();
|
||||
|
||||
if (m_lua) {
|
||||
if (m_lua && m_ownsLuaState) {
|
||||
lua_close(m_lua);
|
||||
m_lua = nullptr;
|
||||
}
|
||||
m_lua = nullptr;
|
||||
|
||||
m_lua = luaL_newstate();
|
||||
m_lua = luaL_newstate();
|
||||
m_ownsLuaState = true;
|
||||
luaL_openlibs(m_lua);
|
||||
|
||||
lua_getglobal(m_lua, "debug");
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace Config::Lua {
|
||||
class CConfigManager : public Config::IConfigManager {
|
||||
public:
|
||||
CConfigManager();
|
||||
virtual ~CConfigManager() override;
|
||||
|
||||
virtual eConfigManagerType type() override;
|
||||
|
||||
@@ -157,7 +158,8 @@ namespace Config::Lua {
|
||||
|
||||
static void watchdogHook(lua_State* L, lua_Debug* ar);
|
||||
|
||||
lua_State* m_lua = nullptr;
|
||||
lua_State* m_lua = nullptr;
|
||||
bool m_ownsLuaState = false;
|
||||
|
||||
bool m_lastConfigVerificationWasSuccessful = true;
|
||||
bool m_isFirstLaunch = true;
|
||||
|
||||
@@ -978,7 +978,10 @@ static PHLWORKSPACE resolveWorkspaceForChange(const std::string& args) {
|
||||
return nullptr;
|
||||
|
||||
const auto PCURRENTWORKSPACE = PMONITOR->m_activeWorkspace;
|
||||
const bool EXPLICITPREVIOUS = args.contains("previous");
|
||||
if (!PCURRENTWORKSPACE)
|
||||
return nullptr;
|
||||
|
||||
const bool EXPLICITPREVIOUS = args.contains("previous");
|
||||
|
||||
// handle "previous" workspace
|
||||
if (args.starts_with("previous")) {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "../../managers/eventLoop/EventLoopManager.hpp"
|
||||
#include "../../render/Renderer.hpp"
|
||||
#include "../../render/OpenGL.hpp"
|
||||
#include <array>
|
||||
#include <ranges>
|
||||
|
||||
using namespace Desktop;
|
||||
@@ -438,6 +439,7 @@ void CPopup::recheckChildrenRecursive() {
|
||||
return;
|
||||
|
||||
std::vector<WP<CPopup>> cpy;
|
||||
cpy.reserve(m_children.size());
|
||||
std::ranges::for_each(m_children, [&cpy](const auto& el) { cpy.emplace_back(el); });
|
||||
for (auto const& c : cpy) {
|
||||
if (!c || !c->visible())
|
||||
@@ -464,19 +466,21 @@ void CPopup::sendScale() {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void CPopup::bfHelper(std::vector<SP<CPopup>> const& nodes, std::function<void(SP<CPopup>, void*)> fn, void* data) {
|
||||
void CPopup::bfHelper(std::span<const SP<CPopup>> nodes, std::function<void(SP<CPopup>, void*)> fn, void* data) {
|
||||
for (auto const& n : nodes) {
|
||||
fn(n, data);
|
||||
}
|
||||
|
||||
std::vector<SP<CPopup>> nodes2;
|
||||
nodes2.reserve(nodes.size() * 2);
|
||||
|
||||
for (auto const& n : nodes) {
|
||||
if (!n)
|
||||
continue;
|
||||
|
||||
for (auto const& c : n->m_children) {
|
||||
if (nodes2.empty())
|
||||
nodes2.reserve(nodes.size() * 2);
|
||||
|
||||
nodes2.emplace_back(c->m_self.lock());
|
||||
}
|
||||
}
|
||||
@@ -489,8 +493,7 @@ void CPopup::breadthfirst(std::function<void(SP<CPopup>, void*)> fn, void* data)
|
||||
if (!m_self)
|
||||
return;
|
||||
|
||||
std::vector<SP<CPopup>> popups;
|
||||
popups.emplace_back(m_self.lock());
|
||||
const std::array popups = {m_self.lock()};
|
||||
bfHelper(popups, fn, data);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <span>
|
||||
#include <vector>
|
||||
#include "Subsurface.hpp"
|
||||
#include "View.hpp"
|
||||
@@ -114,6 +115,6 @@ namespace Desktop::View {
|
||||
Vector2D localToGlobal(const Vector2D& rel) const;
|
||||
Vector2D t1ParentCoords() const;
|
||||
void invalidateTreeExtentsCache();
|
||||
static void bfHelper(std::vector<SP<CPopup>> const& nodes, std::function<void(SP<CPopup>, void*)> fn, void* data);
|
||||
static void bfHelper(std::span<const SP<CPopup>> nodes, std::function<void(SP<CPopup>, void*)> fn, void* data);
|
||||
};
|
||||
}
|
||||
|
||||
+23
-12
@@ -1,5 +1,8 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <ranges>
|
||||
#include <span>
|
||||
#include <hyprutils/animation/AnimatedVariable.hpp>
|
||||
#include <re2/re2.h>
|
||||
|
||||
@@ -353,20 +356,28 @@ void CWindow::updateWindowDecos() {
|
||||
|
||||
m_decosToRemove.clear();
|
||||
|
||||
// make a copy because updateWindow can remove decos.
|
||||
const auto updateDecos = [this](const auto& decos) {
|
||||
for (auto const& wd : decos) {
|
||||
if (std::ranges::find_if(m_windowDecorations, [wd](const auto& other) { return other.get() == wd; }) == m_windowDecorations.end())
|
||||
continue;
|
||||
wd->updateWindow(m_self.lock());
|
||||
}
|
||||
};
|
||||
|
||||
// Make a copy because updateWindow can remove decos. The built-in set fits inline,
|
||||
// while the fallback preserves support for arbitrary plugin decorations.
|
||||
constexpr size_t INLINE_DECOS = 4;
|
||||
std::array<IHyprWindowDecoration*, INLINE_DECOS> inlineDecos = {};
|
||||
if (m_windowDecorations.size() <= inlineDecos.size()) {
|
||||
std::ranges::transform(m_windowDecorations, inlineDecos.begin(), [](const auto& deco) { return deco.get(); });
|
||||
updateDecos(std::span{inlineDecos}.first(m_windowDecorations.size()));
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<IHyprWindowDecoration*> decos;
|
||||
// reserve to avoid reallocations
|
||||
decos.reserve(m_windowDecorations.size());
|
||||
|
||||
for (auto const& wd : m_windowDecorations) {
|
||||
decos.push_back(wd.get());
|
||||
}
|
||||
|
||||
for (auto const& wd : decos) {
|
||||
if (std::ranges::find_if(m_windowDecorations, [wd](const auto& other) { return other.get() == wd; }) == m_windowDecorations.end())
|
||||
continue;
|
||||
wd->updateWindow(m_self.lock());
|
||||
}
|
||||
std::ranges::transform(m_windowDecorations, std::back_inserter(decos), [](const auto& deco) { return deco.get(); });
|
||||
updateDecos(decos);
|
||||
}
|
||||
|
||||
void CWindow::addWindowDeco(UP<IHyprWindowDecoration> deco) {
|
||||
|
||||
@@ -41,7 +41,7 @@ CRegion CDamageRing::getBufferDamage(int age) {
|
||||
}
|
||||
|
||||
// don't return a ludicrous amount of rects
|
||||
if (damage.getRects().size() > 8)
|
||||
if (pixman_region32_n_rects(damage.pixman()) > 8)
|
||||
return damage.getExtents();
|
||||
|
||||
return damage;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "Seat.hpp"
|
||||
#include "../types/WLBuffer.hpp"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <ranges>
|
||||
#include "Subcompositor.hpp"
|
||||
#include "../Viewporter.hpp"
|
||||
@@ -351,9 +352,8 @@ void CWLSurfaceResource::resetRole() {
|
||||
m_role = makeShared<CDefaultSurfaceRole>();
|
||||
}
|
||||
|
||||
void CWLSurfaceResource::bfHelper(std::vector<SP<CWLSurfaceResource>> const& nodes, std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data) {
|
||||
void CWLSurfaceResource::bfHelper(std::span<const SP<CWLSurfaceResource>> nodes, std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data) {
|
||||
std::vector<SP<CWLSurfaceResource>> nodes2;
|
||||
nodes2.reserve(nodes.size() * 2);
|
||||
|
||||
// first, gather all nodes below
|
||||
for (auto const& n : nodes) {
|
||||
@@ -372,6 +372,9 @@ void CWLSurfaceResource::bfHelper(std::vector<SP<CWLSurfaceResource>> const& nod
|
||||
if (!surface)
|
||||
continue;
|
||||
|
||||
if (nodes2.empty())
|
||||
nodes2.reserve(nodes.size() * 2);
|
||||
|
||||
nodes2.emplace_back(surface);
|
||||
}
|
||||
}
|
||||
@@ -407,6 +410,9 @@ void CWLSurfaceResource::bfHelper(std::vector<SP<CWLSurfaceResource>> const& nod
|
||||
if (!surface)
|
||||
continue;
|
||||
|
||||
if (nodes2.empty())
|
||||
nodes2.reserve(nodes.size() * 2);
|
||||
|
||||
nodes2.emplace_back(surface);
|
||||
}
|
||||
}
|
||||
@@ -416,8 +422,7 @@ void CWLSurfaceResource::bfHelper(std::vector<SP<CWLSurfaceResource>> const& nod
|
||||
}
|
||||
|
||||
void CWLSurfaceResource::breadthfirst(std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data) {
|
||||
std::vector<SP<CWLSurfaceResource>> surfs;
|
||||
surfs.emplace_back(m_self.lock());
|
||||
const std::array surfs = {m_self.lock()};
|
||||
bfHelper(surfs, fn, data);
|
||||
}
|
||||
|
||||
@@ -710,7 +715,10 @@ void CWLSurfaceResource::updateCursorShm(CRegion damage) {
|
||||
|
||||
shmData.resize(bufLen);
|
||||
|
||||
if (const auto RECTS = damage.getRects(); RECTS.size() == 1 && RECTS.at(0).x2 == buf->size.x && RECTS.at(0).y2 == buf->size.y)
|
||||
int rectsNum = 0;
|
||||
const auto* rects = pixman_region32_rectangles(damage.pixman(), &rectsNum);
|
||||
|
||||
if (rectsNum == 1 && rects[0].x2 == buf->size.x && rects[0].y2 == buf->size.y)
|
||||
memcpy(shmData.data(), pixelData, bufLen);
|
||||
else {
|
||||
damage.forEachRect([&pixelData, &shmData](const auto& box) {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
- wl_callback
|
||||
*/
|
||||
|
||||
#include <span>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <cstdint>
|
||||
@@ -142,7 +143,7 @@ class CWLSurfaceResource {
|
||||
void releaseBuffers(bool onlyCurrent = true);
|
||||
void dropPendingBuffer();
|
||||
void dropCurrentBuffer();
|
||||
void bfHelper(std::vector<SP<CWLSurfaceResource>> const& nodes, std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
|
||||
void bfHelper(std::span<const SP<CWLSurfaceResource>> nodes, std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
|
||||
SP<CWLSurfaceResource> findFirstPreorderHelper(SP<CWLSurfaceResource> root, std::function<bool(SP<CWLSurfaceResource>)> fn);
|
||||
void updateCursorShm(CRegion damage = CBox{0, 0, INT16_MAX, INT16_MAX});
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ void IElementRenderer::drawRect(WP<CRectPassElement> element, const CRegion& dam
|
||||
}
|
||||
|
||||
void IElementRenderer::drawHints(WP<CRendererHintsPassElement> element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
const auto& m_data = element->m_data;
|
||||
if (m_data.renderModif.has_value())
|
||||
g_pHyprRenderer->m_renderData.renderModif = *m_data.renderModif;
|
||||
}
|
||||
@@ -216,7 +216,7 @@ void IElementRenderer::drawClear(WP<CClearPassElement> element, const CRegion& d
|
||||
}
|
||||
|
||||
void IElementRenderer::drawSurface(WP<CSurfacePassElement> element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
const auto& m_data = element->m_data;
|
||||
auto& m_renderData = g_pHyprRenderer->m_renderData;
|
||||
|
||||
Hyprutils::Utils::CScopeGuard x = {[]() {
|
||||
@@ -472,7 +472,7 @@ void IElementRenderer::drawTexMatte(WP<CTextureMatteElement> element, const CReg
|
||||
if (g_pHyprRenderer->m_renderData.damage.empty())
|
||||
return;
|
||||
|
||||
const auto m_data = element->m_data;
|
||||
const auto& m_data = element->m_data;
|
||||
if (m_data.disableTransformAndModify) {
|
||||
g_pHyprRenderer->pushMonitorTransformEnabled(true);
|
||||
g_pHyprRenderer->m_renderData.renderModif.enabled = false;
|
||||
|
||||
+24
-21
@@ -1492,33 +1492,36 @@ void CHyprOpenGLImpl::renderTextureInternal(SP<ITexture> tex, const CBox& box, c
|
||||
shader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix());
|
||||
shader->setUniformInt(SHADER_TEX, 0);
|
||||
GLCALL(glBindVertexArray(shader->getUniformLocation(SHADER_SHADER_VAO)));
|
||||
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, shader->getUniformLocation(SHADER_SHADER_VBO)));
|
||||
|
||||
// this tells GPU can keep reading the old block for previous draws while the CPU writes to a new one.
|
||||
// to avoid stalls if renderTextureInternal is called multiple times on same renderpass
|
||||
// at the cost of some temporar vram usage.
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), nullptr, GL_DYNAMIC_DRAW);
|
||||
const bool CUSTOMUV = data.allowCustomUV && data.primarySurfaceUVTopLeft != Vector2D(-1, -1);
|
||||
if (CUSTOMUV || shader->usesCustomUV()) {
|
||||
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, shader->getUniformLocation(SHADER_SHADER_VBO)));
|
||||
|
||||
auto verts = fullVerts;
|
||||
// Keep the old block available to previous draws while custom UVs update, or while restoring the defaults.
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), nullptr, GL_DYNAMIC_DRAW);
|
||||
|
||||
if (data.allowCustomUV && data.primarySurfaceUVTopLeft != Vector2D(-1, -1)) {
|
||||
const float u0 = data.primarySurfaceUVTopLeft.x;
|
||||
const float v0 = data.primarySurfaceUVTopLeft.y;
|
||||
const float u1 = data.primarySurfaceUVBottomRight.x;
|
||||
const float v1 = data.primarySurfaceUVBottomRight.y;
|
||||
auto verts = fullVerts;
|
||||
|
||||
verts[0].u = u0;
|
||||
verts[0].v = v0;
|
||||
verts[1].u = u0;
|
||||
verts[1].v = v1;
|
||||
verts[2].u = u1;
|
||||
verts[2].v = v0;
|
||||
verts[3].u = u1;
|
||||
verts[3].v = v1;
|
||||
if (CUSTOMUV) {
|
||||
const float u0 = data.primarySurfaceUVTopLeft.x;
|
||||
const float v0 = data.primarySurfaceUVTopLeft.y;
|
||||
const float u1 = data.primarySurfaceUVBottomRight.x;
|
||||
const float v1 = data.primarySurfaceUVBottomRight.y;
|
||||
|
||||
verts[0].u = u0;
|
||||
verts[0].v = v0;
|
||||
verts[1].u = u0;
|
||||
verts[1].v = v1;
|
||||
verts[2].u = u1;
|
||||
verts[2].v = v0;
|
||||
verts[3].u = u1;
|
||||
verts[3].v = v1;
|
||||
}
|
||||
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(verts), verts.data());
|
||||
shader->setUsesCustomUV(CUSTOMUV);
|
||||
}
|
||||
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(verts), verts.data());
|
||||
|
||||
if (!g_pHyprRenderer->m_renderData.clipBox.empty() || !data.clipRegion.empty()) {
|
||||
CRegion damageClip = g_pHyprRenderer->m_renderData.clipBox;
|
||||
|
||||
|
||||
+11
-2
@@ -7,7 +7,7 @@
|
||||
|
||||
using namespace Render::GL;
|
||||
|
||||
static bool compareFloat(auto a, auto b) {
|
||||
static bool compareFloat(const auto& a, const auto& b) {
|
||||
if (a.size() != b.size())
|
||||
return false;
|
||||
|
||||
@@ -243,6 +243,7 @@ void CShader::createVao() {
|
||||
|
||||
m_uniformLocations[SHADER_SHADER_VAO] = shaderVao;
|
||||
m_uniformLocations[SHADER_SHADER_VBO] = shaderVbo;
|
||||
m_usesCustomUV = false;
|
||||
|
||||
RASSERT(m_uniformLocations[SHADER_SHADER_VAO] >= 0, "SHADER_SHADER_VAO could not be created");
|
||||
RASSERT(m_uniformLocations[SHADER_SHADER_VBO] >= 0, "SHADER_SHADER_VBO_POS could not be created");
|
||||
@@ -365,7 +366,7 @@ void CShader::setUniformfv(eShaderUniform location, GLsizei count, const std::ve
|
||||
auto& cached = uniformStatus.at(location);
|
||||
|
||||
if (cached.index() != 0) {
|
||||
auto val = std::get<SUniformVData>(cached);
|
||||
const auto& val = std::get<SUniformVData>(cached);
|
||||
if (val.count == count && compareFloat(val.value, value))
|
||||
return;
|
||||
}
|
||||
@@ -427,3 +428,11 @@ int CShader::getInitialTime() const {
|
||||
void CShader::setInitialTime(int time) {
|
||||
m_initialTime = time;
|
||||
}
|
||||
|
||||
bool CShader::usesCustomUV() const {
|
||||
return m_usesCustomUV;
|
||||
}
|
||||
|
||||
void CShader::setUsesCustomUV(bool usesCustomUV) {
|
||||
m_usesCustomUV = usesCustomUV;
|
||||
}
|
||||
|
||||
@@ -107,10 +107,13 @@ class CShader {
|
||||
GLint getUniformLocation(eShaderUniform location) const;
|
||||
int getInitialTime() const;
|
||||
void setInitialTime(int time);
|
||||
bool usesCustomUV() const;
|
||||
void setUsesCustomUV(bool usesCustomUV);
|
||||
|
||||
private:
|
||||
GLuint m_program = 0;
|
||||
float m_initialTime = 0;
|
||||
GLuint m_program = 0;
|
||||
float m_initialTime = 0;
|
||||
bool m_usesCustomUV = false;
|
||||
std::array<GLint, SHADER_LAST> m_uniformLocations;
|
||||
|
||||
struct SUniformMatrix3Data {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
using namespace Render::GL;
|
||||
|
||||
void CGLElementRenderer::draw(WP<CBorderPassElement> element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
const auto& m_data = element->m_data;
|
||||
if (m_data.hasGrad2)
|
||||
g_pHyprOpenGL->renderBorder(
|
||||
m_data.box, m_data.grad1, m_data.grad2, m_data.lerp,
|
||||
@@ -81,7 +81,7 @@ void CGLElementRenderer::draw(WP<CPreBlurElement> element, const CRegion& damage
|
||||
};
|
||||
|
||||
void CGLElementRenderer::draw(WP<CRectPassElement> element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
const auto& m_data = element->m_data;
|
||||
|
||||
if (m_data.color.a == 1.F || !m_data.blur)
|
||||
g_pHyprOpenGL->renderRect(m_data.box, m_data.color, {.damage = &damage, .round = m_data.round, .roundingPower = m_data.roundingPower});
|
||||
@@ -91,17 +91,17 @@ void CGLElementRenderer::draw(WP<CRectPassElement> element, const CRegion& damag
|
||||
};
|
||||
|
||||
void CGLElementRenderer::draw(WP<CShadowPassElement> element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
const auto& m_data = element->m_data;
|
||||
m_data.deco->render(g_pHyprRenderer->m_renderData.pMonitor.lock(), m_data.a);
|
||||
};
|
||||
|
||||
void CGLElementRenderer::draw(WP<CInnerGlowPassElement> element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
const auto& m_data = element->m_data;
|
||||
m_data.deco->render(g_pHyprRenderer->m_renderData.pMonitor.lock(), m_data.a);
|
||||
};
|
||||
|
||||
void CGLElementRenderer::draw(WP<CTexPassElement> element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
const auto& m_data = element->m_data;
|
||||
|
||||
g_pHyprOpenGL->renderTexture( //
|
||||
m_data.tex, m_data.box,
|
||||
@@ -133,7 +133,7 @@ void CGLElementRenderer::draw(WP<CTexPassElement> element, const CRegion& damage
|
||||
};
|
||||
|
||||
void CGLElementRenderer::draw(WP<CTextureMatteElement> element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
const auto& m_data = element->m_data;
|
||||
|
||||
g_pHyprOpenGL->renderTextureMatte(m_data.tex, m_data.box, m_data.fb);
|
||||
};
|
||||
+29
-26
@@ -24,7 +24,7 @@ bool CRenderPass::single() const {
|
||||
}
|
||||
|
||||
void CRenderPass::add(UP<IPassElement>&& el) {
|
||||
m_passElements.emplace_back(makeUnique<SPassElementData>(CRegion{}, std::move(el)));
|
||||
m_passElements.emplace_back(SPassElementData{.element = std::move(el)});
|
||||
}
|
||||
|
||||
void CRenderPass::simplify(bool willBlur, const CRegion& liveBlurRegion) {
|
||||
@@ -36,29 +36,32 @@ void CRenderPass::simplify(bool willBlur, const CRegion& liveBlurRegion) {
|
||||
CRegion newDamage = m_damage.copy().intersect(CBox{{}, pMonitor->m_transformedSize});
|
||||
for (auto& el : m_passElements | std::views::reverse) {
|
||||
|
||||
if (newDamage.empty() && !el->element->undiscardable()) {
|
||||
el->discard = true;
|
||||
if (newDamage.empty() && !el.element->undiscardable()) {
|
||||
el.discard = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
el->elementDamage = newDamage;
|
||||
auto bb1 = el->element->boundingBox();
|
||||
if (!bb1 || newDamage.empty())
|
||||
auto bb1 = el.element->boundingBox();
|
||||
if (!bb1 || newDamage.empty()) {
|
||||
el.elementDamage = newDamage;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto bb = bb1->scale(pMonitor->m_scale);
|
||||
|
||||
// drop if empty
|
||||
if (CRegion copy = newDamage.copy(); copy.intersect(bb).empty()) {
|
||||
el->discard = true;
|
||||
el.discard = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto opaque = el->element->opaqueRegion();
|
||||
el.elementDamage = newDamage;
|
||||
|
||||
auto opaque = el.element->opaqueRegion();
|
||||
|
||||
if (!opaque.empty()) {
|
||||
// scale and rounding is very particular so we have to use CBoxes scale and round functions
|
||||
if (opaque.getRects().size() == 1)
|
||||
if (pixman_region32_n_rects(opaque.pixman()) == 1)
|
||||
opaque = opaque.getExtents().scale(pMonitor->m_scale).round();
|
||||
else {
|
||||
CRegion scaledRegion;
|
||||
@@ -85,10 +88,10 @@ void CRenderPass::simplify(bool willBlur, const CRegion& liveBlurRegion) {
|
||||
|
||||
if (*PDEBUGPASS) {
|
||||
for (auto& el2 : m_passElements) {
|
||||
if (!el2->element->needsLiveBlurCached)
|
||||
if (!el2.element->needsLiveBlurCached)
|
||||
continue;
|
||||
|
||||
const auto BB = el2->element->boundingBox();
|
||||
const auto BB = el2.element->boundingBox();
|
||||
RASSERT(BB, "No bounding box for an element with live blur is illegal");
|
||||
|
||||
m_totalLiveBlurRegion.add(BB->copy().scale(pMonitor->m_scale));
|
||||
@@ -108,20 +111,20 @@ CRegion CRenderPass::render(const CRegion& damage_) {
|
||||
bool willBlur = false, willDisableSimplification = false, willPrecomputeBlur = false;
|
||||
CRegion blurRegion;
|
||||
for (auto& el : m_passElements) {
|
||||
el->element->needsLiveBlurCached = el->element->needsLiveBlur();
|
||||
el->element->needsPrecomputeBlurCached = el->element->needsPrecomputeBlur();
|
||||
el.element->needsLiveBlurCached = el.element->needsLiveBlur();
|
||||
el.element->needsPrecomputeBlurCached = el.element->needsPrecomputeBlur();
|
||||
|
||||
if (el->element->needsLiveBlurCached) {
|
||||
if (el.element->needsLiveBlurCached) {
|
||||
willBlur = true;
|
||||
const auto BB = el->element->boundingBox();
|
||||
const auto BB = el.element->boundingBox();
|
||||
RASSERT(BB, "No bounding box for an element with live blur is illegal");
|
||||
blurRegion.add(*BB);
|
||||
}
|
||||
|
||||
if (el->element->needsPrecomputeBlurCached)
|
||||
if (el.element->needsPrecomputeBlurCached)
|
||||
willPrecomputeBlur = true;
|
||||
|
||||
if (el->element->disableSimplification())
|
||||
if (el.element->disableSimplification())
|
||||
willDisableSimplification = true;
|
||||
}
|
||||
|
||||
@@ -169,7 +172,7 @@ CRegion CRenderPass::render(const CRegion& damage_) {
|
||||
|
||||
if (g_pHyprRenderer->m_renderData.noSimplify || willDisableSimplification) {
|
||||
for (auto& el : m_passElements) {
|
||||
el->elementDamage = m_damage;
|
||||
el.elementDamage = m_damage;
|
||||
}
|
||||
} else
|
||||
simplify(willBlur, liveBlurRegion);
|
||||
@@ -181,13 +184,13 @@ CRegion CRenderPass::render(const CRegion& damage_) {
|
||||
return {};
|
||||
|
||||
for (auto& el : m_passElements) {
|
||||
if (el->discard) {
|
||||
el->element->discard();
|
||||
if (el.discard) {
|
||||
el.element->discard();
|
||||
continue;
|
||||
}
|
||||
|
||||
g_pHyprRenderer->m_renderData.damage = el->elementDamage;
|
||||
g_pHyprRenderer->draw(el->element, el->elementDamage);
|
||||
g_pHyprRenderer->m_renderData.damage = el.elementDamage;
|
||||
g_pHyprRenderer->draw(el.element, el.elementDamage);
|
||||
}
|
||||
|
||||
if (*PDEBUGPASS) {
|
||||
@@ -273,7 +276,7 @@ void CRenderPass::renderDebugData() {
|
||||
}
|
||||
}
|
||||
|
||||
const auto DISCARDED_ELEMENTS = std::ranges::count_if(m_passElements, [](const auto& e) { return e->discard; });
|
||||
const auto DISCARDED_ELEMENTS = std::ranges::count_if(m_passElements, [](const auto& e) { return e.discard; });
|
||||
auto tex = g_pHyprRenderer->renderText(std::format("occlusion layers: {}\npass elements: {} ({} discarded)\nviewport: {:X0}", m_occludedRegions.size(), m_passElements.size(),
|
||||
DISCARDED_ELEMENTS, pMonitor->m_pixelSize),
|
||||
Colors::WHITE, 12);
|
||||
@@ -290,8 +293,8 @@ void CRenderPass::renderDebugData() {
|
||||
auto yn = [](const bool val) -> const char* { return val ? "yes" : "no"; };
|
||||
auto tick = [](const bool val) -> const char* { return val ? "✔" : "✖"; };
|
||||
for (const auto& el : m_passElements | std::views::reverse) {
|
||||
passStructure += std::format("{} {} (bb: {} op: {}, pb: {}, lb: {})\n", tick(!el->discard), el->element->passName(), yn(el->element->boundingBox().has_value()),
|
||||
yn(!el->element->opaqueRegion().empty()), yn(el->element->needsPrecomputeBlurCached), yn(el->element->needsLiveBlurCached));
|
||||
passStructure += std::format("{} {} (bb: {} op: {}, pb: {}, lb: {})\n", tick(!el.discard), el.element->passName(), yn(el.element->boundingBox().has_value()),
|
||||
yn(!el.element->opaqueRegion().empty()), yn(el.element->needsPrecomputeBlurCached), yn(el.element->needsLiveBlurCached));
|
||||
}
|
||||
|
||||
if (!passStructure.empty())
|
||||
@@ -318,5 +321,5 @@ float CRenderPass::oneBlurRadius() {
|
||||
}
|
||||
|
||||
void CRenderPass::removeAllOfType(const std::string& type) {
|
||||
std::erase_if(m_passElements, [&type](const auto& e) { return e->element->passName() == type; });
|
||||
std::erase_if(m_passElements, [&type](const auto& e) { return e.element->passName() == type; });
|
||||
}
|
||||
|
||||
@@ -30,11 +30,11 @@ namespace Render {
|
||||
bool discard = false;
|
||||
};
|
||||
|
||||
std::vector<UP<SPassElementData>> m_passElements;
|
||||
std::vector<SPassElementData> m_passElements;
|
||||
|
||||
void simplify(bool willBlur, const CRegion& liveBlurRegion);
|
||||
float oneBlurRadius();
|
||||
void renderDebugData();
|
||||
void simplify(bool willBlur, const CRegion& liveBlurRegion);
|
||||
float oneBlurRadius();
|
||||
void renderDebugData();
|
||||
|
||||
struct {
|
||||
bool present = false;
|
||||
|
||||
Reference in New Issue
Block a user