* THE SOFTWARE.
*/
-#include "fips.h"
-
-#include "glwrap.h"
+#include "dlwrap.h"
/* The prototypes for some OpenGL functions changed at one point from:
*
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
-#include <sys/time.h>
-
-#include "dlwrap.h"
-
-typedef struct counter
-{
- unsigned id;
- unsigned program;
- struct counter *next;
-} counter_t;
-
-typedef struct program_metrics
-{
- unsigned id;
- double ticks;
-} program_metrics_t;
-
-typedef struct context
-{
- unsigned int program;
-
- counter_t *counter_head;
- counter_t *counter_tail;
+#include "fips.h"
- unsigned num_program_metrics;
- program_metrics_t *program_metrics;
-} context_t;
+#include "glwrap.h"
-/* FIXME: Need a map from integers to context objects and track the
- * current context with glXMakeContextCurrent, eglMakeCurrent, etc. */
+#include "metrics.h"
-context_t current_context;
+static void *gl_handle;
-static unsigned
-add_counter (void)
+void
+glwrap_set_gl_handle (void *handle)
{
- counter_t *counter;
-
- counter = malloc (sizeof(counter_t));
- if (counter == NULL) {
- fprintf (stderr, "Out of memory\n");
- exit (1);
- }
-
- glGenQueries (1, &counter->id);
-
- counter->program = current_context.program;
- counter->next = NULL;
-
- if (current_context.counter_tail) {
- current_context.counter_tail->next = counter;
- current_context.counter_tail = counter;
- } else {
- current_context.counter_tail = counter;
- current_context.counter_head = counter;
- }
-
- return counter->id;
+ if (gl_handle == NULL)
+ gl_handle = handle;
}
void *
glwrap_lookup (char *name)
{
- const char *libgl_filename = "libGL.so.1";
- static void *libgl_handle = NULL;
-
- if (! libgl_handle) {
- libgl_handle = dlwrap_real_dlopen (libgl_filename, RTLD_NOW | RTLD_DEEPBIND);
- if (! libgl_handle) {
- fprintf (stderr, "Error: Failed to dlopen %s\n",
- libgl_filename);
- exit (1);
+ void *ret;
+
+ /* We don't call dlopen here to find the library in which to
+ * perform a dlsym lookup. That's because the application may
+ * be loading libGL.so or libGLESv2.so for its OpenGL symbols.
+ *
+ * So we instead watch for one of those filenames to go by in
+ * our dlopen wrapper, which will then call
+ * glwrap_set_gl_handle to give us the handle to use here.
+ *
+ * If the application hasn't called dlopen on a "libGL"
+ * library, then presumably the application is linked directly
+ * to an OpenGL implementation. In this case, we can use
+ * RTLD_NEXT to find the symbol.
+ *
+ * But just in case, we also let the user override that by
+ * specifying the FIPS_LIBGL environment variable to the path
+ * of the real libGL.so library that fips should dlopen here.
+ */
+ if (gl_handle == NULL) {
+ const char *path;
+
+ path = getenv ("FIPS_LIBGL");
+ if (path) {
+ gl_handle = dlopen (path, RTLD_LAZY);
+
+ if (gl_handle == NULL) {
+ fprintf (stderr, "Failed to dlopen FIPS_LIBGL: "
+ "%s\n", path);
+ exit (1);
+ }
+ } else {
+ gl_handle = RTLD_NEXT;
}
}
- return dlwrap_real_dlsym (libgl_handle, name);
-}
-
-/* Execute a glBegineQuery/glEndQuery pair around an OpenGL call. */
-#define TIMED_DEFER(function,...) do { \
- unsigned counter; \
- counter = add_counter (); \
- glBeginQuery (GL_TIME_ELAPSED, counter); \
- GLWRAP_DEFER(function, __VA_ARGS__); \
- glEndQuery (GL_TIME_ELAPSED); \
-} while (0);
-
-/* Thanks to apitrace source code for the list of OpenGL draw calls. */
-void
-glDrawArrays (GLenum mode, GLint first, GLsizei count)
-{
- TIMED_DEFER (glDrawArrays, mode, first, count);
-}
-
-void
-glDrawArraysEXT (GLenum mode, GLint first, GLsizei count)
-{
- TIMED_DEFER (glDrawArraysEXT, mode, first, count);
-}
-
-void
-glDrawArraysIndirect (GLenum mode, const GLvoid *indirect)
-{
- TIMED_DEFER (glDrawArraysIndirect, mode, indirect);
-}
-
-void
-glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count,
- GLsizei primcount)
-{
- TIMED_DEFER (glDrawArraysInstanced, mode, first, count, primcount);
-}
-
-void
-glDrawArraysInstancedARB (GLenum mode, GLint first, GLsizei count,
- GLsizei primcount)
-{
- TIMED_DEFER (glDrawArraysInstancedARB, mode, first, count, primcount);
-}
-
-void
-glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count,
- GLsizei primcount)
-{
- TIMED_DEFER (glDrawArraysInstancedEXT, mode, start, count, primcount);
-}
-
-void
-glDrawArraysInstancedBaseInstance (GLenum mode, GLint first, GLsizei count,
- GLsizei primcount, GLuint baseinstance)
-{
- TIMED_DEFER (glDrawArraysInstancedBaseInstance, mode,
- first, count, primcount, baseinstance);
-}
-
-void
-glDrawMeshArraysSUN (GLenum mode, GLint first, GLsizei count, GLsizei width)
-{
- TIMED_DEFER (glDrawMeshArraysSUN, mode, first, count, width);
-}
-
-void
-glMultiDrawArrays (GLenum mode, const GLint *first,
- const GLsizei *count, GLsizei primcount)
-{
- TIMED_DEFER (glMultiDrawArrays, mode, first, count, primcount);
-}
-
-void
-glMultiDrawArraysEXT (GLenum mode, const GLint *first,
- const GLsizei *count, GLsizei primcount)
-{
- TIMED_DEFER (glMultiDrawArraysEXT, mode, first, count, primcount);
-}
-
-void
-glMultiModeDrawArraysIBM (const GLenum *mode, const GLint *first,
- const GLsizei *count, GLsizei primcount,
- GLint modestride)
-{
- TIMED_DEFER (glMultiModeDrawArraysIBM, mode,
- first, count, primcount, modestride);
-}
-
-/* FIXME?
-void
-glMultiDrawArraysIndirect (...)
-{
- TIMED_DEFER (glMultiDrawArraysIndirect, ...);
-}
-*/
-
-void
-glMultiDrawArraysIndirectAMD (GLenum mode, const GLvoid *indirect,
- GLsizei primcount, GLsizei stride)
-{
- TIMED_DEFER (glMultiDrawArraysIndirectAMD, mode,
- indirect, primcount, stride);
-}
-
-void
-glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
-{
- TIMED_DEFER (glDrawElements, mode, count, type, indices);
-}
-
-void
-glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices, GLint basevertex)
-{
- TIMED_DEFER (glDrawElementsBaseVertex, mode, count,
- type, indices, basevertex);
-}
-
-void
-glDrawElementsIndirect (GLenum mode, GLenum type, const GLvoid *indirect)
-{
- TIMED_DEFER (glDrawElementsIndirect, mode, type, indirect);
-}
-
-void
-glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices, GLsizei primcount)
-{
- TIMED_DEFER (glDrawElementsInstanced, mode, count,
- type, indices, primcount);
-}
-
-void
-glDrawElementsInstancedARB (GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices, GLsizei primcount)
-{
- TIMED_DEFER (glDrawElementsInstancedARB, mode, count,
- type, indices, primcount);
-}
-
-void
-glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices, GLsizei primcount)
-{
- TIMED_DEFER (glDrawElementsInstancedEXT, mode, count,
- type, indices, primcount);
-}
-
-void
-glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices, GLsizei primcount,
- GLint basevertex)
-{
- TIMED_DEFER (glDrawElementsInstancedBaseVertex, mode, count,
- type, indices, primcount, basevertex);
-}
+ ret = dlwrap_real_dlsym (gl_handle, name);
-void
-glDrawElementsInstancedBaseInstance (GLenum mode, GLsizei count, GLenum type,
- const void *indices, GLsizei primcount,
- GLuint baseinstance)
-{
- TIMED_DEFER (glDrawElementsInstancedBaseInstance, mode, count, type,
- indices, primcount, baseinstance);
-}
-
-void
-glDrawElementsInstancedBaseVertexBaseInstance (GLenum mode, GLsizei count,
- GLenum type, const void *indices, GLsizei primcount,
- GLint basevertex, GLuint baseinstance)
-{
- TIMED_DEFER (glDrawElementsInstancedBaseVertexBaseInstance, mode,
- count, type, indices, primcount, basevertex, baseinstance);
-}
-
-void
-glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count,
- GLenum type, const GLvoid *indices)
-{
- TIMED_DEFER (glDrawRangeElements, mode, start, end,
- count, type, indices);
-}
-
-void
-glDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint end, GLsizei count,
- GLenum type, const GLvoid *indices)
-{
- TIMED_DEFER (glDrawRangeElementsEXT, mode, start, end,
- count, type, indices);
-}
-
-void
-glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end,
- GLsizei count, GLenum type,
- const GLvoid *indices, GLint basevertex)
-{
- TIMED_DEFER (glDrawRangeElementsBaseVertex, mode, start, end,
- count, type, indices, basevertex);
-}
-
-void
-glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type,
- const GLvoid* *indices, GLsizei primcount)
-{
- TIMED_DEFER (glMultiDrawElements, mode, count, type,
- indices, primcount);
-}
-
-void
-glMultiDrawElementsBaseVertex (GLenum mode, const GLsizei *count,
- GLenum type, const GLvoid* *indices,
- GLsizei primcount, const GLint *basevertex)
-{
- TIMED_DEFER (glMultiDrawElementsBaseVertex, mode, count,
- type, indices, primcount, basevertex);
-}
-
-void
-glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type,
- const GLvoid* *indices, GLsizei primcount)
-{
- TIMED_DEFER (glMultiDrawElementsEXT, mode, count,
- type, indices, primcount);
-}
-
-void
-glMultiModeDrawElementsIBM (const GLenum *mode, const GLsizei *count,
- GLenum type, const GLvoid* const *indices,
- GLsizei primcount, GLint modestride)
-{
- TIMED_DEFER (glMultiModeDrawElementsIBM, mode, count,
- type, indices, primcount, modestride);
-}
-
-/* FIXME?
-void
-glMultiDrawElementsIndirect (...)
-{
- TIMED_DEFER (glMultiDrawElementsIndirect, ...);
-}
-*/
-
-void
-glMultiDrawElementsIndirectAMD (GLenum mode, GLenum type,
- const GLvoid *indirect,
- GLsizei primcount, GLsizei stride)
-{
- TIMED_DEFER (glMultiDrawElementsIndirectAMD, mode, type,
- indirect, primcount, stride);
-}
-
-void
-glCallList (GLuint list)
-{
- TIMED_DEFER (glCallList, list);
-}
-
-void
-glCallLists (GLsizei n, GLenum type, const GLvoid *lists)
-{
- TIMED_DEFER (glCallLists, n, type, lists);
-}
-
-void
-glClear (GLbitfield mask)
-{
- TIMED_DEFER (glClear, mask);
-}
+ if (ret == NULL) {
+ fprintf (stderr, "Error: glwrap_lookup failed to dlsym %s\n",
+ name);
+ exit (1);
+ }
-void
-glEnd (void)
-{
- TIMED_DEFER (glEnd,);
+ return ret;
}
+/* With a program change, we stop the counter, update the
+ * active program, then start the counter up again. */
void
-glDrawPixels (GLsizei width, GLsizei height, GLenum format,
- GLenum type, const GLvoid *pixels)
+glUseProgram (GLuint program)
{
- TIMED_DEFER (glDrawPixels, width, height, format, type, pixels);
-}
+ metrics_counter_stop ();
-void
-glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter)
-{
- TIMED_DEFER (glBlitFramebuffer,
- srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1,
- mask, filter);
-}
+ metrics_set_current_program (program);
-void
-glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter)
-{
- TIMED_DEFER (glBlitFramebufferEXT,
- srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1,
- mask, filter);
-}
-
-void
-glUseProgram (GLuint program)
-{
- current_context.program = program;
+ metrics_counter_start ();
GLWRAP_DEFER(glUseProgram, program);
}
void
glUseProgramObjectARB (GLhandleARB programObj)
{
- current_context.program = programObj;
+ metrics_counter_stop ();
- GLWRAP_DEFER(glUseProgramObjectARB, programObj);
-}
+ metrics_set_current_program (programObj);
-static void
-accumulate_program_ticks (unsigned program_id, unsigned ticks)
-{
- context_t *ctx = ¤t_context;
- unsigned i;
-
- if (program_id >= ctx->num_program_metrics) {
- ctx->program_metrics = realloc (ctx->program_metrics,
- (program_id + 1) * sizeof (program_metrics_t));
- for (i = ctx->num_program_metrics; i < program_id + 1; i++) {
- ctx->program_metrics[i].id = i;
- ctx->program_metrics[i].ticks = 0.0;
- }
-
- ctx->num_program_metrics = program_id + 1;
- }
-
- ctx->program_metrics[program_id].ticks += ticks;
-}
+ metrics_counter_start ();
-/* FIXME: Should sort the metrics, print out percentages, etc. */
-static void
-print_program_metrics (void)
-{
- context_t *ctx = ¤t_context;
- unsigned i;
-
- for (i = 0; i < ctx->num_program_metrics; i++) {
- if (ctx->program_metrics[i].ticks == 0.0)
- continue;
- printf ("Program %d:\t%7.2f mega-ticks\n",
- i, ctx->program_metrics[i].ticks / 1e6);
- }
-}
-
-void
-glwrap_end_frame (void)
-{
- static int initialized = 0;
- static int frames;
- static struct timeval tv_start, tv_now;
-
- if (! initialized) {
- frames = 0;
- gettimeofday (&tv_start, NULL);
- initialized = 1;
- }
-
-
- frames++;
-
- if (frames % 60 == 0) {
- double fps;
- gettimeofday (&tv_now, NULL);
-
- fps = (double) frames / (tv_now.tv_sec - tv_start.tv_sec +
- (tv_now.tv_usec - tv_start.tv_usec) / 1.0e6);
-
- printf("FPS: %.3f\n", fps);
-
- print_program_metrics ();
- }
-
- /* Consume all counters that are ready. */
- counter_t *counter = current_context.counter_head;
-
- while (counter) {
- GLint available;
- GLuint elapsed;
-
- glGetQueryObjectiv (counter->id, GL_QUERY_RESULT_AVAILABLE,
- &available);
- if (! available)
- break;
-
- glGetQueryObjectuiv (counter->id, GL_QUERY_RESULT, &elapsed);
-
- accumulate_program_ticks (counter->program, elapsed);
-
- current_context.counter_head = counter->next;
- if (current_context.counter_head == NULL)
- current_context.counter_tail = NULL;
-
- glDeleteQueries (1, &counter->id);
-
- free (counter);
- counter = current_context.counter_head;
- }
+ GLWRAP_DEFER(glUseProgramObjectARB, programObj);
}