diff options
Diffstat (limited to 'opengl.c')
-rw-r--r-- | opengl.c | 113 |
1 files changed, 89 insertions, 24 deletions
@@ -140,6 +140,14 @@ glx_init_end: */ void glx_destroy(session_t *ps) { +#ifdef CONFIG_VSYNC_OPENGL_GLSL + // Free GLSL shaders/programs + if (ps->glx_frag_shader_blur) + glDeleteShader(ps->glx_frag_shader_blur); + if (ps->glx_prog_blur) + glDeleteProgram(ps->glx_prog_blur); +#endif + // Free FBConfigs for (int i = 0; i <= OPENGL_MAX_DEPTH; ++i) { free(ps->glx_fbconfigs[i]); @@ -173,20 +181,66 @@ glx_on_root_change(session_t *ps) { */ bool glx_init_blur(session_t *ps) { - printf_errf("(): Blur on GLX backend isn't implemented yet, sorry."); - return false; +#ifdef CONFIG_VSYNC_OPENGL_GLSL + if (ps->o.glx_no_stencil) { + printf_errf("(): I'm afraid blur background won't work so well without " + "stencil buffer support."); + return false; + } + + // 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); + if (!ps->glx_frag_shader_blur) { + printf_errf("(): Failed to create fragment shader."); + return false; + } + + ps->glx_prog_blur = glx_create_program(&ps->glx_frag_shader_blur, 1); + if (!ps->glx_prog_blur) { + printf_errf("(): Failed to create GLSL program."); + return false; + } + +#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; \ + } \ +} + + P_GET_UNIFM_LOC("factor_center", glx_prog_blur_unifm_factor_center); + P_GET_UNIFM_LOC("offset_x", glx_prog_blur_unifm_offset_x); + P_GET_UNIFM_LOC("offset_y", glx_prog_blur_unifm_offset_y); -// #ifdef CONFIG_VSYNC_OPENGL_GLSL -// static const char *FRAG_SHADER_BLUR = ""; -// GLuint frag_shader = glx_create_shader(GL_FRAGMENT_SHADER, FRAG_SHADER_BLUR); -// if (!frag_shader) { -// printf_errf("(): Failed to create fragment shader for blurring."); -// return false; -// } -// #else -// printf_errf("(): GLSL support not compiled in. Cannot do blur with GLX backend."); -// return false; -// #endif +#undef P_GET_UNIFM_LOC + + return true; +#else + printf_errf("(): GLSL support not compiled in. Cannot do blur with GLX backend."); + return false; +#endif } /** @@ -590,7 +644,8 @@ glx_set_clip(session_t *ps, XserverRegion reg) { } bool -glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z) { +glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z, + GLfloat factor_center) { // Read destination pixels into a texture GLuint tex_scr = 0; glGenTextures(1, &tex_scr); @@ -617,10 +672,18 @@ glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z) { #endif // Paint it back - // TODO: Blur function. We are using color negation for testing now. - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); - glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR); + // Color negation for testing... + // glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + // glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); + // glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR); + + 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); +#endif glBegin(GL_QUADS); @@ -653,6 +716,9 @@ glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z) { glEnd(); +#ifdef CONFIG_VSYNC_OPENGL_GLSL + glUseProgram(0); +#endif glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glBindTexture(tex_tgt, 0); glDeleteTextures(1, &tex_scr); @@ -668,8 +734,6 @@ bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx, int dy, int width, int height, int z, double opacity, bool neg, XserverRegion reg_tgt) { - bool blur_background = false; - if (!ptex || !ptex->texture) { printf_errf("(): Missing texture."); return false; @@ -678,8 +742,6 @@ glx_render(session_t *ps, const glx_texture_t *ptex, // Enable blending if needed if (opacity < 1.0 || GLX_TEXTURE_FORMAT_RGBA_EXT == ps->glx_fbconfigs[ptex->depth]->texture_fmt) { - if (!ps->o.glx_no_stencil && blur_background) - glx_blur_dst(ps, dx, dy, width, height, z - 0.5); glEnable(GL_BLEND); @@ -832,8 +894,7 @@ glx_create_shader_end: } GLuint -glx_create_program(GLenum shader_type, const GLuint * const shaders, - int nshaders) { +glx_create_program(const GLuint * const shaders, int nshaders) { bool success = false; GLuint program = glCreateProgram(); if (!program) { @@ -863,6 +924,10 @@ glx_create_program(GLenum shader_type, const GLuint * const shaders, success = true; glx_create_program_end: + if (program) { + for (int i = 0; i < nshaders; ++i) + glDetachShader(program, shaders[i]); + } if (program && !success) { glDeleteProgram(program); program = 0; |