Remember the number of blur kernels

Don't count the number of blur kernels everytime.

Fixes #188

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2019-06-07 21:53:23 +01:00
parent dc7050cb00
commit fa8faaf91d
No known key found for this signature in database
GPG Key ID: 37C999F617EA1A47
9 changed files with 60 additions and 51 deletions

View File

@ -662,12 +662,12 @@ void *gl_copy(backend_t *base, const void *image_data, const region_t *reg_visib
/** /**
* Initialize GL blur filters. * Initialize GL blur filters.
*/ */
static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) { static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels, int nkernels) {
if (!kernels[0]) { if (!nkernels) {
return true; return true;
} }
for (gd->npasses = 0; kernels[gd->npasses]; gd->npasses++); gd->npasses = nkernels;
gd->blur_shader = ccalloc(gd->npasses, gl_blur_shader_t); gd->blur_shader = ccalloc(gd->npasses, gl_blur_shader_t);
char *lc_numeric_old = strdup(setlocale(LC_NUMERIC, NULL)); char *lc_numeric_old = strdup(setlocale(LC_NUMERIC, NULL));
@ -700,7 +700,7 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) {
const char *shader_add = FRAG_SHADER_BLUR_ADD; const char *shader_add = FRAG_SHADER_BLUR_ADD;
char *extension = strdup(""); char *extension = strdup("");
for (int i = 0; kernels[i]; i++) { for (int i = 0; i < nkernels; i++) {
auto kern = kernels[i]; auto kern = kernels[i];
// Build shader // Build shader
int width = kern->w, height = kern->h; int width = kern->w, height = kern->h;
@ -831,7 +831,7 @@ bool gl_init(struct gl_data *gd, session_t *ps) {
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
gl_win_shader_from_string(vertex_shader, win_shader_glsl, &gd->win_shader); gl_win_shader_from_string(vertex_shader, win_shader_glsl, &gd->win_shader);
if (!gl_init_blur(gd, ps->o.blur_kerns)) { if (!gl_init_blur(gd, ps->o.blur_kerns, ps->o.blur_kernel_count)) {
return false; return false;
} }
gd->fill_shader.prog = gl_create_program_from_str(fill_vert, fill_frag); gd->fill_shader.prog = gl_create_program_from_str(fill_vert, fill_frag);

View File

@ -60,7 +60,10 @@ typedef struct _xrender_data {
int target_width, target_height; int target_width, target_height;
/// Blur kernels converted to X format /// Blur kernels converted to X format
struct x_convolution_kernel **x_blur_kern; struct x_convolution_kernel **x_blur_kernel;
/// Number of blur kernels
int x_blur_kernel_count;
xcb_special_event_t *present_event; xcb_special_event_t *present_event;
} xrender_data; } xrender_data;
@ -175,16 +178,16 @@ static bool blur(backend_t *backend_data, double opacity, const region_t *reg_bl
// For 1 pass, we do // For 1 pass, we do
// back -(pass 1)-> tmp0 -(copy)-> target_buffer // back -(pass 1)-> tmp0 -(copy)-> target_buffer
int i; int i;
for (i = 0; xd->x_blur_kern[i]; i++) { for (i = 0; i < xd->x_blur_kernel_count; i++) {
// Copy from source picture to destination. The filter must // Copy from source picture to destination. The filter must
// be applied on source picture, to get the nearby pixels outside the // be applied on source picture, to get the nearby pixels outside the
// window. // window.
// TODO cache converted blur_kerns // TODO cache converted blur_kerns
xcb_render_set_picture_filter( xcb_render_set_picture_filter(
c, src_pict, to_u16_checked(strlen(filter)), filter, c, src_pict, to_u16_checked(strlen(filter)), filter,
to_u32_checked(xd->x_blur_kern[i]->size), xd->x_blur_kern[i]->kernel); to_u32_checked(xd->x_blur_kernel[i]->size), xd->x_blur_kernel[i]->kernel);
if (xd->x_blur_kern[i + 1] || i == 0) { if (i < xd->x_blur_kernel_count - 1 || i == 0) {
// This is not the last pass, or this is the first pass // This is not the last pass, or this is the first pass
xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, src_pict, xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, src_pict,
XCB_NONE, dst_pict, src_x, src_y, 0, 0, 0, 0, XCB_NONE, dst_pict, src_x, src_y, 0, 0, 0, 0,
@ -269,10 +272,10 @@ static void deinit(backend_t *backend_data) {
xcb_render_free_picture(xd->base.c, xd->back[i]); xcb_render_free_picture(xd->base.c, xd->back[i]);
xcb_free_pixmap(xd->base.c, xd->back_pixmap[i]); xcb_free_pixmap(xd->base.c, xd->back_pixmap[i]);
} }
for (int i = 0; xd->x_blur_kern[i]; i++) { for (int i = 0; i < xd->x_blur_kernel_count; i++) {
free(xd->x_blur_kern[i]); free(xd->x_blur_kernel[i]);
} }
free(xd->x_blur_kern); free(xd->x_blur_kernel);
if (xd->present_event) { if (xd->present_event) {
xcb_unregister_for_special_event(xd->base.c, xd->present_event); xcb_unregister_for_special_event(xd->base.c, xd->present_event);
} }
@ -547,14 +550,11 @@ backend_t *backend_xrender_init(session_t *ps) {
ps->c, ps->vis, root_pixmap, 0, NULL); ps->c, ps->vis, root_pixmap, 0, NULL);
} }
int npasses = 0; xd->x_blur_kernel = ccalloc(ps->o.blur_kernel_count, struct x_convolution_kernel *);
for (; ps->o.blur_kerns[npasses]; npasses++) for (int i = 0; i < ps->o.blur_kernel_count; i++) {
; x_create_convolution_kernel(ps->o.blur_kerns[i], 1, &xd->x_blur_kernel[i]);
// +1 for null terminator
xd->x_blur_kern = ccalloc(npasses + 1, struct x_convolution_kernel *);
for (int i = 0; ps->o.blur_kerns[i]; i++) {
x_create_convolution_kernel(ps->o.blur_kerns[i], 1, &xd->x_blur_kern[i]);
} }
xd->x_blur_kernel_count = ps->o.blur_kernel_count;
return &xd->base; return &xd->base;
err: err:
deinit(&xd->base); deinit(&xd->base);

View File

@ -2010,7 +2010,7 @@ static void session_destroy(session_t *ps) {
free(ps->o.write_pid_path); free(ps->o.write_pid_path);
free(ps->o.logpath); free(ps->o.logpath);
for (int i = 0; ps->o.blur_kerns[i]; ++i) { for (int i = 0; i < ps->o.blur_kernel_count; ++i) {
free(ps->o.blur_kerns[i]); free(ps->o.blur_kerns[i]);
} }
free(ps->o.blur_kerns); free(ps->o.blur_kerns);

View File

@ -196,7 +196,7 @@ err1:
* @param[out] hasneg whether any of the kernels have negative values * @param[out] hasneg whether any of the kernels have negative values
* @return the kernels * @return the kernels
*/ */
struct conv **parse_blur_kern_lst(const char *src, bool *hasneg) { struct conv **parse_blur_kern_lst(const char *src, bool *hasneg, int *count) {
// TODO just return a predefined kernels, not parse predefined strings... // TODO just return a predefined kernels, not parse predefined strings...
static const struct { static const struct {
const char *name; const char *name;
@ -251,11 +251,12 @@ struct conv **parse_blur_kern_lst(const char *src, bool *hasneg) {
"000000,"}, "000000,"},
}; };
*count = 0;
*hasneg = false; *hasneg = false;
for (unsigned int i = 0; for (unsigned int i = 0;
i < sizeof(CONV_KERN_PREDEF) / sizeof(CONV_KERN_PREDEF[0]); ++i) { i < sizeof(CONV_KERN_PREDEF) / sizeof(CONV_KERN_PREDEF[0]); ++i) {
if (!strcmp(CONV_KERN_PREDEF[i].name, src)) if (!strcmp(CONV_KERN_PREDEF[i].name, src))
return parse_blur_kern_lst(CONV_KERN_PREDEF[i].kern_str, hasneg); return parse_blur_kern_lst(CONV_KERN_PREDEF[i].kern_str, hasneg, count);
} }
int nkernels = 1; int nkernels = 1;
@ -265,7 +266,7 @@ struct conv **parse_blur_kern_lst(const char *src, bool *hasneg) {
} }
} }
struct conv **ret = ccalloc(nkernels+1, struct conv *); // +1 for NULL terminator struct conv **ret = ccalloc(nkernels, struct conv *);
int i = 0; int i = 0;
const char *pc = src; const char *pc = src;
@ -294,6 +295,8 @@ struct conv **parse_blur_kern_lst(const char *src, bool *hasneg) {
"removed in future releases"); "removed in future releases");
} }
*count = i;
return ret; return ret;
} }
@ -541,6 +544,7 @@ char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable,
.blur_background_fixed = false, .blur_background_fixed = false,
.blur_background_blacklist = NULL, .blur_background_blacklist = NULL,
.blur_kerns = NULL, .blur_kerns = NULL,
.blur_kernel_count = 0,
.inactive_dim = 0.0, .inactive_dim = 0.0,
.inactive_dim_fixed = false, .inactive_dim_fixed = false,
.invert_color_list = NULL, .invert_color_list = NULL,

