]> git.tdb.fi Git - gldbg.git/blobdiff - flavors/gl/source/profiler.cpp
Move the profiler and inspector tools to the gl flavor
[gldbg.git] / flavors / gl / source / profiler.cpp
diff --git a/flavors/gl/source/profiler.cpp b/flavors/gl/source/profiler.cpp
new file mode 100644 (file)
index 0000000..37caa68
--- /dev/null
@@ -0,0 +1,110 @@
+/* $Id$
+
+This file is part of gldbg
+Copyright © 2010  Mikko Rasa, Mikkosoft Productions
+Distributed under the GPL
+*/
+
+#include <msp/io/print.h>
+#include <msp/time/units.h>
+#include <msp/time/utils.h>
+#include "gldbg.h"
+#include "profiler.h"
+
+using namespace std;
+using namespace Msp;
+
+Profiler::Profiler(GlDbg &dbg):
+       decoder(gldecoder_new(this, 0)),
+       enabled(false)
+{
+       dbg.get_command_interpreter().register_command("profile", this, &Profiler::cmd_profile)
+               .set_help("Profiles GL usage and performance",
+                       "profile {on|off}\n"
+                       "  Enables or disables profiling\n");
+
+       decoder->glDrawArrays = glDrawArrays;
+       decoder->glDrawElements = glDrawElements;
+       decoder->glDrawRangeElements = glDrawRangeElements;
+       decoder->glXSwapBuffers = glXSwapBuffers;
+}
+
+void Profiler::decode(const char *data, unsigned len)
+{
+       if(enabled)
+               gldecoder_decode(decoder, data, len);
+}
+
+void Profiler::cmd_profile(const string &args)
+{
+       if(args.empty() || args=="on")
+       {
+               enabled = true;
+               frames = 0;
+               draw_calls = 0;
+               vertices = 0;
+               triangles = 0;
+               start = Msp::Time::now();
+       }
+       else if(args=="off")
+               enabled = false;
+       else
+               throw InvalidParameterValue("Invalid argument");
+}
+
+void Profiler::glDrawArrays(void *user_data, GLenum mode, int, int count)
+{
+       glDrawElements(user_data, mode, count, 0, 0);
+}
+
+void Profiler::glDrawElements(void *user_data, GLenum mode, int count, GLenum, const void *)
+{
+       Profiler *self = reinterpret_cast<Profiler *>(user_data);
+
+       ++self->draw_calls;
+       self->vertices += count;
+
+       switch(mode)
+       {
+       case GL_TRIANGLES:
+               self->triangles += count/3;
+               break;
+       case GL_TRIANGLE_STRIP:
+       case GL_TRIANGLE_FAN:
+               if(count>2)
+                       self->triangles += count-2;
+               break;
+       case GL_QUADS:
+               self->triangles += count/4;
+               break;
+       case GL_QUAD_STRIP:
+               if(count>3)
+                       self->triangles += count/2-1;
+               break;
+       }
+}
+
+void Profiler::glDrawRangeElements(void *user_data, GLenum mode, unsigned, unsigned, int count, GLenum type, const void *data)
+{
+       glDrawElements(user_data, mode, count, type, data);
+}
+
+void Profiler::glXSwapBuffers(void *user_data, Display *, GLXDrawable)
+{
+       Profiler *self = reinterpret_cast<Profiler *>(user_data);
+
+       IO::print("%d draw calls, %d vertices, %d triangles\n", self->draw_calls, self->vertices, self->triangles);
+       self->draw_calls = 0;
+       self->vertices = 0;
+       self->triangles = 0;
+
+       ++self->frames;
+       Msp::Time::TimeStamp t = Msp::Time::now();
+       Msp::Time::TimeDelta dt = t-self->start;
+       if(dt>Msp::Time::sec)
+       {
+               Msp::IO::print("%d frames in %s seconds\n", self->frames, dt);
+               self->start = t;
+               self->frames = 0;
+       }
+}