]> git.hungrycats.org Git - xscreensaver/blobdiff - jwxyz/jwxyz-common.c
From https://www.jwz.org/xscreensaver/xscreensaver-6.09.tar.gz
[xscreensaver] / jwxyz / jwxyz-common.c
index 849c4567881677114550b36b9cb619c8ee5482ce..b54e06c62d624f888637954752c780c438e471ec 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1991-2016 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright © 1991-2022 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
 
 /* JWXYZ Is Not Xlib.
 
-   But it's a bunch of function definitions that bear some resemblance to
-   Xlib and that do Cocoa-ish or OpenGL-ish things that bear some resemblance
-   to the things that Xlib might have done.
+   macOS and iOS:
+
+       jwxyz.m         -- Xlib in terms of Quartz / Core Graphics rendering,
+                          Renders into a CGContextRef that points to a CGImage
+                          in CPU RAM.
+       jwxyz-cocoa.m   -- Cocoa glue: fonts and such.
+
+   Android:
+
+       jwxyz-android.c -- Java / JNI glue.  Renders into an FBO texture if
+                          possible, otherwise an EGL PBuffer.
+
+       jwxyz-image.c   -- Pixmaps implemented in CPU RAM, for OpenGL hacks.
+                          Renders into an XImage, basically.
+
+       jwxyz-gl.c      -- Pixmaps implemented in terms of OpenGL textures,
+                          for X11 hacks (except kumppa, petri and slip).
+
+   Shared code:
+
+       jwxyz-common.c  -- Most of the Xlib implementation, used by all 3 OSes.
+       jwzgles.c       -- OpenGL 1.3 implemented in terms of OpenGLES 1.1.
+
+
+   Why two implemementations of Pixmaps for Android?
+
+     - GL hacks don't tend to need much in the way of Xlib, and having a
+       GL context to render Xlib alongside a GL context for rendering GL
+       seemed like trouble.
+
+     - X11 hacks render to a GL context because hardware acceleration tends
+       to work well with Xlib geometric stuff.  Better framerates, lower
+       power.
+
+   Why not eliminate jwxyz-cocoa.m and use jwxyz-gl.c on macOS and iOS
+   as well?
+
+     - Yeah, maybe.
 
-   This is the version of jwxyz for Android.  The version used by MacOS
-   and iOS is in jwxyz.m.
  */
 
+
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
@@ -27,6 +61,7 @@
 
 #include <stdarg.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "jwxyzI.h"
 #include "pow2.h"
@@ -102,21 +137,22 @@ XDisplayHeightMM (Display *dpy, int screen)
 unsigned long
 XBlackPixelOfScreen(Screen *screen)
 {
-  return DefaultVisualOfScreen (screen)->rgba_masks[3];
+  if (! screen) abort();
+  return DefaultVisualOfScreen (screen)->alpha_mask;
 }
 
 unsigned long
 XWhitePixelOfScreen(Screen *screen)
 {
-  const unsigned long *masks = DefaultVisualOfScreen (screen)->rgba_masks;
-  return masks[0] | masks[1] | masks[2] | masks[3];
+  Visual *v = DefaultVisualOfScreen (screen);
+  return (v->red_mask | v->green_mask |v->blue_mask | v->alpha_mask);
 }
 
 unsigned long
 XCellsOfScreen(Screen *screen)
 {
-  const unsigned long *masks = DefaultVisualOfScreen (screen)->rgba_masks;
-  return masks[0] | masks[1] | masks[2];
+  Visual *v = DefaultVisualOfScreen (screen);
+  return (v->red_mask | v->green_mask |v->blue_mask);
 }
 
 void
@@ -128,9 +164,15 @@ jwxyz_validate_pixel (Display *dpy, unsigned long pixel, unsigned int depth,
 
   if (depth == 1)
     Assert ((pixel == 0 || pixel == 1), "bogus mono  pixel: 0x%08X", pixel);
+
+# if !defined __OPTIMIZE__
+  // This test fails somewhat regularly with certain X11 hacks.  This might
+  // indicate the use of uninitialized data, or an assumption that BlackPixel
+  // is 0, but either way, crashing here is not super helpful.
   else if (!alpha_allowed_p)
     Assert (((pixel & BlackPixel(dpy,0)) == BlackPixel(dpy,0)),
             "bogus color pixel: 0x%08X", pixel);
+# endif
 }
 
 
