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