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 #define GL_GLEXT_PROTOTYPES
33 typedef struct counter
40 typedef struct program_metrics
46 typedef struct context
50 counter_t *counter_head;
51 counter_t *counter_tail;
53 unsigned num_program_metrics;
54 program_metrics_t *program_metrics;
57 /* FIXME: Need a map from integers to context objects and track the
58 * current context with glXMakeContextCurrent, eglMakeCurrent, etc. */
60 context_t current_context;
67 counter = malloc (sizeof(counter_t));
68 if (counter == NULL) {
69 fprintf (stderr, "Out of memory\n");
73 glGenQueries (1, &counter->id);
75 counter->program = current_context.program;
78 if (current_context.counter_tail) {
79 current_context.counter_tail->next = counter;
80 current_context.counter_tail = counter;
82 current_context.counter_tail = counter;
83 current_context.counter_head = counter;
90 lookup (const char *name)
92 const char *libgl_filename = "libGL.so.1";
93 static void *libgl_handle = NULL;
96 libgl_handle = dlwrap_real_dlopen (libgl_filename, RTLD_NOW | RTLD_DEEPBIND);
98 fprintf (stderr, "Error: Failed to dlopen %s\n",
104 return dlwrap_real_dlsym (libgl_handle, name);
107 /* Defer to the underlying, ''real'' function to do the real work. */
108 #define DEFER(function,...) do { \
109 static typeof(&function) real_ ## function; \
110 if (! real_ ## function) \
111 real_ ## function = lookup (#function); \
112 real_ ## function(__VA_ARGS__); \
115 /* Execute a glBegineQuery/glEndQuery pair around an OpenGL call. */
116 #define TIMED_DEFER(function,...) do { \
118 counter = add_counter (); \
119 glBeginQuery (GL_TIME_ELAPSED, counter); \
120 DEFER(function, __VA_ARGS__); \
121 glEndQuery (GL_TIME_ELAPSED); \
124 /* Thanks to apitrace source code for the list of OpenGL draw calls. */
126 glDrawArrays (GLenum mode, GLint first, GLsizei count)
128 TIMED_DEFER (glDrawArrays, mode, first, count);
132 glDrawArraysEXT (GLenum mode, GLint first, GLsizei count)
134 TIMED_DEFER (glDrawArraysEXT, mode, first, count);
138 glDrawArraysIndirect (GLenum mode, const GLvoid *indirect)
140 TIMED_DEFER (glDrawArraysIndirect, mode, indirect);
144 glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count,
147 TIMED_DEFER (glDrawArraysInstanced, mode, first, count, primcount);
151 glDrawArraysInstancedARB (GLenum mode, GLint first, GLsizei count,
154 TIMED_DEFER (glDrawArraysInstancedARB, mode, first, count, primcount);
158 glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count,
161 TIMED_DEFER (glDrawArraysInstancedEXT, mode, start, count, primcount);
165 glDrawArraysInstancedBaseInstance (GLenum mode, GLint first, GLsizei count,
166 GLsizei primcount, GLuint baseinstance)
168 TIMED_DEFER (glDrawArraysInstancedBaseInstance, mode,
169 first, count, primcount, baseinstance);
173 glDrawMeshArraysSUN (GLenum mode, GLint first, GLsizei count, GLsizei width)
175 TIMED_DEFER (glDrawMeshArraysSUN, mode, first, count, width);
179 glMultiDrawArrays (GLenum mode, const GLint *first,
180 const GLsizei *count, GLsizei primcount)
182 TIMED_DEFER (glMultiDrawArrays, mode, first, count, primcount);
186 glMultiDrawArraysEXT (GLenum mode, const GLint *first,
187 const GLsizei *count, GLsizei primcount)
189 TIMED_DEFER (glMultiDrawArraysEXT, mode, first, count, primcount);
193 glMultiModeDrawArraysIBM (const GLenum *mode, const GLint *first,
194 const GLsizei *count, GLsizei primcount,
197 TIMED_DEFER (glMultiModeDrawArraysIBM, mode,
198 first, count, primcount, modestride);
203 glMultiDrawArraysIndirect (...)
205 TIMED_DEFER (glMultiDrawArraysIndirect, ...);
210 glMultiDrawArraysIndirectAMD (GLenum mode, const GLvoid *indirect,
211 GLsizei primcount, GLsizei stride)
213 TIMED_DEFER (glMultiDrawArraysIndirectAMD, mode,
214 indirect, primcount, stride);
218 glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
220 TIMED_DEFER (glDrawElements, mode, count, type, indices);
224 glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type,
225 const GLvoid *indices, GLint basevertex)
227 TIMED_DEFER (glDrawElementsBaseVertex, mode, count,
228 type, indices, basevertex);
232 glDrawElementsIndirect (GLenum mode, GLenum type, const GLvoid *indirect)
234 TIMED_DEFER (glDrawElementsIndirect, mode, type, indirect);
238 glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type,
239 const GLvoid *indices, GLsizei primcount)
241 TIMED_DEFER (glDrawElementsInstanced, mode, count,
242 type, indices, primcount);
246 glDrawElementsInstancedARB (GLenum mode, GLsizei count, GLenum type,
247 const GLvoid *indices, GLsizei primcount)
249 TIMED_DEFER (glDrawElementsInstancedARB, mode, count,
250 type, indices, primcount);
254 glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type,
255 const GLvoid *indices, GLsizei primcount)
257 TIMED_DEFER (glDrawElementsInstancedEXT, mode, count,
258 type, indices, primcount);
262 glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type,
263 const GLvoid *indices, GLsizei primcount,
266 TIMED_DEFER (glDrawElementsInstancedBaseVertex, mode, count,
267 type, indices, primcount, basevertex);
271 glDrawElementsInstancedBaseInstance (GLenum mode, GLsizei count, GLenum type,
272 const void *indices, GLsizei primcount,
275 TIMED_DEFER (glDrawElementsInstancedBaseInstance, mode, count, type,
276 indices, primcount, baseinstance);
280 glDrawElementsInstancedBaseVertexBaseInstance (GLenum mode, GLsizei count,
281 GLenum type, const void *indices, GLsizei primcount,
282 GLint basevertex, GLuint baseinstance)
284 TIMED_DEFER (glDrawElementsInstancedBaseVertexBaseInstance, mode,
285 count, type, indices, primcount, basevertex, baseinstance);
289 glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count,
290 GLenum type, const GLvoid *indices)
292 TIMED_DEFER (glDrawRangeElements, mode, start, end,
293 count, type, indices);
297 glDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint end, GLsizei count,
298 GLenum type, const GLvoid *indices)
300 TIMED_DEFER (glDrawRangeElementsEXT, mode, start, end,
301 count, type, indices);
305 glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end,
306 GLsizei count, GLenum type,
307 const GLvoid *indices, GLint basevertex)
309 TIMED_DEFER (glDrawRangeElementsBaseVertex, mode, start, end,
310 count, type, indices, basevertex);
314 glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type,
315 const GLvoid* *indices, GLsizei primcount)
317 TIMED_DEFER (glMultiDrawElements, mode, count, type,
322 glMultiDrawElementsBaseVertex (GLenum mode, const GLsizei *count,
323 GLenum type, const GLvoid* *indices,
324 GLsizei primcount, const GLint *basevertex)
326 TIMED_DEFER (glMultiDrawElementsBaseVertex, mode, count,
327 type, indices, primcount, basevertex);
331 glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type,
332 const GLvoid* *indices, GLsizei primcount)
334 TIMED_DEFER (glMultiDrawElementsEXT, mode, count,
335 type, indices, primcount);
339 glMultiModeDrawElementsIBM (const GLenum *mode, const GLsizei *count,
340 GLenum type, const GLvoid* const *indices,
341 GLsizei primcount, GLint modestride)
343 TIMED_DEFER (glMultiModeDrawElementsIBM, mode, count,
344 type, indices, primcount, modestride);
349 glMultiDrawElementsIndirect (...)
351 TIMED_DEFER (glMultiDrawElementsIndirect, ...);
356 glMultiDrawElementsIndirectAMD (GLenum mode, GLenum type,
357 const GLvoid *indirect,
358 GLsizei primcount, GLsizei stride)
360 TIMED_DEFER (glMultiDrawElementsIndirectAMD, mode, type,
361 indirect, primcount, stride);
365 glCallList (GLuint list)
367 TIMED_DEFER (glCallList, list);
371 glCallLists (GLsizei n, GLenum type, const GLvoid *lists)
373 TIMED_DEFER (glCallLists, n, type, lists);
377 glClear (GLbitfield mask)
379 TIMED_DEFER (glClear, mask);
385 TIMED_DEFER (glEnd,);
389 glDrawPixels (GLsizei width, GLsizei height, GLenum format,
390 GLenum type, const GLvoid *pixels)
392 TIMED_DEFER (glDrawPixels, width, height, format, type, pixels);
396 glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
397 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
398 GLbitfield mask, GLenum filter)
400 TIMED_DEFER (glBlitFramebuffer,
401 srcX0, srcY0, srcX1, srcY1,
402 dstX0, dstY0, dstX1, dstY1,
407 glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
408 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
409 GLbitfield mask, GLenum filter)
411 TIMED_DEFER (glBlitFramebufferEXT,
412 srcX0, srcY0, srcX1, srcY1,
413 dstX0, dstY0, dstX1, dstY1,
418 glUseProgram (GLuint program)
420 current_context.program = program;
422 DEFER(glUseProgram, program);
426 glUseProgramObjectARB (GLhandleARB programObj)
428 current_context.program = programObj;
430 DEFER(glUseProgramObjectARB, programObj);
434 accumulate_program_ticks (unsigned program_id, unsigned ticks)
436 context_t *ctx = ¤t_context;
439 if (program_id >= ctx->num_program_metrics) {
440 ctx->program_metrics = realloc (ctx->program_metrics,
441 (program_id + 1) * sizeof (program_metrics_t));
442 for (i = ctx->num_program_metrics; i < program_id + 1; i++) {
443 ctx->program_metrics[i].id = i;
444 ctx->program_metrics[i].ticks = 0.0;
447 ctx->num_program_metrics = program_id + 1;
450 ctx->program_metrics[program_id].ticks += ticks;
453 /* FIXME: Should sort the metrics, print out percentages, etc. */
455 print_program_metrics (void)
457 context_t *ctx = ¤t_context;
460 for (i = 0; i < ctx->num_program_metrics; i++) {
461 if (ctx->program_metrics[i].ticks == 0.0)
463 printf ("Program %d:\t%7.2f mega-ticks\n",
464 i, ctx->program_metrics[i].ticks / 1e6);
469 glwrap_end_frame (void)
471 static int initialized = 0;
473 static struct timeval tv_start, tv_now;
477 gettimeofday (&tv_start, NULL);
484 if (frames % 60 == 0) {
486 gettimeofday (&tv_now, NULL);
488 fps = (double) frames / (tv_now.tv_sec - tv_start.tv_sec +
489 (tv_now.tv_usec - tv_start.tv_usec) / 1.0e6);
491 printf("FPS: %.3f\n", fps);
493 print_program_metrics ();
496 /* Consume all counters that are ready. */
497 counter_t *counter = current_context.counter_head;
503 glGetQueryObjectiv (counter->id, GL_QUERY_RESULT_AVAILABLE,
508 glGetQueryObjectuiv (counter->id, GL_QUERY_RESULT, &elapsed);
510 accumulate_program_ticks (counter->program, elapsed);
512 current_context.counter_head = counter->next;
513 if (current_context.counter_head == NULL)
514 current_context.counter_tail = NULL;
516 glDeleteQueries (1, &counter->id);
519 counter = current_context.counter_head;