@@ -578,13 +620,12 @@ XGetGeometry (Display *dpy, Drawable d, Window *root_ret,
 Status
 XAllocColor (Display *dpy, Colormap cmap, XColor *color)
 {
-  const unsigned long *masks =
-    DefaultVisualOfScreen(DefaultScreenOfDisplay(dpy))->rgba_masks;
+  Visual *v = DefaultVisualOfScreen (DefaultScreenOfDisplay (dpy));
   color->pixel =
-    (((color->red   << 16) >> (31 - i_log2(masks[0]))) & masks[0]) |
-    (((color->green << 16) >> (31 - i_log2(masks[1]))) & masks[1]) |
-    (((color->blue  << 16) >> (31 - i_log2(masks[2]))) & masks[2]) |
-    masks[3];
+    (((color->red   << 16) >> (31 - i_log2(v->red_mask)))   & v->red_mask)   |
+    (((color->green << 16) >> (31 - i_log2(v->green_mask))) & v->green_mask) |
+    (((color->blue  << 16) >> (31 - i_log2(v->blue_mask)))  & v->blue_mask)  |
+    v->alpha_mask;
   return 1;
 }
 
@@ -712,6 +753,25 @@ ximage_putpixel_1 (XImage *ximage, int x, int y, unsigned long pixel)
   return 0;
 }
 
