renderer: Add supercircular window corners (#8943)

renderer: Add supercircular shadows and borders

config: Add rounding_power to default and example configs

rule: add `roundingpower` window rule
This commit is contained in:
Pollux 2025-01-05 12:38:49 -06:00 committed by GitHub
parent b0bae15499
commit a5c14370c1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 228 additions and 173 deletions

View file

@ -81,6 +81,7 @@ general {
# https://wiki.hyprland.org/Configuring/Variables/#decoration # https://wiki.hyprland.org/Configuring/Variables/#decoration
decoration { decoration {
rounding = 10 rounding = 10
rounding_power = 2
# Change transparency of focused and unfocused windows # Change transparency of focused and unfocused windows
active_opacity = 1.0 active_opacity = 1.0

View file

@ -139,6 +139,12 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.type = CONFIG_OPTION_INT, .type = CONFIG_OPTION_INT,
.data = SConfigOptionDescription::SRangeData{0, 0, 20}, .data = SConfigOptionDescription::SRangeData{0, 0, 20},
}, },
SConfigOptionDescription{
.value = "decoration:rounding_power",
.description = "rouding power of corners (2 is a circle)",
.type = CONFIG_OPTION_FLOAT,
.data = SConfigOptionDescription::SFloatData{2, 2, 10},
},
SConfigOptionDescription{ SConfigOptionDescription{
.value = "decoration:active_opacity", .value = "decoration:active_opacity",
.description = "opacity of active windows. [0.0 - 1.0]", .description = "opacity of active windows. [0.0 - 1.0]",

View file

@ -427,6 +427,7 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("debug:colored_stdout_logs", Hyprlang::INT{1}); m_pConfig->addConfigValue("debug:colored_stdout_logs", Hyprlang::INT{1});
m_pConfig->addConfigValue("decoration:rounding", Hyprlang::INT{0}); m_pConfig->addConfigValue("decoration:rounding", Hyprlang::INT{0});
m_pConfig->addConfigValue("decoration:rounding_power", {2.F});
m_pConfig->addConfigValue("decoration:blur:enabled", Hyprlang::INT{1}); m_pConfig->addConfigValue("decoration:blur:enabled", Hyprlang::INT{1});
m_pConfig->addConfigValue("decoration:blur:size", Hyprlang::INT{8}); m_pConfig->addConfigValue("decoration:blur:size", Hyprlang::INT{8});
m_pConfig->addConfigValue("decoration:blur:passes", Hyprlang::INT{1}); m_pConfig->addConfigValue("decoration:blur:passes", Hyprlang::INT{1});

View file

@ -259,6 +259,7 @@ class CConfigManager {
}; };
std::unordered_map<std::string, std::function<CWindowOverridableVar<float>*(PHLWINDOW)>> mfWindowProperties = { std::unordered_map<std::string, std::function<CWindowOverridableVar<float>*(PHLWINDOW)>> mfWindowProperties = {
{"roundingpower", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.roundingPower; }},
{"scrollmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollMouse; }}, {"scrollmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollMouse; }},
{"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollTouchpad; }}}; {"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollTouchpad; }}};

View file

@ -94,6 +94,7 @@ general {
# https://wiki.hyprland.org/Configuring/Variables/#decoration # https://wiki.hyprland.org/Configuring/Variables/#decoration
decoration { decoration {
rounding = 10 rounding = 10
rounding_power = 2
# Change transparency of focused and unfocused windows # Change transparency of focused and unfocused windows
active_opacity = 1.0 active_opacity = 1.0

View file

@ -825,6 +825,7 @@ void CWindow::updateDynamicRules() {
// otherwise behaviour is undefined // otherwise behaviour is undefined
bool CWindow::isInCurvedCorner(double x, double y) { bool CWindow::isInCurvedCorner(double x, double y) {
const int ROUNDING = rounding(); const int ROUNDING = rounding();
const int ROUNDINGPOWER = roundingPower();
if (getRealBorderSize() >= ROUNDING) if (getRealBorderSize() >= ROUNDING)
return false; return false;
@ -835,16 +836,16 @@ bool CWindow::isInCurvedCorner(double x, double y) {
double y1 = m_vRealPosition.value().y + m_vRealSize.value().y - ROUNDING; double y1 = m_vRealPosition.value().y + m_vRealSize.value().y - ROUNDING;
if (x < x0 && y < y0) { if (x < x0 && y < y0) {
return Vector2D{x0, y0}.distance(Vector2D{x, y}) > (double)ROUNDING; return std::pow(x0 - x, ROUNDINGPOWER) + std::pow(y0 - y, ROUNDINGPOWER) > std::pow((double)ROUNDING, ROUNDINGPOWER);
} }
if (x > x1 && y < y0) { if (x > x1 && y < y0) {
return Vector2D{x1, y0}.distance(Vector2D{x, y}) > (double)ROUNDING; return std::pow(x - x1, ROUNDINGPOWER) + std::pow(y0 - y, ROUNDINGPOWER) > std::pow((double)ROUNDING, ROUNDINGPOWER);
} }
if (x < x0 && y > y1) { if (x < x0 && y > y1) {
return Vector2D{x0, y1}.distance(Vector2D{x, y}) > (double)ROUNDING; return std::pow(x0 - x, ROUNDINGPOWER) + std::pow(y - y1, ROUNDINGPOWER) > std::pow((double)ROUNDING, ROUNDINGPOWER);
} }
if (x > x1 && y > y1) { if (x > x1 && y > y1) {
return Vector2D{x1, y1}.distance(Vector2D{x, y}) > (double)ROUNDING; return std::pow(x - x1, ROUNDINGPOWER) + std::pow(y - y1, ROUNDINGPOWER) > std::pow((double)ROUNDING, ROUNDINGPOWER);
} }
return false; return false;
@ -1165,12 +1166,20 @@ bool CWindow::opaque() {
float CWindow::rounding() { float CWindow::rounding() {
static auto PROUNDING = CConfigValue<Hyprlang::INT>("decoration:rounding"); static auto PROUNDING = CConfigValue<Hyprlang::INT>("decoration:rounding");
static auto PROUNDINGPOWER = CConfigValue<Hyprlang::FLOAT>("decoration:rounding_power");
float rounding = m_sWindowData.rounding.valueOr(*PROUNDING); float roundingPower = m_sWindowData.roundingPower.valueOr(*PROUNDINGPOWER);
float rounding = m_sWindowData.rounding.valueOr(*PROUNDING) * (roundingPower / 2.0); /* Make perceived roundness consistent. */
return m_sWindowData.noRounding.valueOrDefault() ? 0 : rounding; return m_sWindowData.noRounding.valueOrDefault() ? 0 : rounding;
} }
float CWindow::roundingPower() {
static auto PROUNDINGPOWER = CConfigValue<Hyprlang::FLOAT>("decoration:rounding_power");
return m_sWindowData.roundingPower.valueOr(*PROUNDINGPOWER);
}
void CWindow::updateWindowData() { void CWindow::updateWindowData() {
const auto PWORKSPACE = m_pWorkspace; const auto PWORKSPACE = m_pWorkspace;
const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{}; const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{};

View file

@ -183,6 +183,7 @@ struct SWindowData {
CWindowOverridableVar<bool> renderUnfocused = false; CWindowOverridableVar<bool> renderUnfocused = false;
CWindowOverridableVar<int> rounding; CWindowOverridableVar<int> rounding;
CWindowOverridableVar<float> roundingPower;
CWindowOverridableVar<int> borderSize; CWindowOverridableVar<int> borderSize;
CWindowOverridableVar<float> scrollMouse; CWindowOverridableVar<float> scrollMouse;
@ -414,6 +415,7 @@ class CWindow {
Vector2D middle(); Vector2D middle();
bool opaque(); bool opaque();
float rounding(); float rounding();
float roundingPower();
bool canBeTorn(); bool canBeTorn();
void setSuspended(bool suspend); void setSuspended(bool suspend);
bool visibleOnMonitor(PHLMONITOR pMonitor); bool visibleOnMonitor(PHLMONITOR pMonitor);

View file

@ -9,7 +9,7 @@ static const auto RULES = std::unordered_set<std::string>{
}; };
static const auto RULES_PREFIX = std::unordered_set<std::string>{ static const auto RULES_PREFIX = std::unordered_set<std::string>{
"animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", "move", "opacity", "animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", "move", "opacity",
"plugin:", "prop", "pseudo", "rounding", "scrollmouse", "scrolltouchpad", "size", "suppressevent", "tag", "workspace", "xray", "plugin:", "prop", "pseudo", "rounding", "roundingpower", "scrollmouse", "scrolltouchpad", "size", "suppressevent", "tag", "workspace", "xray",
}; };
CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool isV2, bool isExecRule) : szValue(value), szRule(rule), v2(isV2), execRule(isExecRule) { CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool isV2, bool isExecRule) : szValue(value), szRule(rule), v2(isV2), execRule(isExecRule) {

View file

@ -979,6 +979,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shQUAD.topLeft = glGetUniformLocation(prog, "topLeft"); m_RenderData.pCurrentMonData->m_shQUAD.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shQUAD.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shQUAD.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shQUAD.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shQUAD.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shQUAD.roundingPower = glGetUniformLocation(prog, "roundingPower");
prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBA); prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBA);
m_RenderData.pCurrentMonData->m_shRGBA.program = prog; m_RenderData.pCurrentMonData->m_shRGBA.program = prog;
@ -995,6 +996,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shRGBA.topLeft = glGetUniformLocation(prog, "topLeft"); m_RenderData.pCurrentMonData->m_shRGBA.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shRGBA.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shRGBA.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shRGBA.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shRGBA.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shRGBA.roundingPower = glGetUniformLocation(prog, "roundingPower");
m_RenderData.pCurrentMonData->m_shRGBA.applyTint = glGetUniformLocation(prog, "applyTint"); m_RenderData.pCurrentMonData->m_shRGBA.applyTint = glGetUniformLocation(prog, "applyTint");
m_RenderData.pCurrentMonData->m_shRGBA.tint = glGetUniformLocation(prog, "tint"); m_RenderData.pCurrentMonData->m_shRGBA.tint = glGetUniformLocation(prog, "tint");
m_RenderData.pCurrentMonData->m_shRGBA.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte"); m_RenderData.pCurrentMonData->m_shRGBA.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte");
@ -1037,6 +1039,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shRGBX.topLeft = glGetUniformLocation(prog, "topLeft"); m_RenderData.pCurrentMonData->m_shRGBX.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shRGBX.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shRGBX.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shRGBX.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shRGBX.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shRGBX.roundingPower = glGetUniformLocation(prog, "roundingPower");
m_RenderData.pCurrentMonData->m_shRGBX.applyTint = glGetUniformLocation(prog, "applyTint"); m_RenderData.pCurrentMonData->m_shRGBX.applyTint = glGetUniformLocation(prog, "applyTint");
m_RenderData.pCurrentMonData->m_shRGBX.tint = glGetUniformLocation(prog, "tint"); m_RenderData.pCurrentMonData->m_shRGBX.tint = glGetUniformLocation(prog, "tint");
@ -1053,6 +1056,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shEXT.topLeft = glGetUniformLocation(prog, "topLeft"); m_RenderData.pCurrentMonData->m_shEXT.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shEXT.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shEXT.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shEXT.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shEXT.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shEXT.roundingPower = glGetUniformLocation(prog, "roundingPower");
m_RenderData.pCurrentMonData->m_shEXT.applyTint = glGetUniformLocation(prog, "applyTint"); m_RenderData.pCurrentMonData->m_shEXT.applyTint = glGetUniformLocation(prog, "applyTint");
m_RenderData.pCurrentMonData->m_shEXT.tint = glGetUniformLocation(prog, "tint"); m_RenderData.pCurrentMonData->m_shEXT.tint = glGetUniformLocation(prog, "tint");
@ -1106,6 +1110,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight"); m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_RenderData.pCurrentMonData->m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shSHADOW.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shSHADOW.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shSHADOW.roundingPower = glGetUniformLocation(prog, "roundingPower");
m_RenderData.pCurrentMonData->m_shSHADOW.range = glGetUniformLocation(prog, "range"); m_RenderData.pCurrentMonData->m_shSHADOW.range = glGetUniformLocation(prog, "range");
m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower"); m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower");
m_RenderData.pCurrentMonData->m_shSHADOW.color = glGetUniformLocation(prog, "color"); m_RenderData.pCurrentMonData->m_shSHADOW.color = glGetUniformLocation(prog, "color");
@ -1122,6 +1127,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed = glGetUniformLocation(prog, "fullSizeUntransformed"); m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed = glGetUniformLocation(prog, "fullSizeUntransformed");
m_RenderData.pCurrentMonData->m_shBORDER1.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shBORDER1.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter = glGetUniformLocation(prog, "radiusOuter"); m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter = glGetUniformLocation(prog, "radiusOuter");
m_RenderData.pCurrentMonData->m_shBORDER1.roundingPower = glGetUniformLocation(prog, "roundingPower");
m_RenderData.pCurrentMonData->m_shBORDER1.gradient = glGetUniformLocation(prog, "gradient"); m_RenderData.pCurrentMonData->m_shBORDER1.gradient = glGetUniformLocation(prog, "gradient");
m_RenderData.pCurrentMonData->m_shBORDER1.gradient2 = glGetUniformLocation(prog, "gradient2"); m_RenderData.pCurrentMonData->m_shBORDER1.gradient2 = glGetUniformLocation(prog, "gradient2");
m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength = glGetUniformLocation(prog, "gradientLength"); m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength = glGetUniformLocation(prog, "gradientLength");
@ -1244,12 +1250,12 @@ void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h
scissor(&box, transform); scissor(&box, transform);
} }
void CHyprOpenGLImpl::renderRect(CBox* box, const CHyprColor& col, int round) { void CHyprOpenGLImpl::renderRect(CBox* box, const CHyprColor& col, int round, float roundingPower) {
if (!m_RenderData.damage.empty()) if (!m_RenderData.damage.empty())
renderRectWithDamage(box, col, m_RenderData.damage, round); renderRectWithDamage(box, col, m_RenderData.damage, round, roundingPower);
} }
void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int round, float blurA, bool xray) { void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int round, float roundingPower, float blurA, bool xray) {
if (m_RenderData.damage.empty()) if (m_RenderData.damage.empty())
return; return;
@ -1271,7 +1277,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int r
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
renderRect(box, CHyprColor(0, 0, 0, 0), round); renderRect(box, CHyprColor(0, 0, 0, 0), round, roundingPower);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 1, 0xFF); glStencilFunc(GL_EQUAL, 1, 0xFF);
@ -1282,7 +1288,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int r
m_bEndFrame = true; // fix transformed m_bEndFrame = true; // fix transformed
const auto SAVEDRENDERMODIF = m_RenderData.renderModif; const auto SAVEDRENDERMODIF = m_RenderData.renderModif;
m_RenderData.renderModif = {}; // fix shit m_RenderData.renderModif = {}; // fix shit
renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, blurA, damage, 0, false, false, false); renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, blurA, damage, 0, 2.0f, false, false, false);
m_bEndFrame = false; m_bEndFrame = false;
m_RenderData.renderModif = SAVEDRENDERMODIF; m_RenderData.renderModif = SAVEDRENDERMODIF;
@ -1293,10 +1299,10 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int r
glStencilFunc(GL_ALWAYS, 1, 0xFF); glStencilFunc(GL_ALWAYS, 1, 0xFF);
scissor((CBox*)nullptr); scissor((CBox*)nullptr);
renderRectWithDamage(box, col, m_RenderData.damage, round); renderRectWithDamage(box, col, m_RenderData.damage, round, roundingPower);
} }
void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, const CRegion& damage, int round) { void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, const CRegion& damage, int round, float roundingPower) {
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
@ -1334,6 +1340,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, con
glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y); glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y); glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_RenderData.pCurrentMonData->m_shQUAD.radius, round); glUniform1f(m_RenderData.pCurrentMonData->m_shQUAD.radius, round);
glUniform1f(m_RenderData.pCurrentMonData->m_shQUAD.roundingPower, roundingPower);
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@ -1361,25 +1368,25 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, con
scissor((CBox*)nullptr); scissor((CBox*)nullptr);
} }
void CHyprOpenGLImpl::renderTexture(SP<CTexture> tex, CBox* pBox, float alpha, int round, bool discardActive, bool allowCustomUV) { void CHyprOpenGLImpl::renderTexture(SP<CTexture> tex, CBox* pBox, float alpha, int round, float roundingPower, bool discardActive, bool allowCustomUV) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.damage, round, discardActive, false, allowCustomUV, true); renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.damage, round, roundingPower, discardActive, false, allowCustomUV, true);
scissor((CBox*)nullptr); scissor((CBox*)nullptr);
} }
void CHyprOpenGLImpl::renderTextureWithDamage(SP<CTexture> tex, CBox* pBox, const CRegion& damage, float alpha, int round, bool discardActive, bool allowCustomUV, void CHyprOpenGLImpl::renderTextureWithDamage(SP<CTexture> tex, CBox* pBox, const CRegion& damage, float alpha, int round, float roundingPower, bool discardActive,
SP<CSyncTimeline> waitTimeline, uint64_t waitPoint) { bool allowCustomUV, SP<CSyncTimeline> waitTimeline, uint64_t waitPoint) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
renderTextureInternalWithDamage(tex, pBox, alpha, damage, round, discardActive, false, allowCustomUV, true, waitTimeline, waitPoint); renderTextureInternalWithDamage(tex, pBox, alpha, damage, round, roundingPower, discardActive, false, allowCustomUV, true, waitTimeline, waitPoint);
scissor((CBox*)nullptr); scissor((CBox*)nullptr);
} }
void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pBox, float alpha, const CRegion& damage, int round, bool discardActive, bool noAA, void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pBox, float alpha, const CRegion& damage, int round, float roundingPower, bool discardActive,
bool allowCustomUV, bool allowDim, SP<CSyncTimeline> waitTimeline, uint64_t waitPoint) { bool noAA, bool allowCustomUV, bool allowDim, SP<CSyncTimeline> waitTimeline, uint64_t waitPoint) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
RASSERT((tex->m_iTexID > 0), "Attempted to draw nullptr texture!"); RASSERT((tex->m_iTexID > 0), "Attempted to draw nullptr texture!");
@ -1506,6 +1513,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pB
glUniform2f(shader->topLeft, TOPLEFT.x, TOPLEFT.y); glUniform2f(shader->topLeft, TOPLEFT.x, TOPLEFT.y);
glUniform2f(shader->fullSize, FULLSIZE.x, FULLSIZE.y); glUniform2f(shader->fullSize, FULLSIZE.x, FULLSIZE.y);
glUniform1f(shader->radius, round); glUniform1f(shader->radius, round);
glUniform1f(shader->roundingPower, roundingPower);
if (allowDim && m_RenderData.currentWindow) { if (allowDim && m_RenderData.currentWindow) {
glUniform1i(shader->applyTint, 1); glUniform1i(shader->applyTint, 1);
@ -1997,7 +2005,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() {
clear(CHyprColor(0, 0, 0, 0)); clear(CHyprColor(0, 0, 0, 0));
m_bEndFrame = true; // fix transformed m_bEndFrame = true; // fix transformed
renderTextureInternalWithDamage(POUTFB->getTexture(), &wholeMonitor, 1, fakeDamage, 0, false, true, false); renderTextureInternalWithDamage(POUTFB->getTexture(), &wholeMonitor, 1, fakeDamage, 0, 2.0f, false, true, false);
m_bEndFrame = false; m_bEndFrame = false;
m_RenderData.currentFB->bind(); m_RenderData.currentFB->bind();
@ -2045,8 +2053,8 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWin
return false; return false;
} }
void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float a, SP<CWLSurfaceResource> pSurface, int round, bool blockBlurOptimization, float blurA, void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float a, SP<CWLSurfaceResource> pSurface, int round, float roundingPower, bool blockBlurOptimization,
float overallA) { float blurA, float overallA) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!");
static auto PNOBLUROVERSIZED = CConfigValue<Hyprlang::INT>("decoration:no_blur_on_oversized"); static auto PNOBLUROVERSIZED = CConfigValue<Hyprlang::INT>("decoration:no_blur_on_oversized");
@ -2063,7 +2071,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
m_RenderData.renderModif.applyToRegion(texDamage); m_RenderData.renderModif.applyToRegion(texDamage);
if (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) { if (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) {
renderTexture(tex, pBox, a, round, false, true); renderTexture(tex, pBox, a, round, roundingPower, false, true);
return; return;
} }
@ -2076,7 +2084,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
inverseOpaque.invert(&surfbox).intersect(0, 0, pSurface->current.size.x * pSurface->current.scale, pSurface->current.size.y * pSurface->current.scale); inverseOpaque.invert(&surfbox).intersect(0, 0, pSurface->current.size.x * pSurface->current.scale, pSurface->current.size.y * pSurface->current.scale);
if (inverseOpaque.empty()) { if (inverseOpaque.empty()) {
renderTexture(tex, pBox, a, round, false, true); renderTexture(tex, pBox, a, round, roundingPower, false, true);
return; return;
} }
} else { } else {
@ -2112,9 +2120,9 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
if (USENEWOPTIMIZE && !(m_RenderData.discardMode & DISCARD_ALPHA)) if (USENEWOPTIMIZE && !(m_RenderData.discardMode & DISCARD_ALPHA))
renderRect(pBox, CHyprColor(0, 0, 0, 0), round); renderRect(pBox, CHyprColor(0, 0, 0, 0), round, roundingPower);
else else
renderTexture(tex, pBox, a, round, true, true); // discard opaque renderTexture(tex, pBox, a, round, roundingPower, true, true); // discard opaque
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 1, 0xFF); glStencilFunc(GL_EQUAL, 1, 0xFF);
@ -2127,7 +2135,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
setMonitorTransformEnabled(true); setMonitorTransformEnabled(true);
if (!USENEWOPTIMIZE) if (!USENEWOPTIMIZE)
setRenderModifEnabled(false); setRenderModifEnabled(false);
renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, (*PBLURIGNOREOPACITY ? blurA : a * blurA) * overallA, texDamage, 0, false, false, false); renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, (*PBLURIGNOREOPACITY ? blurA : a * blurA) * overallA, texDamage, 0, 2.0f, false, false, false);
if (!USENEWOPTIMIZE) if (!USENEWOPTIMIZE)
setRenderModifEnabled(true); setRenderModifEnabled(true);
setMonitorTransformEnabled(false); setMonitorTransformEnabled(false);
@ -2138,14 +2146,14 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
// draw window // draw window
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
renderTextureInternalWithDamage(tex, pBox, a * overallA, texDamage, round, false, false, true, true); renderTextureInternalWithDamage(tex, pBox, a * overallA, texDamage, round, roundingPower, false, false, true, true);
glStencilMask(0xFF); glStencilMask(0xFF);
glStencilFunc(GL_ALWAYS, 1, 0xFF); glStencilFunc(GL_ALWAYS, 1, 0xFF);
scissor((CBox*)nullptr); scissor((CBox*)nullptr);
} }
void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, int round, int borderSize, float a, int outerRound) { void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, int round, float roundingPower, int borderSize, float a, int outerRound) {
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
@ -2207,6 +2215,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height); glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.roundingPower, roundingPower);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize);
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@ -2238,7 +2247,8 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in
blend(BLEND); blend(BLEND);
} }
void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, const CGradientValueData& grad2, float lerp, int round, int borderSize, float a, int outerRound) { void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, const CGradientValueData& grad2, float lerp, int round, float roundingPower, int borderSize, float a,
int outerRound) {
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
@ -2304,6 +2314,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, c
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height); glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.roundingPower, roundingPower);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize);
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@ -2335,7 +2346,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, c
blend(BLEND); blend(BLEND);
} }
void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const CHyprColor& color, float a) { void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, float roundingPower, int range, const CHyprColor& color, float a) {
RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!");
RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!"); RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!");
RASSERT(m_RenderData.currentWindow, "Tried to render shadow without a window!"); RASSERT(m_RenderData.currentWindow, "Tried to render shadow without a window!");
@ -2381,6 +2392,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const
glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y); glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y); glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.radius, range + round); glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.radius, range + round);
glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.roundingPower, roundingPower);
glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.range, range); glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.range, range);
glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower, SHADOWPOWER); glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower, SHADOWPOWER);
@ -2421,7 +2433,7 @@ void CHyprOpenGLImpl::saveBufferForMirror(CBox* box) {
blend(false); blend(false);
renderTexture(m_RenderData.currentFB->getTexture(), box, 1.f, 0, false, false); renderTexture(m_RenderData.currentFB->getTexture(), box, 1.f, 0, 2.0f, false, false);
blend(true); blend(true);

View file

@ -170,17 +170,18 @@ class CHyprOpenGLImpl {
void beginSimple(PHLMONITOR, const CRegion& damage, SP<CRenderbuffer> rb = nullptr, CFramebuffer* fb = nullptr); void beginSimple(PHLMONITOR, const CRegion& damage, SP<CRenderbuffer> rb = nullptr, CFramebuffer* fb = nullptr);
void end(); void end();
void renderRect(CBox*, const CHyprColor&, int round = 0); void renderRect(CBox*, const CHyprColor&, int round = 0, float roundingPower = 2.0f);
void renderRectWithBlur(CBox*, const CHyprColor&, int round = 0, float blurA = 1.f, bool xray = false); void renderRectWithBlur(CBox*, const CHyprColor&, int round = 0, float roundingPower = 2.0f, float blurA = 1.f, bool xray = false);
void renderRectWithDamage(CBox*, const CHyprColor&, const CRegion& damage, int round = 0); void renderRectWithDamage(CBox*, const CHyprColor&, const CRegion& damage, int round = 0, float roundingPower = 2.0f);
void renderTexture(SP<CTexture>, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); void renderTexture(SP<CTexture>, CBox*, float a, int round = 0, float roundingPower = 2.0f, bool discardActive = false, bool allowCustomUV = false);
void renderTextureWithDamage(SP<CTexture>, CBox*, const CRegion& damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false, void renderTextureWithDamage(SP<CTexture>, CBox*, const CRegion& damage, float a, int round = 0, float roundingPower = 2.0f, bool discardActive = false,
SP<CSyncTimeline> waitTimeline = nullptr, uint64_t waitPoint = 0); bool allowCustomUV = false, SP<CSyncTimeline> waitTimeline = nullptr, uint64_t waitPoint = 0);
void renderTextureWithBlur(SP<CTexture>, CBox*, float a, SP<CWLSurfaceResource> pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f, void renderTextureWithBlur(SP<CTexture>, CBox*, float a, SP<CWLSurfaceResource> pSurface, int round = 0, float roundingPower = 2.0f, bool blockBlurOptimization = false,
float overallA = 1.f); float blurA = 1.f, float overallA = 1.f);
void renderRoundedShadow(CBox*, int round, int range, const CHyprColor& color, float a = 1.0); void renderRoundedShadow(CBox*, int round, float roundingPower, int range, const CHyprColor& color, float a = 1.0);
void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); void renderBorder(CBox*, const CGradientValueData&, int round, float roundingPower, int borderSize, float a = 1.0, int outerRound = -1 /* use round */);
void renderBorder(CBox*, const CGradientValueData&, const CGradientValueData&, float lerp, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); void renderBorder(CBox*, const CGradientValueData&, const CGradientValueData&, float lerp, int round, float roundingPower, int borderSize, float a = 1.0,
int outerRound = -1 /* use round */);
void renderTextureMatte(SP<CTexture> tex, CBox* pBox, CFramebuffer& matte); void renderTextureMatte(SP<CTexture> tex, CBox* pBox, CFramebuffer& matte);
void setMonitorTransformEnabled(bool enabled); void setMonitorTransformEnabled(bool enabled);
@ -311,8 +312,8 @@ class CHyprOpenGLImpl {
// returns the out FB, can be either Mirror or MirrorSwap // returns the out FB, can be either Mirror or MirrorSwap
CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage); CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage);
void renderTextureInternalWithDamage(SP<CTexture>, CBox* pBox, float a, const CRegion& damage, int round = 0, bool discardOpaque = false, bool noAA = false, void renderTextureInternalWithDamage(SP<CTexture>, CBox* pBox, float a, const CRegion& damage, int round = 0, float roundingPower = 2.0f, bool discardOpaque = false,
bool allowCustomUV = false, bool allowDim = false, SP<CSyncTimeline> = nullptr, uint64_t waitPoint = 0); bool noAA = false, bool allowCustomUV = false, bool allowDim = false, SP<CSyncTimeline> = nullptr, uint64_t waitPoint = 0);
void renderTexturePrimitive(SP<CTexture> tex, CBox* pBox); void renderTexturePrimitive(SP<CTexture> tex, CBox* pBox);
void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size); void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size);

