summaryrefslogtreecommitdiffstats
path: root/twin/compton-tde/compton.c
diff options
context:
space:
mode:
authorTimothy Pearson <[email protected]>2014-11-25 13:38:16 -0600
committerTimothy Pearson <[email protected]>2014-11-25 13:39:37 -0600
commitd8287f97874be7db0d498f3808f68bdfee902ba3 (patch)
tree0c8de5b79b37732eb199d69e3e6cdd945cd3b816 /twin/compton-tde/compton.c
parentf1baae5fff89ee638864f7d9b82f88b9dfa59796 (diff)
downloadtdebase-d8287f97874be7db0d498f3808f68bdfee902ba3.tar.gz
tdebase-d8287f97874be7db0d498f3808f68bdfee902ba3.zip
Rewrite greyscale OpenGL system to use GLSL
Add ability to blend color and greyscale based on window alpha (actual window alpha currently set at 0.5 when blending is enabled) Reenable greyscale logout effect when compositor is in use
Diffstat (limited to 'twin/compton-tde/compton.c')
-rw-r--r--twin/compton-tde/compton.c156
1 files changed, 154 insertions, 2 deletions
diff --git a/twin/compton-tde/compton.c b/twin/compton-tde/compton.c
index dea363f60..d2095123f 100644
--- a/twin/compton-tde/compton.c
+++ b/twin/compton-tde/compton.c
@@ -944,6 +944,9 @@ static Bool
determine_window_transparency_filter_greyscale(const session_t *ps, Window w);
static Bool
+determine_window_transparency_filter_greyscale_blended(const session_t *ps, Window w);
+
+static Bool
determine_window_transparent_to_black(const session_t *ps, Window w);
static Bool
@@ -1590,6 +1593,7 @@ xr_greyscale_dst(session_t *ps, Picture tgt_buffer,
XRenderComposite(ps->dpy, PictOpSrc, ps->black_picture, None,
tmp_picture, 0, 0, 0, 0, 0, 0, wid, hei);
+
XRenderComposite(ps->dpy, PictOpHSLLuminosity, tgt_buffer, None,
tmp_picture, x, y, 0, 0, 0, 0, wid, hei);
@@ -1723,7 +1727,7 @@ win_greyscale_background(session_t *ps, win *w, Picture tgt_buffer,
#ifdef CONFIG_VSYNC_OPENGL_GLSL
case BKEND_GLX:
glx_greyscale_dst(ps, x, y, wid, hei, ps->psglx->z - 0.5,
- reg_paint, pcache_reg, &w->glx_greyscale_cache);
+ NULL, reg_paint, pcache_reg, &w->glx_greyscale_cache);
break;
#endif
default:
@@ -1821,6 +1825,71 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint,
Picture pict = w->paint.pict;
+ if (w->greyscale_blended_background) {
+ // Set window background to greyscale
+ switch (ps->o.backend) {
+ case BKEND_XRENDER:
+ case BKEND_XR_GLX_HYBRID:
+ {
+ // Blend here such that 0 window alpha is fully colored and 100 window alpha is fully greyscale
+ // PictOpInReverse is used to copy alpha from the source to the destination while preserving destination color
+ // provided that the source has alpha set to 1 (equivalent of CAIRO_OPERATOR_DEST_IN)
+ const int x = w->a.x;
+ const int y = w->a.y;
+ const int wid = w->widthb;
+ const int hei = w->heightb;
+ XserverRegion reg_clip = reg_paint;
+ Picture tgt_buffer = ps->tgt_buffer.pict;
+
+ // Apply clipping region to save some CPU
+ if (reg_paint) {
+ XserverRegion reg = copy_region(ps, reg_paint);
+ XFixesTranslateRegion(ps->dpy, reg, -x, -y);
+ XFixesSetPictureClipRegion(ps->dpy, pict, 0, 0, reg);
+ free_region(ps, &reg);
+ }
+
+ // Create greyscale version of background
+ Picture greyscale_picture = xr_build_picture(ps, wid, hei, w->pictfmt);
+ XRenderComposite(ps->dpy, PictOpSrc, tgt_buffer, None,
+ greyscale_picture, x, y, 0, 0, 0, 0, wid, hei);
+ win_greyscale_background(ps, w, greyscale_picture, reg_paint, pcache_reg);
+
+ Picture tmp_picture = xr_build_picture(ps, wid, hei, w->pictfmt);
+
+ if (!tmp_picture) {
+ printf_errf("(): Failed to build intermediate Picture.");
+ }
+ else {
+ if (reg_clip && tmp_picture)
+ XFixesSetPictureClipRegion(ps->dpy, tmp_picture, reg_clip, 0, 0);
+
+ // Transfer greyscale picture to temporary picture
+ XRenderComposite(ps->dpy, PictOpSrc, greyscale_picture, None,
+ tmp_picture, 0, 0, 0, 0, 0, 0, wid, hei);
+
+ // Transfer alpha of window to temporary picture
+ XRenderComposite(ps->dpy, PictOpInReverse, pict, None,
+ tmp_picture, 0, 0, 0, 0, 0, 0, wid, hei);
+
+ // Blend greyscale picture over main color buffer
+ XRenderComposite(ps->dpy, PictOpOver, tmp_picture, None, tgt_buffer,
+ 0, 0, 0, 0, x, y, wid, hei);
+
+ free_picture(ps, &tmp_picture);
+ free_picture(ps, &greyscale_picture);
+ }
+ }
+ break;
+#ifdef CONFIG_VSYNC_OPENGL
+ case BKEND_GLX:
+ glx_greyscale_dst(ps, x, y, wid, hei, ps->psglx->z - 0.5,
+ w->paint.ptex, reg_paint, pcache_reg, &w->glx_greyscale_cache);
+ break;
+#endif
+ }
+ }
+
// Invert window color, if required
if (bkend_use_xrender(ps) && w->invert_color) {
Picture newpict = xr_build_picture(ps, wid, hei, w->pictfmt);
@@ -1846,7 +1915,12 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint,
}
}
- const double dopacity = get_opacity_percent(w);
+ double dopacity = get_opacity_percent(w);
+
+ if (w->greyscale_blended_background) {
+ double scaling_factor = (1.0 / w->greyscale_blended_background_alpha_divisor);
+ dopacity = dopacity * scaling_factor;
+ }
if (!w->frame_opacity) {
win_render(ps, w, 0, 0, wid, hei, dopacity, reg_paint, pcache_reg, pict);
@@ -2439,6 +2513,7 @@ map_win(session_t *ps, Window id) {
/* This needs to be here since we don't get PropertyNotify when unmapped */
w->opacity = wid_get_opacity_prop(ps, w->id, OPAQUE);
w->greyscale_background = determine_window_transparency_filter_greyscale(ps, id);
+ w->greyscale_blended_background = determine_window_transparency_filter_greyscale_blended(ps, id);
w->show_root_tile = determine_window_transparent_to_desktop(ps, id);
w->show_black_background = determine_window_transparent_to_black(ps, id);
@@ -2632,6 +2707,28 @@ get_window_transparency_filter_greyscale(const session_t *ps, Window w)
}
static Bool
+get_window_transparency_filter_greyscale_blended(const session_t *ps, Window w)
+{
+ Atom actual;
+ int format;
+ unsigned long n, left;
+
+ unsigned char *data;
+ int result = XGetWindowProperty (ps->dpy, w, ps->atom_win_type_tde_transparency_filter_greyscale_blend, 0L, 1L, False,
+ XA_ATOM, &actual, &format,
+ &n, &left, &data);
+
+ if (result == Success && data != None && format == 32 )
+ {
+ Atom a;
+ a = *(long*)data;
+ XFree ( (void *) data);
+ return True;
+ }
+ return False;
+}
+
+static Bool
get_window_transparent_to_desktop(const session_t *ps, Window w)
{
Atom actual;
@@ -2711,6 +2808,41 @@ determine_window_transparency_filter_greyscale (const session_t *ps, Window w)
}
static Bool
+determine_window_transparency_filter_greyscale_blended (const session_t *ps, Window w)
+{
+ Window root_return, parent_return;
+ Window *children = NULL;
+ unsigned int nchildren, i;
+ Bool type;
+
+ type = get_window_transparency_filter_greyscale_blended (ps, w);
+ if (type == True) {
+ return True;
+ }
+
+ if (!XQueryTree (ps->dpy, w, &root_return, &parent_return, &children,
+ &nchildren))
+ {
+ /* XQueryTree failed. */
+ if (children)
+ XFree ((void *)children);
+ return False;
+ }
+
+ for (i = 0;i < nchildren;i++)
+ {
+ type = determine_window_transparency_filter_greyscale_blended (ps, children[i]);
+ if (type == True)
+ return True;
+ }
+
+ if (children)
+ XFree ((void *)children);
+
+ return False;
+}
+
+static Bool
determine_window_transparent_to_desktop (const session_t *ps, Window w)
{
Window root_return, parent_return;
@@ -3449,6 +3581,8 @@ add_win(session_t *ps, Window id, Window prev) {
.blur_background = false,
.greyscale_background = false,
+ .greyscale_blended_background = false,
+ .greyscale_blended_background_alpha_divisor = 2,
.show_black_background = false,
.show_root_tile = false,
@@ -6696,6 +6830,7 @@ init_atoms(session_t *ps) {
ps->atom_win_type_tde_transparent_to_black = get_atom(ps, "_TDE_TRANSPARENT_TO_BLACK");
ps->atom_win_type_tde_transparent_to_desktop = get_atom(ps, "_TDE_TRANSPARENT_TO_DESKTOP");
ps->atom_win_type_tde_transparency_filter_greyscale = get_atom(ps, "_TDE_TRANSPARENCY_FILTER_GREYSCALE");
+ ps->atom_win_type_tde_transparency_filter_greyscale_blend = get_atom(ps, "_TDE_TRANSPARENCY_FILTER_GREYSCALE_BLEND");
}
#ifdef CONFIG_XRANDR
@@ -7136,6 +7271,22 @@ init_filters(session_t *ps) {
}
}
+ // Greyscale filter
+ switch (ps->o.backend) {
+ case BKEND_XRENDER:
+ case BKEND_XR_GLX_HYBRID:
+ {
+ break;
+ }
+#ifdef CONFIG_VSYNC_OPENGL
+ case BKEND_GLX:
+ {
+ if (!glx_init_greyscale(ps))
+ return false;
+ }
+#endif
+ }
+
return true;
}
@@ -7666,6 +7817,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
.atom_win_type_tde_transparent_to_black = None,
.atom_win_type_tde_transparent_to_desktop = None,
.atom_win_type_tde_transparency_filter_greyscale = None,
+ .atom_win_type_tde_transparency_filter_greyscale_blend = None,
.atoms_wintypes = { 0 },
.track_atom_lst = NULL,