From http://www.jwz.org/xscreensaver/xscreensaver-5.37.tar.gz
[xscreensaver] / hacks / glx / grab-ximage.c
index 063e9e313dda407f1f4cddb30d56d68fb5887f22..fcf079ec9a672734e3409b6915f6a3bc9126ced8 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_ANDROID
+#include <GLES/gl.h>
+#endif
+
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
-# include <OpenGL/gl.h>
-# include <OpenGL/glu.h>
+# ifndef HAVE_JWZGLES
+#  include <OpenGL/glu.h>
+# endif
 #else
 # include <X11/Xlib.h>
 # include <X11/Xutil.h>
 # include <GL/glx.h>   /* for glXMakeCurrent() */
 #endif
 
+#ifdef HAVE_JWZGLES
+# include "jwzgles.h"
+#endif /* HAVE_JWZGLES */
+
 #include "grab-ximage.h"
 #include "grabscreen.h"
+#include "pow2.h"
 #include "visual.h"
 
 /* If REFORMAT_IMAGE_DATA is defined, then we convert Pixmaps to textures
 #define REFORMAT_IMAGE_DATA
 
 
-#ifdef HAVE_XSHM_EXTENSION
-# include "resources.h"
-# include "xshm.h"
-#endif /* HAVE_XSHM_EXTENSION */
+#include "xshm.h"
 
 extern char *progname;
 
 #include <sys/time.h>
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 #else
 # include <X11/Xutil.h>
@@ -94,7 +101,8 @@ bigendian (void)
 /* Given a bitmask, returns the position and width of the field.
  */
 static void