View file

@ -463,6 +463,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe
renderdata.alpha = pWindow->m_fActiveInactiveAlpha.value(); renderdata.alpha = pWindow->m_fActiveInactiveAlpha.value();
renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && !pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN); renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && !pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN);
renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale; renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale;
renderdata.roundingPower = ignoreAllGeometry || renderdata.dontRound ? 2.0f : pWindow->roundingPower();
renderdata.blur = !ignoreAllGeometry && *PBLUR && !DONT_BLUR; renderdata.blur = !ignoreAllGeometry && *PBLUR && !DONT_BLUR;
renderdata.pWindow = pWindow; renderdata.pWindow = pWindow;

View file

@ -26,6 +26,7 @@ class CShader {
GLint fullSizeUntransformed = -1; GLint fullSizeUntransformed = -1;
GLint radius = -1; GLint radius = -1;
GLint radiusOuter = -1; GLint radiusOuter = -1;
GLfloat roundingPower = -1;
GLint thick = -1; GLint thick = -1;

View file

@ -69,11 +69,13 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) {
int borderSize = m_pWindow->getRealBorderSize(); int borderSize = m_pWindow->getRealBorderSize();
const auto ROUNDING = m_pWindow->rounding() * pMonitor->scale; const auto ROUNDING = m_pWindow->rounding() * pMonitor->scale;
const auto ROUNDINGPOWER = m_pWindow->roundingPower();
CBorderPassElement::SBorderData data; CBorderPassElement::SBorderData data;
data.box = windowBox; data.box = windowBox;
data.grad1 = grad; data.grad1 = grad;
data.round = ROUNDING; data.round = ROUNDING;
data.roundingPower = ROUNDINGPOWER;
data.a = a; data.a = a;
data.borderSize = borderSize; data.borderSize = borderSize;

View file

@ -55,6 +55,7 @@ void CHyprDropShadowDecoration::damageEntire() {
static auto PSHADOWIGNOREWINDOW = CConfigValue<Hyprlang::INT>("decoration:shadow:ignore_window"); static auto PSHADOWIGNOREWINDOW = CConfigValue<Hyprlang::INT>("decoration:shadow:ignore_window");
const auto ROUNDING = PWINDOW->rounding(); const auto ROUNDING = PWINDOW->rounding();
const auto ROUNDINGPOWER = PWINDOW->roundingPower();
const auto ROUNDINGSIZE = ROUNDING - M_SQRT1_2 * ROUNDING + 1; const auto ROUNDINGSIZE = ROUNDING - M_SQRT1_2 * ROUNDING + 1;
CRegion shadowRegion(shadowBox); CRegion shadowRegion(shadowBox);
@ -119,6 +120,7 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
return; // disabled return; // disabled
const auto ROUNDINGBASE = PWINDOW->rounding(); const auto ROUNDINGBASE = PWINDOW->rounding();
const auto ROUNDINGPOWER = PWINDOW->roundingPower();
const auto ROUNDING = ROUNDINGBASE > 0 ? ROUNDINGBASE + PWINDOW->getRealBorderSize() : 0; const auto ROUNDING = ROUNDINGBASE > 0 ? ROUNDINGBASE + PWINDOW->getRealBorderSize() : 0;
const auto PWORKSPACE = PWINDOW->m_pWorkspace; const auto PWORKSPACE = PWINDOW->m_pWorkspace;
const auto WORKSPACEOFFSET = PWORKSPACE && !PWINDOW->m_bPinned ? PWORKSPACE->m_vRenderOffset.value() : Vector2D(); const auto WORKSPACEOFFSET = PWORKSPACE && !PWINDOW->m_bPinned ? PWORKSPACE->m_vRenderOffset.value() : Vector2D();
@ -192,10 +194,10 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
g_pHyprOpenGL->renderRect(&fullBox, CHyprColor(0, 0, 0, 1), 0); g_pHyprOpenGL->renderRect(&fullBox, CHyprColor(0, 0, 0, 1), 0);
// render white shadow with the alpha of the shadow color (otherwise we clear with alpha later and shit it to 2 bit) // render white shadow with the alpha of the shadow color (otherwise we clear with alpha later and shit it to 2 bit)
drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CHyprColor(1, 1, 1, PWINDOW->m_cRealShadowColor.value().a), a); drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, ROUNDINGPOWER, *PSHADOWSIZE * pMonitor->scale, CHyprColor(1, 1, 1, PWINDOW->m_cRealShadowColor.value().a), a);
// render black window box ("clip") // render black window box ("clip")
g_pHyprOpenGL->renderRect(&windowBox, CHyprColor(0, 0, 0, 1.0), (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->scale); g_pHyprOpenGL->renderRect(&windowBox, CHyprColor(0, 0, 0, 1.0), (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->scale, ROUNDINGPOWER);
alphaSwapFB.bind(); alphaSwapFB.bind();
@ -214,7 +216,7 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
g_pHyprOpenGL->m_RenderData.damage = saveDamage; g_pHyprOpenGL->m_RenderData.damage = saveDamage;
} else } else
drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, PWINDOW->m_cRealShadowColor.value(), a); drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, ROUNDINGPOWER, *PSHADOWSIZE * pMonitor->scale, PWINDOW->m_cRealShadowColor.value(), a);
if (m_seExtents != m_seReportedExtents) if (m_seExtents != m_seReportedExtents)
g_pDecorationPositioner->repositionDeco(this); g_pDecorationPositioner->repositionDeco(this);
@ -226,7 +228,7 @@ eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() {
return DECORATION_LAYER_BOTTOM; return DECORATION_LAYER_BOTTOM;
} }
void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, int range, CHyprColor color, float a) { void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, float roundingPower, int range, CHyprColor color, float a) {
static auto PSHADOWSHARP = CConfigValue<Hyprlang::INT>("decoration:shadow:sharp"); static auto PSHADOWSHARP = CConfigValue<Hyprlang::INT>("decoration:shadow:sharp");
g_pHyprOpenGL->blend(true); g_pHyprOpenGL->blend(true);
@ -234,7 +236,7 @@ void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, int ran
color.a *= a; color.a *= a;
if (*PSHADOWSHARP) if (*PSHADOWSHARP)
g_pHyprOpenGL->renderRect(box, color, round); g_pHyprOpenGL->renderRect(box, color, round, roundingPower);
else else
g_pHyprOpenGL->renderRoundedShadow(box, round, range, color, 1.F); g_pHyprOpenGL->renderRoundedShadow(box, round, roundingPower, range, color, 1.F);
} }

