tests.c revision 9aa2a2b5
1/*
2**
3*/
4
5#include <X11/Intrinsic.h>
6#include <X11/StringDefs.h>
7#include <X11/Xaw/AsciiText.h>
8#include <X11/Xos.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <math.h>
12#include "xgc.h"
13#ifdef SVR4
14#define SYSV
15#endif
16#if !defined(SYSV) && !defined(QNX4)
17#include <sys/timeb.h>
18#include <sys/resource.h>
19#endif
20
21#ifndef PI
22#define PI 3.14159265
23#endif
24
25#ifdef SYSV
26#define random lrand48
27#endif
28
29
30/* timer(flag)
31** -----------
32** When called with StartTimer, starts the stopwatch and returns nothing.
33** When called with EndTimer, stops the stopwatch and returns the time
34** in microseconds since it started.
35**
36** Uses rusage() so we can subtract the time used by the system and user
37** from our timer, and just concentrate on the time used in the X calls.
38*/
39
40static long
41timer(int flag)
42{
43#if !defined(SYSV)
44  static struct timeval starttime;  /* starting time for gettimeofday() */
45  struct timeval endtime;           /* ending time for gettimeofday() */
46#if !defined(__UNIXOS2__) && !defined(QNX4)
47  static struct rusage startusage;  /* starting time for getrusage() */
48  struct rusage endusage;           /* ending time for getrusage() */
49#endif
50  struct timezone tz;               /* to make gettimeofday() happy */
51
52  long elapsedtime;                 /* how long since we started the timer */
53
54  switch (flag) {
55    case StartTimer:                       /* store initial values */
56      gettimeofday(&starttime,&tz);
57#if !defined(__UNIXOS2__) && !defined(QNX4)
58      getrusage(RUSAGE_SELF,&startusage);
59#endif
60      return((long) NULL);
61    case EndTimer:
62      gettimeofday(&endtime,&tz);          /* store final values */
63#if !defined(__UNIXOS2__) && !defined(QNX4)
64      getrusage(RUSAGE_SELF,&endusage);
65#endif
66
67  /* all the following line does is use the formula
68     elapsed time = ending time - starting time, but there are three
69     different timers and two different units of time, ack... */
70
71#if !defined(__UNIXOS2__) && !defined(QNX4)
72      elapsedtime = (long) ((long)
73	((endtime.tv_sec - endusage.ru_utime.tv_sec - endusage.ru_stime.tv_sec
74	 - starttime.tv_sec + startusage.ru_utime.tv_sec
75	 + startusage.ru_stime.tv_sec)) * 1000000) + (long)
76      ((endtime.tv_usec - endusage.ru_utime.tv_usec - endusage.ru_stime.tv_usec
77	 - starttime.tv_usec + startusage.ru_utime.tv_usec
78	 + startusage.ru_stime.tv_usec));
79#else
80      elapsedtime = (long)( ((long)endtime.tv_sec-(long)starttime.tv_sec)*1000000
81			   +((long)endtime.tv_usec-(long)starttime.tv_usec));
82#endif
83      return(elapsedtime);
84
85    default:
86      fprintf(stderr,"Invalid flag in timer()\n");
87      return((long) NULL);
88    }
89#else
90  static time_t starttime;
91
92  switch (flag) {
93    case StartTimer:
94      time(&starttime);
95      return((long) NULL);
96    case EndTimer:
97      return( (time(NULL) - starttime) * 1000000);
98    default:
99      fprintf(stderr,"Invalid flag in timer()\n");
100      return((long) NULL);
101    }
102#endif
103}
104
105
106void
107copyarea_test(void)
108{
109  int num_copies = 200;
110  int i;
111  long totaltime;
112  char buf[80];
113
114  num_copies *= X.percent;
115
116  XSetFillStyle(X.dpy,X.miscgc,FillTiled);
117  XFillRectangle(X.dpy,X.win,X.miscgc,0,0,400,400);
118
119  XSync(X.dpy,0);
120  timer(StartTimer);
121  for (i=0;i<num_copies;++i)
122    XCopyArea(X.dpy,X.win,X.win,X.gc,i,200-i,
123	      200,200,200-i,i);
124  XSync(X.dpy,0);
125  totaltime = timer(EndTimer);
126
127  snprintf(buf,sizeof buf,"%.2f seconds.",(double)totaltime/1000000.);
128  show_result(buf);
129}
130
131void
132copyplane_test(void)
133{
134  int num_copies = 200;
135  int i;
136  long totaltime;
137  char buf[80];
138
139  if(!X.gcv.plane_mask || (X.gcv.plane_mask & (X.gcv.plane_mask - 1))) {
140    show_result("exactly one bit in plane mask must be set for this test");
141    return;
142  }
143
144
145  num_copies *= X.percent;
146
147  XSetPlaneMask(X.dpy, X.gc, ~0L);
148  XSetFillStyle(X.dpy,X.miscgc,FillTiled);
149  XFillRectangle(X.dpy,X.win,X.miscgc,0,0,400,400);
150
151  XSync(X.dpy,0);
152  timer(StartTimer);
153  for (i=0;i<num_copies;++i)
154    XCopyPlane(X.dpy,X.win,X.win,X.gc,i,200-i,
155	      200,200,200-i,i,X.gcv.plane_mask);
156  XSync(X.dpy,0);
157  totaltime = timer(EndTimer);
158  XSetPlaneMask(X.dpy, X.gc, X.gcv.plane_mask);
159
160  snprintf(buf,sizeof buf,"%.2f seconds.",(double)totaltime/1000000.);
161  show_result(buf);
162}
163
164void
165circle_line_test(int num_vertices, int radius)
166{
167  double theta, delta;
168  int length, centerx, centery, i;
169  int relative_angle;
170  long totaltime;
171  char buf[80];
172  XPoint *coord;
173
174  relative_angle = num_vertices*5/12+1;
175  delta = (double) relative_angle / (double) num_vertices * 2 * PI;
176  centerx = centery = 200;
177
178  coord = (XPoint *) malloc (sizeof(XPoint)*(num_vertices+1));
179
180  length = (int) (2 * radius * (float) atan(delta/2.));
181
182  for (i=0;i<=num_vertices;++i) {
183    theta = (double) i * delta;
184    coord[i].x = centerx + (int) (radius * cos(theta));
185    coord[i].y = centery + (int) (radius * sin(theta));
186  }
187
188  XSync(X.dpy,0);
189  timer(StartTimer);
190  XDrawLines(X.dpy,X.win,X.gc,coord,num_vertices+1,CoordModeOrigin);
191  XSync(X.dpy,0);
192  totaltime = timer(EndTimer);
193
194  snprintf(buf,sizeof buf,"%d lines of length %d in %.3f seconds.",num_vertices,
195	  length,(double)totaltime/1000000.);
196  show_result(buf);
197
198  free(coord);
199}
200
201
202
203void
204polyline_test(void)
205{
206  circle_line_test((int)(601*X.percent),190);
207}
208
209void
210polysegment_test(void)
211{
212  XSegment *segments;
213  int num_segments = 600;
214  long totaltime;
215  char buf[80];
216  int i;
217
218  num_segments *= X.percent;
219
220  segments = (XSegment *) malloc(sizeof(XSegment) * num_segments);
221
222  segments[0].x1 = random()%400; segments[0].y1 = random()%400;
223  segments[0].x2 = random()%400; segments[0].y2 = random()%400;
224
225  for(i=1;i<num_segments;++i) {
226    segments[i].x1 = (segments[i-1].x1-segments[i-1].y2+400+i)%400;
227    segments[i].y1 = (segments[i-1].y1+segments[i-1].x2+i)%400;
228    segments[i].x2 = (segments[i-1].x1-segments[i-1].y1+400+i)%400;
229    segments[i].y2 = (segments[i-1].x2+segments[i-1].y2+i)%400;
230  }
231
232  XSync(X.dpy,0);
233  start_timer();
234  XDrawSegments(X.dpy,X.win,X.gc,segments,num_segments);
235  XSync(X.dpy,0);
236  totaltime = end_timer();
237
238  snprintf(buf,sizeof buf,"%d segments in %.3f seconds.",num_segments,
239	  (double)totaltime/1000000.);
240  show_result(buf);
241
242  free(segments);
243}
244
245void
246polypoint_test(void)
247{
248  XPoint *points;
249  int num_points = 100000;
250  long totaltime;
251  char buf[80];
252  int i;
253
254  num_points *= X.percent;
255
256  points = (XPoint *) malloc(sizeof(XPoint) * num_points);
257
258  points[0].x = random()%400; points[0].y = random()%400;
259  points[1].x = random()%400; points[1].y = random()%400;
260
261  for (i=2;i<num_points;++i) {
262    points[i].x = (points[i-1].x+points[i-2].y+i*3/200)%400;
263    points[i].y = (points[i-1].y+points[i-2].x+i*5/200)%400;
264  }
265
266  XSync(X.dpy,0);
267  start_timer();
268  XDrawPoints(X.dpy,X.win,X.gc,points,num_points,CoordModeOrigin);
269  XSync(X.dpy,0);
270  totaltime = end_timer();
271
272  snprintf(buf,sizeof buf,"%d points in %.3f seconds.",num_points,
273	  (double)totaltime/1000000.);
274  show_result(buf);
275
276  free(points);
277}
278
279void
280genericrectangle_test(Boolean fill)
281{
282  XRectangle *rects;
283  int num_rects = 200;
284  int perimeter = 0, area = 0;
285  int i;
286  long totaltime;
287  char buf[80];
288
289  num_rects *= X.percent;
290
291  rects = (XRectangle *) malloc(sizeof(XRectangle) * num_rects);
292
293  for (i=0;i<num_rects;++i) {
294    rects[i].x = rects[i].y = 200 - i;
295    rects[i].width = rects[i].height = 2 * i;
296    perimeter += rects[i].width * 2 + rects[i].height * 2;
297    area += rects[i].width * rects[i].height;
298  }
299
300  XSync(X.dpy,0);
301  start_timer();
302  if (fill) XFillRectangles(X.dpy,X.win,X.gc,rects,num_rects);
303  else XDrawRectangles(X.dpy,X.win,X.gc,rects,num_rects);
304  XSync(X.dpy,0);
305  totaltime = end_timer();
306
307  if (fill)
308    snprintf(buf,sizeof buf,"%d pixels in %.2f seconds.",area,(double)totaltime/1000000.);
309  else
310    snprintf(buf,sizeof buf,"Total line length %d in %.3f seconds.",perimeter,
311	    (double)totaltime/1000000.);
312  show_result(buf);
313
314  free(rects);
315}
316
317void
318polyrectangle_test(void)
319{
320  genericrectangle_test(FALSE);
321}
322
323void
324polyfillrectangle_test(void)
325{
326  genericrectangle_test(TRUE);
327}
328
329/*****************************/
330
331void
332fillpolygon_test(void)
333{
334  int i;
335  int points_per_side = 40;
336  int spacing;
337  XPoint *points;
338  XPoint polypoints[3];
339
340  points = (XPoint *) malloc (sizeof(XPoint) * points_per_side * 4);
341  spacing = 400 / points_per_side;
342
343  for (i = 0; i < points_per_side; ++i) {
344    points[i].x = i * spacing;
345    points[i].y = 0;
346
347    points[i + points_per_side].x = 400;
348    points[i + points_per_side].y = i * spacing;
349
350    points[i + 2 * points_per_side].x = 400 - i * spacing;
351    points[i + 2 * points_per_side].y = 400;
352
353    points[i + 3 * points_per_side].x = 0;
354    points[i + 3 * points_per_side].y = 400 - i * spacing;
355  }
356
357  for (i = 0; i < 2 * points_per_side; i += 2) {
358    polypoints[0].x = points[i].x;
359    polypoints[0].y = points[i].y;
360
361    polypoints[1].x = points[i + 2 * points_per_side].x;
362    polypoints[1].y = points[i + 2 * points_per_side].y;
363
364    polypoints[2].x = points[i + 2 * points_per_side + 1].x;
365    polypoints[2].y = points[i + 2 * points_per_side + 1].y;
366
367    XFillPolygon (X.dpy, X.win, X.gc, polypoints, 3, Convex, CoordModeOrigin);
368  }
369  free(points);
370}
371
372/*****************************/
373
374void
375genericarc_test(Boolean fill)
376{
377  XArc *arcs;
378  int num_arcs = 180;
379  int i;
380  long totaltime;
381  char buf[80];
382
383  num_arcs *= X.percent;
384
385  arcs = (XArc *) malloc(sizeof(XArc) * num_arcs);
386
387  for (i=0;i<num_arcs;++i) {
388    arcs[i].x = i;
389    arcs[i].y = i;
390    arcs[i].width = i;
391    arcs[i].height = i;
392    arcs[i].angle1 = i * 128;
393    arcs[i].angle2 = i * 128;
394  }
395
396  XSync(X.dpy,0);
397  start_timer();
398  if (fill) XFillArcs(X.dpy,X.win,X.gc,arcs,num_arcs);
399  else XDrawArcs(X.dpy,X.win,X.gc,arcs,num_arcs);
400  XSync(X.dpy,0);
401  totaltime = end_timer();
402
403  snprintf(buf,sizeof buf,"An uncounted number of pixels in %.3f seconds.",
404	  (double)totaltime/1000000.);
405  show_result(buf);
406
407  free(arcs);
408}
409
410void
411polyarc_test(void)
412{
413  genericarc_test(FALSE);
414}
415
416void
417polyfillarc_test(void)
418{
419  genericarc_test(TRUE);
420}
421
422static const char string8[] = "pack my box with five dozen liquor jugs";
423
424void
425polytext8_test(void)
426{
427  int num_strings = 200;
428  int i;
429  long totaltime;
430  char buf[80];
431
432  num_strings *= X.percent;
433
434  XSync(X.dpy,0);
435  start_timer();
436  for (i=0;i<num_strings;++i) {
437    XDrawString(X.dpy,X.win,X.gc,(i%2 ? i : num_strings - i),i,
438		string8,sizeof(string8)-1);
439  }
440  XSync(X.dpy,0);
441  totaltime = end_timer();
442
443  snprintf(buf,sizeof buf,"%d strings in %.2f seconds.",num_strings,
444	  (double) totaltime/1000000.);
445  show_result(buf);
446}
447
448void
449imagetext8_test(void)
450{
451  int num_strings = 200;
452  int i;
453  long totaltime;
454  char buf[80];
455
456  num_strings *= X.percent;
457
458  XSync(X.dpy,0);
459  start_timer();
460  for (i=0;i<num_strings;++i) {
461    XDrawImageString(X.dpy,X.win,X.gc,(i%2 ? i : num_strings - i),i,
462		     string8,sizeof(string8)-1);
463  }
464  XSync(X.dpy,0);
465  totaltime = end_timer();
466
467  snprintf(buf,sizeof buf,"%d strings in %.2f seconds.",num_strings,
468	  (double) totaltime/1000000.);
469  show_result(buf);
470}
471
472static char unicode_font[] =
473  "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1";
474
475static const XChar2b string16[] = {
476  { 0x00, 0x20 }, { 0x00, 0x20 }, { 0x22, 0x2E }, { 0x00, 0x20 },
477  { 0x00, 0x45 }, { 0x22, 0xC5 }, { 0x00, 0x64 }, { 0x00, 0x61 },
478  { 0x00, 0x20 }, { 0x00, 0x3D }, { 0x00, 0x20 }, { 0x00, 0x51 },
479  { 0x00, 0x2C }, { 0x00, 0x20 }, { 0x00, 0x20 }, { 0x00, 0x6E },
480  { 0x00, 0x20 }, { 0x21, 0x92 }, { 0x00, 0x20 }, { 0x22, 0x1E },
481  { 0x00, 0x2C }, { 0x00, 0x20 }, { 0x22, 0x11 }, { 0x00, 0x20 },
482  { 0x00, 0x66 }, { 0x00, 0x28 }, { 0x00, 0x69 }, { 0x00, 0x29 },
483  { 0x00, 0x20 }, { 0x00, 0x3D }, { 0x00, 0x20 }, { 0x22, 0x0F },
484  { 0x00, 0x20 }, { 0x00, 0x67 }, { 0x00, 0x28 }, { 0x00, 0x69 },
485  { 0x00, 0x29 }, { 0x00, 0x2C }, { 0x00, 0x20 }, { 0x22, 0x00 },
486  { 0x00, 0x78 }, { 0x22, 0x08 }, { 0x21, 0x1D }, { 0x00, 0x3A },
487  { 0x00, 0x20 }, { 0x23, 0x08 }, { 0x00, 0x78 }, { 0x23, 0x09 },
488  { 0x00, 0x20 }, { 0x00, 0x3D }, { 0x00, 0x20 }, { 0x22, 0x12 },
489  { 0x23, 0x0A }, { 0x22, 0x12 }, { 0x00, 0x78 }, { 0x23, 0x0B },
490  { 0x00, 0x2C }, { 0x00, 0x20 }, { 0x03, 0xB1 }, { 0x00, 0x20 },
491  { 0x22, 0x27 }, { 0x00, 0x20 }, { 0x00, 0xAC }, { 0x03, 0xB2 },
492  { 0x00, 0x20 }, { 0x00, 0x3D }, { 0x00, 0x20 }, { 0x00, 0xAC },
493  { 0x00, 0x28 }, { 0x00, 0xAC }, { 0x03, 0xB1 }, { 0x00, 0x20 },
494  { 0x22, 0x28 }, { 0x00, 0x20 }, { 0x03, 0xB2 }, { 0x00, 0x29 },
495  { 0x00, 0x2C }
496};
497
498void
499polytext16_test(void)
500{
501  int num_strings = 50;
502  int i;
503  long totaltime;
504  char buf[80];
505
506  num_strings *= X.percent;
507
508  GC_change_font(unicode_font,FALSE);
509
510  XSync(X.dpy,0);
511  start_timer();
512  for (i=0;i<num_strings;++i) {
513    XDrawString16(X.dpy,X.win,X.gc,(i%2 ? i : num_strings - i),10*i,
514		  string16,sizeof(string16)/sizeof(XChar2b));
515  }
516  XSync(X.dpy,0);
517  totaltime = end_timer();
518
519  GC_change_font(X.fontname,FALSE);
520
521  snprintf(buf,sizeof buf,"%d strings in %.2f seconds.",num_strings,
522	  (double) totaltime/1000000.);
523  show_result(buf);
524}
525
526void
527imagetext16_test(void)
528{
529  int num_strings = 50;
530  int i;
531  long totaltime;
532  char buf[80];
533
534  num_strings *= X.percent;
535
536  GC_change_font(unicode_font,FALSE);
537
538  XSync(X.dpy,0);
539  start_timer();
540  for (i=0;i<num_strings;++i) {
541    XDrawImageString16(X.dpy,X.win,X.gc,(i%2 ? i : num_strings - i),10*i,
542		       string16,sizeof(string16)/sizeof(XChar2b));
543  }
544  XSync(X.dpy,0);
545  totaltime = end_timer();
546
547  GC_change_font(X.fontname,FALSE);
548
549  snprintf(buf,sizeof buf,"%d strings in %.2f seconds.",num_strings,
550	  (double) totaltime/1000000.);
551  show_result(buf);
552}
553
554void
555putimage_test(void)
556{
557  int num_copies = 200;
558  int i;
559  long totaltime;
560  char buf[80];
561
562  num_copies *= X.percent;
563
564  XSetFillStyle(X.dpy,X.miscgc,FillTiled);
565  XFillRectangle(X.dpy,X.win,X.miscgc,0,0,400,400);
566
567  X.image = XGetImage(X.dpy,X.win,0,0,200,200,~0,XYPixmap);
568
569  XSync(X.dpy,0);
570  timer(StartTimer);
571  for (i=0;i<num_copies;++i)
572    XPutImage(X.dpy,X.win,X.gc,X.image,0,0,i,i,200,200);
573  XSync(X.dpy,0);
574  totaltime = timer(EndTimer);
575
576  snprintf(buf,sizeof buf,"%.2f seconds.",(double)totaltime/1000000.);
577  show_result(buf);
578}
579
580
581/*****************************/
582/*****************************/
583
584void
585run_test(void)
586{
587  XClearWindow(X.dpy,X.win);
588
589  print_if_recording("run\n");
590
591  switch (X.test) {
592    case CopyArea:      copyarea_test();           break;
593    case CopyPlane:     copyplane_test();          break;
594    case PolyPoint:     polypoint_test();          break;
595    case PolyLine:      polyline_test();           break;
596    case PolySegment:   polysegment_test();        break;
597    case PolyRectangle: polyrectangle_test();      break;
598    case PolyArc:       polyarc_test();            break;
599    case FillPolygon:   fillpolygon_test();        break;
600    case PolyFillRect:  polyfillrectangle_test();  break;
601    case PolyFillArc:   polyfillarc_test();        break;
602    case PolyText8:     polytext8_test();          break;
603    case ImageText8:    imagetext8_test();         break;
604    case PolyText16:    polytext16_test();         break;
605    case ImageText16:   imagetext16_test();        break;
606    case PutImage:      putimage_test();           break;
607    default: fprintf(stderr,"That test doesn't exist yet.\n");
608    }
609}
610
611/*****************************/
612
613/* set_text(w,string)
614** ------------------
615** Sets the text in a read-only text widget to the specified string.
616*/
617
618void
619set_text(Widget w, char *string)
620{
621  static Arg args[2];
622
623  XtSetArg(args[0], XtNstring, string);
624  XtSetArg(args[1], XtNlength, strlen(string));
625  XtSetValues(w, args, (Cardinal) 2 );
626}
627
628void
629show_result(char *string)
630{
631  char buf[80];
632
633  set_text(result,string);
634
635  strcpy(buf,"# ");
636  strncat(buf,string,sizeof(buf) - 3);
637  buf[sizeof(buf) - 3] = '\0';
638  strcat(buf,"\n");
639  print_if_recording(buf);
640}
641