From http://www.jwz.org/xscreensaver/xscreensaver-5.37.tar.gz
[xscreensaver] / hacks / analogtv.c
index 8d64d50370558ccfe04af87c8d4b4e7fa70b7010..642037de54d6365f05055089efb0f9c26f694b8f 100644 (file)
   Fixed a bug or two.
 */
 
-#ifdef HAVE_COCOA
+/* 2015-02-27, Tomasz Sulej <tomeksul@gmail.com>:
+   - tint_control variable is used now
+   - removed unusable hashnoise code
+ */
+
+/*
+  2016-10-09, Dave Odell <dmo2118@gmail.com>:
+  Updated for new xshm.c.
+*/
+
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
-#else /* !HAVE_COCOA */
+#else /* !HAVE_JWXYZ */
 # include <X11/Xlib.h>
 # include <X11/Xutil.h>
 #endif
+#include <limits.h>
 
 #include <assert.h>
 #include <errno.h>
@@ -77,7 +88,7 @@
 
 /* #define DEBUG 1 */
 
-#ifdef DEBUG
+#if defined(DEBUG) && (defined(__linux) || defined(__FreeBSD__))
 /* only works on linux + freebsd */
 #include <machine/cpufunc.h>
 
@@ -211,19 +222,19 @@ analogtv_set_defaults(analogtv *it, char *prefix)
 
 #ifdef DEBUG
   printf("analogtv: prefix=%s\n",prefix);
-  printf("  use: shm=%d cmap=%d color=%d\n",
-         it->use_shm,it->use_cmap,it->use_color);
+  printf("  use: cmap=%d color=%d\n",
+         it->use_cmap,it->use_color);
   printf("  controls: tint=%g color=%g brightness=%g contrast=%g\n",
          it->tint_control, it->color_control, it->brightness_control,
          it->contrast_control);
-  printf("  freq_error %g: %g %d\n",
-         it->freq_error, it->freq_error_inc, it->flutter_tint);
+/*  printf("  freq_error %g: %g %d\n",
+         it->freq_error, it->freq_error_inc, it->flutter_tint); */
   printf("  desync: %g %d\n",
          it->horiz_desync, it->flutter_horiz_desync);
   printf("  hashnoise rpm: %g\n",
          it->hashnoise_rpm);
