Bug 18769

Summary: Minor speedups for libvgl's boxing functions
Product: Base System Reporter: Pedro F. Giffuni <giffunip>
Component: miscAssignee: Pedro F. Giffuni <pfg>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: Unspecified   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
file.diff
none
patch-vgl
none
patch-vgl
none
simple none

Description Pedro F. Giffuni 2000-05-23 07:20:00 UTC
The VGL boxing functions usually call VGLLine, which uses some 
arithmetic to work out the slope. In the case of boxes we already know
which lines are horizontal or vertical and we can do it faster.

How-To-Repeat: The problem is admittedly not noticeable, however the enhancements in
/usr/lib/libvgl/simple.c were trivial.
Comment 1 giffunip 2000-07-24 03:03:44 UTC
The attached uu-encoded diff for simple.c further improves VGLFilledBox
by avoiding some loops.
Comment 2 giffunip 2000-07-24 04:25:47 UTC
I am sorry, the previous patch had a minor typo with a problem difficult
to notice:
2 --> x2 on VGLBoxFill.

The attached file fixes this. Also feel free to nuke the comments.
Comment 3 Sheldon Hearn freebsd_committer freebsd_triage 2000-07-24 10:08:32 UTC
Responsible Changed
From-To: freebsd-bugs->sos

vgl is another of Soren's babies.
Comment 4 pfg1+ 2000-09-10 04:16:32 UTC
I integrated the line drawing algorithm in "Graphic Gems 1"; it claims
to be 3-4 times faster than the traditional algorithm.
Comment 5 Søren Schmidt freebsd_committer freebsd_triage 2003-04-28 19:49:30 UTC
State Changed
From-To: open->closed

Long since this was relevant, I think vgl is no longer used..
Comment 6 Pedro F. Giffuni 2003-04-29 14:54:14 UTC
> Long since this was relevant, I think vgl is no
> longer used..
> 

I respectfully disagree with the reasoning around this
decision. As long as libvgl is distributed, and in
fact included in the FreeBSD base distribution, well
documented changes like the generic line drawing
algorithm from "Graphic Gems" shouldn't be just dumped
in the bit bucket.


______________________________________________________________________
Yahoo! Cellulari: loghi, suonerie, picture message per il tuo telefonino
http://it.yahoo.com/mail_it/foot/?http://it.mobile.yahoo.com/index2002.html
Comment 7 Pedro F. Giffuni freebsd_committer freebsd_triage 2012-01-03 19:44:20 UTC
State Changed
From-To: closed->open

reopen - unly for the fast line function. 


Comment 8 Pedro F. Giffuni freebsd_committer freebsd_triage 2012-01-03 19:44:20 UTC
Responsible Changed
From-To: sos->pfg

Assign to myself.
Comment 9 dfilter service freebsd_committer freebsd_triage 2012-01-03 19:47:43 UTC
Author: pfg
Date: Tue Jan  3 19:47:32 2012
New Revision: 229415
URL: http://svn.freebsd.org/changeset/base/229415

Log:
  Integrate the line drawing algorithm from the book "Graphic Gems 1".
  
  http://www.graphicsgems.org/
  
  At the time it claimed to be 3-4 times faster than the traditional
  algorithm.
  
  PR:		18769
  Approved by:	jhb (mentor)
  MFC after:	2 weeks

Modified:
  head/lib/libvgl/simple.c

Modified: head/lib/libvgl/simple.c
==============================================================================
--- head/lib/libvgl/simple.c	Tue Jan  3 19:44:36 2012	(r229414)
+++ head/lib/libvgl/simple.c	Tue Jan  3 19:47:32 2012	(r229415)
@@ -198,36 +198,205 @@ get_planar:
   return 0;		/* XXX black? */
 }
 
