Improvement: Split shadow_pict to shadow_pict & shadow_alpha_pict
Split w->shadow_pict to w->shadow_pict and w->shadow_alpha_pict, so that the whole w->shadow_pict need not to be rebuild on shadow opacity change. This greatly reduces CPU usage of compton when a window with shadow is fading. (My test shows the CPU usage of compton process dropped from 1.15% to 0.35% when constantly fading in and out a window.) It uses a rather painful and slow method in shadow_picture() to get around the limitation of PictStandardA8 to make colored shadows work. I wonder if there's a better approach. - Merge variables gsize and cgsize as they seemingly represent the same thing.
This commit is contained in:
parent
9139d038c2
commit
5a3dfbc064
100
src/compton.c
100
src/compton.c
|
@ -384,11 +384,10 @@ make_shadow(Display *dpy, double opacity,
|
||||||
int width, int height) {
|
int width, int height) {
|
||||||
XImage *ximage;
|
XImage *ximage;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
int gsize = gaussian_map->size;
|
|
||||||
int ylimit, xlimit;
|
int ylimit, xlimit;
|
||||||
int swidth = width + gsize;
|
int swidth = width + cgsize;
|
||||||
int sheight = height + gsize;
|
int sheight = height + cgsize;
|
||||||
int center = gsize / 2;
|
int center = cgsize / 2;
|
||||||
int x, y;
|
int x, y;
|
||||||
unsigned char d;
|
unsigned char d;
|
||||||
int x_diff;
|
int x_diff;
|
||||||
|
@ -434,10 +433,10 @@ make_shadow(Display *dpy, double opacity,
|
||||||
* corners
|
* corners
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ylimit = gsize;
|
ylimit = cgsize;
|
||||||
if (ylimit > sheight / 2) ylimit = (sheight + 1) / 2;
|
if (ylimit > sheight / 2) ylimit = (sheight + 1) / 2;
|
||||||
|
|
||||||
xlimit = gsize;
|
xlimit = cgsize;
|
||||||
if (xlimit > swidth / 2) xlimit = (swidth + 1) / 2;
|
if (xlimit > swidth / 2) xlimit = (swidth + 1) / 2;
|
||||||
|
|
||||||
for (y = 0; y < ylimit; y++) {
|
for (y = 0; y < ylimit; y++) {
|
||||||
|
@ -460,7 +459,7 @@ make_shadow(Display *dpy, double opacity,
|
||||||
* top/bottom
|
* top/bottom
|
||||||
*/
|
*/
|
||||||
|
|
||||||
x_diff = swidth - (gsize * 2);
|
x_diff = swidth - (cgsize * 2);
|
||||||
if (x_diff > 0 && ylimit > 0) {
|
if (x_diff > 0 && ylimit > 0) {
|
||||||
for (y = 0; y < ylimit; y++) {
|
for (y = 0; y < ylimit; y++) {
|
||||||
if (ylimit == cgsize) {
|
if (ylimit == cgsize) {
|
||||||
|
@ -469,8 +468,8 @@ make_shadow(Display *dpy, double opacity,
|
||||||
d = sum_gaussian(gaussian_map,
|
d = sum_gaussian(gaussian_map,
|
||||||
opacity, center, y - center, width, height);
|
opacity, center, y - center, width, height);
|
||||||
}
|
}
|
||||||
memset(&data[y * swidth + gsize], d, x_diff);
|
memset(&data[y * swidth + cgsize], d, x_diff);
|
||||||
memset(&data[(sheight - y - 1) * swidth + gsize], d, x_diff);
|
memset(&data[(sheight - y - 1) * swidth + cgsize], d, x_diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,7 +484,7 @@ make_shadow(Display *dpy, double opacity,
|
||||||
d = sum_gaussian(gaussian_map,
|
d = sum_gaussian(gaussian_map,
|
||||||
opacity, x - center, center, width, height);
|
opacity, x - center, center, width, height);
|
||||||
}
|
}
|
||||||
for (y = gsize; y < sheight - gsize; y++) {
|
for (y = cgsize; y < sheight - cgsize; y++) {
|
||||||
data[y * swidth + x] = d;
|
data[y * swidth + x] = d;
|
||||||
data[y * swidth + (swidth - x - 1)] = d;
|
data[y * swidth + (swidth - x - 1)] = d;
|
||||||
}
|
}
|
||||||
|
@ -512,48 +511,62 @@ make_shadow(Display *dpy, double opacity,
|
||||||
|
|
||||||
static Picture
|
static Picture
|
||||||
shadow_picture(Display *dpy, double opacity, int width, int height) {
|
shadow_picture(Display *dpy, double opacity, int width, int height) {
|
||||||
XImage *shadow_image;
|
XImage *shadow_image = NULL;
|
||||||
Pixmap shadow_pixmap;
|
Pixmap shadow_pixmap = None, shadow_pixmap_argb = None;
|
||||||
Picture shadow_picture;
|
Picture shadow_picture = None, shadow_picture_argb = None;
|
||||||
GC gc;
|
GC gc = None;
|
||||||
|
|
||||||
shadow_image = make_shadow(dpy, opacity, width, height);
|
shadow_image = make_shadow(dpy, opacity, width, height);
|
||||||
if (!shadow_image) return None;
|
if (!shadow_image)
|
||||||
|
return None;
|
||||||
|
|
||||||
shadow_pixmap = XCreatePixmap(dpy, root,
|
shadow_pixmap = XCreatePixmap(dpy, root,
|
||||||
shadow_image->width, shadow_image->height, 8);
|
shadow_image->width, shadow_image->height, 8);
|
||||||
|
shadow_pixmap_argb = XCreatePixmap(dpy, root,
|
||||||
|
shadow_image->width, shadow_image->height, 32);
|
||||||
|
|
||||||
if (!shadow_pixmap) {
|
if (!shadow_pixmap || !shadow_pixmap_argb)
|
||||||
XDestroyImage(shadow_image);
|
goto shadow_picture_err;
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
shadow_picture = XRenderCreatePicture(dpy, shadow_pixmap,
|
shadow_picture = XRenderCreatePicture(dpy, shadow_pixmap,
|
||||||
XRenderFindStandardFormat(dpy, PictStandardA8), 0, 0);
|
XRenderFindStandardFormat(dpy, PictStandardA8), 0, 0);
|
||||||
|
shadow_picture_argb = XRenderCreatePicture(dpy, shadow_pixmap_argb,
|
||||||
if (!shadow_picture) {
|
XRenderFindStandardFormat(dpy, PictStandardARGB32), 0, 0);
|
||||||
XDestroyImage(shadow_image);
|
if (!shadow_picture || !shadow_picture_argb)
|
||||||
XFreePixmap(dpy, shadow_pixmap);
|
goto shadow_picture_err;
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
gc = XCreateGC(dpy, shadow_pixmap, 0, 0);
|
gc = XCreateGC(dpy, shadow_pixmap, 0, 0);
|
||||||
if (!gc) {
|
if (!gc)
|
||||||
XDestroyImage(shadow_image);
|
goto shadow_picture_err;
|
||||||
XFreePixmap(dpy, shadow_pixmap);
|
|
||||||
XRenderFreePicture(dpy, shadow_picture);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
XPutImage(
|
XPutImage(dpy, shadow_pixmap, gc, shadow_image, 0, 0, 0, 0,
|
||||||
dpy, shadow_pixmap, gc, shadow_image, 0, 0, 0, 0,
|
|
||||||
shadow_image->width, shadow_image->height);
|
shadow_image->width, shadow_image->height);
|
||||||
|
XRenderComposite(dpy, PictOpSrc, cshadow_picture, shadow_picture,
|
||||||
|
shadow_picture_argb, 0, 0, 0, 0, 0, 0,
|
||||||
|
shadow_image->width, shadow_image->height);
|
||||||
|
|
||||||
XFreeGC(dpy, gc);
|
XFreeGC(dpy, gc);
|
||||||
XDestroyImage(shadow_image);
|
XDestroyImage(shadow_image);
|
||||||
XFreePixmap(dpy, shadow_pixmap);
|
XFreePixmap(dpy, shadow_pixmap);
|
||||||
|
XFreePixmap(dpy, shadow_pixmap_argb);
|
||||||
|
XRenderFreePicture(dpy, shadow_picture);
|
||||||
|
|
||||||
return shadow_picture;
|
return shadow_picture_argb;
|
||||||
|
|
||||||
|
shadow_picture_err:
|
||||||
|
if (shadow_image)
|
||||||
|
XDestroyImage(shadow_image);
|
||||||
|
if (shadow_pixmap)
|
||||||
|
XFreePixmap(dpy, shadow_pixmap);
|
||||||
|
if (shadow_pixmap_argb)
|
||||||
|
XFreePixmap(dpy, shadow_pixmap_argb);
|
||||||
|
if (shadow_picture)
|
||||||
|
XRenderFreePicture(dpy, shadow_picture);
|
||||||
|
if (shadow_picture_argb)
|
||||||
|
XRenderFreePicture(dpy, shadow_picture_argb);
|
||||||
|
if (gc)
|
||||||
|
XFreeGC(dpy, gc);
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Picture
|
static Picture
|
||||||
|
@ -1276,12 +1289,18 @@ paint_preprocess(Display *dpy, win *list) {
|
||||||
if (w->flags & WFLAG_SIZE_CHANGE)
|
if (w->flags & WFLAG_SIZE_CHANGE)
|
||||||
free_picture(dpy, &w->shadow_pict);
|
free_picture(dpy, &w->shadow_pict);
|
||||||
|
|
||||||
if (w->shadow
|
if (w->shadow && !w->shadow_pict) {
|
||||||
&& (!w->shadow_pict
|
w->shadow_pict = shadow_picture(dpy, 1,
|
||||||
|| 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->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_opacity_cur = w->shadow_opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1359,7 +1378,7 @@ paint_all(Display *dpy, XserverRegion region, win *t) {
|
||||||
// Painting shadow
|
// Painting shadow
|
||||||
if (w->shadow) {
|
if (w->shadow) {
|
||||||
XRenderComposite(
|
XRenderComposite(
|
||||||
dpy, PictOpOver, cshadow_picture, w->shadow_pict,
|
dpy, PictOpOver, w->shadow_pict, w->shadow_alpha_pict,
|
||||||
root_buffer, 0, 0, 0, 0,
|
root_buffer, 0, 0, 0, 0,
|
||||||
w->a.x + w->shadow_dx, w->a.y + w->shadow_dy,
|
w->a.x + w->shadow_dx, w->a.y + w->shadow_dy,
|
||||||
w->shadow_width, w->shadow_height);
|
w->shadow_width, w->shadow_height);
|
||||||
|
@ -1942,6 +1961,7 @@ add_win(Display *dpy, Window id, Window prev, Bool override_redirect) {
|
||||||
new->shadow_opacity = 0.0;
|
new->shadow_opacity = 0.0;
|
||||||
new->shadow_opacity_cur = 0.0;
|
new->shadow_opacity_cur = 0.0;
|
||||||
new->shadow_pict = None;
|
new->shadow_pict = None;
|
||||||
|
new->shadow_alpha_pict = None;
|
||||||
new->shadow_dx = 0;
|
new->shadow_dx = 0;
|
||||||
new->shadow_dy = 0;
|
new->shadow_dy = 0;
|
||||||
new->shadow_width = 0;
|
new->shadow_width = 0;
|
||||||
|
|
|
@ -228,9 +228,10 @@ typedef struct _win {
|
||||||
int shadow_width;
|
int shadow_width;
|
||||||
/// Height of shadow. Affected by window size and commandline argument.
|
/// Height of shadow. Affected by window size and commandline argument.
|
||||||
int shadow_height;
|
int shadow_height;
|
||||||
/// Alpha mask Picture to render shadow. Affected by window size and
|
/// Picture to render shadow. Affected by window size.
|
||||||
/// shadow opacity.
|
|
||||||
Picture shadow_pict;
|
Picture shadow_pict;
|
||||||
|
/// Alpha mask Picture to render shadow. Affected by shadow opacity.
|
||||||
|
Picture shadow_alpha_pict;
|
||||||
|
|
||||||
// Dim-related members
|
// Dim-related members
|
||||||
/// Whether the window is to be dimmed.
|
/// Whether the window is to be dimmed.
|
||||||
|
|
Loading…
Reference in New Issue