Jamie McCracken wrote:

> I have attached a patch to
> http://bugzilla.openedhand.com/show_bug.cgi?id=412
> 
> This should give you a transparent stage free of any defects if you have
> nvidia graphics by simply setting the alpha component of the stage
> colour to a value less than 255.
> 
> Patch also solves the annoying blending, masking and painting issues
> that plagued previous attempts at this
> 
> Patch is ready to be applied so it would be nice to get this into
> Clutter 1.0 if practical

That's great. Since I like to have this feature accessable from the Perl
bindings I backported your patch to the current stable version 0.8.8. 
Your patch applied fine besides references to 
cogl_color_get_alpha_float(), which could be easily resolved by copying
the code inline. BTW: I think on this call is a small C syntax error in
the gles/cogl.c file (an odd closed bracked).

Attached you find the patch file which applies cleanly to the current 
0.8.8 release.

To get the feature from Perl I hacked a new method into Clutter.xs 
(which is indeed a hack, because it wraps the call to clutter-x11 at the
wrong position; this was easier because clutter-x11 isn't bound to Perl
yet). But with this patch I could get a transparent stage on my desktop.
Great!

It's just important to load the Clutter module this way:

  use Clutter;
  Clutter->enable_transparent_stage;
  Clutter->init;

because the transparency enabling stuff needs to be done before init().

The Perl binding patch is attached as well.

I don't know if this stuff is worth adding to Bugzilla. If yes, just 
tell me.

Regards,

Jörn

-- 
LINUX - Linux Is Not gnU linuX
diff -urN Clutter-0.820/t/ClutterStage.t Clutter-0.820.patched/t/ClutterStage.t
--- Clutter-0.820/t/ClutterStage.t      2007-08-08 15:38:01.000000000 +0200
+++ Clutter-0.820.patched/t/ClutterStage.t      2009-03-07 12:42:32.000000000 
+0100
@@ -5,7 +5,7 @@
 isa_ok($stage, 'Clutter::Group', 'is a plane');
 isa_ok($stage, 'Clutter::Stage', 'no, is a Clutter::Stage');
 
-my $color = Clutter::Color->new(255, 0, 0, 0);
+my $color = Clutter::Color->new(255, 0, 0, 255);
 $stage->set_color($color);
 is($stage->get_color->red, 255, 'check set color (red)');
 isnt($stage->get_color->green, 255, 'check set color (green)');
diff -urN Clutter-0.820/t/ClutterStageTrans.t 
Clutter-0.820.patched/t/ClutterStageTrans.t
--- Clutter-0.820/t/ClutterStageTrans.t 1970-01-01 01:00:00.000000000 +0100
+++ Clutter-0.820.patched/t/ClutterStageTrans.t 2009-03-07 12:42:58.000000000 
+0100
@@ -0,0 +1,29 @@
+use Clutter;
+Clutter->enable_transparent_stage();
+Clutter->init;
+
+use Clutter::TestHelper tests => 9;
+
+my $stage = Clutter::Stage->get_default;
+isa_ok($stage, 'Clutter::Actor', 'is a bird');
+isa_ok($stage, 'Clutter::Group', 'is a plane');
+isa_ok($stage, 'Clutter::Stage', 'no, is a Clutter::Stage');
+
+my $color = Clutter::Color->new(255, 0, 0, 255);
+is($color->red, 255, 'check color (red)');
+$stage->set_color($color);
+is($stage->get_color->red, 255, 'check set color (red)');
+isnt($stage->get_color->green, 255, 'check set color (green)');
+
+my $trans = Clutter::Color->new(128, 0, 0, 128);
+$stage->set_color($trans);
+is($stage->get_color->red, 64, 'check set color (red trans)');
+
+$stage->set_size(800, 600);
+is($stage->get_width, 800, 'check width');
+isnt($stage->get_height, 800, 'check height');
+
+__END__
+
+Copyright (C) 2006  OpenedHand Ltd.  See the file AUTHORS for the full list.
+See LICENSE for more information.
diff -urN Clutter-0.820/xs/Clutter.xs Clutter-0.820.patched/xs/Clutter.xs
--- Clutter-0.820/xs/Clutter.xs 2008-07-17 19:19:57.000000000 +0200
+++ Clutter-0.820.patched/xs/Clutter.xs 2009-03-07 11:55:22.000000000 +0100
@@ -361,3 +361,7 @@
     C_ARGS:
         /* void */
 
