Branch: master

d8287f97 2014-11-25 13:39:37 Timothy Pearson
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
M ksmserver/shutdowndlg.cpp
M twin/compton-tde/common.h
M twin/compton-tde/compton.c
M twin/compton-tde/opengl.c
diff --git a/ksmserver/shutdowndlg.cpp b/ksmserver/shutdowndlg.cpp
index 5c50602..6573f8b 100644
--- a/ksmserver/shutdowndlg.cpp
+++ b/ksmserver/shutdowndlg.cpp
@@ -87,6 +87,11 @@
 		m_grayImage.setAlphaBuffer(false);
 		m_grayImage.fill(0);	// Set the alpha buffer to 0 (fully transparent)
 		m_grayImage.setAlphaBuffer(true);
+
+		// Signal that we want a greyscale filter on the transparency
+		Atom kde_wm_transparent_greyscale_filter;
+		kde_wm_transparent_greyscale_filter = XInternAtom(tqt_xdisplay(), "_TDE_TRANSPARENCY_FILTER_GREYSCALE_BLEND", False);
+		XChangeProperty(tqt_xdisplay(), winId(), kde_wm_transparent_greyscale_filter, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L);
 	}
 	else {
 		// The hacks below aren't needed any more because Qt3 supports true transparency for the fading logout screen when composition is available
@@ -135,10 +140,10 @@
 				m_root.resize( width(), height() );
 				TQImage blendedImage = m_grayImage;
 				TQPainter p;
-							p.begin( &m_root );
-							blendedImage.setAlphaBuffer(false);
-							p.drawImage( 0, 0, blendedImage );
-							p.end();
+				p.begin( &m_root );
+				blendedImage.setAlphaBuffer(false);
+				p.drawImage( 0, 0, blendedImage );
+				p.end();
 
 				setBackgroundPixmap( m_root );
 				setGeometry( TQApplication::desktop()->geometry() );
@@ -150,7 +155,7 @@
 				uchar * end = m_grayImage.bits() + m_grayImage.numBytes();
 
 				while ( r != end ) {
-					*reinterpret_cast<TQRgb*>(r) = tqRgba(0, 0, 0, 128);
+					*reinterpret_cast<TQRgb*>(r) = tqRgba(0, 0, 0, 255);
 					r += 4;
 				}
 
@@ -220,7 +225,6 @@
 			{
 				TQImage img( imgWidth, y2-start_y1, 32 );
 				memcpy( img.bits(), m_grayImage.scanLine( start_y1 ), ( y2-start_y1 ) * imgWidth * 4 );
-				register uchar * rs = m_unfadedImage.scanLine( start_y1 );
 				register uchar * rd = img.bits();
 				for( int y = start_y1; y < y2; ++y )
 				{
@@ -228,8 +232,8 @@
 					short int opac = static_cast<short int>( 128 - cosf( M_PI*(y-y1)/heightUnit )*128.0f );
 					for( short int x = 0; x < imgWidth; ++x )
 					{
-						*reinterpret_cast<TQRgb*>(rd) = tqRgba(0, 0, 0, ((255.0-opac)/(255.0/127.0)));
-						rs += 4; rd += 4;
+						*reinterpret_cast<TQRgb*>(rd) = tqRgba(0, 0, 0, ((255.0-opac)));
+						rd += 4;
 					}
 				}
 				bitBlt( this, 0, start_y1, &img );
diff --git a/twin/compton-tde/common.h b/twin/compton-tde/common.h
index 759e646..9ff5a21 100644
--- a/twin/compton-tde/common.h
+++ b/twin/compton-tde/common.h
@@ -490,6 +490,21 @@
 } glx_blur_cache_t;
 
 typedef struct {
+  /// Fragment shader for greyscale.
+  GLuint frag_shader;
+  /// GLSL program for greyscale.
+  GLuint prog;
+  /// Location of uniform "greyscale_weights" in greyscale GLSL program.
+  GLint unifm_greyscale_weights;
+  /// Location of uniform "enable_blend" in greyscale GLSL program.
+  GLint unifm_enable_blend;
+  /// Location of uniform "tex_scr" in greyscale GLSL program.
+  GLint unifm_tex_scr;
+  /// Location of uniform "alpha_scr" in greyscale GLSL program.
+  GLint unifm_alpha_scr;
+} glx_greyscale_t;
+
+typedef struct {
   /// Framebuffer used for greyscale conversion.
   GLuint fbo;
   /// Textures used for greyscale conversion.
@@ -817,6 +832,9 @@
 #ifdef CONFIG_VSYNC_OPENGL_GLSL
   glx_blur_pass_t blur_passes[MAX_BLUR_PASS];
 #endif
+#ifdef CONFIG_VSYNC_OPENGL_GLSL
+  glx_greyscale_t greyscale_glsl;
+#endif
 } glx_session_t;
 
 #define CGLX_SESSION_INIT { .context = NULL }
@@ -1068,6 +1086,8 @@
   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;
+  /// Atom of property <code>_TDE_TRANSPARENCY_FILTER_GREYSCALE_BLEND</code>.
+  Atom atom_win_type_tde_transparency_filter_greyscale_blend;
   /// Array of atoms of all possible window types.
   Atom atoms_wintypes[NUM_WINTYPES];
   /// Linked list of additional atoms to track.
@@ -1262,6 +1282,11 @@
   bool greyscale_background;
   /// Background state on last paint.
   bool greyscale_background_last;
+
+  /// Whether to set window background to blended greyscale.
+  bool greyscale_blended_background;
+  /// Blended greyscale alpha divisor.
+  int greyscale_blended_background_alpha_divisor;
 
   /// Whether to show black background
   bool show_black_background;
@@ -2202,6 +2227,9 @@
 bool
 glx_init_blur(session_t *ps);
 
+bool
+glx_init_greyscale(session_t *ps);
+
 #ifdef CONFIG_VSYNC_OPENGL_GLSL
 bool
 glx_load_prog_main(session_t *ps,
@@ -2245,7 +2273,7 @@
 
 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);
+    glx_texture_t *ptex, 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,
@@ -2342,7 +2370,6 @@
 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;
 }
diff --git a/twin/compton-tde/compton.c b/twin/compton-tde/compton.c
index dea363f..d209512 100644
--- a/twin/compton-tde/compton.c
+++ b/twin/compton-tde/compton.c
@@ -944,6 +944,9 @@
 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 @@
 
   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 @@
 #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 @@
 
   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 @@
     }
   }
 
 ** Diff limit reached (max: 250 lines) **
04837bf9 2014-11-25 13:40:09 Timothy Pearson
Merge branch 'master' of https://scm.trinitydesktop.org/scm/git/tdebase
M doc/tdm/index.docbook
M kcontrol/displayconfig/displayconfig.cpp
M kcontrol/displayconfig/displayconfig.h
M kcontrol/tdm/main.cpp
M kcontrol/tdm/main.h
M kcontrol/tdm/tdm.desktop
 ** Diff limit reached (max: 250 lines) **