Branch: master

a582c6e2 2014-11-22 16:51:56 Timothy Pearson
Add optional global/per window greyscale transparency filter to compton-tde
M twin/compton-tde/common.h
M twin/compton-tde/compton.c
M twin/compton-tde/compton.h
M twin/compton-tde/opengl.c
diff --git a/twin/compton-tde/common.h b/twin/compton-tde/common.h
index acaf686..ddb00fa 100644
--- a/twin/compton-tde/common.h
+++ b/twin/compton-tde/common.h
@@ -490,6 +490,17 @@
 } glx_blur_cache_t;
 
 typedef struct {
+  /// Framebuffer used for greyscale conversion.
+  GLuint fbo;
+  /// Textures used for greyscale conversion.
+  GLuint textures[2];
+  /// Width of the textures.
+  int width;
+  /// Height of the textures.
+  int height;
+} glx_greyscale_cache_t;
+
+typedef struct {
   /// GLSL program.
   GLuint prog;
   /// Location of uniform "opacity" in window GLSL program.
@@ -714,6 +725,10 @@
   c2_lptr_t *blur_background_blacklist;
   /// Blur convolution kernel.
   XFixed *blur_kerns[MAX_BLUR_PASS];
+  /// Whether to set background of semi-transparent / ARGB windows to greyscale.
+  bool greyscale_background;
+  /// Greyscale background blacklist. A linked list of conditions.
+  c2_lptr_t *greyscale_background_blacklist;
   /// How much to dim an inactive window. 0.0 - 1.0, 0 to disable.
   double inactive_dim;
   /// Whether to use fixed inactive dim opacity, instead of deciding
@@ -1047,10 +1062,12 @@
   Atom atom_compton_shadow;
   /// Atom of property <code>_NET_WM_WINDOW_TYPE</code>.
   Atom atom_win_type;
-  /// Atom of property <code>_KDE_TRANSPARENT_TO_BLACK</code>.
+  /// Atom of property <code>_TDE_TRANSPARENT_TO_BLACK</code>.
   Atom atom_win_type_tde_transparent_to_black;
-  /// Atom of property <code>_KDE_TRANSPARENT_TO_DESKTOP</code>.
+  /// Atom of property <code>_TDE_TRANSPARENT_TO_DESKTOP</code>.
   Atom atom_win_type_tde_transparent_to_desktop;
+  /// Atom of property <code>_TDE_TRANSPARENCY_FILTER_GREYSCALE</code>.
+  Atom atom_win_type_tde_transparency_filter_greyscale;
   /// Array of atoms of all possible window types.
   Atom atoms_wintypes[NUM_WINTYPES];
   /// Linked list of additional atoms to track.
@@ -1241,6 +1258,11 @@
   /// Background state on last paint.
   bool blur_background_last;
 
+  /// Whether to set window background to greyscale.
+  bool greyscale_background;
+  /// Background state on last paint.
+  bool greyscale_background_last;
+
   /// Whether to show black background
   bool show_black_background;
 
@@ -1250,6 +1272,9 @@
 #ifdef CONFIG_VSYNC_OPENGL_GLSL
   /// Textures and FBO background blur use.
   glx_blur_cache_t glx_blur_cache;
+
+  /// Textures and FBO greyscale background use.
+  glx_greyscale_cache_t glx_greyscale_cache;
 #endif
 } win;
 
@@ -2219,6 +2244,10 @@
     GLfloat factor, XserverRegion reg_tgt, const reg_data_t *pcache_reg);
 
 bool
+glx_greyscale_dst(session_t *ps, int dx, int dy, int width, int height, float z,
+    XserverRegion reg_tgt, const reg_data_t *pcache_reg, glx_greyscale_cache_t *pbc);
+
+bool
 glx_render_(session_t *ps, const glx_texture_t *ptex,
     int x, int y, int dx, int dy, int width, int height, int z,
     double opacity, bool argb, bool neg,
@@ -2306,6 +2335,26 @@
   free_glx_fbo(ps, &pbc->fbo);
   free_glx_bc_resize(ps, pbc);
 }
+
+/**
+ * Free data in glx_greyscale_cache_t on resize.
+ */
+static inline void
+free_glx_gc_resize(session_t *ps, glx_greyscale_cache_t *pbc) {
+  free_texture_r(ps, &pbc->textures[0]);
+  free_texture_r(ps, &pbc->textures[1]);
+  pbc->width = 0;
+  pbc->height = 0;
+}
+
+/**
+ * Free a glx_greyscale_cache_t
+ */
+static inline void
+free_glx_gc(session_t *ps, glx_greyscale_cache_t *pbc) {
+  free_glx_fbo(ps, &pbc->fbo);
+  free_glx_gc_resize(ps, pbc);
+}
 #endif
 #endif
 
@@ -2349,6 +2398,7 @@
   free_paint_glx(ps, &w->shadow_paint);
 #ifdef CONFIG_VSYNC_OPENGL_GLSL
   free_glx_bc(ps, &w->glx_blur_cache);
