1 /* Copyright © 2013, Intel Corporation
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:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
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
26 /* The prototypes for some OpenGL functions changed at one point from:
28 * const void* *indices
30 * const void* const coist *indices
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.
36 * To workaround this problem, we simply #define away const altogether
37 * before including gl.h.
39 * Kudos to Keith Packard for suggesting this kludge.
43 #define GL_GLEXT_PROTOTYPES
50 typedef struct counter
57 typedef struct program_metrics
63 typedef struct context
67 counter_t *counter_head;
68 counter_t *counter_tail;
70 unsigned num_program_metrics;
71 program_metrics_t *program_metrics;
74 /* FIXME: Need a map from integers to context objects and track the
75 * current context with glXMakeContextCurrent, eglMakeCurrent, etc. */
77 context_t current_context;
84 counter = malloc (sizeof(counter_t));
85 if (counter == NULL) {
86 fprintf (stderr, "Out of memory\n");
90 glGenQueries (1, &counter->id);
92 counter->program = current_context.program;
95 if (current_context.counter_tail) {
96 current_context.counter_tail->next = counter;
97 current_context.counter_tail = counter;
99 current_context.counter_tail = counter;
100 current_context.counter_head = counter;
107 lookup (const char *name)
109 const char *libgl_filename = "libGL.so.1";
110 static void *libgl_handle = NULL;
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",
121 return dlwrap_real_dlsym (libgl_handle, name);
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__); \
132 /* Execute a glBegineQuery/glEndQuery pair around an OpenGL call. */
133 #define TIMED_DEFER(function,...) do { \
135 counter = add_counter (); \
136 glBeginQuery (GL_TIME_ELAPSED, counter); \
137 DEFER(function, __VA_ARGS__); \
138 glEndQuery (GL_TIME_ELAPSED); \
141 /* Thanks to apitrace source code for the list of OpenGL draw calls. */
143 glDrawArrays (GLenum mode, GLint first, GLsizei count)
145 TIMED_DEFER (glDrawArrays, mode, first, count);
149 glDrawArraysEXT (GLenum mode, GLint first, GLsizei count)
151 TIMED_DEFER (glDrawArraysEXT, mode, first, count);
155 glDrawArraysIndirect (GLenum mode, const GLvoid *indirect)
157 TIMED_DEFER (glDrawArraysIndirect, mode, indirect);
161 glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count,
164 TIMED_DEFER (glDrawArraysInstanced, mode, first, count, primcount);
168 glDrawArraysInstancedARB (GLenum mode, GLint first, GLsizei count,
171 TIMED_DEFER (glDrawArraysInstancedARB, mode, first, count, primcount);
175 glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count,
178 TIMED_DEFER (glDrawArraysInstancedEXT, mode, start, count, primcount);
182 glDrawArraysInstancedBaseInstance (GLenum mode, GLint first, GLsizei count,
183 GLsizei primcount, GLuint baseinstance)
185 TIMED_DEFER (glDrawArraysInstancedBaseInstance, mode,
186 first, count, primcount, baseinstance);
190 glDrawMeshArraysSUN (GLenum mode, GLint first, GLsizei count, GLsizei width)
192 TIMED_DEFER (glDrawMeshArraysSUN, mode, first, count, width);
196 glMultiDrawArrays (GLenum mode, const GLint *first,
197 const GLsizei *count, GLsizei primcount)
199 TIMED_DEFER (glMultiDrawArrays, mode, first, count, primcount);
203 glMultiDrawArraysEXT (GLenum mode, const GLint *first,
204 const GLsizei *count, GLsizei primcount)
206 TIMED_DEFER (glMultiDrawArraysEXT, mode, first, count, primcount);
210 glMultiModeDrawArraysIBM (const GLenum *mode, const GLint *first,
211 const GLsizei *count, GLsizei primcount,
214 TIMED_DEFER (glMultiModeDrawArraysIBM, mode,
215 first, count, primcount, modestride);
220 glMultiDrawArraysIndirect (...)
222 TIMED_DEFER (glMultiDrawArraysIndirect, ...);
227 glMultiDrawArraysIndirectAMD (GLenum mode, const GLvoid *indirect,
228 GLsizei primcount, GLsizei stride)
230 TIMED_DEFER (glMultiDrawArraysIndirectAMD, mode,
231 indirect, primcount, stride);
235 glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
237 TIMED_DEFER (glDrawElements, mode, count, type, indices);
241 glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type,
242 const GLvoid *indices, GLint basevertex)
244 TIMED_DEFER (glDrawElementsBaseVertex, mode, count,
245 type, indices, basevertex);
249 glDrawElementsIndirect (GLenum mode, GLenum type, const GLvoid *indirect)
251 TIMED_DEFER (glDrawElementsIndirect, mode, type, indirect);
255 glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type,
256 const GLvoid *indices, GLsizei primcount)
258 TIMED_DEFER (glDrawElementsInstanced, mode, count,
259 type, indices, primcount);
263 glDrawElementsInstancedARB (GLenum mode, GLsizei count, GLenum type,
264 const GLvoid *indices, GLsizei primcount)
266 TIMED_DEFER (glDrawElementsInstancedARB, mode, count,
267 type, indices, primcount);
271 glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type,
272 const GLvoid *indices, GLsizei primcount)
274 TIMED_DEFER (glDrawElementsInstancedEXT, mode, count,
275 type, indices, primcount);
279 glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type,
280 const GLvoid *indices, GLsizei primcount,
283 TIMED_DEFER (glDrawElementsInstancedBaseVertex, mode, count,
284 type, indices, primcount, basevertex);
288 glDrawElementsInstancedBaseInstance (GLenum mode, GLsizei count, GLenum type,
289 const void *indices, GLsizei primcount,
292 TIMED_DEFER (glDrawElementsInstancedBaseInstance, mode, count, type,
293 indices, primcount, baseinstance);
297 glDrawElementsInstancedBaseVertexBaseInstance (GLenum mode, GLsizei count,
298 GLenum type, const void *indices, GLsizei primcount,
299 GLint basevertex, GLuint baseinstance)
301 TIMED_DEFER (glDrawElementsInstancedBaseVertexBaseInstance, mode,
302 count, type, indices, primcount, basevertex, baseinstance);
306 glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count,
307 GLenum type, const GLvoid *indices)
309 TIMED_DEFER (glDrawRangeElements, mode, start, end,
310 count, type, indices);
314 glDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint end, GLsizei count,
315 GLenum type, const GLvoid *indices)
317 TIMED_DEFER (glDrawRangeElementsEXT, mode, start, end,
318 count, type, indices);
322 glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end,
323 GLsizei count, GLenum type,
324 const GLvoid *indices, GLint basevertex)
326 TIMED_DEFER (glDrawRangeElementsBaseVertex, mode, start, end,
327 count, type, indices, basevertex);
331 glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type,
332 const GLvoid* *indices, GLsizei primcount)
334 TIMED_DEFER (glMultiDrawElements, mode, count, type,
339 glMultiDrawElementsBaseVertex (GLenum mode, const GLsizei *count,
340 GLenum type, const GLvoid* *indices,
341 GLsizei primcount, const GLint *basevertex)
343 TIMED_DEFER (glMultiDrawElementsBaseVertex, mode, count,
344 type, indices, primcount, basevertex);
348 glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type,
349 const GLvoid* *indices, GLsizei primcount)
351 TIMED_DEFER (glMultiDrawElementsEXT, mode, count,
352 type, indices, primcount);
356 glMultiModeDrawElementsIBM (const GLenum *mode, const GLsizei *count,
357 GLenum type, const GLvoid* const *indices,
358 GLsizei primcount, GLint modestride)
360 TIMED_DEFER (glMultiModeDrawElementsIBM, mode, count,
361 type, indices, primcount, modestride);
366 glMultiDrawElementsIndirect (...)
368 TIMED_DEFER (glMultiDrawElementsIndirect, ...);
373 glMultiDrawElementsIndirectAMD (GLenum mode, GLenum type,
374 const GLvoid *indirect,
375 GLsizei primcount, GLsizei stride)
377 TIMED_DEFER (glMultiDrawElementsIndirectAMD, mode, type,
378 indirect, primcount, stride);
382 glCallList (GLuint list)
384 TIMED_DEFER (glCallList, list);
388 glCallLists (GLsizei n, GLenum type, const GLvoid *lists)
390 TIMED_DEFER (glCallLists, n, type, lists);
394 glClear (GLbitfield mask)
396 TIMED_DEFER (glClear, mask);
402 TIMED_DEFER (glEnd,);
406 glDrawPixels (GLsizei width, GLsizei height, GLenum format,
407 GLenum type, const GLvoid *pixels)
409 TIMED_DEFER (glDrawPixels, width, height, format, type, pixels);
413 glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
414 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
415 GLbitfield mask, GLenum filter)
417 TIMED_DEFER (glBlitFramebuffer,
418 srcX0, srcY0, srcX1, srcY1,
419 dstX0, dstY0, dstX1, dstY1,
424 glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
425 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
426 GLbitfield mask, GLenum filter)
428 TIMED_DEFER (glBlitFramebufferEXT,
429 srcX0, srcY0, srcX1, srcY1,
430 dstX0, dstY0, dstX1, dstY1,
435 glUseProgram (GLuint program)
437 current_context.program = program;
439 DEFER(glUseProgram, program);
443 glUseProgramObjectARB (GLhandleARB programObj)
445 current_context.program = programObj;
447 DEFER(glUseProgramObjectARB, programObj);
451 accumulate_program_ticks (unsigned program_id, unsigned ticks)
453 context_t *ctx = ¤t_context;
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;
464 ctx->num_program_metrics = program_id + 1;
467 ctx->program_metrics[program_id].ticks += ticks;
470 /* FIXME: Should sort the metrics, print out percentages, etc. */
472 print_program_metrics (void)
474 context_t *ctx = ¤t_context;
477 for (i = 0; i < ctx->num_program_metrics; i++) {
478 if (ctx->program_metrics[i].ticks == 0.0)
480 printf ("Program %d:\t%7.2f mega-ticks\n",
481 i, ctx->program_metrics[i].ticks / 1e6);
486 glwrap_end_frame (void)
488 static int initialized = 0;
490 static struct timeval tv_start, tv_now;
494 gettimeofday (&tv_start, NULL);
501 if (frames % 60 == 0) {
503 gettimeofday (&tv_now, NULL);
505 fps = (double) frames / (tv_now.tv_sec - tv_start.tv_sec +
506 (tv_now.tv_usec - tv_start.tv_usec) / 1.0e6);
508 printf("FPS: %.3f\n", fps);
510 print_program_metrics ();
513 /* Consume all counters that are ready. */
514 counter_t *counter = current_context.counter_head;
520 glGetQueryObjectiv (counter->id, GL_QUERY_RESULT_AVAILABLE,
525 glGetQueryObjectuiv (counter->id, GL_QUERY_RESULT, &elapsed);
527 accumulate_program_ticks (counter->program, elapsed);
529 current_context.counter_head = counter->next;
530 if (current_context.counter_head == NULL)
531 current_context.counter_tail = NULL;
533 glDeleteQueries (1, &counter->id);
536 counter = current_context.counter_head;