corner radii

This commit is contained in:
Micovec 2024-01-08 12:51:18 +01:00
parent 880996b053
commit 2cf2a0d986
17 changed files with 332 additions and 182 deletions

View file

@ -563,7 +563,7 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
m_sAdditionalConfigData.nearestNeighbor = true; m_sAdditionalConfigData.nearestNeighbor = true;
} else if (r.szRule.starts_with("rounding")) { } else if (r.szRule.starts_with("rounding")) {
try { try {
m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1)); m_sAdditionalConfigData.cornerRadii = configStringToRadii(r.szRule);
} catch (std::exception& e) { Debug::log(ERR, "Rounding rule \"{}\" failed with: {}", r.szRule, e.what()); } } catch (std::exception& e) { Debug::log(ERR, "Rounding rule \"{}\" failed with: {}", r.szRule, e.what()); }
} else if (r.szRule.starts_with("bordersize")) { } else if (r.szRule.starts_with("bordersize")) {
try { try {
@ -656,7 +656,7 @@ void CWindow::updateDynamicRules() {
m_sAdditionalConfigData.forceOpaque = false; m_sAdditionalConfigData.forceOpaque = false;
m_sAdditionalConfigData.forceNoAnims = false; m_sAdditionalConfigData.forceNoAnims = false;
m_sAdditionalConfigData.animationStyle = std::string(""); m_sAdditionalConfigData.animationStyle = std::string("");
m_sAdditionalConfigData.rounding = -1; m_sAdditionalConfigData.cornerRadii = -1;
m_sAdditionalConfigData.dimAround = false; m_sAdditionalConfigData.dimAround = false;
m_sAdditionalConfigData.forceRGBX = false; m_sAdditionalConfigData.forceRGBX = false;
m_sAdditionalConfigData.borderSize = -1; m_sAdditionalConfigData.borderSize = -1;
@ -678,27 +678,29 @@ void CWindow::updateDynamicRules() {
// it is assumed that the point is within the real window box (m_vRealPosition, m_vRealSize) // it is assumed that the point is within the real window box (m_vRealPosition, m_vRealSize)
// 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 CCornerRadiiData ROUNDING = getCornerRadii();
if (getRealBorderSize() >= ROUNDING) const int BORDER = getRealBorderSize();
if (BORDER >= ROUNDING.topLeft && BORDER >= ROUNDING.topRight && BORDER >= ROUNDING.bottomLeft && BORDER >= ROUNDING.bottomRight)
return false; return false;
// (x0, y0), (x0, y1), ... are the center point of rounding at each corner // topLeft, topRight, bottomLeft, bottomRight, ... are the center point of rounding at each corner
double x0 = m_vRealPosition.vec().x + ROUNDING; Vector2D topLeft = {m_vRealPosition.vec().x + ROUNDING.topLeft, m_vRealPosition.vec().y + ROUNDING.topLeft};
double y0 = m_vRealPosition.vec().y + ROUNDING; Vector2D topRight = {m_vRealPosition.vec().x + m_vRealSize.vec().x + ROUNDING.topRight, m_vRealPosition.vec().y + ROUNDING.topRight};
double x1 = m_vRealPosition.vec().x + m_vRealSize.vec().x - ROUNDING; Vector2D bottomLeft = {m_vRealPosition.vec().x + ROUNDING.bottomLeft, m_vRealPosition.vec().y + m_vRealSize.vec().y + ROUNDING.bottomLeft};
double y1 = m_vRealPosition.vec().y + m_vRealSize.vec().y - ROUNDING; Vector2D bottomRight = {m_vRealPosition.vec().x + m_vRealSize.vec().x + ROUNDING.bottomRight, m_vRealPosition.vec().y + m_vRealSize.vec().y + ROUNDING.bottomRight};
if (x < x0 && y < y0) { if (x < topLeft.x && y < topLeft.y) {
return Vector2D{x0, y0}.distance(Vector2D{x, y}) > (double)ROUNDING; return topLeft.distance(Vector2D{x, y}) > (double)ROUNDING.topLeft;
} }
if (x > x1 && y < y0) { if (x > topRight.x && y < topRight.y) {
return Vector2D{x1, y0}.distance(Vector2D{x, y}) > (double)ROUNDING; return topRight.distance(Vector2D{x, y}) > (double)ROUNDING.topRight;
} }
if (x < x0 && y > y1) { if (x < bottomLeft.x && y > bottomLeft.y) {
return Vector2D{x0, y1}.distance(Vector2D{x, y}) > (double)ROUNDING; return bottomLeft.distance(Vector2D{x, y}) > (double)ROUNDING.bottomLeft;
} }
if (x > x1 && y > y1) { if (x > bottomRight.x && y > bottomRight.y) {
return Vector2D{x1, y1}.distance(Vector2D{x, y}) > (double)ROUNDING; return bottomRight.distance(Vector2D{x, y}) > (double)ROUNDING.bottomRight;
} }
return false; return false;
@ -989,12 +991,12 @@ bool CWindow::opaque() {
return false; return false;
} }
float CWindow::rounding() { CCornerRadiiData CWindow::getCornerRadii() {
static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue; static auto* const PRADII = (CCornerRadiiData*)g_pConfigManager->getConfigValuePtr("decoration:rounding")->data.get();
float rounding = m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_sAdditionalConfigData.rounding.toUnderlying(); CCornerRadiiData radii = m_sAdditionalConfigData.cornerRadii.toUnderlying() == -1 ? *PRADII : m_sAdditionalConfigData.cornerRadii.toUnderlying();
return m_sSpecialRenderData.rounding ? rounding : 0; return m_sSpecialRenderData.rounding ? radii : 0;
} }
void CWindow::updateSpecialRenderData() { void CWindow::updateSpecialRenderData() {

View file

@ -35,8 +35,8 @@ class IWindowTransformer;
template <typename T> template <typename T>
class CWindowOverridableVar { class CWindowOverridableVar {
public: public:
CWindowOverridableVar(T val) { CWindowOverridableVar(T val)
value = val; : value(val) {
} }
~CWindowOverridableVar() = default; ~CWindowOverridableVar() = default;
@ -51,7 +51,7 @@ class CWindowOverridableVar {
return *this; return *this;
} }
T operator=(T& other) { T operator=(const T& other) {
if (locked) if (locked)
return value; return value;
value = other; value = other;
@ -124,7 +124,7 @@ struct SWindowSpecialRenderData {
struct SWindowAdditionalConfigData { struct SWindowAdditionalConfigData {
std::string animationStyle = std::string(""); std::string animationStyle = std::string("");
CWindowOverridableVar<int> rounding = -1; // -1 means no CWindowOverridableVar<CCornerRadiiData> cornerRadii = CCornerRadiiData(-1); // -1 means no
CWindowOverridableVar<bool> forceNoBlur = false; CWindowOverridableVar<bool> forceNoBlur = false;
CWindowOverridableVar<bool> forceOpaque = false; CWindowOverridableVar<bool> forceOpaque = false;
CWindowOverridableVar<bool> forceOpaqueOverridden = false; // if true, a rule will not change the forceOpaque state. This is for the force opaque dispatcher. CWindowOverridableVar<bool> forceOpaqueOverridden = false; // if true, a rule will not change the forceOpaque state. This is for the force opaque dispatcher.
@ -368,7 +368,7 @@ class CWindow {
SWindowDecorationExtents getFullWindowReservedArea(); SWindowDecorationExtents getFullWindowReservedArea();
Vector2D middle(); Vector2D middle();
bool opaque(); bool opaque();
float rounding(); CCornerRadiiData getCornerRadii();
bool canBeTorn(); bool canBeTorn();
bool shouldSendFullscreenState(); bool shouldSendFullscreenState();
void setSuspended(bool suspend); void setSuspended(bool suspend);

View file

@ -4,7 +4,8 @@
enum eConfigValueDataTypes { enum eConfigValueDataTypes {
CVD_TYPE_INVALID = -1, CVD_TYPE_INVALID = -1,
CVD_TYPE_GRADIENT = 0 CVD_TYPE_GRADIENT = 0,
CVD_TYPE_CORNER_RADII = 1
}; };
class ICustomConfigValueData { class ICustomConfigValueData {
@ -49,3 +50,74 @@ class CGradientValueData : public ICustomConfigValueData {
return true; return true;
} }
}; };
// This class is probably going to be refactored once hyprlang is used
class CCornerRadiiData : public ICustomConfigValueData {
public:
CCornerRadiiData()
: CCornerRadiiData(0) {
}
CCornerRadiiData(int radius)
: CCornerRadiiData(radius, radius, radius, radius) {
}
CCornerRadiiData(int topL, int topR, int bottomR, int bottomL)
: topLeft(topL), topRight(topR), bottomRight(bottomR), bottomLeft(bottomL) {
}
virtual ~CCornerRadiiData(){}
virtual eConfigValueDataTypes getDataType() {
return CVD_TYPE_CORNER_RADII;
}
void reset(int radius) {
topLeft = topRight = bottomRight = bottomLeft = radius;
}
CCornerRadiiData operator+(int a) const {
return CCornerRadiiData(topLeft + a, topRight + a, bottomRight + a, bottomLeft + a);
}
CCornerRadiiData operator-(int a) const {
return CCornerRadiiData(topLeft - a, topRight - a, bottomRight - a, bottomLeft - a);
}
CCornerRadiiData operator*(int a) const {
return CCornerRadiiData(topLeft * a, topRight * a, bottomRight * a, bottomLeft * a);
}
CCornerRadiiData operator/(int a) const {
return CCornerRadiiData(topLeft / a, topRight / a, bottomRight / a, bottomLeft / a);
}
bool operator==(int a) const {
return topLeft == a && topRight == a && bottomRight == a && bottomLeft == a;
}
bool operator!=(int a) const {
return topLeft != a && topRight != a && bottomRight != a && bottomLeft != a;
}
CCornerRadiiData& operator+=(int a) {
topLeft += a;
topRight += a;
bottomRight += a;
bottomLeft += a;
return *this;
}
CCornerRadiiData& operator-=(int a) {
topLeft -= a;
topRight -= a;
bottomRight -= a;
bottomLeft -= a;
return *this;
}
int topLeft;
int topRight;
int bottomRight;
int bottomLeft;
};

View file

@ -33,6 +33,8 @@ CConfigManager::CConfigManager() {
configValues["group:groupbar:col.locked_active"].data = std::make_shared<CGradientValueData>(0x66ff5500); configValues["group:groupbar:col.locked_active"].data = std::make_shared<CGradientValueData>(0x66ff5500);
configValues["group:groupbar:col.locked_inactive"].data = std::make_shared<CGradientValueData>(0x66775500); configValues["group:groupbar:col.locked_inactive"].data = std::make_shared<CGradientValueData>(0x66775500);
configValues["decoration:rounding"].data = std::make_shared<CCornerRadiiData>(0);
Debug::log(LOG, "NOTE: further logs to stdout / logfile are disabled by default. Use debug:disable_logs and debug:enable_stdout_logs to override this."); Debug::log(LOG, "NOTE: further logs to stdout / logfile are disabled by default. Use debug:disable_logs and debug:enable_stdout_logs to override this.");
setDefaultVars(); setDefaultVars();
@ -161,7 +163,7 @@ void CConfigManager::setDefaultVars() {
configValues["debug:watchdog_timeout"].intValue = 5; configValues["debug:watchdog_timeout"].intValue = 5;
configValues["debug:disable_scale_checks"].intValue = 0; configValues["debug:disable_scale_checks"].intValue = 0;
configValues["decoration:rounding"].intValue = 0; ((CCornerRadiiData*)configValues["decoration:rounding"].data.get())->reset(0xffffffff);
configValues["decoration:blur:enabled"].intValue = 1; configValues["decoration:blur:enabled"].intValue = 1;
configValues["decoration:blur:size"].intValue = 8; configValues["decoration:blur:size"].intValue = 8;
configValues["decoration:blur:passes"].intValue = 1; configValues["decoration:blur:passes"].intValue = 1;
@ -543,6 +545,18 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
break; break;
} }
case CVD_TYPE_CORNER_RADII: {
CCornerRadiiData* data = static_cast<CCornerRadiiData*>(CONFIGENTRY->data.get());
try {
*data = configStringToRadii(VALUE);
} catch (std::exception& e) {
Debug::log(WARN, "Error reading value of {}", COMMAND);
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">. " + e.what();
}
break;
}
default: { default: {
UNREACHABLE(); UNREACHABLE();
} }

View file

@ -1106,7 +1106,7 @@ std::string dispatchSetProp(std::string request) {
if (PROP == "animationstyle") { if (PROP == "animationstyle") {
PWINDOW->m_sAdditionalConfigData.animationStyle = VAL; PWINDOW->m_sAdditionalConfigData.animationStyle = VAL;
} else if (PROP == "rounding") { } else if (PROP == "rounding") {
PWINDOW->m_sAdditionalConfigData.rounding.forceSetIgnoreLocked(configStringToInt(VAL), lock); PWINDOW->m_sAdditionalConfigData.cornerRadii.forceSetIgnoreLocked(configStringToRadii(VAL), lock);
} else if (PROP == "forcenoblur") { } else if (PROP == "forcenoblur") {
PWINDOW->m_sAdditionalConfigData.forceNoBlur.forceSetIgnoreLocked(configStringToInt(VAL), lock); PWINDOW->m_sAdditionalConfigData.forceNoBlur.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "forceopaque") { } else if (PROP == "forceopaque") {

View file

@ -715,6 +715,24 @@ int64_t configStringToInt(const std::string& VALUE) {
return std::stoll(VALUE); return std::stoll(VALUE);
} }
CCornerRadiiData configStringToRadii(const std::string& VALUE) {
CVarList vars(VALUE);
CCornerRadiiData radii;
if (vars.size() == 1) {
radii.reset(std::stoi(vars[0]));
} else if (vars.size() == 4) {
radii.topLeft = std::stoi(vars[0]);
radii.topRight = std::stoi(vars[1]);
radii.bottomRight = std::stoi(vars[2]);
radii.bottomLeft = std::stoi(vars[3]);
} else {
throw std::invalid_argument("not enough or too many values (1 or 4 separated by comma)");
}
return radii;
}
double normalizeAngleRad(double ang) { double normalizeAngleRad(double ang) {
if (ang > M_PI * 2) { if (ang > M_PI * 2) {
while (ang > M_PI * 2) while (ang > M_PI * 2)

View file

@ -5,6 +5,7 @@
#include <wayland-server.h> #include <wayland-server.h>
#include <wlr/util/box.h> #include <wlr/util/box.h>
#include "Vector2D.hpp" #include "Vector2D.hpp"
#include "../config/ConfigDataValues.hpp"
#include <vector> #include <vector>
#include <format> #include <format>
@ -27,6 +28,7 @@ void logSystemInfo();
std::string execAndGet(const char*); std::string execAndGet(const char*);
int64_t getPPIDof(int64_t pid); int64_t getPPIDof(int64_t pid);
int64_t configStringToInt(const std::string&); int64_t configStringToInt(const std::string&);
CCornerRadiiData configStringToRadii(const std::string&);
std::optional<float> getPlusMinusKeywordResult(std::string in, float relative); std::optional<float> getPlusMinusKeywordResult(std::string in, float relative);
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr); void matrixProjection(float mat[9], int w, int h, wl_output_transform tr);
double normalizeAngleRad(double ang); double normalizeAngleRad(double ang);

View file

@ -86,7 +86,7 @@ struct SRenderData {
bool decorate = false; bool decorate = false;
// for custom round values // for custom round values
int rounding = -1; // -1 means not set CCornerRadiiData cornerRadii = -1; // -1 means not set
// for blurring // for blurring
bool blur = false; bool blur = false;

View file

@ -320,7 +320,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shQUAD.posAttrib = glGetAttribLocation(prog, "pos"); m_RenderData.pCurrentMonData->m_shQUAD.posAttrib = glGetAttribLocation(prog, "pos");
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.cornerRadii = glGetUniformLocation(prog, "cornerRadii");
prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBA); prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBA);
m_RenderData.pCurrentMonData->m_shRGBA.program = prog; m_RenderData.pCurrentMonData->m_shRGBA.program = prog;
@ -336,7 +336,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shRGBA.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue"); m_RenderData.pCurrentMonData->m_shRGBA.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue");
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.cornerRadii = glGetUniformLocation(prog, "cornerRadii");
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");
@ -378,7 +378,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shRGBX.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue"); m_RenderData.pCurrentMonData->m_shRGBX.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue");
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.cornerRadii = glGetUniformLocation(prog, "cornerRadii");
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");
@ -394,7 +394,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shEXT.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue"); m_RenderData.pCurrentMonData->m_shEXT.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue");
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.cornerRadii = glGetUniformLocation(prog, "cornerRadii");
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");
@ -405,7 +405,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shBLUR1.proj = glGetUniformLocation(prog, "proj"); m_RenderData.pCurrentMonData->m_shBLUR1.proj = glGetUniformLocation(prog, "proj");
m_RenderData.pCurrentMonData->m_shBLUR1.posAttrib = glGetAttribLocation(prog, "pos"); m_RenderData.pCurrentMonData->m_shBLUR1.posAttrib = glGetAttribLocation(prog, "pos");
m_RenderData.pCurrentMonData->m_shBLUR1.texAttrib = glGetAttribLocation(prog, "texcoord"); m_RenderData.pCurrentMonData->m_shBLUR1.texAttrib = glGetAttribLocation(prog, "texcoord");
m_RenderData.pCurrentMonData->m_shBLUR1.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shBLUR1.cornerRadii = glGetUniformLocation(prog, "cornerRadii");
m_RenderData.pCurrentMonData->m_shBLUR1.halfpixel = glGetUniformLocation(prog, "halfpixel"); m_RenderData.pCurrentMonData->m_shBLUR1.halfpixel = glGetUniformLocation(prog, "halfpixel");
m_RenderData.pCurrentMonData->m_shBLUR1.passes = glGetUniformLocation(prog, "passes"); m_RenderData.pCurrentMonData->m_shBLUR1.passes = glGetUniformLocation(prog, "passes");
m_RenderData.pCurrentMonData->m_shBLUR1.vibrancy = glGetUniformLocation(prog, "vibrancy"); m_RenderData.pCurrentMonData->m_shBLUR1.vibrancy = glGetUniformLocation(prog, "vibrancy");
@ -418,7 +418,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shBLUR2.proj = glGetUniformLocation(prog, "proj"); m_RenderData.pCurrentMonData->m_shBLUR2.proj = glGetUniformLocation(prog, "proj");
m_RenderData.pCurrentMonData->m_shBLUR2.posAttrib = glGetAttribLocation(prog, "pos"); m_RenderData.pCurrentMonData->m_shBLUR2.posAttrib = glGetAttribLocation(prog, "pos");
m_RenderData.pCurrentMonData->m_shBLUR2.texAttrib = glGetAttribLocation(prog, "texcoord"); m_RenderData.pCurrentMonData->m_shBLUR2.texAttrib = glGetAttribLocation(prog, "texcoord");
m_RenderData.pCurrentMonData->m_shBLUR2.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shBLUR2.cornerRadii = glGetUniformLocation(prog, "cornerRadii");
m_RenderData.pCurrentMonData->m_shBLUR2.halfpixel = glGetUniformLocation(prog, "halfpixel"); m_RenderData.pCurrentMonData->m_shBLUR2.halfpixel = glGetUniformLocation(prog, "halfpixel");
prog = createProgram(TEXVERTSRC, FRAGBLURPREPARE); prog = createProgram(TEXVERTSRC, FRAGBLURPREPARE);
@ -445,9 +445,11 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos"); m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos");
m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord"); m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord");
m_RenderData.pCurrentMonData->m_shSHADOW.topLeft = glGetUniformLocation(prog, "topLeft"); m_RenderData.pCurrentMonData->m_shSHADOW.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shSHADOW.topRight = glGetUniformLocation(prog, "topRight");
m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight"); m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_RenderData.pCurrentMonData->m_shSHADOW.bottomLeft = glGetUniformLocation(prog, "bottomLeft");
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.cornerRadii = glGetUniformLocation(prog, "cornerRadii");
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");
@ -462,8 +464,8 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shBORDER1.bottomRight = glGetUniformLocation(prog, "bottomRight"); m_RenderData.pCurrentMonData->m_shBORDER1.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_RenderData.pCurrentMonData->m_shBORDER1.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shBORDER1.fullSize = glGetUniformLocation(prog, "fullSize");
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.cornerRadii = glGetUniformLocation(prog, "cornerRadii");
m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter = glGetUniformLocation(prog, "radiusOuter"); m_RenderData.pCurrentMonData->m_shBORDER1.cornerRadiiOuter = glGetUniformLocation(prog, "cornerRadiiOuter");
m_RenderData.pCurrentMonData->m_shBORDER1.gradient = glGetUniformLocation(prog, "gradient"); m_RenderData.pCurrentMonData->m_shBORDER1.gradient = glGetUniformLocation(prog, "gradient");
m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength = glGetUniformLocation(prog, "gradientLength"); m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength = glGetUniformLocation(prog, "gradientLength");
m_RenderData.pCurrentMonData->m_shBORDER1.angle = glGetUniformLocation(prog, "angle"); m_RenderData.pCurrentMonData->m_shBORDER1.angle = glGetUniformLocation(prog, "angle");
@ -578,12 +580,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 CColor& col, int round) { void CHyprOpenGLImpl::renderRect(CBox* box, const CColor& col, CCornerRadiiData radii) {
if (!m_RenderData.damage.empty()) if (!m_RenderData.damage.empty())
renderRectWithDamage(box, col, &m_RenderData.damage, round); renderRectWithDamage(box, col, &m_RenderData.damage, radii);
} }
void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round, float blurA, bool xray) { void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, CCornerRadiiData radii, float blurA, bool xray) {
if (m_RenderData.damage.empty()) if (m_RenderData.damage.empty())
return; return;
@ -605,7 +607,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round
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, CColor(0, 0, 0, 0), round); renderRect(box, CColor(0, 0, 0, 0), radii);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 1, -1); glStencilFunc(GL_EQUAL, 1, -1);
@ -627,10 +629,10 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round
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, radii);
} }
void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion* damage, int round) { void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion* damage, CCornerRadiiData radii) {
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()!");
@ -670,7 +672,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion
// Rounded corners // Rounded corners
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); glUniform4f(m_RenderData.pCurrentMonData->m_shQUAD.cornerRadii, radii.topLeft, radii.topRight, radii.bottomRight, radii.bottomLeft);
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);
@ -696,21 +698,21 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib); glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib);
} }
void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, CBox* pBox, float alpha, int round, bool allowCustomUV) { void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, CBox* pBox, float alpha, CCornerRadiiData radii, bool allowCustomUV) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
renderTexture(CTexture(tex), pBox, alpha, round, false, allowCustomUV); renderTexture(CTexture(tex), pBox, alpha, radii, false, allowCustomUV);
} }
void CHyprOpenGLImpl::renderTexture(const CTexture& tex, CBox* pBox, float alpha, int round, bool discardActive, bool allowCustomUV) { void CHyprOpenGLImpl::renderTexture(const CTexture& tex, CBox* pBox, float alpha, CCornerRadiiData radii, 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, radii, discardActive, false, allowCustomUV, true);
scissor((CBox*)nullptr); scissor((CBox*)nullptr);
} }
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA, bool allowCustomUV, void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox* pBox, float alpha, CRegion* damage, CCornerRadiiData radii, bool discardActive, bool noAA, bool allowCustomUV,
bool allowDim) { bool allowDim) {
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 NULL texture!"); RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
@ -824,7 +826,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox*
// Rounded corners // Rounded corners
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); glUniform4f(shader->cornerRadii, radii.topLeft, radii.topRight, radii.bottomRight, radii.bottomLeft);
if (allowDim && m_pCurrentWindow && *PDIMINACTIVE) { if (allowDim && m_pCurrentWindow && *PDIMINACTIVE) {
glUniform1i(shader->applyTint, 1); glUniform1i(shader->applyTint, 1);
@ -1094,7 +1096,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
wlr_matrix_transpose(glMatrix, glMatrix); wlr_matrix_transpose(glMatrix, glMatrix);
glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix); glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix);
#endif #endif
glUniform1f(pShader->radius, *PBLURSIZE * a); // this makes the blursize change with a glUniform4f(pShader->cornerRadii, *PBLURSIZE * a, *PBLURSIZE * a, *PBLURSIZE * a, *PBLURSIZE * a); // this makes the blursize change with a
if (pShader == &m_RenderData.pCurrentMonData->m_shBLUR1) { if (pShader == &m_RenderData.pCurrentMonData->m_shBLUR1) {
glUniform2f(m_RenderData.pCurrentMonData->m_shBLUR1.halfpixel, 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), glUniform2f(m_RenderData.pCurrentMonData->m_shBLUR1.halfpixel, 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f),
0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f)); 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
@ -1361,7 +1363,7 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(SLayerSurface* pLayer, CWind
return false; return false;
} }
void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, float a, wlr_surface* pSurface, int round, bool blockBlurOptimization, float blurA) { void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, float a, wlr_surface* pSurface, CCornerRadiiData radii, bool blockBlurOptimization, float blurA) {
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* const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; static auto* const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue;
@ -1378,7 +1380,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, flo
if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) || if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) ||
(m_pCurrentWindow && (m_pCurrentWindow->m_sAdditionalConfigData.forceNoBlur || m_pCurrentWindow->m_sAdditionalConfigData.forceRGBX))) { (m_pCurrentWindow && (m_pCurrentWindow->m_sAdditionalConfigData.forceNoBlur || m_pCurrentWindow->m_sAdditionalConfigData.forceRGBX))) {
renderTexture(tex, pBox, a, round, false, true); renderTexture(tex, pBox, a, radii, false, true);
return; return;
} }
@ -1391,7 +1393,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, flo
inverseOpaque.invert(&surfbox).intersect(0, 0, pSurface->current.width * pSurface->current.scale, pSurface->current.height * pSurface->current.scale); inverseOpaque.invert(&surfbox).intersect(0, 0, pSurface->current.width * pSurface->current.scale, pSurface->current.height * pSurface->current.scale);
if (inverseOpaque.empty()) { if (inverseOpaque.empty()) {
renderTexture(tex, pBox, a, round, false, true); renderTexture(tex, pBox, a, radii, false, true);
return; return;
} }
} else { } else {
@ -1426,9 +1428,9 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, flo
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, CColor(0, 0, 0, 0), round); renderRect(pBox, CColor(0, 0, 0, 0), radii);
else else
renderTexture(tex, pBox, a, round, true, true); // discard opaque renderTexture(tex, pBox, a, radii, 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, -1); glStencilFunc(GL_EQUAL, 1, -1);
@ -1451,7 +1453,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, flo
// draw window // draw window
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
renderTextureInternalWithDamage(tex, pBox, a, &texDamage, round, false, false, true, true); renderTextureInternalWithDamage(tex, pBox, a, &texDamage, radii, false, false, true, true);
glStencilMask(-1); glStencilMask(-1);
glStencilFunc(GL_ALWAYS, 1, 0xFF); glStencilFunc(GL_ALWAYS, 1, 0xFF);
@ -1465,7 +1467,7 @@ void pushVert2D(float x, float y, float* arr, int& counter, CBox* box) {
counter++; counter++;
} }
void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, int round, int borderSize, float a, int outerRound) { void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, CCornerRadiiData radii, int borderSize, float a, CCornerRadiiData outerRadii) {
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()!");
@ -1490,7 +1492,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in
box->width += 2 * scaledBorderSize; box->width += 2 * scaledBorderSize;
box->height += 2 * scaledBorderSize; box->height += 2 * scaledBorderSize;
round += round == 0 ? 0 : scaledBorderSize; radii += radii == 0 ? 0 : scaledBorderSize;
float matrix[9]; float matrix[9];
wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0,
@ -1528,8 +1530,10 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y); glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y); glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
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); glUniform4f(m_RenderData.pCurrentMonData->m_shBORDER1.cornerRadii, radii.topLeft, radii.topRight, radii.bottomRight, radii.bottomLeft);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound);
CCornerRadiiData actualOuterRadii = outerRadii == -1 ? radii : outerRadii;
glUniform4f(m_RenderData.pCurrentMonData->m_shBORDER1.cornerRadiiOuter, actualOuterRadii.topLeft, actualOuterRadii.topRight, actualOuterRadii.bottomRight, actualOuterRadii.bottomLeft);
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);
@ -1768,7 +1772,7 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) {
m_bEndFrame = false; m_bEndFrame = false;
} }
void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const CColor& color, float a) { void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, CCornerRadiiData radii, int range, const CColor& 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_pCurrentWindow, "Tried to render shadow without a window!"); RASSERT(m_pCurrentWindow, "Tried to render shadow without a window!");
@ -1808,15 +1812,19 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const
#endif #endif
glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r, col.g, col.b, col.a * a); glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r, col.g, col.b, col.a * a);
const auto TOPLEFT = Vector2D(range + round, range + round); const auto TOPLEFT = Vector2D(range + radii.topLeft, range + radii.topLeft);
const auto BOTTOMRIGHT = Vector2D(box->width - (range + round), box->height - (range + round)); const auto TOPRIGHT = Vector2D(box->width - range - radii.topRight, range + radii.topRight);
const auto BOTTOMRIGHT = Vector2D(box->width - (range + radii.bottomRight), box->height - (range + radii.bottomRight));
const auto BOTTOMLEFT = Vector2D(range + radii.bottomLeft, box->height - (range + radii.bottomLeft));
const auto FULLSIZE = Vector2D(box->width, box->height); const auto FULLSIZE = Vector2D(box->width, box->height);
// Rounded corners // Rounded corners
glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y); glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.topRight, (float)TOPRIGHT.x, (float)TOPRIGHT.y);
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.bottomLeft, (float)BOTTOMLEFT.x, (float)BOTTOMLEFT.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); glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.cornerRadii, range + radii.topLeft, range + radii.topRight, range + radii.bottomRight, range + radii.bottomLeft);
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);

