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.
This commit is contained in:
parent
4a4f857cc2
commit
2e6fb0203d
2
Makefile
2
Makefile
|
@ -80,7 +80,7 @@ else
|
||||||
export LD_ALTEXEC = /usr/bin/ld.gold
|
export LD_ALTEXEC = /usr/bin/ld.gold
|
||||||
OBJS += backtrace-symbols.o
|
OBJS += backtrace-symbols.o
|
||||||
LIBS += -lbfd
|
LIBS += -lbfd
|
||||||
CFLAGS += -ggdb
|
CFLAGS += -ggdb -Wshadow
|
||||||
# CFLAGS += -Weverything -Wno-disabled-macro-expansion -Wno-padded -Wno-gnu
|
# CFLAGS += -Weverything -Wno-disabled-macro-expansion -Wno-padded -Wno-gnu
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -483,6 +483,8 @@ typedef struct {
|
||||||
bool blur_background_fixed;
|
bool blur_background_fixed;
|
||||||
/// Background blur blacklist. A linked list of conditions.
|
/// Background blur blacklist. A linked list of conditions.
|
||||||
c2_lptr_t *blur_background_blacklist;
|
c2_lptr_t *blur_background_blacklist;
|
||||||
|
/// Blur convolution kernel.
|
||||||
|
XFixed *blur_kern;
|
||||||
/// How much to dim an inactive window. 0.0 - 1.0, 0 to disable.
|
/// How much to dim an inactive window. 0.0 - 1.0, 0 to disable.
|
||||||
double inactive_dim;
|
double inactive_dim;
|
||||||
/// Whether to use fixed inactive dim opacity, instead of deciding
|
/// Whether to use fixed inactive dim opacity, instead of deciding
|
||||||
|
|
193
src/compton.c
193
src/compton.c
|
@ -9,6 +9,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "compton.h"
|
#include "compton.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
// === Global constants ===
|
// === Global constants ===
|
||||||
|
|
||||||
|
@ -1348,21 +1349,6 @@ win_blur_background(session_t *ps, win *w, Picture tgt_buffer,
|
||||||
switch (ps->o.backend) {
|
switch (ps->o.backend) {
|
||||||
case BKEND_XRENDER:
|
case BKEND_XRENDER:
|
||||||
{
|
{
|
||||||
const static int convolution_blur_size = 3;
|
|
||||||
// Convolution filter parameter (box blur)
|
|
||||||
// gaussian or binomial filters are definitely superior, yet looks
|
|
||||||
// like they aren't supported as of xorg-server-1.13.0
|
|
||||||
XFixed convolution_blur[] = {
|
|
||||||
// Must convert to XFixed with XDoubleToFixed()
|
|
||||||
// Matrix size
|
|
||||||
XDoubleToFixed(convolution_blur_size),
|
|
||||||
XDoubleToFixed(convolution_blur_size),
|
|
||||||
// Matrix
|
|
||||||
XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1),
|
|
||||||
XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1),
|
|
||||||
XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Directly copying from tgt_buffer does not work, so we create a
|
// Directly copying from tgt_buffer does not work, so we create a
|
||||||
// Picture in the middle.
|
// Picture in the middle.
|
||||||
Picture tmp_picture = win_build_picture(ps, w, NULL);
|
Picture tmp_picture = win_build_picture(ps, w, NULL);
|
||||||
|
@ -1370,7 +1356,12 @@ win_blur_background(session_t *ps, win *w, Picture tgt_buffer,
|
||||||
if (!tmp_picture)
|
if (!tmp_picture)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
convolution_blur[2 + convolution_blur_size + ((convolution_blur_size - 1) / 2)] = XDoubleToFixed(factor_center);
|
XFixed *convolution_blur = ps->o.blur_kern;
|
||||||
|
int kwid = XFixedToDouble((ps->o.blur_kern[0])),
|
||||||
|
khei = XFixedToDouble((ps->o.blur_kern[1]));
|
||||||
|
|
||||||
|
// Modify the factor of the center pixel
|
||||||
|
convolution_blur[2 + (khei / 2) * kwid + kwid / 2] = XDoubleToFixed(factor_center);
|
||||||
|
|
||||||
// Minimize the region we try to blur, if the window itself is not
|
// Minimize the region we try to blur, if the window itself is not
|
||||||
// opaque, only the frame is.
|
// opaque, only the frame is.
|
||||||
|
@ -1386,7 +1377,7 @@ win_blur_background(session_t *ps, win *w, Picture tgt_buffer,
|
||||||
// Copy the content to tmp_picture, then copy back. The filter must
|
// Copy the content to tmp_picture, then copy back. The filter must
|
||||||
// be applied on tgt_buffer, to get the nearby pixels outside the
|
// be applied on tgt_buffer, to get the nearby pixels outside the
|
||||||
// window.
|
// window.
|
||||||
XRenderSetPictureFilter(ps->dpy, tgt_buffer, XRFILTER_CONVOLUTION, (XFixed *) convolution_blur, sizeof(convolution_blur) / sizeof(XFixed));
|
XRenderSetPictureFilter(ps->dpy, tgt_buffer, XRFILTER_CONVOLUTION, convolution_blur, kwid * khei + 2);
|
||||||
XRenderComposite(ps->dpy, PictOpSrc, tgt_buffer, None, tmp_picture, x, y, 0, 0, 0, 0, wid, hei);
|
XRenderComposite(ps->dpy, PictOpSrc, tgt_buffer, None, tmp_picture, x, y, 0, 0, 0, 0, wid, hei);
|
||||||
xrfilter_reset(ps, tgt_buffer);
|
xrfilter_reset(ps, tgt_buffer);
|
||||||
XRenderComposite(ps->dpy, PictOpSrc, tmp_picture, None, tgt_buffer, 0, 0, 0, 0, x, y, wid, hei);
|
XRenderComposite(ps->dpy, PictOpSrc, tmp_picture, None, tgt_buffer, 0, 0, 0, 0, x, y, wid, hei);
|
||||||
|
@ -1665,10 +1656,18 @@ paint_all(session_t *ps, XserverRegion region, win *t) {
|
||||||
XFixesSetPictureClipRegion(ps->dpy, ps->tgt_picture, 0, 0, region);
|
XFixesSetPictureClipRegion(ps->dpy, ps->tgt_picture, 0, 0, region);
|
||||||
|
|
||||||
#ifdef MONITOR_REPAINT
|
#ifdef MONITOR_REPAINT
|
||||||
XRenderComposite(
|
switch (ps->o.backend) {
|
||||||
ps->dpy, PictOpSrc, ps->black_picture, None,
|
case BKEND_XRENDER:
|
||||||
ps->tgt_picture, 0, 0, 0, 0, 0, 0,
|
XRenderComposite(ps->dpy, PictOpSrc, ps->black_picture, None,
|
||||||
ps->root_width, ps->root_height);
|
ps->tgt_picture, 0, 0, 0, 0, 0, 0,
|
||||||
|
ps->root_width, ps->root_height);
|
||||||
|
break;
|
||||||
|
case BKEND_GLX:
|
||||||
|
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (t && t->reg_ignore) {
|
if (t && t->reg_ignore) {
|
||||||
|
@ -4234,6 +4233,14 @@ usage(void) {
|
||||||
"--blur-background-fixed\n"
|
"--blur-background-fixed\n"
|
||||||
" Use fixed blur strength instead of adjusting according to window\n"
|
" Use fixed blur strength instead of adjusting according to window\n"
|
||||||
" opacity.\n"
|
" opacity.\n"
|
||||||
|
"--blur-kern matrix\n"
|
||||||
|
" Specify the blur convolution kernel, with the following format:\n"
|
||||||
|
" WIDTH,HEIGHT,ELE1,ELE2,ELE3,ELE4,ELE5...\n"
|
||||||
|
" The element in the center must not be included, it will be forever\n"
|
||||||
|
" 1.0 or changing based on opacity, depending on whether you have\n"
|
||||||
|
" --blur-background-fixed.\n"
|
||||||
|
" A 7x7 Guassian blur kernel looks like:\n"
|
||||||
|
" --blur-kern '7,7,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000102,0.003494,0.029143,0.059106,0.029143,0.003494,0.000102,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.001723,0.059106,0.493069,0.493069,0.059106,0.001723,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.000102,0.003494,0.029143,0.059106,0.029143,0.003494,0.000102,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003'\n"
|
||||||
"--blur-background-exclude condition\n"
|
"--blur-background-exclude condition\n"
|
||||||
" Exclude conditions for background blur.\n"
|
" Exclude conditions for background blur.\n"
|
||||||
"--invert-color-include condition\n"
|
"--invert-color-include condition\n"
|
||||||
|
@ -4476,10 +4483,113 @@ open_config_file(char *cpath, char **ppath) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a floating-point number in matrix.
|
||||||
|
*/
|
||||||
|
static inline const char *
|
||||||
|
parse_matrix_readnum(const char *src, double *dest) {
|
||||||
|
char *pc = NULL;
|
||||||
|
double val = strtod(src, &pc);
|
||||||
|
if (!pc || pc == src) {
|
||||||
|
printf_errf("(\"%s\"): No number found.", src);
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*pc && (isspace(*pc) || ',' == *pc))
|
||||||
|
++pc;
|
||||||
|
|
||||||
|
*dest = val;
|
||||||
|
|
||||||
|
return pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a matrix.
|
||||||
|
*/
|
||||||
|
static inline XFixed *
|
||||||
|
parse_matrix(session_t *ps, const char *src) {
|
||||||
|
int wid = 0, hei = 0;
|
||||||
|
const char *pc = NULL;
|
||||||
|
XFixed *matrix = NULL;
|
||||||
|
|
||||||
|
// Get matrix width and height
|
||||||
|
{
|
||||||
|
double val = 0.0;
|
||||||
|
if (src == (pc = parse_matrix_readnum(src, &val)))
|
||||||
|
goto parse_matrix_err;
|
||||||
|
src = pc;
|
||||||
|
wid = val;
|
||||||
|
if (src == (pc = parse_matrix_readnum(src, &val)))
|
||||||
|
goto parse_matrix_err;
|
||||||
|
src = pc;
|
||||||
|
hei = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate matrix width and height
|
||||||
|
if (wid <= 0 || hei <= 0) {
|
||||||
|
printf_errf("(): Invalid matrix width/height.");
|
||||||
|
goto parse_matrix_err;
|
||||||
|
}
|
||||||
|
if (!(wid % 2 && hei % 2)) {
|
||||||
|
printf_errf("(): Width/height not odd.");
|
||||||
|
goto parse_matrix_err;
|
||||||
|
}
|
||||||
|
if (wid > 16 || hei > 16) {
|
||||||
|
printf_errf("(): Matrix width/height too large.");
|
||||||
|
goto parse_matrix_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate memory
|
||||||
|
matrix = calloc(wid * hei + 2, sizeof(XFixed));
|
||||||
|
if (!matrix) {
|
||||||
|
printf_errf("(): Failed to allocate memory for matrix.");
|
||||||
|
goto parse_matrix_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read elements
|
||||||
|
{
|
||||||
|
int skip = hei / 2 * wid + wid / 2;
|
||||||
|
bool hasneg = false;
|
||||||
|
for (int i = 0; i < wid * hei; ++i) {
|
||||||
|
// Ignore the center element
|
||||||
|
if (i == skip) {
|
||||||
|
matrix[2 + i] = XDoubleToFixed(0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
double val = 0;
|
||||||
|
if (src == (pc = parse_matrix_readnum(src, &val)))
|
||||||
|
goto parse_matrix_err;
|
||||||
|
src = pc;
|
||||||
|
if (val < 0) hasneg = true;
|
||||||
|
matrix[2 + i] = XDoubleToFixed(val);
|
||||||
|
}
|
||||||
|
if (BKEND_XRENDER == ps->o.backend && hasneg)
|
||||||
|
printf_errf("(): A convolution kernel with negative values "
|
||||||
|
"may not work properly under X Render backend.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect trailing characters
|
||||||
|
for ( ;*pc; ++pc)
|
||||||
|
if (!isspace(*pc) && ',' != *pc) {
|
||||||
|
printf_errf("(): Trailing characters in matrix string.");
|
||||||
|
goto parse_matrix_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in width and height
|
||||||
|
matrix[0] = XDoubleToFixed(wid);
|
||||||
|
matrix[1] = XDoubleToFixed(hei);
|
||||||
|
|
||||||
|
return matrix;
|
||||||
|
|
||||||
|
parse_matrix_err:
|
||||||
|
free(matrix);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a condition list in configuration file.
|
* Parse a condition list in configuration file.
|
||||||
*/
|
*/
|
||||||
static void
|
static inline void
|
||||||
parse_cfg_condlst(session_t *ps, const config_t *pcfg, c2_lptr_t **pcondlst,
|
parse_cfg_condlst(session_t *ps, const config_t *pcfg, c2_lptr_t **pcondlst,
|
||||||
const char *name) {
|
const char *name) {
|
||||||
config_setting_t *setting = config_lookup(pcfg, name);
|
config_setting_t *setting = config_lookup(pcfg, name);
|
||||||
|
@ -4756,6 +4866,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
|
||||||
{ "glx-no-rebind-pixmap", no_argument, NULL, 298 },
|
{ "glx-no-rebind-pixmap", no_argument, NULL, 298 },
|
||||||
{ "glx-swap-method", required_argument, NULL, 299 },
|
{ "glx-swap-method", required_argument, NULL, 299 },
|
||||||
{ "fade-exclude", required_argument, NULL, 300 },
|
{ "fade-exclude", required_argument, NULL, 300 },
|
||||||
|
{ "blur-kern", required_argument, NULL, 301 },
|
||||||
// Must terminate with a NULL entry
|
// Must terminate with a NULL entry
|
||||||
{ NULL, 0, NULL, 0 },
|
{ NULL, 0, NULL, 0 },
|
||||||
};
|
};
|
||||||
|
@ -4979,6 +5090,12 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
|
||||||
// --fade-exclude
|
// --fade-exclude
|
||||||
condlst_add(ps, &ps->o.fade_blacklist, optarg);
|
condlst_add(ps, &ps->o.fade_blacklist, optarg);
|
||||||
break;
|
break;
|
||||||
|
case 301:
|
||||||
|
// --blur-kern
|
||||||
|
free(ps->o.blur_kern);
|
||||||
|
if (!(ps->o.blur_kern = parse_matrix(ps, optarg)))
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
break;
|
break;
|
||||||
|
@ -5042,6 +5159,29 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
|
||||||
ps->o.track_leader = true;
|
ps->o.track_leader = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fill default blur kernel
|
||||||
|
if (ps->o.blur_background && !ps->o.blur_kern) {
|
||||||
|
const static int convolution_blur_size = 3;
|
||||||
|
// Convolution filter parameter (box blur)
|
||||||
|
// gaussian or binomial filters are definitely superior, yet looks
|
||||||
|
// like they aren't supported as of xorg-server-1.13.0
|
||||||
|
const static XFixed convolution_blur[] = {
|
||||||
|
// Must convert to XFixed with XDoubleToFixed()
|
||||||
|
// Matrix size
|
||||||
|
XDoubleToFixed(convolution_blur_size),
|
||||||
|
XDoubleToFixed(convolution_blur_size),
|
||||||
|
// Matrix
|
||||||
|
XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1),
|
||||||
|
XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1),
|
||||||
|
XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1),
|
||||||
|
};
|
||||||
|
ps->o.blur_kern = malloc(sizeof(convolution_blur));
|
||||||
|
if (!ps->o.blur_kern) {
|
||||||
|
printf_errf("(): Failed to allocate memory for convolution kernel.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
memcpy(ps->o.blur_kern, &convolution_blur, sizeof(convolution_blur));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5864,6 +6004,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
|
||||||
.blur_background_frame = false,
|
.blur_background_frame = false,
|
||||||
.blur_background_fixed = false,
|
.blur_background_fixed = false,
|
||||||
.blur_background_blacklist = NULL,
|
.blur_background_blacklist = NULL,
|
||||||
|
.blur_kern = NULL,
|
||||||
.inactive_dim = 0.0,
|
.inactive_dim = 0.0,
|
||||||
.inactive_dim_fixed = false,
|
.inactive_dim_fixed = false,
|
||||||
.invert_color_list = NULL,
|
.invert_color_list = NULL,
|
||||||
|
@ -5929,6 +6070,12 @@ session_init(session_t *ps_old, int argc, char **argv) {
|
||||||
.glXWaitVideoSyncSGI = NULL,
|
.glXWaitVideoSyncSGI = NULL,
|
||||||
.glXGetSyncValuesOML = NULL,
|
.glXGetSyncValuesOML = NULL,
|
||||||
.glXWaitForMscOML = NULL,
|
.glXWaitForMscOML = NULL,
|
||||||
|
|
||||||
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
|
.glx_prog_blur_unifm_offset_x = -1,
|
||||||
|
.glx_prog_blur_unifm_offset_y = -1,
|
||||||
|
.glx_prog_blur_unifm_factor_center = -1,
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
.xfixes_event = 0,
|
.xfixes_event = 0,
|
||||||
|
@ -6277,6 +6424,7 @@ session_destroy(session_t *ps) {
|
||||||
free_wincondlst(&ps->o.fade_blacklist);
|
free_wincondlst(&ps->o.fade_blacklist);
|
||||||
free_wincondlst(&ps->o.focus_blacklist);
|
free_wincondlst(&ps->o.focus_blacklist);
|
||||||
free_wincondlst(&ps->o.invert_color_list);
|
free_wincondlst(&ps->o.invert_color_list);
|
||||||
|
free_wincondlst(&ps->o.blur_background_blacklist);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Free tracked atom list
|
// Free tracked atom list
|
||||||
|
@ -6338,6 +6486,7 @@ session_destroy(session_t *ps) {
|
||||||
free(ps->o.display);
|
free(ps->o.display);
|
||||||
free(ps->o.logpath);
|
free(ps->o.logpath);
|
||||||
free(ps->o.config_file);
|
free(ps->o.config_file);
|
||||||
|
free(ps->o.blur_kern);
|
||||||
free(ps->pfds_read);
|
free(ps->pfds_read);
|
||||||
free(ps->pfds_write);
|
free(ps->pfds_write);
|
||||||
free(ps->pfds_except);
|
free(ps->pfds_except);
|
||||||
|
|
88
src/opengl.c
88
src/opengl.c
|
@ -191,28 +191,60 @@ bool
|
||||||
glx_init_blur(session_t *ps) {
|
glx_init_blur(session_t *ps) {
|
||||||
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
// Build shader
|
// Build shader
|
||||||
static const char *FRAG_SHADER_BLUR =
|
{
|
||||||
"#version 110\n"
|
static const char *FRAG_SHADER_BLUR_PREFIX =
|
||||||
"uniform float offset_x;\n"
|
"#version 110\n"
|
||||||
"uniform float offset_y;\n"
|
"uniform float offset_x;\n"
|
||||||
"uniform float factor_center;\n"
|
"uniform float offset_y;\n"
|
||||||
"uniform sampler2D tex_scr;\n"
|
"uniform float factor_center;\n"
|
||||||
"\n"
|
"uniform sampler2D tex_scr;\n"
|
||||||
"void main() {\n"
|
"\n"
|
||||||
" vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n"
|
"void main() {\n"
|
||||||
" sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x - offset_x, gl_TexCoord[0].y - offset_y));\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));\n"
|
static const char *FRAG_SHADER_BLUR_ADD =
|
||||||
" sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x - offset_x, gl_TexCoord[0].y + offset_y));\n"
|
" sum += float(%.7g) * texture2D(tex_scr, vec2(gl_TexCoord[0].x + offset_x * float(%d), gl_TexCoord[0].y + offset_y * float(%d)));\n";
|
||||||
" sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y - offset_y));\n"
|
static const char *FRAG_SHADER_BLUR_SUFFIX =
|
||||||
" 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)) * factor_center;\n"
|
||||||
" sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y + offset_y));\n"
|
" gl_FragColor = sum / (factor_center + float(%.7g));\n"
|
||||||
" sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x + offset_x, gl_TexCoord[0].y - offset_y));\n"
|
"}\n";
|
||||||
" sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x + offset_x, gl_TexCoord[0].y));\n"
|
int wid = XFixedToDouble(ps->o.blur_kern[0]), hei = XFixedToDouble(ps->o.blur_kern[1]);
|
||||||
" sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x + offset_x, gl_TexCoord[0].y + offset_y));\n"
|
int nele = wid * hei - 1;
|
||||||
" gl_FragColor = sum / (factor_center + 8.0);\n"
|
int len = strlen(FRAG_SHADER_BLUR_PREFIX) + (strlen(FRAG_SHADER_BLUR_ADD) + 42) * nele
|
||||||
"}\n"
|
+ strlen(FRAG_SHADER_BLUR_SUFFIX) + 12 + 1;
|
||||||
;
|
char *shader_str = calloc(len, sizeof(char));
|
||||||
ps->glx_frag_shader_blur = glx_create_shader(GL_FRAGMENT_SHADER, FRAG_SHADER_BLUR);
|
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) {
|
if (!ps->glx_frag_shader_blur) {
|
||||||
printf_errf("(): Failed to create fragment shader.");
|
printf_errf("(): Failed to create fragment shader.");
|
||||||
return false;
|
return false;
|
||||||
|
@ -227,8 +259,7 @@ glx_init_blur(session_t *ps) {
|
||||||
#define P_GET_UNIFM_LOC(name, target) { \
|
#define P_GET_UNIFM_LOC(name, target) { \
|
||||||
ps->target = glGetUniformLocation(ps->glx_prog_blur, name); \
|
ps->target = glGetUniformLocation(ps->glx_prog_blur, name); \
|
||||||
if (ps->target < 0) { \
|
if (ps->target < 0) { \
|
||||||
printf_errf("(): Failed to get location of uniform '" name "'."); \
|
printf_errf("(): Failed to get location of uniform '" name "'. Might be troublesome."); \
|
||||||
return false; \
|
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||||
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
glUseProgram(ps->glx_prog_blur);
|
glUseProgram(ps->glx_prog_blur);
|
||||||
glUniform1f(ps->glx_prog_blur_unifm_offset_x, 1.0f / width);
|
if (ps->glx_prog_blur_unifm_offset_x >= 0)
|
||||||
glUniform1f(ps->glx_prog_blur_unifm_offset_y, 1.0f / height);
|
glUniform1f(ps->glx_prog_blur_unifm_offset_x, 1.0f / width);
|
||||||
glUniform1f(ps->glx_prog_blur_unifm_factor_center, factor_center);
|
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
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue