]> Pileus Git - ~andy/gtk/commitdiff
Fill in unused bits so they can be used for the depth-32 target case.
authorOwen Taylor <otaylor@redhat.com>
Mon, 9 May 2005 22:54:10 +0000 (22:54 +0000)
committerOwen Taylor <otaylor@src.gnome.org>
Mon, 9 May 2005 22:54:10 +0000 (22:54 +0000)
2005-05-09  Owen Taylor  <otaylor@redhat.com>

        * gdk/gdkrgb.c (gdk_rgb_convert_0888_br, gdk_rgb_convert_8880_br):
        Fill in unused bits so they can be used for the depth-32 target case.
        Rewrite so that that gives a marginal speedup rather than a
        marginal slowdown. (on x86)

        * gdk/gdkscreen.h gdk/x11/gdkscreen-x11.[ch] gdk/x11/gdkvisual-x11.c:
        Add gdk_screen_get_rgba_colormap/visual to get a visual for
        windows with an alpha channel, if one exists.

        * gdk/win32/gdkscreen-win32.c gdk/linux-fb/gdkscreen-fb.c:
        Stub out gdk_screen_get_rgba_colormap/visual.

        * gdk/x11/gdkcolor-x11.c (gdk_colormap_alloc_colors): computation of
        "unused" wasn't right for depth == 32, since it depended on
        shifting by 32.

        * gdk/gdkrgb.c: Fill in alpha bits with 1s. (Based on patch from
        Keith Packard,
        http://mail.gnome.org/archives/gtk-devel-list/2004-June/msg00080.html)

        * gdk/x11/gdkdrawable-x11.c (gdk_x11_drawable_get_picture):
        Implement again, without using Xft.

        * tests/testgtk.c: Add a test for windows with an alpha channel.

15 files changed:
ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-8
docs/reference/gdk/gdk-sections.txt
gdk/gdk.symbols
gdk/gdkrgb.c
gdk/gdkscreen.h
gdk/linux-fb/gdkscreen-fb.c
gdk/win32/gdkscreen-win32.c
gdk/x11/gdkcolor-x11.c
gdk/x11/gdkdrawable-x11.c
gdk/x11/gdkscreen-x11.c
gdk/x11/gdkscreen-x11.h
gdk/x11/gdkvisual-x11.c
tests/testgtk.c

index 50564b3240f6a645eff571bf4133cc578fcbe310..005494f7fd101b618a88a4ca4f4656911dea0625 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2005-05-09  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/gdkrgb.c (gdk_rgb_convert_0888_br, gdk_rgb_convert_8880_br): 
+       Fill in unused bits so they can be used for the depth-32 target case.
+       Rewrite so that that gives a marginal speedup rather than a
+       marginal slowdown. (on x86)
+
+       * gdk/gdkscreen.h gdk/x11/gdkscreen-x11.[ch] gdk/x11/gdkvisual-x11.c:
+       Add gdk_screen_get_rgba_colormap/visual to get a visual for
+       windows with an alpha channel, if one exists.
+
+       * gdk/win32/gdkscreen-win32.c gdk/linux-fb/gdkscreen-fb.c:
+       Stub out gdk_screen_get_rgba_colormap/visual.
+
+       * gdk/x11/gdkcolor-x11.c (gdk_colormap_alloc_colors): computation of
+       "unused" wasn't right for depth == 32, since it depended on
+       shifting by 32.
+
+       * gdk/gdkrgb.c: Fill in alpha bits with 1s. (Based on patch from
+       Keith Packard,
+       http://mail.gnome.org/archives/gtk-devel-list/2004-June/msg00080.html)
+
+       * gdk/x11/gdkdrawable-x11.c (gdk_x11_drawable_get_picture):
+       Implement again, without using Xft.
+
+       * tests/testgtk.c: Add a test for windows with an alpha channel.
+
 2005-05-09  Matthias Clasen  <mclasen@redhat.com>
 
        * autogen.sh: Revert accidental commit.
index 50564b3240f6a645eff571bf4133cc578fcbe310..005494f7fd101b618a88a4ca4f4656911dea0625 100644 (file)
@@ -1,3 +1,30 @@
+2005-05-09  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/gdkrgb.c (gdk_rgb_convert_0888_br, gdk_rgb_convert_8880_br): 
+       Fill in unused bits so they can be used for the depth-32 target case.
+       Rewrite so that that gives a marginal speedup rather than a
+       marginal slowdown. (on x86)
+
+       * gdk/gdkscreen.h gdk/x11/gdkscreen-x11.[ch] gdk/x11/gdkvisual-x11.c:
+       Add gdk_screen_get_rgba_colormap/visual to get a visual for
+       windows with an alpha channel, if one exists.
+
+       * gdk/win32/gdkscreen-win32.c gdk/linux-fb/gdkscreen-fb.c:
+       Stub out gdk_screen_get_rgba_colormap/visual.
+
+       * gdk/x11/gdkcolor-x11.c (gdk_colormap_alloc_colors): computation of
+       "unused" wasn't right for depth == 32, since it depended on
+       shifting by 32.
+
+       * gdk/gdkrgb.c: Fill in alpha bits with 1s. (Based on patch from
+       Keith Packard,
+       http://mail.gnome.org/archives/gtk-devel-list/2004-June/msg00080.html)
+
+       * gdk/x11/gdkdrawable-x11.c (gdk_x11_drawable_get_picture):
+       Implement again, without using Xft.
+
+       * tests/testgtk.c: Add a test for windows with an alpha channel.
+
 2005-05-09  Matthias Clasen  <mclasen@redhat.com>
 
        * autogen.sh: Revert accidental commit.
index 50564b3240f6a645eff571bf4133cc578fcbe310..005494f7fd101b618a88a4ca4f4656911dea0625 100644 (file)
@@ -1,3 +1,30 @@
+2005-05-09  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/gdkrgb.c (gdk_rgb_convert_0888_br, gdk_rgb_convert_8880_br): 
+       Fill in unused bits so they can be used for the depth-32 target case.
+       Rewrite so that that gives a marginal speedup rather than a
+       marginal slowdown. (on x86)
+
+       * gdk/gdkscreen.h gdk/x11/gdkscreen-x11.[ch] gdk/x11/gdkvisual-x11.c:
+       Add gdk_screen_get_rgba_colormap/visual to get a visual for
+       windows with an alpha channel, if one exists.
+
+       * gdk/win32/gdkscreen-win32.c gdk/linux-fb/gdkscreen-fb.c:
+       Stub out gdk_screen_get_rgba_colormap/visual.
+
+       * gdk/x11/gdkcolor-x11.c (gdk_colormap_alloc_colors): computation of
+       "unused" wasn't right for depth == 32, since it depended on
+       shifting by 32.
+
+       * gdk/gdkrgb.c: Fill in alpha bits with 1s. (Based on patch from
+       Keith Packard,
+       http://mail.gnome.org/archives/gtk-devel-list/2004-June/msg00080.html)
+
+       * gdk/x11/gdkdrawable-x11.c (gdk_x11_drawable_get_picture):
+       Implement again, without using Xft.
+
+       * tests/testgtk.c: Add a test for windows with an alpha channel.
+
 2005-05-09  Matthias Clasen  <mclasen@redhat.com>
 
        * autogen.sh: Revert accidental commit.
index 10f911d383edfa31f5f93e9a758dea4abd083f90..db2f0e264f6ef7f39f14a7f5fc12cb8349b22fdd 100644 (file)
@@ -197,6 +197,8 @@ gdk_screen_get_system_colormap
 gdk_screen_get_system_visual
 gdk_screen_get_rgb_colormap
 gdk_screen_get_rgb_visual
+gdk_screen_get_rgba_colormap
+gdk_screen_get_rgba_visual
 gdk_screen_get_root_window
 gdk_screen_get_display
 gdk_screen_get_number
index a7883569becd44ed019b9a8f9e745cea9e52404f..93448836dcadffc7a99be1aa70f8cf54a2968b43 100644 (file)
@@ -992,6 +992,8 @@ gdk_screen_get_default_colormap
 gdk_screen_set_default_colormap
 gdk_screen_get_n_monitors
 gdk_screen_get_monitor_geometry
+gdk_screen_get_rgba_colormap
+gdk_screen_get_rgba_visual
 gdk_screen_make_display_name
 #endif
 #endif
index e8c1e53602874ca02a950f9edfa092e4208ca0a6..d78584216d2125aad866feba4373aeff8981b114 100644 (file)
@@ -719,6 +719,23 @@ gdk_rgb_get_info_from_colormap (GdkColormap *cmap)
   return image_info;
 }
 
+static guint32
+gdk_rgb_alpha_mask (GdkRgbInfo *image_info)
+{
+  guint padding;
+  
+  /* Shifting by >= width-of-type isn't defined in C */
+  if (image_info->visual->depth >= 32)
+    padding = 0;
+  else
+    padding = ((~(guint32)0)) << image_info->visual->depth;
+         
+  return ~(image_info->visual->red_mask |
+          image_info->visual->green_mask |
+          image_info->visual->blue_mask |
+          padding);
+}
+
 static gulong
 gdk_rgb_xpixel_from_rgb_internal (GdkColormap *colormap,
                                  guint16 r, guint16 g, guint16 b)
@@ -767,6 +784,7 @@ gdk_rgb_xpixel_from_rgb_internal (GdkColormap *colormap,
       pixel = (unused + ((r >> (16 - image_info->visual->red_prec)) << image_info->visual->red_shift) +
               ((g >> (16 - image_info->visual->green_prec)) << image_info->visual->green_shift) +
               ((b >> (16 - image_info->visual->blue_prec)) << image_info->visual->blue_shift));
+      pixel |= gdk_rgb_alpha_mask (image_info);
     }
   else if (image_info->visual->type == GDK_VISUAL_STATIC_GRAY ||
           image_info->visual->type == GDK_VISUAL_GRAYSCALE)
@@ -2126,11 +2144,10 @@ gdk_rgb_convert_0888 (GdkRgbInfo *image_info, GdkImage *image,
                      guchar *buf, int rowstride,
                      gint x_align, gint y_align, GdkRgbCmap *cmap)
 {
-  int x, y;
-  guchar *obuf;
+  int y, w;
+  guchar *obuf, *p;
   gint bpl;
   guchar *bptr, *bp2;
-  int r, g, b;
 
   bptr = buf;
   bpl = image->bpl;
@@ -2138,13 +2155,16 @@ gdk_rgb_convert_0888 (GdkRgbInfo *image_info, GdkImage *image,
   for (y = 0; y < height; y++)
     {
       bp2 = bptr;
-      for (x = 0; x < width; x++)
+      p = obuf;
+      w = width;
+      while (w--)
        {
-         r = bp2[0];
-         g = bp2[1];
-         b = bp2[2];
-         ((guint32 *)obuf)[x] = (r << 16) | (g << 8) | b;
+         p[0] = bp2[2];
+         p[1] = bp2[1];
+         p[2] = bp2[0];
+         p[3] = 0xff;
          bp2 += 3;
+         p += 4;
        }
       bptr += rowstride;
       obuf += bpl;
@@ -2157,11 +2177,10 @@ gdk_rgb_convert_0888_br (GdkRgbInfo *image_info, GdkImage *image,
                         guchar *buf, int rowstride,
                         gint x_align, gint y_align, GdkRgbCmap *cmap)
 {
-  int x, y;
-  guchar *obuf;
+  int y, w;
+  guchar *obuf, *p;
   gint bpl;
   guchar *bptr, *bp2;
-  int r, g, b;
 
   bptr = buf;
   bpl = image->bpl;
@@ -2169,13 +2188,16 @@ gdk_rgb_convert_0888_br (GdkRgbInfo *image_info, GdkImage *image,
   for (y = 0; y < height; y++)
     {
       bp2 = bptr;
-      for (x = 0; x < width; x++)
+      p = obuf;
+      w = width;
+      while (w--)
        {
-         r = bp2[0];
-         g = bp2[1];
-         b = bp2[2];
-         ((guint32 *)obuf)[x] = (b << 24) | (g << 16) | (r << 8);
+         p[0] = 0xff;
+         p[1] = bp2[0];
+         p[2] = bp2[1];
+         p[3] = bp2[2];
          bp2 += 3;
+         p += 4;
        }
       bptr += rowstride;
       obuf += bpl;
@@ -2232,6 +2254,7 @@ gdk_rgb_convert_truecolor_lsb (GdkRgbInfo *image_info, GdkImage *image,
   gint b_right, b_left;
   gint bpp;
   guint32 pixel;
+  guint32 alpha_mask = gdk_rgb_alpha_mask (image_info);
   gint i;
 
   r_right = 8 - image_info->visual->red_prec;
@@ -2255,7 +2278,7 @@ gdk_rgb_convert_truecolor_lsb (GdkRgbInfo *image_info, GdkImage *image,
          b = bp2[2];
          pixel = ((r >> r_right) << r_left) |
            ((g >> g_right) << g_left) |
-           ((b >> b_right) << b_left);
+           ((b >> b_right) << b_left) | alpha_mask;
          for (i = 0; i < bpp; i++)
            {
              *obptr++ = pixel & 0xff;
@@ -2285,6 +2308,7 @@ gdk_rgb_convert_truecolor_lsb_d (GdkRgbInfo *image_info, GdkImage *image,
   gint b_right, b_left, b_prec;
   gint bpp;
   guint32 pixel;
+  guint32 alpha_mask = gdk_rgb_alpha_mask (image_info);
   gint i;
   gint dith;
   gint r1, g1, b1;
@@ -2319,7 +2343,7 @@ gdk_rgb_convert_truecolor_lsb_d (GdkRgbInfo *image_info, GdkImage *image,
          b1 = b + (dith >> b_prec);
          pixel = (((r1 - (r1 >> r_prec)) >> r_right) << r_left) |
            (((g1 - (g1 >> g_prec)) >> g_right) << g_left) |
-           (((b1 - (b1 >> b_prec)) >> b_right) << b_left);
+           (((b1 - (b1 >> b_prec)) >> b_right) << b_left) | alpha_mask;
          for (i = 0; i < bpp; i++)
            {
              *obptr++ = pixel & 0xff;
@@ -2349,6 +2373,7 @@ gdk_rgb_convert_truecolor_msb (GdkRgbInfo *image_info, GdkImage *image,
   gint b_right, b_left;
   gint bpp;
   guint32 pixel;
+  guint32 alpha_mask = gdk_rgb_alpha_mask (image_info);
   gint shift, shift_init;
 
   r_right = 8 - image_info->visual->red_prec;
@@ -2373,7 +2398,7 @@ gdk_rgb_convert_truecolor_msb (GdkRgbInfo *image_info, GdkImage *image,
          b = bp2[2];
          pixel = ((r >> r_right) << r_left) |
            ((g >> g_right) << g_left) |
-           ((b >> b_right) << b_left);
+           ((b >> b_right) << b_left) | alpha_mask;
          for (shift = shift_init; shift >= 0; shift -= 8)
            {
              *obptr++ = (pixel >> shift) & 0xff;
@@ -2402,6 +2427,7 @@ gdk_rgb_convert_truecolor_msb_d (GdkRgbInfo *image_info, GdkImage *image,
   gint b_right, b_left, b_prec;
   gint bpp;
   guint32 pixel;
+  guint32 alpha_mask = gdk_rgb_alpha_mask (image_info);
   gint shift, shift_init;
   gint dith;
   gint r1, g1, b1;
@@ -2437,7 +2463,7 @@ gdk_rgb_convert_truecolor_msb_d (GdkRgbInfo *image_info, GdkImage *image,
          b1 = b + (dith >> b_prec);
          pixel = (((r1 - (r1 >> r_prec)) >> r_right) << r_left) |
            (((g1 - (g1 >> g_prec)) >> g_right) << g_left) |
-           (((b1 - (b1 >> b_prec)) >> b_right) << b_left);
+           (((b1 - (b1 >> b_prec)) >> b_right) << b_left) | alpha_mask;
          for (shift = shift_init; shift >= 0; shift -= 8)
            {
              *obptr++ = (pixel >> shift) & 0xff;
@@ -3110,27 +3136,43 @@ gdk_rgb_select_conv (GdkRgbInfo *image_info)
            (mask_bgr && byte_order == GDK_LSB_FIRST)))
     conv = gdk_rgb_convert_888_msb;
 #if G_BYTE_ORDER == G_BIG_ENDIAN
-  else if (bpp == 32 && depth == 24 && vtype == GDK_VISUAL_TRUE_COLOR &&
+  else if (bpp == 32 &&
+          (depth == 24 || depth == 32) &&
+          vtype == GDK_VISUAL_TRUE_COLOR &&
           (mask_rgb && byte_order == GDK_LSB_FIRST))
     conv = gdk_rgb_convert_0888_br;
-  else if (bpp == 32 && depth == 24 && vtype == GDK_VISUAL_TRUE_COLOR &&
+  else if (bpp == 32 &&
+          (depth == 24 || depth == 32) &&
+          vtype == GDK_VISUAL_TRUE_COLOR &&
           (mask_rgb && byte_order == GDK_MSB_FIRST))
     conv = gdk_rgb_convert_0888;
   else if (bpp == 32 && depth == 24 && vtype == GDK_VISUAL_TRUE_COLOR &&
           (mask_bgr && byte_order == GDK_MSB_FIRST))
     conv = gdk_rgb_convert_8880_br;
+  else if (bpp == 32 && depth == 32 && vtype == GDK_VISUAL_TRUE_COLOR &&
+          (mask_rgb && byte_order == GDK_LSB_FIRST))
+    conv = gdk_rgb_convert_8880_br;
+  else if (bpp == 32 && depth == 32 && vtype == GDK_VISUAL_TRUE_COLOR &&
+          (mask_rgb && byte_order == GDK_MSB_FIRST))
+    conv = gdk_rgb_convert_8880_br;
 #else
-  else if (bpp == 32 && depth == 24 && vtype == GDK_VISUAL_TRUE_COLOR &&
+  else if (bpp == 32 &&
+          (depth == 24 || depth == 32) &&
+          vtype == GDK_VISUAL_TRUE_COLOR &&
           (mask_rgb && byte_order == GDK_MSB_FIRST))
     conv = gdk_rgb_convert_0888_br;
-  else if (bpp == 32 && depth == 24 && vtype == GDK_VISUAL_TRUE_COLOR &&
+  else if (bpp == 32 &&
+          (depth == 24 || depth == 32) &&
+          vtype == GDK_VISUAL_TRUE_COLOR &&
           (mask_rgb && byte_order == GDK_LSB_FIRST))
     conv = gdk_rgb_convert_0888;
   else if (bpp == 32 && depth == 24 && vtype == GDK_VISUAL_TRUE_COLOR &&
           (mask_bgr && byte_order == GDK_LSB_FIRST))
     conv = gdk_rgb_convert_8880_br;
+  else if (bpp == 32 && depth == 32 && vtype == GDK_VISUAL_TRUE_COLOR &&
+          (mask_rgb && byte_order == GDK_LSB_FIRST))
+    conv = gdk_rgb_convert_0888;
 #endif
-
   else if (vtype == GDK_VISUAL_TRUE_COLOR && byte_order == GDK_LSB_FIRST)
     {
       conv = gdk_rgb_convert_truecolor_lsb;
index f527099f4447e05f090c590a40a8239b48b86bd8..5a27cbe232ba34ee99189d65d69b4f88b2a55e10 100644 (file)
@@ -63,6 +63,9 @@ GdkColormap* gdk_screen_get_system_colormap   (GdkScreen   *screen);
 GdkVisual*   gdk_screen_get_system_visual     (GdkScreen   *screen);
 GdkColormap *gdk_screen_get_rgb_colormap      (GdkScreen   *screen);
 GdkVisual *  gdk_screen_get_rgb_visual        (GdkScreen   *screen);
+GdkColormap *gdk_screen_get_rgba_colormap     (GdkScreen   *screen);
+GdkVisual *  gdk_screen_get_rgba_visual       (GdkScreen   *screen);
+
 
 GdkWindow *  gdk_screen_get_root_window       (GdkScreen   *screen);
 GdkDisplay * gdk_screen_get_display           (GdkScreen   *screen);
index fd237c3fb47cdde4f23fa54a4c89f1b856d502cb..ff19caaa98fd475b8e0ae24ab7786829fbfa519e 100644 (file)
@@ -82,6 +82,22 @@ gdk_screen_get_monitor_geometry (GdkScreen    *screen,
   dest->height = gdk_screen_height ();
 }
 
+GdkColormap *
+gdk_screen_get_rgba_colormap (GdkScreen *screen)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+  return NULL;
+}
+  
+GdkVisual *
+gdk_screen_get_rgba_visual (GdkScreen *screen)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+  return NULL;
+}
+  
 gint
 gdk_screen_get_number (GdkScreen *screen)
 {
index a68d24c2c06ad43502a56b2a4e90255be3e2fc35..45e151a377471a46e35c04d759aa886c1e672d4d 100644 (file)
@@ -78,6 +78,22 @@ gdk_screen_get_monitor_geometry (GdkScreen    *screen,
   *dest = _gdk_monitors[num_monitor];
 }
 
+GdkColormap *
+gdk_screen_get_rgba_colormap (GdkScreen *screen)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+  return NULL;
+}
+  
+GdkVisual *
+gdk_screen_get_rgba_visual (GdkScreen *screen)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+  return NULL;
+}
+  
 gint
 gdk_screen_get_number (GdkScreen *screen)
 {
index 9322e9391b9de3cc9917f4b836c2cca68720e9c8..95fffe82b7d6c8e6a578ebf433cb6fa943c3d75a 100644 (file)
@@ -1130,8 +1130,16 @@ gdk_colormap_alloc_colors (GdkColormap *colormap,
          /* If bits not used for color are used for something other than padding,
           * it's likely alpha, so we set them to 1s.
           */
-         guint32 unused = ~ (visual->red_mask | visual->green_mask | visual->blue_mask |
-                             (((~(guint32)0)) << visual->depth));
+         guint padding, unused;
+
+         /* Shifting by >= width-of-type isn't defined in C */
+         if (visual->depth >= 32)
+           padding = 0;
+         else
+           padding = ((~(guint32)0)) << visual->depth;
+         
+         unused = ~ (visual->red_mask | visual->green_mask | visual->blue_mask | padding);
+         
          colors[i].pixel = (unused +
                             ((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
                             ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
index 71e02909f5e61900d875ee96d491a33ce0271d7c..7922aaeee01770a77d569db5ccba53b821f115e8 100644 (file)
@@ -337,7 +337,29 @@ _gdk_x11_have_render (GdkDisplay *display)
 static Picture
 gdk_x11_drawable_get_picture (GdkDrawable *drawable)
 {
-  return None;
+  GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+  
+  if (!impl->picture)
+    {
+      Display *xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
+      XRenderPictFormat *format;
+      
+      GdkVisual *visual = gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
+      if (!visual)
+       return None;
+
+      format = XRenderFindVisualFormat (xdisplay, GDK_VISUAL_XVISUAL (visual));
+      if (format)
+       {
+         XRenderPictureAttributes attributes;
+         attributes.graphics_exposures = False;
+         
+         impl->picture = XRenderCreatePicture (xdisplay, impl->xid, format,
+                                               CPGraphicsExposure, &attributes);
+       }
+    }
+  
+  return impl->picture;
 }
 
 static void
index 3ab2bfc8afa238a5182c2667c688f81dc7d610f8..1dbff67c2ee0e19186ac7958149e048e9ccdfcff 100644 (file)
@@ -288,6 +288,12 @@ gdk_screen_x11_dispose (GObject *object)
 
   g_object_unref (screen_x11->default_colormap);
   screen_x11->default_colormap = NULL;
+
+  if (screen_x11->rgba_colormap)
+    {
+      g_object_unref (screen_x11->rgba_colormap);
+      screen_x11->rgba_colormap = NULL;
+    }
   
   screen_x11->root_window = NULL;
 
@@ -371,6 +377,68 @@ gdk_screen_get_monitor_geometry (GdkScreen    *screen,
   *dest = GDK_SCREEN_X11 (screen)->monitors[monitor_num];
 }
 
+/**
+ * gdk_screen_get_rgba_colormap:
+ * @screen: a #GdkScreen.
+ * 
+ * Gets a colormap to use for creating windows or pixmaps with an
+ * alpha channel. The windowing system on which GTK+ is running
+ * may not support this capability, in which case %NULL will
+ * be returned. Even if a non-%NULL value is returned, its
+ * possible that the window's alpha channel won't be honored
+ * when displaying the window on the screen: in particular, for
+ * X an appropriate windowing manager and compositing manager
+ * must be running to provide appropriate display.
+ * 
+ * Return value: a colormap to use for windows with an alpha channel
+ *   or %NULL if the capability is not available.
+ *
+ * Since: 2.8
+ **/
+GdkColormap *
+gdk_screen_get_rgba_colormap (GdkScreen *screen)
+{
+  GdkScreenX11 *screen_x11;
+
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+  screen_x11 = GDK_SCREEN_X11 (screen);
+
+  if (!screen_x11->rgba_visual)
+    return NULL;
+
+  if (!screen_x11->rgba_colormap)
+    screen_x11->rgba_colormap = gdk_colormap_new (screen_x11->rgba_visual,
+                                                 FALSE);
+  
+  return screen_x11->rgba_colormap;
+}
+
+/**
+ * gdk_screen_get_rgba_visual:
+ * @screen: a #GdkScreen
+ * 
+ * Gets a visual to use for creating windows or pixmaps with an
+ * alpha channel. See the docs for gdk_screen_get_rgba_colormap()
+ * for caveats.
+ * 
+ * Return value: a visual to use for windows with an alpha channel
+ *   or %NULL if the capability is not available.
+ *
+ * Since: 2.8
+ **/
+GdkVisual *
+gdk_screen_get_rgba_visual (GdkScreen *screen)
+{
+  GdkScreenX11 *screen_x11;
+
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+  screen_x11 = GDK_SCREEN_X11 (screen);
+
+  return screen_x11->rgba_visual;
+}
+
 /**
  * gdk_x11_screen_get_xscreen:
  * @screen: a #GdkScreen.
index fddc28dd04e812e60b209eda8ea1782cea203f73..aa08dca15ba47de8096984ccd4b01a0b54ff57c2 100644 (file)
@@ -76,11 +76,13 @@ struct _GdkScreenX11
   gint navailable_types;
   GHashTable *visual_hash;
   GHashTable *colormap_hash;
+  GdkVisual *rgba_visual;
   
   /* Colormap Part */
   GdkColormap *default_colormap;
   GdkColormap *system_colormap;
-  
+  GdkColormap *rgba_colormap;
+
   /* X settings */
   XSettingsClient *xsettings_client;
   guint xsettings_in_init : 1;
index 95b2df7a2af42b6675769da33cb326e0fbc25faf..94d3687a1170885c42ab6cb72ce2cd3ff68d082a 100644 (file)
@@ -257,11 +257,22 @@ _gdk_visual_init (GdkScreen *screen)
     }
 
   for (i = 0; i < nvisuals; i++)
-    if (default_xvisual->visualid == visuals[i]->xvisual->visualid)
-      {
+    {
+      if (default_xvisual->visualid == visuals[i]->xvisual->visualid)
        screen_x11->system_visual = visuals[i];
-       break;
-      }
+
+      /* For now, we only support 8888 ARGB for the "rgba visual".
+       * Additional formats (like ABGR) could be added later if they
+       * turn up.
+       */
+      if (visuals[i]->visual.depth == 32 &&
+         (visuals[i]->visual.red_mask   == 0xff0000 &&
+          visuals[i]->visual.green_mask == 0x00ff00 &&
+          visuals[i]->visual.blue_mask  == 0x0000ff))
+       {
+         screen_x11->rgba_visual = GDK_VISUAL (visuals[i]);
+       }
+    }
 
 #ifdef G_ENABLE_DEBUG 
   if (_gdk_debug_flags & GDK_DEBUG_MISC)
index 22919bd23c72d2a42de651c7aefd4855babf53c6..b4480be8d49d9c36745359e893085eb8afd99efa 100644 (file)
@@ -147,6 +147,258 @@ destroy_tooltips (GtkWidget *widget, GtkWindow **window)
 }
 
 
+/*
+ * Windows with an alpha channel
+ */
+
+
+static gboolean
+on_alpha_window_expose (GtkWidget      *widget,
+                       GdkEventExpose *expose)
+{
+  cairo_t *cr;
+  cairo_pattern_t *pattern;
+  int radius;
+
+  cr = gdk_drawable_create_cairo_context (widget->window);
+
+  radius = MIN (widget->allocation.width, widget->allocation.height) / 2;
+  pattern = cairo_pattern_create_radial (widget->allocation.width / 2,
+                                        widget->allocation.height / 2,
+                                        0.0,
+                                        widget->allocation.width / 2,
+                                        widget->allocation.height / 2,
+                                        radius * 1.33);
+
+  if (gdk_screen_get_rgba_colormap (gtk_widget_get_screen (widget)))
+    cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); /* transparent */
+  else
+    cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* opaque white */
+    
+  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+  cairo_paint (cr);
+  
+  cairo_pattern_add_color_stop_rgba (pattern, 0.0,
+                                    1.0, 0.75, 0.0, 1.0); /* solid orange */
+  cairo_pattern_add_color_stop_rgba (pattern, 1.0,
+                                    1.0, 0.75, 0.0, 0.0); /* transparent orange */
+
+  cairo_set_source (cr, pattern);
+  cairo_pattern_destroy (pattern);
+  
+  cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+  cairo_paint (cr);
+
+  cairo_destroy (cr);
+
+  return FALSE;
+}
+
+static GtkWidget *
+build_alpha_widgets (void)
+{
+  GtkWidget *table;
+  GtkWidget *radio_button;
+  GtkWidget *hbox;
+  GtkWidget *label;
+  GtkWidget *entry;
+
+  table = gtk_table_new (1, 1, FALSE);
+
+  radio_button = gtk_radio_button_new_with_label (NULL, "Red");
+  gtk_table_attach (GTK_TABLE (table),
+                   radio_button,
+                   0, 1,                  0, 1,
+                   GTK_EXPAND | GTK_FILL, 0,
+                   0,                     0);
+
+  radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Green");
+  gtk_table_attach (GTK_TABLE (table),
+                   radio_button,
+                   0, 1,                  1, 2,
+                   GTK_EXPAND | GTK_FILL, 0,
+                   0,                     0);
+
+  radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Blue"),
+  gtk_table_attach (GTK_TABLE (table),
+                   radio_button,
+                   0, 1,                  2, 3,
+                   GTK_EXPAND | GTK_FILL, 0,
+                   0,                     0);
+
+  gtk_table_attach (GTK_TABLE (table),
+                   gtk_check_button_new_with_label ("Sedentary"),
+                   1, 2,                  0, 1,
+                   GTK_EXPAND | GTK_FILL, 0,
+                   0,                     0);
+  gtk_table_attach (GTK_TABLE (table),
+                   gtk_check_button_new_with_label ("Nocturnal"),
+                   1, 2,                  1, 2,
+                   GTK_EXPAND | GTK_FILL, 0,
+                   0,                     0);
+  gtk_table_attach (GTK_TABLE (table),
+                   gtk_check_button_new_with_label ("Compulsive"),
+                   1, 2,                  2, 3,
+                   GTK_EXPAND | GTK_FILL, 0,
+                   0,                     0);
+
+  radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Green");
+  gtk_table_attach (GTK_TABLE (table),
+                   radio_button,
+                   0, 1,                  1, 2,
+                   GTK_EXPAND | GTK_FILL, 0,
+                   0,                     0);
+
+  radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Blue"),
+  gtk_table_attach (GTK_TABLE (table),
+                   radio_button,
+                   0, 1,                  2, 3,
+                   GTK_EXPAND | GTK_FILL, 0,
+                   0,                     0);
+  
+  hbox = gtk_hbox_new (FALSE, 0);
+  label = gtk_label_new (NULL);
+  gtk_label_set_markup (GTK_LABEL (label), "<i>Entry: </i>");
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+  entry = gtk_entry_new ();
+  gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
+  gtk_table_attach (GTK_TABLE (table),
+                   hbox,
+                   0, 1,                  3, 4,
+                   GTK_EXPAND | GTK_FILL, 0,
+                   0,                     0);
+  
+  return table;
+}
+
+static gboolean
+on_alpha_drawing_expose (GtkWidget      *widget,
+                        GdkEventExpose *expose)
+{
+  int x = widget->allocation.x;
+  int y = widget->allocation.y;
+  int width = widget->allocation.width;
+  int height = widget->allocation.height;
+  GdkPixbuf *pixbuf;
+  guchar *buffer;
+  guchar *p;
+  int i, j;
+
+  buffer = g_malloc (64 * 64 * 4);
+  
+  gdk_draw_rectangle (widget->window, widget->style->black_gc, FALSE,
+                     x,         y,
+                     width - 1, height - 1);
+
+  p = buffer;
+  for (i = 0; i < 64; i++) {
+    for (j = 0; j < 64; j++) {
+      *(p++) = i * 4 + 3;
+      *(p++) = 0;
+      *(p++) = j + 4 + 3;
+      *(p++) = MIN (255, ((32 - i) * (32 - i) + (32 - j) * (32 - j)) / 8);
+    }
+  }
+  p++;
+
+  gdk_draw_rgb_32_image (widget->window, widget->style->black_gc,
+                        x + 18, y + (height - 64) /2,
+                        64, 64, GDK_RGB_DITHER_NORMAL, buffer, 64 * 4);
+
+  pixbuf = gdk_pixbuf_new_from_data (buffer, GDK_COLORSPACE_RGB, TRUE,
+                                    8, 64, 64, 4 * 64, NULL, NULL);
+
+  gdk_draw_pixbuf (widget->window, widget->style->black_gc, pixbuf,
+                  0, 0, x + width - 18 - 64, y + (height - 64) /2,
+                  64, 64, GDK_RGB_DITHER_NORMAL, 0, 0);
+
+  g_object_unref (pixbuf);
+
+  g_free (buffer);
+  
+  return FALSE;
+}
+
+static GtkWidget *
+build_alpha_drawing ()
+{
+  GtkWidget *hbox;
+
+  hbox = gtk_hbox_new (FALSE, 0);
+  gtk_widget_set_size_request (hbox, 100, 100);
+
+  g_signal_connect (hbox, "expose-event",
+                   G_CALLBACK (on_alpha_drawing_expose), NULL);
+
+  return hbox;
+}
+
+static void
+on_alpha_screen_changed (GtkWidget *widget,
+                        GdkScreen *old_screen,
+                        GtkWidget *label)
+{
+  GdkScreen *screen = gtk_widget_get_screen (widget);
+  GdkColormap *colormap = gdk_screen_get_rgba_colormap (screen);
+
+  if (!colormap)
+    {
+      colormap = gdk_screen_get_rgb_colormap (screen);
+      gtk_label_set_markup (GTK_LABEL (label), "<b>Screen doesn't support alpha</b>");
+    }
+  else
+    {
+      gtk_label_set_markup (GTK_LABEL (label), "<b>Screen supports alpha</b>");
+    }
+
+  gtk_widget_set_colormap (widget, colormap);
+}
+
+void
+create_alpha_window (GtkWidget *widget)
+{
+  static GtkWidget *window;
+
+  if (!window)
+    {
+      GtkWidget *vbox;
+      GtkWidget *label;
+      
+      window = gtk_dialog_new_with_buttons ("Alpha Window",
+                                           GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
+                                           GTK_STOCK_CLOSE, 0,
+                                           NULL);
+
+      gtk_widget_set_app_paintable (window, TRUE);
+      g_signal_connect (window, "expose-event",
+                       G_CALLBACK (on_alpha_window_expose), NULL);
+      
+      vbox = gtk_vbox_new (FALSE, 8);
+      gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
+      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
+                         TRUE, TRUE, 0);
+
+      label = gtk_label_new (NULL);
+      
+      gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
+      gtk_box_pack_start (GTK_BOX (vbox), build_alpha_widgets (), TRUE, TRUE, 0);
+      gtk_box_pack_start (GTK_BOX (vbox), build_alpha_drawing (), TRUE, TRUE, 0);
+
+      on_alpha_screen_changed (window, NULL, label);
+      g_signal_connect (window, "screen-changed",
+                       G_CALLBACK (on_alpha_screen_changed), label);
+      
+      g_signal_connect (window, "destroy",
+                       G_CALLBACK (gtk_widget_destroyed),
+                       &window);
+    }
+
+  if (!GTK_WIDGET_VISIBLE (window))
+    gtk_widget_show_all (window);
+  else
+    gtk_widget_destroy (window);
+}
+
 /*
  * Big windows and guffaw scrolling
  */
@@ -12860,6 +13112,7 @@ struct {
   gboolean do_not_benchmark;
 } buttons[] =
 {
+  { "alpha window", create_alpha_window },
 #ifdef G_OS_WIN32
   /* dog slow on NT, no working at all on 9x */
   { "big windows", create_big_windows, TRUE },