View file

@ -118,14 +118,14 @@ class CHyprOpenGLImpl {
void begin(CMonitor*, CRegion*, CFramebuffer* fb = nullptr /* if provided, it's not a real frame */); void begin(CMonitor*, CRegion*, CFramebuffer* fb = nullptr /* if provided, it's not a real frame */);
void end(); void end();
void renderRect(CBox*, const CColor&, int round = 0); void renderRect(CBox*, const CColor&, CCornerRadiiData radii = 0);
void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f, bool xray = false); void renderRectWithBlur(CBox*, const CColor&, CCornerRadiiData radii = 0, float blurA = 1.f, bool xray = false);
void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0); void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, CCornerRadiiData radii = 0);
void renderTexture(wlr_texture*, CBox*, float a, int round = 0, bool allowCustomUV = false); void renderTexture(wlr_texture*, CBox*, float a, CCornerRadiiData radii = 0, bool allowCustomUV = false);
void renderTexture(const CTexture&, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); void renderTexture(const CTexture&, CBox*, float a, CCornerRadiiData radii = 0, bool discardActive = false, bool allowCustomUV = false);
void renderTextureWithBlur(const CTexture&, CBox*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); void renderTextureWithBlur(const CTexture&, CBox*, float a, wlr_surface* pSurface, CCornerRadiiData radii = 0, bool blockBlurOptimization = false, float blurA = 1.f);
void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0); void renderRoundedShadow(CBox*, CCornerRadiiData radii, int range, const CColor& 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&, CCornerRadiiData radii, int borderSize, float a = 1.0, CCornerRadiiData outerRadii = -1 /* use round */);
void renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte); void renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte);
void setMonitorTransformEnabled(bool enabled); void setMonitorTransformEnabled(bool enabled);
@ -216,7 +216,7 @@ 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(const CTexture&, CBox* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false, void renderTextureInternalWithDamage(const CTexture&, CBox* pBox, float a, CRegion* damage, CCornerRadiiData radii = 0, bool discardOpaque = false, bool noAA = false,
bool allowCustomUV = false, bool allowDim = false); bool allowCustomUV = false, bool allowDim = false);
void renderTexturePrimitive(const CTexture& tex, CBox* pBox); void renderTexturePrimitive(const CTexture& tex, CBox* pBox);
void renderSplash(cairo_t* const, cairo_surface_t* const, double); void renderSplash(cairo_t* const, cairo_surface_t* const, double);