+ /*
+  * Symmetric Double Step Line Algorithm by Brian Wyvill from
+  * "Graphics Gems", Academic Press, 1990.
+  */
+
+#define SL_SWAP(a,b)           {a^=b; b^=a; a^=b;}
+#define SL_ABSOLUTE(i,j,k)     ( (i-j)*(k = ( (i-j)<0 ? -1 : 1)))
+
+void
+plot(VGLBitmap * object, int x, int y, int flag, byte color)
+{
+  /* non-zero flag indicates the pixels need swapping back. */
+  if (flag)
+    VGLSetXY(object, y, x, color);
+  else
+    VGLSetXY(object, x, y, color);
+}
+
+
 void
 VGLLine(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color)
 {
-  int d, x, y, ax, ay, sx, sy, dx, dy;
+  int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left;
+  int sign_x, sign_y, step, reverse, i;
 
-  dx = x2-x1; ax = ABS(dx)<<1; sx = SGN(dx); x = x1;
-  dy = y2-y1; ay = ABS(dy)<<1; sy = SGN(dy); y = y1;
+  dx = SL_ABSOLUTE(x2, x1, sign_x);
+  dy = SL_ABSOLUTE(y2, y1, sign_y);
+  /* decide increment sign by the slope sign */
+  if (sign_x == sign_y)
+    step = 1;
+  else
+    step = -1;
+
+  if (dy > dx) {	/* chooses axis of greatest movement (make dx) */
+    SL_SWAP(x1, y1);
+    SL_SWAP(x2, y2);
+    SL_SWAP(dx, dy);
+    reverse = 1;
+  } else
+    reverse = 0;
+  /* note error check for dx==0 should be included here */
+  if (x1 > x2) {      /* start from the smaller coordinate */
+    x = x2;
+    y = y2;
+    x1 = x1;
+    y1 = y1;
+  } else {
+    x = x1;
+    y = y1;
+    x1 = x2;
+    y1 = y2;
+  }
+
+
+  /* Note dx=n implies 0 - n or (dx+1) pixels to be set */
+  /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */
+  /* In fact (dx-1)/4 as 2 pixels are already plotted */
+  xend = (dx - 1) / 4;
+  pixels_left = (dx - 1) % 4;  /* number of pixels left over at the
+           * end */
+  plot(object, x, y, reverse, color);
+  if (pixels_left < 0)
+    return;      /* plot only one pixel for zero length
+           * vectors */
+  plot(object, x1, y1, reverse, color);  /* plot first two points */
+  incr2 = 4 * dy - 2 * dx;
+  if (incr2 < 0) {    /* slope less than 1/2 */
+    c = 2 * dy;
+    incr1 = 2 * c;
+    D = incr1 - dx;
+
+    for (i = 0; i < xend; i++) {  /* plotting loop */
+      ++x;
+      --x1;
+      if (D < 0) {
+        /* pattern 1 forwards */
+        plot(object, x, y, reverse, color);
+        plot(object, ++x, y, reverse, color);
+        /* pattern 1 backwards */
+        plot(object, x1, y1, reverse, color);
+        plot(object, --x1, y1, reverse, color);
+        D += incr1;
+      } else {
+        if (D < c) {
+          /* pattern 2 forwards */
+          plot(object, x, y, reverse, color);
+          plot(object, ++x, y += step, reverse,
+              color);
+          /* pattern 2 backwards */
+          plot(object, x1, y1, reverse, color);
+          plot(object, --x1, y1 -= step, reverse,
+              color);
+        } else {
+          /* pattern 3 forwards */
+          plot(object, x, y += step, reverse, color);
+          plot(object, ++x, y, reverse, color);
+          /* pattern 3 backwards */
+          plot(object, x1, y1 -= step, reverse,
+              color);
+          plot(object, --x1, y1, reverse, color);
+        }
+        D += incr2;
+      }
+    }      /* end for */
 
-  if (ax>ay) {					/* x dominant */
-    d = ay-(ax>>1);
-    for (;;) {
-      VGLSetXY(object, x, y, color);
-      if (x==x2)
-	break;
-      if (d>=0) {
-	y += sy; d -= ax;
+    /* plot last pattern */
+    if (pixels_left) {
+      if (D < 0) {
+        plot(object, ++x, y, reverse, color);  /* pattern 1 */
+        if (pixels_left > 1)
+          plot(object, ++x, y, reverse, color);
+        if (pixels_left > 2)
+          plot(object, --x1, y1, reverse, color);
+      } else {
+        if (D < c) {
+          plot(object, ++x, y, reverse, color);  /* pattern 2  */
+          if (pixels_left > 1)
+            plot(object, ++x, y += step, reverse, color);
+          if (pixels_left > 2)
+            plot(object, --x1, y1, reverse, color);
+        } else {
+          /* pattern 3 */
+          plot(object, ++x, y += step, reverse, color);
+          if (pixels_left > 1)
+            plot(object, ++x, y, reverse, color);
+          if (pixels_left > 2)
+            plot(object, --x1, y1 -= step, reverse, color);
+        }
       }
-      x += sx; d += ay;
-    }
+    }      /* end if pixels_left */
   }
-  else {					/* y dominant */
-    d = ax-(ay>>1);
-    for (;;) {
-      VGLSetXY(object, x, y, color);
-      if (y==y2) 
-	break;
-      if (d>=0) {
-	x += sx; d -= ay;
+  /* end slope < 1/2 */
+  else {        /* slope greater than 1/2 */
+    c = 2 * (dy - dx);
+    incr1 = 2 * c;
+    D = incr1 + dx;
+    for (i = 0; i < xend; i++) {
+      ++x;
+      --x1;
+      if (D > 0) {
+        /* pattern 4 forwards */
+        plot(object, x, y += step, reverse, color);
+        plot(object, ++x, y += step, reverse, color);
+        /* pattern 4 backwards */
+        plot(object, x1, y1 -= step, reverse, color);
+        plot(object, --x1, y1 -= step, reverse, color);
+        D += incr1;
+      } else {
+        if (D < c) {
+          /* pattern 2 forwards */
+          plot(object, x, y, reverse, color);
+          plot(object, ++x, y += step, reverse,
+              color);
+
+          /* pattern 2 backwards */
+          plot(object, x1, y1, reverse, color);
+          plot(object, --x1, y1 -= step, reverse,
+              color);
+        } else {
+          /* pattern 3 forwards */
+          plot(object, x, y += step, reverse, color);
+          plot(object, ++x, y, reverse, color);
+          /* pattern 3 backwards */
+          plot(object, x1, y1 -= step, reverse, color);
+          plot(object, --x1, y1, reverse, color);
+        }
+        D += incr2;
+      }
+    }      /* end for */
+    /* plot last pattern */
+    if (pixels_left) {
+      if (D > 0) {
+        plot(object, ++x, y += step, reverse, color);  /* pattern 4 */
+        if (pixels_left > 1)
+          plot(object, ++x, y += step, reverse,
+              color);
+        if (pixels_left > 2)
+          plot(object, --x1, y1 -= step, reverse,
+              color);
+      } else {
+        if (D < c) {
+          plot(object, ++x, y, reverse, color);  /* pattern 2  */
+          if (pixels_left > 1)
+            plot(object, ++x, y += step, reverse, color);
+          if (pixels_left > 2)
+            plot(object, --x1, y1, reverse, color);
+        } else {
+          /* pattern 3 */
+          plot(object, ++x, y += step, reverse, color);
+          if (pixels_left > 1)
+            plot(object, ++x, y, reverse, color);
+          if (pixels_left > 2) {
+            if (D > c)  /* step 3 */
+              plot(object, --x1, y1 -= step, reverse, color);
+            else  /* step 2 */
+              plot(object, --x1, y1, reverse, color);
+          }
+        }
       }
-      y += sy; d += ax;
     }
   }
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 10 Pedro F. Giffuni freebsd_committer freebsd_triage 2012-01-11 21:36:11 UTC
State Changed
From-To: open->patched

Commited to head.
Comment 11 dfilter service freebsd_committer freebsd_triage 2012-02-04 04:31:49 UTC
Author: pfg
Date: Sat Feb  4 04:31:28 2012
New Revision: 230975
URL: http://svn.freebsd.org/changeset/base/230975

Log:
  MFC:	r229415, r229516
  
  Integrate the line drawing algorithm from the book "Graphic Gems 1".
  
  http://www.graphicsgems.org/
  
  At the time it claimed to be 3-4 times faster than the traditional
  algorithm.
  
  Make sure this doesn't give problems to clang.
  
  PR:		18769
  Approved by:	jhb (mentor)

Modified:
  stable/9/lib/libvgl/simple.c
Directory Properties:
  stable/9/lib/libvgl/   (props changed)

Modified: stable/9/lib/libvgl/simple.c
==============================================================================
--- stable/9/lib/libvgl/simple.c	Sat Feb  4 03:08:23 2012	(r230974)
+++ stable/9/lib/libvgl/simple.c	Sat Feb  4 04:31:28 2012	(r230975)
@@ -198,36 +198,205 @@ get_planar:
   return 0;		/* XXX black? */
 }
 
+ /*
+  * Symmetric Double Step Line Algorithm by Brian Wyvill from
+  * "Graphics Gems", Academic Press, 1990.
+  */
+
+#define SL_SWAP(a,b)           {a^=b; b^=a; a^=b;}
+#define SL_ABSOLUTE(i,j,k)     ( (i-j)*(k = ( (i-j)<0 ? -1 : 1)))
+
+void
+plot(VGLBitmap * object, int x, int y, int flag, byte color)
+{
+  /* non-zero flag indicates the pixels need swapping back. */
+  if (flag)
+    VGLSetXY(object, y, x, color);
+  else
+    VGLSetXY(object, x, y, color);
+}
+
+
 void
 VGLLine(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color)
 {
-  int d, x, y, ax, ay, sx, sy, dx, dy;
+  int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left;
+  int sign_x, sign_y, step, reverse, i;
 
-  dx = x2-x1; ax = ABS(dx)<<1; sx = SGN(dx); x = x1;
-  dy = y2-y1; ay = ABS(dy)<<1; sy = SGN(dy); y = y1;
+  dx = SL_ABSOLUTE(x2, x1, sign_x);
+  dy = SL_ABSOLUTE(y2, y1, sign_y);
+  /* decide increment sign by the slope sign */
+  if (sign_x == sign_y)
+    step = 1;
+  else
+    step = -1;
+
+  if (dy > dx) {	/* chooses axis of greatest movement (make dx) */
+    SL_SWAP(x1, y1);
+    SL_SWAP(x2, y2);
+    SL_SWAP(dx, dy);
+    reverse = 1;
+  } else
+    reverse = 0;
+  /* note error check for dx==0 should be included here */
+  if (x1 > x2) {      /* start from the smaller coordinate */
+    x = x2;
+    y = y2;
+/*  x1 = x1;
+    y1 = y1; */
+  } else {
+    x = x1;
+    y = y1;
+    x1 = x2;
+    y1 = y2;
+  }
+
+
+  /* Note dx=n implies 0 - n or (dx+1) pixels to be set */
+  /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */
+  /* In fact (dx-1)/4 as 2 pixels are already plotted */
+  xend = (dx - 1) / 4;
+  pixels_left = (dx - 1) % 4;  /* number of pixels left over at the
+           * end */
+  plot(object, x, y, reverse, color);
+  if (pixels_left < 0)
+    return;      /* plot only one pixel for zero length
+           * vectors */
+  plot(object, x1, y1, reverse, color);  /* plot first two points */
+  incr2 = 4 * dy - 2 * dx;
+  if (incr2 < 0) {    /* slope less than 1/2 */
+    c = 2 * dy;
+    incr1 = 2 * c;
+    D = incr1 - dx;
+
+    for (i = 0; i < xend; i++) {  /* plotting loop */
+      ++x;
+      --x1;
+      if (D < 0) {
+        /* pattern 1 forwards */
+        plot(object, x, y, reverse, color);
+        plot(object, ++x, y, reverse, color);
+        /* pattern 1 backwards */
+        plot(object, x1, y1, reverse, color);
+        plot(object, --x1, y1, reverse, color);
+        D += incr1;
+      } else {
+        if (D < c) {
+          /* pattern 2 forwards */
+          plot(object, x, y, reverse, color);
+          plot(object, ++x, y += step, reverse,
+              color);
+          /* pattern 2 backwards */
+          plot(object, x1, y1, reverse, color);
+          plot(object, --x1, y1 -= step, reverse,
+              color);
+        } else {
+          /* pattern 3 forwards */
+          plot(object, x, y += step, reverse, color);
+          plot(object, ++x, y, reverse, color);
+          /* pattern 3 backwards */
+          plot(object, x1, y1 -= step, reverse,
+              color);
+          plot(object, --x1, y1, reverse, color);
+        }
+        D += incr2;
+      }
+    }      /* end for */
 
-  if (ax>ay) {					/* x dominant */
-    d = ay-(ax>>1);
-    for (;;) {
-      VGLSetXY(object, x, y, color);
-      if (x==x2)
-	break;
-      if (d>=0) {
-	y += sy; d -= ax;
+    /* plot last pattern */
+    if (pixels_left) {
+      if (D < 0) {
+        plot(object, ++x, y, reverse, color);  /* pattern 1 */
+        if (pixels_left > 1)
+          plot(object, ++x, y, reverse, color);
+        if (pixels_left > 2)
+          plot(object, --x1, y1, reverse, color);
+      } else {
+        if (D < c) {
+          plot(object, ++x, y, reverse, color);  /* pattern 2  */
+          if (pixels_left > 1)
+            plot(object, ++x, y += step, reverse, color);
+          if (pixels_left > 2)
+            plot(object, --x1, y1, reverse, color);
+        } else {
+          /* pattern 3 */
+          plot(object, ++x, y += step, reverse, color);
+          if (pixels_left > 1)
+            plot(object, ++x, y, reverse, color);
+          if (pixels_left > 2)
+            plot(object, --x1, y1 -= step, reverse, color);
+        }
       }
-      x += sx; d += ay;
-    }
+    }      /* end if pixels_left */
   }
-  else {					/* y dominant */
-    d = ax-(ay>>1);
-    for (;;) {
-      VGLSetXY(object, x, y, color);
-      if (y==y2) 
-	break;
-      if (d>=0) {
-	x += sx; d -= ay;
+  /* end slope < 1/2 */
+  else {        /* slope greater than 1/2 */
+    c = 2 * (dy - dx);
+    incr1 = 2 * c;
+    D = incr1 + dx;
+    for (i = 0; i < xend; i++) {
+      ++x;
+      --x1;
+      if (D > 0) {
+        /* pattern 4 forwards */
+        plot(object, x, y += step, reverse, color);
+        plot(object, ++x, y += step, reverse, color);
+        /* pattern 4 backwards */
+        plot(object, x1, y1 -= step, reverse, color);
+        plot(object, --x1, y1 -= step, reverse, color);
+        D += incr1;
+      } else {
+        if (D < c) {
+          /* pattern 2 forwards */
+          plot(object, x, y, reverse, color);
+          plot(object, ++x, y += step, reverse,
+              color);
+
+          /* pattern 2 backwards */
+          plot(object, x1, y1, reverse, color);
+          plot(object, --x1, y1 -= step, reverse,
+              color);
+        } else {
+          /* pattern 3 forwards */
+          plot(object, x, y += step, reverse, color);
+          plot(object, ++x, y, reverse, color);
+          /* pattern 3 backwards */
+          plot(object, x1, y1 -= step, reverse, color);
+          plot(object, --x1, y1, reverse, color);
+        }
+        D += incr2;
+      }
+    }      /* end for */
+    /* plot last pattern */
+    if (pixels_left) {
+      if (D > 0) {
+        plot(object, ++x, y += step, reverse, color);  /* pattern 4 */
+        if (pixels_left > 1)
+          plot(object, ++x, y += step, reverse,
+              color);
+        if (pixels_left > 2)
+          plot(object, --x1, y1 -= step, reverse,
+              color);
+      } else {
+        if (D < c) {
+          plot(object, ++x, y, reverse, color);  /* pattern 2  */
+          if (pixels_left > 1)
+            plot(object, ++x, y += step, reverse, color);
+          if (pixels_left > 2)
+            plot(object, --x1, y1, reverse, color);
+        } else {
+          /* pattern 3 */
+          plot(object, ++x, y += step, reverse, color);
+          if (pixels_left > 1)
+            plot(object, ++x, y, reverse, color);
+          if (pixels_left > 2) {
+            if (D > c)  /* step 3 */
+              plot(object, --x1, y1 -= step, reverse, color);
+            else  /* step 2 */
+              plot(object, --x1, y1, reverse, color);
+          }
+        }
       }
-      y += sy; d += ax;
     }
   }
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 12 Pedro F. Giffuni freebsd_committer freebsd_triage 2012-02-04 04:42:30 UTC
State Changed
From-To: patched->closed

Line drawing algorith was MFC/9