]> git.cworth.org Git - fips/blobdiff - glwrap.c
glxwrap: Initialize fips_dispatch when glxMakeContextCurrent is called
[fips] / glwrap.c
index c37bae3a16ab1b63ad1883ed5f6c46fdf4def4c8..0ae295a87082212b59d764f8b89250c2ab5c68b8 100644 (file)
--- a/glwrap.c
+++ b/glwrap.c
@@ -19,9 +19,7 @@
  * 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;
+#include "fips.h"
 
-       counter_t *counter_head;
-       counter_t *counter_tail;
+#include "glwrap.h"
 
-       unsigned num_program_metrics;
-       program_metrics_t *program_metrics;
-} context_t;
+#include "metrics.h"
 
-/* FIXME: Need a map from integers to context objects and track the
- * current context with glXMakeContextCurrent, eglMakeCurrent, etc. */
+static int inside_new_list = 0;
 
-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);
+       if (gl_handle == NULL)
+               gl_handle = handle;
+}
 
-       counter->program = current_context.program;
-       counter->next = NULL;
+void *
+glwrap_lookup (char *name)
+{
+       void *ret;
 
-       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;
-       }
+       /* 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.
+        *
 
-       return counter->id;
-}
+        * 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.
+        */
+       if (gl_handle == NULL)
+               gl_handle = RTLD_NEXT;
 
-static void *
-lookup (const char *name)
-{
-       const char *libgl_filename = "libGL.so.1";
-       static void *libgl_handle = NULL;
+       ret = dlwrap_real_dlsym (gl_handle, name);
 
-       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);
-               }
+       if (ret == NULL) {
+               fprintf (stderr, "Error: glwrap_lookup failed to dlsym %s\n",
+                        name);
+               exit (1);
        }
 
-       return dlwrap_real_dlsym (libgl_handle, name);
+       return ret;
 }
 
-/* Defer to the underlying, ''real'' function to do the real work. */
-#define DEFER(function,...) do {                               \
-       static typeof(&function) real_ ## function;             \
-       if (! real_ ## function)                                \
-               real_ ## function = lookup (#function);         \
-       real_ ## function(__VA_ARGS__);                         \
-} while (0);
-
-/* Execute a glBegineQuery/glEndQuery pair around an OpenGL call. */
-#define TIMED_DEFER(function,...) do {                 \
-       unsigned counter;                               \
-       counter = add_counter ();                       \
-       glBeginQuery (GL_TIME_ELAPSED, counter);        \
-       DEFER(function, __VA_ARGS__);                   \
-       glEndQuery (GL_TIME_ELAPSED);                   \
+/* Execute an OpenGL call and time it with a GPU metrics counter. */
+#define TIMED_DEFER(function,...) do {                                 \
+       if (! inside_new_list) {                                        \
+               unsigned counter;                                       \
+               counter = metrics_counter_new ();                       \
+               metrics_counter_start (counter);                        \
+       }                                                               \
+       GLWRAP_DEFER(function, __VA_ARGS__);                            \
+       if (! inside_new_list) {                                        \
+               metrics_counter_stop ();                                \
+       }                                                               \
 } while (0);
 
 /* Thanks to apitrace source code for the list of OpenGL draw calls. */
@@ -215,13 +181,12 @@ glMultiModeDrawArraysIBM (const GLenum *mode, const GLint *first,
                     first, count, primcount, modestride);
 }
 
-/* FIXME?
 void
-glMultiDrawArraysIndirect (...)
+glMultiDrawArraysIndirect (GLenum mode, const void *indirect,
+                          GLsizei drawcount, GLsizei stride)
 {
-       TIMED_DEFER (glMultiDrawArraysIndirect, ...);
+       TIMED_DEFER (glMultiDrawArraysIndirect, mode, indirect, drawcount, stride);
 }
-*/
 
 void
 glMultiDrawArraysIndirectAMD (GLenum mode, const GLvoid *indirect,
@@ -361,13 +326,13 @@ glMultiModeDrawElementsIBM (const GLenum *mode, const GLsizei *count,
                     type, indices, primcount, modestride);
 }
 
-/* FIXME?
 void
-glMultiDrawElementsIndirect (...)
+glMultiDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect,
+                            GLsizei drawcount, GLsizei stride)
 {
-       TIMED_DEFER (glMultiDrawElementsIndirect, ...);
+       TIMED_DEFER (glMultiDrawElementsIndirect, mode, type,
+                    indirect, drawcount, stride);
 }
-*/
 
 void
 glMultiDrawElementsIndirectAMD (GLenum mode, GLenum type,
@@ -396,10 +361,47 @@ glClear (GLbitfield mask)
        TIMED_DEFER (glClear, mask);
 }
 
+/* We can't just use TIMED_DEFER for glBegin/glEnd since the metrics
+ * counter must be started before glBegin and stopped after glEnd,
+ * (that is, everything from glBegin to glEnd is counted as a single
+ * operation). */
+void
+glBegin (GLenum mode)
+{
+       if (! inside_new_list)
+       {
+               unsigned counter;
+               counter = metrics_counter_new ();
+               metrics_counter_start (counter);
+       }
+
+       GLWRAP_DEFER (glBegin, mode);
+}
+
 void
 glEnd (void)
 {
-       TIMED_DEFER (glEnd,);
+       GLWRAP_DEFER (glEnd);
+
+       if (! inside_new_list) {
+               metrics_counter_stop ();
+       }
+}
+
+/* And we need to track display lists to avoid inserting queries
+ * inside the list while it's being constructed. */
+void
+glNewList (GLuint list, GLenum mode)
+{
+       inside_new_list = 1;
+       GLWRAP_DEFER (glNewList, list, mode);
+}
+
+void
+glEndList (void)
+{
+       GLWRAP_DEFER (glEndList);
+       inside_new_list = 0;
 }
 
 void
@@ -434,105 +436,15 @@ glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
 void
 glUseProgram (GLuint program)
 {
-       current_context.program = program;
+       metrics_set_current_program (program);
 
-       DEFER(glUseProgram, program);
+       GLWRAP_DEFER(glUseProgram, program);
 }
 
 void
 glUseProgramObjectARB (GLhandleARB programObj)
 {
-       current_context.program = programObj;
-
-       DEFER(glUseProgramObjectARB, programObj);
-}
-
-static void
-accumulate_program_ticks (unsigned program_id, unsigned ticks)
-{
-       context_t *ctx = &current_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;
-}
-
-/* FIXME: Should sort the metrics, print out percentages, etc. */
-static void
-print_program_metrics (void)
-{
-       context_t *ctx = &current_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;
-       }
-
+       metrics_set_current_program (programObj);
 
-       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);
 }