View file

@ -122,15 +122,15 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data)
(!RDATA->pWindow || (!RDATA->pWindow->m_vRealSize.isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */) (!RDATA->pWindow || (!RDATA->pWindow->m_vRealSize.isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */)
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true;
float rounding = RDATA->rounding; CCornerRadiiData radii = RDATA->cornerRadii;
rounding -= 1; // to fix a border issue radii -= 1; // to fix a border issue
if (RDATA->dontRound) if (RDATA->dontRound)
rounding = 0; radii = 0;
const bool WINDOWOPAQUE = RDATA->pWindow && RDATA->pWindow->m_pWLSurface.wlr() == surface ? RDATA->pWindow->opaque() : false; const bool WINDOWOPAQUE = RDATA->pWindow && RDATA->pWindow->m_pWLSurface.wlr() == surface ? RDATA->pWindow->opaque() : false;
const bool CANDISABLEBLEND = RDATA->alpha * RDATA->fadeAlpha >= 1.f && rounding == 0 && (WINDOWOPAQUE || surface->opaque); const bool CANDISABLEBLEND = RDATA->alpha * RDATA->fadeAlpha >= 1.f && radii == 0 && (WINDOWOPAQUE || surface->opaque);
if (CANDISABLEBLEND) if (CANDISABLEBLEND)
g_pHyprOpenGL->blend(false); g_pHyprOpenGL->blend(false);
@ -139,12 +139,12 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data)
if (RDATA->surface && surface == RDATA->surface) { if (RDATA->surface && surface == RDATA->surface) {
if (wlr_xwayland_surface_try_from_wlr_surface(surface) && !wlr_xwayland_surface_try_from_wlr_surface(surface)->has_alpha && RDATA->fadeAlpha * RDATA->alpha == 1.f) { if (wlr_xwayland_surface_try_from_wlr_surface(surface) && !wlr_xwayland_surface_try_from_wlr_surface(surface)->has_alpha && RDATA->fadeAlpha * RDATA->alpha == 1.f) {
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true); g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, radii, true);
} else { } else {
if (RDATA->blur) if (RDATA->blur)
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding, RDATA->blockBlurOptimization, RDATA->fadeAlpha); g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, radii, RDATA->blockBlurOptimization, RDATA->fadeAlpha);
else else
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true); g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, radii, true);
} }
} else { } else {
if (RDATA->blur && RDATA->popup && *PBLURPOPUPS) { if (RDATA->blur && RDATA->popup && *PBLURPOPUPS) {
@ -154,10 +154,10 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data)
g_pHyprOpenGL->m_RenderData.discardOpacity = *PBLURPOPUPSIGNOREALPHA; g_pHyprOpenGL->m_RenderData.discardOpacity = *PBLURPOPUPSIGNOREALPHA;
} }
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding, true); g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, radii, true);
g_pHyprOpenGL->m_RenderData.discardMode &= ~DISCARD_ALPHA; g_pHyprOpenGL->m_RenderData.discardMode &= ~DISCARD_ALPHA;
} else } else
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true); g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, radii, true);
} }
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) {
@ -429,7 +429,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (pWindow->m_bPinned ? 1.f : PWORKSPACE->m_fAlpha.fl()); renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (pWindow->m_bPinned ? 1.f : PWORKSPACE->m_fAlpha.fl());
renderdata.alpha = pWindow->m_fActiveInactiveAlpha.fl(); renderdata.alpha = pWindow->m_fActiveInactiveAlpha.fl();
renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL); renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL);
renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale; renderdata.cornerRadii = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->getCornerRadii() * pMonitor->scale;
renderdata.blur = !ignoreAllGeometry; // if it shouldn't, it will be ignored later renderdata.blur = !ignoreAllGeometry; // if it shouldn't, it will be ignored later
renderdata.pWindow = pWindow; renderdata.pWindow = pWindow;
@ -524,7 +524,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall && renderdata.blur && *PBLUR) { if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall && renderdata.blur && *PBLUR) {
CBox wb = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h}; CBox wb = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h};
wb.scale(pMonitor->scale).round(); wb.scale(pMonitor->scale).round();
g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1, renderdata.fadeAlpha, g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.cornerRadii - 1, renderdata.fadeAlpha,
g_pHyprOpenGL->shouldUseNewBlurOptimizations(nullptr, pWindow)); g_pHyprOpenGL->shouldUseNewBlurOptimizations(nullptr, pWindow));
renderdata.blur = false; renderdata.blur = false;
} }
@ -2250,9 +2250,10 @@ void CHyprRenderer::setOccludedForMainWorkspace(CRegion& region, CWorkspace* pWo
if (!w->opaque()) if (!w->opaque())
continue; continue;
const auto ROUNDING = w->rounding() * PMONITOR->scale; const auto RADII = w->getCornerRadii() * PMONITOR->scale;
const Vector2D POS = w->m_vRealPosition.vec() + Vector2D{ROUNDING, ROUNDING} - PMONITOR->vecPosition + (w->m_bPinned ? Vector2D{} : pWorkspace->m_vRenderOffset.vec()); const int MINRADIUS = std::min(std::min(RADII.topLeft, RADII.topRight), std::min(RADII.bottomLeft, RADII.bottomRight));
const Vector2D SIZE = w->m_vRealSize.vec() - Vector2D{ROUNDING * 2, ROUNDING * 2}; const Vector2D POS = w->m_vRealPosition.vec() + Vector2D{MINRADIUS, MINRADIUS} - PMONITOR->vecPosition + (w->m_bPinned ? Vector2D{} : pWorkspace->m_vRenderOffset.vec());
const Vector2D SIZE = w->m_vRealSize.vec() - Vector2D{MINRADIUS * 2, MINRADIUS * 2};
CBox box = {POS.x, POS.y, SIZE.x, SIZE.y}; CBox box = {POS.x, POS.y, SIZE.x, SIZE.y};
@ -2276,9 +2277,10 @@ void CHyprRenderer::setOccludedForBackLayers(CRegion& region, CWorkspace* pWorks
if (!w->opaque()) if (!w->opaque())
continue; continue;
const auto ROUNDING = w->rounding() * PMONITOR->scale; const auto RADII = w->getCornerRadii() * PMONITOR->scale;
const Vector2D POS = w->m_vRealPosition.vec() + Vector2D{ROUNDING, ROUNDING} - PMONITOR->vecPosition + (w->m_bPinned ? Vector2D{} : pWorkspace->m_vRenderOffset.vec()); const int MINRADIUS = std::min(std::min(RADII.topLeft, RADII.topRight), std::min(RADII.bottomLeft, RADII.bottomRight));
const Vector2D SIZE = w->m_vRealSize.vec() - Vector2D{ROUNDING * 2, ROUNDING * 2}; const Vector2D POS = w->m_vRealPosition.vec() + Vector2D{MINRADIUS, MINRADIUS} - PMONITOR->vecPosition + (w->m_bPinned ? Vector2D{} : pWorkspace->m_vRenderOffset.vec());
const Vector2D SIZE = w->m_vRealSize.vec() - Vector2D{MINRADIUS * 2, MINRADIUS * 2};
CBox box = {POS.x, POS.y, SIZE.x, SIZE.y}; CBox box = {POS.x, POS.y, SIZE.x, SIZE.y};

View file

@ -21,11 +21,13 @@ class CShader {
GLfloat discardAlphaValue = -1; GLfloat discardAlphaValue = -1;
GLint topLeft = -1; GLint topLeft = -1;
GLint topRight = -1;
GLint bottomRight = -1; GLint bottomRight = -1;
GLint bottomLeft = -1;
GLint fullSize = -1; GLint fullSize = -1;
GLint fullSizeUntransformed = -1; GLint fullSizeUntransformed = -1;
GLint radius = -1; GLint cornerRadii = -1;
GLint radiusOuter = -1; GLint cornerRadiiOuter = -1;
GLint thick = -1; GLint thick = -1;

View file

@ -66,13 +66,13 @@ void CHyprBorderDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& of
} }
int borderSize = m_pWindow->getRealBorderSize(); int borderSize = m_pWindow->getRealBorderSize();
const auto ROUNDING = m_pWindow->rounding() * pMonitor->scale; const auto RADII = m_pWindow->getCornerRadii() * pMonitor->scale;
g_pHyprOpenGL->renderBorder(&windowBox, grad, ROUNDING, borderSize, a1); g_pHyprOpenGL->renderBorder(&windowBox, grad, RADII, borderSize, a1);
if (ANIMATED) { if (ANIMATED) {
float a2 = a * (1.f - m_pWindow->m_fBorderFadeAnimationProgress.fl()); float a2 = a * (1.f - m_pWindow->m_fBorderFadeAnimationProgress.fl());
g_pHyprOpenGL->renderBorder(&windowBox, m_pWindow->m_cRealBorderColorPrevious, ROUNDING, borderSize, a2); g_pHyprOpenGL->renderBorder(&windowBox, m_pWindow->m_cRealBorderColorPrevious, RADII, borderSize, a2);
} }
} }

