From da85de48a9d078eeb5a437482c41c85884496318 Mon Sep 17 00:00:00 2001 From: Richard Grenville Date: Wed, 20 Mar 2013 17:29:45 +0800 Subject: Feature #69: GLX: Blur background - GLX backend: Add blur background support using a GLSL shader. Only tested with nvidia-drivers-313.26. Known to cause quite some decrease in performance (~10%?). - Detach shaders in glx_create_program(). Misc changes. --- compton.c | 98 +++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 57 insertions(+), 41 deletions(-) (limited to 'compton.c') diff --git a/compton.c b/compton.c index 2b1ca9204..9e8623ea8 100644 --- a/compton.c +++ b/compton.c @@ -1329,60 +1329,76 @@ win_build_picture(session_t *ps, win *w, XRenderPictFormat *pictfmt) { static inline void win_blur_background(session_t *ps, win *w, Picture tgt_buffer, XserverRegion reg_paint) { - const static int convolution_blur_size = 3; - // Convolution filter parameter (box blur) - // gaussian or binomial filters are definitely superior, yet looks - // like they aren't supported as of xorg-server-1.13.0 - XFixed convolution_blur[] = { - // Must convert to XFixed with XDoubleToFixed() - // Matrix size - XDoubleToFixed(convolution_blur_size), - XDoubleToFixed(convolution_blur_size), - // Matrix - XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1), - XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1), - XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1), - }; - const int x = w->a.x; const int y = w->a.y; const int wid = w->widthb; const int hei = w->heightb; - // Directly copying from tgt_buffer does not work, so we create a - // Picture in the middle. - Picture tmp_picture = win_build_picture(ps, w, NULL); - - if (!tmp_picture) - return; - + double factor_center = 1.0; // Adjust blur strength according to window opacity, to make it appear // better during fading if (!ps->o.blur_background_fixed) { double pct = 1.0 - get_opacity_percent(w) * (1.0 - 1.0 / 9.0); - convolution_blur[2 + convolution_blur_size + ((convolution_blur_size - 1) / 2)] = XDoubleToFixed(pct * 8.0 / (1.1 - pct)); + factor_center = pct * 8.0 / (1.1 - pct); } - // Minimize the region we try to blur, if the window itself is not - // opaque, only the frame is. - if (WMODE_SOLID == w->mode && w->frame_opacity) { - XserverRegion reg_all = border_size(ps, w, false); - XserverRegion reg_noframe = win_get_region_noframe(ps, w, false); - XFixesSubtractRegion(ps->dpy, reg_noframe, reg_all, reg_noframe); - XFixesSetPictureClipRegion(ps->dpy, tmp_picture, reg_noframe, 0, 0); - free_region(ps, ®_all); - free_region(ps, ®_noframe); - } + switch (ps->o.backend) { + case BKEND_XRENDER: + { + const static int convolution_blur_size = 3; + // Convolution filter parameter (box blur) + // gaussian or binomial filters are definitely superior, yet looks + // like they aren't supported as of xorg-server-1.13.0 + XFixed convolution_blur[] = { + // Must convert to XFixed with XDoubleToFixed() + // Matrix size + XDoubleToFixed(convolution_blur_size), + XDoubleToFixed(convolution_blur_size), + // Matrix + XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1), + XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1), + XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1), + }; + + // Directly copying from tgt_buffer does not work, so we create a + // Picture in the middle. + Picture tmp_picture = win_build_picture(ps, w, NULL); + + if (!tmp_picture) + return; - // Copy the content to tmp_picture, then copy back. The filter must - // be applied on tgt_buffer, to get the nearby pixels outside the - // window. - XRenderSetPictureFilter(ps->dpy, tgt_buffer, XRFILTER_CONVOLUTION, (XFixed *) convolution_blur, sizeof(convolution_blur) / sizeof(XFixed)); - XRenderComposite(ps->dpy, PictOpSrc, tgt_buffer, None, tmp_picture, x, y, 0, 0, 0, 0, wid, hei); - xrfilter_reset(ps, tgt_buffer); - XRenderComposite(ps->dpy, PictOpSrc, tmp_picture, None, tgt_buffer, 0, 0, 0, 0, x, y, wid, hei); + convolution_blur[2 + convolution_blur_size + ((convolution_blur_size - 1) / 2)] = XDoubleToFixed(factor_center); - free_picture(ps, &tmp_picture); + // Minimize the region we try to blur, if the window itself is not + // opaque, only the frame is. + if (WMODE_SOLID == w->mode && w->frame_opacity) { + XserverRegion reg_all = border_size(ps, w, false); + XserverRegion reg_noframe = win_get_region_noframe(ps, w, false); + XFixesSubtractRegion(ps->dpy, reg_noframe, reg_all, reg_noframe); + XFixesSetPictureClipRegion(ps->dpy, tmp_picture, reg_noframe, 0, 0); + free_region(ps, ®_all); + free_region(ps, ®_noframe); + } + + // Copy the content to tmp_picture, then copy back. The filter must + // be applied on tgt_buffer, to get the nearby pixels outside the + // window. + XRenderSetPictureFilter(ps->dpy, tgt_buffer, XRFILTER_CONVOLUTION, (XFixed *) convolution_blur, sizeof(convolution_blur) / sizeof(XFixed)); + XRenderComposite(ps->dpy, PictOpSrc, tgt_buffer, None, tmp_picture, x, y, 0, 0, 0, 0, wid, hei); + xrfilter_reset(ps, tgt_buffer); + XRenderComposite(ps->dpy, PictOpSrc, tmp_picture, None, tgt_buffer, 0, 0, 0, 0, x, y, wid, hei); + + free_picture(ps, &tmp_picture); + } + break; +#ifdef CONFIG_VSYNC_OPENGL + case BKEND_GLX: + glx_blur_dst(ps, x, y, wid, hei, ps->glx_z - 0.5, factor_center); + break; +#endif + default: + assert(0); + } } static void -- cgit v1.2.1