+#include <msp/io/print.h>
+#include <msp/time/units.h>
+#include <msp/time/utils.h>
+#include "profiler.h"
+
+using namespace Msp;
+
+Profiler::Profiler():
+ decoder(gldecoder_new(this, 0)),
+ enabled(false)
+{
+ decoder->glDrawArrays = glDrawArrays;
+ decoder->glDrawElements = glDrawElements;
+ decoder->glDrawRangeElements = glDrawRangeElements;
+ decoder->glXSwapBuffers = glXSwapBuffers;
+}
+
+void Profiler::enable()
+{
+ enabled = true;
+ frames = 0;
+ draw_calls = 0;
+ vertices = 0;
+ triangles = 0;
+ start = Msp::Time::now();
+}
+
+void Profiler::disable()
+{
+ enabled = false;
+}
+
+int Profiler::decode(const char *data, unsigned len)
+{
+ if(enabled)
+ return gldecoder_decode(decoder, data, len);
+ else
+ return 0;
+}
+
+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;
+ }
+}