-  printf("  vis: %d %d %d\n",
-         it->visclass, it->visbits, it->visdepth);
+  printf("  vis: %d %d\n",
+         it->visclass, it->visdepth);
   printf("  shift: %d-%d %d-%d %d-%d\n",
          it->red_invprec,it->red_shift,
          it->green_invprec,it->green_shift,
@@ -256,15 +267,7 @@ static void
 analogtv_free_image(analogtv *it)
 {
   if (it->image) {
-    if (it->use_shm) {
-#ifdef HAVE_XSHM_EXTENSION
-      destroy_xshm_image(it->dpy, it->image, &it->shm_info);
-#endif
-    } else {
-      thread_free(it->image->data);
-      it->image->data = NULL;
-      XDestroyImage(it->image);
-    }
+    destroy_xshm_image(it->dpy, it->image, &it->shm_info);
     it->image=NULL;
   }
 }
@@ -274,31 +277,14 @@ analogtv_alloc_image(analogtv *it)
 {
   /* On failure, it->image is NULL. */
 
-  unsigned bits_per_pixel = get_bits_per_pixel(it->dpy, it->xgwa.depth);
+  unsigned bits_per_pixel = visual_pixmap_depth(it->screen, it->xgwa.visual);
   unsigned align = thread_memory_alignment(it->dpy) * 8 - 1;
   /* Width is in bits. */
   unsigned width = (it->usewidth * bits_per_pixel + align) & ~align;
 
-  if (it->use_shm) {
-#ifdef HAVE_XSHM_EXTENSION
-    it->image=create_xshm_image(it->dpy, it->xgwa.visual, it->xgwa.depth, ZPixmap, 0,
-                                &it->shm_info,
-                                width / bits_per_pixel, it->useheight);
-#endif
-    if (!it->image) it->use_shm=0;
-  }
-  if (!it->image) {
-    it->image = XCreateImage(it->dpy, it->xgwa.visual, it->xgwa.depth, ZPixmap, 0, 0,
-                             it->usewidth, it->useheight, 8, width / 8);
-    if (it->image) {
-      if(thread_malloc((void **)&it->image->data, it->dpy,
-                       it->image->height * it->image->bytes_per_line)) {
-        it->image->data = NULL;
-        XDestroyImage(it->image);
-        it->image = NULL;
-      }
-    }
-  }
+  it->image=create_xshm_image(it->dpy, it->xgwa.visual, it->xgwa.depth,
+                              ZPixmap, &it->shm_info,
+                              width / bits_per_pixel, it->useheight);
 
   if (it->image) {
     memset (it->image->data, 0, it->image->height * it->image->bytes_per_line);
@@ -319,19 +305,18 @@ analogtv_configure(analogtv *it)
   /* If the window is very small, don't let the image we draw get lower
      than the actual TV resolution (266x200.)
 
-     If the aspect ratio of the window is within 15% of a 4:3 ratio,
+     If the aspect ratio of the window is close to a 4:3 or 16:9 ratio,
      then scale the image to exactly fill the window.
 
      Otherwise, center the image either horizontally or vertically,
-     padding on the left+right, or top+bottom, but not both.
+     letterboxing or pillarboxing (but not both).
 
      If it's very close (2.5%) to a multiple of VISLINES, make it exact
      For example, it maps 1024 => 1000.
    */
-  float percent = 0.15;  /* jwz: 20% caused severe top/bottom clipping
-                                 in Pong on 1680x1050 iMac screen. */
-  float min_ratio = 4.0 / 3.0 * (1 - percent);
-  float max_ratio = 4.0 / 3.0 * (1 + percent);
+  float percent = 0.15;
+  float min_ratio =  4.0 / 3.0 * (1 - percent);
+  float max_ratio = 16.0 / 9.0 * (1 + percent);
   float ratio;
   float height_snap=0.025;
 
@@ -339,10 +324,10 @@ analogtv_configure(analogtv *it)
   wlim = it->xgwa.width;
   ratio = wlim / (float) hlim;
 
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   /* Fill the whole iPhone screen, even though that distorts the image. */
-  min_ratio = 640.0 / 1136.0 * (1 - percent);
-  max_ratio = 1136.0 / 640.0 * (1 + percent);
+  min_ratio = 0;
+  max_ratio = 10;
 #endif
 
   if (wlim < 266 || hlim < 200)
@@ -364,7 +349,7 @@ analogtv_configure(analogtv *it)
                wlim, hlim, min_ratio, ratio, max_ratio);
 # endif
     }
-  else if (ratio > max_ratio)
+  else if (ratio >= max_ratio)
     {
       wlim = hlim*max_ratio;
 # ifdef DEBUG
@@ -374,7 +359,7 @@ analogtv_configure(analogtv *it)
                min_ratio, ratio, max_ratio);
 # endif
     }