View file

@ -36,7 +36,7 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration {
Vector2D m_vLastWindowPos; Vector2D m_vLastWindowPos;
Vector2D m_vLastWindowSize; Vector2D m_vLastWindowSize;
void drawShadowInternal(CBox* box, int round, int range, CHyprColor color, float a); void drawShadowInternal(CBox* box, int round, float roundingPower, int range, CHyprColor color, float a);
CBox m_bLastWindowBox = {0}; CBox m_bLastWindowBox = {0};
CBox m_bLastWindowBoxWithDecos = {0}; CBox m_bLastWindowBoxWithDecos = {0};

View file

@ -7,9 +7,9 @@ CBorderPassElement::CBorderPassElement(const CBorderPassElement::SBorderData& da
void CBorderPassElement::draw(const CRegion& damage) { void CBorderPassElement::draw(const CRegion& damage) {
if (data.hasGrad2) if (data.hasGrad2)
g_pHyprOpenGL->renderBorder(&data.box, data.grad1, data.grad2, data.lerp, data.round, data.borderSize, data.a, data.outerRound); g_pHyprOpenGL->renderBorder(&data.box, data.grad1, data.grad2, data.lerp, data.round, data.roundingPower, data.borderSize, data.a, data.outerRound);
else else
g_pHyprOpenGL->renderBorder(&data.box, data.grad1, data.round, data.borderSize, data.a, data.outerRound); g_pHyprOpenGL->renderBorder(&data.box, data.grad1, data.round, data.roundingPower, data.borderSize, data.a, data.outerRound);
} }
bool CBorderPassElement::needsLiveBlur() { bool CBorderPassElement::needsLiveBlur() {

View file

@ -12,6 +12,7 @@ class CBorderPassElement : public IPassElement {
bool hasGrad2 = false; bool hasGrad2 = false;
float lerp = 0.F, a = 1.F; float lerp = 0.F, a = 1.F;
int round = 0, borderSize = 1, outerRound = -1; int round = 0, borderSize = 1, outerRound = -1;
float roundingPower = 2.F;
}; };
CBorderPassElement(const SBorderData& data_); CBorderPassElement(const SBorderData& data_);

View file

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

View file

@ -7,6 +7,7 @@ class CRectPassElement : public IPassElement {
CBox box; CBox box;
CHyprColor color; CHyprColor color;
int round = 0; int round = 0;
float roundingPower = 2.0f;
bool blur = false, xray = false; bool blur = false, xray = false;
float blurA = 1.F; float blurA = 1.F;
}; };

View file

@ -89,11 +89,14 @@ void CSurfacePassElement::draw(const CRegion& damage) {
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true;
float rounding = data.rounding; float rounding = data.rounding;
float roundingPower = data.roundingPower;
rounding -= 1; // to fix a border issue rounding -= 1; // to fix a border issue
if (data.dontRound) if (data.dontRound) {
rounding = 0; rounding = 0;
roundingPower = 2.0f;
}
const bool WINDOWOPAQUE = data.pWindow && data.pWindow->m_pWLSurface->resource() == data.surface ? data.pWindow->opaque() : false; const bool WINDOWOPAQUE = data.pWindow && data.pWindow->m_pWLSurface->resource() == data.surface ? data.pWindow->opaque() : false;
const bool CANDISABLEBLEND = ALPHA >= 1.f && OVERALL_ALPHA >= 1.f && rounding == 0 && WINDOWOPAQUE; const bool CANDISABLEBLEND = ALPHA >= 1.f && OVERALL_ALPHA >= 1.f && rounding == 0 && WINDOWOPAQUE;
@ -108,14 +111,14 @@ void CSurfacePassElement::draw(const CRegion& damage) {
// to what we do for misaligned surfaces (blur the entire thing and then render shit without blur) // to what we do for misaligned surfaces (blur the entire thing and then render shit without blur)
if (data.surfaceCounter == 0 && !data.popup) { if (data.surfaceCounter == 0 && !data.popup) {
if (BLUR) if (BLUR)
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, data.surface, rounding, data.blockBlurOptimization, data.fadeAlpha, OVERALL_ALPHA); g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, data.surface, rounding, roundingPower, data.blockBlurOptimization, data.fadeAlpha, OVERALL_ALPHA);
else else
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA * OVERALL_ALPHA, rounding, false, true); g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA * OVERALL_ALPHA, rounding, roundingPower, false, true);
} else { } else {
if (BLUR && data.popup) if (BLUR && data.popup)
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, data.surface, rounding, true, data.fadeAlpha, OVERALL_ALPHA); g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, data.surface, rounding, roundingPower, true, data.fadeAlpha, OVERALL_ALPHA);
else else
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA * OVERALL_ALPHA, rounding, false, true); g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA * OVERALL_ALPHA, rounding, roundingPower, false, true);
} }
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) if (!g_pHyprRenderer->m_bBlockSurfaceFeedback)