View File

@ -198,6 +198,8 @@ typedef struct options {
c2_lptr_t *blur_background_blacklist; c2_lptr_t *blur_background_blacklist;
/// Blur convolution kernel. /// Blur convolution kernel.
struct conv **blur_kerns; struct conv **blur_kerns;
/// Number of convolution kernels
int blur_kernel_count;
/// 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
@ -233,7 +235,7 @@ extern const char *const BACKEND_STRS[NUM_BKEND + 1];
bool must_use parse_long(const char *, long *); bool must_use parse_long(const char *, long *);
bool must_use parse_int(const char *, int *); bool must_use parse_int(const char *, int *);
struct conv **must_use parse_blur_kern_lst(const char *, bool *hasneg); struct conv **must_use parse_blur_kern_lst(const char *, bool *hasneg, int *count);
bool must_use parse_geometry(session_t *, const char *, region_t *); bool must_use parse_geometry(session_t *, const char *, region_t *);
bool must_use parse_rule_opacity(c2_lptr_t **, const char *); bool must_use parse_rule_opacity(c2_lptr_t **, const char *);
enum blur_method must_use parse_blur_method(const char *src); enum blur_method must_use parse_blur_method(const char *src);

View File

@ -380,7 +380,8 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
lcfg_lookup_bool(&cfg, "blur-background-fixed", &opt->blur_background_fixed); lcfg_lookup_bool(&cfg, "blur-background-fixed", &opt->blur_background_fixed);
// --blur-kern // --blur-kern
if (config_lookup_string(&cfg, "blur-kern", &sval)) { if (config_lookup_string(&cfg, "blur-kern", &sval)) {
opt->blur_kerns = parse_blur_kern_lst(sval, conv_kern_hasneg); opt->blur_kerns =
parse_blur_kern_lst(sval, conv_kern_hasneg, &opt->blur_kernel_count);
if (!opt->blur_kerns) { if (!opt->blur_kerns) {
log_fatal("Cannot parse \"blur-kern\""); log_fatal("Cannot parse \"blur-kern\"");
goto err; goto err;
@ -464,7 +465,8 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
config_setting_lookup_int(blur_cfg, "size", &opt->blur_radius); config_setting_lookup_int(blur_cfg, "size", &opt->blur_radius);
if (config_setting_lookup_string(blur_cfg, "kernel", &sval)) { if (config_setting_lookup_string(blur_cfg, "kernel", &sval)) {
opt->blur_kerns = parse_blur_kern_lst(sval, conv_kern_hasneg); opt->blur_kerns = parse_blur_kern_lst(sval, conv_kern_hasneg,
&opt->blur_kernel_count);
if (!opt->blur_kerns) { if (!opt->blur_kerns) {
log_warn("Failed to parse blur kernel: %s", sval); log_warn("Failed to parse blur kernel: %s", sval);
} }

View File

@ -89,13 +89,10 @@ bool glx_init(session_t *ps, bool need_render) {
ps->psglx = cmalloc(glx_session_t); ps->psglx = cmalloc(glx_session_t);
memcpy(ps->psglx, &CGLX_SESSION_DEF, sizeof(glx_session_t)); memcpy(ps->psglx, &CGLX_SESSION_DEF, sizeof(glx_session_t));
int npasses;
for (npasses = 0; ps->o.blur_kerns[npasses]; npasses++)
;
// +1 for the zero terminator // +1 for the zero terminator
ps->psglx->blur_passes = ccalloc(npasses + 1, glx_blur_pass_t); ps->psglx->blur_passes = ccalloc(ps->o.blur_kernel_count, glx_blur_pass_t);
for (int i = 0; ps->o.blur_kerns[i]; ++i) { for (int i = 0; i < ps->o.blur_kernel_count; ++i) {
glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i]; glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i];
ppass->unifm_factor_center = -1; ppass->unifm_factor_center = -1;
ppass->unifm_offset_x = -1; ppass->unifm_offset_x = -1;
@ -236,7 +233,7 @@ void glx_destroy(session_t *ps) {
} }
// Free GLSL shaders/programs // Free GLSL shaders/programs
for (int i = 0; ps->psglx->blur_passes[i].prog; ++i) { for (int i = 0; i < ps->o.blur_kernel_count; ++i) {
glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i]; glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i];
if (ppass->frag_shader) if (ppass->frag_shader)
glDeleteShader(ppass->frag_shader); glDeleteShader(ppass->frag_shader);
@ -277,10 +274,12 @@ void glx_on_root_change(session_t *ps) {
* Initialize GLX blur filter. * Initialize GLX blur filter.
*/ */
bool glx_init_blur(session_t *ps) { bool glx_init_blur(session_t *ps) {
assert(ps->o.blur_kernel_count > 0);
assert(ps->o.blur_kerns);
assert(ps->o.blur_kerns[0]); assert(ps->o.blur_kerns[0]);
// Allocate PBO if more than one blur kernel is present // Allocate PBO if more than one blur kernel is present
if (ps->o.blur_kerns[1]) { if (ps->o.blur_kernel_count > 1) {
// Try to generate a framebuffer // Try to generate a framebuffer
GLuint fbo = 0; GLuint fbo = 0;
glGenFramebuffers(1, &fbo); glGenFramebuffers(1, &fbo);
@ -331,7 +330,7 @@ bool glx_init_blur(session_t *ps) {
extension = strdup(""); extension = strdup("");
} }
for (int i = 0; ps->o.blur_kerns[i]; ++i) { for (int i = 0; i < ps->o.blur_kernel_count; ++i) {
auto kern = ps->o.blur_kerns[i]; auto kern = ps->o.blur_kerns[i];
glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i]; glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i];
@ -695,7 +694,7 @@ static inline void glx_copy_region_to_tex(session_t *ps, GLenum tex_tgt, int bas
bool glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z, bool glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
GLfloat factor_center, const region_t *reg_tgt, glx_blur_cache_t *pbc) { GLfloat factor_center, const region_t *reg_tgt, glx_blur_cache_t *pbc) {
assert(ps->psglx->blur_passes[0].prog); assert(ps->psglx->blur_passes[0].prog);
const bool more_passes = ps->psglx->blur_passes[1].prog; const bool more_passes = ps->o.blur_kernel_count > 1;
const bool have_scissors = glIsEnabled(GL_SCISSOR_TEST); const bool have_scissors = glIsEnabled(GL_SCISSOR_TEST);
const bool have_stencil = glIsEnabled(GL_STENCIL_TEST); const bool have_stencil = glIsEnabled(GL_STENCIL_TEST);
bool ret = false; bool ret = false;
@ -788,8 +787,8 @@ bool glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
} }
bool last_pass = false; bool last_pass = false;
for (int i = 0; !last_pass; ++i) { for (int i = 0; i < ps->o.blur_kernel_count; ++i) {
last_pass = !ps->psglx->blur_passes[i + 1].prog; last_pass = (i == ps->o.blur_kernel_count - 1);
const glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i]; const glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i];
assert(ppass->prog); assert(ppass->prog);

View File

@ -710,7 +710,8 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
break; break;
case 301: case 301:
// --blur-kern // --blur-kern
opt->blur_kerns = parse_blur_kern_lst(optarg, &conv_kern_hasneg); opt->blur_kerns = parse_blur_kern_lst(optarg, &conv_kern_hasneg,
&opt->blur_kernel_count);
if (!opt->blur_kerns) { if (!opt->blur_kerns) {
exit(1); exit(1);
} }
@ -819,8 +820,10 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
// Fill default blur kernel // Fill default blur kernel
if (opt->blur_method == BLUR_METHOD_KERNEL && if (opt->blur_method == BLUR_METHOD_KERNEL &&
(!opt->blur_kerns || !opt->blur_kerns[0])) { (!opt->blur_kerns || !opt->blur_kerns[0])) {
opt->blur_kerns = parse_blur_kern_lst("3x3box", &conv_kern_hasneg); opt->blur_kerns = parse_blur_kern_lst("3x3box", &conv_kern_hasneg,
&opt->blur_kernel_count);
CHECK(opt->blur_kerns); CHECK(opt->blur_kerns);
CHECK(opt->blur_kernel_count);
} }
if (opt->resize_damage < 0) { if (opt->resize_damage < 0) {

View File

@ -616,9 +616,10 @@ win_paint_shadow(session_t *ps, struct managed_win *w, region_t *reg_paint) {
* *
* @return true if successful, false otherwise * @return true if successful, false otherwise
*/ */
static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int16_t x, static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int16_t x, int16_t y,
int16_t y, uint16_t wid, uint16_t hei, uint16_t wid, uint16_t hei, struct x_convolution_kernel **blur_kerns,
struct x_convolution_kernel **blur_kerns, const region_t *reg_clip) { int nkernels, const region_t *reg_clip) {
assert(blur_kerns);
assert(blur_kerns[0]); assert(blur_kerns[0]);
// Directly copying from tgt_buffer to it does not work, so we create a // Directly copying from tgt_buffer to it does not work, so we create a
@ -635,7 +636,7 @@ static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int16_t
x_set_picture_clip_region(ps->c, tmp_picture, 0, 0, reg_clip); x_set_picture_clip_region(ps->c, tmp_picture, 0, 0, reg_clip);
xcb_render_picture_t src_pict = tgt_buffer, dst_pict = tmp_picture; xcb_render_picture_t src_pict = tgt_buffer, dst_pict = tmp_picture;
for (int i = 0; blur_kerns[i]; ++i) { for (int i = 0; i < nkernels; ++i) {
xcb_render_fixed_t *convolution_blur = blur_kerns[i]->kernel; xcb_render_fixed_t *convolution_blur = blur_kerns[i]->kernel;
// `x / 65536.0` converts from X fixed point to double // `x / 65536.0` converts from X fixed point to double
int kwid = (int)((double)convolution_blur[0] / 65536.0), int kwid = (int)((double)convolution_blur[0] / 65536.0),
@ -693,7 +694,7 @@ win_blur_background(session_t *ps, struct managed_win *w, xcb_render_picture_t t
case BKEND_XRENDER: case BKEND_XRENDER:
case BKEND_XR_GLX_HYBRID: { case BKEND_XR_GLX_HYBRID: {
// Normalize blur kernels // Normalize blur kernels
for (int i = 0; ps->o.blur_kerns[i]; ++i) { for (int i = 0; i < ps->o.blur_kernel_count; i++) {
// Note: `x * 65536` converts double `x` to a X fixed point // Note: `x * 65536` converts double `x` to a X fixed point
// representation. `x / 65536` is the other way. // representation. `x / 65536` is the other way.
auto kern_src = ps->o.blur_kerns[i]; auto kern_src = ps->o.blur_kerns[i];
@ -724,7 +725,8 @@ win_blur_background(session_t *ps, struct managed_win *w, xcb_render_picture_t t
} }
// Translate global coordinates to local ones // Translate global coordinates to local ones
pixman_region32_translate(&reg_blur, -x, -y); pixman_region32_translate(&reg_blur, -x, -y);
xr_blur_dst(ps, tgt_buffer, x, y, wid, hei, ps->blur_kerns_cache, &reg_blur); xr_blur_dst(ps, tgt_buffer, x, y, wid, hei, ps->blur_kerns_cache,
ps->o.blur_kernel_count, &reg_blur);
pixman_region32_clear(&reg_blur); pixman_region32_clear(&reg_blur);
} break; } break;
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
@ -1135,12 +1137,9 @@ bool init_render(session_t *ps) {
// Blur filter // Blur filter
if (ps->o.blur_method) { if (ps->o.blur_method) {
int npasses; ps->blur_kerns_cache =
for (npasses = 0; ps->o.blur_kerns[npasses]; npasses++) ccalloc(ps->o.blur_kernel_count, struct x_convolution_kernel *);
;
// +1 for NULL terminator
ps->blur_kerns_cache = ccalloc(npasses+1, struct x_convolution_kernel *);
bool ret = false; bool ret = false;
if (ps->o.backend == BKEND_GLX) { if (ps->o.backend == BKEND_GLX) {
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
@ -1223,7 +1222,7 @@ void deinit_render(session_t *ps) {
} }
#endif #endif
for (int i = 0; ps->blur_kerns_cache[i]; i++) { for (int i = 0; i < ps->o.blur_kernel_count; i++) {
free(ps->blur_kerns_cache[i]); free(ps->blur_kerns_cache[i]);
} }
free(ps->blur_kerns_cache); free(ps->blur_kerns_cache);