Improvement: Defer shadow picture generation
- Defer shadow picture generation to minimize interactions with X, hoping to boost performance. - Fix a rendering issue caused by clip_changed in configure_win(). Remove clip_changed altogether. - Split generation of shadow picture from calculating its geometry. - Cache width/height including borders in struct _win as it's frequently used.
This commit is contained in:
parent
cdf7db750d
commit
1437e406c7
167
src/compton.c
167
src/compton.c
|
@ -30,7 +30,6 @@ Picture cshadow_picture;
|
|||
Picture dim_picture = 0;
|
||||
Picture root_tile;
|
||||
XserverRegion all_damage;
|
||||
Bool clip_changed;
|
||||
#if HAS_NAME_WINDOW_PIXMAP
|
||||
Bool has_name_pixmap;
|
||||
#endif
|
||||
|
@ -276,16 +275,6 @@ run_fades(Display *dpy) {
|
|||
|
||||
determine_mode(dpy, w);
|
||||
|
||||
if (w->shadow_pict) {
|
||||
XRenderFreePicture(dpy, w->shadow_pict);
|
||||
w->shadow_pict = None;
|
||||
|
||||
free_region(dpy, &w->extents);
|
||||
|
||||
/* rebuild the shadow */
|
||||
w->extents = win_extents(dpy, w);
|
||||
}
|
||||
|
||||
/* Must do this last as it might
|
||||
destroy f->w in callbacks */
|
||||
if (need_dequeue) dequeue_fade(dpy, f);
|
||||
|
@ -577,8 +566,7 @@ make_shadow(Display *dpy, double opacity,
|
|||
}
|
||||
|
||||
static Picture
|
||||
shadow_picture(Display *dpy, double opacity,
|
||||
int width, int height, int *wp, int *hp) {
|
||||
shadow_picture(Display *dpy, double opacity, int width, int height) {
|
||||
XImage *shadow_image;
|
||||
Pixmap shadow_pixmap;
|
||||
Picture shadow_picture;
|
||||
|
@ -616,8 +604,6 @@ shadow_picture(Display *dpy, double opacity,
|
|||
dpy, shadow_pixmap, gc, shadow_image, 0, 0, 0, 0,
|
||||
shadow_image->width, shadow_image->height);
|
||||
|
||||
*wp = shadow_image->width;
|
||||
*hp = shadow_image->height;
|
||||
XFreeGC(dpy, gc);
|
||||
XDestroyImage(shadow_image);
|
||||
XFreePixmap(dpy, shadow_pixmap);
|
||||
|
@ -881,39 +867,24 @@ paint_root(Display *dpy) {
|
|||
root_width, root_height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a rectangular region a window (and possibly its shadow) occupies.
|
||||
*
|
||||
* Note w->shadow and shadow geometry must be correct before calling this
|
||||
* function.
|
||||
*/
|
||||
static XserverRegion
|
||||
win_extents(Display *dpy, win *w) {
|
||||
XRectangle r;
|
||||
|
||||
r.x = w->a.x;
|
||||
r.y = w->a.y;
|
||||
r.width = w->a.width + w->a.border_width * 2;
|
||||
r.height = w->a.height + w->a.border_width * 2;
|
||||
r.width = w->widthb;
|
||||
r.height = w->heightb;
|
||||
|
||||
if (win_type_shadow[w->window_type]) {
|
||||
if (w->shadow) {
|
||||
XRectangle sr;
|
||||
|
||||
w->shadow_dx = shadow_offset_x;
|
||||
w->shadow_dy = shadow_offset_y;
|
||||
|
||||
if (!w->shadow_pict) {
|
||||
double opacity = shadow_opacity;
|
||||
|
||||
if (w->mode != WINDOW_SOLID) {
|
||||
opacity = opacity * get_opacity_percent(dpy, w);
|
||||
}
|
||||
|
||||
if (HAS_FRAME_OPACITY(w)) {
|
||||
opacity = opacity * frame_opacity;
|
||||
}
|
||||
|
||||
w->shadow_pict = shadow_picture(
|
||||
dpy, opacity,
|
||||
w->a.width + w->a.border_width * 2,
|
||||
w->a.height + w->a.border_width * 2,
|
||||
&w->shadow_width, &w->shadow_height);
|
||||
}
|
||||
|
||||
sr.x = w->a.x + w->shadow_dx;
|
||||
sr.y = w->a.y + w->shadow_dy;
|
||||
sr.width = w->shadow_width;
|
||||
|
@ -953,12 +924,10 @@ border_size(Display *dpy, win *w) {
|
|||
* instead of an invalid XID.
|
||||
*/
|
||||
|
||||
set_ignore(dpy, NextRequest(dpy));
|
||||
border = XFixesCreateRegionFromWindow(
|
||||
dpy, w->id, WindowRegionBounding);
|
||||
|
||||
/* translate this */
|
||||
set_ignore(dpy, NextRequest(dpy));
|
||||
XFixesTranslateRegion(dpy, border,
|
||||
w->a.x + w->a.border_width,
|
||||
w->a.y + w->a.border_width);
|
||||
|
@ -1109,11 +1078,6 @@ paint_all(Display *dpy, XserverRegion region) {
|
|||
printf(" %#010lx", w->id);
|
||||
#endif
|
||||
|
||||
if (clip_changed) {
|
||||
free_region(dpy, &w->border_size);
|
||||
free_region(dpy, &w->extents);
|
||||
}
|
||||
|
||||
if (!w->border_size) {
|
||||
w->border_size = border_size(dpy, w);
|
||||
}
|
||||
|
@ -1147,6 +1111,28 @@ paint_all(Display *dpy, XserverRegion region) {
|
|||
w->frame_opacity_cur = w->frame_opacity;
|
||||
}
|
||||
|
||||
// Calculate shadow opacity
|
||||
if (w->frame_opacity)
|
||||
w->shadow_opacity = shadow_opacity * w->frame_opacity;
|
||||
else
|
||||
w->shadow_opacity = shadow_opacity * get_opacity_percent(dpy, w);
|
||||
|
||||
// Rebuild shadow_pict if necessary
|
||||
if (w->flags & WFLAG_SIZE_CHANGE)
|
||||
free_picture(dpy, &w->shadow_pict);
|
||||
|
||||
if (w->shadow
|
||||
&& (!w->shadow_pict
|
||||
|| w->shadow_opacity != w->shadow_opacity_cur)) {
|
||||
free_picture(dpy, &w->shadow_pict);
|
||||
w->shadow_pict = shadow_picture(dpy, w->shadow_opacity,
|
||||
w->widthb, w->heightb);
|
||||
w->shadow_opacity_cur = w->shadow_opacity;
|
||||
}
|
||||
|
||||
// Reset flags
|
||||
w->flags = 0;
|
||||
|
||||
w->prev_trans = t;
|
||||
t = w;
|
||||
}
|
||||
|
@ -1166,8 +1152,8 @@ paint_all(Display *dpy, XserverRegion region) {
|
|||
#if HAS_NAME_WINDOW_PIXMAP
|
||||
x = w->a.x;
|
||||
y = w->a.y;
|
||||
wid = w->a.width + w->a.border_width * 2;
|
||||
hei = w->a.height + w->a.border_width * 2;
|
||||
wid = w->widthb;
|
||||
hei = w->heightb;
|
||||
#else
|
||||
x = w->a.x + w->a.border_width;
|
||||
y = w->a.y + w->a.border_width;
|
||||
|
@ -1429,6 +1415,19 @@ map_win(Display *dpy, Window id,
|
|||
w->a.map_state = IsViewable;
|
||||
w->window_type = determine_wintype(dpy, w->id, w->id);
|
||||
|
||||
// Window type change could affect shadow
|
||||
{
|
||||
Bool shadow_old = w->shadow;
|
||||
determine_shadow(dpy, w);
|
||||
if (w->shadow != shadow_old) {
|
||||
calc_shadow_geometry(dpy, w);
|
||||
if (w->extents) {
|
||||
free_region(dpy, &w->extents);
|
||||
w->extents = win_extents(dpy, w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_WINTYPE
|
||||
printf("map_win(): window %#010lx type %s\n",
|
||||
w->id, wintype_name(w->window_type));
|
||||
|
@ -1508,8 +1507,6 @@ finish_unmap_win(Display *dpy, win *w) {
|
|||
free_picture(dpy, &w->picture);
|
||||
free_region(dpy, &w->border_size);
|
||||
free_picture(dpy, &w->shadow_pict);
|
||||
|
||||
clip_changed = True;
|
||||
}
|
||||
|
||||
#if HAS_NAME_WINDOW_PIXMAP
|
||||
|
@ -1605,16 +1602,6 @@ set_opacity(Display *dpy, win *w, opacity_t opacity) {
|
|||
|
||||
w->opacity = opacity;
|
||||
determine_mode(dpy, w);
|
||||
|
||||
if (w->shadow_pict) {
|
||||
XRenderFreePicture(dpy, w->shadow_pict);
|
||||
w->shadow_pict = None;
|
||||
|
||||
free_region(dpy, &w->extents);
|
||||
|
||||
/* rebuild the shadow */
|
||||
w->extents = win_extents(dpy, w);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1683,6 +1670,37 @@ calc_dim(Display *dpy, win *w) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a window should have shadow.
|
||||
*/
|
||||
static void
|
||||
determine_shadow(Display *dpy, win *w) {
|
||||
w->shadow = win_type_shadow[w->window_type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update cache data in struct _win that depends on window size.
|
||||
*/
|
||||
|
||||
static void
|
||||
calc_win_size(Display *dpy, win *w) {
|
||||
w->widthb = w->a.width + w->a.border_width * 2;
|
||||
w->heightb = w->a.height + w->a.border_width * 2;
|
||||
calc_shadow_geometry(dpy, w);
|
||||
w->flags |= WFLAG_SIZE_CHANGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate and update geometry of the shadow of a window.
|
||||
*/
|
||||
static void
|
||||
calc_shadow_geometry(Display *dpy, win *w) {
|
||||
w->shadow_dx = shadow_offset_x;
|
||||
w->shadow_dy = shadow_offset_y;
|
||||
w->shadow_width = w->widthb + gaussian_map->size;
|
||||
w->shadow_height = w->heightb + gaussian_map->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a window as the client window of another.
|
||||
*
|
||||
|
@ -1749,10 +1767,12 @@ add_win(Display *dpy, Window id, Window prev, Bool override_redirect) {
|
|||
new->damage = XDamageCreate(dpy, id, XDamageReportNonEmpty);
|
||||
}
|
||||
|
||||
new->shadow = False;
|
||||
new->shadow_pict = None;
|
||||
new->border_size = None;
|
||||
new->extents = None;
|
||||
new->shadow = False;
|
||||
new->shadow_opacity = 0.0;
|
||||
new->shadow_opacity_cur = 0.0;
|
||||
new->shadow_pict = None;
|
||||
new->shadow_dx = 0;
|
||||
new->shadow_dy = 0;
|
||||
new->shadow_width = 0;
|
||||
|
@ -1779,6 +1799,10 @@ add_win(Display *dpy, Window id, Window prev, Bool override_redirect) {
|
|||
|
||||
new->client_win = 0;
|
||||
|
||||
new->flags = 0;
|
||||
|
||||
calc_win_size(dpy, new);
|
||||
|
||||
new->next = *p;
|
||||
*p = new;
|
||||
|
||||
|
@ -1898,12 +1922,15 @@ configure_win(Display *dpy, XConfigureEvent *ce) {
|
|||
free_pixmap(dpy, &w->pixmap);
|
||||
free_picture(dpy, &w->picture);
|
||||
#endif
|
||||
free_picture(dpy, &w->shadow_pict);
|
||||
}
|
||||
|
||||
w->a.width = ce->width;
|
||||
w->a.height = ce->height;
|
||||
w->a.border_width = ce->border_width;
|
||||
if (w->a.width != ce->width || w->a.height != ce->height
|
||||
|| w->a.border_width != ce->border_width) {
|
||||
w->a.width = ce->width;
|
||||
w->a.height = ce->height;
|
||||
w->a.border_width = ce->border_width;
|
||||
calc_win_size(dpy, w);
|
||||
}
|
||||
|
||||
if (w->a.map_state != IsUnmapped && damage) {
|
||||
XserverRegion extents = win_extents(dpy, w);
|
||||
|
@ -1912,7 +1939,9 @@ configure_win(Display *dpy, XConfigureEvent *ce) {
|
|||
add_damage(dpy, damage);
|
||||
}
|
||||
|
||||
clip_changed = True;
|
||||
// Window extents and border_size may have changed
|
||||
free_region(dpy, &w->extents);
|
||||
free_region(dpy, &w->border_size);
|
||||
}
|
||||
|
||||
w->a.override_redirect = ce->override_redirect;
|
||||
|
@ -1932,7 +1961,6 @@ circulate_win(Display *dpy, XCirculateEvent *ce) {
|
|||
}
|
||||
|
||||
restack_win(dpy, w, new_above);
|
||||
clip_changed = True;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2016,7 +2044,6 @@ damage_win(Display *dpy, XDamageNotifyEvent *de) {
|
|||
&& w->damage_bounds.y <= 0
|
||||
&& w->a.width <= w->damage_bounds.x + w->damage_bounds.width
|
||||
&& w->a.height <= w->damage_bounds.y + w->damage_bounds.height) {
|
||||
clip_changed = True;
|
||||
if (win_type_fade[w->window_type]) {
|
||||
set_fade(dpy, w, 0, get_opacity_percent(dpy, w),
|
||||
fade_in_step, 0, True, True);
|
||||
|
@ -2935,7 +2962,6 @@ main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
all_damage = None;
|
||||
clip_changed = True;
|
||||
XGrabServer(dpy);
|
||||
|
||||
XCompositeRedirectSubwindows(
|
||||
|
@ -2986,7 +3012,6 @@ main(int argc, char **argv) {
|
|||
paint++;
|
||||
XSync(dpy, False);
|
||||
all_damage = None;
|
||||
clip_changed = False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,11 @@ extern struct timeval time_start;
|
|||
#define WINDOW_TRANS 1
|
||||
#define WINDOW_ARGB 2
|
||||
|
||||
// Window flags
|
||||
|
||||
// Window size is changed
|
||||
#define WFLAG_SIZE_CHANGE 0x0001
|
||||
|
||||
/**
|
||||
* Types
|
||||
*/
|
||||
|
@ -95,12 +100,17 @@ typedef struct _win {
|
|||
Picture picture;
|
||||
XserverRegion border_size;
|
||||
XserverRegion extents;
|
||||
Bool shadow;
|
||||
Picture shadow_pict;
|
||||
int shadow_dx;
|
||||
int shadow_dy;
|
||||
int shadow_width;
|
||||
int shadow_height;
|
||||
// Type of the window.
|
||||
wintype window_type;
|
||||
/// Whether the window is focused.
|
||||
Bool focused;
|
||||
Bool destroyed;
|
||||
/// Cached width/height of the window including border.
|
||||
int widthb, heightb;
|
||||
unsigned int left_width;
|
||||
unsigned int right_width;
|
||||
unsigned int top_width;
|
||||
unsigned int bottom_width;
|
||||
|
||||
/// Current window opacity.
|
||||
opacity_t opacity;
|
||||
|
@ -111,24 +121,38 @@ typedef struct _win {
|
|||
/// Alpha mask Picture to render window with opacity.
|
||||
Picture alpha_pict;
|
||||
|
||||
/// Current window frame opacity.
|
||||
/// 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;
|
||||
|
||||
/// Whether a window has shadow. Affected by window type.
|
||||
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.
|
||||
int shadow_dy;
|
||||
/// Width of shadow. Affected by window size and commandline argument.
|
||||
int shadow_width;
|
||||
/// Height of shadow. Affected by window size and commandline argument.
|
||||
int shadow_height;
|
||||
/// Alpha mask Picture to render shadow. Affected by window size and
|
||||
/// shadow opacity.
|
||||
Picture shadow_pict;
|
||||
|
||||
/// Whether the window is to be dimmed.
|
||||
Bool dim;
|
||||
wintype window_type;
|
||||
/// Whether the window is focused.
|
||||
Bool focused;
|
||||
|
||||
/// Window flags. Definitions above.
|
||||
int_fast16_t flags;
|
||||
|
||||
unsigned long damage_sequence; /* sequence when damage was created */
|
||||
Bool destroyed;
|
||||
unsigned int left_width;
|
||||
unsigned int right_width;
|
||||
unsigned int top_width;
|
||||
unsigned int bottom_width;
|
||||
|
||||
Bool need_configure;
|
||||
XConfigureEvent queue_configure;
|
||||
|
@ -409,8 +433,7 @@ make_shadow(Display *dpy, double opacity,
|
|||
int width, int height);
|
||||
|
||||
static Picture
|
||||
shadow_picture(Display *dpy, double opacity,
|
||||
int width, int height, int *wp, int *hp);
|
||||
shadow_picture(Display *dpy, double opacity, int width, int height);
|
||||
|
||||
static Picture
|
||||
solid_picture(Display *dpy, Bool argb, double a,
|
||||
|
@ -502,6 +525,15 @@ calc_opacity(Display *dpy, win *w, Bool refetch_prop);
|
|||
static void
|
||||
calc_dim(Display *dpy, win *w);
|
||||
|
||||
static void
|
||||
determine_shadow(Display *dpy, win *w);
|
||||
|
||||
static void
|
||||
calc_win_size(Display *dpy, win *w);
|
||||
|
||||
static void
|
||||
calc_shadow_geometry(Display *dpy, win *w);
|
||||
|
||||
static void
|
||||
mark_client_win(Display *dpy, win *w, Window client);
|
||||
|
||||
|
|
Loading…
Reference in New Issue