View file

@ -79,8 +79,8 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D
if (*PSHADOWS != 1) if (*PSHADOWS != 1)
return; // disabled return; // disabled
const auto ROUNDINGBASE = m_pWindow->rounding(); const auto RADIIBASE = m_pWindow->getCornerRadii();
const auto ROUNDING = ROUNDINGBASE > 0 ? ROUNDINGBASE + m_pWindow->getRealBorderSize() : 0; const auto RADII = RADIIBASE.topLeft > 0|| RADIIBASE.topRight > 0 || RADIIBASE.bottomRight > 0 || RADIIBASE.bottomLeft > 0 ? RADIIBASE + m_pWindow->getRealBorderSize() : 0;
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_pWindow->m_iWorkspaceID); const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_pWindow->m_iWorkspaceID);
const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D(); const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
@ -137,7 +137,15 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D
CRegion saveDamage = g_pHyprOpenGL->m_RenderData.damage; CRegion saveDamage = g_pHyprOpenGL->m_RenderData.damage;
g_pHyprOpenGL->m_RenderData.damage = fullBox; g_pHyprOpenGL->m_RenderData.damage = fullBox;
g_pHyprOpenGL->m_RenderData.damage.subtract(windowBox.copy().expand(-ROUNDING * pMonitor->scale)).intersect(saveDamage);
// TODO: check if CBox has the right params
CBox substract = windowBox.copy();
substract.x -= -std::min(RADII.topLeft, RADII.bottomLeft) * pMonitor->scale;
substract.y -= -std::min(RADII.topRight, RADII.bottomRight) * pMonitor->scale;
substract.w += -(std::min(RADII.topLeft, RADII.bottomLeft) + std::min(RADII.topRight, RADII.bottomRight)) * pMonitor->scale;
substract.h += -(std::min(RADII.topLeft, RADII.topRight) + std::min(RADII.bottomLeft, RADII.bottomRight)) * pMonitor->scale;
g_pHyprOpenGL->m_RenderData.damage.subtract(substract).intersect(saveDamage);
alphaFB.bind(); alphaFB.bind();
@ -147,10 +155,10 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D
g_pHyprOpenGL->renderRect(&fullBox, CColor(0, 0, 0, 1), 0); g_pHyprOpenGL->renderRect(&fullBox, CColor(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)
g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CColor(1, 1, 1, m_pWindow->m_cRealShadowColor.col().a), a); g_pHyprOpenGL->renderRoundedShadow(&fullBox, RADII * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CColor(1, 1, 1, m_pWindow->m_cRealShadowColor.col().a), a);
// render black window box ("clip") // render black window box ("clip")
g_pHyprOpenGL->renderRect(&windowBox, CColor(0, 0, 0, 1.0), ROUNDING * pMonitor->scale); g_pHyprOpenGL->renderRect(&windowBox, CColor(0, 0, 0, 1.0), RADII * pMonitor->scale);
alphaSwapFB.bind(); alphaSwapFB.bind();
@ -166,7 +174,7 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D
g_pHyprOpenGL->m_RenderData.damage = saveDamage; g_pHyprOpenGL->m_RenderData.damage = saveDamage;
} else { } else {
g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, m_pWindow->m_cRealShadowColor.col(), a); g_pHyprOpenGL->renderRoundedShadow(&fullBox, RADII * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, m_pWindow->m_cRealShadowColor.col(), a);
} }
if (m_seExtents != m_seReportedExtents) if (m_seExtents != m_seReportedExtents)

