Index:
[thread]
[date]
[subject]
[author]
From: Martin Eli Erhardsen <mee@daimi.aau.dk>
To : ggi-develop@eskimo.com
Date: Wed, 08 Jul 1998 21:15:47 +0200
Fast lines
Why are the linear targets using the sliced runlength bresenham
linedrawing algoritm, when a straight bresenham linedraw is
faster and much simpler.
I think that a fixedpoint linedrawing algoritm could be
a good idea too, but it requires an extra division compared
with bresenham, and the decision variable must be
tvice as wide for the same precision.
I have attached the program, which I used to take the
following measurements on a MIPS R10000
~/prgs/lines> hinv
1 175 MHZ IP30 Processor
CPU: MIPS R10000 Processor Chip Revision: 2.7
FPU: MIPS R10010 Floating Point Chip Revision: 0.0
Main memory size: 128 Mbytes
Instruction cache size: 32 Kbytes
Data cache size: 32 Kbytes
Secondary unified instruction/data cache size: 1 Mbyte
Integral SCSI controller 0: Version QL1040B (rev. 2)
Disk drive: unit 1 on SCSI controller 0
Integral SCSI controller 1: Version QL1040B (rev. 2)
CDROM: unit 4 on SCSI controller 1
IOC3 serial port: tty1
IOC3 serial port: tty2
IOC3 parallel port: plp1
Graphics board: SI
Integral Fast Ethernet: ef0, version 1
Iris Audio Processor: version RAD revision 12.0, number 1
~/prgs/lines> cc -O2 -n32 -mips4 -r10000 speed.c -o speed
~/prgs/lines> ./speed
BasicConsistency
ColorWrap
Info:Color wraps at 256
HLine
VLine
sliced
Line 1: 9803921.568627 1.020000 0.000000
XMajorLine 10: 1098901.098901 8.970000 0.130000
YmajorLine 10: 1102535.832415 8.980000 0.090000
XMajorLine 100: 200400.801603 4.940000 0.050000
YmajorLine 100: 199600.798403 4.950000 0.060000
bres1
LineTest Skipped
Line 1: 5988023.952096 1.660000 0.010000
XMajorLine 10: 990099.009901 1.010000 0.000000
YmajorLine 10: 976562.500000 10.120000 0.120000
XMajorLine 100: 128700.128700 7.710000 0.060000
YmajorLine 100: 128700.128700 7.720000 0.050000
bres2
Line 1: 6944444.444444 1.440000 0.000000
XMajorLine 10: 2314814.814815 4.310000 0.010000
YmajorLine 10: 2083333.333333 4.770000 0.030000
XMajorLine 100: 374531.835206 2.650000 0.020000
YmajorLine 100: 309597.523220 3.220000 0.010000
bres3
Line 1: 6944444.444444 1.430000 0.010000
XMajorLine 10: 1445086.705202 6.860000 0.060000
YmajorLine 10: 1600000.000000 6.210000 0.040000
XMajorLine 100: 188323.917137 5.280000 0.030000
YmajorLine 100: 228310.502283 4.340000 0.040000
fixedpoint1
Line 1: 5102040.816327 1.900000 0.060000
XMajorLine 10: 2105263.157895 4.720000 0.030000
YmajorLine 10: 2222222.222222 4.480000 0.020000
XMajorLine 100: 392156.862745 2.530000 0.020000
YmajorLine 100: 492610.837438 2.020000 0.010000
fixedpoint2
Line 1: 6666666.666667 1.480000 0.020000
XMajorLine 10: 1464128.843338 6.740000 0.090000
YmajorLine 10: 1398601.398601 7.070000 0.080000
XMajorLine 100: 409836.065574 2.430000 0.010000
YmajorLine 100: 458715.596330 2.170000 0.010000
~/prgs/lines>
/*
* This is a GGI speed- and consistency-test application.
* Policy : Speed-Tests send their output to stdout,
* Consistency-Tests report to stderr.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/times.h>
#ifdef _POSIX_PRIORITY_SCHEDULING
# include <sched.h>
#else
# define sched_yield() ;
#endif
unsigned char Buffer[128][128];
unsigned int COL;
#define ggiSetGCForeground(vis,c) COL=c
#define ggiDrawPixel(vis,x,y) Buffer[y][x]=COL
#define GGIdrawpixel(vis,x,y) Buffer[y][x]=COL
#define ggiPutPixel(vis,x,y,c) Buffer[y][x]=c
#define ggiGetPixel(vis,x,y,p) *p=Buffer[y][x]
#define ggiFillscreen(vis) memset(Buffer,COL,128*128)
#define ggiDrawHLine(vis,x,y,l) memset(&Buffer[y][x],COL,l)
#define ggiDrawVLine(vis,x,y,l) {int i;for(i=0;i<l;i++) Buffer[y+i][x]=COL;}
int (*ggiDrawLine)(int *vis,int x1,int y1,int x2,int y2);
#define VIS_FB_LINEAR(vis) Buffer
#define VIS_FB_WIDTH(vis) 128
#define VIS_GC_FGCOLOR(vis) COL
#define LIBGGI_FB_LINEAR(vis) Buffer
#define LIBGGI_FB_WIDTH(vis) 128
#define LIBGGI_GC_FGCOLOR(vis) COL
struct {
int *vis;
int vx,vy;
} mode;
typedef unsigned int ggi_uint;
typedef int ggi_visual;
typedef unsigned char uchar;
#define EOK 0
/**********************************************************************/
/* This is a general clipping linedrawer using a sliced run-length
bresenham algorithm. It is modified to calculate the first and last
run-lengths when they are clipped to get pixel-perfect rasterization.
If you wan't to use this you have to define FBTYPE to the right frame-
buffer type and then include this file.
*/
typedef unsigned char FBTYPE;
int sliced(ggi_visual *vis,int orig_x1,int orig_y1,int orig_x2,int orig_y2)
{
int orig_dx,orig_dy,sx,sy;
int dx,dy;
int i;
int w;
int x1,y1,x2,y2;
int clip_first=0,clip_last=0;
FBTYPE *fb,color;
color = LIBGGI_GC_FGCOLOR(vis);
x1 = orig_x1;
y1 = orig_y1;
x2 = orig_x2;
y2 = orig_y2;
/* clip x1,y1 and x2,y2. Set clip_first and clip_last if clipped */
/* if (!clip2d(vis, &x1,&y1,&x2,&y2,&clip_first,&clip_last))
return 0; */ /* Clipped */
dy = y2 - y1;
orig_dy = orig_y2 - orig_y1;
sy=1;
if (orig_dy<0) {
orig_dy = -orig_dy;
dy = -dy;
sy = -1;
}
dx = x2-x1;
orig_dx = orig_x2 - orig_x1;
sx=1;
if (orig_dx<0) {
sx=-1;
orig_dx = -orig_dx;
dx = -dx;
}
w = LIBGGI_FB_WIDTH(vis);
fb = ((FBTYPE *)LIBGGI_FB_LINEAR(vis)) + y1*w+x1;
if (dx==0) {
if (sy<0)
w=-w;
for (i=dy;i>=0; i--) {
*fb = color;
fb += w;
}
return 0;
}
if (dy==0) {
for (i=dx;i>=0; i--) {
*fb = color;
fb += sx;
}
return 0;
}
if (orig_dx==orig_dy) {
if (sy<0)
w=-w;
w += sx;
for (i=dx;i>=0; i--) {
*fb = color;
fb += w;
}
return 0;
}
if (orig_dx >= orig_dy) { /* x major */
int runlen,adjup,adjdown,e,len;
int firstlen,lastlen;
runlen = orig_dx/orig_dy;
adjup = orig_dx%orig_dy;
lastlen = firstlen = (runlen>>1) + 1;
if (clip_first) { /* clipped, Adjust firstlen */
int clip_dx = abs(x1 - orig_x1);
int clip_dy = abs(y1 - orig_y1);
int d = (2*clip_dy+1)*orig_dx;
firstlen = d/(2*orig_dy) - clip_dx + 1;
e = d%(2*orig_dy);
if ((e==0) && (sy>0)) { /* Special case, arbitrary choise. Select lower pixel.(?) */
firstlen--;
e += 2*orig_dy;
}
e -= (orig_dy*2);
} else { /* Not clipped, calculate start error term */
e = adjup - (orig_dy<<1); /* initial errorterm == half a step */
if ((runlen&1) != 0) {
e += orig_dy;
}
}
if (clip_last) { /* Last endpoint clipped */
int clip_dx = abs(x2 - orig_x2);
int clip_dy = abs(y2 - orig_y2);
int d = (1+2*clip_dy)*orig_dx;
lastlen = d/(2*orig_dy) - clip_dx + 1;
if ((sy<0) && ((d%(2*orig_dy))==0) ) /* special arbitrary case */
lastlen--;
}
adjup <<= 1;
adjdown = orig_dy<<1;
if (sy>0) { /* line goes down */
if ((adjup==0) && ((runlen&1)==0) && (!clip_first)) {
firstlen--;
}
if (sx>0) { /* line goes right */
for (;firstlen>0; firstlen--) {
*fb = color;
fb++;
}
fb += w;
for (i=dy-1; i>0; i--) {
len = runlen;
e += adjup;
if (e>0) {
len++;
e -= adjdown;
}
for (;len>0; len--) {
*fb = color;
fb++;
}
fb += w;
}
for (;lastlen>0; lastlen--) {
*fb = color;
fb++;
}
return 0;
} else { /* line goes left */
for (;firstlen>0; firstlen--) {
*fb = color;
fb--;
}
fb += w;
for (i=dy-1; i>0; i--) {
len = runlen;
e += adjup;
if (e>0) {
len++;
e -= adjdown;
}
for (;len>0; len--) {
*fb = color;
fb--;
}
fb += w;
}
for (;lastlen>0; lastlen--) {
*fb = color;
fb--;
}
return 0;
}
} else { /* line goes up */
if ((adjup==0) && ((runlen&1)==0) && (!clip_last)) {
lastlen--;
}
if (sx>0) { /* line goes right */
for (;firstlen>0; firstlen--) {
*fb = color;
fb++;
}
fb -= w;
for (i=dy-1; i>0; i--) {
len = runlen;
e += adjup;
if (e>=0) {
len++;
e -= adjdown;
}
for (;len>0; len--) {
*fb = color;
fb++;
}
fb -= w;
}
for (;lastlen>0; lastlen--) {
*fb = color;
fb++;
}
return 0;
} else { /* line goes left */
for (;firstlen>0; firstlen--) {
*fb = color;
fb--;
}
fb -= w;
for (i=dy-1; i>0; i--) {
len = runlen;
e += adjup;
if (e>=0) {
len++;
e -= adjdown;
}
for (;len>0; len--) {
*fb = color;
fb--;
}
fb -= w;
}
for (;lastlen>0; lastlen--) {
*fb = color;
fb--;
}
return 0;
}
}
} else { /* y major */
int runlen,adjup,adjdown,e,len;
int firstlen,lastlen;
runlen = orig_dy/orig_dx;
adjup = orig_dy%orig_dx;
lastlen = firstlen = (runlen>>1) + 1;
if (clip_first) { /* clipped, Adjust firstlen */
int clip_dx = abs(x1 - orig_x1);
int clip_dy = abs(y1 - orig_y1);
int d = (2*clip_dx+1)*orig_dy;
firstlen = d/(2*orig_dx) - clip_dy + 1;
e = d%(2*orig_dx);
if ((e==0) && (sx>0)) { /* Special case, arbitrary choise. Select lower pixel.(?) */
firstlen--;
e += 2*orig_dx;
}
e -= (orig_dx*2);
} else { /* Not clipped, calculate start error term */
e = adjup - (orig_dx<<1); /* initial errorterm == half a step */
if ((runlen&1) != 0) {
e += orig_dx;
}
}
if (clip_last) { /* Last endpoint clipped */
int clip_dx = abs(x2 - orig_x2);
int clip_dy = abs(y2 - orig_y2);
int d = (1+2*clip_dx)*orig_dy;
lastlen = d/(2*orig_dx) - clip_dy + 1;
if ((sx<0) && ((d%(2*orig_dx))==0) ) /* special arbitrary case */
lastlen--;
}
adjup <<= 1;
adjdown = orig_dx<<1;
if (sy>0) { /* Line goes DOWN */
if (sx>0) { /* line goes RIGHT */
if ((adjup==0) && ((runlen&1)==0) && (!clip_first)) {
firstlen--;
}
for (;firstlen>0; firstlen--) {
*fb = color;
fb += w;
}
fb++;
for (i=dx-1; i>0; i--) {
len = runlen;
e += adjup;
if (e>0) {
len++;
e -= adjdown;
}
for (;len>0; len--) {
*fb = color;
fb += w;
}
fb ++;
}
for (;lastlen>0; lastlen--) {
*fb = color;
fb += w;
}
return 0;
} else { /* line goes LEFT */
if ((adjup==0) && ((runlen&1)==0) && (!clip_last)) {
lastlen--;
}
for (;firstlen>0; firstlen--) {
*fb = color;
fb += w;
}
fb--;
for (i=dx-1; i>0; i--) {
len = runlen;
e += adjup;
if (e>=0) {
len++;
e -= adjdown;
}
for (;len>0; len--) {
*fb = color;
fb += w;
}
fb --;
}
for (;lastlen>0; lastlen--) {
*fb = color;
fb += w;
}
return 0;
}
} else { /* Line goes UP */
if (sx>0) { /* line goes RIGHT */
if ((adjup==0) && ((runlen&1)==0) && (!clip_first)) {
firstlen--;
}
for (;firstlen>0; firstlen--) {
*fb = color;
fb -= w;
}
fb++;
for (i=dx-1; i>0; i--) {
len = runlen;
e += adjup;
if (e>0) {
len++;
e -= adjdown;
}
for (;len>0; len--) {
*fb = color;
fb -= w;
}
fb ++;
}
for (;lastlen>0; lastlen--) {
*fb = color;
fb -= w;
}
return 0;
} else { /* line goes LEFT */
if ((adjup==0) && ((runlen&1)==0) && (!clip_last)) {
lastlen--;
}
for (;firstlen>0; firstlen--) {
*fb = color;
fb -= w;
}
fb--;
for (i=dx-1; i>0; i--) {
len = runlen;
e += adjup;
if (e>=0) {
len++;
e -= adjdown;
}
for (;len>0; len--) {
*fb = color;
fb -= w;
}
fb --;
}
for (;lastlen>0; lastlen--) {
*fb = color;
fb -= w;
}
return 0;
}
}
}
}
/***********************
* Drawline, Bresenham *
***********************/
int bres1(ggi_visual *vis,int x1,int y1,int x2,int y2)
{
int dx,dy,dz,m11,m12,m21,m22,x,y,p,q,c,e,k1,k2;
dx=x2-x1;dy=y2-y1;dz=abs(dx)-abs(dy);
if (dx<0) { m21=-1; } else { m21=+1; }
if (dy<0) { m22=-1; } else { m22=+1; }
if (dz<0) {
p=abs(dx);q=abs(dy);m11=0;m12=m22;
} else {
p=abs(dy);q=abs(dx);m11=m21;m12=0;
}
x=x1;y=y1;c=q;k1=2*p;e=2*p-q;k2=2*p-2*q;
if ((dz>0)&&(dy>0)) e--;
if ((dz<0)&&(dx<0)) e--;
GGIdrawpixel(vis,x,y);c--;
while (c>=0) {
if (e<0) {
x+=m11;y+=m12;e+=k1;
} else {
x+=m21;y+=m22;e+=k2;
}
GGIdrawpixel(vis,x,y);c--;
}
return EOK;
}
int bres2(ggi_visual *vis,int x1,int y1,int x2,int y2)
{
int dx,dy,sx,sy,st,bla,mask,c; unsigned char color,*adr;
sx=1;dx=x2-x1;if (dx<0) {sx=-1;dx=-dx;}
sy=1;dy=y2-y1;if (dy<0) {sy=-1;dy=-dy;}
st=(dx-dy);bla=(dx>dy);
if (bla) st-=dy;else st+=dx;
if (bla&&sy>0) st--;
if (!bla&&sx<0) st--;
dx*=2;dy*=2;
adr=((unsigned char *)VIS_FB_LINEAR(vis))+y1*VIS_FB_WIDTH(vis)+x1;
sy*=VIS_FB_WIDTH(vis);
color=VIS_GC_FGCOLOR(vis);
*adr=color;
if (bla) {
c=abs(x1-x2);
while(c--) {
mask=(st>>31);adr+=(sy&mask);st+=dx&mask;
adr+=sx;st-=dy;
*adr=color;
}
} else {
c=abs(y1-y2);
while(c--) {
mask=~(st>>31);adr+=(sx&mask);st-=dy&mask;
adr+=sy;st+=dx;
*adr=color;
}
}
return EOK;
}
int bres3(ggi_visual *vis,int x1,int y1,int x2,int y2)
{
int dx,dy,sx,sy,st,bla,mask,c; unsigned char color,*adr;
sx=1;dx=x2-x1;if (dx<0) {sx=-1;dx=-dx;}
sy=1;dy=y2-y1;if (dy<0) {sy=-1;dy=-dy;}
st=(dx-dy);bla=(dx>dy);
if (bla) st-=dy;else st+=dx;
if (bla&&sy>0) st--;
if (!bla&&sx<0) st--;
dx*=2;dy*=2;
adr=((unsigned char *)VIS_FB_LINEAR(vis))+y1*VIS_FB_WIDTH(vis)+x1;
sy*=VIS_FB_WIDTH(vis);
color=VIS_GC_FGCOLOR(vis);
*adr=color;
if (bla) {
c=abs(x1-x2);
while(c--) {
if (st<0) { adr+=sy;st+=dx; }
adr+=sx;st-=dy;
*adr=color;
}
} else {
c=abs(y1-y2);
while(c--) {
if (st>=0) { adr+=sx;st-=dy; }
adr+=sy;st+=dx;
*adr=color;
}
}
return EOK;
}
int fixedpoint1(ggi_visual *vis,int x1,int y1,int x2,int y2)
{
int dx,dy,sy,sx,x,y,slope;
dx=abs(x2-x1);
dy=abs(y2-y1);
if (dy==0) {
if (x1>x2) {x=x1;x1=x2;x2=x;}
ggiDrawHLine(vis,x1,y1,dx+1);
} else if (dx==0) {
if (y1>y2) {y=y1;y1=y2;y2=y;}
ggiDrawVLine(vis,x1,y1,dy+1);
} else if (dy>dx) {
if (y1>y2) {sy=-1;} else {sy=1;};
dx=x2-x1;
slope=(dx<<20)/dy;
x=(x1<<20)+(1<<19)+dy;
for(y=y1;y!=y2+sy;y+=sy) {
ggiDrawPixel(vis,x>>20,y);
x+=slope;
}
} else {
if (x1>x2) {sx=-1;} else {sx=1;};
dy=y2-y1;
slope=(dy<<20)/dx;
y=(y1<<20)+(1<<19)+dx;
for(x=x1;x!=x2+sx;x+=sx) {
ggiDrawPixel(vis,x,y>>20);
y+=slope;
}
}
return 0;
}
int fixedpoint2(ggi_visual *vis,int x1,int y1,int x2,int y2)
{
int sx,sy;
uint dx,dy,slope,frac,temp,step;
FBTYPE *adr,color;
dx=abs(x2-x1);
dy=abs(y2-y1);
if (dy==0) {
if (x1>x2) x1=x2;
adr=((FBTYPE *)LIBGGI_FB_LINEAR(vis))+
y1*LIBGGI_FB_WIDTH(vis)+x1;
memset(adr,VIS_GC_FGCOLOR(vis),dx+1);
} else if (dy>=dx) {
if (dy==dx) {slope=-1;} else
slope=(((unsigned long long)dx)<<32)/dy;
step=VIS_FB_WIDTH(vis);
if (y1>y2) {step=-step;}
if (x1>x2) {
step--;
slope=-slope;
}
adr=((FBTYPE *)VIS_FB_LINEAR(vis))+y1*VIS_FB_WIDTH(vis)+x1;
frac=(1UL<<31)+dy;
color=VIS_GC_FGCOLOR(vis);
for (dy++;dy--;)
{
*adr=color;
temp=frac;
frac+=slope;
adr+=step;
adr+=temp>frac;
}
} else {
sx=1|((x2-x1)>>31);
slope=(((unsigned long long) dy)<<32)/dx;
frac=(1UL<<31)+dx;
sy=VIS_FB_WIDTH(vis);
if (y1>y2) { sy=-sy; frac=-frac; }
adr=((FBTYPE *)LIBGGI_FB_LINEAR(vis))+
y1*LIBGGI_FB_WIDTH(vis)+x1;
color=LIBGGI_GC_FGCOLOR(vis);
for(dx++;dx--;)
{
*adr=color;
adr+=sx;
temp=frac;
frac+=slope;
adr+=sy&(-(frac<temp));
}
}
return 0;
}
#if 0
int fixedpoint_asm(ggi_visual *vis,int x1,int y1,int x2,int y2)
{
uint slope,step,frac,temp;
uchar *adr,color;
int dx,dy,sy,sx,x,y,res;
dx=abs(x2-x1);
dy=abs(y2-y1);
if (dy==0) {
if (x1>x2) x1=x2;
adr=((uchar *)VIS_FB_LINEAR(vis))+y1*VIS_FB_WIDTH(vis)+x1;
memset(adr,VIS_GC_FGCOLOR(vis),dx+1);
} else if (dy>=dx) {
if (dy==dx) {slope=-1;} else
asm("divl %3":"=eax" (slope) : "0"(0), "edx" (dx) ,"g" (dy));
step=VIS_FB_WIDTH(vis);
if (y1>y2) {step=-step;}
if (x1>x2) {
step--;
slope=-slope;
}
adr=((uchar *)VIS_FB_LINEAR(vis))+y1*VIS_FB_WIDTH(vis)+x1;
frac=(1UL<<31)+dy;
color=VIS_GC_FGCOLOR(vis);
asm volatile ("l1: movb %4,(%1)\n\t"
"addl %2,%0\n\t"
"adcl %3,%1\n\t"
"decl %5\n\t"
"jns l1\n\t"
: : "r" (frac), "r" (adr), "r" (slope),
"g" (step), "r" (color),"r" (dy));
} else {
if (x1>x2) { sx=-1;} else {sx=1;}
asm("divl %3":"=eax" (slope) : "0"(0), "edx" (dy) ,"g" (dx));
sy=VIS_FB_WIDTH(vis);
frac=(1UL<<31)+dx;
if (y1>y2) { sy=-sy; frac=-frac; }
adr=((uchar *)VIS_FB_LINEAR(vis))+y1*VIS_FB_WIDTH(vis)+x1;
color=VIS_GC_FGCOLOR(vis);
for(dx++;--dx>=0;) {
*adr=color;
adr+=sx;
frac=(temp=frac)+slope;
if (temp>frac) adr+=sy;
}
}
return 0;
}
#endif
/**********************************************************************/
struct tms timer;
double u_time,s_time;
void time_start(void)
{ times(&timer); }
void time_offset(void)
{ struct tms end;
times(&end);
u_time=-(end.tms_utime-timer.tms_utime)/(double)CLK_TCK;
s_time=-(end.tms_stime-timer.tms_stime)/(double)CLK_TCK;
time_start();
}
void time_stop(void)
{ struct tms end;
times(&end);
u_time+=(end.tms_utime-timer.tms_utime)/(double)CLK_TCK;
s_time+=(end.tms_stime-timer.tms_stime)/(double)CLK_TCK;
}
#define white_pixel 1
int nothing(ggi_visual *vis,int x1,int y1,int x2,int y2) {return 0;}
int getnumpixels(int x1,int y1,int x2,int y2)
{
int x,y,c;
ggi_uint i;
c=0;
for(y=y1;y<=y2;y++)
for(x=x1;x<=x2;x++)
{
ggiGetPixel(mode.vis,x,y,&i);
if ( i != 0 ) c++;
}
return c;
}
void BasicConsistency(void)
{
int c,x,y;
ggi_uint i;
/* Get/Put/DrawPixel consistency test */
ggiSetGCForeground(mode.vis,0);
ggiFillscreen(mode.vis);
/* The screen should now be all zero. */
c=0;
for(y=0;y<mode.vy;y++)
for(x=0;x<mode.vx;x++)
{
ggiGetPixel(mode.vis,x,y,&i);
if ( i != 0 )
{
printf("Warning: Screen not blank at %d,%d (%x)\n",x,y,i);
c++;
if (c>16)
{
fprintf(stderr,"Error: Screen not blank or GetPixel not working. Disabled consitency checks.\n");
y=mode.vy;
break;
}
}
}
}
void ColorWrap(void)
{
ggi_uint i,c;
/* Now we check when we have a color wraparound. */
if (1)
for(i=0;i!=0xffffffff;i++)
{
ggiPutPixel(mode.vis,0,0,i);
ggiGetPixel(mode.vis,0,0,&c);
if ( i != c )
{ fprintf(stderr,"Info:Color wraps at %d\n",i);
break;
}
}
}
void Hline(void)
{
int x,y,c;
ggiSetGCForeground(mode.vis,0);
ggiFillscreen(mode.vis);
if (1)
for(x=0;x<mode.vx;x++)
{
for(y=0;y<=mode.vx-x;y++)
{
ggiSetGCForeground(mode.vis,white_pixel);
ggiDrawHLine(mode.vis,x,0,y);
ggiSetGCForeground(mode.vis,0);
/* for speed reasons, we hope for no stray pixels far away ... */
if ((c=getnumpixels(0,0,mode.vx-1,1))!=y || getnumpixels(x,0,x+y-1,0)!=y )
{
ggiFillscreen(mode.vis);
fprintf(stderr,"Error:Hline(%d,0,%d); consistency failed (%d pixels measured).\n",x,y,c);
} else
ggiDrawHLine(mode.vis,x,0,y);
}
}
}
void Vline(void)
{
int x,y,c;
if (1)
for(y=0;y<mode.vy;y++)
{
ggiSetGCForeground(mode.vis,0);
ggiFillscreen(mode.vis);
ggiSetGCForeground(mode.vis,white_pixel);
for(x=0;x<=mode.vy-y;x++)
{
ggiDrawVLine(mode.vis,0,y,x);
/* for speed reasons, we hope for no stray pixels far away ... */
if ((c=getnumpixels(0,0,1,mode.vy-1))!=x || (c=getnumpixels(0,y,0,x+y-1))!=x )
{
fprintf(stderr,"Error:Vline(0,%d,%d); consistency failed (%d pixels measured).\n",y,x,c);
}
}
}
}
void CheckLine(ggi_visual *vis,int x1,int y1,int x2,int y2)
{
int xx,max,cx,cy;
ggi_uint c;
ggiSetGCForeground(vis,white_pixel);
ggiDrawLine(vis,x1,y1,x2,y2);
ggiSetGCForeground(vis,0);
max=abs(x2-x1);if (abs(y2-y1)>max) max=abs(y2-y1);
if (max==0) return;
for(xx=0;xx<=max;xx++)
{
cx=(x1*xx+x2*(max-xx)+max/2)/max;
cy=(y1*xx+y2*(max-xx)+max/2)/max;
ggiGetPixel (vis,cx,cy,&c);
if (c==0) printf("Line: Unset pixel %d,%d in line(%d,%d,%d,%d).\n",
cx,cy,x1,y1,x2,y2);
ggiDrawPixel(vis,cx,cy);
}
if ((c=getnumpixels(0,0,120,120))!=0)
{ printf("Line: %d surplus pixels in line(%d,%d,%d,%d).\n",
c,x1,y1,x2,y2);
ggiFillscreen(vis);
}
}
void LineTest(void)
{
int x;
ggiSetGCForeground(mode.vis,0);
ggiFillscreen(mode.vis);
for(x=10;x<110;x++)
CheckLine(mode.vis, 10, 10,x,110);
for(x=10;x<110;x++)
CheckLine(mode.vis, 10, 10,110,x);
for(x=10;x<110;x++)
CheckLine(mode.vis,110, 10,x,110);
for(x=10;x<110;x++)
CheckLine(mode.vis,110, 10, 10,x);
for(x=10;x<110;x++)
CheckLine(mode.vis, 10,110,x, 10);
for(x=10;x<110;x++)
CheckLine(mode.vis, 10,110,110,x);
for(x=10;x<110;x++)
CheckLine(mode.vis,110,110,x, 10);
for(x=10;x<110;x++)
CheckLine(mode.vis,110,110, 10,x);
}
void LineSpeed(void)
{
int x,c,mxcnt;
for(mxcnt=1000;mxcnt<1000000000;mxcnt*=10)
{
time_start();
for(c=mxcnt;c>0;c--)
nothing(mode.vis,10,10,10,10);
time_offset();
for(c=mxcnt;c>0;c--)
ggiDrawLine(mode.vis,10,10,10,10);
time_stop();
if ( u_time+s_time > 1.0 ) break;
}
printf("Line 1: %f %f %f\n",mxcnt/(u_time+s_time),u_time,s_time);
for(mxcnt=1;mxcnt<1000000000;mxcnt*=10)
{
time_start();
for(c=mxcnt/10;c>0;c--)
for(x=10;x<20;x++)
nothing(mode.vis,10,10,19,x);
time_offset();
for(c=mxcnt/10;c>0;c--)
for(x=10;x<20;x++)
ggiDrawLine(mode.vis,10,10,19,x);
time_stop();
if ( u_time+s_time > 1.0 ) break;
}
printf("XMajorLine 10: %f %f %f\n",mxcnt/(u_time+s_time),u_time,s_time);
for(mxcnt=1;mxcnt<1000000000;mxcnt*=10)
{
time_start();
for(c=mxcnt/10;c>0;c--)
for(x=10;x<20;x++)
nothing(mode.vis,10,10,x,19);
time_offset();
for(c=mxcnt/10;c>0;c--)
for(x=10;x<20;x++)
ggiDrawLine(mode.vis,10,10,x,19);
time_stop();
if ( u_time+s_time > 1.0 ) break;
}
printf("YmajorLine 10: %f %f %f\n",mxcnt/(u_time+s_time),u_time,s_time);
for(mxcnt=1;mxcnt<1000000000;mxcnt*=10)
{
time_start();
for(c=mxcnt/100;c>0;c--)
for(x=10;x<110;x++)
nothing(mode.vis,10,10,109,x);
time_offset();
for(c=mxcnt/100;c>0;c--)
for(x=10;x<110;x++)
ggiDrawLine(mode.vis,10,10,109,x);
time_stop();
if ( u_time+s_time > 1.0 ) break;
}
printf("XMajorLine 100: %f %f %f\n",mxcnt/(u_time+s_time),u_time,s_time);
for(mxcnt=1;mxcnt<1000000000;mxcnt*=10)
{
time_start();
for(c=mxcnt/100;c>0;c--)
for(x=10;x<110;x++)
nothing(mode.vis,10,10,x,109);
time_offset();
for(c=mxcnt/100;c>0;c--)
for(x=10;x<110;x++)
ggiDrawLine(mode.vis,10,10,x,109);
time_stop();
if ( u_time+s_time > 1.0 ) break;
}
printf("YmajorLine 100: %f %f %f\n",mxcnt/(u_time+s_time),u_time,s_time);
}
int main(int argc,char **argv)
{
srandom(time(NULL));
printf("BasicConsistency\n");
BasicConsistency();
printf("ColorWrap\n");
ColorWrap();
printf("HLine\n");
Hline();
printf("VLine\n");
Vline();
printf("sliced\n");
ggiDrawLine=sliced;
LineTest();
LineSpeed();
printf("bres1\n");
ggiDrawLine=bres1;
printf("LineTest Skipped\n");
/* LineTest(); */
LineSpeed();
printf("bres2\n");
ggiDrawLine=bres2;
LineTest();
LineSpeed();
printf("bres3\n");
ggiDrawLine=bres3;
LineTest();
LineSpeed();
printf("fixedpoint1\n");
ggiDrawLine=fixedpoint1;
LineTest();
LineSpeed();
printf("fixedpoint2\n");
ggiDrawLine=fixedpoint2;
LineTest();
LineSpeed();
#if 0
printf("fixedpoint_asm\n");
ggiDrawLine=fixedpoint_asm;
LineTest();
LineSpeed();
#endif
return 0;
}
Index:
[thread]
[date]
[subject]
[author]