+void
+clutter_enable_transparent_stage(class=NULL)
+    CODE:
+        clutter_x11_enable_transparent_stage();
diff -ru clutter-0.8.8/clutter/clutter-stage.c 
clutter-0.8.8.patched/clutter/clutter-stage.c
--- clutter-0.8.8/clutter/clutter-stage.c       2009-02-20 16:41:39.000000000 
+0100
+++ clutter-0.8.8.patched/clutter/clutter-stage.c       2009-03-07 
11:02:03.000000000 +0100
@@ -789,13 +789,19 @@
                         const ClutterColor *color)
 {
   ClutterStagePrivate *priv;
-
+  gfloat mul;
+  
   g_return_if_fail (CLUTTER_IS_STAGE (stage));
   g_return_if_fail (color != NULL);
 
+  mul = color->alpha / 255.0;
+
   priv = stage->priv;
 
-  priv->color = *color;
+  priv->color.red = mul * color->red;
+  priv->color.green = mul * color->green;
+  priv->color.blue = mul * color->blue;
+  priv->color.alpha =  color->alpha;
 
   if (CLUTTER_ACTOR_IS_VISIBLE (stage))
     clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
diff -ru clutter-0.8.8/clutter/cogl/gl/cogl.c 
clutter-0.8.8.patched/clutter/cogl/gl/cogl.c
--- clutter-0.8.8/clutter/cogl/gl/cogl.c        2009-02-20 16:41:39.000000000 
+0100
+++ clutter-0.8.8.patched/clutter/cogl/gl/cogl.c        2009-03-07 
11:38:29.000000000 +0100
@@ -174,7 +174,7 @@
   GE( glClearColor (((float) color->red / 0xff * 1.0),
                    ((float) color->green / 0xff * 1.0),
                    ((float) color->blue / 0xff * 1.0),
-                   0.0) );
+                   ((float) color->alpha / 0xff * 1.0)));
 
   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
   glDisable (GL_LIGHTING);
diff -ru clutter-0.8.8/clutter/cogl/gl/cogl-context.c 
clutter-0.8.8.patched/clutter/cogl/gl/cogl-context.c
--- clutter-0.8.8/clutter/cogl/gl/cogl-context.c        2009-02-20 
16:41:39.000000000 +0100
+++ clutter-0.8.8.patched/clutter/cogl/gl/cogl-context.c        2009-03-07 
11:02:03.000000000 +0100
@@ -102,7 +102,6 @@
 
   /* Init OpenGL state */
   GE( glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) );
-  GE( glColorMask (TRUE, TRUE, TRUE, FALSE) );
   GE( glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) );
   cogl_enable (0);
   
diff -ru clutter-0.8.8/clutter/cogl/gles/cogl.c 
clutter-0.8.8.patched/clutter/cogl/gles/cogl.c
--- clutter-0.8.8/clutter/cogl/gles/cogl.c      2009-02-20 16:41:39.000000000 
+0100
+++ clutter-0.8.8.patched/clutter/cogl/gles/cogl.c      2009-03-07 
11:28:22.000000000 +0100
@@ -95,7 +95,7 @@
   cogl_wrap_glClearColorx ((color->red << 16) / 0xff, 
                           (color->green << 16) / 0xff,
                           (color->blue << 16) / 0xff, 
-                          0xff);
+                          (float) color->alpha / 255.0));
 
   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
   cogl_wrap_glDisable (GL_LIGHTING);
diff -ru clutter-0.8.8/clutter/cogl/gles/cogl-context.c 
clutter-0.8.8.patched/clutter/cogl/gles/cogl-context.c
--- clutter-0.8.8/clutter/cogl/gles/cogl-context.c      2009-02-20 
16:41:39.000000000 +0100
+++ clutter-0.8.8.patched/clutter/cogl/gles/cogl-context.c      2009-03-07 
11:02:03.000000000 +0100
@@ -80,7 +80,6 @@
   
   /* Init OpenGL state */
   GE( cogl_wrap_glTexEnvx (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) );
-  GE( glColorMask (TRUE, TRUE, TRUE, FALSE) );
   GE( glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) );
   cogl_enable (0);
   
diff -ru clutter-0.8.8/clutter/glx/clutter-stage-glx.c 
clutter-0.8.8.patched/clutter/glx/clutter-stage-glx.c
--- clutter-0.8.8/clutter/glx/clutter-stage-glx.c       2009-02-20 
16:41:39.000000000 +0100
+++ clutter-0.8.8.patched/clutter/glx/clutter-stage-glx.c       2009-03-07 
11:02:03.000000000 +0100
@@ -47,6 +47,9 @@
 #include <GL/glx.h>
 #include <GL/gl.h>
 
+#include <X11/extensions/Xrender.h>
+
+
 static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
 
 G_DEFINE_TYPE_WITH_CODE (ClutterStageGLX,
@@ -106,6 +109,69 @@
   CLUTTER_MARK ();
 }
 