-  else /* ratio < min_ratio */
+  else /* ratio <= min_ratio */
     {
       hlim = wlim/min_ratio;
 # ifdef DEBUG
@@ -387,7 +372,7 @@ analogtv_configure(analogtv *it)
 
 
   height_diff = ((hlim + ANALOGTV_VISLINES/2) % ANALOGTV_VISLINES) - ANALOGTV_VISLINES/2;
-  if (height_diff != 0 && fabs(height_diff) < hlim * height_snap)
+  if (height_diff != 0 && abs(height_diff) < hlim * height_snap)
     {
       hlim -= height_diff;
     }
@@ -503,18 +488,11 @@ analogtv_allocate(Display *dpy, Window window)
 
   it->n_colors=0;
 
-#ifdef HAVE_XSHM_EXTENSION
-  it->use_shm=1;
-#else
-  it->use_shm=0;
-#endif
-
   XGetWindowAttributes (it->dpy, it->window, &it->xgwa);
 
   it->screen=it->xgwa.screen;
   it->colormap=it->xgwa.colormap;
-  it->visclass=it->xgwa.visual->class;
-  it->visbits=it->xgwa.visual->bits_per_rgb;
+  it->visclass=visual_class(it->xgwa.screen, it->xgwa.visual);
   it->visdepth=it->xgwa.depth;
   if (it->visclass == TrueColor || it->visclass == DirectColor) {
     if (get_integer_resource (it->dpy, "use_cmap", "Integer")) {
@@ -533,9 +511,8 @@ analogtv_allocate(Display *dpy, Window window)
     it->use_color=0;
   }
 
-  it->red_mask=it->xgwa.visual->red_mask;
-  it->green_mask=it->xgwa.visual->green_mask;
-  it->blue_mask=it->xgwa.visual->blue_mask;
+  visual_rgb_masks (it->xgwa.screen, it->xgwa.visual,
+                    &it->red_mask, &it->green_mask, &it->blue_mask);
   it->red_shift=it->red_invprec=-1;
   it->green_shift=it->green_invprec=-1;
   it->blue_shift=it->blue_invprec=-1;
@@ -594,15 +571,7 @@ void
 analogtv_release(analogtv *it)
 {
   if (it->image) {
-    if (it->use_shm) {
-#ifdef HAVE_XSHM_EXTENSION
-      destroy_xshm_image(it->dpy, it->image, &it->shm_info);
-#endif
-    } else {
-      thread_free(it->image->data);
-      it->image->data = NULL;
-      XDestroyImage(it->image);
-    }
+    destroy_xshm_image(it->dpy, it->image, &it->shm_info);
     it->image=NULL;
   }
   if (it->gc) XFreeGC(it->dpy, it->gc);
@@ -792,11 +761,8 @@ analogtv_ntsc_to_yiq(const analogtv *it, int lineno, const float *signal,
     colormode = (cb_i * cb_i + cb_q * cb_q) > 2.8;
 
     if (colormode) {
-      double tint_i = -cos((103 + it->color_control)*3.1415926/180);
-      double tint_q = sin((103 + it->color_control)*3.1415926/180);
-
-      multiq2[0] = (cb_i*tint_i - cb_q*tint_q) * it->color_control;
-      multiq2[1] = (cb_q*tint_i + cb_i*tint_q) * it->color_control;
+      multiq2[0] = (cb_i*it->tint_i - cb_q*it->tint_q) * it->color_control;
+      multiq2[1] = (cb_q*it->tint_i + cb_i*it->tint_q) * it->color_control;
       multiq2[2]=-multiq2[0];
       multiq2[3]=-multiq2[1];
     }
@@ -908,7 +874,7 @@ analogtv_setup_teletext(analogtv_input *input)
 void
 analogtv_setup_frame(analogtv *it)
 {
-  int i,x,y;
+  /*  int i,x,y;*/
 
   it->redraw_all=0;
 
@@ -920,10 +886,13 @@ analogtv_setup_frame(analogtv *it)
       ((int)(random()&0xff)-0x80) * 0.000001;
   }
 
+  /* it wasn't used
   for (i=0; i<ANALOGTV_V; i++) {
     it->hashnoise_times[i]=0;
   }
+  */
 
+  /* let's leave it to process shrinkpulse */
   if (it->hashnoise_enable && !it->hashnoise_on) {
     if (random()%10000==0) {
       it->hashnoise_on=1;
@@ -933,6 +902,8 @@ analogtv_setup_frame(analogtv *it)
   if (random()%1000==0) {
     it->hashnoise_on=0;
   }
+
+#if 0  /* never used */
   if (it->hashnoise_on) {
     it->hashnoise_rpm += (15000.0 - it->hashnoise_rpm)*0.05 +
       ((int)(random()%2000)-1000)*0.1;
@@ -942,11 +913,13 @@ analogtv_setup_frame(analogtv *it)
   }
   if (it->hashnoise_rpm > 0.0) {
     int hni;
+    double hni_double;
     int hnc=it->hashnoise_counter; /* in 24.8 format */
 
     /* Convert rpm of a 16-pole motor into dots in 24.8 format */
-    hni = (int)(ANALOGTV_V * ANALOGTV_H * 256.0 /
-                (it->hashnoise_rpm * 16.0 / 60.0 / 60.0));
+    hni_double = ANALOGTV_V * ANALOGTV_H * 256.0 /
+                (it->hashnoise_rpm * 16.0 / 60.0 / 60.0);
+    hni = (hni_double <= INT_MAX) ? (int)hni_double : INT_MAX;
 
     while (hnc < (ANALOGTV_V * ANALOGTV_H)<<8) {
       y=(hnc>>8)/ANALOGTV_H;
@@ -955,10 +928,18 @@ analogtv_setup_frame(analogtv *it)
       if (x>0 && x<ANALOGTV_H - ANALOGTV_HASHNOISE_LEN) {
         it->hashnoise_times[y]=x;
       }
-      hnc += hni + (int)(random()%65536)-32768;
+      /* hnc += hni + (int)(random()%65536)-32768; */
+      {
+        hnc += (int)(random()%65536)-32768;
+        if ((hnc >= 0) && (INT_MAX - hnc < hni)) break;
+        hnc += hni;
+      }
     }
-/*    hnc -= (ANALOGTV_V * ANALOGTV_H)<<8;*/
   }
+#endif /* 0 */
+
+/*    hnc -= (ANALOGTV_V * ANALOGTV_H)<<8;*/
+
 
   if (it->rx_signal_level != 0.0)
     it->agclevel = 1.0/it->rx_signal_level;
@@ -1196,14 +1177,17 @@ static void analogtv_init_signal(const analogtv *it, double noiselevel, unsigned
   float *pe=it->rx_signal + end;
   float *p=ps;
   unsigned int fastrnd=rnd_seek(FASTRND_A, FASTRND_C, it->random0, start);
+  unsigned int fastrnd_offset;
   float nm1,nm2;
   float noisemul = sqrt(noiselevel*150)/(float)0x7fffffff;
 
-  nm1 = ((int)fastrnd-(int)0x7fffffff) * noisemul;
+  fastrnd_offset = fastrnd - 0x7fffffff;
+  nm1 = (fastrnd_offset <= INT_MAX ? (int)fastrnd_offset : -1 - (int)(UINT_MAX - fastrnd_offset)) * noisemul;
   while (p != pe) {
     nm2=nm1;
     fastrnd = (fastrnd*FASTRND_A+FASTRND_C) & 0xffffffffu;
-    nm1 = ((int)fastrnd-(int)0x7fffffff) * noisemul;
+    fastrnd_offset = fastrnd - 0x7fffffff;
+    nm1 = (fastrnd_offset <= INT_MAX ? (int)fastrnd_offset : -1 - (int)(UINT_MAX - fastrnd_offset)) * noisemul;
     *p++ = nm1*nm2;
   }
 }
@@ -1244,7 +1228,8 @@ static void analogtv_add_signal(const analogtv *it, const analogtv_reception *re
     */
 
     float sig0=(float)s[0];
-    float noise = ((int)fastrnd-(int)0x7fffffff) * (50.0f/(float)0x7fffffff);
+    unsigned int fastrnd_offset = fastrnd - 0x7fffffff;
+    float noise = (fastrnd_offset <= INT_MAX ? (int)fastrnd_offset : -1 - (int)(UINT_MAX - fastrnd_offset)) * (50.0f/(float)0x7fffffff);
     fastrnd = (fastrnd*FASTRND_A+FASTRND_C) & 0xffffffffu;
 
     p[0] += sig0 * level * (1.0f - noise_ampl) + noise * noise_ampl;
@@ -1728,7 +1713,7 @@ analogtv_draw(analogtv *it, double noiselevel,
               const analogtv_reception *const *recs, unsigned rec_count)
 {
   int i,lineno;
-  int /*bigloadchange,*/drawcount;
+  /*  int bigloadchange,drawcount;*/
   double baseload;
   int overall_top, overall_bot;
 
@@ -1783,14 +1768,18 @@ analogtv_draw(analogtv *it, double noiselevel,
   baseload=0.5;
   /* if (it->hashnoise_on) baseload=0.5; */
 
-  /*bigloadchange=1;*/
-  drawcount=0;
+  /*bigloadchange=1;
+    drawcount=0;*/
   it->crtload[ANALOGTV_TOP-1]=baseload;
   it->puheight = puramp(it, 2.0, 1.0, 1.3) * it->height_control *
     (1.125 - 0.125*puramp(it, 2.0, 2.0, 1.1));
 
   analogtv_setup_levels(it, it->puheight * (double)it->useheight/(double)ANALOGTV_VISLINES);
 
+  /* calculate tint once per frame */
+  it->tint_i = -cos((103 + it->tint_control)*3.1415926/180);
+  it->tint_q = sin((103 + it->tint_control)*3.1415926/180);
+  
   for (lineno=ANALOGTV_TOP; lineno<ANALOGTV_BOT; lineno++) {
     int slineno, ytop, ybot;
     unsigned signal_offset;
@@ -1816,7 +1805,7 @@ analogtv_draw(analogtv *it, double noiselevel,
     }
     it->onscreen_signature[lineno] = linesig;
 #endif
-    drawcount++;
+    /*    drawcount++;*/
 
     /*
       Interpolate the 600-dotclock line into however many horizontal
@@ -1938,20 +1927,11 @@ analogtv_draw(analogtv *it, double noiselevel,
   }
 
   if (overall_bot > overall_top) {
-    if (it->use_shm) {
-#ifdef HAVE_XSHM_EXTENSION
-      XShmPutImage(it->dpy, it->window, it->gc, it->image,
+    put_xshm_image(it->dpy, it->window, it->gc, it->image,
                    0, overall_top,
                    it->screen_xo, it->screen_yo+overall_top,
                    it->usewidth, overall_bot - overall_top,
-                   False);
-#endif
-    } else {
-      XPutImage(it->dpy, it->window, it->gc, it->image,
-                0, overall_top,
-                it->screen_xo, it->screen_yo+overall_top,
-                it->usewidth, overall_bot - overall_top);
-    }
+                   &it->shm_info);
   }
 
 #ifdef DEBUG