blob: ec2145d821e4e467899909240c34089a8996b6bc [file] [log] [blame]
bungeman@google.combe9ad4e2011-06-07 19:16:02 +00001#include "BenchGpuTimer_gl.h"
2#include <string.h>
3
4//GL
5#define BENCH_GL_FUNCTION_TYPE
6#if defined(SK_MESA)
7 #include <GL/osmesa.h>
8 #define SK_BENCH_CONTEXT_CHECK (NULL != OSMesaGetCurrentContext())
9
10 #define SK_GL_GET_PROC(F) gBenchGL.f ## F = (BenchGL ## F ## Proc) \
11 OSMesaGetProcAddress("gl" #F);
12 #define SK_GL_GET_PROC_SUFFIX(F, S) gBenchGL.f ## F = (BenchGL##F##Proc)\
13 OSMesaGetProcAddress("gl" #F #S);
14
15#elif defined(SK_BUILD_FOR_WIN32)
16 #define WIN32_LEAN_AND_MEAN 1
17 #include <Windows.h>
18 #include <GL/GL.h>
19 #define SK_BENCH_CONTEXT_CHECK (NULL != wglGetCurrentContext())
20
21 #undef BENCH_GL_FUNCTION_TYPE
22 #define BENCH_GL_FUNCTION_TYPE __stdcall
23
24 #define SK_GL_GET_PROC(F) gBenchGL.f ## F = (BenchGL ## F ## Proc) \
25 wglGetProcAddress("gl" #F);
26 #define SK_GL_GET_PROC_SUFFIX(F, S) gBenchGL.f ## F = (BenchGL##F##Proc)\
27 wglGetProcAddress("gl" #F #S);
28
29#elif defined(SK_BUILD_FOR_MAC)
30 #include <OpenGL/gl.h>
31 #include <OpenGL/CGLCurrent.h>
32 #define SK_BENCH_CONTEXT_CHECK (NULL != CGLGetCurrentContext())
33
34#elif defined(SK_BUILD_FOR_UNIX)
35 #include <GL/gl.h>
36 #include <GL/glx.h>
37 #define SK_BENCH_CONTEXT_CHECK (NULL != glXGetCurrentContext())
38
39 #define SK_GL_GET_PROC(F) gBenchGL.f ## F = (BenchGL ## F ## Proc) \
40 glXGetProcAddressARB(reinterpret_cast<const GLubyte*>("gl" #F));
41 #define SK_GL_GET_PROC_SUFFIX(F, S) gBenchGL.f ## F = (BenchGL##F##Proc)\
42 glXGetProcAddressARB(reinterpret_cast<const GLubyte*>("gl" #F #S));
43#else
44 #error unsupported platform
45#endif
46
47#define BenchGL_TIME_ELAPSED 0x88BF
48#define BenchGL_QUERY_RESULT 0x8866
49#define BenchGL_QUERY_RESULT_AVAILABLE 0x8867
50
51#if defined(SK_BUILD_FOR_WIN32)
52typedef UINT64 BenchGLuint64;
53#else
54#include <stdint.h>
55typedef uint64_t BenchGLuint64;
56#endif
57
58typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLGenQueriesProc) (GLsizei n, GLuint *ids);
59typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLBeginQueryProc) (GLenum target, GLuint id);
60typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLEndQueryProc) (GLenum target);
61typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLDeleteQueriesProc) (GLsizei n, const GLuint *ids);
62typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLGetQueryObjectivProc) (GLuint id, GLenum pname, GLint *params);
63typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLGetQueryObjectui64vProc) (GLuint id, GLenum pname, BenchGLuint64 *params);
64
65struct BenchGLInterface {
66 bool fHasTimer;
67 BenchGLGenQueriesProc fGenQueries;
68 BenchGLBeginQueryProc fBeginQuery;
69 BenchGLEndQueryProc fEndQuery;
70 BenchGLDeleteQueriesProc fDeleteQueries;
71 BenchGLGetQueryObjectivProc fGetQueryObjectiv;
72 BenchGLGetQueryObjectui64vProc fGetQueryObjectui64v;
73};
74
75static bool BenchGLCheckExtension(const char* ext,
76 const char* extensionString) {
77 int extLength = strlen(ext);
78
79 while (true) {
80 int n = strcspn(extensionString, " ");
81 if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
82 return true;
83 }
84 if (0 == extensionString[n]) {
85 return false;
86 }
87 extensionString += n+1;
88 }
89
90 return false;
91}
92
93static BenchGLInterface gBenchGL;
94static bool gBenchGLInterfaceInit = false;
95
96static void BenchGLSetDefaultGLInterface() {
97 gBenchGL.fHasTimer = false;
98 if (gBenchGLInterfaceInit || !SK_BENCH_CONTEXT_CHECK) return;
99
100 const char* glExts =
101 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
102 const GLboolean ext =
103 BenchGLCheckExtension("GL_EXT_timer_query", glExts);
104 const GLboolean arb =
105 BenchGLCheckExtension("GL_ARB_timer_query", glExts);
106 if (ext || arb) {
107#if defined(SK_BUILD_FOR_MAC)
108 #if GL_EXT_timer_query || GL_ARB_timer_query
109 gBenchGL.fHasTimer = true;
110 gBenchGL.fGenQueries = glGenQueries;
111 gBenchGL.fBeginQuery = glBeginQuery;
112 gBenchGL.fEndQuery = glEndQuery;
113 gBenchGL.fDeleteQueries = glDeleteQueries;
114 gBenchGL.fGetQueryObjectiv = glGetQueryObjectiv;
115 #endif
116 #if GL_ARB_timer_query
117 gBenchGL.fGetQueryObjectui64v = glGetQueryObjectui64v;
118 #elif GL_EXT_timer_query
119 gBenchGL.fGetQueryObjectui64v = glGetQueryObjectui64vEXT;
120 #endif
121#else
122 gBenchGL.fHasTimer = true;
123 SK_GL_GET_PROC(GenQueries)
124 SK_GL_GET_PROC(BeginQuery)
125 SK_GL_GET_PROC(EndQuery)
126 SK_GL_GET_PROC(DeleteQueries)
127
128 SK_GL_GET_PROC(GetQueryObjectiv)
129 if (arb) {
130 SK_GL_GET_PROC(GetQueryObjectui64v)
131 } else {
132 SK_GL_GET_PROC_SUFFIX(GetQueryObjectui64v, EXT)
133 }
134#endif
135 }
136 gBenchGLInterfaceInit = true;
137}
138
139BenchGpuTimer::BenchGpuTimer() {
140 BenchGLSetDefaultGLInterface();
141 if (gBenchGL.fHasTimer) {
142 gBenchGL.fGenQueries(1, &this->fQuery);
143 }
144}
145
146BenchGpuTimer::~BenchGpuTimer() {
147 if (gBenchGL.fHasTimer) {
148 gBenchGL.fDeleteQueries(1, &this->fQuery);
149 }
150}
151
152void BenchGpuTimer::startGpu() {
153 if (!gBenchGL.fHasTimer) return;
154
155 this->fStarted = true;
156 gBenchGL.fBeginQuery(BenchGL_TIME_ELAPSED, this->fQuery);
157}
158
159/**
160 * It is important to stop the cpu clocks first,
161 * as this will cpu wait for the gpu to finish.
162 */
163double BenchGpuTimer::endGpu() {
164 if (!gBenchGL.fHasTimer) return 0;
165
166 this->fStarted = false;
167 gBenchGL.fEndQuery(BenchGL_TIME_ELAPSED);
168
169 GLint available = 0;
170 while (!available) {
171 gBenchGL.fGetQueryObjectiv(this->fQuery
172 , BenchGL_QUERY_RESULT_AVAILABLE
173 , &available);
174 }
175 BenchGLuint64 totalGPUTimeElapsed = 0;
176 gBenchGL.fGetQueryObjectui64v(this->fQuery
177 , BenchGL_QUERY_RESULT
178 , &totalGPUTimeElapsed);
179
180 return totalGPUTimeElapsed / 1000000.0;
181}