1
0
Fork 0
mirror of https://github.com/yshui/picom.git synced 2024-11-18 13:55:36 -05:00

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).
This commit is contained in:
Richard Grenville 2012-10-13 18:46:59 +08:00
parent 72ea4b5f47
commit 07e4420ab4
4 changed files with 55 additions and 37 deletions

1
.gitignore vendored
View file

@ -35,3 +35,4 @@ install_manifest.txt
core
oprofile_data
compton.plist
callgrind.out.*

View file

@ -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;

View file

@ -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;

View file

@ -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);