View file

@ -35,6 +35,9 @@ class CSurfacePassElement : public IPassElement {
// for custom round values // for custom round values
int rounding = -1; // -1 means not set int rounding = -1; // -1 means not set
// for custom rounding powers
float roundingPower = 2.0f;
// for blurring // for blurring
bool blur = false; bool blur = false;
bool blockBlurOptimization = false; bool blockBlurOptimization = false;

View file

@ -18,7 +18,8 @@ void CTexPassElement::draw(const CRegion& damage) {
if (data.replaceProjection) if (data.replaceProjection)
g_pHyprOpenGL->m_RenderData.monitorProjection = *data.replaceProjection; g_pHyprOpenGL->m_RenderData.monitorProjection = *data.replaceProjection;
g_pHyprOpenGL->renderTextureInternalWithDamage(data.tex, &data.box, data.a, data.damage.empty() ? damage : data.damage, data.round, data.syncTimeline, data.syncPoint); g_pHyprOpenGL->renderTextureInternalWithDamage(data.tex, &data.box, data.a, data.damage.empty() ? damage : data.damage, data.round, data.roundingPower, data.syncTimeline,
data.syncPoint);
if (data.replaceProjection) if (data.replaceProjection)
g_pHyprOpenGL->m_RenderData.monitorProjection = g_pHyprOpenGL->m_RenderData.pMonitor->projMatrix; g_pHyprOpenGL->m_RenderData.monitorProjection = g_pHyprOpenGL->m_RenderData.pMonitor->projMatrix;
} }

