1 // Copyright (C)2004 Landmark Graphics Corporation
2 // Copyright (C)2005 Sun Microsystems, Inc.
3 // Copyright (C)2011, 2014, 2017-2020 D. R. Commander
4 //
5 // This library is free software and may be redistributed and/or modified under
6 // the terms of the wxWindows Library License, Version 3.1 or (at your option)
7 // any later version. The full license is in the LICENSE.txt file included
8 // with this distribution.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // wxWindows Library License for more details.
14
15 #include "Thread.h"
16 #include "Frame.h"
17 #include "../client/GLFrame.h"
18 #include "vglutil.h"
19 #include "Timer.h"
20 #include "bmp.h"
21 #include "vgllogo.h"
22 #ifdef USEHELGRIND
23 #include <valgrind/helgrind.h>
24 #endif
25
26 using namespace vglutil;
27 using namespace vglcommon;
28
29 #define ITER 50
30 #define NFRAMES 2
31 #define MINW 1
32 #define MAXW 400
33 #define BORDER 0
34 #define NUMWIN 1
35
36 bool useGL = false, useXV = false, doRgbBench = false, useRGB = false,
37 addLogo = false, anaglyph = false, check = false;
38
39
resizeWindow(Display * dpy,Window win,int width,int height,int myID)40 void resizeWindow(Display *dpy, Window win, int width, int height, int myID)
41 {
42 XWindowAttributes xwa;
43 XGetWindowAttributes(dpy, win, &xwa);
44 if(width != xwa.width || height != xwa.height)
45 {
46 XLockDisplay(dpy);
47 XWindowChanges xwc;
48 xwc.x = (width + BORDER * 2) * myID; xwc.y = 0;
49 xwc.width = width; xwc.height = height;
50 XConfigureWindow(dpy, win, CWWidth | CWHeight | CWX | CWY, &xwc);
51 XFlush(dpy);
52 XSync(dpy, False);
53 XUnlockDisplay(dpy);
54 }
55 }
56
57
58 class Blitter : public Runnable
59 {
60 public:
61
Blitter(Display * dpy_,Window win_,int myID_)62 Blitter(Display *dpy_, Window win_, int myID_) : findex(0), deadYet(false),
63 dpy(dpy_), win(win_), thread(NULL), myID(myID_)
64 {
65 for(int i = 0; i < NFRAMES; i++)
66 {
67 if(useGL) { frames[i] = new GLFrame(dpy, win); }
68 #ifdef USEXV
69 else if(useXV) { frames[i] = new XVFrame(dpy, win); }
70 #endif
71 else { frames[i] = new FBXFrame(dpy, win); }
72 }
73 thread = new Thread(this);
74 thread->start();
75 #ifdef USEHELGRIND
76 ANNOTATE_BENIGN_RACE_SIZED(&deadYet, sizeof(bool), );
77 #endif
78 }
79
~Blitter(void)80 virtual ~Blitter(void)
81 {
82 shutdown();
83 for(int i = 0; i < NFRAMES; i++)
84 {
85 if(frames[i])
86 {
87 if(frames[i]->isGL) delete (GLFrame *)frames[i];
88 #ifdef USEXV
89 else if(frames[i]->isXV) delete (XVFrame *)frames[i];
90 #endif
91 else delete (FBXFrame *)frames[i];
92 frames[i] = NULL;
93 }
94 }
95 }
96
get(void)97 Frame *get(void)
98 {
99 Frame *frame = frames[findex];
100 findex = (findex + 1) % NFRAMES;
101 if(thread) thread->checkError();
102 if(!deadYet) frame->waitUntilComplete();
103 if(thread) thread->checkError();
104 return frame;
105 }
106
put(Frame * frame)107 void put(Frame *frame)
108 {
109 if(thread) thread->checkError();
110 frame->signalReady();
111 }
112
shutdown(void)113 void shutdown(void)
114 {
115 deadYet = true;
116 int i;
117 for(i = 0; i < NFRAMES; i++)
118 frames[i]->signalReady(); // Release my thread
119 if(thread)
120 {
121 thread->stop(); delete thread; thread = NULL;
122 }
123 for(i = 0; i < NFRAMES; i++)
124 frames[i]->signalComplete(); // Release Decompressor
125 }
126
127 private:
128
run(void)129 void run(void)
130 {
131 Timer timer;
132 double mpixels = 0., totalTime = 0.;
133 int index = 0; Frame *frame;
134 try
135 {
136 while(!deadYet)
137 {
138 frame = frames[index];
139 index = (index + 1) % NFRAMES;
140 frame->waitUntilReady(); if(deadYet) break;
141 if(useXV)
142 resizeWindow(dpy, win, frame->hdr.width, frame->hdr.height, myID);
143 timer.start();
144 if(frame->isGL) ((GLFrame *)frame)->redraw();
145 #ifdef USEXV
146 else if(frame->isXV) ((XVFrame *)frame)->redraw();
147 #endif
148 else ((FBXFrame *)frame)->redraw();
149 mpixels += (double)(frame->hdr.width * frame->hdr.height) / 1000000.;
150 totalTime += timer.elapsed();
151 if(check && !checkFrame(frame))
152 THROW("Pixel data is bogus");
153 frame->signalComplete();
154 }
155 fprintf(stderr, "Average Blitter performance = %f Mpixels/sec%s\n",
156 mpixels / totalTime, check ? " [PASSED]" : "");
157 }
158 catch(std::exception &e)
159 {
160 if(thread) thread->setError(e);
161 for(int i = 0; i < NFRAMES; i++)
162 if(frames[i]) frames[i]->signalComplete();
163 throw;
164 }
165 fprintf(stderr, "Blitter exiting ...\n");
166 }
167
checkFrame(Frame * frame)168 bool checkFrame(Frame *frame)
169 {
170 int i, j, _j, pitch = frame->pitch, seed = frame->hdr.winid;
171 unsigned char *ptr = frame->bits, *pixel;
172 PF *pf = pf_get(frame->hdr.dpynum);
173 int maxRGB = (1 << pf->bpc);
174
175 for(_j = 0; _j < frame->hdr.height; _j++, ptr += pitch)
176 {
177 j = frame->flags & FRAME_BOTTOMUP ? frame->hdr.height - _j - 1 : _j;
178 for(i = 0, pixel = ptr; i < frame->hdr.width;
179 i++, pixel += frame->pf->size)
180 {
181 int r, g, b;
182 frame->pf->getRGB(pixel, &r, &g, &b);
183 if(frame->pf->bpc == 10 && pf->bpc != 10)
184 {
185 r >>= 2; g >>= 2; b >>= 2;
186 }
187 if(addLogo && !useXV)
188 {
189 int lw = min(VGLLOGO_WIDTH, frame->hdr.width - 1);
190 int lh = min(VGLLOGO_HEIGHT, frame->hdr.height - 1);
191 int li = i - (frame->hdr.width - lw - 1);
192 int lj = j - (frame->hdr.height - lh - 1);
193 if(lw > 0 && lh > 0 && li >= 0 && lj >= 0 && li < lw && lj < lh
194 && vgllogo[lj * VGLLOGO_WIDTH + li])
195 {
196 r ^= 113; g ^= 162; b ^= 117;
197 }
198 }
199 if(r != (i + seed) % maxRGB || g != (j + seed) % maxRGB
200 || b != (i + j + seed) % maxRGB)
201 return false;
202 }
203 }
204
205 return true;
206 }
207
208 int findex; bool deadYet;
209 Frame *frames[NFRAMES];
210 Display *dpy; Window win;
211 Thread *thread;
212 int myID;
213 };
214
215
216 class Decompressor : public Runnable
217 {
218 public:
219
Decompressor(Blitter * blitter_,Display * dpy_,Window win_,int myID_)220 Decompressor(Blitter *blitter_, Display *dpy_, Window win_, int myID_) :
221 blitter(blitter_), findex(0), deadYet(false), dpy(dpy_), win(win_),
222 myID(myID_), thread(NULL)
223 {
224 thread = new Thread(this);
225 thread->start();
226 #ifdef USEHELGRIND
227 ANNOTATE_BENIGN_RACE_SIZED(&deadYet, sizeof(bool), );
228 #endif
229 }
230
~Decompressor(void)231 virtual ~Decompressor(void) { shutdown(); }
232
get(void)233 CompressedFrame &get(void)
234 {
235 CompressedFrame &cframe = cframes[findex];
236 findex = (findex + 1) % NFRAMES;
237 if(deadYet) return cframe;
238 if(thread) thread->checkError();
239 if(!deadYet) cframe.waitUntilComplete();
240 if(thread) thread->checkError();
241 return cframe;
242 }
243
put(CompressedFrame & cframe)244 void put(CompressedFrame &cframe)
245 {
246 if(thread) thread->checkError();
247 cframe.signalReady();
248 }
249
shutdown(void)250 void shutdown(void)
251 {
252 deadYet = true;
253 int i;
254 for(i = 0; i < NFRAMES; i++)
255 cframes[i].signalReady(); // Release my thread
256 if(thread)
257 {
258 thread->stop(); delete thread; thread = NULL;
259 }
260 for(i = 0; i < NFRAMES; i++)
261 cframes[i].signalComplete(); // Release compressor
262 }
263
264 private:
265
run(void)266 void run(void)
267 {
268 int index = 0; Frame *frame = NULL;
269 try
270 {
271 while(!deadYet)
272 {
273 CompressedFrame &cframe = cframes[index];
274 index = (index + 1) % NFRAMES;
275 cframe.waitUntilReady(); if(deadYet) break;
276 frame = blitter->get(); if(deadYet) break;
277 resizeWindow(dpy, win, cframe.hdr.width, cframe.hdr.height, myID);
278 if(frame->isGL) *((GLFrame *)frame) = cframe;
279 #ifdef USEXV
280 else if(frame->isXV) *((XVFrame *)frame) = cframe;
281 #endif
282 else *((FBXFrame *)frame) = cframe;
283 blitter->put(frame);
284 cframe.signalComplete();
285 }
286 }
287 catch(std::exception &e)
288 {
289 if(thread) thread->setError(e);
290 for(int i = 0; i < NFRAMES; i++) cframes[i].signalComplete();
291 throw;
292 }
293 fprintf(stderr, "Decompressor exiting ...\n");
294 }
295
296 Blitter *blitter;
297 int findex; bool deadYet;
298 Display *dpy; Window win;
299 CompressedFrame cframes[NFRAMES];
300 int myID; Thread *thread;
301 };
302
303
304 class Compressor : public Runnable
305 {
306 public:
307
Compressor(Decompressor * decompressor_,Blitter * blitter_)308 Compressor(Decompressor *decompressor_, Blitter *blitter_) : findex(0),
309 deadYet(false), thread(NULL), decompressor(decompressor_)
310 #ifdef USEXV
311 , blitter(blitter_)
312 #endif
313 {
314 thread = new Thread(this);
315 thread->start();
316 #ifdef USEHELGRIND
317 ANNOTATE_BENIGN_RACE_SIZED(&deadYet, sizeof(bool), );
318 #endif
319 }
320
~Compressor(void)321 virtual ~Compressor(void)
322 {
323 if(thread) thread->stop();
324 }
325
get(int width,int height,int pixelFormat)326 Frame &get(int width, int height, int pixelFormat)
327 {
328 Frame &frame = frames[findex];
329 findex = (findex + 1) % NFRAMES;
330 if(thread) thread->checkError();
331 if(!deadYet) frame.waitUntilComplete();
332 if(thread) thread->checkError();
333 rrframeheader hdr;
334 memset(&hdr, 0, sizeof(rrframeheader));
335 hdr.framew = hdr.width = width + BORDER;
336 hdr.frameh = hdr.height = height + BORDER;
337 hdr.x = hdr.y = BORDER;
338 hdr.qual = 80;
339 hdr.subsamp = 2;
340 hdr.compress = useRGB ? RRCOMP_RGB : RRCOMP_JPEG;
341 if(useXV) hdr.compress = RRCOMP_YUV;
342 frame.init(hdr, pixelFormat, 0);
343 return frame;
344 }
345
put(Frame & frame)346 void put(Frame &frame)
347 {
348 if(thread) thread->checkError();
349 frame.signalReady();
350 }
351
shutdown(void)352 void shutdown(void)
353 {
354 deadYet = true;
355 int i;
356 for(i = 0; i < NFRAMES; i++)
357 frames[i].signalReady(); // Release my thread
358 if(thread)
359 {
360 thread->stop(); delete thread; thread = NULL;
361 }
362 for(i = 0; i < NFRAMES; i++)
363 frames[i].signalComplete(); // Release main thread
364 }
365
366 private:
367
run(void)368 void run(void)
369 {
370 int index = 0;
371 try
372 {
373 while(!deadYet)
374 {
375 Frame &frame = frames[index];
376 index = (index + 1) % NFRAMES;
377 frame.waitUntilReady(); if(deadYet) break;
378 #ifdef USEXV
379 if(useXV)
380 {
381 XVFrame *xvframe = (XVFrame *)blitter->get(); if(deadYet) break;
382 *xvframe = frame;
383 blitter->put(xvframe);
384 }
385 else
386 #endif
387 {
388 CompressedFrame &cframe = decompressor->get(); if(deadYet) break;
389 cframe = frame;
390 decompressor->put(cframe);
391 }
392 frame.signalComplete();
393 }
394 }
395 catch(std::exception &e)
396 {
397 if(thread) thread->setError(e);
398 for(int i = 0; i < NFRAMES; i++) frames[i].signalComplete();
399 throw;
400 }
401 fprintf(stderr, "Compressor exiting ...\n");
402 }
403
404 int findex; bool deadYet;
405 Thread *thread;
406 Frame frames[NFRAMES];
407 Decompressor *decompressor;
408 #ifdef USEXV
409 Blitter *blitter;
410 #endif
411 };
412
413
414 class FrameTest
415 {
416 public:
417
FrameTest(Display * dpy_,int myID_)418 FrameTest(Display *dpy_, int myID_) : dpy(dpy_), compressor(NULL),
419 decompressor(NULL), blitter(NULL), myID(myID_)
420 {
421 ERRIFNOT(win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy),
422 myID * (MINW + BORDER * 2), 0, MINW + BORDER, MINW + BORDER, 0,
423 WhitePixel(dpy, DefaultScreen(dpy)),
424 BlackPixel(dpy, DefaultScreen(dpy))));
425 ERRIFNOT(XMapRaised(dpy, win));
426
427 blitter = new Blitter(dpy, win, myID);
428 if(!useXV)
429 decompressor = new Decompressor(blitter, dpy, win, myID);
430 compressor = new Compressor(decompressor, blitter);
431 }
432
~FrameTest(void)433 ~FrameTest(void) { shutdown(); XDestroyWindow(dpy, win); }
434
dotest(int width,int height,int seed,PF * pf)435 void dotest(int width, int height, int seed, PF *pf)
436 {
437 if(pf->bpc == 8)
438 {
439 Frame &frame = compressor->get(width, height, pf->id);
440 if(anaglyph) makeAnaglyph(frame, seed);
441 else initFrame(frame, seed);
442 // This unit test doesn't use winid, so use it to track the seed.
443 frame.hdr.winid = seed;
444 // This unit test doesn't use dpynum, so use it to track the source
445 // pixel format.
446 frame.hdr.dpynum = pf->id;
447 if(addLogo) frame.addLogo();
448 compressor->put(frame);
449 }
450 else
451 {
452 FBXFrame *frame = (FBXFrame *)blitter->get();
453 rrframeheader hdr;
454 memset(&hdr, 0, sizeof(rrframeheader));
455 hdr.width = hdr.framew = width;
456 hdr.height = hdr.frameh = height;
457 frame->init(hdr);
458 if(anaglyph) makeAnaglyph(*frame, seed);
459 else initFrame(*frame, seed);
460 // This unit test doesn't use winid, so use it to track the seed.
461 frame->hdr.winid = seed;
462 // This unit test doesn't use dpynum, so use it to track the source
463 // pixel format.
464 frame->hdr.dpynum = pf->id;
465 if(addLogo) frame->addLogo();
466 resizeWindow(dpy, win, width, height, myID);
467 blitter->put(frame);
468 }
469 }
470
471 private:
472
initFrame(Frame & frame,int seed)473 void initFrame(Frame &frame, int seed)
474 {
475 int i, j, pitch = frame.pitch;
476 unsigned char *ptr = frame.bits, *pixel;
477 int maxRGB = (1 << frame.pf->bpc);
478
479 for(j = 0; j < frame.hdr.height; j++, ptr += pitch)
480 {
481 for(i = 0, pixel = ptr; i < frame.hdr.width;
482 i++, pixel += frame.pf->size)
483 frame.pf->setRGB(pixel, (i + seed) % maxRGB, (j + seed) % maxRGB,
484 (i + j + seed) % maxRGB);
485 }
486 }
487
makeAnaglyph(Frame & frame,int seed)488 void makeAnaglyph(Frame &frame, int seed)
489 {
490 Frame rFrame, gFrame, bFrame;
491 int i, j;
492 unsigned char *ptr;
493
494 rFrame.init(frame.hdr, PF_COMP, frame.flags, false);
495 for(j = 0, ptr = rFrame.bits; j < frame.hdr.height;
496 j++, ptr += rFrame.pitch)
497 {
498 for(i = 0; i < frame.hdr.width; i++) ptr[i] = (i + seed) % 256;
499 }
500 gFrame.init(frame.hdr, PF_COMP, frame.flags, false);
501 for(j = 0, ptr = gFrame.bits; j < frame.hdr.height;
502 j++, ptr += gFrame.pitch)
503 {
504 memset(ptr, (j + seed) % 256, frame.hdr.width);
505 }
506 bFrame.init(frame.hdr, PF_COMP, frame.flags, false);
507 for(j = 0, ptr = bFrame.bits; j < frame.hdr.height;
508 j++, ptr += bFrame.pitch)
509 {
510 for(i = 0; i < frame.hdr.width; i++) ptr[i] = (i + j + seed) % 256;
511 }
512
513 frame.makeAnaglyph(rFrame, gFrame, bFrame);
514 }
515
shutdown(void)516 void shutdown(void)
517 {
518 fprintf(stderr, "Shutting down....\n"); fflush(stderr);
519 if(compressor) compressor->shutdown();
520 if(decompressor) decompressor->shutdown();
521 if(blitter) blitter->shutdown();
522 delete compressor; compressor = NULL;
523 delete decompressor; decompressor = NULL;
524 delete blitter; blitter = NULL;
525 }
526
527 Display *dpy; Window win;
528 Compressor *compressor; Decompressor *decompressor; Blitter *blitter;
529 int myID;
530 };
531
532
cmpFrame(unsigned char * buf,int width,int height,Frame & dst)533 int cmpFrame(unsigned char *buf, int width, int height, Frame &dst)
534 {
535 int _i; int pitch = width * 3;
536 bool dstbu = (dst.flags & FRAME_BOTTOMUP);
537 for(int i = 0; i < height; i++)
538 {
539 _i = dstbu ? i : height - i - 1;
540 for(int j = 0; j < height; j++)
541 {
542 int r, g, b;
543 dst.pf->getRGB(&dst.bits[dst.pitch * i + j * dst.pf->size], &r, &g, &b);
544 if(dst.pf->bpc == 10)
545 {
546 r >>= 2; g >>= 2; b >>= 2;
547 }
548 if(r != buf[pitch * _i + j * 3] || g != buf[pitch * _i + j * 3 + 1]
549 || b != buf[pitch * _i + j * 3 + 2])
550 return 1;
551 }
552 }
553 return 0;
554 }
555
556
rgbBench(char * filename)557 void rgbBench(char *filename)
558 {
559 unsigned char *buf; int width, height, dstbu;
560 CompressedFrame src; Frame dst; int dstformat;
561
562 for(dstformat = 0; dstformat < PIXELFORMATS - 1; dstformat++)
563 {
564 PF *dstpf = pf_get(dstformat);
565 for(dstbu = 0; dstbu < 2; dstbu++)
566 {
567 if(bmp_load(filename, &buf, &width, 1, &height, PF_RGB,
568 BMPORN_BOTTOMUP) == -1)
569 THROW(bmp_geterr());
570 rrframeheader hdr;
571 memset(&hdr, 0, sizeof(hdr));
572 hdr.width = hdr.framew = width;
573 hdr.height = hdr.frameh = height;
574 hdr.compress = RRCOMP_RGB; hdr.size = width * 3 * height;
575 src.init(hdr, hdr.flags);
576 memcpy(src.bits, buf, width * 3 * height);
577 dst.init(hdr, dstpf->id, dstbu ? FRAME_BOTTOMUP : 0);
578 memset(dst.bits, 0, dst.pitch * dst.hdr.frameh);
579 fprintf(stderr, "RGB (BOTTOM-UP) -> %s (%s)\n", dstpf->name,
580 dstbu ? "BOTTOM-UP" : "TOP-DOWN");
581 double tStart, tTotal = 0.; int iter = 0;
582 do
583 {
584 tStart = GetTime();
585 dst.decompressRGB(src, width, height, false);
586 tTotal += GetTime() - tStart; iter++;
587 } while(tTotal < 1.);
588 fprintf(stderr, "%f Mpixels/sec - ", (double)width * (double)height *
589 (double)iter / 1000000. / tTotal);
590 if(cmpFrame(buf, width, height, dst))
591 fprintf(stderr, "FAILED!\n");
592 else fprintf(stderr, "Passed.\n");
593 free(buf);
594 }
595 fprintf(stderr, "\n");
596 }
597 }
598
599
usage(char ** argv)600 void usage(char **argv)
601 {
602 fprintf(stderr, "\nUSAGE: %s [options]\n\n", argv[0]);
603 fprintf(stderr, "Options:\n");
604 fprintf(stderr, "-gl = Use OpenGL instead of X11 for blitting\n");
605 fprintf(stderr, "-xv = Test X Video encoding/display\n");
606 fprintf(stderr, "-rgb = Use RGB encoding instead of JPEG compression\n");
607 fprintf(stderr, "-logo = Add VirtualGL logo\n");
608 fprintf(stderr, "-anaglyph = Test anaglyph creation\n");
609 fprintf(stderr, "-rgbbench <filename> = Benchmark the decoding of RGB-encoded frames.\n");
610 fprintf(stderr, " <filename> should be a BMP or PPM file.\n");
611 fprintf(stderr, "-v = Verbose output (may affect benchmark results)\n");
612 fprintf(stderr, "-check = Check correctness of pixel paths (implies -rgb)\n\n");
613 exit(1);
614 }
615
616
main(int argc,char ** argv)617 int main(int argc, char **argv)
618 {
619 Display *dpy = NULL;
620 FrameTest *test[NUMWIN];
621 int i, j, w, h;
622 char *fileName = NULL;
623 bool verbose = false;
624
625 if(argc > 1) for(i = 1; i < argc; i++)
626 {
627 if(!stricmp(argv[i], "-h") || !strcmp(argv[i], "-?")) usage(argv);
628 else if(!stricmp(argv[i], "-gl"))
629 {
630 fprintf(stderr, "Using OpenGL for blitting ...\n");
631 useGL = true;
632 }
633 else if(!stricmp(argv[i], "-logo")) addLogo = true;
634 else if(!stricmp(argv[i], "-anaglyph")) anaglyph = true;
635 #ifdef USEXV
636 else if(!stricmp(argv[i], "-xv"))
637 {
638 fprintf(stderr, "Using X Video ...\n");
639 useXV = true;
640 }
641 #endif
642 else if(!stricmp(argv[i], "-rgb"))
643 {
644 fprintf(stderr, "Using RGB encoding ...\n");
645 useRGB = true;
646 }
647 else if(!stricmp(argv[i], "-rgbbench") && i < argc - 1)
648 {
649 fileName = argv[++i]; doRgbBench = true;
650 }
651 else if(!stricmp(argv[i], "-v")) verbose = true;
652 else if(!stricmp(argv[i], "-check")) { check = true; useRGB = true; }
653 else usage(argv);
654 }
655
656 try
657 {
658 if(doRgbBench) { rgbBench(fileName); exit(0); }
659
660 ERRIFNOT(XInitThreads());
661 if(!(dpy = XOpenDisplay(0)))
662 {
663 fprintf(stderr, "Could not open display %s\n", XDisplayName(0));
664 exit(1);
665 }
666
667 for(int format = 0; format < PIXELFORMATS - 1; format++)
668 {
669 PF *pf = pf_get(format);
670
671 if((useXV || anaglyph || useGL) && pf->bpc != 8) continue;
672 if(DefaultDepth(dpy, DefaultScreen(dpy)) != 30 && pf->bpc == 10)
673 continue;
674
675 fprintf(stderr, "Pixel format: %s\n", pf->name);
676
677 for(i = 0; i < NUMWIN; i++)
678 {
679 test[i] = new FrameTest(dpy, i);
680 }
681
682 for(w = MINW; w <= MAXW; w += 33)
683 {
684 h = 1;
685 if(verbose) fprintf(stderr, "%.4d x %.4d: ", w, h);
686 for(i = 0; i < ITER; i++)
687 {
688 if(verbose) fprintf(stderr, ".");
689 for(j = 0; j < NUMWIN; j++) test[j]->dotest(w, h, i, pf);
690 }
691 if(verbose) fprintf(stderr, "\n");
692 }
693
694 for(h = MINW; h <= MAXW; h += 33)
695 {
696 w = 1;
697 if(verbose) fprintf(stderr, "%.4d x %.4d: ", w, h);
698 for(i = 0; i < ITER; i++)
699 {
700 if(verbose) fprintf(stderr, ".");
701 for(j = 0; j < NUMWIN; j++) test[j]->dotest(w, h, i, pf);
702 }
703 if(verbose) fprintf(stderr, "\n");
704 }
705
706 for(w = MINW; w <= MAXW; w += 33)
707 {
708 h = w;
709 if(verbose) fprintf(stderr, "%.4d x %.4d: ", w, h);
710 for(i = 0; i < ITER; i++)
711 {
712 if(verbose) fprintf(stderr, ".");
713 for(j = 0; j < NUMWIN; j++) test[j]->dotest(w, h, i, pf);
714 }
715 if(verbose) fprintf(stderr, "\n");
716 }
717
718 for(i = 0; i < NUMWIN; i++)
719 {
720 delete test[i];
721 }
722 fprintf(stderr, "\n");
723 }
724 }
725 catch(std::exception &e)
726 {
727 fprintf(stderr, "%s\n%s\n", GET_METHOD(e), e.what());
728 if(dpy) XCloseDisplay(dpy);
729 exit(1);
730 }
731 if(dpy) XCloseDisplay(dpy);
732 return 0;
733 }
734