]> git.cworth.org Git - fips/blob - glwrap.c
Fix glwrap.c to workaround 'const' changes in OpenGL headers.
[fips] / glwrap.c
1 /* Copyright © 2013, Intel Corporation
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to deal
5  * in the Software without restriction, including without limitation the rights
6  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7  * copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19  * THE SOFTWARE.
20  */
21
22 #include "fips.h"
23
24 #include "glwrap.h"
25
26 /* The prototypes for some OpenGL functions changed at one point from:
27  *
28  *      const void* *indices
29  * to:
30  *      const void* const coist *indices
31  *
32  * This makes it difficult for us to provide an implementation of
33  * these functions that is consistent with the locally-available gl.h
34  * since we don't know if the extra const will be present or not.
35  *
36  * To workaround this problem, we simply #define away const altogether
37  * before including gl.h.
38  *
39  * Kudos to Keith Packard for suggesting this kludge.
40  */
41 #define const
42
43 #define GL_GLEXT_PROTOTYPES
44 #include <GL/gl.h>
45
46 #include <sys/time.h>
47
48 #include "dlwrap.h"
49
50 typedef struct counter
51 {
52         unsigned id;
53         unsigned program;
54         struct counter *next;
55 } counter_t;
56
57 typedef struct program_metrics
58 {
59         unsigned id;
60         double ticks;
61 } program_metrics_t;
62
63 typedef struct context
64 {
65         unsigned int program;
66
67         counter_t *counter_head;
68         counter_t *counter_tail;
69
70         unsigned num_program_metrics;
71         program_metrics_t *program_metrics;
72 } context_t;
73
74 /* FIXME: Need a map from integers to context objects and track the
75  * current context with glXMakeContextCurrent, eglMakeCurrent, etc. */
76
77 context_t current_context;
78
79 static unsigned
80 add_counter (void)
81 {
82         counter_t *counter;
83
84         counter = malloc (sizeof(counter_t));
85         if (counter == NULL) {
86                 fprintf (stderr, "Out of memory\n");
87                 exit (1);
88         }
89
90         glGenQueries (1, &counter->id);
91
92         counter->program = current_context.program;
93         counter->next = NULL;
94
95         if (current_context.counter_tail) {
96                 current_context.counter_tail->next = counter;
97                 current_context.counter_tail = counter;
98         } else {
99                 current_context.counter_tail = counter;
100                 current_context.counter_head = counter;
101         }
102
103         return counter->id;
104 }
105
106 static void *
107 lookup (const char *name)
108 {
109         const char *libgl_filename = "libGL.so.1";
110         static void *libgl_handle = NULL;
111
112         if (! libgl_handle) {
113                 libgl_handle = dlwrap_real_dlopen (libgl_filename, RTLD_NOW | RTLD_DEEPBIND);
114                 if (! libgl_handle) {
115                         fprintf (stderr, "Error: Failed to dlopen %s\n",
116                                  libgl_filename);
117                         exit (1);
118                 }
119         }
120
121         return dlwrap_real_dlsym (libgl_handle, name);
122 }
123
124 /* Defer to the underlying, ''real'' function to do the real work. */
125 #define DEFER(function,...) do {                                \
126         static typeof(&function) real_ ## function;             \
127         if (! real_ ## function)                                \
128                 real_ ## function = lookup (#function);         \
129         real_ ## function(__VA_ARGS__);                         \
130 } while (0);
131
132 /* Execute a glBegineQuery/glEndQuery pair around an OpenGL call. */
133 #define TIMED_DEFER(function,...) do {                  \
134         unsigned counter;                               \
135         counter = add_counter ();                       \
136         glBeginQuery (GL_TIME_ELAPSED, counter);        \
137         DEFER(function, __VA_ARGS__);                   \
138         glEndQuery (GL_TIME_ELAPSED);                   \
139 } while (0);
140
141 /* Thanks to apitrace source code for the list of OpenGL draw calls. */
142 void
143 glDrawArrays (GLenum mode, GLint first, GLsizei count)
144 {
145         TIMED_DEFER (glDrawArrays, mode, first, count);
146 }
147
148 void
149 glDrawArraysEXT (GLenum mode, GLint first, GLsizei count)
150 {
151         TIMED_DEFER (glDrawArraysEXT, mode, first, count);
152 }
153
154 void
155 glDrawArraysIndirect (GLenum mode, const GLvoid *indirect)
156 {
157         TIMED_DEFER (glDrawArraysIndirect, mode, indirect);
158 }
159
160 void
161 glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count,
162                        GLsizei primcount)
163 {
164         TIMED_DEFER (glDrawArraysInstanced, mode, first, count, primcount);
165 }
166
167 void
168 glDrawArraysInstancedARB (GLenum mode, GLint first, GLsizei count,
169                           GLsizei primcount)
170 {
171         TIMED_DEFER (glDrawArraysInstancedARB, mode, first, count, primcount);
172 }
173
174 void
175 glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count,
176                           GLsizei primcount)
177 {
178         TIMED_DEFER (glDrawArraysInstancedEXT, mode, start, count, primcount);
179 }
180
181 void
182 glDrawArraysInstancedBaseInstance (GLenum mode, GLint first, GLsizei count,
183                                    GLsizei primcount, GLuint baseinstance)
184 {
185         TIMED_DEFER (glDrawArraysInstancedBaseInstance, mode,
186                      first, count, primcount, baseinstance);
187 }
188
189 void
190 glDrawMeshArraysSUN (GLenum mode, GLint first, GLsizei count, GLsizei width)
191 {
192         TIMED_DEFER (glDrawMeshArraysSUN, mode, first, count, width);
193 }
194
195 void
196 glMultiDrawArrays (GLenum mode, const GLint *first,
197                    const GLsizei *count, GLsizei primcount)
198 {
199         TIMED_DEFER (glMultiDrawArrays, mode, first, count, primcount);
200 }
201
202 void
203 glMultiDrawArraysEXT (GLenum mode, const GLint *first,
204                       const GLsizei *count, GLsizei primcount)
205 {
206         TIMED_DEFER (glMultiDrawArraysEXT, mode, first, count, primcount);
207 }
208
209 void
210 glMultiModeDrawArraysIBM (const GLenum *mode, const GLint *first,
211                           const GLsizei *count, GLsizei primcount,
212                           GLint modestride)
213 {
214         TIMED_DEFER (glMultiModeDrawArraysIBM, mode,
215                      first, count, primcount, modestride);
216 }
217
218 /* FIXME?
219 void
220 glMultiDrawArraysIndirect (...)
221 {
222         TIMED_DEFER (glMultiDrawArraysIndirect, ...);
223 }
224 */
225
226 void
227 glMultiDrawArraysIndirectAMD (GLenum mode, const GLvoid *indirect,
228                               GLsizei primcount, GLsizei stride)
229 {
230         TIMED_DEFER (glMultiDrawArraysIndirectAMD, mode,
231                      indirect, primcount, stride);
232 }
233
234 void
235 glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
236 {
237         TIMED_DEFER (glDrawElements, mode, count, type, indices);
238 }
239
240 void
241 glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type,
242                           const GLvoid *indices, GLint basevertex)
243 {
244         TIMED_DEFER (glDrawElementsBaseVertex, mode, count,
245                      type, indices, basevertex);
246 }
247
248 void
249 glDrawElementsIndirect (GLenum mode, GLenum type, const GLvoid *indirect)
250 {
251         TIMED_DEFER (glDrawElementsIndirect, mode, type, indirect);
252 }
253
254 void
255 glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type,
256                          const GLvoid *indices, GLsizei primcount)
257 {
258         TIMED_DEFER (glDrawElementsInstanced, mode, count,
259                      type, indices, primcount);
260 }
261
262 void
263 glDrawElementsInstancedARB (GLenum mode, GLsizei count, GLenum type,
264                             const GLvoid *indices, GLsizei primcount)
265 {
266         TIMED_DEFER (glDrawElementsInstancedARB, mode, count,
267                      type, indices, primcount);
268 }
269
270 void
271 glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type,
272                             const GLvoid *indices, GLsizei primcount)
273 {
274         TIMED_DEFER (glDrawElementsInstancedEXT, mode, count,
275                      type, indices, primcount);
276 }
277
278 void
279 glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type,
280                                    const GLvoid *indices, GLsizei primcount,
281                                    GLint basevertex)
282 {
283         TIMED_DEFER (glDrawElementsInstancedBaseVertex, mode, count,
284                      type, indices, primcount, basevertex);
285 }
286
287 void
288 glDrawElementsInstancedBaseInstance (GLenum mode, GLsizei count, GLenum type,
289                                      const void *indices, GLsizei primcount,
290                                      GLuint baseinstance)
291 {
292         TIMED_DEFER (glDrawElementsInstancedBaseInstance, mode, count, type,
293                      indices, primcount, baseinstance);
294 }
295
296 void
297 glDrawElementsInstancedBaseVertexBaseInstance (GLenum mode, GLsizei count,
298                       GLenum type, const void *indices, GLsizei primcount,
299                       GLint basevertex, GLuint baseinstance)
300 {
301         TIMED_DEFER (glDrawElementsInstancedBaseVertexBaseInstance, mode,
302                      count, type, indices, primcount, basevertex, baseinstance);
303 }
304
305 void
306 glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count,
307                      GLenum type, const GLvoid *indices)
308 {
309         TIMED_DEFER (glDrawRangeElements, mode, start, end,
310                      count, type, indices);
311 }
312
313 void
314 glDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint end, GLsizei count,
315                         GLenum type, const GLvoid *indices)
316 {
317         TIMED_DEFER (glDrawRangeElementsEXT, mode, start, end,
318                      count, type, indices);
319 }
320
321 void
322 glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end,
323                                GLsizei count, GLenum type,
324                                const GLvoid *indices, GLint basevertex)
325 {
326         TIMED_DEFER (glDrawRangeElementsBaseVertex, mode, start, end,
327                      count, type, indices, basevertex);
328 }
329
330 void
331 glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type,
332                      const GLvoid* *indices, GLsizei primcount)
333 {
334         TIMED_DEFER (glMultiDrawElements, mode, count, type,
335                      indices, primcount);
336 }
337
338 void
339 glMultiDrawElementsBaseVertex (GLenum mode, const GLsizei *count,
340                                GLenum type, const GLvoid* *indices,
341                                GLsizei primcount, const GLint *basevertex)
342 {
343         TIMED_DEFER (glMultiDrawElementsBaseVertex, mode, count,
344                      type, indices, primcount, basevertex);
345 }
346
347 void
348 glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type,
349                         const GLvoid* *indices, GLsizei primcount)
350 {
351         TIMED_DEFER (glMultiDrawElementsEXT, mode, count,
352                      type, indices, primcount);
353 }
354
355 void
356 glMultiModeDrawElementsIBM (const GLenum *mode, const GLsizei *count,
357                             GLenum type, const GLvoid* const *indices,
358                             GLsizei primcount, GLint modestride)
359 {
360         TIMED_DEFER (glMultiModeDrawElementsIBM, mode, count,
361                      type, indices, primcount, modestride);
362 }
363
364 /* FIXME?
365 void
366 glMultiDrawElementsIndirect (...)
367 {
368         TIMED_DEFER (glMultiDrawElementsIndirect, ...);
369 }
370 */
371
372 void
373 glMultiDrawElementsIndirectAMD (GLenum mode, GLenum type,
374                                 const GLvoid *indirect,
375                                 GLsizei primcount, GLsizei stride)
376 {
377         TIMED_DEFER (glMultiDrawElementsIndirectAMD, mode, type,
378                      indirect, primcount, stride);
379 }
380
381 void
382 glCallList (GLuint list)
383 {
384         TIMED_DEFER (glCallList, list);
385 }
386
387 void
388 glCallLists (GLsizei n, GLenum type, const GLvoid *lists)
389 {
390         TIMED_DEFER (glCallLists, n, type, lists);
391 }
392
393 void
394 glClear (GLbitfield mask)
395 {
396         TIMED_DEFER (glClear, mask);
397 }
398
399 void
400 glEnd (void)
401 {
402         TIMED_DEFER (glEnd,);
403 }
404
405 void
406 glDrawPixels (GLsizei width, GLsizei height, GLenum format,
407               GLenum type, const GLvoid *pixels)
408 {
409         TIMED_DEFER (glDrawPixels, width, height, format, type, pixels);
410 }
411
412 void
413 glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
414                    GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
415                    GLbitfield mask, GLenum filter)
416 {
417         TIMED_DEFER (glBlitFramebuffer,
418                      srcX0, srcY0, srcX1, srcY1,
419                      dstX0, dstY0, dstX1, dstY1,
420                      mask, filter);
421 }
422
423 void
424 glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
425                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
426                       GLbitfield mask, GLenum filter)
427 {
428         TIMED_DEFER (glBlitFramebufferEXT,
429                      srcX0, srcY0, srcX1, srcY1,
430                      dstX0, dstY0, dstX1, dstY1,
431                      mask, filter);
432 }
433
434 void
435 glUseProgram (GLuint program)
436 {
437         current_context.program = program;
438
439         DEFER(glUseProgram, program);
440 }
441
442 void
443 glUseProgramObjectARB (GLhandleARB programObj)
444 {
445         current_context.program = programObj;
446
447         DEFER(glUseProgramObjectARB, programObj);
448 }
449
450 static void
451 accumulate_program_ticks (unsigned program_id, unsigned ticks)
452 {
453         context_t *ctx = &current_context;
454         unsigned i;
455
456         if (program_id >= ctx->num_program_metrics) {
457                 ctx->program_metrics = realloc (ctx->program_metrics,
458                                                 (program_id + 1) * sizeof (program_metrics_t));
459                 for (i = ctx->num_program_metrics; i < program_id + 1; i++) {
460                         ctx->program_metrics[i].id = i;
461                         ctx->program_metrics[i].ticks = 0.0;
462                 }
463
464                 ctx->num_program_metrics = program_id + 1;
465         }
466
467         ctx->program_metrics[program_id].ticks += ticks;
468 }
469
470 /* FIXME: Should sort the metrics, print out percentages, etc. */
471 static void
472 print_program_metrics (void)
473 {
474         context_t *ctx = &current_context;
475         unsigned i;
476
477         for (i = 0; i < ctx->num_program_metrics; i++) {
478                 if (ctx->program_metrics[i].ticks == 0.0)
479                         continue;
480                 printf ("Program %d:\t%7.2f mega-ticks\n",
481                         i, ctx->program_metrics[i].ticks / 1e6);
482         }
483 }
484
485 void
486 glwrap_end_frame (void)
487 {
488         static int initialized = 0;
489         static int frames;
490         static struct timeval tv_start, tv_now;
491
492         if (! initialized) {
493                 frames = 0;
494                 gettimeofday (&tv_start, NULL);
495                 initialized = 1;
496         }
497
498
499         frames++;
500
501         if (frames % 60 == 0) {
502                 double fps;
503                 gettimeofday (&tv_now, NULL);
504
505                 fps = (double) frames / (tv_now.tv_sec - tv_start.tv_sec +
506                                          (tv_now.tv_usec - tv_start.tv_usec) / 1.0e6);
507
508                 printf("FPS: %.3f\n", fps);
509
510                 print_program_metrics ();
511         }
512
513         /* Consume all counters that are ready. */
514         counter_t *counter = current_context.counter_head;
515
516         while (counter) {
517                 GLint available;
518                 GLuint elapsed;
519
520                 glGetQueryObjectiv (counter->id, GL_QUERY_RESULT_AVAILABLE,
521                                     &available);
522                 if (! available)
523                         break;
524
525                 glGetQueryObjectuiv (counter->id, GL_QUERY_RESULT, &elapsed);
526
527                 accumulate_program_ticks (counter->program, elapsed);
528
529                 current_context.counter_head = counter->next;
530                 if (current_context.counter_head == NULL)
531                         current_context.counter_tail = NULL;
532
533                 glDeleteQueries (1, &counter->id);
534
535                 free (counter);
536                 counter = current_context.counter_head;
537         }
538 }