+static XVisualInfo *
+get_argb_visual_info (ClutterStageX11 *stage_x11)
+{
+
+  GLXFBConfig *fbconfigs;
+  int numfbconfigs, render_event_base, render_error_base, i;
+  XVisualInfo *visinfo = NULL;
+  XRenderPictFormat *pictFormat = NULL;
+
+  /* Make sure we have the RENDER extension */
+  if(!XRenderQueryExtension(stage_x11->xdpy, 
+                           &render_event_base, &render_error_base)) 
+      return None;
+
+
+  int attrib[] = 
+    {
+      GLX_RENDER_TYPE, GLX_RGBA_BIT,
+      GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+      GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
+      GLX_RED_SIZE, 8,
+      GLX_GREEN_SIZE, 8,
+      GLX_BLUE_SIZE, 8,
+      GLX_ALPHA_SIZE, 8,
+      GLX_DOUBLEBUFFER, True,
+      GLX_DEPTH_SIZE, 1,
+      None 
+    };
+              
+              
+  fbconfigs = glXChooseFBConfig(stage_x11->xdpy, stage_x11->xscreen, 
+                               attrib, &numfbconfigs);
+  if (!fbconfigs) 
+    return None;
+
+  /* Find an FBConfig with a visual that has a RENDER picture format that
+     has alpha */
+  for (i = 0; i < numfbconfigs; i++) 
+    {
+      visinfo = glXGetVisualFromFBConfig (stage_x11->xdpy, fbconfigs[i]);
+      if (!visinfo) 
+        continue;
+
+      pictFormat = XRenderFindVisualFormat (stage_x11->xdpy, 
+                                           visinfo->visual);
+      if (!pictFormat) 
+       continue;
+
+      if (pictFormat->direct.alphaMask > 0) 
+        break;
+       
+      XFree (visinfo);
+    }
+    
+  XFree (fbconfigs);       
+  
+  if (i == numfbconfigs)
+    return None;
+           
+  return visinfo;
+}
+
+
 static void
 clutter_stage_glx_realize (ClutterActor *actor)
 {
@@ -140,12 +206,16 @@
           XFree (stage_x11->xvisinfo);
           stage_x11->xvisinfo = None;
         }
-
-      /* The following check seems strange */
+        
+        
+      if (backend_x11->transparent_stage) 
+        stage_x11->xvisinfo = get_argb_visual_info (stage_x11);
+      
       if (stage_x11->xvisinfo == None)
         stage_x11->xvisinfo = glXChooseVisual (stage_x11->xdpy,
                                                stage_x11->xscreen,
                                                gl_attributes);
+                                          
       if (!stage_x11->xvisinfo)
         {
           g_critical ("Unable to find suitable GL visual.");
diff -ru clutter-0.8.8/clutter/x11/clutter-backend-x11.c 
clutter-0.8.8.patched/clutter/x11/clutter-backend-x11.c
--- clutter-0.8.8/clutter/x11/clutter-backend-x11.c     2009-02-20 
16:41:39.000000000 +0100
+++ clutter-0.8.8.patched/clutter/x11/clutter-backend-x11.c     2009-03-07 
11:02:03.000000000 +0100
@@ -95,6 +95,7 @@
 static gchar *clutter_display_name = NULL;
 static gint clutter_screen = 0;
 static gboolean clutter_synchronise = FALSE;
+static gboolean _transparent_stage = FALSE;
 
 /* X error trap */
 static int TrappedErrorCode = 0;
@@ -127,6 +128,9 @@
 
   if (_foreign_dpy)
     backend_x11->xdpy = _foreign_dpy;
+
+  backend_x11->transparent_stage = _transparent_stage;
+
   /*
    * Only open connection if not already set by prior call to
    * clutter_x11_set_display()
@@ -446,6 +450,21 @@
 }
 
 /**
+ * clutter_x11_enable_transparent_stage:
+ *
+ * Attempts to make stage transparent if ARGB visuals is supported; should be 
called
+ * before clutter_init(), clutter_init_with_args() or other functions
+ * pertaining Clutter's initialization process.
+ *
+ * Since: 0.9
+ */
+void
+clutter_x11_enable_transparent_stage ()
+{
+  _transparent_stage = TRUE;
+}
+
+/**
  * clutter_x11_enable_xinput:
  *
  * Enables the use of the XInput extension if present on connected
diff -ru clutter-0.8.8/clutter/x11/clutter-backend-x11.h 
clutter-0.8.8.patched/clutter/x11/clutter-backend-x11.h
--- clutter-0.8.8/clutter/x11/clutter-backend-x11.h     2009-02-20 
16:41:39.000000000 +0100
+++ clutter-0.8.8.patched/clutter/x11/clutter-backend-x11.h     2009-03-07 
11:02:03.000000000 +0100
@@ -62,7 +62,8 @@
   Screen  *xscreen;
   int      xscreen_num;
   gchar   *display_name;
-
+  gboolean transparent_stage;
+  
   /* event source */
   GSource *event_source;
   GSList  *event_filters;
diff -ru clutter-0.8.8/clutter/x11/clutter-stage-x11.c 
clutter-0.8.8.patched/clutter/x11/clutter-stage-x11.c
--- clutter-0.8.8/clutter/x11/clutter-stage-x11.c       2009-02-20 
16:41:39.000000000 +0100
+++ clutter-0.8.8.patched/clutter/x11/clutter-stage-x11.c       2009-03-07 
11:02:03.000000000 +0100
@@ -576,7 +576,7 @@
   stage->fullscreen_on_map = FALSE;
   stage->handling_configure = FALSE;
   stage->is_cursor_visible = TRUE;
-
+  
   stage->title = NULL;
 
   stage->wrapper = NULL;
@@ -677,6 +677,7 @@
   return CLUTTER_STAGE_X11 (impl)->xvisinfo;
 }
 
