]> git.cworth.org Git - fips/blob - glwrap.c
Reduce code duplication with with new 'glwrap_lookup' function.
[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 void *
107 glwrap_lookup (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 /* Execute a glBegineQuery/glEndQuery pair around an OpenGL call. */
125 #define TIMED_DEFER(function,...) do {                  \
126         unsigned counter;                               \
127         counter = add_counter ();                       \
128         glBeginQuery (GL_TIME_ELAPSED, counter);        \
129         GLWRAP_DEFER(function, __VA_ARGS__);            \
130         glEndQuery (GL_TIME_ELAPSED);                   \
131 } while (0);
132
133 /* Thanks to apitrace source code for the list of OpenGL draw calls. */
134 void
135 glDrawArrays (GLenum mode, GLint first, GLsizei count)
136 {
137         TIMED_DEFER (glDrawArrays, mode, first, count);
138 }
139
140 void
141 glDrawArraysEXT (GLenum mode, GLint first, GLsizei count)
142 {
143         TIMED_DEFER (glDrawArraysEXT, mode, first, count);
144 }
145
146 void
147 glDrawArraysIndirect (GLenum mode, const GLvoid *indirect)
148 {
149         TIMED_DEFER (glDrawArraysIndirect, mode, indirect);
150 }
151
152 void
153 glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count,
154                        GLsizei primcount)
155 {
156         TIMED_DEFER (glDrawArraysInstanced, mode, first, count, primcount);
157 }
158
159 void
160 glDrawArraysInstancedARB (GLenum mode, GLint first, GLsizei count,
161                           GLsizei primcount)
162 {
163         TIMED_DEFER (glDrawArraysInstancedARB, mode, first, count, primcount);
164 }
165
166 void
167 glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count,
168                           GLsizei primcount)
169 {
170         TIMED_DEFER (glDrawArraysInstancedEXT, mode, start, count, primcount);
171 }
172
173 void
174 glDrawArraysInstancedBaseInstance (GLenum mode, GLint first, GLsizei count,
175                                    GLsizei primcount, GLuint baseinstance)
176 {
177         TIMED_DEFER (glDrawArraysInstancedBaseInstance, mode,
178                      first, count, primcount, baseinstance);
179 }
180
181 void
182 glDrawMeshArraysSUN (GLenum mode, GLint first, GLsizei count, GLsizei width)
183 {
184         TIMED_DEFER (glDrawMeshArraysSUN, mode, first, count, width);
185 }
186
187 void
188 glMultiDrawArrays (GLenum mode, const GLint *first,
189                    const GLsizei *count, GLsizei primcount)
190 {
191         TIMED_DEFER (glMultiDrawArrays, mode, first, count, primcount);
192 }
193
194 void
195 glMultiDrawArraysEXT (GLenum mode, const GLint *first,
196                       const GLsizei *count, GLsizei primcount)
197 {
198         TIMED_DEFER (glMultiDrawArraysEXT, mode, first, count, primcount);
199 }
200
201 void
202 glMultiModeDrawArraysIBM (const GLenum *mode, const GLint *first,
203                           const GLsizei *count, GLsizei primcount,
204                           GLint modestride)
205 {
206         TIMED_DEFER (glMultiModeDrawArraysIBM, mode,
207                      first, count, primcount, modestride);
208 }
209
210 /* FIXME?
211 void
212 glMultiDrawArraysIndirect (...)
213 {
214         TIMED_DEFER (glMultiDrawArraysIndirect, ...);
215 }
216 */
217
218 void
219 glMultiDrawArraysIndirectAMD (GLenum mode, const GLvoid *indirect,
220                               GLsizei primcount, GLsizei stride)
221 {
222         TIMED_DEFER (glMultiDrawArraysIndirectAMD, mode,
223                      indirect, primcount, stride);
224 }
225
226 void
227 glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
228 {
229         TIMED_DEFER (glDrawElements, mode, count, type, indices);
230 }
231
232 void
233 glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type,
234                           const GLvoid *indices, GLint basevertex)
235 {
236         TIMED_DEFER (glDrawElementsBaseVertex, mode, count,
237                      type, indices, basevertex);
238 }
239
240 void
241 glDrawElementsIndirect (GLenum mode, GLenum type, const GLvoid *indirect)
242 {
243         TIMED_DEFER (glDrawElementsIndirect, mode, type, indirect);
244 }
245
246 void
247 glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type,
248                          const GLvoid *indices, GLsizei primcount)
249 {
250         TIMED_DEFER (glDrawElementsInstanced, mode, count,
251                      type, indices, primcount);
252 }
253
254 void
255 glDrawElementsInstancedARB (GLenum mode, GLsizei count, GLenum type,
256                             const GLvoid *indices, GLsizei primcount)
257 {
258         TIMED_DEFER (glDrawElementsInstancedARB, mode, count,
259                      type, indices, primcount);
260 }
261
262 void
263 glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type,
264                             const GLvoid *indices, GLsizei primcount)
265 {
266         TIMED_DEFER (glDrawElementsInstancedEXT, mode, count,
267                      type, indices, primcount);
268 }
269
270 void
271 glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type,
272                                    const GLvoid *indices, GLsizei primcount,
273                                    GLint basevertex)
274 {
275         TIMED_DEFER (glDrawElementsInstancedBaseVertex, mode, count,
276                      type, indices, primcount, basevertex);
277 }
278
279 void
280 glDrawElementsInstancedBaseInstance (GLenum mode, GLsizei count, GLenum type,
281                                      const void *indices, GLsizei primcount,
282                                      GLuint baseinstance)
283 {
284         TIMED_DEFER (glDrawElementsInstancedBaseInstance, mode, count, type,
285                      indices, primcount, baseinstance);
286 }
287
288 void
289 glDrawElementsInstancedBaseVertexBaseInstance (GLenum mode, GLsizei count,
290                       GLenum type, const void *indices, GLsizei primcount,
291                       GLint basevertex, GLuint baseinstance)
292 {
293         TIMED_DEFER (glDrawElementsInstancedBaseVertexBaseInstance, mode,
294                      count, type, indices, primcount, basevertex, baseinstance);
295 }
296
297 void
298 glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count,
299                      GLenum type, const GLvoid *indices)
300 {
301         TIMED_DEFER (glDrawRangeElements, mode, start, end,
302                      count, type, indices);
303 }
304
305 void
306 glDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint end, GLsizei count,
307                         GLenum type, const GLvoid *indices)
308 {
309         TIMED_DEFER (glDrawRangeElementsEXT, mode, start, end,
310                      count, type, indices);
311 }
312
313 void
314 glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end,
315                                GLsizei count, GLenum type,
316                                const GLvoid *indices, GLint basevertex)
317 {
318         TIMED_DEFER (glDrawRangeElementsBaseVertex, mode, start, end,
319                      count, type, indices, basevertex);
320 }
321
322 void
323 glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type,
324                      const GLvoid* *indices, GLsizei primcount)
325 {
326         TIMED_DEFER (glMultiDrawElements, mode, count, type,
327                      indices, primcount);
328 }
329
330 void
331 glMultiDrawElementsBaseVertex (GLenum mode, const GLsizei *count,
332                                GLenum type, const GLvoid* *indices,
333                                GLsizei primcount, const GLint *basevertex)
334 {
335         TIMED_DEFER (glMultiDrawElementsBaseVertex, mode, count,
336                      type, indices, primcount, basevertex);
337 }
338
339 void
340 glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type,
341                         const GLvoid* *indices, GLsizei primcount)
342 {
343         TIMED_DEFER (glMultiDrawElementsEXT, mode, count,
344                      type, indices, primcount);
345 }
346
347 void
348 glMultiModeDrawElementsIBM (const GLenum *mode, const GLsizei *count,
349                             GLenum type, const GLvoid* const *indices,
350                             GLsizei primcount, GLint modestride)
351 {
352         TIMED_DEFER (glMultiModeDrawElementsIBM, mode, count,
353                      type, indices, primcount, modestride);
354 }
355
356 /* FIXME?
357 void
358 glMultiDrawElementsIndirect (...)
359 {
360         TIMED_DEFER (glMultiDrawElementsIndirect, ...);
361 }
362 */
363
364 void
365 glMultiDrawElementsIndirectAMD (GLenum mode, GLenum type,
366                                 const GLvoid *indirect,
367                                 GLsizei primcount, GLsizei stride)
368 {
369         TIMED_DEFER (glMultiDrawElementsIndirectAMD, mode, type,
370                      indirect, primcount, stride);
371 }
372
373 void
374 glCallList (GLuint list)
375 {
376         TIMED_DEFER (glCallList, list);
377 }
378
379 void
380 glCallLists (GLsizei n, GLenum type, const GLvoid *lists)
381 {
382         TIMED_DEFER (glCallLists, n, type, lists);
383 }
384
385 void
386 glClear (GLbitfield mask)
387 {
388         TIMED_DEFER (glClear, mask);
389 }
390
391 void
392 glEnd (void)
393 {
394         TIMED_DEFER (glEnd,);
395 }
396
397 void
398 glDrawPixels (GLsizei width, GLsizei height, GLenum format,
399               GLenum type, const GLvoid *pixels)
400 {
401         TIMED_DEFER (glDrawPixels, width, height, format, type, pixels);
402 }
403
404 void
405 glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
406                    GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
407                    GLbitfield mask, GLenum filter)
408 {
409         TIMED_DEFER (glBlitFramebuffer,
410                      srcX0, srcY0, srcX1, srcY1,
411                      dstX0, dstY0, dstX1, dstY1,
412                      mask, filter);
413 }
414
415 void
416 glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
417                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
418                       GLbitfield mask, GLenum filter)
419 {
420         TIMED_DEFER (glBlitFramebufferEXT,
421                      srcX0, srcY0, srcX1, srcY1,
422                      dstX0, dstY0, dstX1, dstY1,
423                      mask, filter);
424 }
425
426 void
427 glUseProgram (GLuint program)
428 {
429         current_context.program = program;
430
431         GLWRAP_DEFER(glUseProgram, program);
432 }
433
434 void
435 glUseProgramObjectARB (GLhandleARB programObj)
436 {
437         current_context.program = programObj;
438
439         GLWRAP_DEFER(glUseProgramObjectARB, programObj);
440 }
441
442 static void
443 accumulate_program_ticks (unsigned program_id, unsigned ticks)
444 {
445         context_t *ctx = &current_context;
446         unsigned i;
447
448         if (program_id >= ctx->num_program_metrics) {
449                 ctx->program_metrics = realloc (ctx->program_metrics,
450                                                 (program_id + 1) * sizeof (program_metrics_t));
451                 for (i = ctx->num_program_metrics; i < program_id + 1; i++) {
452                         ctx->program_metrics[i].id = i;
453                         ctx->program_metrics[i].ticks = 0.0;
454                 }
455
456                 ctx->num_program_metrics = program_id + 1;
457         }
458
459         ctx->program_metrics[program_id].ticks += ticks;
460 }
461
462 /* FIXME: Should sort the metrics, print out percentages, etc. */
463 static void
464 print_program_metrics (void)
465 {
466         context_t *ctx = &current_context;
467         unsigned i;
468
469         for (i = 0; i < ctx->num_program_metrics; i++) {
470                 if (ctx->program_metrics[i].ticks == 0.0)
471                         continue;
472                 printf ("Program %d:\t%7.2f mega-ticks\n",
473                         i, ctx->program_metrics[i].ticks / 1e6);
474         }
475 }
476
477 void
478 glwrap_end_frame (void)
479 {
480         static int initialized = 0;
481         static int frames;
482         static struct timeval tv_start, tv_now;
483
484         if (! initialized) {
485                 frames = 0;
486                 gettimeofday (&tv_start, NULL);
487                 initialized = 1;
488         }
489
490
491         frames++;
492
493         if (frames % 60 == 0) {
494                 double fps;
495                 gettimeofday (&tv_now, NULL);
496
497                 fps = (double) frames / (tv_now.tv_sec - tv_start.tv_sec +
498                                          (tv_now.tv_usec - tv_start.tv_usec) / 1.0e6);
499
500                 printf("FPS: %.3f\n", fps);
501
502                 print_program_metrics ();
503         }
504
505         /* Consume all counters that are ready. */
506         counter_t *counter = current_context.counter_head;
507
508         while (counter) {
509                 GLint available;
510                 GLuint elapsed;
511
512                 glGetQueryObjectiv (counter->id, GL_QUERY_RESULT_AVAILABLE,
513                                     &available);
514                 if (! available)
515                         break;
516
517                 glGetQueryObjectuiv (counter->id, GL_QUERY_RESULT, &elapsed);
518
519                 accumulate_program_ticks (counter->program, elapsed);
520
521                 current_context.counter_head = counter->next;
522                 if (current_context.counter_head == NULL)
523                         current_context.counter_tail = NULL;
524
525                 glDeleteQueries (1, &counter->id);
526
527                 free (counter);
528                 counter = current_context.counter_head;
529         }
530 }