View file

@ -11,8 +11,8 @@ varying vec2 v_texcoord;
uniform vec2 topLeft; uniform vec2 topLeft;
uniform vec2 fullSize; uniform vec2 fullSize;
uniform vec2 fullSizeUntransformed; uniform vec2 fullSizeUntransformed;
uniform float radius; uniform vec4 cornerRadii;
uniform float radiusOuter; uniform vec4 cornerRadiiOuter;
uniform float thick; uniform float thick;
uniform vec4 gradient[10]; uniform vec4 gradient[10];
@ -62,8 +62,24 @@ void main() {
bool done = false; bool done = false;
pixCoord -= topLeft + fullSize * 0.5; pixCoord -= topLeft + fullSize * 0.5;
bvec2 positive = lessThan(vec2(0.0), pixCoord);
vec4 pick = vec4(
!positive.x && !positive.y,
positive.x && !positive.y,
positive.x && positive.y,
!positive.x && positive.y);
vec4 result = pick * cornerRadii;
vec4 resultOuter = pick * cornerRadiiOuter;
float radius = result.x + result.y + result.z + result.w;
float radiusOuter = resultOuter.x + resultOuter.y + resultOuter.z + resultOuter.w;
pixCoord *= vec2(lessThan(pixCoord, vec2(0.0))) * -2.0 + 1.0; pixCoord *= vec2(lessThan(pixCoord, vec2(0.0))) * -2.0 + 1.0;
pixCoordOuter = pixCoord; pixCoordOuter = pixCoord;
pixCoord -= fullSize * 0.5 - radius; pixCoord -= fullSize * 0.5 - radius;
pixCoordOuter -= fullSize * 0.5 - radiusOuter; pixCoordOuter -= fullSize * 0.5 - radiusOuter;

View file

@ -8,13 +8,15 @@ varying vec4 v_color;
varying vec2 v_texcoord; varying vec2 v_texcoord;
uniform vec2 topLeft; uniform vec2 topLeft;
uniform vec2 topRight;
uniform vec2 bottomRight; uniform vec2 bottomRight;
uniform vec2 bottomLeft;
uniform vec2 fullSize; uniform vec2 fullSize;
uniform float radius; uniform vec4 cornerRadii;
uniform float range; uniform float range;
uniform float shadowPower; uniform float shadowPower;
float pixAlphaRoundedDistance(float distanceToCorner) { float pixAlphaRoundedDistance(float distanceToCorner, float radius) {
if (distanceToCorner > radius) { if (distanceToCorner > radius) {
return 0.0; return 0.0;
} }
@ -36,28 +38,19 @@ void main() {
vec2 pixCoord = fullSize * v_texcoord; vec2 pixCoord = fullSize * v_texcoord;
// ok, now we check the distance to a border. // ok, now we check the distance to a border.
if (pixCoord[0] < topLeft[0] && pixCoord[1] < topLeft[1]) {
if (pixCoord[0] < topLeft[0]) { pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, topLeft), cornerRadii.x);
if (pixCoord[1] < topLeft[1]) {
// top left
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, topLeft));
done = true; done = true;
} else if (pixCoord[1] > bottomRight[1]) { } else if (pixCoord[0] > topRight[0] && pixCoord[1] < topRight[1]) {
// bottom left pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, topRight), cornerRadii.y);
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, vec2(topLeft[0], bottomRight[1])));
done = true; done = true;
} } else if (pixCoord[0] > bottomRight[0] && pixCoord[1] > bottomRight[1]) {
} else if (pixCoord[0] > bottomRight[0]) { pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, bottomRight), cornerRadii.z);
if (pixCoord[1] < topLeft[1]) {
// top right
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, vec2(bottomRight[0], topLeft[1])));
done = true; done = true;
} else if (pixCoord[1] > bottomRight[1]) { } else if (pixCoord[0] < bottomLeft[0] && pixCoord[1] > bottomLeft[1]) {
// bottom right pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, bottomLeft), cornerRadii.w);
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, bottomRight));
done = true; done = true;
} }
}
if (!done) { if (!done) {
// distance to all straight bb borders // distance to all straight bb borders

View file

@ -8,6 +8,19 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar
// branchless baby! // branchless baby!
highp vec2 pixCoord = vec2(gl_FragCoord); highp vec2 pixCoord = vec2(gl_FragCoord);
pixCoord -= topLeft + fullSize * 0.5; pixCoord -= topLeft + fullSize * 0.5;
bvec2 positive = lessThan(vec2(0.0), pixCoord);
vec4 pick = vec4(
!positive.x && !positive.y,
positive.x && !positive.y,
positive.x && positive.y,
!positive.x && positive.y);
vec4 result = pick * cornerRadii;
float radius = result.x + result.y + result.z + result.w;
pixCoord *= vec2(lessThan(pixCoord, vec2(0.0))) * -2.0 + 1.0; pixCoord *= vec2(lessThan(pixCoord, vec2(0.0))) * -2.0 + 1.0;
pixCoord -= fullSize * 0.5 - radius; pixCoord -= fullSize * 0.5 - radius;
pixCoord += vec2(1.0, 1.0) / fullSize; // center the pix dont make it top-left pixCoord += vec2(1.0, 1.0) / fullSize; // center the pix dont make it top-left
@ -20,8 +33,6 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar
discard; discard;
if (dist > radius - 1.0) { if (dist > radius - 1.0) {
float dist = length(pixCoord);
float normalized = 1.0 - smoothstep(0.0, 1.0, dist - radius + 0.5); float normalized = 1.0 - smoothstep(0.0, 1.0, dist - radius + 0.5);
)#" + )#" +
@ -55,13 +66,13 @@ varying vec4 v_color;
uniform vec2 topLeft; uniform vec2 topLeft;
uniform vec2 fullSize; uniform vec2 fullSize;
uniform float radius; uniform vec4 cornerRadii;
void main() { void main() {
vec4 pixColor = v_color; vec4 pixColor = v_color;
if (radius > 0.0) { if (cornerRadii != vec4(0, 0, 0, 0)) {
)#" + )#" +
ROUNDED_SHADER_FUNC("pixColor") + R"#( ROUNDED_SHADER_FUNC("pixColor") + R"#(
} }
@ -88,7 +99,7 @@ uniform float alpha;
uniform vec2 topLeft; uniform vec2 topLeft;
uniform vec2 fullSize; uniform vec2 fullSize;
uniform float radius; uniform vec4 cornerRadii;
uniform int discardOpaque; uniform int discardOpaque;
uniform int discardAlpha; uniform int discardAlpha;
@ -113,7 +124,7 @@ void main() {
pixColor[2] = pixColor[2] * tint[2]; pixColor[2] = pixColor[2] * tint[2];
} }
if (radius > 0.0) { if (cornerRadii != vec4(0, 0, 0, 0)) {
)#" + )#" +
ROUNDED_SHADER_FUNC("pixColor") + R"#( ROUNDED_SHADER_FUNC("pixColor") + R"#(
} }
@ -148,7 +159,7 @@ uniform float alpha;
uniform vec2 topLeft; uniform vec2 topLeft;
uniform vec2 fullSize; uniform vec2 fullSize;
uniform float radius; uniform vec4 cornerRadii;
uniform int discardOpaque; uniform int discardOpaque;
uniform int discardAlpha; uniform int discardAlpha;
@ -170,7 +181,7 @@ void main() {
pixColor[2] = pixColor[2] * tint[2]; pixColor[2] = pixColor[2] * tint[2];
} }
if (radius > 0.0) { if (cornerRadii != vec4(0, 0, 0, 0)) {
)#" + )#" +
ROUNDED_SHADER_FUNC("pixColor") + R"#( ROUNDED_SHADER_FUNC("pixColor") + R"#(
} }
@ -184,7 +195,7 @@ precision mediump float;
varying mediump vec2 v_texcoord; // is in 0-1 varying mediump vec2 v_texcoord; // is in 0-1
uniform sampler2D tex; uniform sampler2D tex;
uniform float radius; uniform vec4 cornerRadii;
uniform vec2 halfpixel; uniform vec2 halfpixel;
uniform int passes; uniform int passes;
uniform float vibrancy; uniform float vibrancy;
@ -292,6 +303,7 @@ void main() {
vec2 uv = v_texcoord * 2.0; vec2 uv = v_texcoord * 2.0;
vec4 sum = texture2D(tex, uv) * 4.0; vec4 sum = texture2D(tex, uv) * 4.0;
float radius = cornerRadii.x;
sum += texture2D(tex, uv - halfpixel.xy * radius); sum += texture2D(tex, uv - halfpixel.xy * radius);
sum += texture2D(tex, uv + halfpixel.xy * radius); sum += texture2D(tex, uv + halfpixel.xy * radius);
sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius); sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius);
@ -328,12 +340,13 @@ precision mediump float;
varying mediump vec2 v_texcoord; // is in 0-1 varying mediump vec2 v_texcoord; // is in 0-1
uniform sampler2D tex; uniform sampler2D tex;
uniform float radius; uniform vec4 cornerRadii;
uniform vec2 halfpixel; uniform vec2 halfpixel;
void main() { void main() {
vec2 uv = v_texcoord / 2.0; vec2 uv = v_texcoord / 2.0;
float radius = cornerRadii.x;
vec4 sum = texture2D(tex, uv + vec2(-halfpixel.x * 2.0, 0.0) * radius); vec4 sum = texture2D(tex, uv + vec2(-halfpixel.x * 2.0, 0.0) * radius);
sum += texture2D(tex, uv + vec2(-halfpixel.x, halfpixel.y) * radius) * 2.0; sum += texture2D(tex, uv + vec2(-halfpixel.x, halfpixel.y) * radius) * 2.0;
@ -419,7 +432,7 @@ uniform float alpha;
uniform vec2 topLeft; uniform vec2 topLeft;
uniform vec2 fullSize; uniform vec2 fullSize;
uniform float radius; uniform vec4 cornerRadii;
uniform int discardOpaque; uniform int discardOpaque;
uniform int discardAlpha; uniform int discardAlpha;
@ -441,7 +454,7 @@ void main() {
pixColor[2] = pixColor[2] * tint[2]; pixColor[2] = pixColor[2] * tint[2];
} }
if (radius > 0.0) { if (cornerRadii != vec4(0, 0, 0, 0)) {
)#" + )#" +
ROUNDED_SHADER_FUNC("pixColor") + R"#( ROUNDED_SHADER_FUNC("pixColor") + R"#(
} }