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