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 glwrap_lookup (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 /* Execute a glBegineQuery/glEndQuery pair around an OpenGL call. */
125 #define TIMED_DEFER(function,...) do { \
127 counter = add_counter (); \
128 glBeginQuery (GL_TIME_ELAPSED, counter); \
129 GLWRAP_DEFER(function, __VA_ARGS__); \
130 glEndQuery (GL_TIME_ELAPSED); \
133 /* Thanks to apitrace source code for the list of OpenGL draw calls. */
135 glDrawArrays (GLenum mode, GLint first, GLsizei count)
137 TIMED_DEFER (glDrawArrays, mode, first, count);
141 glDrawArraysEXT (GLenum mode, GLint first, GLsizei count)
143 TIMED_DEFER (glDrawArraysEXT, mode, first, count);
147 glDrawArraysIndirect (GLenum mode, const GLvoid *indirect)
149 TIMED_DEFER (glDrawArraysIndirect, mode, indirect);
153 glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count,
156 TIMED_DEFER (glDrawArraysInstanced, mode, first, count, primcount);
160 glDrawArraysInstancedARB (GLenum mode, GLint first, GLsizei count,
163 TIMED_DEFER (glDrawArraysInstancedARB, mode, first, count, primcount);
167 glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count,
170 TIMED_DEFER (glDrawArraysInstancedEXT, mode, start, count, primcount);
174 glDrawArraysInstancedBaseInstance (GLenum mode, GLint first, GLsizei count,
175 GLsizei primcount, GLuint baseinstance)
177 TIMED_DEFER (glDrawArraysInstancedBaseInstance, mode,
178 first, count, primcount, baseinstance);
182 glDrawMeshArraysSUN (GLenum mode, GLint first, GLsizei count, GLsizei width)
184 TIMED_DEFER (glDrawMeshArraysSUN, mode, first, count, width);
188 glMultiDrawArrays (GLenum mode, const GLint *first,
189 const GLsizei *count, GLsizei primcount)
191 TIMED_DEFER (glMultiDrawArrays, mode, first, count, primcount);
195 glMultiDrawArraysEXT (GLenum mode, const GLint *first,
196 const GLsizei *count, GLsizei primcount)
198 TIMED_DEFER (glMultiDrawArraysEXT, mode, first, count, primcount);
202 glMultiModeDrawArraysIBM (const GLenum *mode, const GLint *first,
203 const GLsizei *count, GLsizei primcount,
206 TIMED_DEFER (glMultiModeDrawArraysIBM, mode,
207 first, count, primcount, modestride);
212 glMultiDrawArraysIndirect (...)
214 TIMED_DEFER (glMultiDrawArraysIndirect, ...);
219 glMultiDrawArraysIndirectAMD (GLenum mode, const GLvoid *indirect,
220 GLsizei primcount, GLsizei stride)
222 TIMED_DEFER (glMultiDrawArraysIndirectAMD, mode,
223 indirect, primcount, stride);
227 glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
229 TIMED_DEFER (glDrawElements, mode, count, type, indices);
233 glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type,
234 const GLvoid *indices, GLint basevertex)
236 TIMED_DEFER (glDrawElementsBaseVertex, mode, count,
237 type, indices, basevertex);
241 glDrawElementsIndirect (GLenum mode, GLenum type, const GLvoid *indirect)
243 TIMED_DEFER (glDrawElementsIndirect, mode, type, indirect);
247 glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type,
248 const GLvoid *indices, GLsizei primcount)
250 TIMED_DEFER (glDrawElementsInstanced, mode, count,
251 type, indices, primcount);
255 glDrawElementsInstancedARB (GLenum mode, GLsizei count, GLenum type,
256 const GLvoid *indices, GLsizei primcount)
258 TIMED_DEFER (glDrawElementsInstancedARB, mode, count,
259 type, indices, primcount);
263 glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type,
264 const GLvoid *indices, GLsizei primcount)
266 TIMED_DEFER (glDrawElementsInstancedEXT, mode, count,
267 type, indices, primcount);
271 glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type,
272 const GLvoid *indices, GLsizei primcount,
275 TIMED_DEFER (glDrawElementsInstancedBaseVertex, mode, count,
276 type, indices, primcount, basevertex);
280 glDrawElementsInstancedBaseInstance (GLenum mode, GLsizei count, GLenum type,
281 const void *indices, GLsizei primcount,
284 TIMED_DEFER (glDrawElementsInstancedBaseInstance, mode, count, type,
285 indices, primcount, baseinstance);
289 glDrawElementsInstancedBaseVertexBaseInstance (GLenum mode, GLsizei count,
290 GLenum type, const void *indices, GLsizei primcount,
291 GLint basevertex, GLuint baseinstance)
293 TIMED_DEFER (glDrawElementsInstancedBaseVertexBaseInstance, mode,
294 count, type, indices, primcount, basevertex, baseinstance);
298 glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count,
299 GLenum type, const GLvoid *indices)
301 TIMED_DEFER (glDrawRangeElements, mode, start, end,
302 count, type, indices);
306 glDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint end, GLsizei count,
307 GLenum type, const GLvoid *indices)
309 TIMED_DEFER (glDrawRangeElementsEXT, mode, start, end,
310 count, type, indices);
314 glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end,
315 GLsizei count, GLenum type,
316 const GLvoid *indices, GLint basevertex)
318 TIMED_DEFER (glDrawRangeElementsBaseVertex, mode, start, end,
319 count, type, indices, basevertex);
323 glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type,
324 const GLvoid* *indices, GLsizei primcount)
326 TIMED_DEFER (glMultiDrawElements, mode, count, type,
331 glMultiDrawElementsBaseVertex (GLenum mode, const GLsizei *count,
332 GLenum type, const GLvoid* *indices,
333 GLsizei primcount, const GLint *basevertex)
335 TIMED_DEFER (glMultiDrawElementsBaseVertex, mode, count,
336 type, indices, primcount, basevertex);
340 glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type,
341 const GLvoid* *indices, GLsizei primcount)
343 TIMED_DEFER (glMultiDrawElementsEXT, mode, count,
344 type, indices, primcount);
348 glMultiModeDrawElementsIBM (const GLenum *mode, const GLsizei *count,
349 GLenum type, const GLvoid* const *indices,
350 GLsizei primcount, GLint modestride)
352 TIMED_DEFER (glMultiModeDrawElementsIBM, mode, count,
353 type, indices, primcount, modestride);
358 glMultiDrawElementsIndirect (...)
360 TIMED_DEFER (glMultiDrawElementsIndirect, ...);
365 glMultiDrawElementsIndirectAMD (GLenum mode, GLenum type,
366 const GLvoid *indirect,
367 GLsizei primcount, GLsizei stride)
369 TIMED_DEFER (glMultiDrawElementsIndirectAMD, mode, type,
370 indirect, primcount, stride);
374 glCallList (GLuint list)
376 TIMED_DEFER (glCallList, list);
380 glCallLists (GLsizei n, GLenum type, const GLvoid *lists)
382 TIMED_DEFER (glCallLists, n, type, lists);
386 glClear (GLbitfield mask)
388 TIMED_DEFER (glClear, mask);
394 TIMED_DEFER (glEnd,);
398 glDrawPixels (GLsizei width, GLsizei height, GLenum format,
399 GLenum type, const GLvoid *pixels)
401 TIMED_DEFER (glDrawPixels, width, height, format, type, pixels);
405 glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
406 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
407 GLbitfield mask, GLenum filter)
409 TIMED_DEFER (glBlitFramebuffer,
410 srcX0, srcY0, srcX1, srcY1,
411 dstX0, dstY0, dstX1, dstY1,
416 glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
417 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
418 GLbitfield mask, GLenum filter)
420 TIMED_DEFER (glBlitFramebufferEXT,
421 srcX0, srcY0, srcX1, srcY1,
422 dstX0, dstY0, dstX1, dstY1,
427 glUseProgram (GLuint program)
429 current_context.program = program;
431 GLWRAP_DEFER(glUseProgram, program);
435 glUseProgramObjectARB (GLhandleARB programObj)
437 current_context.program = programObj;
439 GLWRAP_DEFER(glUseProgramObjectARB, programObj);
443 accumulate_program_ticks (unsigned program_id, unsigned ticks)
445 context_t *ctx = ¤t_context;
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;
456 ctx->num_program_metrics = program_id + 1;
459 ctx->program_metrics[program_id].ticks += ticks;
462 /* FIXME: Should sort the metrics, print out percentages, etc. */
464 print_program_metrics (void)
466 context_t *ctx = ¤t_context;
469 for (i = 0; i < ctx->num_program_metrics; i++) {
470 if (ctx->program_metrics[i].ticks == 0.0)
472 printf ("Program %d:\t%7.2f mega-ticks\n",
473 i, ctx->program_metrics[i].ticks / 1e6);
478 glwrap_end_frame (void)
480 static int initialized = 0;
482 static struct timeval tv_start, tv_now;
486 gettimeofday (&tv_start, NULL);
493 if (frames % 60 == 0) {
495 gettimeofday (&tv_now, NULL);
497 fps = (double) frames / (tv_now.tv_sec - tv_start.tv_sec +
498 (tv_now.tv_usec - tv_start.tv_usec) / 1.0e6);
500 printf("FPS: %.3f\n", fps);
502 print_program_metrics ();
505 /* Consume all counters that are ready. */
506 counter_t *counter = current_context.counter_head;
512 glGetQueryObjectiv (counter->id, GL_QUERY_RESULT_AVAILABLE,
517 glGetQueryObjectuiv (counter->id, GL_QUERY_RESULT, &elapsed);
519 accumulate_program_ticks (counter->program, elapsed);
521 current_context.counter_head = counter->next;
522 if (current_context.counter_head == NULL)
523 current_context.counter_tail = NULL;
525 glDeleteQueries (1, &counter->id);
528 counter = current_context.counter_head;