1 /**
2 *
3 * Compiz benchmark plugin
4 *
5 * bench.c
6 *
7 * Copyright : (C) 2006 by Dennis Kasprzyk
8 * E-mail : onestone@beryl-project.org
9 *
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 **/
22
23 #include <compiz-core.h>
24
25 #include "bench_tex.h"
26 #include "bench_options.h"
27
28 #define GET_BENCH_DISPLAY(d) \
29 ((BenchDisplay *) (d)->base.privates[displayPrivateIndex].ptr)
30
31 #define BENCH_DISPLAY(d) \
32 BenchDisplay *bd = GET_BENCH_DISPLAY (d)
33
34 #define GET_BENCH_SCREEN(s, bd) \
35 ((BenchScreen *) (s)->base.privates[(bd)->screenPrivateIndex].ptr)
36
37 #define BENCH_SCREEN(s) \
38 BenchScreen *bs = GET_BENCH_SCREEN (s, GET_BENCH_DISPLAY (s->display))
39
40 #define TIMEVALDIFF(tv1, tv2) \
41 (((tv1)->tv_sec == (tv2)->tv_sec || (tv1)->tv_usec >= (tv2)->tv_usec) ? \
42 ((((tv1)->tv_sec - (tv2)->tv_sec) * 1000000) + \
43 ((tv1)->tv_usec - (tv2)->tv_usec)) / 1000 : \
44 ((((tv1)->tv_sec - 1 - (tv2)->tv_sec) * 1000000) + \
45 (1000000 + (tv1)->tv_usec - (tv2)->tv_usec)) / 1000)
46
47 #define TIMEVALDIFFU(tv1, tv2) \
48 (((tv1)->tv_sec == (tv2)->tv_sec || (tv1)->tv_usec >= (tv2)->tv_usec) ? \
49 ((((tv1)->tv_sec - (tv2)->tv_sec) * 1000000) + \
50 ((tv1)->tv_usec - (tv2)->tv_usec)): \
51 ((((tv1)->tv_sec - 1 - (tv2)->tv_sec) * 1000000) + \
52 (1000000 + (tv1)->tv_usec - (tv2)->tv_usec)))
53
54 #ifdef GL_DEBUG
55
56 static GLenum gl_error;
57
58 #define GLERR gl_error=glGetError(); if (gl_error != GL_NO_ERROR) { fprintf (stderr,"GL error 0x%X has occured at %s:%d\n",gl_error,__FILE__,__LINE__); }
59 #else
60 #define GLERR
61 #endif
62
63 static int displayPrivateIndex = 0;
64
65 typedef struct _BenchDisplay
66 {
67 int screenPrivateIndex;
68 Bool active;
69 }
70 BenchDisplay;
71
72 typedef struct _BenchScreen
73 {
74 GLuint dList;
75 float rrVal;
76 float fps;
77 float alpha;
78
79 struct timeval initTime;
80 struct timeval lastRedraw;
81
82 float ctime;
83 float frames;
84
85 GLuint numTex[10];
86 GLuint backTex;
87
88 PreparePaintScreenProc preparePaintScreen;
89 DonePaintScreenProc donePaintScreen;
90 PaintOutputProc paintOutput;
91 }
92 BenchScreen;
93
94 static void
benchPreparePaintScreen(CompScreen * s,int ms)95 benchPreparePaintScreen (CompScreen *s,
96 int ms)
97 {
98 BENCH_SCREEN (s);
99 BENCH_DISPLAY (s->display);
100
101 float nRrVal;
102 float ratio = 0.05;
103 int timediff;
104
105 struct timeval now;
106
107 gettimeofday (&now, 0);
108
109 timediff = TIMEVALDIFF (&now, &bs->lastRedraw);
110
111 nRrVal = MIN (1.1, (float) s->optimalRedrawTime / (float) timediff);
112
113 bs->rrVal = (bs->rrVal * (1.0 - ratio) ) + (nRrVal * ratio);
114
115 bs->fps = (bs->fps * (1.0 - ratio) ) +
116 (1000000.0 / TIMEVALDIFFU (&now, &bs->lastRedraw) * ratio);
117
118 bs->lastRedraw = now;
119
120 if (benchGetOutputConsole (s->display) && bd->active)
121 {
122 bs->frames++;
123 bs->ctime += timediff;
124
125 if (bs->ctime >
126 benchGetConsoleUpdateTime (s->display) * 1000)
127 {
128 printf ("[BENCH] : %.0f frames in %.1f seconds = %.3f FPS\n",
129 bs->frames, bs->ctime / 1000.0,
130 bs->frames / (bs->ctime / 1000.0) );
131 bs->frames = 0;
132 bs->ctime = 0;
133 }
134 }
135
136 UNWRAP (bs, s, preparePaintScreen);
137 (*s->preparePaintScreen) (s, (bs->alpha > 0.0) ? timediff : ms);
138 WRAP (bs, s, preparePaintScreen, benchPreparePaintScreen);
139
140 if (bd->active)
141 bs->alpha += timediff / 1000.0;
142 else
143 bs->alpha -= timediff / 1000.0;
144
145 bs->alpha = MIN (1.0, MAX (0.0, bs->alpha) );
146 }
147
148 static void
benchDonePaintScreen(CompScreen * s)149 benchDonePaintScreen (CompScreen *s)
150 {
151 BENCH_SCREEN (s);
152 BENCH_DISPLAY (s->display);
153
154 if (bs->alpha > 0.0)
155 {
156 damageScreen (s);
157 glFlush();
158 XSync (s->display->display, FALSE);
159
160 if (benchGetDisableLimiter (s->display) )
161 {
162 s->lastRedraw = bs->initTime;
163 s->timeMult = 0;
164 }
165
166 if (!bd->active)
167 s->timeMult = 0;
168 }
169
170 UNWRAP (bs, s, donePaintScreen);
171 (*s->donePaintScreen) (s);
172 WRAP (bs, s, donePaintScreen, benchDonePaintScreen);
173 }
174
175 static Bool
benchPaintOutput(CompScreen * s,const ScreenPaintAttrib * sa,const CompTransform * transform,Region region,CompOutput * output,unsigned int mask)176 benchPaintOutput (CompScreen *s,
177 const ScreenPaintAttrib *sa,
178 const CompTransform *transform,
179 Region region,
180 CompOutput *output,
181 unsigned int mask)
182 {
183
184 Bool status, isSet;
185 unsigned int fps;
186 CompTransform sTransform = *transform;
187
188 BENCH_SCREEN (s);
189
190 UNWRAP (bs, s, paintOutput);
191 status = (*s->paintOutput) (s, sa, transform, region, output, mask);
192 WRAP (bs, s, paintOutput, benchPaintOutput);
193
194 if (bs->alpha <= 0.0
195 || !benchGetOutputScreen (s->display) )
196 return status;
197
198 glGetError();
199 glPushAttrib (GL_COLOR_BUFFER_BIT | GL_TEXTURE_BIT);
200 GLERR;
201
202 transformToScreenSpace (s, output, -DEFAULT_Z_CAMERA, &sTransform);
203
204 glPushMatrix ();
205 glLoadMatrixf (sTransform.m);
206
207 glEnable (GL_BLEND);
208 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
209 glColor4f (1.0, 1.0, 1.0, bs->alpha);
210 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
211
212 glTranslatef (benchGetPositionX (s->display),
213 benchGetPositionY (s->display), 0);
214
215 glEnable (GL_TEXTURE_2D);
216 glBindTexture (GL_TEXTURE_2D, bs->backTex);
217
218 glBegin (GL_QUADS);
219 glTexCoord2f (0, 0);
220 glVertex2f (0, 0);
221 glTexCoord2f (0, 1);
222 glVertex2f (0, 256);
223 glTexCoord2f (1, 1);
224 glVertex2f (512, 256);
225 glTexCoord2f (1, 0);
226 glVertex2f (512, 0);
227 glEnd();
228
229 glBindTexture (GL_TEXTURE_2D, 0);
230 glDisable (GL_TEXTURE_2D);
231
232 glTranslatef (53, 83, 0);
233
234 float rrVal = MIN (1.0, MAX (0.0, bs->rrVal) );
235
236 if (rrVal < 0.5)
237 {
238 glBegin (GL_QUADS);
239 glColor4f (1.0, 0.0, 0.0, bs->alpha);
240 glVertex2f (0.0, 0.0);
241 glVertex2f (0.0, 25.0);
242 glColor4f (1.0, rrVal * 2.0, 0.0, bs->alpha);
243 glVertex2f (330.0 * rrVal, 25.0);
244 glVertex2f (330.0 * rrVal, 0.0);
245 glEnd();
246 }
247 else
248 {
249 glBegin (GL_QUADS);
250 glColor4f (1.0, 0.0, 0.0, bs->alpha);
251 glVertex2f (0.0, 0.0);
252 glVertex2f (0.0, 25.0);
253 glColor4f (1.0, 1.0, 0.0, bs->alpha);
254 glVertex2f (165.0, 25.0);
255 glVertex2f (165.0, 0.0);
256 glEnd();
257
258 glBegin (GL_QUADS);
259 glColor4f (1.0, 1.0, 0.0, bs->alpha);
260 glVertex2f (165.0, 0.0);
261 glVertex2f (165.0, 25.0);
262 glColor4f (1.0 - ( (rrVal - 0.5) * 2.0), 1.0, 0.0, bs->alpha);
263 glVertex2f (165.0 + 330.0 * (rrVal - 0.5), 25.0);
264 glVertex2f (165.0 + 330.0 * (rrVal - 0.5), 0.0);
265 glEnd();
266 }
267
268 glColor4f (0.0, 0.0, 0.0, bs->alpha);
269 glCallList (bs->dList);
270 glTranslatef (72, 45, 0);
271
272 float red;
273
274 if (bs->fps > 30.0)
275 red = 0.0;
276 else
277 red = 1.0;
278
279 if (bs->fps <= 30.0 && bs->fps > 20.0)
280 red = 1.0 - ( (bs->fps - 20.0) / 10.0);
281
282 glColor4f (red, 0.0, 0.0, bs->alpha);
283 glEnable (GL_TEXTURE_2D);
284
285 isSet = FALSE;
286
287 fps = (bs->fps * 100.0);
288 fps = MIN (999999, fps);
289
290 if (fps >= 100000)
291 {
292 glBindTexture (GL_TEXTURE_2D, bs->numTex[fps / 100000]);
293 glCallList (bs->dList + 1);
294 isSet = TRUE;
295 }
296
297 fps %= 100000;
298
299 glTranslatef (12, 0, 0);
300
301 if (fps >= 10000 || isSet)
302 {
303 glBindTexture (GL_TEXTURE_2D, bs->numTex[fps / 10000]);
304 glCallList (bs->dList + 1);
305 isSet = TRUE;
306 }
307
308 fps %= 10000;
309
310 glTranslatef (12, 0, 0);
311
312 if (fps >= 1000 || isSet)
313 {
314 glBindTexture (GL_TEXTURE_2D, bs->numTex[fps / 1000]);
315 glCallList (bs->dList + 1);
316 }
317
318 fps %= 1000;
319
320 glTranslatef (12, 0, 0);
321
322 glBindTexture (GL_TEXTURE_2D, bs->numTex[fps / 100]);
323 glCallList (bs->dList + 1);
324 fps %= 100;
325
326 glTranslatef (19, 0, 0);
327
328 glBindTexture (GL_TEXTURE_2D, bs->numTex[fps / 10]);
329 glCallList (bs->dList + 1);
330 fps %= 10;
331
332 glTranslatef (12, 0, 0);
333
334 glBindTexture (GL_TEXTURE_2D, bs->numTex[fps]);
335 glCallList (bs->dList + 1);
336
337 glBindTexture (GL_TEXTURE_2D, 0);
338 glDisable (GL_TEXTURE_2D);
339
340 glPopMatrix();
341
342 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
343
344 glColor4f (1.0, 1.0, 1.0, 1.0);
345
346 glPopAttrib();
347 glGetError();
348
349 return status;
350 }
351
352 static Bool
benchInitScreen(CompPlugin * p,CompScreen * s)353 benchInitScreen (CompPlugin *p,
354 CompScreen *s)
355 {
356 int i;
357
358 BENCH_DISPLAY (s->display);
359
360 BenchScreen *bs = (BenchScreen *) calloc (1, sizeof (BenchScreen) );
361
362 s->base.privates[bd->screenPrivateIndex].ptr = bs;
363
364 WRAP (bs, s, paintOutput, benchPaintOutput);
365 WRAP (bs, s, preparePaintScreen, benchPreparePaintScreen);
366 WRAP (bs, s, donePaintScreen, benchDonePaintScreen);
367
368 glGenTextures (10, bs->numTex);
369 glGenTextures (1, &bs->backTex);
370
371 glGetError();
372
373 glEnable (GL_TEXTURE_2D);
374
375 bs->alpha = 0;
376 bs->ctime = 0;
377 bs->frames = 0;
378
379 for (i = 0; i < 10; i++)
380 {
381 //Bind the texture
382 glBindTexture (GL_TEXTURE_2D, bs->numTex[i]);
383
384 //Load the parameters
385 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
386 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
387 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
388 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
389
390 glTexImage2D (GL_TEXTURE_2D, 0, GL_ALPHA, 16, 32, 0,
391 GL_RGBA, GL_UNSIGNED_BYTE, number_data[i]);
392 GLERR;
393 }
394
395 glBindTexture (GL_TEXTURE_2D, bs->backTex);
396
397 //Load the parameters
398 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
399 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
400 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
401 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
402
403 glTexImage2D (GL_TEXTURE_2D, 0, 4, 512, 256, 0, GL_RGBA,
404 GL_UNSIGNED_BYTE, image_data);
405 GLERR;
406
407 glBindTexture (GL_TEXTURE_2D, 0);
408 glDisable (GL_TEXTURE_2D);
409
410 bs->dList = glGenLists (2);
411 glNewList (bs->dList, GL_COMPILE);
412
413 glLineWidth (2.0);
414
415 glBegin (GL_LINE_LOOP);
416 glVertex2f (0, 0);
417 glVertex2f (0, 25);
418 glVertex2f (330, 25);
419 glVertex2f (330, 0);
420 glEnd();
421
422 glLineWidth (1.0);
423
424 glBegin (GL_LINES);
425
426 for (i = 33; i < 330; i += 33)
427 {
428 glVertex2f (i, 15);
429 glVertex2f (i, 25);
430 }
431
432 for (i = 16; i < 330; i += 33)
433 {
434 glVertex2f (i, 20);
435 glVertex2f (i, 25);
436 }
437
438 glEnd();
439
440 glEndList();
441
442 glNewList (bs->dList + 1, GL_COMPILE);
443 glBegin (GL_QUADS);
444 glTexCoord2f (0, 0);
445 glVertex2f (0, 0);
446 glTexCoord2f (0, 1);
447 glVertex2f (0, 32);
448 glTexCoord2f (1, 1);
449 glVertex2f (16, 32);
450 glTexCoord2f (1, 0);
451 glVertex2f (16, 0);
452 glEnd();
453 glEndList();
454
455 gettimeofday (&bs->initTime, 0);
456 gettimeofday (&bs->lastRedraw, 0);
457
458 return TRUE;
459 }
460
461
462 static void
benchFiniScreen(CompPlugin * p,CompScreen * s)463 benchFiniScreen (CompPlugin *p,
464 CompScreen *s)
465 {
466
467 BENCH_SCREEN (s);
468 glDeleteLists (bs->dList, 2);
469
470 glDeleteTextures (10, bs->numTex);
471 glDeleteTextures (1, &bs->backTex);
472
473 //Restore the original function
474 UNWRAP (bs, s, paintOutput);
475 UNWRAP (bs, s, preparePaintScreen);
476 UNWRAP (bs, s, donePaintScreen);
477
478 //Free the pointer
479 free (bs);
480 }
481
482 static Bool
benchInitiate(CompDisplay * d,CompAction * ac,CompActionState state,CompOption * option,int nOption)483 benchInitiate (CompDisplay *d,
484 CompAction *ac,
485 CompActionState state,
486 CompOption *option,
487 int nOption)
488 {
489 CompScreen *s;
490
491 BENCH_DISPLAY (d);
492 bd->active = !bd->active;
493 bd->active &= benchGetOutputScreen (d) || benchGetOutputConsole (d);
494 s = findScreenAtDisplay (d, getIntOptionNamed (option, nOption, "root", 0));
495
496 if (s)
497 {
498 BENCH_SCREEN (s);
499 damageScreen (s);
500 bs->ctime = 0;
501 bs->frames = 0;
502 }
503
504 return FALSE;
505 }
506
507 static Bool
benchInitDisplay(CompPlugin * p,CompDisplay * d)508 benchInitDisplay (CompPlugin *p,
509 CompDisplay *d)
510 {
511 //Generate a bench display
512 BenchDisplay *bd;
513
514 if (!checkPluginABI ("core", CORE_ABIVERSION))
515 return FALSE;
516
517 bd = (BenchDisplay *) malloc (sizeof (BenchDisplay));
518
519 if (!bd)
520 return FALSE;
521
522 //Allocate a private index
523 bd->screenPrivateIndex = allocateScreenPrivateIndex (d);
524 //Check if its valid
525
526 if (bd->screenPrivateIndex < 0)
527 {
528 //Its invalid so free memory and return
529 free (bd);
530 return FALSE;
531 }
532
533 benchSetInitiateKeyInitiate (d, benchInitiate);
534
535 bd->active = FALSE;
536 //Record the display
537 d->base.privates[displayPrivateIndex].ptr = bd;
538 return TRUE;
539 }
540
541 static void
benchFiniDisplay(CompPlugin * p,CompDisplay * d)542 benchFiniDisplay (CompPlugin *p,
543 CompDisplay *d)
544 {
545 BENCH_DISPLAY (d);
546 //Free the private index
547 freeScreenPrivateIndex (d, bd->screenPrivateIndex);
548 //Free the pointer
549 free (bd);
550 }
551
552
553
554 static Bool
benchInit(CompPlugin * p)555 benchInit (CompPlugin * p)
556 {
557 displayPrivateIndex = allocateDisplayPrivateIndex();
558
559 if (displayPrivateIndex < 0)
560 return FALSE;
561
562 return TRUE;
563 }
564
565 static void
benchFini(CompPlugin * p)566 benchFini (CompPlugin * p)
567 {
568 if (displayPrivateIndex >= 0)
569 freeDisplayPrivateIndex (displayPrivateIndex);
570 }
571
572 static CompBool
benchInitObject(CompPlugin * p,CompObject * o)573 benchInitObject (CompPlugin *p,
574 CompObject *o)
575 {
576 static InitPluginObjectProc dispTab[] = {
577 (InitPluginObjectProc) 0, /* InitCore */
578 (InitPluginObjectProc) benchInitDisplay,
579 (InitPluginObjectProc) benchInitScreen
580 };
581
582 RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
583 }
584
585 static void
benchFiniObject(CompPlugin * p,CompObject * o)586 benchFiniObject (CompPlugin *p,
587 CompObject *o)
588 {
589 static FiniPluginObjectProc dispTab[] = {
590 (FiniPluginObjectProc) 0, /* FiniCore */
591 (FiniPluginObjectProc) benchFiniDisplay,
592 (FiniPluginObjectProc) benchFiniScreen
593 };
594
595 DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o));
596 }
597
598 CompPluginVTable benchVTable = {
599 "bench",
600 0,
601 benchInit,
602 benchFini,
603 benchInitObject,
604 benchFiniObject,
605 0,
606 0
607 };
608
609 CompPluginVTable *
getCompPluginInfo(void)610 getCompPluginInfo (void)
611 {
612 return &benchVTable;
613 }
614