summaryrefslogtreecommitdiff
path: root/src/render
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2024-12-03 18:58:24 +0000
committerGitHub <noreply@github.com>2024-12-03 18:58:24 +0000
commit320144ae7288fe23686935ebb235d9fe0c900862 (patch)
tree351b04e228926f98c12c340284c25450bb1fed4f /src/render
parent92186898c0ca1b3f72922b72c4af1723f0d9b888 (diff)
core: move colorspace handling to oklab (#8635)
* Meson: add hyprgraphics * Nix: add hyprgraphics * CI/setup_base: get hyprgraphics-git --------- Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
Diffstat (limited to 'src/render')
-rw-r--r--src/render/OpenGL.cpp157
-rw-r--r--src/render/OpenGL.hpp13
-rw-r--r--src/render/Renderer.cpp20
-rw-r--r--src/render/Shader.hpp10
-rw-r--r--src/render/decorations/CHyprBorderDecoration.cpp11
-rw-r--r--src/render/decorations/CHyprDropShadowDecoration.cpp10
-rw-r--r--src/render/decorations/CHyprDropShadowDecoration.hpp2
-rw-r--r--src/render/decorations/CHyprGroupBarDecoration.cpp28
-rw-r--r--src/render/shaders/Border.hpp62
9 files changed, 241 insertions, 72 deletions
diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp
index 9c00daee..9b878317 100644
--- a/src/render/OpenGL.cpp
+++ b/src/render/OpenGL.cpp
@@ -566,7 +566,11 @@ void CHyprOpenGLImpl::logShaderError(const GLuint& shader, bool program) {
glGetShaderInfoLog(shader, maxLength, &maxLength, errorLog.data());
std::string errorStr(errorLog.begin(), errorLog.end());
- g_pConfigManager->addParseError((program ? "Screen shader parser: Error linking program:" : "Screen shader parser: Error compiling shader: ") + errorStr);
+ const auto FULLERROR = (program ? "Screen shader parser: Error linking program:" : "Screen shader parser: Error compiling shader: ") + errorStr;
+
+ Debug::log(ERR, "Failed to link shader: {}", FULLERROR);
+
+ g_pConfigManager->addParseError(FULLERROR);
}
GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string& frag, bool dynamic) {
@@ -604,6 +608,8 @@ GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string
return 0;
}
} else {
+ if (ok != GL_TRUE)
+ logShaderError(prog, true);
RASSERT(ok != GL_FALSE, "createProgram() failed! GL_LINK_STATUS not OK!");
}
@@ -627,6 +633,8 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool
return 0;
}
} else {
+ if (ok != GL_TRUE)
+ logShaderError(shader, false);
RASSERT(ok != GL_FALSE, "compileShader() failed! GL_COMPILE_STATUS not OK!");
}
@@ -1114,8 +1122,12 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shBORDER1.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter = glGetUniformLocation(prog, "radiusOuter");
m_RenderData.pCurrentMonData->m_shBORDER1.gradient = glGetUniformLocation(prog, "gradient");
+ m_RenderData.pCurrentMonData->m_shBORDER1.gradient2 = glGetUniformLocation(prog, "gradient2");
m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength = glGetUniformLocation(prog, "gradientLength");
+ m_RenderData.pCurrentMonData->m_shBORDER1.gradient2Length = glGetUniformLocation(prog, "gradient2Length");
m_RenderData.pCurrentMonData->m_shBORDER1.angle = glGetUniformLocation(prog, "angle");
+ m_RenderData.pCurrentMonData->m_shBORDER1.angle2 = glGetUniformLocation(prog, "angle2");
+ m_RenderData.pCurrentMonData->m_shBORDER1.gradientLerp = glGetUniformLocation(prog, "gradientLerp");
m_RenderData.pCurrentMonData->m_shBORDER1.alpha = glGetUniformLocation(prog, "alpha");
m_RenderData.pCurrentMonData->m_bShadersInitialized = true;
@@ -1167,7 +1179,7 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) {
m_sFinalScreenShader.posAttrib = glGetAttribLocation(m_sFinalScreenShader.program, "pos");
}
-void CHyprOpenGLImpl::clear(const CColor& color) {
+void CHyprOpenGLImpl::clear(const CHyprColor& color) {
RASSERT(m_RenderData.pMonitor, "Tried to render without begin()!");
TRACY_GPU_ZONE("RenderClear");
@@ -1231,12 +1243,12 @@ void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h
scissor(&box, transform);
}
-void CHyprOpenGLImpl::renderRect(CBox* box, const CColor& col, int round) {
+void CHyprOpenGLImpl::renderRect(CBox* box, const CHyprColor& col, int round) {
if (!m_RenderData.damage.empty())
renderRectWithDamage(box, col, &m_RenderData.damage, round);
}
-void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round, float blurA, bool xray) {
+void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int round, float blurA, bool xray) {
if (m_RenderData.damage.empty())
return;
@@ -1258,7 +1270,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- renderRect(box, CColor(0, 0, 0, 0), round);
+ renderRect(box, CHyprColor(0, 0, 0, 0), round);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 1, 0xFF);
@@ -1283,7 +1295,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round
renderRectWithDamage(box, col, &m_RenderData.damage, round);
}
-void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion* damage, int round) {
+void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, CRegion* damage, int round) {
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()!");
@@ -1981,7 +1993,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() {
m_RenderData.pMonitor->output->state->state().drmFormat);
m_RenderData.pCurrentMonData->blurFB.bind();
- clear(CColor(0, 0, 0, 0));
+ clear(CHyprColor(0, 0, 0, 0));
m_bEndFrame = true; // fix transformed
renderTextureInternalWithDamage(POUTFB->getTexture(), &wholeMonitor, 1, &fakeDamage, 0, false, true, false);
@@ -2100,7 +2112,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
if (USENEWOPTIMIZE && !(m_RenderData.discardMode & DISCARD_ALPHA))
- renderRect(pBox, CColor(0, 0, 0, 0), round);
+ renderRect(pBox, CHyprColor(0, 0, 0, 0), round);
else
renderTexture(tex, pBox, a, round, true, true); // discard opaque
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@@ -2184,12 +2196,107 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix.getMatrix().data());
#endif
- static_assert(sizeof(CColor) == 4 * sizeof(float)); // otherwise the line below this will fail
-
- glUniform4fv(m_RenderData.pCurrentMonData->m_shBORDER1.gradient, grad.m_vColors.size(), (float*)grad.m_vColors.data());
- glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength, grad.m_vColors.size());
+ glUniform4fv(m_RenderData.pCurrentMonData->m_shBORDER1.gradient, grad.m_vColorsOkLabA.size(), (float*)grad.m_vColorsOkLabA.data());
+ glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength, grad.m_vColorsOkLabA.size() / 4);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.angle, (int)(grad.m_fAngle / (PI / 180.0)) % 360 * (PI / 180.0));
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a);
+ glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradient2Length, 0);
+
+ CBox transformedBox = *box;
+ transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x,
+ m_RenderData.pMonitor->vecTransformedSize.y);
+
+ const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y);
+ const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height);
+
+ 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.fullSizeUntransformed, (float)box->width, (float)box->height);
+ 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.thick, scaledBorderSize);
+
+ glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
+ glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
+
+ glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib);
+ glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib);
+
+ if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) {
+ CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height};
+ damageClip.intersect(m_RenderData.damage);
+
+ if (!damageClip.empty()) {
+ for (auto const& RECT : damageClip.getRects()) {
+ scissor(&RECT);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ }
+ }
+ } else {
+ for (auto const& RECT : m_RenderData.damage.getRects()) {
+ scissor(&RECT);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ }
+ }
+
+ glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib);
+ glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib);
+
+ blend(BLEND);
+}
+
+void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, const CGradientValueData& grad2, float lerp, int round, int borderSize, float a, int outerRound) {
+ 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()!");
+
+ TRACY_GPU_ZONE("RenderBorder2");
+
+ if (m_RenderData.damage.empty() || (m_pCurrentWindow.lock() && m_pCurrentWindow->m_sWindowData.noBorder.valueOrDefault()))
+ return;
+
+ CBox newBox = *box;
+ m_RenderData.renderModif.applyToBox(newBox);
+
+ box = &newBox;
+
+ if (borderSize < 1)
+ return;
+
+ int scaledBorderSize = std::round(borderSize * m_RenderData.pMonitor->scale);
+ scaledBorderSize = std::round(scaledBorderSize * m_RenderData.renderModif.combinedScale());
+
+ // adjust box
+ box->x -= scaledBorderSize;
+ box->y -= scaledBorderSize;
+ box->width += 2 * scaledBorderSize;
+ box->height += 2 * scaledBorderSize;
+
+ round += round == 0 ? 0 : scaledBorderSize;
+
+ Mat3x3 matrix = m_RenderData.monitorProjection.projectBox(
+ newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot);
+ Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix);
+
+ const auto BLEND = m_bBlend;
+ blend(true);
+
+ glUseProgram(m_RenderData.pCurrentMonData->m_shBORDER1.program);
+
+#ifndef GLES2
+ glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_TRUE, glMatrix.getMatrix().data());
+#else
+ glMatrix.transpose();
+ glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix.getMatrix().data());
+#endif
+
+ glUniform4fv(m_RenderData.pCurrentMonData->m_shBORDER1.gradient, grad1.m_vColorsOkLabA.size(), (float*)grad1.m_vColorsOkLabA.data());
+ glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength, grad1.m_vColorsOkLabA.size() / 4);
+ glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.angle, (int)(grad1.m_fAngle / (PI / 180.0)) % 360 * (PI / 180.0));
+ glUniform4fv(m_RenderData.pCurrentMonData->m_shBORDER1.gradient2, grad2.m_vColorsOkLabA.size(), (float*)grad2.m_vColorsOkLabA.data());
+ glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradient2Length, grad2.m_vColorsOkLabA.size() / 4);
+ glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.angle2, (int)(grad2.m_fAngle / (PI / 180.0)) % 360 * (PI / 180.0));
+ glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a);
+ glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLerp, lerp);
CBox transformedBox = *box;
transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x,
@@ -2253,7 +2360,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr
g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, pFramebuffer);
- clear(CColor(0, 0, 0, 0)); // JIC
+ clear(CHyprColor(0, 0, 0, 0)); // JIC
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
@@ -2272,7 +2379,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr
m_RenderData.currentFB = pFramebuffer;
- clear(CColor(0, 0, 0, 0)); // JIC
+ clear(CHyprColor(0, 0, 0, 0)); // JIC
g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, false, RENDER_PASS_ALL, true);
@@ -2308,7 +2415,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(PHLWINDOW pWindow) {
g_pHyprRenderer->m_bRenderingSnapshot = true;
- clear(CColor(0, 0, 0, 0)); // JIC
+ clear(CHyprColor(0, 0, 0, 0)); // JIC
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
@@ -2322,7 +2429,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(PHLWINDOW pWindow) {
const auto BLURVAL = **PBLUR;
**PBLUR = 0;
- clear(CColor(0, 0, 0, 0)); // JIC
+ clear(CHyprColor(0, 0, 0, 0)); // JIC
g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders, RENDER_PASS_ALL);
@@ -2355,7 +2462,7 @@ void CHyprOpenGLImpl::makeLayerSnapshot(PHLLS pLayer) {
g_pHyprRenderer->m_bRenderingSnapshot = true;
- clear(CColor(0, 0, 0, 0)); // JIC
+ clear(CHyprColor(0, 0, 0, 0)); // JIC
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
@@ -2405,7 +2512,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLWINDOW pWindow) {
if (*PDIMAROUND && pWindow->m_sWindowData.dimAround.valueOrDefault()) {
CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y};
- g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * pWindow->m_fAlpha.value()));
+ g_pHyprOpenGL->renderRect(&monbox, CHyprColor(0, 0, 0, *PDIMAROUND * pWindow->m_fAlpha.value()));
g_pHyprRenderer->damageMonitor(PMONITOR);
}
@@ -2449,7 +2556,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLLS pLayer) {
m_bEndFrame = false;
}
-void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const CColor& color, float a) {
+void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const CHyprColor& color, float a) {
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(m_pCurrentWindow.lock(), "Tried to render shadow without a window!");
@@ -2568,7 +2675,7 @@ void CHyprOpenGLImpl::renderMirrored() {
.translate(-monitor->vecTransformedSize / 2.0);
// clear stuff outside of mirrored area (e.g. when changing to mirrored)
- clear(CColor(0, 0, 0, 0));
+ clear(CHyprColor(0, 0, 0, 0));
renderTexture(PFB->getTexture(), &monbox, 1.f, 0, false, false);
@@ -2583,7 +2690,7 @@ void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const
const auto FONTFAMILY = *PSPLASHFONT != STRVAL_EMPTY ? *PSPLASHFONT : *FALLBACKFONT;
const auto FONTSIZE = (int)(size.y / 76);
- const auto COLOR = CColor(*PSPLASHCOLOR);
+ const auto COLOR = CHyprColor(*PSPLASHCOLOR);
PangoLayout* layoutText = pango_cairo_create_layout(CAIRO);
PangoFontDescription* pangoFD = pango_font_description_new();
@@ -2671,7 +2778,7 @@ SP<CTexture> CHyprOpenGLImpl::loadAsset(const std::string& filename) {
return tex;
}
-SP<CTexture> CHyprOpenGLImpl::renderText(const std::string& text, CColor col, int pt, bool italic) {
+SP<CTexture> CHyprOpenGLImpl::renderText(const std::string& text, CHyprColor col, int pt, bool italic) {
SP<CTexture> tex = makeShared<CTexture>();
static auto FONT = CConfigValue<std::string>("misc:font_family");
@@ -2804,7 +2911,7 @@ void CHyprOpenGLImpl::initAssets() {
g_pCompositor->m_pAqBackend->hasSession() && g_pCompositor->m_pAqBackend->session->vt > 0 ?
std::to_string(g_pCompositor->m_pAqBackend->session->vt) :
"unknown"),
- CColor{0.9F, 0.9F, 0.9F, 0.7F}, 20, true);
+ CHyprColor{0.9F, 0.9F, 0.9F, 0.7F}, 20, true);
// create the default background texture
{
@@ -2889,7 +2996,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) {
CRegion fakeDamage{0, 0, INT16_MAX, INT16_MAX};
blend(true);
- clear(CColor{0, 0, 0, 1});
+ clear(CHyprColor{0, 0, 0, 1});
// first render the background
if (m_pBackgroundTexture) {
@@ -2981,7 +3088,7 @@ void CHyprOpenGLImpl::restoreMatrix() {
void CHyprOpenGLImpl::bindOffMain() {
m_RenderData.pCurrentMonData->offMainFB.bind();
- clear(CColor(0, 0, 0, 0));
+ clear(CHyprColor(0, 0, 0, 0));
m_RenderData.currentFB = &m_RenderData.pCurrentMonData->offMainFB;
}
diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp
index c594a7cc..6c0632dd 100644
--- a/src/render/OpenGL.hpp
+++ b/src/render/OpenGL.hpp
@@ -153,15 +153,16 @@ class CHyprOpenGLImpl {
void beginSimple(PHLMONITOR, const CRegion& damage, SP<CRenderbuffer> rb = nullptr, CFramebuffer* fb = nullptr);
void end();
- void renderRect(CBox*, const CColor&, int round = 0);
- void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f, bool xray = false);
- void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0);
+ void renderRect(CBox*, const CHyprColor&, int round = 0);
+ void renderRectWithBlur(CBox*, const CHyprColor&, int round = 0, float blurA = 1.f, bool xray = false);
+ void renderRectWithDamage(CBox*, const CHyprColor&, CRegion* damage, int round = 0);
void renderTexture(SP<CTexture>, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
void renderTextureWithDamage(SP<CTexture>, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, 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 renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0);
+ void renderRoundedShadow(CBox*, int round, 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&, const CGradientValueData&, float lerp, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */);
void renderTextureMatte(SP<CTexture> tex, CBox* pBox, CFramebuffer& matte);
void setMonitorTransformEnabled(bool enabled);
@@ -180,7 +181,7 @@ class CHyprOpenGLImpl {
void renderSnapshot(PHLLS);
bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow);
- void clear(const CColor&);
+ void clear(const CHyprColor&);
void clearWithTex();
void scissor(const CBox*, bool transform = true);
void scissor(const pixman_box32*, bool transform = true);
@@ -289,7 +290,7 @@ class CHyprOpenGLImpl {
void initEGL(bool gbm);
EGLDeviceEXT eglDeviceFromDRMFD(int drmFD);
SP<CTexture> loadAsset(const std::string& file);
- SP<CTexture> renderText(const std::string& text, CColor col, int pt, bool italic = false);
+ SP<CTexture> renderText(const std::string& text, CHyprColor col, int pt, bool italic = false);
void initAssets();
void initMissingAssetTexture();
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index bba133d9..7e44e64e 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -619,7 +619,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe
if (*PDIMAROUND && pWindow->m_sWindowData.dimAround.valueOrDefault() && !m_bRenderingSnapshot && mode != RENDER_PASS_POPUP) {
CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y};
- g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * renderdata.alpha * renderdata.fadeAlpha));
+ g_pHyprOpenGL->renderRect(&monbox, CHyprColor(0, 0, 0, *PDIMAROUND * renderdata.alpha * renderdata.fadeAlpha));
}
renderdata.x += pWindow->m_vFloatingOffset.x;
@@ -668,7 +668,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe
if (!pWindow->m_sWindowData.noBlur.valueOrDefault() && 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};
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, CHyprColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1, renderdata.fadeAlpha,
g_pHyprOpenGL->shouldUseNewBlurOptimizations(nullptr, pWindow));
renderdata.blur = false;
}
@@ -780,7 +780,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* tim
if (*PDIMAROUND && pLayer->dimAround && !m_bRenderingSnapshot && !popups) {
CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y};
- g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * pLayer->alpha.value()));
+ g_pHyprOpenGL->renderRect(&monbox, CHyprColor(0, 0, 0, *PDIMAROUND * pLayer->alpha.value()));
}
if (pLayer->fadingOut) {
@@ -919,7 +919,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA
g_pHyprOpenGL->blend(false);
if (!canSkipBackBufferClear(pMonitor)) {
if (*PRENDERTEX /* inverted cfg flag */)
- g_pHyprOpenGL->clear(CColor(*PBACKGROUNDCOLOR));
+ g_pHyprOpenGL->clear(CHyprColor(*PBACKGROUNDCOLOR));
else
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
}
@@ -959,7 +959,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA
g_pHyprOpenGL->blend(false);
if (!canSkipBackBufferClear(pMonitor)) {
if (*PRENDERTEX /* inverted cfg flag */)
- g_pHyprOpenGL->clear(CColor(*PBACKGROUNDCOLOR));
+ g_pHyprOpenGL->clear(CHyprColor(*PBACKGROUNDCOLOR));
else
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
}
@@ -995,12 +995,12 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA
if (*PDIMSPECIAL != 0.f) {
CBox monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale};
- g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMSPECIAL * (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS)));
+ g_pHyprOpenGL->renderRect(&monbox, CHyprColor(0, 0, 0, *PDIMSPECIAL * (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS)));
}
if (*PBLURSPECIAL && *PBLUR) {
CBox monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale};
- g_pHyprOpenGL->renderRectWithBlur(&monbox, CColor(0, 0, 0, 0), 0, (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS));
+ g_pHyprOpenGL->renderRectWithBlur(&monbox, CHyprColor(0, 0, 0, 0), 0, (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS));
}
break;
@@ -1447,7 +1447,7 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor) {
if (*PDAMAGEBLINK && damageBlinkCleanup == 0) {
CBox monrect = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y};
- g_pHyprOpenGL->renderRect(&monrect, CColor(1.0, 0.0, 1.0, 100.0 / 255.0), 0);
+ g_pHyprOpenGL->renderRect(&monrect, CHyprColor(1.0, 0.0, 1.0, 100.0 / 255.0), 0);
damageBlinkCleanup = 1;
} else if (*PDAMAGEBLINK) {
damageBlinkCleanup++;
@@ -2526,7 +2526,7 @@ std::tuple<float, float, float> CHyprRenderer::getRenderTimes(PHLMONITOR pMonito
static int handleCrashLoop(void* data) {
- g_pHyprNotificationOverlay->addNotification("Hyprland will crash in " + std::to_string(10 - (int)(g_pHyprRenderer->m_fCrashingDistort * 2.f)) + "s.", CColor(0), 5000,
+ g_pHyprNotificationOverlay->addNotification("Hyprland will crash in " + std::to_string(10 - (int)(g_pHyprRenderer->m_fCrashingDistort * 2.f)) + "s.", CHyprColor(0), 5000,
ICON_INFO);
g_pHyprRenderer->m_fCrashingDistort += 0.5f;
@@ -2540,7 +2540,7 @@ static int handleCrashLoop(void* data) {
}
void CHyprRenderer::initiateManualCrash() {
- g_pHyprNotificationOverlay->addNotification("Manual crash initiated. Farewell...", CColor(0), 5000, ICON_INFO);
+ g_pHyprNotificationOverlay->addNotification("Manual crash initiated. Farewell...", CHyprColor(0), 5000, ICON_INFO);
m_pCrashingLoop = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, handleCrashLoop, nullptr);
wl_event_source_timer_update(m_pCrashingLoop, 1000);
diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp
index d5a312c3..eaf9da96 100644
--- a/src/render/Shader.hpp
+++ b/src/render/Shader.hpp
@@ -38,9 +38,13 @@ class CShader {
GLint applyTint = -1;
GLint tint = -1;
- GLint gradient = -1;
- GLint gradientLength = -1;
- GLint angle = -1;
+ GLint gradient = -1;
+ GLint gradientLength = -1;
+ GLint angle = -1;
+ GLint gradient2 = -1;
+ GLint gradient2Length = -1;
+ GLint angle2 = -1;
+ GLint gradientLerp = -1;
float initialTime = 0;
GLint time = -1;
diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp
index d62e67c4..b0de4a64 100644
--- a/src/render/decorations/CHyprBorderDecoration.cpp
+++ b/src/render/decorations/CHyprBorderDecoration.cpp
@@ -60,7 +60,6 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) {
auto grad = m_pWindow->m_cRealBorderColor;
const bool ANIMATED = m_pWindow->m_fBorderFadeAnimationProgress.isBeingAnimated();
- float a1 = a * (ANIMATED ? m_pWindow->m_fBorderFadeAnimationProgress.value() : 1.f);
if (m_pWindow->m_fBorderAngleAnimationProgress.getConfig()->pValues->internalEnabled) {
grad.m_fAngle += m_pWindow->m_fBorderAngleAnimationProgress.value() * M_PI * 2;
@@ -70,12 +69,10 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) {
int borderSize = m_pWindow->getRealBorderSize();
const auto ROUNDING = m_pWindow->rounding() * pMonitor->scale;
- g_pHyprOpenGL->renderBorder(&windowBox, grad, ROUNDING, borderSize, a1);
-
- if (ANIMATED) {
- float a2 = a * (1.f - m_pWindow->m_fBorderFadeAnimationProgress.value());
- g_pHyprOpenGL->renderBorder(&windowBox, m_pWindow->m_cRealBorderColorPrevious, ROUNDING, borderSize, a2);
- }
+ if (ANIMATED)
+ g_pHyprOpenGL->renderBorder(&windowBox, m_pWindow->m_cRealBorderColorPrevious, grad, m_pWindow->m_fBorderFadeAnimationProgress.value(), ROUNDING, borderSize, a);
+ else
+ g_pHyprOpenGL->renderBorder(&windowBox, grad, ROUNDING, borderSize, a);
}
eDecorationType CHyprBorderDecoration::getDecorationType() {
diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp
index 893ad498..39398878 100644
--- a/src/render/decorations/CHyprDropShadowDecoration.cpp
+++ b/src/render/decorations/CHyprDropShadowDecoration.cpp
@@ -93,7 +93,7 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) {
if (!validMapped(PWINDOW))
return;
- if (PWINDOW->m_cRealShadowColor.value() == CColor(0, 0, 0, 0))
+ if (PWINDOW->m_cRealShadowColor.value() == CHyprColor(0, 0, 0, 0))
return; // don't draw invisible shadows
if (!PWINDOW->m_sWindowData.decorate.valueOrDefault())
@@ -181,13 +181,13 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) {
// build the matte
// 10-bit formats have dogshit alpha channels, so we have to use the matte to its fullest.
// first, clear region of interest with black (fully transparent)
- g_pHyprOpenGL->renderRect(&fullBox, CColor(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)
- drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CColor(1, 1, 1, PWINDOW->m_cRealShadowColor.value().a), a);
+ drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CHyprColor(1, 1, 1, PWINDOW->m_cRealShadowColor.value().a), a);
// render black window box ("clip")
- g_pHyprOpenGL->renderRect(&windowBox, CColor(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);
alphaSwapFB.bind();
@@ -215,7 +215,7 @@ eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() {
return DECORATION_LAYER_BOTTOM;
}
-void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, int range, CColor color, float a) {
+void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, int range, CHyprColor color, float a) {
static auto PSHADOWSHARP = CConfigValue<Hyprlang::INT>("decoration:shadow:sharp");
g_pHyprOpenGL->blend(true);
diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp
index 933ee0ef..650f8c92 100644
--- a/src/render/decorations/CHyprDropShadowDecoration.hpp
+++ b/src/render/decorations/CHyprDropShadowDecoration.hpp
@@ -34,7 +34,7 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration {
Vector2D m_vLastWindowPos;
Vector2D m_vLastWindowSize;
- void drawShadowInternal(CBox* box, int round, int range, CColor color, float a);
+ void drawShadowInternal(CBox* box, int round, int range, CHyprColor color, float a);
CBox m_bLastWindowBox = {0};
CBox m_bLastWindowBoxWithDecos = {0};
diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp
index b5189be5..937c913d 100644
--- a/src/render/decorations/CHyprGroupBarDecoration.cpp
+++ b/src/render/decorations/CHyprGroupBarDecoration.cpp
@@ -147,7 +147,7 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) {
const auto* const PCOLACTIVE = GROUPLOCKED ? GROUPCOLACTIVELOCKED : GROUPCOLACTIVE;
const auto* const PCOLINACTIVE = GROUPLOCKED ? GROUPCOLINACTIVELOCKED : GROUPCOLINACTIVE;
- CColor color = m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_pLastWindow.lock() ? PCOLACTIVE->m_vColors[0] : PCOLINACTIVE->m_vColors[0];
+ CHyprColor color = m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_pLastWindow.lock() ? PCOLACTIVE->m_vColors[0] : PCOLINACTIVE->m_vColors[0];
color.a *= a;
g_pHyprOpenGL->renderRect(&rect, color);
@@ -205,19 +205,19 @@ void CHyprGroupBarDecoration::invalidateTextures() {
}
CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float monitorScale) {
- tex = makeShared<CTexture>();
- szContent = pWindow->m_szTitle;
- pWindowOwner = pWindow;
- const auto LAYOUTSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
- const auto LAYOUTCAIRO = cairo_create(LAYOUTSURFACE);
-
- static auto FALLBACKFONT = CConfigValue<std::string>("misc:font_family");
- static auto PTITLEFONTFAMILY = CConfigValue<std::string>("group:groupbar:font_family");
- static auto PTITLEFONTSIZE = CConfigValue<Hyprlang::INT>("group:groupbar:font_size");
- static auto PTEXTCOLOR = CConfigValue<Hyprlang::INT>("group:groupbar:text_color");
-
- const CColor COLOR = CColor(*PTEXTCOLOR);
- const auto FONTFAMILY = *PTITLEFONTFAMILY != STRVAL_EMPTY ? *PTITLEFONTFAMILY : *FALLBACKFONT;
+ tex = makeShared<CTexture>();
+ szContent = pWindow->m_szTitle;
+ pWindowOwner = pWindow;
+ const auto LAYOUTSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
+ const auto LAYOUTCAIRO = cairo_create(LAYOUTSURFACE);
+
+ static auto FALLBACKFONT = CConfigValue<std::string>("misc:font_family");
+ static auto PTITLEFONTFAMILY = CConfigValue<std::string>("group:groupbar:font_family");
+ static auto PTITLEFONTSIZE = CConfigValue<Hyprlang::INT>("group:groupbar:font_size");
+ static auto PTEXTCOLOR = CConfigValue<Hyprlang::INT>("group:groupbar:text_color");
+
+ const CHyprColor COLOR = CHyprColor(*PTEXTCOLOR);
+ const auto FONTFAMILY = *PTITLEFONTFAMILY != STRVAL_EMPTY ? *PTITLEFONTFAMILY : *FALLBACKFONT;
cairo_surface_destroy(LAYOUTSURFACE);
diff --git a/src/render/shaders/Border.hpp b/src/render/shaders/Border.hpp
index 1f4a1d97..acd3f3ff 100644
--- a/src/render/shaders/Border.hpp
+++ b/src/render/shaders/Border.hpp
@@ -17,12 +17,32 @@ uniform float radius;
uniform float radiusOuter;
uniform float thick;
+// Gradients are in OkLabA!!!! {l, a, b, alpha}
uniform vec4 gradient[10];
+uniform vec4 gradient2[10];
uniform int gradientLength;
+uniform int gradient2Length;
uniform float angle;
+uniform float angle2;
+uniform float gradientLerp;
uniform float alpha;
-vec4 getColorForCoord(vec2 normalizedCoord) {
+float linearToGamma(float x) {
+ return x >= 0.0031308 ? 1.055 * pow(x, 0.416666666) - 0.055 : 12.92 * x;
+}
+
+vec4 okLabAToSrgb(vec4 lab) {
+ float l = pow(lab[0] + lab[1] * 0.3963377774 + lab[2] * 0.2158037573, 3.0);
+ float m = pow(lab[0] + lab[1] * (-0.1055613458) + lab[2] * (-0.0638541728), 3.0);
+ float s = pow(lab[0] + lab[1] * (-0.0894841775) + lab[2] * (-1.2914855480), 3.0);
+
+ return vec4(linearToGamma(l * 4.0767416621 + m * -3.3077115913 + s * 0.2309699292),
+ linearToGamma(l * (-1.2684380046) + m * 2.6097574011 + s * (-0.3413193965)),
+ linearToGamma(l * (-0.0041960863) + m * (-0.7034186147) + s * 1.7076147010),
+ lab[3]);
+}
+
+vec4 getOkColorForCoordArray1(vec2 normalizedCoord) {
if (gradientLength < 2)
return gradient[0];
@@ -51,6 +71,46 @@ vec4 getColorForCoord(vec2 normalizedCoord) {
return gradient[top] * (progress - float(bottom)) + gradient[bottom] * (float(top) - progress);
}
+vec4 getOkColorForCoordArray2(vec2 normalizedCoord) {
+ if (gradient2Length < 2)
+ return gradient2[0];
+
+ float finalAng = 0.0;
+
+ if (angle2 > 4.71 /* 270 deg */) {
+ normalizedCoord[1] = 1.0 - normalizedCoord[1];
+ finalAng = 6.28 - angle;
+ } else if (angle2 > 3.14 /* 180 deg */) {
+ normalizedCoord[0] = 1.0 - normalizedCoord[0];
+ normalizedCoord[1] = 1.0 - normalizedCoord[1];
+ finalAng = angle - 3.14;
+ } else if (angle2 > 1.57 /* 90 deg */) {
+ normalizedCoord[0] = 1.0 - normalizedCoord[0];
+ finalAng = 3.14 - angle2;
+ } else {
+ finalAng = angle2;
+ }
+
+ float sine = sin(finalAng);
+
+ float progress = (normalizedCoord[1] * sine + normalizedCoord[0] * (1.0 - sine)) * float(gradient2Length - 1);
+ int bottom = int(floor(progress));
+ int top = bottom + 1;
+
+ return gradient2[top] * (progress - float(bottom)) + gradient2[bottom] * (float(top) - progress);
+}
+
+vec4 getColorForCoord(vec2 normalizedCoord) {
+ vec4 result1 = getOkColorForCoordArray1(normalizedCoord);
+
+ if (gradient2Length <= 0)
+ return okLabAToSrgb(result1);
+
+ vec4 result2 = getOkColorForCoordArray2(normalizedCoord);
+
+ return okLabAToSrgb(mix(result1, result2, gradientLerp));
+}
+
void main() {
highp vec2 pixCoord = vec2(gl_FragCoord);