+  free_glx_gc(ps, &w->glx_greyscale_cache);
 #endif
 }
 
diff --git a/twin/compton-tde/compton.c b/twin/compton-tde/compton.c
index 36af91f..4a4d058 100644
--- a/twin/compton-tde/compton.c
+++ b/twin/compton-tde/compton.c
@@ -1260,6 +1260,7 @@
       w->fade = w->fade_last;
       win_set_invert_color(ps, w, w->invert_color_last);
       win_set_blur_background(ps, w, w->blur_background_last);
+      win_set_greyscale_background(ps, w, w->greyscale_background_last);
     }
 
     // Update window opacity target and dim state if asked
@@ -1407,6 +1408,7 @@
         w->fade_last = w->fade;
         w->invert_color_last = w->invert_color;
         w->blur_background_last = w->blur_background;
+        w->greyscale_background_last = w->greyscale_background;
       }
     }
   }
@@ -1546,6 +1548,53 @@
   return true;
 }
 
+/**
+ * @brief Make an area on a buffer greyscale.
+ *
+ * @param ps current session
+ * @param tgt_buffer a buffer as both source and destination
+ * @param x x pos
+ * @param y y pos
+ * @param wid width
+ * @param hei height
+ * @param reg_clip a clipping region to be applied on intermediate buffers
+ *
+ * @return true if successful, false otherwise
+ */
+static bool
+xr_greyscale_dst(session_t *ps, Picture tgt_buffer,
+    int x, int y, int wid, int hei, XserverRegion reg_clip) {
+
+  // Directly copying from tgt_buffer to it does not work, so we create a
+  // Picture in the middle.
+  Picture tmp_picture = xr_build_picture(ps, wid, hei, NULL);
+
+  if (!tmp_picture) {
+    printf_errf("(): Failed to build intermediate Picture.");
+    return false;
+  }
+
+  if (reg_clip && tmp_picture)
+    XFixesSetPictureClipRegion(ps->dpy, tmp_picture, reg_clip, 0, 0);
+
+  Picture src_pict = tgt_buffer, dst_pict = tmp_picture;
+
+  XRenderComposite(ps->dpy, PictOpHSLLuminosity, src_pict, None,
+      dst_pict, x, y, 0, 0, 0, 0, wid, hei);
+
+      XserverRegion tmp = src_pict;
+      src_pict = dst_pict;
+      dst_pict = tmp;
+
+  if (src_pict != tgt_buffer)
+    XRenderComposite(ps->dpy, PictOpSrc, src_pict, None, tgt_buffer,
+        0, 0, 0, 0, x, y, wid, hei);
+
+  free_picture(ps, &tmp_picture);
+
+  return true;
+}
+
 /*
  * WORK-IN-PROGRESS!
 static void
@@ -1640,6 +1689,35 @@
       // TODO: Handle frame opacity
       glx_blur_dst(ps, x, y, wid, hei, ps->psglx->z - 0.5, factor_center,
           reg_paint, pcache_reg, &w->glx_blur_cache);
+      break;
+#endif
+    default:
+      assert(0);
+  }
+}
+
+/**
+ * Set the background of a window to greyscale.
+ */
+static inline void
+win_greyscale_background(session_t *ps, win *w, Picture tgt_buffer,
+    XserverRegion reg_paint, const reg_data_t *pcache_reg) {
+  const int x = w->a.x;
+  const int y = w->a.y;
+  const int wid = w->widthb;
+  const int hei = w->heightb;
+
+  switch (ps->o.backend) {
+    case BKEND_XRENDER:
+    case BKEND_XR_GLX_HYBRID:
+      {
+        xr_greyscale_dst(ps, tgt_buffer, x, y, wid, hei, reg_paint);
+      }
+      break;
+#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);
       break;
 #endif
     default:
@@ -2111,6 +2189,11 @@
           win_blur_background(ps, w, ps->tgt_buffer.pict, reg_paint, &cache_reg);
         }
 
+        // Set window background to greyscale
+        if (w->greyscale_background && (!win_is_solid(ps, w))) {
+          win_greyscale_background(ps, w, ps->tgt_buffer.pict, reg_paint, &cache_reg);
+        }
+
         // Painting the window
         win_paint_win(ps, w, reg_paint, &cache_reg);
       }
@@ -2403,6 +2486,7 @@
   }
 
   win_determine_blur_background(ps, w);
+  win_determine_greyscale_background(ps, w);
 
   w->damaged = false;
 
@@ -2517,6 +2601,28 @@
 static double
 get_opacity_percent(win *w) {
   return ((double) w->opacity) / OPAQUE;
 ** Diff limit reached (max: 250 lines) **
fb7b5f6d 2014-11-22 16:52:29 Timothy Pearson
Merge branch 'master' of https://scm.trinitydesktop.org/scm/git/tdebase
M tdmlib/dmctl.cpp
 ** Diff limit reached (max: 250 lines) **