-decode_mask (unsigned int mask, unsigned int *pos_ret, unsigned int *size_ret)
+decode_mask (unsigned long mask, unsigned long *pos_ret,
+             unsigned long *size_ret)
 {
   int i;
   for (i = 0; i < 32; i++)
@@ -137,23 +145,22 @@ convert_ximage_to_rgba32 (Screen *screen, XImage *image)
   Visual *visual = DefaultVisualOfScreen (screen);
 
   int x, y;
-  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 long crpos=0, cgpos=0, cbpos=0, capos=0; /* bitfield positions */
+  unsigned long srpos=0, sgpos=0, sbpos=0;
+  unsigned long srmsk=0, sgmsk=0, sbmsk=0;
+  unsigned long srsiz=0, sgsiz=0, sbsiz=0;
   XColor *colors = 0;
   unsigned char spread_map[3][256];
 
-  /* Note: height+2 in "to" to be to work around an array bounds overrun
+  /* Note: height+2 in "to" to work around an array bounds overrun
      in gluBuild2DMipmaps / gluScaleImage.
    */
   XImage *from = image;
   XImage *to = XCreateImage (dpy, visual, 32,  /* depth */
-                             ZPixmap, 0, 0, from->width, from->height + 2,
+                             ZPixmap, 0, 0, from->width, from->height,
                              32, /* bitmap pad */
                              0);
-  to->data = (char *) calloc (to->height, to->bytes_per_line);
+  to->data = (char *) calloc (to->height + 2, to->bytes_per_line);
 
   /* Set the bit order in the XImage structure to whatever the
      local host's native bit order is.
@@ -193,6 +200,7 @@ convert_ximage_to_rgba32 (Screen *screen, XImage *image)
 
   if (colors == 0)  /* truecolor */
     {
+      int i;
       for (i = 0; i < 256; i++)
         {
           spread_map[0][i] = spread_bits (i, srsiz);
@@ -201,6 +209,10 @@ convert_ximage_to_rgba32 (Screen *screen, XImage *image)
         }
     }
 
+  /* trying to track down an intermittent crash in ximage_putpixel_32 */
+  if (to->width  < from->width)  abort();
+  if (to->height < from->height) abort();
+
   for (y = 0; y < from->height; y++)
     for (x = 0; x < from->width; x++)
       {
@@ -302,12 +314,10 @@ static XImage *
 pixmap_to_gl_ximage (Screen *screen, Window window, Pixmap pixmap)
 {
   Display *dpy = DisplayOfScreen (screen);
+  Visual *visual = DefaultVisualOfScreen (screen);
   unsigned int width, height, depth;
 
-# ifdef HAVE_XSHM_EXTENSION
-  Bool use_shm = get_boolean_resource (dpy, "useSHM", "Boolean");
   XShmSegmentInfo shm_info;
-# endif /* HAVE_XSHM_EXTENSION */
 
   XImage *server_ximage = 0;
   XImage *client_ximage = 0;
@@ -324,31 +334,13 @@ pixmap_to_gl_ximage (Screen *screen, Window window, Pixmap pixmap)
 
   /* Convert the server-side Pixmap to a client-side GL-ordered XImage.
    */
-# ifdef HAVE_XSHM_EXTENSION
-  if (use_shm)
-    {
-      Visual *visual = DefaultVisualOfScreen (screen);
-      server_ximage = create_xshm_image (dpy, visual, depth,
-                                         ZPixmap, 0, &shm_info,
-                                         width, height);
-      if (server_ximage)
-        XShmGetImage (dpy, pixmap, server_ximage, 0, 0, ~0L);
-      else
-        use_shm = False;
-    }
-# endif /* HAVE_XSHM_EXTENSION */
-
-  if (!server_ximage)
-    server_ximage = XGetImage (dpy, pixmap, 0, 0, width, height, ~0L, ZPixmap);
+  server_ximage = create_xshm_image (dpy, visual, depth, ZPixmap, &shm_info,
+                                     width, height);
+  get_xshm_image (dpy, pixmap, server_ximage, 0, 0, ~0L, &shm_info);
 
   client_ximage = convert_ximage_to_rgba32 (screen, server_ximage);
 
-# ifdef HAVE_XSHM_EXTENSION
-  if (use_shm)
-    destroy_xshm_image (dpy, server_ximage, &shm_info);
-  else
-# endif /* HAVE_XSHM_EXTENSION */
-    XDestroyImage (server_ximage);
+  destroy_xshm_image (dpy, server_ximage, &shm_info);
 
   return client_ximage;
 }
@@ -518,20 +510,6 @@ double_time (void)
 }
 
 
-/* return the next larger power of 2. */
-static int
-to_pow2 (int i)
-{
-  static const unsigned int pow2[] = { 
-    1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 
-    2048, 4096, 8192, 16384, 32768, 65536 };
-  int j;
-  for (j = 0; j < countof(pow2); j++)
-    if (pow2[j] >= i) return pow2[j];
-  abort();  /* too big! */
-}
-
-
 /* Loads the given XImage into GL's texture memory.
    The image may be of any size.
    If mipmap_p is true, then make mipmaps instead of just a single texture.
@@ -550,8 +528,8 @@ ximage_to_texture (XImage *ximage,
   GLenum err = 0;
   int orig_width = ximage->width;
   int orig_height = ximage->height;
-  int tex_width = 0;
-  int tex_height = 0;
+  GLsizei tex_width = 0;
+  GLsizei tex_height = 0;
 
  AGAIN:
 
@@ -575,15 +553,15 @@ ximage_to_texture (XImage *ximage,
          So first, create a texture of that size (but don't write any
          data into it.)
        */
-      tex_width  = to_pow2 (ximage->width);
-      tex_height = to_pow2 (ximage->height);
+      tex_width  = (GLsizei) to_pow2 (ximage->width);
+      tex_height = (GLsizei) to_pow2 (ximage->height);
 
       if (debug_p)
         fprintf (stderr, "%s: texture %d x %d (%d x %d)\n",
                  progname, ximage->width, ximage->height,
                  tex_width, tex_height);
 
-      glTexImage2D (GL_TEXTURE_2D, 0, 3, tex_width, tex_height, 0,
+      glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0,
                     format, type, 0);
       err = glGetError();
 
@@ -725,7 +703,7 @@ load_texture_async_cb (Screen *screen, Window window, Drawable drawable,
   if (geometry->width <= 0 || geometry->height <= 0)
     {
       /* This can happen if an old version of xscreensaver-getimage
-         is installed. */
+         is installed. Or if we have no image (checkerboard). */
       geometry->x = 0;
       geometry->y = 0;
       geometry->width  = dd.pix_width;