+static unsigned long
+ximage_getpixel_8 (XImage *ximage, int x, int y)
+{
+  return ((unsigned long)
+          *((uint8_t *) ximage->data +
+            (y * ximage->bytes_per_line) +
+            x));
+}
+
+static int
+ximage_putpixel_8 (XImage *ximage, int x, int y, unsigned long pixel)
+{
+  *((uint8_t *) ximage->data +
+    (y * ximage->bytes_per_line) +
+    x) = (uint8_t) pixel;
+  return 0;
+}
+
+
 static unsigned long
 ximage_getpixel_32 (XImage *ximage, int x, int y)
 {
@@ -735,9 +795,9 @@ Status
 XInitImage (XImage *ximage)
 {
   if (!ximage->bytes_per_line)
-    ximage->bytes_per_line = (ximage->depth == 1
-                              ? (ximage->width + 7) / 8
-                              ximage->width * 4);
+    ximage->bytes_per_line = (ximage->depth == 1 ? (ximage->width + 7) / 8 :
+                              ximage->depth == 8 ? ximage->width :
+                              ximage->width * 4);
 
   if (ximage->depth == 1) {
     ximage->f.put_pixel = ximage_putpixel_1;
@@ -745,6 +805,9 @@ XInitImage (XImage *ximage)
   } else if (ximage->depth == 32 || ximage->depth == 24) {
     ximage->f.put_pixel = ximage_putpixel_32;
     ximage->f.get_pixel = ximage_getpixel_32;
+  } else if (ximage->depth == 8) {
+    ximage->f.put_pixel = ximage_putpixel_8;
+    ximage->f.get_pixel = ximage_getpixel_8;
   } else {
     Assert (0, "unknown depth");
   }
@@ -769,9 +832,9 @@ XCreateImage (Display *dpy, Visual *visual, unsigned int depth,
   ximage->bitmap_pad = bitmap_pad;
   ximage->depth = depth;
   Visual *v = DefaultVisualOfScreen (DefaultScreenOfDisplay (dpy));
-  ximage->red_mask   = (depth == 1 ? 0 : v->rgba_masks[0]);
-  ximage->green_mask = (depth == 1 ? 0 : v->rgba_masks[1]);
-  ximage->blue_mask  = (depth == 1 ? 0 : v->rgba_masks[2]);
+  ximage->red_mask   = (depth == 1 ? 0 : v->red_mask);
+  ximage->green_mask = (depth == 1 ? 0 : v->green_mask);
+  ximage->blue_mask  = (depth == 1 ? 0 : v->blue_mask);
   ximage->bits_per_pixel = (depth == 1 ? 1 : visual_depth (NULL, NULL));
   ximage->bytes_per_line = bytes_per_line;
 
@@ -1035,6 +1098,9 @@ try_native_font (Display *dpy, const char *name, Font fid)
       fid->xa_font = strdup (name); // Maybe this should be an XLFD?
       break;
     } else {
+      // To list fonts:
+      //  po [UIFont familyNames]
+      //  po [UIFont fontNamesForFamilyName:@"Arial"]
       Log("No native font: \"%s\" %.0f", name2, size);
     }
   }
@@ -1108,7 +1174,7 @@ try_xlfd_font (Display *dpy, const char *name, Font fid)
     // This used to substitute Georgia for Times. Now it doesn't.
     if (CMP ("random")) {
       rand = True;
-    } else if (CMP ("fixed")) {
+    } else if (CMP ("fixed") || CMP ("monospace")) {
       require |= JWXYZ_STYLE_MONOSPACE;
       family_name = "Courier";
       family_name_size = strlen(family_name);
@@ -1493,11 +1559,10 @@ jwxyz_draw_string (Display *dpy, Drawable d, GC gc, int x, int y,
   {
 # define ROTL(x, rot) (((x) << ((rot) & 31)) | ((x) >> (32 - ((rot) & 31))))
 
-    const unsigned long *masks =
-      DefaultVisualOfScreen (DefaultScreenOfDisplay(dpy))->rgba_masks;
-    unsigned shift = (i_log2 (masks[3]) - i_log2 (masks[1])) & 31;
-    uint32_t mask = ROTL(masks[1], shift) & masks[3],
-             color = gcv->foreground & ~masks[3];
+    Visual *v = DefaultVisualOfScreen (DefaultScreenOfDisplay(dpy));
+    unsigned shift = (i_log2 (v->alpha_mask) - i_log2 (v->green_mask)) & 31;
+    uint32_t mask = ROTL(v->green_mask, shift) & v->alpha_mask,
+             color = gcv->foreground & ~v->alpha_mask;
     uint32_t *s = (uint32_t *)data;
     uint32_t *end = s + (w * h);
     while (s < end) {
@@ -1566,9 +1631,13 @@ XDrawImageString (Display *dpy, Drawable d, GC gc, int x, int y,
   jwxyz_fill_rect (dpy, d, gc,
                    x + MIN (0, cs.lbearing),
                    y - MAX (0, ascent),
+
+                   /* The +1 here is almost certainly wrong, but BSOD
+                      requires it; and only BSOD, fluidballs, juggle
+                      and grabclient call XDrawImageString... */
                    MAX (MAX (0, cs.rbearing) -
                         MIN (0, cs.lbearing),
-                        cs.width),
+                        cs.width) + 1,
                    MAX (0, ascent) + MAX (0, descent),
                    VTBL->gc_gcv(gc)->background);
   return XDrawString (dpy, d, gc, x, y, str, len);
@@ -1760,7 +1829,7 @@ visual_depth (Screen *s, Visual *v)
 int
 visual_cells (Screen *s, Visual *v)
 {
-  return (int)(v->rgba_masks[0] | v->rgba_masks[1] | v->rgba_masks[2]);
+  return (int)(v->red_mask | v->green_mask | v->blue_mask);
 }
 
 int
@@ -1773,9 +1842,9 @@ void
 visual_rgb_masks (Screen *s, Visual *v, unsigned long *red_mask,
                   unsigned long *green_mask, unsigned long *blue_mask)
 {
-  *red_mask = v->rgba_masks[0];
-  *green_mask = v->rgba_masks[1];
-  *blue_mask = v->rgba_masks[2];
+  *red_mask = v->red_mask;
+  *green_mask = v->green_mask;
+  *blue_mask = v->blue_mask;
 }
 
 int
@@ -1790,11 +1859,4 @@ screen_number (Screen *screen)
   return 0;
 }
 
-// declared in utils/grabclient.h
-Bool
-use_subwindow_mode_p (Screen *screen, Window window)
-{
-  return False;
-}
-
 #endif /* HAVE_JWXYZ */