]> git.tdb.fi Git - gldbg.git/blob - flavors/gl/source/profiler.cpp
Fix several problems reported by valgrind
[gldbg.git] / flavors / gl / source / profiler.cpp
1 #include <stdexcept>
2 #include <cstdio>
3 #include <ctime>
4 #include "gldbg.h"
5 #include "profiler.h"
6
7 using namespace std;
8
9 Profiler::Profiler(GlDbg &dbg):
10         decoder(gldecoder_new(this, 0)),
11         enabled(false)
12 {
13         dbg.get_command_interpreter().register_command("profile", this, &Profiler::cmd_profile)
14                 .set_help("Profiles GL usage and performance",
15                         "profile {on|off}\n"
16                         "  Enables or disables profiling\n");
17
18         decoder->glDrawArrays = glDrawArrays;
19         decoder->glDrawElements = glDrawElements;
20         decoder->glDrawRangeElements = glDrawRangeElements;
21         decoder->glXSwapBuffers = glXSwapBuffers;
22 }
23
24 Profiler::~Profiler()
25 {
26         gldecoder_delete(decoder);
27 }
28
29 void Profiler::decode(const char *data, unsigned len)
30 {
31         if(enabled)
32                 gldecoder_decode(decoder, data, len);
33 }
34
35 void Profiler::cmd_profile(const string &args)
36 {
37         if(args.empty() || args=="on")
38         {
39                 enabled = true;
40                 frames = 0;
41                 draw_calls = 0;
42                 vertices = 0;
43                 triangles = 0;
44                 start = get_time();
45         }
46         else if(args=="off")
47                 enabled = false;
48         else
49                 throw runtime_error("Invalid argument");
50 }
51
52 void Profiler::glDrawArrays(void *user_data, GLenum mode, int, int count)
53 {
54         glDrawElements(user_data, mode, count, 0, 0);
55 }
56
57 void Profiler::glDrawElements(void *user_data, GLenum mode, int count, GLenum, const void *)
58 {
59         Profiler *self = reinterpret_cast<Profiler *>(user_data);
60
61         ++self->draw_calls;
62         self->vertices += count;
63
64         switch(mode)
65         {
66         case GL_TRIANGLES:
67                 self->triangles += count/3;
68                 break;
69         case GL_TRIANGLE_STRIP:
70         case GL_TRIANGLE_FAN:
71                 if(count>2)
72                         self->triangles += count-2;
73                 break;
74         case GL_QUADS:
75                 self->triangles += count/4;
76                 break;
77         case GL_QUAD_STRIP:
78                 if(count>3)
79                         self->triangles += count/2-1;
80                 break;
81         }
82 }
83
84 void Profiler::glDrawRangeElements(void *user_data, GLenum mode, unsigned, unsigned, int count, GLenum type, const void *data)
85 {
86         glDrawElements(user_data, mode, count, type, data);
87 }
88
89 void Profiler::glXSwapBuffers(void *user_data, Display *, GLXDrawable)
90 {
91         Profiler *self = reinterpret_cast<Profiler *>(user_data);
92
93         printf("%d draw calls, %d vertices, %d triangles\n", self->draw_calls, self->vertices, self->triangles);
94         self->draw_calls = 0;
95         self->vertices = 0;
96         self->triangles = 0;
97
98         ++self->frames;
99         Time t = get_time();
100         float dt = (t-self->start)/1e6;
101         if(dt>1)
102         {
103                 printf("%d frames in %.2f seconds\n", self->frames, dt);
104                 self->start = t;
105                 self->frames = 0;
106         }
107 }
108
109 Profiler::Time Profiler::get_time()
110 {
111         struct timespec ts;
112         clock_gettime(CLOCK_REALTIME, &ts);
113         return ts.tv_sec*1000000+ts.tv_nsec/1000;
114 }