+
 /**
  * clutter_x11_set_stage_foreign:
  * @stage: a #ClutterStage
diff -ru clutter-0.8.8/clutter/x11/clutter-x11.h 
clutter-0.8.8.patched/clutter/x11/clutter-x11.h
--- clutter-0.8.8/clutter/x11/clutter-x11.h     2009-02-20 16:41:39.000000000 
+0100
+++ clutter-0.8.8.patched/clutter/x11/clutter-x11.h     2009-03-07 
11:02:03.000000000 +0100
@@ -134,6 +134,8 @@
 
 gboolean clutter_x11_has_composite_extension (void);
 
+void     clutter_x11_enable_transparent_stage ();
+
 G_END_DECLS
 
 #endif /* __CLUTTER_X11_H__ */
diff -ru clutter-0.8.8/config.h.in clutter-0.8.8.patched/config.h.in
--- clutter-0.8.8/config.h.in   2009-02-20 16:58:14.000000000 +0100
+++ clutter-0.8.8.patched/config.h.in   2009-03-07 11:11:12.000000000 +0100
@@ -127,6 +127,9 @@
 /* Define to 1 if we have the XFIXES X extension */
 #undef HAVE_XFIXES
 
+/* Define to 1 if we have the XRENDER X extension */
+#undef HAVE_XRENDER
+
 /* Name of package */
 #undef PACKAGE
 
diff -ru clutter-0.8.8/configure clutter-0.8.8.patched/configure
--- clutter-0.8.8/configure     2009-02-20 16:58:01.000000000 +0100
+++ clutter-0.8.8.patched/configure     2009-03-07 11:08:53.000000000 +0100
@@ -21670,6 +21670,32 @@
 echo "${ECHO_T}found" >&6; }
 fi
 
+{ echo "$as_me:$LINENO: checking for XRENDER extension" >&5
+echo $ECHO_N "checking for XRENDER extension... $ECHO_C" >&6; }
+if test -n "$PKG_CONFIG" && \
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors 
\"xrender\"") >&5
+  ($PKG_CONFIG --exists --print-errors "xrender") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  have_xrender=yes
+else
+  have_xrender=no
+fi
+if test "x$have_xrender" = "xyes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_XRENDER 1
+_ACEOF
+
+  X11_LIBS="$X11_LIBS -lXrender"
+  { echo "$as_me:$LINENO: result: found" >&5
+echo "${ECHO_T}found" >&6; }
+else
+  { echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6; }
+fi
+
 { echo "$as_me:$LINENO: checking for XFIXES extension >= 3" >&5
 echo $ECHO_N "checking for XFIXES extension >= 3... $ECHO_C" >&6; }
 if test -n "$PKG_CONFIG" && \
diff -ru clutter-0.8.8/configure.ac clutter-0.8.8.patched/configure.ac
--- clutter-0.8.8/configure.ac  2009-02-20 16:57:24.000000000 +0100
+++ clutter-0.8.8.patched/configure.ac  2009-03-07 11:02:31.000000000 +0100
@@ -180,6 +180,16 @@
   AC_MSG_RESULT([found])
 fi
 
+AC_MSG_CHECKING([for XRENDER extension])
+PKG_CHECK_EXISTS([xrender], [have_xrender=yes], [have_xrender=no])
+if test "x$have_xrender" = "xyes"; then
+  AC_DEFINE(HAVE_XRENDER, 1, [Define to 1 if we have the XRENDER X extension])
+  X11_LIBS="$X11_LIBS -lXrender"
+  AC_MSG_RESULT([found])
+else
+  AC_MSG_RESULT([not found])
+fi
+
 AC_MSG_CHECKING([for XFIXES extension >= 3])
 PKG_CHECK_EXISTS([xfixes >= 3], [have_xfixes=yes], [have_xfixes=no])
 if test "x$have_xfixes" = "xyes"; then

Attachment: pgpaZgnwbvuAR.pgp
Description: PGP signature

Reply via email to