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