Skip to content

Commit

Permalink
stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
vaxerski committed Dec 9, 2024
1 parent 5cf198b commit a7f6dd4
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 37 deletions.
30 changes: 6 additions & 24 deletions src/render/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1251,30 +1251,10 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor) {
}

// if we have no tracking or full tracking, invalidate the entire monitor
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || pMonitor->forceFullFrames > 0 || damageBlinkCleanup > 0) {
damage = {0, 0, (int)pMonitor->vecTransformedSize.x * 10, (int)pMonitor->vecTransformedSize.y * 10};
finalDamage = damage;
} else {
static auto PBLURENABLED = CConfigValue<Hyprlang::INT>("decoration:blur:enabled");

// if we use blur we need to expand the damage for proper blurring
// if framebuffer was not offloaded we're not doing introspection aka not blurring so this is redundant and dumb
if (*PBLURENABLED == 1 && g_pHyprOpenGL->m_bOffloadedFramebuffer) {
// TODO: can this be optimized?
static auto PBLURSIZE = CConfigValue<Hyprlang::INT>("decoration:blur:size");
static auto PBLURPASSES = CConfigValue<Hyprlang::INT>("decoration:blur:passes");
const auto BLURRADIUS =
*PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think.
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || pMonitor->forceFullFrames > 0 || damageBlinkCleanup > 0)
damage = {0, 0, (int)pMonitor->vecTransformedSize.x * 10, (int)pMonitor->vecTransformedSize.y * 10};

// now, prep the damage, get the extended damage region
damage.expand(BLURRADIUS); // expand for proper blurring

finalDamage = damage;

damage.expand(BLURRADIUS); // expand for proper blurring
} else
finalDamage = damage;
}
finalDamage = damage;