View file

@ -14,6 +14,7 @@ class CTexPassElement : public IPassElement {
float a = 1.F; float a = 1.F;
CRegion damage; CRegion damage;
int round = 0; int round = 0;
float roundingPower = 2.0f;
bool flipEndFrame = false; bool flipEndFrame = false;
SP<CSyncTimeline> syncTimeline; SP<CSyncTimeline> syncTimeline;
int64_t syncPoint = 0; int64_t syncPoint = 0;

View file

@ -15,6 +15,7 @@ uniform vec2 fullSize;
uniform vec2 fullSizeUntransformed; uniform vec2 fullSizeUntransformed;
uniform float radius; uniform float radius;
uniform float radiusOuter; uniform float radiusOuter;
uniform float roundingPower;
uniform float thick; uniform float thick;
// Gradients are in OkLabA!!!! {l, a, b, alpha} // Gradients are in OkLabA!!!! {l, a, b, alpha}
@ -138,8 +139,8 @@ void main() {
const float SMOOTHING_CONSTANT = )#" + const float SMOOTHING_CONSTANT = )#" +
std::format("{:.7f}", SHADER_ROUNDED_SMOOTHING_FACTOR) + R"#(; std::format("{:.7f}", SHADER_ROUNDED_SMOOTHING_FACTOR) + R"#(;
float dist = length(pixCoord); float dist = pow(pow(pixCoord.x,roundingPower)+pow(pixCoord.y,roundingPower),1.0/roundingPower);
float distOuter = length(pixCoordOuter); float distOuter = pow(pow(pixCoordOuter.x,roundingPower)+pow(pixCoordOuter.y,roundingPower),1.0/roundingPower);
float h = (thick / 2.0); float h = (thick / 2.0);
if (dist < radius - h) { if (dist < radius - h) {

View file

@ -11,6 +11,7 @@ uniform vec2 topLeft;
uniform vec2 bottomRight; uniform vec2 bottomRight;
uniform vec2 fullSize; uniform vec2 fullSize;
uniform float radius; uniform float radius;
uniform float roundingPower;
uniform float range; uniform float range;
uniform float shadowPower; uniform float shadowPower;
@ -26,6 +27,10 @@ float pixAlphaRoundedDistance(float distanceToCorner) {
return 1.0; return 1.0;
} }
float modifiedLength(vec2 a) {
return pow(pow(abs(a.x),roundingPower)+pow(abs(a.y),roundingPower),1.0/roundingPower);
}
void main() { void main() {
vec4 pixColor = v_color; vec4 pixColor = v_color;
@ -40,21 +45,21 @@ void main() {
if (pixCoord[0] < topLeft[0]) { if (pixCoord[0] < topLeft[0]) {
if (pixCoord[1] < topLeft[1]) { if (pixCoord[1] < topLeft[1]) {
// top left // top left
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, topLeft)); pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - topLeft));
done = true; done = true;
} else if (pixCoord[1] > bottomRight[1]) { } else if (pixCoord[1] > bottomRight[1]) {
// bottom left // bottom left
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, vec2(topLeft[0], bottomRight[1]))); pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - vec2(topLeft[0], bottomRight[1])));
done = true; done = true;
} }
} else if (pixCoord[0] > bottomRight[0]) { } else if (pixCoord[0] > bottomRight[0]) {
if (pixCoord[1] < topLeft[1]) { if (pixCoord[1] < topLeft[1]) {
// top right // top right
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, vec2(bottomRight[0], topLeft[1]))); pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - vec2(bottomRight[0], topLeft[1])));
done = true; done = true;
} else if (pixCoord[1] > bottomRight[1]) { } else if (pixCoord[1] > bottomRight[1]) {
// bottom right // bottom right
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, bottomRight)); pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - bottomRight));
done = true; done = true;
} }
} }

