aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorvaxerski <[email protected]>2022-12-01 13:36:07 +0000
committervaxerski <[email protected]>2022-12-01 13:36:07 +0000
commit7b020ffa84e64d0734709b2489e1da5463689e61 (patch)
tree8d66b4951862fd67a1de828b7cfec75a6a2d6132
parentb8ccf3dc3a03352bccae4cd01dcdd5bc3438c49f (diff)
downloadHyprland-7b020ffa84e64d0734709b2489e1da5463689e61.tar.gz
Hyprland-7b020ffa84e64d0734709b2489e1da5463689e61.zip
Added screen shaders
-rw-r--r--example/screenShader.frag16
-rw-r--r--src/config/ConfigManager.cpp21
-rw-r--r--src/render/OpenGL.cpp143
-rw-r--r--src/render/OpenGL.hpp11
-rw-r--r--src/render/Shader.cpp6
-rw-r--r--src/render/Shader.hpp2
6 files changed, 159 insertions, 40 deletions
diff --git a/example/screenShader.frag b/example/screenShader.frag
new file mode 100644
index 00000000..5eeac17a
--- /dev/null
+++ b/example/screenShader.frag
@@ -0,0 +1,16 @@
+//
+// Example blue light filter shader.
+//
+
+precision mediump float;
+varying vec2 v_texcoord;
+uniform sampler2D tex;
+
+void main() {
+
+ vec4 pixColor = texture2D(tex, v_texcoord);
+
+ pixColor[2] *= 0.8;
+
+ gl_FragColor = pixColor;
+}
diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp
index 8834aff1..c9890d17 100644
--- a/src/config/ConfigManager.cpp
+++ b/src/config/ConfigManager.cpp
@@ -92,6 +92,7 @@ void CConfigManager::setDefaultVars() {
configValues["decoration:col.shadow_inactive"].intValue = INT_MAX;
configValues["decoration:dim_inactive"].intValue = 0;
configValues["decoration:dim_strength"].floatValue = 0.5f;
+ configValues["decoration:screen_shader"].strValue = STRVAL_EMPTY;
configValues["dwindle:pseudotile"].intValue = 0;
configValues["dwindle:col.group_border"].intValue = 0x66777700;
@@ -403,6 +404,21 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
}
}
}
+
+ if (COMMAND == "decoration:screen_shader") {
+ const auto PATH = absolutePath(VALUE, configCurrentPath);
+
+ configPaths.push_back(PATH);
+
+ struct stat fileStat;
+ int err = stat(PATH.c_str(), &fileStat);
+ if (err != 0) {
+ Debug::log(WARN, "Error at ticking config at %s, error %i: %s", PATH.c_str(), err, strerror(err));
+ return;
+ }
+
+ configModifyTimes[PATH] = fileStat.st_mtime;
+ }
}
void CConfigManager::handleRawExec(const std::string& command, const std::string& args) {
@@ -1230,6 +1246,9 @@ void CConfigManager::loadConfigLoadVars() {
// Calculate the internal vars
configValues["general:main_mod_internal"].intValue = g_pKeybindManager->stringToModMask(configValues["general:main_mod"].strValue);
+ if (!isFirstLaunch)
+ g_pHyprOpenGL->m_bReloadScreenShader = true;
+
// parseError will be displayed next frame
if (parseError != "")
g_pHyprError->queueCreate(parseError + "\nHyprland may not work correctly.", CColor(255, 50, 50, 255));
@@ -1652,6 +1671,8 @@ SAnimationPropertyConfig* CConfigManager::getAnimationPropertyConfig(const std::
void CConfigManager::addParseError(const std::string& err) {
if (parseError == "")
parseError = err;
+
+ g_pHyprError->queueCreate(parseError + "\nHyprland may not work correctly.", CColor(255, 50, 50, 255));
}
CMonitor* CConfigManager::getBoundMonitorForWS(std::string wsname) {
diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp
index bee6449b..b3914fde 100644
--- a/src/render/OpenGL.cpp
+++ b/src/render/OpenGL.cpp
@@ -30,12 +30,22 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT), "Couldn't unset current EGL!");
}
-GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string& frag) {
+GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string& frag, bool dynamic) {
auto vertCompiled = compileShader(GL_VERTEX_SHADER, vert);
- RASSERT(vertCompiled, "Compiling shader failed. VERTEX NULL! Shader source:\n\n%s", vert.c_str());
+ if (dynamic) {
+ if (vertCompiled == 0)
+ return 0;
+ } else {
+ RASSERT(vertCompiled, "Compiling shader failed. VERTEX NULL! Shader source:\n\n%s", vert.c_str());
+ }
auto fragCompiled = compileShader(GL_FRAGMENT_SHADER, frag);
- RASSERT(fragCompiled, "Compiling shader failed. FRAGMENT NULL! Shader source:\n\n%s", frag.c_str());
+ if (dynamic) {
+ if (fragCompiled == 0)
+ return 0;
+ } else {
+ RASSERT(fragCompiled, "Compiling shader failed. FRAGMENT NULL! Shader source:\n\n%s", frag.c_str());
+ }
auto prog = glCreateProgram();
glAttachShader(prog, vertCompiled);
@@ -49,12 +59,17 @@ GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string
GLint ok;
glGetProgramiv(prog, GL_LINK_STATUS, &ok);
- RASSERT(ok != GL_FALSE, "createProgram() failed! GL_LINK_STATUS not OK!");
+ if (dynamic) {
+ if (ok == GL_FALSE)
+ return 0;
+ } else {
+ RASSERT(ok != GL_FALSE, "createProgram() failed! GL_LINK_STATUS not OK!");
+ }
return prog;
}
-GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src) {
+GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool dynamic) {
auto shader = glCreateShader(type);
auto shaderSource = src.c_str();
@@ -64,7 +79,12 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src) {
GLint ok;
glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
- RASSERT(ok != GL_FALSE, "compileShader() failed! GL_COMPILE_STATUS not OK!");
+ if (dynamic) {
+ if (ok == GL_FALSE)
+ return 0;
+ } else {
+ RASSERT(ok != GL_FALSE, "compileShader() failed! GL_COMPILE_STATUS not OK!");
+ }
return shader;
}
@@ -112,6 +132,11 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool
m_RenderData.pDamage = pDamage;
m_bFakeFrame = fake;
+
+ if (m_bReloadScreenShader) {
+ m_bReloadScreenShader = false;
+ applyScreenShader(g_pConfigManager->getString("decoration:screen_shader"));
+ }
}
void CHyprOpenGLImpl::end() {
@@ -128,9 +153,11 @@ void CHyprOpenGLImpl::end() {
clear(CColor(11, 11, 11, 255));
m_bEndFrame = true;
+ m_bApplyFinalShader = true;
renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 255.f, 0);
+ m_bApplyFinalShader = false;
m_bEndFrame = false;
}
@@ -250,6 +277,35 @@ void CHyprOpenGLImpl::initShaders() {
Debug::log(LOG, "Shaders initialized successfully.");
}
+void CHyprOpenGLImpl::applyScreenShader(const std::string& path) {
+
+ m_sFinalScreenShader.destroy();
+
+ if (path == "" || path == STRVAL_EMPTY)
+ return;
+
+ std::ifstream infile(absolutePath(path, std::string(getenv("HOME")) + "/.config/hypr"));
+
+ if (!infile.good()) {
+ g_pConfigManager->addParseError("Screen shader parser: Screen shader path not found");
+ return;
+ }
+
+ std::string fragmentShader((std::istreambuf_iterator<char>(infile)), (std::istreambuf_iterator<char>()));
+
+ m_sFinalScreenShader.program = createProgram(TEXVERTSRC, fragmentShader, true);
+
+ if (!m_sFinalScreenShader.program) {
+ g_pConfigManager->addParseError("Screen shader parser: Screen shader parse failed");
+ return;
+ }
+
+ m_sFinalScreenShader.proj = glGetUniformLocation(m_sFinalScreenShader.program, "proj");
+ m_sFinalScreenShader.tex = glGetUniformLocation(m_sFinalScreenShader.program, "tex");
+ m_sFinalScreenShader.texAttrib = glGetAttribLocation(m_sFinalScreenShader.program, "texcoord");
+ m_sFinalScreenShader.posAttrib = glGetAttribLocation(m_sFinalScreenShader.program, "pos");
+}
+
void CHyprOpenGLImpl::clear(const CColor& color) {
RASSERT(m_RenderData.pMonitor, "Tried to render without begin()!");
@@ -420,18 +476,25 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- switch (tex.m_iType) {
- case TEXTURE_RGBA:
- shader = &m_RenderData.pCurrentMonData->m_shRGBA;
- break;
- case TEXTURE_RGBX:
- shader = &m_RenderData.pCurrentMonData->m_shRGBX;
- break;
- case TEXTURE_EXTERNAL:
- shader = &m_RenderData.pCurrentMonData->m_shEXT;
- break;
- default:
- RASSERT(false, "tex.m_iTarget unsupported!");
+ bool usingFinalShader = false;
+
+ if (m_bApplyFinalShader && m_sFinalScreenShader.program) {
+ shader = &m_sFinalScreenShader;
+ usingFinalShader = true;
+ } else {
+ switch (tex.m_iType) {
+ case TEXTURE_RGBA:
+ shader = &m_RenderData.pCurrentMonData->m_shRGBA;
+ break;
+ case TEXTURE_RGBX:
+ shader = &m_RenderData.pCurrentMonData->m_shRGBX;
+ break;
+ case TEXTURE_EXTERNAL:
+ shader = &m_RenderData.pCurrentMonData->m_shEXT;
+ break;
+ default:
+ RASSERT(false, "tex.m_iTarget unsupported!");
+ }
}
glActiveTexture(GL_TEXTURE0);
@@ -448,8 +511,10 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix);
#endif
glUniform1i(shader->tex, 0);
- glUniform1f(shader->alpha, alpha / 255.f);
- glUniform1i(shader->discardOpaque, (int)discardOpaque);
+ if (!usingFinalShader) {
+ glUniform1f(shader->alpha, alpha / 255.f);
+ glUniform1i(shader->discardOpaque, (int)discardOpaque);
+ }
wlr_box transformedBox;
wlr_box_transform(&transformedBox, pBox, wlr_output_transform_invert(m_RenderData.pMonitor->transform),
@@ -459,18 +524,20 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height);
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
- // Rounded corners
- glUniform2f(shader->topLeft, TOPLEFT.x, TOPLEFT.y);
- glUniform2f(shader->fullSize, FULLSIZE.x ,FULLSIZE.y);
- glUniform1f(shader->radius, round);
- glUniform1i(shader->primitiveMultisample, (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !noAA));
-
- if (allowDim && m_pCurrentWindow && *PDIMINACTIVE && m_pCurrentWindow != g_pCompositor->m_pLastWindow) {
- glUniform1i(shader->applyTint, 1);
- const auto DIM = m_pCurrentWindow->m_fDimPercent.fl();
- glUniform3f(shader->tint, 1.f - DIM, 1.f - DIM, 1.f - DIM);
- } else {
- glUniform1i(shader->applyTint, 0);
+ if (!usingFinalShader) {
+ // Rounded corners
+ glUniform2f(shader->topLeft, TOPLEFT.x, TOPLEFT.y);
+ glUniform2f(shader->fullSize, FULLSIZE.x, FULLSIZE.y);
+ glUniform1f(shader->radius, round);
+ glUniform1i(shader->primitiveMultisample, (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !noAA));
+
+ if (allowDim && m_pCurrentWindow && *PDIMINACTIVE && m_pCurrentWindow != g_pCompositor->m_pLastWindow) {
+ glUniform1i(shader->applyTint, 1);
+ const auto DIM = m_pCurrentWindow->m_fDimPercent.fl();
+ glUniform3f(shader->tint, 1.f - DIM, 1.f - DIM, 1.f - DIM);
+ } else {
+ glUniform1i(shader->applyTint, 0);
+ }
}
const float verts[] = {
@@ -504,13 +571,13 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
}
}
- pixman_region32_fini(&damageClip);
+ pixman_region32_fini(&damageClip);
} else {
- PIXMAN_DAMAGE_FOREACH(damage) {
- const auto RECT = RECTSARR[i];
- scissor(&RECT);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- }
+ PIXMAN_DAMAGE_FOREACH(damage) {
+ const auto RECT = RECTSARR[i];
+ scissor(&RECT);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ }
}
glDisableVertexAttribArray(shader->posAttrib);
diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp
index e54b76aa..fabd3666 100644
--- a/src/render/OpenGL.hpp
+++ b/src/render/OpenGL.hpp
@@ -111,11 +111,15 @@ public:
void onWindowResizeStart(CWindow*);
void onWindowResizeEnd(CWindow*);
+ void applyScreenShader(const std::string& path);
+
SCurrentRenderData m_RenderData;
GLint m_iCurrentOutputFb = 0;
GLint m_iWLROutputFb = 0;
+ bool m_bReloadScreenShader = true; // at launch it can be set
+
CWindow* m_pCurrentWindow = nullptr; // hack to get the current rendered window
pixman_region32_t m_rOriginalDamageRegion; // used for storing the pre-expanded region
@@ -134,9 +138,12 @@ private:
bool m_bFakeFrame = false;
bool m_bEndFrame = false;
+ bool m_bApplyFinalShader = false;
+
+ CShader m_sFinalScreenShader;
- GLuint createProgram(const std::string&, const std::string&);
- GLuint compileShader(const GLuint&, std::string);
+ GLuint createProgram(const std::string&, const std::string&, bool dynamic = false);
+ GLuint compileShader(const GLuint&, std::string, bool dynamic = false);
void createBGTextureForMonitor(CMonitor*);
void initShaders();
diff --git a/src/render/Shader.cpp b/src/render/Shader.cpp
index f965e681..03b13055 100644
--- a/src/render/Shader.cpp
+++ b/src/render/Shader.cpp
@@ -14,5 +14,11 @@ GLint CShader::getUniformLocation(const std::string& unif) {
CShader::~CShader() {
// destroy shader
+ destroy();
+
+ program = 0;
+}
+
+void CShader::destroy() {
glDeleteProgram(program);
} \ No newline at end of file
diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp
index c9c63725..f107bb6d 100644
--- a/src/render/Shader.hpp
+++ b/src/render/Shader.hpp
@@ -39,6 +39,8 @@ public:
GLint getUniformLocation(const std::string&);
+ void destroy();
+
private:
std::unordered_map<std::string, GLint> m_muUniforms;
}; \ No newline at end of file