// update damage in renderdata as we modified it
g_pHyprOpenGL->setDamage(damage, finalDamage);
Expand Down Expand Up @@ -1346,6 +1326,8 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor) {

endRender();

finalDamage = g_pHyprOpenGL->m_RenderData.damage;

TRACY_GPU_COLLECT;

if (!pMonitor->mirrors.empty()) {
Expand Down Expand Up @@ -2560,7 +2542,7 @@ void CHyprRenderer::endRender() {

PMONITOR->commitSeq++;

m_sRenderPass.render(g_pHyprOpenGL->m_RenderData.damage);
g_pHyprOpenGL->m_RenderData.damage = m_sRenderPass.render(g_pHyprOpenGL->m_RenderData.damage);

auto cleanup = CScopeGuard([this]() {
if (m_pCurrentRenderbuffer)
Expand Down
76 changes: 72 additions & 4 deletions src/render/pass/Pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "../OpenGL.hpp"
#include <algorithm>
#include <ranges>
#include "../../config/ConfigValue.hpp"

bool CRenderPass::empty() const {
return false;
Expand All @@ -20,6 +21,22 @@ void CRenderPass::add(SP<IPassElement> el) {
}

void CRenderPass::simplify() {
// TODO: use precompute blur for instances where there is nothing in between

// if there is live blur, we need to NOT occlude any area where it will be influenced
// TODO: do this better. This should be layered, cuz we don't need to check infringement
// if the blur is ABOVE our thing.
CRegion liveBlurRegion;
for (auto& el : m_vPassElements) {
if (!el->element->needsLiveBlur())
continue;

const auto BB = el->element->boundingBox();
RASSERT(BB, "No bounding box for an element with live blur is illegal");

liveBlurRegion.add(*BB);
}

std::vector<SP<SPassElementData>> toRemove;
CRegion newDamage = damage.copy().intersect(CBox{{}, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize});
for (auto& el : m_vPassElements | std::views::reverse) {
Expand All @@ -40,10 +57,18 @@ void CRenderPass::simplify() {
continue;
}

const auto opaque = el->element->opaqueRegion();
auto opaque = el->element->opaqueRegion();

if (!opaque.empty())
if (!opaque.empty()) {
// if this intersects the liveBlur region, allow live blur to operate correctly.
// do not occlude a border near it.
if (auto infringement = opaque.copy().intersect(liveBlurRegion); !infringement.empty()) {
// eh, this is not the correct solution, but it will do...
// TODO: is this *easily* fixable?
opaque.subtract(infringement);
}
newDamage.subtract(opaque);
}
}

std::erase_if(m_vPassElements, [&toRemove](const auto& el) { return std::find(toRemove.begin(), toRemove.end(), el) != toRemove.end(); });
Expand All @@ -53,9 +78,36 @@ void CRenderPass::clear() {
m_vPassElements.clear();
}

void CRenderPass::render(const CRegion& damage_) {
CRegion CRenderPass::render(const CRegion& damage_) {
const auto WILLBLUR = std::ranges::any_of(m_vPassElements, [](const auto& el) { return el->element->needsLiveBlur(); });

damage = damage_.copy();

if (WILLBLUR) {
// combine blur regions into one that will be expanded
CRegion blurRegion;
for (auto& el : m_vPassElements) {
if (!el->element->needsLiveBlur())
continue;

const auto BB = el->element->boundingBox();
RASSERT(BB, "No bounding box for an element with live blur is illegal");

blurRegion.add(*BB);
}

blurRegion.intersect(damage);

blurRegion = expandRegionForBlur(blurRegion);

g_pHyprOpenGL->m_RenderData.finalDamage = blurRegion.copy().add(damage);

blurRegion = expandRegionForBlur(blurRegion);

damage = blurRegion.copy().add(damage);
} else
g_pHyprOpenGL->m_RenderData.finalDamage = damage;

if (std::ranges::any_of(m_vPassElements, [](const auto& el) { return el->element->disableSimplification(); })) {
for (auto& el : m_vPassElements) {
el->elementDamage = damage;
Expand All @@ -66,12 +118,28 @@ void CRenderPass::render(const CRegion& damage_) {
g_pHyprOpenGL->m_RenderData.pCurrentMonData->blurFBShouldRender = std::ranges::any_of(m_vPassElements, [](const auto& el) { return el->element->needsPrecomputeBlur(); });

if (m_vPassElements.empty())
return;
return {};

for (auto& el : m_vPassElements) {
g_pHyprOpenGL->m_RenderData.damage = el->elementDamage;
el->element->draw(el->elementDamage);
}

g_pHyprOpenGL->m_RenderData.damage = damage;
return damage;
}

float CRenderPass::oneBlurRadius() {
// TODO: is this exact range correct?
static auto PBLURSIZE = CConfigValue<Hyprlang::INT>("decoration:blur:size");
static auto PBLURPASSES = CConfigValue<Hyprlang::INT>("decoration:blur:passes");
return *PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think.
}

// If we use live blur we need to expand the damage for proper blurring.
// This function expands only ONCE, while we need to expand twice.
// Once for final damage
// Once more for rendering
CRegion CRenderPass::expandRegionForBlur(const CRegion& rg) {
return rg.copy().expand(oneBlurRadius());
}
14 changes: 8 additions & 6 deletions src/render/pass/Pass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ class CGradientValueData;

class CRenderPass {
public:
bool empty() const;
bool single() const;
bool needsIntrospection() const;
bool empty() const;
bool single() const;
bool needsIntrospection() const;

void add(SP<IPassElement> elem);
void clear();
void add(SP<IPassElement> elem);
void clear();

void render(const CRegion& damage_);
CRegion render(const CRegion& damage_);

private:
CRegion damage;
Expand All @@ -29,6 +29,8 @@ class CRenderPass {
SP<IPassElement> currentPassInfo = nullptr;

void simplify();
CRegion expandRegionForBlur(const CRegion& rg);
float oneBlurRadius();

friend class CHyprOpenGLImpl;
};
6 changes: 3 additions & 3 deletions src/render/pass/RectPassElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ CRectPassElement::CRectPassElement(const CRectPassElement::SRectData& data_) : d
}

void CRectPassElement::draw(const CRegion& damage) {
if (data.color.a == 1.F)
if (data.color.a == 1.F || !data.blur)
g_pHyprOpenGL->renderRectWithDamage(&data.box, data.color, damage, data.round);
else
g_pHyprOpenGL->renderRectWithBlur(&data.box, data.color, data.round, data.blurA, data.xray);
}

bool CRectPassElement::needsLiveBlur() {
return data.color.a < 1.F && !data.xray;
return data.color.a < 1.F && !data.xray && data.blur;
}

bool CRectPassElement::needsPrecomputeBlur() {
return data.color.a < 1.F && data.xray;
return data.color.a < 1.F && data.xray && data.blur;
}

std::optional<CBox> CRectPassElement::boundingBox() {
Expand Down

0 comments on commit a7f6dd4

Please sign in to comment.