1
2 #include <X11/Xlib.h>
3 #include <X11/Xos.h>
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <string.h>
7
8 class XMoveChecker {
9 public:
10 XMoveChecker( unsigned bsize, unsigned avgmove );
11 virtual ~XMoveChecker();
12 virtual void RollBall() = 0;
13 double loop( unsigned long secs );
14
15 protected:
16 Display *dpy;
17 int scr;
18 Window win;
19
20 unsigned bsize; // Ball-Size
21 unsigned avgmove; // durchschnittssprung
22 unsigned dhelp;
23 };
24
25 // ==========================================================================
26
XMoveChecker(unsigned bsize_in,unsigned avg)27 XMoveChecker::XMoveChecker( unsigned bsize_in, unsigned avg )
28 : bsize(bsize_in), avgmove(avg)
29 {
30 XSetWindowAttributes setwinattr;
31
32 dpy = XOpenDisplay( "" );
33 scr = DefaultScreen( dpy );
34
35 if (avgmove>bsize-1) avgmove=bsize-1;
36 dhelp = 2*bsize-1;
37
38 win = XCreateSimpleWindow( dpy, RootWindow( dpy, scr ), 0, 0, dhelp, dhelp,
39 0, BlackPixel( dpy,scr ), WhitePixel( dpy,scr ) );
40 setwinattr.override_redirect = True;
41 XChangeWindowAttributes( dpy, win, CWOverrideRedirect, &setwinattr );
42
43 // map window and wait for it to be mapped.
44 XEvent event;
45 XSelectInput( dpy, win, ExposureMask );
46 XMapRaised( dpy, win );
47 XNextEvent( dpy, &event );
48 }
49
~XMoveChecker()50 XMoveChecker::~XMoveChecker() {
51 XDestroyWindow( dpy, win );
52 XCloseDisplay( dpy );
53 }
54
loop(unsigned long secs)55 double XMoveChecker::loop( unsigned long secs ) {
56 struct timeval start;
57 struct timeval current;
58 struct timeval diff;
59 long count=-1; // Vorlauf
60
61 if (secs<=5) {
62 XGrabServer(dpy);
63 XSync(dpy,0);
64 }
65
66 do {
67 for (int i=0;i<16;i++) RollBall();
68 XSync( dpy, 0 );
69 if (count++<0) gettimeofday( &start, NULL );
70 gettimeofday( ¤t, NULL );
71 diff.tv_sec = current.tv_sec - start.tv_sec;
72 if ( current.tv_usec >= start.tv_usec ) {
73 diff.tv_usec = current.tv_usec - start.tv_usec;
74 }
75 else {
76 diff.tv_usec = 1000000L + current.tv_usec - start.tv_usec;
77 diff.tv_sec--;
78 }
79 } while( diff.tv_sec < secs );
80
81 if (secs<=5) {
82 XUngrabServer(dpy);
83 }
84
85 return ( (double)count / ((double)diff.tv_sec + diff.tv_usec/1000000.0)*(double)secs );
86 }
87
88 // ==========================================================================
89
90
91 class XMoveChecker1 : public XMoveChecker {
92 public:
93 XMoveChecker1( unsigned bsize, unsigned avg );
94 virtual ~XMoveChecker1();
95 virtual void RollBall();
96
97 protected:
98 Pixmap help; // Doublebuffer: Depth 8 (2*bsize-1)
99 Pixmap bpix; // Ball-Bitmap: Depth 1 bsize
100 Pixmap spix; // Shadow-Bitmap: Depth 1 bsize
101 Pixmap rpix; // Ring-Bitmap: Depth 1 bsize
102 GC gc_bclear; // reset help-pixmap
103 GC gc_ballwhite; // create white ball
104 GC gc_lay2; // add shades to ball
105 GC gc_ball; // add colored rings
106 GC gc_bxor; // copy help pixmap to screen
107 GC gc_bit; // initialize bitmaps
108 };
109
XMoveChecker1(unsigned bsize_in,unsigned avg)110 XMoveChecker1::XMoveChecker1( unsigned bsize_in, unsigned avg )
111 : XMoveChecker( bsize_in, avg )
112 {
113 help = XCreatePixmap(dpy,win,dhelp,dhelp,DefaultDepth(dpy,scr));
114
115 bpix = XCreatePixmap(dpy,win,bsize,bsize,1);
116 spix = XCreatePixmap(dpy,win,bsize,bsize,1);
117 rpix = XCreatePixmap(dpy,win,bsize,bsize,1);
118
119 gc_bit = XCreateGC( dpy, bpix, 0, 0 );
120 XFillRectangle( dpy, bpix, gc_bit, 0, 0, bsize, bsize );
121 XFillRectangle( dpy, spix, gc_bit, 0, 0, bsize, bsize );
122 XFillRectangle( dpy, rpix, gc_bit, 0, 0, bsize, bsize );
123
124 //
125 // ball_mask: 0x03
126 // shade_mask: 0x04
127 //
128 unsigned long value_mask;
129 XGCValues values;
130
131 value_mask = GCPlaneMask | GCForeground | GCBackground | GCFunction
132 | GCGraphicsExposures;
133
134 values.graphics_exposures = False;
135 values.fill_style = FillSolid;
136 values.background = 0;
137
138 values.foreground = 0x00;
139 values.plane_mask = 0x07; // Arbeiten in lay2
140 values.function = GXclear;
141 gc_bclear = XCreateGC( dpy, win, value_mask, &values );
142 values.function = GXxor;
143 gc_bxor = XCreateGC( dpy, win, value_mask, &values );
144
145 values.function = GXxor;
146 values.foreground = 0x04;
147 values.plane_mask = 0x04;
148 gc_lay2 = XCreateGC( dpy, win, value_mask, &values );
149
150 values.function = GXxor;
151 values.foreground = 0x01;
152 values.plane_mask = 0x03;
153 gc_ballwhite = XCreateGC( dpy, win, value_mask, &values );
154 values.foreground = 0x03;
155 gc_ball = XCreateGC( dpy, win, value_mask, &values );
156 }
157
~XMoveChecker1()158 XMoveChecker1::~XMoveChecker1() {
159 XFreeGC( dpy, gc_ball );
160 XFreeGC( dpy, gc_ballwhite );
161 XFreeGC( dpy, gc_lay2 );
162 XFreeGC( dpy, gc_bxor );
163 XFreeGC( dpy, gc_bclear );
164 XFreePixmap( dpy, help );
165 XFreePixmap( dpy, bpix );
166 XFreePixmap( dpy, spix );
167 XFreePixmap( dpy, rpix );
168 }
169
170 // XMoveChecker1: simulates the original algorithm that consists of
171 // - clearing the double buffer pixmap of depth 8
172 // - copying old ball, constisting of 3 layers of depth 1
173 // - copying new ball, consisting of 3 layers of depth 1
174 // - copying the double buffer to the screen
175 // - 8 X-calls
176
RollBall()177 void XMoveChecker1::RollBall() {
178
179 int d = bsize;
180 int dx = avgmove;
181 int dy = avgmove;
182
183 int absx = (dx>0)?dx:-dx;
184 int absy = (dy>0)?dy:-dy;
185
186 int width = d+absx; // tats�chlicher Ausschnittgr��e der Pixmap
187 int height= d+absy;
188 int ox = (dx>0)?0:absx; // relativer Abstand alte Position
189 int oy = (dy>0)?0:absy;
190 int nx = (dx>0)?absx:0; // relativer Abstand neue Position
191 int ny = (dy>0)?absy:0;
192
193 XFillRectangle(dpy,help,gc_bclear,0,0,width,height);
194
195 XCopyPlane(dpy,bpix,help,gc_ballwhite,0,0,d,d,ox,oy,1);
196 XCopyPlane(dpy,spix,help,gc_lay2,0,0,d,d,ox,oy,1);
197 XCopyPlane(dpy,rpix,help,gc_ball,0,0,d,d,ox,oy,1);
198
199 XCopyPlane(dpy,bpix,help,gc_ballwhite,0,0,d,d,nx,ny,1);
200 XCopyPlane(dpy,spix,help,gc_lay2,0,0,d,d,nx,ny,1);
201 XCopyPlane(dpy,rpix,help,gc_ball,0,0,d,d,nx,ny,1);
202
203 XCopyArea(dpy,help,win,gc_bxor,0,0,width,height,0,0 );
204 }
205
206 // ==========================================================================
207
208 class XMoveChecker2 : public XMoveChecker {
209 public:
210 XMoveChecker2( unsigned bsize, unsigned avg );
211 virtual ~XMoveChecker2();
212 virtual void RollBall();
213
214 protected:
215 Pixmap help; // Doublebuffer: Depth 8 (2*bsize-1)
216 Pixmap bpix; // Ball/Shade-Bitmap: Depth 8 bsize
217 Pixmap rpix; // Ring-Bitmap: Depth 1 bsize
218 GC gc_bcopy; // preset help-pixmap
219 GC gc_ball; // add colored rings
220 GC gc_bxor; // copy help pixmap to screen
221 GC gc_bit; // initialize bitmaps
222 };
223
XMoveChecker2(unsigned bsize_in,unsigned avg)224 XMoveChecker2::XMoveChecker2( unsigned bsize_in, unsigned avg )
225 : XMoveChecker( bsize_in, avg )
226 {
227 help = XCreatePixmap(dpy,win,dhelp,dhelp,DefaultDepth(dpy,scr));
228 bpix = XCreatePixmap(dpy,win,dhelp,dhelp,DefaultDepth(dpy,scr));
229 XFillRectangle( dpy, bpix, DefaultGC(dpy,scr), 0, 0, dhelp, dhelp );
230
231 rpix = XCreatePixmap(dpy,win,bsize,bsize,1);
232
233 gc_bit = XCreateGC( dpy, rpix, 0, 0 );
234 XFillRectangle( dpy, rpix, gc_bit, 0, 0, bsize, bsize );
235
236 //
237 // ball_mask: 0x03
238 // shade_mask: 0x04
239 //
240 unsigned long value_mask;
241 XGCValues values;
242
243 value_mask = GCPlaneMask | GCForeground | GCBackground | GCFunction
244 | GCGraphicsExposures;
245
246 values.graphics_exposures = False;
247 values.fill_style = FillSolid;
248 values.background = 0;
249
250 values.foreground = 0x00;
251 values.plane_mask = 0x07;
252 values.function = GXcopy;
253 gc_bcopy = XCreateGC( dpy, win, value_mask, &values );
254 values.function = GXxor;
255 gc_bxor = XCreateGC( dpy, win, value_mask, &values );
256
257 values.function = GXxor;
258 values.plane_mask = 0x03;
259 values.foreground = 0x03;
260 gc_ball = XCreateGC( dpy, win, value_mask, &values );
261 }
262
~XMoveChecker2()263 XMoveChecker2::~XMoveChecker2() {
264 XFreeGC( dpy, gc_ball );
265 XFreeGC( dpy, gc_bxor );
266 XFreeGC( dpy, gc_bcopy );
267 XFreePixmap( dpy, help );
268 XFreePixmap( dpy, bpix );
269 XFreePixmap( dpy, rpix );
270 }
271
272
273 // XMoveChecker2: simulates the enhanced algorithm that consists of
274 // - initialisation the double buffer with an oversized 8 bit shadowed image of the old ball
275 // (a lot more memory is need in this approach than in the next similare one)
276 // - copying the 8 bit shadow image of the new ball
277 // - copying 2 bitmaps with the rings of the ball with 1 bit each
278 // - copying the double buffer to the screen
279 // - 5 X-calls
280
RollBall()281 void XMoveChecker2::RollBall() {
282
283 int d = bsize;
284 int dx = avgmove;
285 int dy = avgmove;
286
287 int absx = (dx>0)?dx:-dx;
288 int absy = (dy>0)?dy:-dy;
289
290 int width = d+absx; // tats�chlicher Ausschnittgr��e der Pixmap
291 int height= d+absy;
292 int ox = (dx>0)?0:absx; // relativer Abstand alte Position
293 int oy = (dy>0)?0:absy;
294 int nx = (dx>0)?absx:0; // relativer Abstand neue Position
295 int ny = (dy>0)?absy:0;
296
297 XCopyArea(dpy,bpix,help,gc_bcopy,0,0,width,height,0,0);
298 XCopyArea(dpy,bpix,help,gc_bxor,0,0,d,d,nx,ny);
299
300 XCopyPlane(dpy,rpix,help,gc_ball,0,0,d,d,ox,oy,1);
301 XCopyPlane(dpy,rpix,help,gc_ball,0,0,d,d,nx,ny,1);
302
303 XCopyArea(dpy,help,win,gc_bxor,0,0,width,height,0,0 );
304 }
305
306 // ==========================================================================
307
308 class XMoveChecker3 : public XMoveChecker2 {
309 public:
310 XMoveChecker3( unsigned bsize, unsigned avg );
311 virtual ~XMoveChecker3();
312 virtual void RollBall();
313 };
314
XMoveChecker3(unsigned bsize_in,unsigned avg)315 XMoveChecker3::XMoveChecker3( unsigned bsize_in, unsigned avg )
316 : XMoveChecker2( bsize_in, avg ) {
317 }
318
~XMoveChecker3()319 XMoveChecker3::~XMoveChecker3() {
320 }
321
322 // XMoveChecker3: simulates the enhanced algorithm that consists of
323 // - clearing the double buffer pixmap of depth 8
324 // - copying the 8 bit shadow image of the balls with 8 bits each
325 // - copying 2 bitmaps with the rings of the ball with 1 bit each
326 // - copying the double buffer to the screen
327 // - 6 X-calls
328
RollBall()329 void XMoveChecker3::RollBall() {
330
331 int d = bsize;
332 int dx = avgmove;
333 int dy = avgmove;
334
335 int absx = (dx>0)?dx:-dx;
336 int absy = (dy>0)?dy:-dy;
337
338 int width = d+absx; // tats�chlicher Ausschnittgr��e der Pixmap
339 int height= d+absy;
340 int ox = (dx>0)?0:absx; // relativer Abstand alte Position
341 int oy = (dy>0)?0:absy;
342 int nx = (dx>0)?absx:0; // relativer Abstand neue Position
343 int ny = (dy>0)?absy:0;
344
345 XFillRectangle(dpy,help,gc_bcopy,0,0,width,height);
346
347 XCopyArea(dpy,bpix,help,gc_bxor,0,0,d,d,ox,oy);
348 XCopyArea(dpy,bpix,help,gc_bxor,0,0,d,d,nx,ny);
349
350 XCopyPlane(dpy,rpix,help,gc_ball,0,0,d,d,ox,oy,1);
351 XCopyPlane(dpy,rpix,help,gc_ball,0,0,d,d,nx,ny,1);
352
353 XCopyArea(dpy,help,win,gc_bxor,0,0,width,height,0,0 );
354 }
355
356 // ==========================================================================
357
358 class XMoveChecker4 : public XMoveChecker2 {
359 public:
360 XMoveChecker4( unsigned bsize, unsigned avg );
361 virtual ~XMoveChecker4();
362 virtual void RollBall();
363 };
364
XMoveChecker4(unsigned bsize_in,unsigned avg)365 XMoveChecker4::XMoveChecker4( unsigned bsize_in, unsigned avg )
366 : XMoveChecker2( bsize_in, avg ) {
367 }
368
~XMoveChecker4()369 XMoveChecker4::~XMoveChecker4() {
370 }
371
372 // XMoveChecker4: simulates the enhanced algorithm that consists of
373 // - initialisation of double-buffer parts, not covered from old ball
374 // - initialisaion of the double-buffer part containing old ball (8 bit)
375 // - copying the 8 bit shadow image of the new ball (8 bit)
376 // - copying 2 bitmaps with the rings of the ball with 1 bit each
377 // - copying the double buffer to the screen
378 // - 6 X-calls
379
RollBall()380 void XMoveChecker4::RollBall() {
381
382 int d = bsize;
383 int dx = avgmove;
384 int dy = avgmove;
385
386 int absx = (dx>0)?dx:-dx;
387 int absy = (dy>0)?dy:-dy;
388
389 int width = d+absx; // tats�chlicher Ausschnittgr��e der Pixmap
390 int height= d+absy;
391 int ox = (dx>0)?0:absx; // relativer Abstand alte Position
392 int oy = (dy>0)?0:absy;
393 int nx = (dx>0)?absx:0; // relativer Abstand neue Position
394 int ny = (dy>0)?absy:0;
395
396 XFillRectangle(dpy,help,gc_bcopy,0,d,width-d,height-d);
397 XFillRectangle(dpy,help,gc_bcopy,d,0,width-d,height);
398
399 XCopyArea(dpy,bpix,help,gc_bcopy,0,0,d,d,ox,oy);
400 XCopyArea(dpy,bpix,help,gc_bxor,0,0,d,d,nx,ny);
401
402 XCopyPlane(dpy,rpix,help,gc_ball,0,0,d,d,ox,oy,1);
403 XCopyPlane(dpy,rpix,help,gc_ball,0,0,d,d,nx,ny,1);
404
405 XCopyArea(dpy,help,win,gc_bxor,0,0,width,height,0,0 );
406 }
407
408 // ==========================================================================
409
410
main_xbench(int argc,char ** argv)411 void main_xbench(int argc, char **argv)
412 {
413 XMoveChecker *xm=0;
414 unsigned bsize = 24;
415 unsigned avgmove = 8;
416 unsigned count = 3;
417 unsigned secs = 3;
418
419 for (int i=1;i<argc;i++) {
420 if (!strncmp(argv[i],"-n",2)) count = atoi(argv[i]+2);
421 else if (!strncmp(argv[i],"-s",2)) secs = atoi(argv[i]+2);
422 else if (!strncmp(argv[i],"-b",2)) bsize = atoi(argv[i]+2);
423 else if (!strncmp(argv[i],"-m",2)) avgmove = atoi(argv[i]+2);
424 else {
425 printf( "usage: bench [-options]\n" );
426 printf( " -n<n> number of tests (def: %d)\n", count );
427 printf( " -s<n> seconds of test (def: %d)\n", secs );
428 printf( " -b<n> size of pixmap (def: %d)\n", bsize );
429 printf( " -m<n> average move distance (def: %d)\n", avgmove );
430 exit(0);
431 }
432 }
433
434 printf( "\nBenchmark for different animation modes of flying -deluxe\n" );
435 printf( "Mode 2 usually turns out to be the fastest and\n" );
436 printf( "therefore is turned on by default in the game.\n\n" );
437 printf( " Mode 1 Mode 2 Mode 3\n" );
438 printf( "------------------------------------------\n" );
439 fflush( stdout );
440 while( count-- > 0 ) {
441 for (int j=1;j<=3;j++) {
442 switch(j) {
443 case 1: xm = new XMoveChecker1( bsize, avgmove ); break;
444 case 2: xm = new XMoveChecker2( bsize, avgmove ); break;
445 case 3: xm = new XMoveChecker3( bsize, avgmove ); break;
446 case 4: xm = new XMoveChecker4( bsize, avgmove ); break;
447 }
448
449 printf( "%6.2f pics/s ", xm->loop(secs)/(double)secs );
450 fflush(stdout);
451 delete xm;
452 }
453 printf( "\n" );
454 }
455 printf("\nThe benchmark computes the number frames per second by\n" );
456 printf( "assuming that all 16 balls are moving at constant speed.\n" );
457
458 printf("\nby Helmut H�nig, May 1995\n\n" );
459 }
460