View file

@ -19,23 +19,18 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar
const float SMOOTHING_CONSTANT = )#" + const float SMOOTHING_CONSTANT = )#" +
std::format("{:.7f}", SHADER_ROUNDED_SMOOTHING_FACTOR) + R"#(; std::format("{:.7f}", SHADER_ROUNDED_SMOOTHING_FACTOR) + R"#(;
if (pixCoord.x + pixCoord.y > radius) { //if (pixCoord.x + pixCoord.y > radius) {
float dist = length(pixCoord); float dist = pow(pow(pixCoord.x, roundingPower) + pow(pixCoord.y, roundingPower), 1.0/roundingPower);
if (dist > radius + SMOOTHING_CONSTANT * 2.0) if (dist > radius + SMOOTHING_CONSTANT)
discard; discard;
if (dist > radius - SMOOTHING_CONSTANT * 2.0) {
float dist = length(pixCoord);
float normalized = 1.0 - smoothstep(0.0, 1.0, (dist - radius + SMOOTHING_CONSTANT) / (SMOOTHING_CONSTANT * 2.0)); float normalized = 1.0 - smoothstep(0.0, 1.0, (dist - radius + SMOOTHING_CONSTANT) / (SMOOTHING_CONSTANT * 2.0));
)#" + )#" +
colorVarName + R"#( = )#" + colorVarName + R"#( * normalized; colorVarName + R"#( = )#" + colorVarName + R"#( * normalized;
} //}
}
)#"; )#";
}; };
@ -63,6 +58,7 @@ varying vec4 v_color;
uniform vec2 topLeft; uniform vec2 topLeft;
uniform vec2 fullSize; uniform vec2 fullSize;
uniform float radius; uniform float radius;
uniform float roundingPower;
void main() { void main() {
@ -107,6 +103,7 @@ uniform float alpha;
uniform vec2 topLeft; uniform vec2 topLeft;
uniform vec2 fullSize; uniform vec2 fullSize;
uniform float radius; uniform float radius;
uniform float roundingPower;
uniform int discardOpaque; uniform int discardOpaque;
uniform int discardAlpha; uniform int discardAlpha;
@ -167,6 +164,7 @@ uniform float alpha;
uniform vec2 topLeft; uniform vec2 topLeft;
uniform vec2 fullSize; uniform vec2 fullSize;
uniform float radius; uniform float radius;
uniform float roundingPower;
uniform int discardOpaque; uniform int discardOpaque;
uniform int discardAlpha; uniform int discardAlpha;
@ -440,6 +438,7 @@ uniform float alpha;
uniform vec2 topLeft; uniform vec2 topLeft;
uniform vec2 fullSize; uniform vec2 fullSize;
uniform float radius; uniform float radius;
uniform float roundingPower;
uniform int discardOpaque; uniform int discardOpaque;
uniform int discardAlpha; uniform int discardAlpha;