http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.14.tar.gz
[xscreensaver] / hacks / glx / grab-ximage.c
index 6a5b1fa2daa2e6474c4202c2ee525895997dacbf..99e92317487e25373e5a456a86d94eb356e74a89 100644 (file)
@@ -1,5 +1,5 @@
 /* grab-ximage.c --- grab the screen to an XImage for use with OpenGL.
- * xscreensaver, Copyright (c) 2001 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 2001, 2003 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -85,37 +85,51 @@ spread_bits (unsigned char value, unsigned char width)
 }
 
 
+static Bool
+bigendian (void)
+{
+  union { int i; char c[sizeof(int)]; } u;
+  u.i = 1;
+  return !u.c[0];
+}
+
+
 /* Returns an XImage structure containing an image of the desktop.
-   (As a side-effect, that image will be painted onto the given Window.)
+   (As a side-effect, that image *may* be painted onto the given Window.)
    This XImage will be 32 bits per pixel, 8 each per R, G, and B, with the
    extra byte set to 0xFF.
  */
 XImage *
-screen_to_ximage (Screen *screen, Window window)
+screen_to_ximage (Screen *screen, Window window, char **filename_return)
 {
   Display *dpy = DisplayOfScreen (screen);
+  Pixmap pixmap = 0;
   XWindowAttributes xgwa;
   int win_width, win_height;
   int tex_width, tex_height;
 
-  grab_screen_image (screen, window);
-
   XGetWindowAttributes (dpy, window, &xgwa);
   win_width = xgwa.width;
   win_height = xgwa.height;
 
+  pixmap = XCreatePixmap(dpy, window, xgwa.width, xgwa.height, xgwa.depth);
+  load_random_image (screen, window, pixmap, filename_return);
+
   /* GL texture sizes must be powers of two. */
   tex_width  = to_pow2(win_width);
   tex_height = to_pow2(win_height);
 
-  /* Convert the server-side Drawable to a client-side GL-ordered XImage.
+  /* Convert the server-side Pixmap to a client-side GL-ordered XImage.
    */
   {
     XImage *ximage1, *ximage2;
     XColor *colors = 0;
 
-    ximage1 = XGetImage (dpy, window, 0, 0, win_width, win_height, ~0L,
+    ximage1 = XGetImage (dpy, pixmap, 0, 0, win_width, win_height, ~0L,
                          ZPixmap);
+    XFreePixmap (dpy, pixmap);
+    pixmap = 0;
+
     ximage2 = XCreateImage (dpy, xgwa.visual, 32, ZPixmap, 0, 0,
                             tex_width, tex_height, 32, 0);
 
@@ -141,21 +155,24 @@ screen_to_ximage (Screen *screen, Window window)
      */
     {
       int x, y;
-      int crpos, cgpos, cbpos, capos;  /* bitfield positions */
-      int srpos, sgpos, sbpos;
-      int srmsk, sgmsk, sbmsk;
-      int srsiz, sgsiz, sbsiz;
+      unsigned int crpos=0, cgpos=0, cbpos=0, capos=0; /* bitfield positions */
+      unsigned int srpos=0, sgpos=0, sbpos=0;
+      unsigned int srmsk=0, sgmsk=0, sbmsk=0;
+      unsigned int srsiz=0, sgsiz=0, sbsiz=0;
       int i;
 
       unsigned char spread_map[3][256];
 
-      srmsk = ximage1->red_mask;
-      sgmsk = ximage1->green_mask;
-      sbmsk = ximage1->blue_mask;
+      if (colors == 0)  /* truecolor */
+        {
+          srmsk = ximage2->red_mask;
+          sgmsk = ximage2->green_mask;
+          sbmsk = ximage2->blue_mask;
 
-      decode_mask (srmsk, &srpos, &srsiz);
-      decode_mask (sgmsk, &sgpos, &sgsiz);
-      decode_mask (sbmsk, &sbpos, &sbsiz);
+          decode_mask (srmsk, &srpos, &srsiz);
+          decode_mask (sgmsk, &sgpos, &sgsiz);
+          decode_mask (sbmsk, &sbpos, &sbsiz);
+        }
 
       /* Note that unlike X, which is endianness-agnostic (since any XImage
          can have its own specific bit ordering, with the server reversing
@@ -163,13 +180,19 @@ screen_to_ximage (Screen *screen, Window window)
          we need to pack things in "RGBA" order on the client machine,
          regardless of its endianness.
        */
-      crpos =  0, cgpos =  8, cbpos = 16, capos = 24;
+      if (bigendian())
+        crpos = 24, cgpos = 16, cbpos =  8, capos =  0;
+      else
+        crpos =  0, cgpos =  8, cbpos = 16, capos = 24;
 
-      for (i = 0; i < 256; i++)
+      if (colors == 0)  /* truecolor */
         {
-          spread_map[0][i] = spread_bits (i, srsiz);
-          spread_map[1][i] = spread_bits (i, sgsiz);
-          spread_map[2][i] = spread_bits (i, sbsiz);
+          for (i = 0; i < 256; i++)
+            {
+              spread_map[0][i] = spread_bits (i, srsiz);
+              spread_map[1][i] = spread_bits (i, sgsiz);
+              spread_map[2][i] = spread_bits (i, sbsiz);
+            }
         }
 
       for (y = 0; y < win_height; y++)
@@ -208,6 +231,7 @@ screen_to_ximage (Screen *screen, Window window)
         }
     }
 
+    if (pixmap) XFreePixmap (dpy, pixmap);
     if (colors) free (colors);
     free (ximage1->data);
     ximage1->data = 0;