From 07e4420ab428b5cfc76909a1369391dffb1010f1 Mon Sep 17 00:00:00 2001 From: Richard Grenville Date: Sat, 13 Oct 2012 18:46:59 +0800 Subject: [PATCH] Improvement: Pregenerate alpha pictures Pregenerate alpha pictures to save time when painting. Add --alpha-step to control the step of alpha picture generation (the opacity difference between two consecutively generated alpha pictures). --- .gitignore | 1 + compton.sample.conf | 1 + src/compton.c | 79 +++++++++++++++++++++++++++------------------ src/compton.h | 11 +++---- 4 files changed, 55 insertions(+), 37 deletions(-) diff --git a/.gitignore b/.gitignore index b4a8bfe2..cb2c71df 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ install_manifest.txt core oprofile_data compton.plist +callgrind.out.* diff --git a/compton.sample.conf b/compton.sample.conf index 880046a8..6ef97bec 100644 --- a/compton.sample.conf +++ b/compton.sample.conf @@ -19,6 +19,7 @@ menu-opacity = 0.8; inactive-opacity = 0.8; frame-opacity = 0.7; inactive-opacity-override = false; +alpha-step = 0.06; # Fading fading = true; diff --git a/src/compton.c b/src/compton.c index 9f144882..8992cd30 100755 --- a/src/compton.c +++ b/src/compton.c @@ -52,6 +52,8 @@ Bool has_name_pixmap; #endif int root_height, root_width; +/// Pregenerated alpha pictures. +Picture *alpha_picts = NULL; /// Whether the program is idling. I.e. no fading, no potential window /// changes. Bool idling; @@ -187,6 +189,7 @@ static options_t opts = { .frame_opacity = 0.0, .detect_client_opacity = False, .inactive_dim = 0.0, + .alpha_step = 0.03, .track_focus = False, .track_wdata = False, @@ -1282,6 +1285,17 @@ get_frame_extents(Display *dpy, win *w, Window client) { } } +static inline Picture +get_alpha_pict_d(double o) { + assert((lround(normalize_d(o) / opts.alpha_step)) <= lround(1.0 / opts.alpha_step)); + return alpha_picts[lround(normalize_d(o) / opts.alpha_step)]; +} + +static inline Picture +get_alpha_pict_o(opacity_t o) { + return get_alpha_pict_d((double) o / OPAQUE); +} + static win * paint_preprocess(Display *dpy, win *list) { win *w; @@ -1356,14 +1370,7 @@ paint_preprocess(Display *dpy, win *list) { add_damage_win(dpy, w); } - // Rebuild alpha_pict only if necessary - if (OPAQUE != w->opacity - && (!w->alpha_pict || w->opacity != w->opacity_cur)) { - free_picture(dpy, &w->alpha_pict); - w->alpha_pict = solid_picture( - dpy, False, get_opacity_percent(dpy, w), 0, 0, 0); - w->opacity_cur = w->opacity; - } + w->alpha_pict = get_alpha_pict_o(w->opacity); // Calculate frame_opacity if (opts.frame_opacity && 1.0 != opts.frame_opacity && w->top_width) @@ -1371,15 +1378,7 @@ paint_preprocess(Display *dpy, win *list) { else w->frame_opacity = 0.0; - // Rebuild frame_alpha_pict only if necessary - if (w->frame_opacity - && (!w->frame_alpha_pict - || w->frame_opacity != w->frame_opacity_cur)) { - free_picture(dpy, &w->frame_alpha_pict); - w->frame_alpha_pict = solid_picture( - dpy, False, w->frame_opacity, 0, 0, 0); - w->frame_opacity_cur = w->frame_opacity; - } + w->frame_alpha_pict = get_alpha_pict_d(w->frame_opacity); // Calculate shadow opacity if (w->frame_opacity) @@ -1396,15 +1395,7 @@ paint_preprocess(Display *dpy, win *list) { w->widthb, w->heightb); } - // Rebuild shadow_alpha_pict if necessary - if (w->shadow - && (!w->shadow_alpha_pict - || w->shadow_opacity != w->shadow_opacity_cur)) { - free_picture(dpy, &w->shadow_alpha_pict); - w->shadow_alpha_pict = solid_picture( - dpy, False, w->shadow_opacity, 0, 0, 0); - w->shadow_opacity_cur = w->shadow_opacity; - } + w->shadow_alpha_pict = get_alpha_pict_d(w->shadow_opacity); // Reset flags w->flags = 0; @@ -2078,7 +2069,6 @@ add_win(Display *dpy, Window id, Window prev, Bool override_redirect) { new->extents = None; new->shadow = False; new->shadow_opacity = 0.0; - new->shadow_opacity_cur = 0.0; new->shadow_pict = None; new->shadow_alpha_pict = None; new->shadow_dx = 0; @@ -2087,7 +2077,6 @@ add_win(Display *dpy, Window id, Window prev, Bool override_redirect) { new->shadow_height = 0; new->opacity = 0; new->opacity_tgt = 0; - new->opacity_cur = OPAQUE; new->opacity_prop = OPAQUE; new->opacity_prop_client = OPAQUE; new->fade = False; @@ -2095,7 +2084,6 @@ add_win(Display *dpy, Window id, Window prev, Bool override_redirect) { new->fade_fin = False; new->alpha_pict = None; new->frame_opacity = 1.0; - new->frame_opacity_cur = 1.0; new->frame_alpha_pict = None; new->dim = False; new->focused = False; @@ -2284,8 +2272,6 @@ finish_destroy_win(Display *dpy, Window id) { finish_unmap_win(dpy, w); *prev = w->next; - free_picture(dpy, &w->alpha_pict); - free_picture(dpy, &w->frame_alpha_pict); free_picture(dpy, &w->shadow_pict); free_damage(dpy, &w->damage); free(w->name); @@ -3105,6 +3091,9 @@ usage(void) { " opengl = Try to VSync with SGI_swap_control OpenGL extension. Only\n" " work on some drivers. Experimental.\n" " (Note some VSync methods may not be enabled at compile time.)\n" + "--alpha-step val\n" + " Step for pregenerating alpha pictures. 0.01 - 1.0. Defaults to\n" + " 0.03.\n" "\n" "Format of a condition:\n" "\n" @@ -3421,6 +3410,8 @@ parse_config(char *cpath, struct options_tmp *pcfgtmp) { &opts.detect_client_opacity); // --refresh-rate lcfg_lookup_int(&cfg, "refresh-rate", &opts.refresh_rate); + // --alpha-step + config_lookup_float(&cfg, "alpha-step", &opts.alpha_step); // --shadow-exclude { config_setting_t *setting = @@ -3486,6 +3477,7 @@ get_cfg(int argc, char *const *argv) { { "detect-client-opacity", no_argument, NULL, 268 }, { "refresh-rate", required_argument, NULL, 269 }, { "vsync", required_argument, NULL, 270 }, + { "alpha-step", required_argument, NULL, 271 }, // Must terminate with a NULL entry { NULL, 0, NULL, 0 }, }; @@ -3668,6 +3660,10 @@ get_cfg(int argc, char *const *argv) { } } break; + case 271: + // --alpha-step + opts.alpha_step = atof(optarg); + break; default: usage(); break; @@ -3689,6 +3685,7 @@ get_cfg(int argc, char *const *argv) { opts.shadow_opacity = normalize_d(opts.shadow_opacity); cfgtmp.menu_opacity = normalize_d(cfgtmp.menu_opacity); opts.refresh_rate = normalize_i_range(opts.refresh_rate, 0, 300); + opts.alpha_step = normalize_d_range(opts.alpha_step, 0.01, 1.0); if (OPAQUE == opts.inactive_opacity) { opts.inactive_opacity = 0; } @@ -4028,6 +4025,25 @@ vsync_wait(Display *dpy, struct pollfd *fd, int timeout) { return 0; } +/** + * Pregenerate alpha pictures. + */ +static void +init_alpha_picts(Display *dpy) { + int i; + int num = lround(1.0 / opts.alpha_step) + 1; + + alpha_picts = malloc(sizeof(Picture) * num); + + for (i = 0; i < num; ++i) { + double o = i * opts.alpha_step; + if ((1.0 - o) > opts.alpha_step) + alpha_picts[i] = solid_picture(dpy, False, o, 0, 0, 0); + else + alpha_picts[i] = None; + } +} + int main(int argc, char **argv) { XEvent ev; @@ -4130,6 +4146,7 @@ main(int argc, char **argv) { if (opts.fork_after_register) fork_after(); get_atoms(); + init_alpha_picts(dpy); pa.subwindow_mode = IncludeInferiors; diff --git a/src/compton.h b/src/compton.h index d28018b7..56a39766 100644 --- a/src/compton.h +++ b/src/compton.h @@ -221,8 +221,6 @@ typedef struct _win { opacity_t opacity; /// Target window opacity. opacity_t opacity_tgt; - /// Opacity of current alpha_pict. - opacity_t opacity_cur; /// Cached value of opacity window attribute. opacity_t opacity_prop; /// Cached value of opacity window attribute on client window. For @@ -244,8 +242,6 @@ typedef struct _win { // Frame-opacity-related members /// Current window frame opacity. Affected by window opacity. double frame_opacity; - /// Opacity of current frame_alpha_pict. - opacity_t frame_opacity_cur; /// Alpha mask Picture to render window frame with opacity. Picture frame_alpha_pict; /// Frame widths. Determined by client window attributes. @@ -256,8 +252,6 @@ typedef struct _win { Bool shadow; /// Opacity of the shadow. Affected by window opacity and frame opacity. double shadow_opacity; - /// Opacity of current shadow_pict. - double shadow_opacity_cur; /// X offset of shadow. Affected by commandline argument. int shadow_dx; /// Y offset of shadow. Affected by commandline argument. @@ -359,6 +353,8 @@ typedef struct _options { Bool detect_client_opacity; /// How much to dim an inactive window. 0.0 - 1.0, 0 to disable. double inactive_dim; + /// Step for pregenerating alpha pictures. 0.01 - 1.0. + double alpha_step; // Calculated /// Whether compton needs to track focus changes. @@ -1125,3 +1121,6 @@ vsync_opengl_wait(void); static Bool vsync_wait(Display *dpy, struct pollfd *fd, int timeout); + +static void +init_alpha_picts(Display *dpy);