Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

403 lines
18 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. // TOGL CODE LICENSE
  3. //
  4. // Copyright 2011-2014 Valve Corporation
  5. // All Rights Reserved.
  6. //
  7. // Permission is hereby granted, free of charge, to any person obtaining a copy
  8. // of this software and associated documentation files (the "Software"), to deal
  9. // in the Software without restriction, including without limitation the rights
  10. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. // copies of the Software, and to permit persons to whom the Software is
  12. // furnished to do so, subject to the following conditions:
  13. //
  14. // The above copyright notice and this permission notice shall be included in
  15. // all copies or substantial portions of the Software.
  16. //
  17. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. // THE SOFTWARE.
  24. //
  25. // glentrypoints.h
  26. //
  27. //===============================================================================
  28. #ifndef GLENTRYPOINTS_H
  29. #define GLENTRYPOINTS_H
  30. #pragma once
  31. #ifdef DX_TO_GL_ABSTRACTION
  32. #include "tier0/platform.h"
  33. #include "tier0/vprof_telemetry.h"
  34. #include "interface.h"
  35. #include "togl/rendermechanism.h"
  36. void *VoidFnPtrLookup_GlMgr(const char *fn, bool &okay, const bool bRequired, void *fallback=NULL);
  37. #if GL_USE_EXECUTE_HELPER_FOR_ALL_API_CALLS
  38. class CGLExecuteHelperBase
  39. {
  40. public:
  41. inline void StartCall(const char *pName);
  42. inline void StopCall(const char *pName);
  43. #if GL_TRACK_API_TIME
  44. TmU64 m_nStartTime;
  45. #endif
  46. };
  47. template < class FunctionType, typename Result >
  48. class CGLExecuteHelper : public CGLExecuteHelperBase
  49. {
  50. public:
  51. inline CGLExecuteHelper(FunctionType pFn, const char *pName ) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(); StopCall(pName); }
  52. template<typename A> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a); StopCall(pName); }
  53. template<typename A, typename B> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b); StopCall(pName); }
  54. template<typename A, typename B, typename C> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c); StopCall(pName); }
  55. template<typename A, typename B, typename C, typename D> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d); StopCall(pName); }
  56. template<typename A, typename B, typename C, typename D, typename E> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e); StopCall(pName); }
  57. template<typename A, typename B, typename C, typename D, typename E, typename F> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f); StopCall(pName); }
  58. template<typename A, typename B, typename C, typename D, typename E, typename F, typename G> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g); StopCall(pName); }
  59. template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h); StopCall(pName); }
  60. template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h, i); StopCall(pName); }
  61. template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h, i, j); StopCall(pName); }
  62. inline operator Result() const { return m_Result; }
  63. inline operator char*() const { return (char*)m_Result; }
  64. FunctionType m_pFn;
  65. Result m_Result;
  66. };
  67. template < class FunctionType>
  68. class CGLExecuteHelper<FunctionType, void> : public CGLExecuteHelperBase
  69. {
  70. public:
  71. inline CGLExecuteHelper(FunctionType pFn, const char *pName ) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(); StopCall(pName); }
  72. template<typename A> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a); StopCall(pName); }
  73. template<typename A, typename B> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b); StopCall(pName); }
  74. template<typename A, typename B, typename C> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c); StopCall(pName); }
  75. template<typename A, typename B, typename C, typename D> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d); StopCall(pName); }
  76. template<typename A, typename B, typename C, typename D, typename E> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e); StopCall(pName); }
  77. template<typename A, typename B, typename C, typename D, typename E, typename F> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f); StopCall(pName); }
  78. template<typename A, typename B, typename C, typename D, typename E, typename F, typename G> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g); StopCall(pName); }
  79. template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h); StopCall(pName); }
  80. template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h, i); StopCall(pName); }
  81. template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h, i, j); StopCall(pName); }
  82. FunctionType m_pFn;
  83. };
  84. #endif
  85. template < class FunctionType, typename Result >
  86. class CDynamicFunctionOpenGLBase
  87. {
  88. public:
  89. // Construct with a NULL function pointer. You must manually call
  90. // Lookup() before you can call a dynamic function through this interface.
  91. CDynamicFunctionOpenGLBase() : m_pFn(NULL) {}
  92. // Construct and do a lookup right away. You will need to make sure that
  93. // the lookup actually succeeded, as the gl library might have failed to load
  94. // or (fn) might not exist in it.
  95. CDynamicFunctionOpenGLBase(const char *fn, FunctionType fallback=NULL) : m_pFn(NULL)
  96. {
  97. Lookup(fn, fallback);
  98. }
  99. // Construct and do a lookup right away. See comments in Lookup() about what (okay) does.
  100. CDynamicFunctionOpenGLBase(const char *fn, bool &okay, FunctionType fallback=NULL) : m_pFn(NULL)
  101. {
  102. Lookup(fn, okay, fallback);
  103. }
  104. // Load library if necessary, look up symbol. Returns true and sets
  105. // m_pFn on successful lookup, returns false otherwise. If the
  106. // function pointer is already looked up, this return true immediately.
  107. // Use Reset() first if you want to look up the symbol again.
  108. // This function will return false immediately unless (okay) is true.
  109. // This allows you to chain lookups like this:
  110. // bool okay = true;
  111. // x.Lookup(lib, "x", okay);
  112. // y.Lookup(lib, "y", okay);
  113. // z.Lookup(lib, "z", okay);
  114. // if (okay) { printf("All functions were loaded successfully!\n"); }
  115. // If you supply a fallback, it'll be used if the lookup fails (and if
  116. // non-NULL, means this will always return (okay)).
  117. bool Lookup(const char *fn, bool &okay, FunctionType fallback=NULL)
  118. {
  119. if (!okay)
  120. return false;
  121. else if (this->m_pFn == NULL)
  122. {
  123. this->m_pFn = (FunctionType) VoidFnPtrLookup_GlMgr(fn, okay, false, (void *) fallback);
  124. this->SetFuncName( fn );
  125. }
  126. okay = m_pFn != NULL;
  127. return okay;
  128. }
  129. // Load library if necessary, look up symbol. Returns true and sets
  130. // m_pFn on successful lookup, returns false otherwise. If the
  131. // function pointer is already looked up, this return true immediately.
  132. // Use Reset() first if you want to look up the symbol again.
  133. // This function will return false immediately unless (okay) is true.
  134. // If you supply a fallback, it'll be used if the lookup fails (and if
  135. // non-NULL, means this will always return true).
  136. bool Lookup(const char *fn, FunctionType fallback=NULL)
  137. {
  138. bool okay = true;
  139. return Lookup(fn, okay, fallback);
  140. }
  141. // Invalidates the current lookup. Makes the function pointer NULL. You
  142. // will need to call Lookup() before you can call a dynamic function
  143. // through this interface again.
  144. void Reset() { m_pFn = NULL; }
  145. // Force this to be a specific function pointer.
  146. void Force(FunctionType ptr) { m_pFn = ptr; }
  147. // Retrieve the actual function pointer.
  148. FunctionType Pointer() const { return m_pFn; }
  149. #if GL_USE_EXECUTE_HELPER_FOR_ALL_API_CALLS
  150. #if GL_TELEMETRY_ZONES || GL_DUMP_ALL_API_CALLS
  151. #define GL_FUNC_NAME m_szName
  152. #else
  153. #define GL_FUNC_NAME ""
  154. #endif
  155. inline CGLExecuteHelper<FunctionType, Result> operator() () const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME ); }
  156. template<typename T>
  157. inline CGLExecuteHelper<FunctionType, Result> operator() (T a) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a); }
  158. template<typename T, typename U>
  159. inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b); }
  160. template<typename T, typename U, typename V>
  161. inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b, V c ) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b, c); }
  162. template<typename T, typename U, typename V, typename W>
  163. inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b, V c, W d) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b, c, d); }
  164. template<typename T, typename U, typename V, typename W, typename X>
  165. inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b, V c, W d, X e) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b, c, d, e); }
  166. template<typename T, typename U, typename V, typename W, typename X, typename Y>
  167. inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b, V c, W d, X e, Y f) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f); }
  168. template<typename T, typename U, typename V, typename W, typename X, typename Y, typename Z>
  169. inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b, V c, W d, X e, Y f, Z g) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g); }
  170. template<typename T, typename U, typename V, typename W, typename X, typename Y, typename Z, typename A>
  171. inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b, V c, W d, X e, Y f, Z g, A h) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h); }
  172. template<typename T, typename U, typename V, typename W, typename X, typename Y, typename Z, typename A, typename B>
  173. inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b, V c, W d, X e, Y f, Z g, A h, B i) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h, i); }
  174. template<typename T, typename U, typename V, typename W, typename X, typename Y, typename Z, typename A, typename B, typename C>
  175. inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b, V c, W d, X e, Y f, Z g, A h, B i, C j) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h, i, j); }
  176. #else
  177. operator FunctionType() const { return m_pFn; }
  178. #endif
  179. // Can be used to verify that we have an actual function looked up and
  180. // ready to call: if (!MyDynFunc) { printf("Function not found!\n"); }
  181. operator bool () const { return m_pFn != NULL; }
  182. bool operator !() const { return m_pFn == NULL; }
  183. protected:
  184. FunctionType m_pFn;
  185. #if GL_TELEMETRY_ZONES || GL_DUMP_ALL_API_CALLS
  186. char m_szName[32];
  187. inline void SetFuncName(const char *pFn) { V_strncpy( m_szName, pFn, sizeof( m_szName ) ); }
  188. #else
  189. inline void SetFuncName(const char *pFn) { (void)pFn; }
  190. #endif
  191. };
  192. // This works a lot like CDynamicFunctionMustInit, but we use SDL_GL_GetProcAddress().
  193. template < const bool bRequired, class FunctionType, typename Result >
  194. class CDynamicFunctionOpenGL : public CDynamicFunctionOpenGLBase< FunctionType, Result >
  195. {
  196. private: // forbid default constructor.
  197. CDynamicFunctionOpenGL() {}
  198. public:
  199. CDynamicFunctionOpenGL(const char *fn, FunctionType fallback=NULL)
  200. {
  201. bool okay = true;
  202. Lookup(fn, okay, fallback);
  203. this->SetFuncName( fn );
  204. }
  205. CDynamicFunctionOpenGL(const char *fn, bool &okay, FunctionType fallback=NULL)
  206. {
  207. Lookup(fn, okay, fallback);
  208. this->SetFuncName( fn );
  209. }
  210. // Please note this is not virtual.
  211. // !!! FIXME: we might want to fall back and try "EXT" or "ARB" versions in some case.
  212. bool Lookup(const char *fn, bool &okay, FunctionType fallback=NULL)
  213. {
  214. if (this->m_pFn == NULL)
  215. {
  216. this->m_pFn = (FunctionType) VoidFnPtrLookup_GlMgr(fn, okay, bRequired, (void *) fallback);
  217. this->SetFuncName( fn );
  218. }
  219. return okay;
  220. }
  221. };
  222. enum GLDriverStrings_t
  223. {
  224. cGLVendorString,
  225. cGLRendererString,
  226. cGLVersionString,
  227. cGLExtensionsString,
  228. cGLTotalDriverStrings
  229. };
  230. enum GLDriverProvider_t
  231. {
  232. cGLDriverProviderUnknown,
  233. cGLDriverProviderNVIDIA,
  234. cGLDriverProviderAMD,
  235. cGLDriverProviderIntel,
  236. cGLDriverProviderIntelOpenSource,
  237. cGLDriverProviderApple,
  238. cGLTotalDriverProviders
  239. };
  240. // This provides all the entry points for a given OpenGL context.
  241. // ENTRY POINTS ARE ONLY VALID FOR THE CONTEXT THAT WAS CURRENT WHEN
  242. // YOU LOOKED THEM UP. 99% of the time, this is not a problem, but
  243. // that 1% is really hard to track down. Always access the GL
  244. // through this class!
  245. class COpenGLEntryPoints
  246. {
  247. COpenGLEntryPoints( const COpenGLEntryPoints & );
  248. COpenGLEntryPoints &operator= ( const COpenGLEntryPoints & );
  249. public:
  250. // The GL context you are looking up entry points for must be current when you construct this object!
  251. COpenGLEntryPoints();
  252. ~COpenGLEntryPoints();
  253. void ClearEntryPoints();
  254. uint64 m_nTotalGLCycles, m_nTotalGLCalls;
  255. int m_nOpenGLVersionMajor; // if GL_VERSION is 2.1.0, this will be set to 2.
  256. int m_nOpenGLVersionMinor; // if GL_VERSION is 2.1.0, this will be set to 1.
  257. int m_nOpenGLVersionPatch; // if GL_VERSION is 2.1.0, this will be set to 0.
  258. bool m_bHave_OpenGL;
  259. char *m_pGLDriverStrings[cGLTotalDriverStrings];
  260. GLDriverProvider_t m_nDriverProvider;
  261. #ifdef OSX
  262. #define GL_EXT(x,glmajor,glminor) bool m_bHave_##x;
  263. #define GL_FUNC(ext,req,ret,fn,arg,call) CDynamicFunctionOpenGL< req, ret (*) arg, ret > fn;
  264. #define GL_FUNC_VOID(ext,req,fn,arg,call) CDynamicFunctionOpenGL< req, void (*) arg, void > fn;
  265. #else
  266. #define GL_EXT(x,glmajor,glminor) bool m_bHave_##x;
  267. #define GL_FUNC(ext,req,ret,fn,arg,call) CDynamicFunctionOpenGL< req, ret (APIENTRY *) arg, ret > fn;
  268. #define GL_FUNC_VOID(ext,req,fn,arg,call) CDynamicFunctionOpenGL< req, void (APIENTRY *) arg, void > fn;
  269. #endif
  270. #include "togl/glfuncs.inl"
  271. #undef GL_FUNC_VOID
  272. #undef GL_FUNC
  273. #undef GL_EXT
  274. bool HasSwapTearExtension() const
  275. {
  276. #ifdef _WIN32
  277. return m_bHave_WGL_EXT_swap_control_tear;
  278. #else
  279. return m_bHave_GLX_EXT_swap_control_tear;
  280. #endif
  281. }
  282. };
  283. // This will be set to the current OpenGL context's entry points.
  284. extern COpenGLEntryPoints *gGL;
  285. typedef void * (*GL_GetProcAddressCallbackFunc_t)(const char *, bool &, const bool, void *);
  286. #ifdef TOGL_DLL_EXPORT
  287. DLL_EXPORT COpenGLEntryPoints *ToGLConnectLibraries( CreateInterfaceFn factory );
  288. DLL_EXPORT void ToGLDisconnectLibraries();
  289. DLL_EXPORT COpenGLEntryPoints *GetOpenGLEntryPoints(GL_GetProcAddressCallbackFunc_t callback);
  290. DLL_EXPORT void ClearOpenGLEntryPoints();
  291. #else
  292. DLL_IMPORT COpenGLEntryPoints *ToGLConnectLibraries( CreateInterfaceFn factory );
  293. DLL_IMPORT void ToGLDisconnectLibraries();
  294. DLL_IMPORT COpenGLEntryPoints *GetOpenGLEntryPoints(GL_GetProcAddressCallbackFunc_t callback);
  295. DLL_IMPORT void ClearOpenGLEntryPoints();
  296. #endif
  297. #if GL_USE_EXECUTE_HELPER_FOR_ALL_API_CALLS
  298. inline void CGLExecuteHelperBase::StartCall(const char *pName)
  299. {
  300. (void)pName;
  301. #if GL_TELEMETRY_ZONES
  302. tmEnter( TELEMETRY_LEVEL3, TMZF_NONE, pName );
  303. #endif
  304. #if GL_TRACK_API_TIME
  305. m_nStartTime = tmFastTime();
  306. #endif
  307. #if GL_DUMP_ALL_API_CALLS
  308. static bool s_bDumpCalls;
  309. if ( s_bDumpCalls )
  310. {
  311. char buf[128];
  312. buf[0] = 'G';
  313. buf[1] = 'L';
  314. buf[2] = ':';
  315. size_t l = strlen( pName );
  316. memcpy( buf + 3, pName, l );
  317. buf[3 + l] = '\n';
  318. buf[4 + l] = '\0';
  319. Plat_DebugString( buf );
  320. }
  321. #endif
  322. }
  323. inline void CGLExecuteHelperBase::StopCall(const char *pName)
  324. {
  325. #if GL_TRACK_API_TIME
  326. uint64 nTotalCycles = tmFastTime() - m_nStartTime;
  327. #endif
  328. #if GL_TELEMETRY_ZONES
  329. tmLeave( TELEMETRY_LEVEL3 );
  330. #endif
  331. #if GL_TRACK_API_TIME
  332. //double flMilliseconds = g_Telemetry.flRDTSCToMilliSeconds * nTotalCycles;
  333. if (gGL)
  334. {
  335. gGL->m_nTotalGLCycles += nTotalCycles;
  336. gGL->m_nTotalGLCalls++;
  337. }
  338. #endif
  339. }
  340. #endif
  341. #endif // DX_TO_GL_ABSTRACTION
  342. #endif // GLENTRYPOINTS_H