summaryrefslogtreecommitdiffstats
path: root/opengl.c
diff options
context:
space:
mode:
authorRichard Grenville <pyxlcy@gmail.com>2013-04-25 22:23:35 +0800
committerRichard Grenville <pyxlcy@gmail.com>2013-04-25 22:23:35 +0800
commitec2cd6276d6b137b946a48f4dffaaecd793bff0f (patch)
treef86d5b631925c34076115bafc3dfd673046e2b23 /opengl.c
parent1dd41253b22c78bf3cd4497895c906fe07cb209b (diff)
downloadtdebase-ec2cd6276d6b137b946a48f4dffaaecd793bff0f.tar.gz
tdebase-ec2cd6276d6b137b946a48f4dffaaecd793bff0f.zip
Improvement: --blur-kern
- Add blur convolution kernel customization, --blur-kern. The format is a bit tricky so be sure to read the description in `compton -h`. Not much tests received. - GLX backend: Tolerate missing GLSL uniforms for strangely shaped convolution kernel. - Fix a memory leak that blur-background blacklist is not freed.
Diffstat (limited to 'opengl.c')
-rw-r--r--opengl.c88
1 files changed, 61 insertions, 27 deletions
diff --git a/opengl.c b/opengl.c
index eb65e4f4c..50f64f529 100644
--- a/opengl.c
+++ b/opengl.c
@@ -191,28 +191,60 @@ bool
glx_init_blur(session_t *ps) {
#ifdef CONFIG_VSYNC_OPENGL_GLSL
// Build shader
- static const char *FRAG_SHADER_BLUR =
- "#version 110\n"
- "uniform float offset_x;\n"
- "uniform float offset_y;\n"
- "uniform float factor_center;\n"
- "uniform sampler2D tex_scr;\n"
- "\n"
- "void main() {\n"
- " vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n"
- " sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x - offset_x, gl_TexCoord[0].y - offset_y));\n"
- " sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x - offset_x, gl_TexCoord[0].y));\n"
- " sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x - offset_x, gl_TexCoord[0].y + offset_y));\n"
- " sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y - offset_y));\n"
- " sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y)) * factor_center;\n"
- " sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y + offset_y));\n"
- " sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x + offset_x, gl_TexCoord[0].y - offset_y));\n"
- " sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x + offset_x, gl_TexCoord[0].y));\n"
- " sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x + offset_x, gl_TexCoord[0].y + offset_y));\n"
- " gl_FragColor = sum / (factor_center + 8.0);\n"
- "}\n"
- ;
- ps->glx_frag_shader_blur = glx_create_shader(GL_FRAGMENT_SHADER, FRAG_SHADER_BLUR);
+ {
+ static const char *FRAG_SHADER_BLUR_PREFIX =
+ "#version 110\n"
+ "uniform float offset_x;\n"
+ "uniform float offset_y;\n"
+ "uniform float factor_center;\n"
+ "uniform sampler2D tex_scr;\n"
+ "\n"
+ "void main() {\n"
+ " vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n";
+ static const char *FRAG_SHADER_BLUR_ADD =
+ " sum += float(%.7g) * texture2D(tex_scr, vec2(gl_TexCoord[0].x + offset_x * float(%d), gl_TexCoord[0].y + offset_y * float(%d)));\n";
+ static const char *FRAG_SHADER_BLUR_SUFFIX =
+ " sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y)) * factor_center;\n"
+ " gl_FragColor = sum / (factor_center + float(%.7g));\n"
+ "}\n";
+ int wid = XFixedToDouble(ps->o.blur_kern[0]), hei = XFixedToDouble(ps->o.blur_kern[1]);
+ int nele = wid * hei - 1;
+ int len = strlen(FRAG_SHADER_BLUR_PREFIX) + (strlen(FRAG_SHADER_BLUR_ADD) + 42) * nele
+ + strlen(FRAG_SHADER_BLUR_SUFFIX) + 12 + 1;
+ char *shader_str = calloc(len, sizeof(char));
+ if (!shader_str) {
+ printf_errf("(): Failed to allocate %d bytes for shader string.", len);
+ return false;
+ }
+ {
+ char *pc = shader_str;
+ strcpy(pc, FRAG_SHADER_BLUR_PREFIX);
+ pc += strlen(FRAG_SHADER_BLUR_PREFIX);
+ assert(strlen(shader_str) < len);
+
+ double sum = 0.0;
+ for (int i = 0; i < hei; ++i) {
+ for (int j = 0; j < wid; ++j) {
+ if (hei / 2 == i && wid / 2 == j)
+ continue;
+ double val = XFixedToDouble(ps->o.blur_kern[2 + i * wid + j]);
+ sum += val;
+ sprintf(pc, FRAG_SHADER_BLUR_ADD, val, j - wid / 2, i - hei / 2);
+ pc += strlen(pc);
+ assert(strlen(shader_str) < len);
+ }
+ }
+
+ sprintf(pc, FRAG_SHADER_BLUR_SUFFIX, sum);
+ assert(strlen(shader_str) < len);
+#ifdef DEBUG_GLX_GLSL
+ fputs(shader_str, stdout);
+ fflush(stdout);
+#endif
+ }
+ ps->glx_frag_shader_blur = glx_create_shader(GL_FRAGMENT_SHADER, shader_str);
+ }
+
if (!ps->glx_frag_shader_blur) {
printf_errf("(): Failed to create fragment shader.");
return false;
@@ -227,8 +259,7 @@ glx_init_blur(session_t *ps) {
#define P_GET_UNIFM_LOC(name, target) { \
ps->target = glGetUniformLocation(ps->glx_prog_blur, name); \
if (ps->target < 0) { \
- printf_errf("(): Failed to get location of uniform '" name "'."); \
- return false; \
+ printf_errf("(): Failed to get location of uniform '" name "'. Might be troublesome."); \
} \
}
@@ -759,9 +790,12 @@ glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
#ifdef CONFIG_VSYNC_OPENGL_GLSL
glUseProgram(ps->glx_prog_blur);
- glUniform1f(ps->glx_prog_blur_unifm_offset_x, 1.0f / width);
- glUniform1f(ps->glx_prog_blur_unifm_offset_y, 1.0f / height);
- glUniform1f(ps->glx_prog_blur_unifm_factor_center, factor_center);
+ if (ps->glx_prog_blur_unifm_offset_x >= 0)
+ glUniform1f(ps->glx_prog_blur_unifm_offset_x, 1.0f / width);
+ if (ps->glx_prog_blur_unifm_offset_y >= 0)
+ glUniform1f(ps->glx_prog_blur_unifm_offset_y, 1.0f / height);
+ if (ps->glx_prog_blur_unifm_factor_center >= 0)
+ glUniform1f(ps->glx_prog_blur_unifm_factor_center, factor_center);
#endif
{