summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Grenville <[email protected]>2012-09-17 22:15:04 +0800
committerRichard Grenville <[email protected]>2012-09-17 22:15:04 +0800
commitbe3451e09798b1ec72c69e1372e94257219f4abc (patch)
tree1ad526daa2f484d561ee3d0d7e711358d7dfcd87
parente7ba091cccc4eba365302f79eee9ab0abe1ec253 (diff)
downloadtdebase-be3451e09798b1ec72c69e1372e94257219f4abc.tar.gz
tdebase-be3451e09798b1ec72c69e1372e94257219f4abc.zip
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.
-rw-r--r--compton.c167
-rw-r--r--compton.h66
2 files changed, 145 insertions, 88 deletions
diff --git a/compton.c b/compton.c
index 544121ea9..389b857b3 100644
--- a/compton.c
+++ b/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);
- }
}
/**
@@ -1684,6 +1671,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.
*
* @param dpy display to use
@@ -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;
}
}
}
diff --git a/compton.h b/compton.h
index 3ca318fe8..19f5f2aac 100644
--- a/compton.h
+++ b/compton.h
@@ -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,
@@ -503,6 +526,15 @@ 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);
static void