Counter Strike : Global Offensive Source Code
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.

2393 lines
79 KiB

  1. //============ Copyright (c) Valve Corporation, All rights reserved. ============
  2. //
  3. // glmgr.h
  4. // singleton class, common basis for managing GL contexts
  5. // responsible for tracking adapters and contexts
  6. //
  7. //===============================================================================
  8. #ifndef GLMGR_H
  9. #define GLMGR_H
  10. #pragma once
  11. #undef HAVE_GL_ARB_SYNC
  12. #ifndef OSX
  13. #define HAVE_GL_ARB_SYNC 1
  14. #endif
  15. #include "glbase.h"
  16. #include "glentrypoints.h"
  17. #include "glmdebug.h"
  18. #include "glmdisplay.h"
  19. #include "glmgrext.h"
  20. #include "glmgrbasics.h"
  21. #include "cglmtex.h"
  22. #include "cglmfbo.h"
  23. #include "cglmprogram.h"
  24. #include "cglmbuffer.h"
  25. #include "cglmquery.h"
  26. #include "tier0/tslist.h"
  27. #include "tier0/vprof_telemetry.h"
  28. #include "materialsystem/IShader.h"
  29. #include "dxabstract_types.h"
  30. #include "tier0/icommandline.h"
  31. #undef FORCEINLINE
  32. #define FORCEINLINE inline
  33. //===============================================================================
  34. #define GLM_OPENGL_VENDOR_ID 1
  35. #define GLM_OPENGL_DEFAULT_DEVICE_ID 1
  36. #define GLM_OPENGL_LOW_PERF_DEVICE_ID 2
  37. extern void GLMDebugPrintf( const char *pMsg, ... );
  38. extern uint g_nTotalDrawsOrClears, g_nTotalVBLockBytes, g_nTotalIBLockBytes;
  39. #if GL_TELEMETRY_GPU_ZONES
  40. struct TelemetryGPUStats_t
  41. {
  42. uint m_nTotalBufferLocksAndUnlocks;
  43. uint m_nTotalTexLocksAndUnlocks;
  44. uint m_nTotalBlit2;
  45. uint m_nTotalResolveTex;
  46. uint m_nTotalPresent;
  47. inline void Clear() { memset( this, 0, sizeof( *this ) ); }
  48. inline uint GetTotal() const { return m_nTotalBufferLocksAndUnlocks + m_nTotalTexLocksAndUnlocks + m_nTotalBlit2 + m_nTotalResolveTex + m_nTotalPresent; }
  49. };
  50. extern TelemetryGPUStats_t g_TelemetryGPUStats;
  51. #endif
  52. struct GLMRect;
  53. typedef void *PseudoGLContextPtr;
  54. // parrot the D3D present parameters, more or less... "adapter" translates into "active display index" per the m_activeDisplayCount below.
  55. class GLMDisplayParams
  56. {
  57. public:
  58. // presumption, these indices are in sync with the current display DB that GLMgr has handy
  59. //int m_rendererIndex; // index of renderer (-1 if root context)
  60. //int m_displayIndex; // index of display in renderer - for FS
  61. //int m_modeIndex; // index of mode in display - for FS
  62. void *m_focusWindow; // (VD3DHWND aka WindowRef) - what window does this context display into
  63. bool m_fsEnable; // fullscreen on or not
  64. bool m_vsyncEnable; // vsync on or not
  65. // height and width have to match the display mode info if full screen.
  66. uint m_backBufferWidth; // pixel width (aka screen h-resolution if full screen)
  67. uint m_backBufferHeight; // pixel height (aka screen v-resolution if full screen)
  68. D3DFORMAT m_backBufferFormat; // pixel format
  69. uint m_multiSampleCount; // 0 means no MSAA, 2 means 2x MSAA, etc
  70. // uint m_multiSampleQuality; // no MSAA quality control yet
  71. bool m_enableAutoDepthStencil; // generally set to 'TRUE' per CShaderDeviceDx8::SetPresentParameters
  72. D3DFORMAT m_autoDepthStencilFormat;
  73. uint m_fsRefreshHz; // if full screen, this refresh rate (likely 0 for LCD's)
  74. //uint m_rootRendererID; // only used if m_rendererIndex is -1.
  75. //uint m_rootDisplayMask; // only used if m_rendererIndex is -1.
  76. bool m_mtgl; // enable multi threaded GL driver
  77. };
  78. //===============================================================================
  79. class GLMgr
  80. {
  81. public:
  82. //===========================================================================
  83. // class methods - singleton
  84. static void NewGLMgr( void ); // instantiate singleton..
  85. static GLMgr *aGLMgr( void ); // return singleton..
  86. static void DelGLMgr( void ); // tear down singleton..
  87. //===========================================================================
  88. // plain methods
  89. #if 0 // turned all these off while new approach is coded
  90. void RefreshDisplayDB( void ); // blow away old display DB, make a new one
  91. GLMDisplayDB *GetDisplayDB( void ); // get a ptr to the one GLMgr keeps. only valid til next refresh.
  92. // eligible renderers will be ranked by desirability starting at index 0 within the db
  93. // within each renderer, eligible displays will be ranked some kind of desirability (area? dist from menu bar?)
  94. // within each display, eligible modes will be ranked by descending areas
  95. // calls supplying indices are implicitly making reference to the current DB
  96. bool CaptureDisplay( int rendIndex, int displayIndex, bool captureAll ); // capture one display or all displays
  97. void ReleaseDisplays( void ); // release all captures
  98. int GetDisplayMode( int rendIndex, int displayIndex ); // retrieve current display res (returns modeIndex)
  99. void SetDisplayMode( GLMDisplayParams *params ); // set the display res (only useful for FS)
  100. #endif
  101. GLMContext *NewContext( IDirect3DDevice9 *pDevice, GLMDisplayParams *params ); // this will have to change
  102. void DelContext( GLMContext *context );
  103. // with usage of CGLMacro.h we could dispense with the "current context" thing
  104. // and just declare a member variable of GLMContext, allowing each glXXX call to be routed directly
  105. // to the correct context
  106. void SetCurrentContext( GLMContext *context ); // make current in calling thread only
  107. GLMContext *GetCurrentContext( void );
  108. protected:
  109. friend class GLMContext;
  110. GLMgr();
  111. ~GLMgr();
  112. };
  113. //===========================================================================//
  114. // helper function to do enable or disable in one step
  115. FORCEINLINE void glSetEnable( GLenum which, bool enable )
  116. {
  117. if (enable)
  118. gGL->glEnable(which);
  119. else
  120. gGL->glDisable(which);
  121. }
  122. // helper function for int vs enum clarity
  123. FORCEINLINE void glGetEnumv( GLenum which, GLenum *dst )
  124. {
  125. gGL->glGetIntegerv( which, (int*)dst );
  126. }
  127. //===========================================================================//
  128. //
  129. // types to support the GLMContext
  130. //
  131. //===========================================================================//
  132. // Each state set/get path we are providing caching for, needs its own struct and a comparison operator.
  133. // we also provide an enum of how many such types there are, handy for building dirty masks etc.
  134. // shorthand macros
  135. #define EQ(fff) ( (src.fff) == (fff) )
  136. //rasterizer
  137. struct GLAlphaTestEnable_t { GLint enable; inline bool operator==(const GLAlphaTestEnable_t& src) const { return EQ(enable); } };
  138. struct GLAlphaTestFunc_t { GLenum func; GLclampf ref; inline bool operator==(const GLAlphaTestFunc_t& src) const { return EQ(func) && EQ(ref); } };
  139. struct GLCullFaceEnable_t { GLint enable; inline bool operator==(const GLCullFaceEnable_t& src) const { return EQ(enable); } };
  140. struct GLCullFrontFace_t { GLenum value; inline bool operator==(const GLCullFrontFace_t& src) const { return EQ(value); } };
  141. struct GLPolygonMode_t { GLenum values[2]; inline bool operator==(const GLPolygonMode_t& src) const { return EQ(values[0]) && EQ(values[1]); } };
  142. struct GLDepthBias_t { GLfloat factor; GLfloat units; inline bool operator==(const GLDepthBias_t& src) const { return EQ(factor) && EQ(units); } };
  143. struct GLScissorEnable_t { GLint enable; inline bool operator==(const GLScissorEnable_t& src) const { return EQ(enable); } };
  144. struct GLScissorBox_t { GLint x,y; GLsizei width, height; inline bool operator==(const GLScissorBox_t& src) const { return EQ(x) && EQ(y) && EQ(width) && EQ(height); } };
  145. struct GLAlphaToCoverageEnable_t{ GLint enable; inline bool operator==(const GLAlphaToCoverageEnable_t& src) const { return EQ(enable); } };
  146. struct GLViewportBox_t { GLint x,y; GLsizei width, height; uint widthheight; inline bool operator==(const GLViewportBox_t& src) const { return EQ(x) && EQ(y) && EQ(width) && EQ(height); } };
  147. struct GLViewportDepthRange_t { GLdouble flNear,flFar; inline bool operator==(const GLViewportDepthRange_t& src) const { return EQ(flNear) && EQ(flFar); } };
  148. struct GLClipPlaneEnable_t { GLint enable; inline bool operator==(const GLClipPlaneEnable_t& src) const { return EQ(enable); } };
  149. struct GLClipPlaneEquation_t { GLfloat x,y,z,w; inline bool operator==(const GLClipPlaneEquation_t& src) const { return EQ(x) && EQ(y) && EQ(z) && EQ(w); } };
  150. //blend
  151. struct GLColorMaskSingle_t { char r,g,b,a; inline bool operator==(const GLColorMaskSingle_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } };
  152. struct GLColorMaskMultiple_t { char r,g,b,a; inline bool operator==(const GLColorMaskMultiple_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } };
  153. struct GLBlendEnable_t { GLint enable; inline bool operator==(const GLBlendEnable_t& src) const { return EQ(enable); } };
  154. struct GLBlendFactor_t { GLenum srcfactor,dstfactor; inline bool operator==(const GLBlendFactor_t& src) const { return EQ(srcfactor) && EQ(dstfactor); } };
  155. struct GLBlendEquation_t { GLenum equation; inline bool operator==(const GLBlendEquation_t& src) const { return EQ(equation); } };
  156. struct GLBlendColor_t { GLfloat r,g,b,a; inline bool operator==(const GLBlendColor_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } };
  157. struct GLBlendEnableSRGB_t { GLint enable; inline bool operator==(const GLBlendEnableSRGB_t& src) const { return EQ(enable); } };
  158. //depth
  159. struct GLDepthTestEnable_t { GLint enable; inline bool operator==(const GLDepthTestEnable_t& src) const { return EQ(enable); } };
  160. struct GLDepthFunc_t { GLenum func; inline bool operator==(const GLDepthFunc_t& src) const { return EQ(func); } };
  161. struct GLDepthMask_t { char mask; inline bool operator==(const GLDepthMask_t& src) const { return EQ(mask); } };
  162. //stencil
  163. struct GLStencilTestEnable_t { GLint enable; inline bool operator==(const GLStencilTestEnable_t& src) const { return EQ(enable); } };
  164. struct GLStencilFunc_t { GLenum frontfunc, backfunc; GLint ref; GLuint mask; inline bool operator==(const GLStencilFunc_t& src) const { return EQ(frontfunc) && EQ(backfunc) && EQ(ref) && EQ(mask); } };
  165. struct GLStencilOp_t { GLenum sfail; GLenum dpfail; GLenum dppass; inline bool operator==(const GLStencilOp_t& src) const { return EQ(sfail) && EQ(dpfail) && EQ(dppass); } };
  166. struct GLStencilWriteMask_t { GLint mask; inline bool operator==(const GLStencilWriteMask_t& src) const { return EQ(mask); } };
  167. //clearing
  168. struct GLClearColor_t { GLfloat r,g,b,a; inline bool operator==(const GLClearColor_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } };
  169. struct GLClearDepth_t { GLdouble d; inline bool operator==(const GLClearDepth_t& src) const { return EQ(d); } };
  170. struct GLClearStencil_t { GLint s; inline bool operator==(const GLClearStencil_t& src) const { return EQ(s); } };
  171. #undef EQ
  172. enum EGLMStateBlockType
  173. {
  174. kGLAlphaTestEnable,
  175. kGLAlphaTestFunc,
  176. kGLCullFaceEnable,
  177. kGLCullFrontFace,
  178. kGLPolygonMode,
  179. kGLDepthBias,
  180. kGLScissorEnable,
  181. kGLScissorBox,
  182. kGLViewportBox,
  183. kGLViewportDepthRange,
  184. kGLClipPlaneEnable,
  185. kGLClipPlaneEquation,
  186. kGLColorMaskSingle,
  187. kGLColorMaskMultiple,
  188. kGLBlendEnable,
  189. kGLBlendFactor,
  190. kGLBlendEquation,
  191. kGLBlendColor,
  192. kGLBlendEnableSRGB,
  193. kGLDepthTestEnable,
  194. kGLDepthFunc,
  195. kGLDepthMask,
  196. kGLStencilTestEnable,
  197. kGLStencilFunc,
  198. kGLStencilOp,
  199. kGLStencilWriteMask,
  200. kGLClearColor,
  201. kGLClearDepth,
  202. kGLClearStencil,
  203. kGLAlphaToCoverageEnable,
  204. kGLMStateBlockLimit
  205. };
  206. //===========================================================================//
  207. // templated functions representing GL R/W bottlenecks
  208. // one set of set/get/getdefault is instantiated for each of the GL*** types above.
  209. // use these from the non array state objects
  210. template<typename T> void GLContextSet( T *src );
  211. template<typename T> void GLContextGet( T *dst );
  212. template<typename T> void GLContextGetDefault( T *dst );
  213. // use these from the array state objects
  214. template<typename T> void GLContextSetIndexed( T *src, int index );
  215. template<typename T> void GLContextGetIndexed( T *dst, int index );
  216. template<typename T> void GLContextGetDefaultIndexed( T *dst, int index );
  217. //===============================================================================
  218. // template specializations for each type of state
  219. // --- GLAlphaTestEnable ---
  220. FORCEINLINE void GLContextSet( GLAlphaTestEnable_t *src )
  221. {
  222. glSetEnable( GL_ALPHA_TEST, src->enable != 0 );
  223. }
  224. FORCEINLINE void GLContextGet( GLAlphaTestEnable_t *dst )
  225. {
  226. dst->enable = gGL->glIsEnabled( GL_ALPHA_TEST );
  227. }
  228. FORCEINLINE void GLContextGetDefault( GLAlphaTestEnable_t *dst )
  229. {
  230. dst->enable = GL_FALSE;
  231. }
  232. // --- GLAlphaTestFunc ---
  233. FORCEINLINE void GLContextSet( GLAlphaTestFunc_t *src )
  234. {
  235. gGL->glAlphaFunc( src->func, src->ref );
  236. }
  237. FORCEINLINE void GLContextGet( GLAlphaTestFunc_t *dst )
  238. {
  239. glGetEnumv( GL_ALPHA_TEST_FUNC, &dst->func );
  240. gGL->glGetFloatv( GL_ALPHA_TEST_REF, &dst->ref );
  241. }
  242. FORCEINLINE void GLContextGetDefault( GLAlphaTestFunc_t *dst )
  243. {
  244. dst->func = GL_ALWAYS;
  245. dst->ref = 0.0f;
  246. }
  247. // --- GLAlphaToCoverageEnable ---
  248. FORCEINLINE void GLContextSet( GLAlphaToCoverageEnable_t *src )
  249. {
  250. glSetEnable( GL_SAMPLE_ALPHA_TO_COVERAGE_ARB, src->enable != 0 );
  251. }
  252. FORCEINLINE void GLContextGet( GLAlphaToCoverageEnable_t *dst )
  253. {
  254. dst->enable = gGL->glIsEnabled( GL_SAMPLE_ALPHA_TO_COVERAGE_ARB );
  255. }
  256. FORCEINLINE void GLContextGetDefault( GLAlphaToCoverageEnable_t *dst )
  257. {
  258. dst->enable = GL_FALSE;
  259. }
  260. // --- GLCullFaceEnable ---
  261. FORCEINLINE void GLContextSet( GLCullFaceEnable_t *src )
  262. {
  263. glSetEnable( GL_CULL_FACE, src->enable != 0 );
  264. }
  265. FORCEINLINE void GLContextGet( GLCullFaceEnable_t *dst )
  266. {
  267. dst->enable = gGL->glIsEnabled( GL_CULL_FACE );
  268. }
  269. FORCEINLINE void GLContextGetDefault( GLCullFaceEnable_t *dst )
  270. {
  271. dst->enable = GL_TRUE;
  272. }
  273. // --- GLCullFrontFace ---
  274. FORCEINLINE void GLContextSet( GLCullFrontFace_t *src )
  275. {
  276. gGL->glFrontFace( src->value ); // legal values are GL_CW or GL_CCW
  277. }
  278. FORCEINLINE void GLContextGet( GLCullFrontFace_t *dst )
  279. {
  280. glGetEnumv( GL_FRONT_FACE, &dst->value );
  281. }
  282. FORCEINLINE void GLContextGetDefault( GLCullFrontFace_t *dst )
  283. {
  284. dst->value = GL_CCW;
  285. }
  286. // --- GLPolygonMode ---
  287. FORCEINLINE void GLContextSet( GLPolygonMode_t *src )
  288. {
  289. gGL->glPolygonMode( GL_FRONT, src->values[0] );
  290. gGL->glPolygonMode( GL_BACK, src->values[1] );
  291. }
  292. FORCEINLINE void GLContextGet( GLPolygonMode_t *dst )
  293. {
  294. glGetEnumv( GL_POLYGON_MODE, &dst->values[0] );
  295. }
  296. FORCEINLINE void GLContextGetDefault( GLPolygonMode_t *dst )
  297. {
  298. dst->values[0] = dst->values[1] = GL_FILL;
  299. }
  300. // --- GLDepthBias ---
  301. // note the implicit enable / disable.
  302. // if you set non zero values, it is enabled, otherwise not.
  303. FORCEINLINE void GLContextSet( GLDepthBias_t *src )
  304. {
  305. bool enable = (src->factor != 0.0f) || (src->units != 0.0f);
  306. glSetEnable( GL_POLYGON_OFFSET_FILL, enable );
  307. gGL->glPolygonOffset( src->factor, src->units );
  308. }
  309. FORCEINLINE void GLContextGet( GLDepthBias_t *dst )
  310. {
  311. gGL->glGetFloatv ( GL_POLYGON_OFFSET_FACTOR, &dst->factor );
  312. gGL->glGetFloatv ( GL_POLYGON_OFFSET_UNITS, &dst->units );
  313. }
  314. FORCEINLINE void GLContextGetDefault( GLDepthBias_t *dst )
  315. {
  316. dst->factor = 0.0;
  317. dst->units = 0.0;
  318. }
  319. // --- GLScissorEnable ---
  320. FORCEINLINE void GLContextSet( GLScissorEnable_t *src )
  321. {
  322. glSetEnable( GL_SCISSOR_TEST, src->enable != 0 );
  323. }
  324. FORCEINLINE void GLContextGet( GLScissorEnable_t *dst )
  325. {
  326. dst->enable = gGL->glIsEnabled( GL_SCISSOR_TEST );
  327. }
  328. FORCEINLINE void GLContextGetDefault( GLScissorEnable_t *dst )
  329. {
  330. dst->enable = GL_FALSE;
  331. }
  332. // --- GLScissorBox ---
  333. FORCEINLINE void GLContextSet( GLScissorBox_t *src )
  334. {
  335. gGL->glScissor ( src->x, src->y, src->width, src->height );
  336. }
  337. FORCEINLINE void GLContextGet( GLScissorBox_t *dst )
  338. {
  339. gGL->glGetIntegerv ( GL_SCISSOR_BOX, &dst->x );
  340. }
  341. FORCEINLINE void GLContextGetDefault( GLScissorBox_t *dst )
  342. {
  343. // hmmmm, good question? we can't really know a good answer so we pick a silly one
  344. // and the client better come back with a better answer later.
  345. dst->x = dst->y = 0;
  346. dst->width = dst->height = 16;
  347. }
  348. // --- GLViewportBox ---
  349. FORCEINLINE void GLContextSet( GLViewportBox_t *src )
  350. {
  351. Assert( src->width == (int)( src->widthheight & 0xFFFF ) );
  352. Assert( src->height == (int)( src->widthheight >> 16 ) );
  353. gGL->glViewport (src->x, src->y, src->width, src->height );
  354. }
  355. FORCEINLINE void GLContextGet( GLViewportBox_t *dst )
  356. {
  357. gGL->glGetIntegerv ( GL_VIEWPORT, &dst->x );
  358. dst->widthheight = dst->width | ( dst->height << 16 );
  359. }
  360. FORCEINLINE void GLContextGetDefault( GLViewportBox_t *dst )
  361. {
  362. // as with the scissor box, we don't know yet, so pick a silly one and change it later
  363. dst->x = dst->y = 0;
  364. dst->width = dst->height = 16;
  365. dst->widthheight = dst->width | ( dst->height << 16 );
  366. }
  367. // --- GLViewportDepthRange ---
  368. FORCEINLINE void GLContextSet( GLViewportDepthRange_t *src )
  369. {
  370. gGL->glDepthRange ( src->flNear, src->flFar );
  371. }
  372. FORCEINLINE void GLContextGet( GLViewportDepthRange_t *dst )
  373. {
  374. gGL->glGetDoublev ( GL_DEPTH_RANGE, &dst->flNear );
  375. }
  376. FORCEINLINE void GLContextGetDefault( GLViewportDepthRange_t *dst )
  377. {
  378. dst->flNear = 0.0;
  379. dst->flFar = 1.0;
  380. }
  381. // --- GLClipPlaneEnable ---
  382. FORCEINLINE void GLContextSetIndexed( GLClipPlaneEnable_t *src, int index )
  383. {
  384. #if GLMDEBUG
  385. if (CommandLine()->FindParm("-caps_noclipplanes"))
  386. {
  387. if (GLMKnob("caps-key",NULL) > 0.0)
  388. {
  389. // caps ON means NO clipping
  390. src->enable = false;
  391. }
  392. }
  393. #endif
  394. glSetEnable( GL_CLIP_PLANE0 + index, src->enable != 0 );
  395. }
  396. FORCEINLINE void GLContextGetIndexed( GLClipPlaneEnable_t *dst, int index )
  397. {
  398. dst->enable = gGL->glIsEnabled( GL_CLIP_PLANE0 + index );
  399. }
  400. FORCEINLINE void GLContextGetDefaultIndexed( GLClipPlaneEnable_t *dst, int index )
  401. {
  402. dst->enable = 0;
  403. }
  404. // --- GLClipPlaneEquation ---
  405. FORCEINLINE void GLContextSetIndexed( GLClipPlaneEquation_t *src, int index )
  406. {
  407. // shove into glGlipPlane
  408. GLdouble coeffs[4] = { src->x, src->y, src->z, src->w };
  409. gGL->glClipPlane( GL_CLIP_PLANE0 + index, coeffs );
  410. }
  411. FORCEINLINE void GLContextGetIndexed( GLClipPlaneEquation_t *dst, int index )
  412. {
  413. DebuggerBreak(); // do this later
  414. // glClipPlane( GL_CLIP_PLANE0 + index, coeffs );
  415. // GLdouble coeffs[4] = { src->x, src->y, src->z, src->w };
  416. }
  417. FORCEINLINE void GLContextGetDefaultIndexed( GLClipPlaneEquation_t *dst, int index )
  418. {
  419. dst->x = 1.0;
  420. dst->y = 0.0;
  421. dst->z = 0.0;
  422. dst->w = 0.0;
  423. }
  424. // --- GLColorMaskSingle ---
  425. FORCEINLINE void GLContextSet( GLColorMaskSingle_t *src )
  426. {
  427. gGL->glColorMask( src->r, src->g, src->b, src->a );
  428. }
  429. FORCEINLINE void GLContextGet( GLColorMaskSingle_t *dst )
  430. {
  431. gGL->glGetBooleanv( GL_COLOR_WRITEMASK, (GLboolean*)&dst->r);
  432. }
  433. FORCEINLINE void GLContextGetDefault( GLColorMaskSingle_t *dst )
  434. {
  435. dst->r = dst->g = dst->b = dst->a = 1;
  436. }
  437. // --- GLColorMaskMultiple ---
  438. FORCEINLINE void GLContextSetIndexed( GLColorMaskMultiple_t *src, int index )
  439. {
  440. gGL->glColorMaskIndexedEXT ( index, src->r, src->g, src->b, src->a );
  441. }
  442. FORCEINLINE void GLContextGetIndexed( GLColorMaskMultiple_t *dst, int index )
  443. {
  444. gGL->glGetBooleanIndexedvEXT ( GL_COLOR_WRITEMASK, index, (GLboolean*)&dst->r );
  445. }
  446. FORCEINLINE void GLContextGetDefaultIndexed( GLColorMaskMultiple_t *dst, int index )
  447. {
  448. dst->r = dst->g = dst->b = dst->a = 1;
  449. }
  450. // --- GLBlendEnable ---
  451. FORCEINLINE void GLContextSet( GLBlendEnable_t *src )
  452. {
  453. glSetEnable( GL_BLEND, src->enable != 0 );
  454. }
  455. FORCEINLINE void GLContextGet( GLBlendEnable_t *dst )
  456. {
  457. dst->enable = gGL->glIsEnabled( GL_BLEND );
  458. }
  459. FORCEINLINE void GLContextGetDefault( GLBlendEnable_t *dst )
  460. {
  461. dst->enable = GL_FALSE;
  462. }
  463. // --- GLBlendFactor ---
  464. FORCEINLINE void GLContextSet( GLBlendFactor_t *src )
  465. {
  466. gGL->glBlendFunc ( src->srcfactor, src->dstfactor );
  467. }
  468. FORCEINLINE void GLContextGet( GLBlendFactor_t *dst )
  469. {
  470. glGetEnumv ( GL_BLEND_SRC, &dst->srcfactor );
  471. glGetEnumv ( GL_BLEND_DST, &dst->dstfactor );
  472. }
  473. FORCEINLINE void GLContextGetDefault( GLBlendFactor_t *dst )
  474. {
  475. dst->srcfactor = GL_ONE;
  476. dst->dstfactor = GL_ZERO;
  477. }
  478. // --- GLBlendEquation ---
  479. FORCEINLINE void GLContextSet( GLBlendEquation_t *src )
  480. {
  481. gGL->glBlendEquation ( src->equation );
  482. }
  483. FORCEINLINE void GLContextGet( GLBlendEquation_t *dst )
  484. {
  485. glGetEnumv ( GL_BLEND_EQUATION, &dst->equation );
  486. }
  487. FORCEINLINE void GLContextGetDefault( GLBlendEquation_t *dst )
  488. {
  489. dst->equation = GL_FUNC_ADD;
  490. }
  491. // --- GLBlendColor ---
  492. FORCEINLINE void GLContextSet( GLBlendColor_t *src )
  493. {
  494. gGL->glBlendColor ( src->r, src->g, src->b, src->a );
  495. }
  496. FORCEINLINE void GLContextGet( GLBlendColor_t *dst )
  497. {
  498. gGL->glGetFloatv ( GL_BLEND_COLOR, &dst->r );
  499. }
  500. FORCEINLINE void GLContextGetDefault( GLBlendColor_t *dst )
  501. {
  502. //solid white
  503. dst->r = dst->g = dst->b = dst->a = 1.0;
  504. }
  505. // --- GLBlendEnableSRGB ---
  506. #define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
  507. #define GL_COLOR_ATTACHMENT0 0x8CE0
  508. FORCEINLINE void GLContextSet( GLBlendEnableSRGB_t *src )
  509. {
  510. #if GLMDEBUG
  511. // just check in debug... this is too expensive to look at on MTGL
  512. if (src->enable)
  513. {
  514. GLboolean srgb_capable = false;
  515. gGL->glGetBooleanv( GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgb_capable);
  516. if (src->enable && !srgb_capable)
  517. {
  518. GLMPRINTF(("-Z- srgb-state-set FBO conflict: attempt to enable SRGB on non SRGB capable FBO config"));
  519. }
  520. }
  521. #endif
  522. // this query is not useful unless you have the ARB_framebuffer_srgb ext.
  523. //GLint encoding = 0;
  524. //pfnglGetFramebufferAttachmentParameteriv( GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &encoding );
  525. glSetEnable( GL_FRAMEBUFFER_SRGB_EXT, src->enable != 0 );
  526. }
  527. FORCEINLINE void GLContextGet( GLBlendEnableSRGB_t *dst )
  528. {
  529. //dst->enable = glIsEnabled( GL_FRAMEBUFFER_SRGB_EXT );
  530. dst->enable = true; // wtf ?
  531. }
  532. FORCEINLINE void GLContextGetDefault( GLBlendEnableSRGB_t *dst )
  533. {
  534. dst->enable = GL_FALSE;
  535. }
  536. // --- GLDepthTestEnable ---
  537. FORCEINLINE void GLContextSet( GLDepthTestEnable_t *src )
  538. {
  539. glSetEnable( GL_DEPTH_TEST, src->enable != 0 );
  540. }
  541. FORCEINLINE void GLContextGet( GLDepthTestEnable_t *dst )
  542. {
  543. dst->enable = gGL->glIsEnabled( GL_DEPTH_TEST );
  544. }
  545. FORCEINLINE void GLContextGetDefault( GLDepthTestEnable_t *dst )
  546. {
  547. dst->enable = GL_FALSE;
  548. }
  549. // --- GLDepthFunc ---
  550. FORCEINLINE void GLContextSet( GLDepthFunc_t *src )
  551. {
  552. gGL->glDepthFunc ( src->func );
  553. }
  554. FORCEINLINE void GLContextGet( GLDepthFunc_t *dst )
  555. {
  556. glGetEnumv ( GL_DEPTH_FUNC, &dst->func );
  557. }
  558. FORCEINLINE void GLContextGetDefault( GLDepthFunc_t *dst )
  559. {
  560. dst->func = GL_GEQUAL;
  561. }
  562. // --- GLDepthMask ---
  563. FORCEINLINE void GLContextSet( GLDepthMask_t *src )
  564. {
  565. gGL->glDepthMask ( src->mask );
  566. }
  567. FORCEINLINE void GLContextGet( GLDepthMask_t *dst )
  568. {
  569. gGL->glGetBooleanv ( GL_DEPTH_WRITEMASK, (GLboolean*)&dst->mask );
  570. }
  571. FORCEINLINE void GLContextGetDefault( GLDepthMask_t *dst )
  572. {
  573. dst->mask = GL_TRUE;
  574. }
  575. // --- GLStencilTestEnable ---
  576. FORCEINLINE void GLContextSet( GLStencilTestEnable_t *src )
  577. {
  578. glSetEnable( GL_STENCIL_TEST, src->enable != 0 );
  579. }
  580. FORCEINLINE void GLContextGet( GLStencilTestEnable_t *dst )
  581. {
  582. dst->enable = gGL->glIsEnabled( GL_STENCIL_TEST );
  583. }
  584. FORCEINLINE void GLContextGetDefault( GLStencilTestEnable_t *dst )
  585. {
  586. dst->enable = GL_FALSE;
  587. }
  588. // --- GLStencilFunc ---
  589. FORCEINLINE void GLContextSet( GLStencilFunc_t *src )
  590. {
  591. if (src->frontfunc == src->backfunc)
  592. gGL->glStencilFuncSeparate( GL_FRONT_AND_BACK, src->frontfunc, src->ref, src->mask);
  593. else
  594. {
  595. gGL->glStencilFuncSeparate( GL_FRONT, src->frontfunc, src->ref, src->mask);
  596. gGL->glStencilFuncSeparate( GL_BACK, src->backfunc, src->ref, src->mask);
  597. }
  598. }
  599. FORCEINLINE void GLContextGet( GLStencilFunc_t *dst )
  600. {
  601. glGetEnumv ( GL_STENCIL_FUNC, &dst->frontfunc );
  602. glGetEnumv ( GL_STENCIL_BACK_FUNC, &dst->backfunc );
  603. gGL->glGetIntegerv ( GL_STENCIL_REF, &dst->ref );
  604. gGL->glGetIntegerv ( GL_STENCIL_VALUE_MASK, (GLint*)&dst->mask );
  605. }
  606. FORCEINLINE void GLContextGetDefault( GLStencilFunc_t *dst )
  607. {
  608. dst->frontfunc = GL_ALWAYS;
  609. dst->backfunc = GL_ALWAYS;
  610. dst->ref = 0;
  611. dst->mask = 0xFFFFFFFF;
  612. }
  613. // --- GLStencilOp --- indexed 0=front, 1=back
  614. FORCEINLINE void GLContextSetIndexed( GLStencilOp_t *src, int index )
  615. {
  616. GLenum face = (index==0) ? GL_FRONT : GL_BACK;
  617. gGL->glStencilOpSeparate( face, src->sfail, src->dpfail, src->dppass );
  618. }
  619. FORCEINLINE void GLContextGetIndexed( GLStencilOp_t *dst, int index )
  620. {
  621. glGetEnumv ( (index==0) ? GL_STENCIL_FAIL : GL_STENCIL_BACK_FAIL, &dst->sfail );
  622. glGetEnumv ( (index==0) ? GL_STENCIL_PASS_DEPTH_FAIL : GL_STENCIL_BACK_PASS_DEPTH_FAIL, &dst->dpfail );
  623. glGetEnumv ( (index==0) ? GL_STENCIL_PASS_DEPTH_PASS : GL_STENCIL_BACK_PASS_DEPTH_PASS, &dst->dppass );
  624. }
  625. FORCEINLINE void GLContextGetDefaultIndexed( GLStencilOp_t *dst, int index )
  626. {
  627. dst->sfail = dst->dpfail = dst->dppass = GL_KEEP;
  628. }
  629. // --- GLStencilWriteMask ---
  630. FORCEINLINE void GLContextSet( GLStencilWriteMask_t *src )
  631. {
  632. gGL->glStencilMask( src->mask );
  633. }
  634. FORCEINLINE void GLContextGet( GLStencilWriteMask_t *dst )
  635. {
  636. gGL->glGetIntegerv ( GL_STENCIL_WRITEMASK, &dst->mask );
  637. }
  638. FORCEINLINE void GLContextGetDefault( GLStencilWriteMask_t *dst )
  639. {
  640. dst->mask = 0xFFFFFFFF;
  641. }
  642. // --- GLClearColor ---
  643. FORCEINLINE void GLContextSet( GLClearColor_t *src )
  644. {
  645. gGL->glClearColor( src->r, src->g, src->b, src->a );
  646. }
  647. FORCEINLINE void GLContextGet( GLClearColor_t *dst )
  648. {
  649. gGL->glGetFloatv ( GL_COLOR_CLEAR_VALUE, &dst->r );
  650. }
  651. FORCEINLINE void GLContextGetDefault( GLClearColor_t *dst )
  652. {
  653. dst->r = dst->g = dst->b = 0.5;
  654. dst->a = 1.0;
  655. }
  656. // --- GLClearDepth ---
  657. FORCEINLINE void GLContextSet( GLClearDepth_t *src )
  658. {
  659. gGL->glClearDepth ( src->d );
  660. }
  661. FORCEINLINE void GLContextGet( GLClearDepth_t *dst )
  662. {
  663. gGL->glGetDoublev ( GL_DEPTH_CLEAR_VALUE, &dst->d );
  664. }
  665. FORCEINLINE void GLContextGetDefault( GLClearDepth_t *dst )
  666. {
  667. dst->d = 1.0;
  668. }
  669. // --- GLClearStencil ---
  670. FORCEINLINE void GLContextSet( GLClearStencil_t *src )
  671. {
  672. gGL->glClearStencil( src->s );
  673. }
  674. FORCEINLINE void GLContextGet( GLClearStencil_t *dst )
  675. {
  676. gGL->glGetIntegerv ( GL_STENCIL_CLEAR_VALUE, &dst->s );
  677. }
  678. FORCEINLINE void GLContextGetDefault( GLClearStencil_t *dst )
  679. {
  680. dst->s = 0;
  681. }
  682. //===========================================================================//
  683. // caching state object template. One of these is instantiated in the context per unique struct type above
  684. template<typename T> class GLState
  685. {
  686. public:
  687. inline GLState()
  688. {
  689. memset( &data, 0, sizeof(data) );
  690. Default();
  691. }
  692. FORCEINLINE void Flush()
  693. {
  694. // immediately blast out the state - it makes no sense to delta it or do anything fancy because shaderapi, dxabstract, and OpenGL itself does this for us (and OpenGL calls with multithreaded drivers are very cheap)
  695. GLContextSet( &data );
  696. }
  697. // write: client src into cache
  698. // common case is both false. dirty is calculated, context write is deferred.
  699. FORCEINLINE void Write( const T *src )
  700. {
  701. data = *src;
  702. Flush();
  703. }
  704. // default: write default value to cache, optionally write through
  705. inline void Default( bool noDefer=false )
  706. {
  707. GLContextGetDefault( &data ); // read default values directly to our cache copy
  708. Flush();
  709. }
  710. // read: sel = 0 for cache, 1 for context
  711. inline void Read( T *dst, int sel )
  712. {
  713. if (sel==0)
  714. *dst = data;
  715. else
  716. GLContextGet( dst );
  717. }
  718. // check: verify that context equals cache, return true if mismatched or if illegal values seen
  719. inline bool Check ( void )
  720. {
  721. T temp;
  722. bool result;
  723. GLContextGet( &temp );
  724. result = !(temp == data);
  725. return result;
  726. }
  727. FORCEINLINE const T &GetData() const { return data; }
  728. protected:
  729. T data;
  730. };
  731. // caching state object template - with multiple values behind it that are indexed
  732. template<typename T, int COUNT> class GLStateArray
  733. {
  734. public:
  735. inline GLStateArray()
  736. {
  737. memset( &data, 0, sizeof(data) );
  738. Default();
  739. }
  740. // write cache->context if dirty or forced.
  741. FORCEINLINE void FlushIndex( int index )
  742. {
  743. // immediately blast out the state - it makes no sense to delta it or do anything fancy because shaderapi, dxabstract, and OpenGL itself does this for us (and OpenGL calls with multithreaded drivers are very cheap)
  744. GLContextSetIndexed( &data[index], index );
  745. };
  746. // write: client src into cache
  747. // common case is both false. dirty is calculated, context write is deferred.
  748. FORCEINLINE void WriteIndex( T *src, int index )
  749. {
  750. data[index] = *src;
  751. FlushIndex( index ); // dirty becomes false
  752. };
  753. // write all slots in the array
  754. FORCEINLINE void Flush()
  755. {
  756. for( int i=0; i < COUNT; i++)
  757. {
  758. FlushIndex( i );
  759. }
  760. }
  761. // default: write default value to cache, optionally write through
  762. inline void DefaultIndex( int index )
  763. {
  764. GLContextGetDefaultIndexed( &data[index], index ); // read default values directly to our cache copy
  765. Flush();
  766. };
  767. inline void Default( void )
  768. {
  769. for( int i=0; i<COUNT; i++)
  770. {
  771. DefaultIndex( i );
  772. }
  773. }
  774. // read: sel = 0 for cache, 1 for context
  775. inline void ReadIndex( T *dst, int index, int sel )
  776. {
  777. if (sel==0)
  778. *dst = data[index];
  779. else
  780. GLContextGetIndexed( dst, index );
  781. };
  782. // check: verify that context equals cache, return true if mismatched or if illegal values seen
  783. inline bool CheckIndex( int index )
  784. {
  785. T temp;
  786. bool result;
  787. GLContextGetIndexed( &temp, index );
  788. result = !(temp == data[index]);
  789. return result;
  790. };
  791. inline bool Check( void )
  792. {
  793. //T temp;
  794. bool result = false;
  795. for( int i=0; i<COUNT; i++)
  796. {
  797. result |= CheckIndex( i );
  798. }
  799. return result;
  800. };
  801. protected:
  802. T data[COUNT];
  803. };
  804. //===========================================================================//
  805. struct GLMTexSampler
  806. {
  807. CGLMTex *m_pBoundTex; // tex which is actually bound now
  808. GLMTexSamplingParams m_samp; // current 2D sampler state
  809. };
  810. // GLMContext will maintain one of these structures inside the context to represent the current state.
  811. // Client can supply a new one when it wants to change the setup.
  812. //FIXME GLMContext can do the work to migrate from old setup to new setup as efficiently as possible (but it doesn't yet)
  813. struct GLMVertexSetup
  814. {
  815. uint m_attrMask; // which attrs are enabled (1<<n) mask where n is a GLMVertexAttributeIndex.
  816. GLMVertexAttributeDesc m_attrs[ kGLMVertexAttributeIndexMax ];
  817. // copied in from dxabstract, not strictly needed for operation, helps debugging
  818. unsigned char m_vtxAttribMap[16];
  819. /* high nibble is usage per _D3DDECLUSAGE
  820. typedef enum _D3DDECLUSAGE
  821. {
  822. D3DDECLUSAGE_POSITION = 0,
  823. D3DDECLUSAGE_BLENDWEIGHT = 1,
  824. D3DDECLUSAGE_BLENDINDICES = 2,
  825. D3DDECLUSAGE_NORMAL = 3,
  826. D3DDECLUSAGE_PSIZE = 4,
  827. D3DDECLUSAGE_TEXCOORD = 5,
  828. D3DDECLUSAGE_TANGENT = 6,
  829. D3DDECLUSAGE_BINORMAL = 7,
  830. D3DDECLUSAGE_TESSFACTOR = 8,
  831. D3DDECLUSAGE_PLUGH = 9, // mystery value
  832. D3DDECLUSAGE_COLOR = 10,
  833. D3DDECLUSAGE_FOG = 11,
  834. D3DDECLUSAGE_DEPTH = 12,
  835. D3DDECLUSAGE_SAMPLE = 13,
  836. } D3DDECLUSAGE;
  837. low nibble is usageindex (i.e. POSITION0, POSITION1, etc)
  838. array position is attrib number.
  839. */
  840. };
  841. //===========================================================================//
  842. //FIXME magic numbers here
  843. #define kGLMProgramParamFloat4Limit 256
  844. #define kGLMProgramParamBoolLimit 16
  845. #define kGLMProgramParamInt4Limit 16
  846. #define kGLMVertexProgramParamFloat4Limit 256
  847. #define kGLMFragmentProgramParamFloat4Limit 256
  848. struct GLMProgramParamsF
  849. {
  850. float m_values[kGLMProgramParamFloat4Limit][4]; // float4's 256 of them
  851. int m_firstDirtySlotNonBone;
  852. int m_dirtySlotHighWaterNonBone; // index of slot past highest dirty non-bone register (assume 0 for base of range)
  853. int m_dirtySlotHighWaterBone; // index of slot past highest dirty bone register (0=first bone reg, which is DXABSTRACT_VS_FIRST_BONE_SLOT)
  854. };
  855. struct GLMProgramParamsB
  856. {
  857. int m_values[kGLMProgramParamBoolLimit]; // bools, 4 of them
  858. uint m_dirtySlotCount;
  859. };
  860. struct GLMProgramParamsI
  861. {
  862. int m_values[kGLMProgramParamInt4Limit][4]; // int4s, 16 of them
  863. uint m_dirtySlotCount;
  864. };
  865. enum EGLMParamWriteMode
  866. {
  867. eParamWriteAllSlots, // glUniform4fv of the maximum size (not recommended if shader is down-sizing the decl)
  868. eParamWriteShaderSlots, // glUniform4fv of the active slot count ("highwater")
  869. eParamWriteShaderSlotsOptional, // glUniform4fv of the active slot count ("highwater") - but only if at least one has been written - it's optional
  870. eParamWriteDirtySlotRange // glUniform4fv of the 0-N range where N is highest dirty slot
  871. };
  872. enum EGLMAttribWriteMode
  873. {
  874. eAttribWriteAll,
  875. eAttribWriteDirty
  876. };
  877. //===========================================================================//
  878. #if GLMDEBUG
  879. enum EGLMDebugCallSite
  880. {
  881. eBeginFrame, // inside begin frame func - frame number has been inc'd, batch number should be -1
  882. eClear, // inside clear func
  883. eDrawElements, // inside repeat loop, prior to draw call - batch numberhas been inc'd
  884. eEndFrame, // end frame
  885. ePresent // before showing pixels
  886. };
  887. // caller should zero one of these out and fill in the m_caller before invoking the hook
  888. struct GLMDebugHookInfo
  889. {
  890. // info from the caller to the debug hook
  891. EGLMDebugCallSite m_caller;
  892. // state the hook uses to keep track of progress within a single run of the caller
  893. int m_iteration; // which call to the hook is this. if it's zero, it precedes any action in the caller.
  894. // bools used to communicate between caller and hook
  895. bool m_loop; // hook tells caller to loop around again (don't exit)
  896. bool m_holding; // current mood of hook, are we holding on this batch (i.e. rerun)
  897. // specific info for a draw call
  898. GLenum m_drawMode;
  899. GLuint m_drawStart;
  900. GLuint m_drawEnd;
  901. GLsizei m_drawCount;
  902. GLenum m_drawType;
  903. const GLvoid *m_drawIndices;
  904. };
  905. #endif
  906. //===========================================================================//
  907. class CFlushDrawStatesStats
  908. {
  909. public:
  910. CFlushDrawStatesStats()
  911. {
  912. Clear();
  913. }
  914. void Clear()
  915. {
  916. memset(this, 0, sizeof(*this));
  917. }
  918. uint m_nTotalBatchFlushes;
  919. uint m_nTotalProgramPairChanges;
  920. uint m_nNumChangedSamplers;
  921. uint m_nNumSamplingParamsChanged;
  922. uint m_nIndexBufferChanged;
  923. uint m_nVertexBufferChanged;
  924. uint m_nFirstVSConstant;
  925. uint m_nNumVSConstants;
  926. uint m_nNumVSBoneConstants;
  927. uint m_nFirstPSConstant;
  928. uint m_nNumPSConstants;
  929. uint m_nNewPS;
  930. uint m_nNewVS;
  931. };
  932. //===========================================================================//
  933. #ifndef OSX
  934. #ifndef GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD
  935. #define GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD 0x9160
  936. #endif
  937. #define GLMGR_PINNED_MEMORY_BUFFER_SIZE ( 6 * 1024 * 1024 )
  938. class CPinnedMemoryBuffer
  939. {
  940. CPinnedMemoryBuffer( const CPinnedMemoryBuffer & );
  941. CPinnedMemoryBuffer & operator= ( const CPinnedMemoryBuffer & );
  942. public:
  943. CPinnedMemoryBuffer()
  944. :
  945. m_pRawBuf( NULL )
  946. , m_pBuf( NULL )
  947. , m_nSize( 0 )
  948. , m_nOfs( 0 )
  949. , m_nBufferObj( 0 )
  950. #ifdef HAVE_GL_ARB_SYNC
  951. , m_nSyncObj( 0 )
  952. #endif
  953. {
  954. }
  955. ~CPinnedMemoryBuffer()
  956. {
  957. Deinit();
  958. }
  959. bool Init( uint nSize )
  960. {
  961. Deinit();
  962. // Guarantee 64KB alignment
  963. m_pRawBuf = malloc( nSize + 65535 );
  964. m_pBuf = reinterpret_cast<void *>((reinterpret_cast<uint64>(m_pRawBuf) + 65535) & (~65535));
  965. m_nSize = nSize;
  966. m_nOfs = 0;
  967. gGL->glGenBuffersARB( 1, &m_nBufferObj );
  968. gGL->glBindBufferARB( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, m_nBufferObj );
  969. gGL->glBufferDataARB( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, m_nSize, m_pBuf, GL_STREAM_COPY );
  970. return true;
  971. }
  972. void Deinit()
  973. {
  974. if ( !m_pRawBuf )
  975. return;
  976. BlockUntilNotBusy();
  977. gGL->glBindBufferARB(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, m_nBufferObj );
  978. gGL->glBufferDataARB( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0, (void*)NULL, GL_STREAM_COPY );
  979. gGL->glBindBufferARB( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0 );
  980. gGL->glDeleteBuffersARB( 1, &m_nBufferObj );
  981. m_nBufferObj = 0;
  982. free( m_pRawBuf );
  983. m_pRawBuf = NULL;
  984. m_pBuf = NULL;
  985. m_nSize = 0;
  986. m_nOfs = 0;
  987. }
  988. inline uint GetSize() const { return m_nSize; }
  989. inline uint GetOfs() const { return m_nOfs; }
  990. inline uint GetBytesRemaining() const { return m_nSize - m_nOfs; }
  991. inline void *GetPtr() const { return m_pBuf; }
  992. inline GLuint GetHandle() const { return m_nBufferObj; }
  993. void InsertFence()
  994. {
  995. #ifdef HAVE_GL_ARB_SYNC
  996. if ( m_nSyncObj )
  997. {
  998. gGL->glDeleteSync( m_nSyncObj );
  999. }
  1000. m_nSyncObj = gGL->glFenceSync( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 );
  1001. #endif
  1002. }
  1003. void BlockUntilNotBusy()
  1004. {
  1005. #ifdef HAVE_GL_ARB_SYNC
  1006. if ( m_nSyncObj )
  1007. {
  1008. gGL->glClientWaitSync( m_nSyncObj, GL_SYNC_FLUSH_COMMANDS_BIT, 3000000000000ULL );
  1009. gGL->glDeleteSync( m_nSyncObj );
  1010. m_nSyncObj = 0;
  1011. }
  1012. #endif
  1013. m_nOfs = 0;
  1014. }
  1015. void Append( uint nSize )
  1016. {
  1017. m_nOfs += nSize;
  1018. Assert( m_nOfs <= m_nSize );
  1019. }
  1020. private:
  1021. void *m_pRawBuf;
  1022. void *m_pBuf;
  1023. uint m_nSize;
  1024. uint m_nOfs;
  1025. GLuint m_nBufferObj;
  1026. #ifdef HAVE_GL_ARB_SYNC
  1027. GLsync m_nSyncObj;
  1028. #endif
  1029. };
  1030. #endif // OSX
  1031. //===========================================================================//
  1032. class GLMContext
  1033. {
  1034. public:
  1035. // set/check current context (perq for many other calls)
  1036. void MakeCurrent( bool bRenderThread = false );
  1037. void ReleaseCurrent( bool bRenderThread = false );
  1038. // CheckCurrent has been removed (it no longer compiled on Linux). To minimize churn I'm leaving
  1039. // the inline NOP version.
  1040. // DO NOT change this to non-inlined. It's called all over the place from very hot codepaths.
  1041. FORCEINLINE void CheckCurrent( void ) { }
  1042. void PopulateCaps( void ); // fill out later portions of renderer info record which need context queries
  1043. void DumpCaps( void ); // printf all the caps info (you can call this in release too)
  1044. const GLMRendererInfoFields& Caps( void ); // peek at the caps record
  1045. // state cache/mirror
  1046. void SetDefaultStates( void );
  1047. void ForceFlushStates();
  1048. void VerifyStates( void );
  1049. // textures
  1050. // Lock and Unlock reqs go directly to the tex object
  1051. CGLMTex *NewTex( GLMTexLayoutKey *key, uint levels=1, const char *debugLabel=NULL );
  1052. void DelTex( CGLMTex *tex );
  1053. // options for Blit (replacement for ResolveTex and BlitTex)
  1054. // pass NULL for dstTex if you want to target GL_BACK with the blit. You get y-flip with that, don't change the dstrect yourself.
  1055. void Blit2( CGLMTex *srcTex, GLMRect *srcRect, int srcFace, int srcMip, CGLMTex *dstTex, GLMRect *dstRect, int dstFace, int dstMip, uint filter );
  1056. // tex blit (via FBO blit)
  1057. void BlitTex( CGLMTex *srcTex, GLMRect *srcRect, int srcFace, int srcMip, CGLMTex *dstTex, GLMRect *dstRect, int dstFace, int dstMip, uint filter, bool useBlitFB = true );
  1058. // MSAA resolve - we do this in GLMContext because it has to do a bunch of FBO/blit gymnastics
  1059. void ResolveTex( CGLMTex *tex, bool forceDirty=false );
  1060. // texture pre-load (residency forcing) - normally done one-time but you can force it
  1061. void PreloadTex( CGLMTex *tex, bool force=false );
  1062. // samplers
  1063. FORCEINLINE void SetSamplerTex( int sampler, CGLMTex *tex );
  1064. FORCEINLINE void SetSamplerDirty( int sampler );
  1065. FORCEINLINE void SetSamplerMinFilter( int sampler, GLenum Value );
  1066. FORCEINLINE void SetSamplerMagFilter( int sampler, GLenum Value );
  1067. FORCEINLINE void SetSamplerMipFilter( int sampler, GLenum Value );
  1068. FORCEINLINE void SetSamplerAddressU( int sampler, GLenum Value );
  1069. FORCEINLINE void SetSamplerAddressV( int sampler, GLenum Value );
  1070. FORCEINLINE void SetSamplerAddressW( int sampler, GLenum Value );
  1071. FORCEINLINE void SetSamplerStates( int sampler, GLenum AddressU, GLenum AddressV, GLenum AddressW, GLenum minFilter, GLenum magFilter, GLenum mipFilter );
  1072. FORCEINLINE void SetSamplerBorderColor( int sampler, DWORD Value );
  1073. FORCEINLINE void SetSamplerMipMapLODBias( int sampler, DWORD Value );
  1074. FORCEINLINE void SetSamplerMaxMipLevel( int sampler, DWORD Value );
  1075. FORCEINLINE void SetSamplerMaxAnisotropy( int sampler, DWORD Value );
  1076. FORCEINLINE void SetSamplerSRGBTexture( int sampler, DWORD Value );
  1077. FORCEINLINE void SetShadowFilter( int sampler, DWORD Value );
  1078. // render targets (FBO's)
  1079. CGLMFBO *NewFBO( void );
  1080. void DelFBO( CGLMFBO *fbo );
  1081. // programs
  1082. CGLMProgram *NewProgram( EGLMProgramType type, char *progString, const char *pShaderName );
  1083. void DelProgram( CGLMProgram *pProg );
  1084. void NullProgram( void ); // de-ac all shader state
  1085. FORCEINLINE void SetVertexProgram( CGLMProgram *pProg );
  1086. FORCEINLINE void SetFragmentProgram( CGLMProgram *pProg );
  1087. FORCEINLINE void SetProgram( EGLMProgramType nProgType, CGLMProgram *pProg ) { m_drawingProgram[nProgType] = pProg; m_bDirtyPrograms = true; }
  1088. void SetDrawingLang( EGLMProgramLang lang, bool immediate=false ); // choose ARB or GLSL. immediate=false defers lang change to top of frame
  1089. void LinkShaderPair( CGLMProgram *vp, CGLMProgram *fp ); // ensure this combo has been linked and is in the GLSL pair cache
  1090. void ValidateShaderPair( CGLMProgram *vp, CGLMProgram *fp );
  1091. void ClearShaderPairCache( void ); // call this to shoot down all the linked pairs
  1092. void QueryShaderPair( int index, GLMShaderPairInfo *infoOut ); // this lets you query the shader pair cache for saving its state
  1093. // buffers
  1094. // Lock and Unlock reqs go directly to the buffer object
  1095. CGLMBuffer *NewBuffer( EGLMBufferType type, uint size, uint options );
  1096. void DelBuffer( CGLMBuffer *buff );
  1097. FORCEINLINE void SetIndexBuffer( CGLMBuffer *buff ) { BindIndexBufferToCtx( buff ); }
  1098. // FIXME: Remove this, it's no longer used
  1099. FORCEINLINE void SetVertexAttributes( GLMVertexSetup *setup )
  1100. {
  1101. // we now just latch the vert setup and then execute on it at flushdrawstatestime if shaders are enabled.
  1102. if ( setup )
  1103. {
  1104. m_drawVertexSetup = *setup;
  1105. }
  1106. else
  1107. {
  1108. memset( &m_drawVertexSetup, 0, sizeof( m_drawVertexSetup ) );
  1109. }
  1110. }
  1111. // note, no API is exposed for setting a single attribute source.
  1112. // come prepared with a complete block of attributes to use.
  1113. // Queries
  1114. CGLMQuery *NewQuery( GLMQueryParams *params );
  1115. void DelQuery( CGLMQuery *query );
  1116. // "slot" means a vec4-sized thing
  1117. // these write into .env parameter space
  1118. FORCEINLINE void SetProgramParametersF( EGLMProgramType type, uint baseSlot, float *slotData, uint slotCount );
  1119. FORCEINLINE void SetProgramParametersB( EGLMProgramType type, uint baseSlot, int *slotData, uint boolCount ); // take "BOOL" aka int
  1120. FORCEINLINE void SetProgramParametersI( EGLMProgramType type, uint baseSlot, int *slotData, uint slotCount ); // take int4s
  1121. // state sync
  1122. // If lazyUnbinding is true, unbound samplers will not actually be unbound to the GL device.
  1123. FORCEINLINE void FlushDrawStates( uint nStartIndex, uint nEndIndex, uint nBaseVertex ); // pushes all drawing state - samplers, tex, programs, etc.
  1124. void FlushDrawStatesNoShaders();
  1125. // drawing
  1126. #ifndef OSX
  1127. FORCEINLINE void DrawRangeElements( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, uint baseVertex, CGLMBuffer *pIndexBuf );
  1128. void DrawRangeElementsNonInline( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, uint baseVertex, CGLMBuffer *pIndexBuf );
  1129. #else
  1130. void DrawRangeElements( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, CGLMBuffer *pIndexBuf );
  1131. #endif
  1132. void CheckNative( void );
  1133. // clearing
  1134. void Clear( bool color, unsigned long colorValue, bool depth, float depthValue, bool stencil, unsigned int stencilValue, GLScissorBox_t *rect = NULL );
  1135. // display
  1136. //void SetVSyncEnable( bool vsyncOn );
  1137. //void SetFullScreen( bool fsOn, int screenIndex ); // will be latched for next BeginFrame
  1138. //void ActivateFullScreen( bool fsOn, int screenIndex ); // will be called by BeginFrame
  1139. bool SetDisplayParams( GLMDisplayParams *params ); // either the first time setup, or a change to new setup
  1140. void Present( CGLMTex *tex ); // somewhat hardwired for the time being
  1141. // Called when IDirect3DDevice9::Reset() is called.
  1142. void Reset();
  1143. // writers for the state block inputs
  1144. FORCEINLINE void WriteAlphaTestEnable( GLAlphaTestEnable_t *src ) { m_AlphaTestEnable.Write( src ); }
  1145. FORCEINLINE void WriteAlphaTestFunc( GLAlphaTestFunc_t *src ) { m_AlphaTestFunc.Write( src ); }
  1146. FORCEINLINE void WriteAlphaToCoverageEnable( GLAlphaToCoverageEnable_t *src ) { m_AlphaToCoverageEnable.Write( src ); }
  1147. FORCEINLINE void WriteCullFaceEnable( GLCullFaceEnable_t *src ) { m_CullFaceEnable.Write( src ); }
  1148. FORCEINLINE void WriteCullFrontFace( GLCullFrontFace_t *src ) { m_CullFrontFace.Write( src ); }
  1149. FORCEINLINE void WritePolygonMode( GLPolygonMode_t *src ) { m_PolygonMode.Write( src ); }
  1150. FORCEINLINE void WriteDepthBias( GLDepthBias_t *src ) { m_DepthBias.Write( src ); }
  1151. FORCEINLINE void WriteClipPlaneEnable( GLClipPlaneEnable_t *src, int which ) { m_ClipPlaneEnable.WriteIndex( src, which ); }
  1152. FORCEINLINE void WriteClipPlaneEquation( GLClipPlaneEquation_t *src, int which ) { m_ClipPlaneEquation.WriteIndex( src, which ); }
  1153. FORCEINLINE void WriteScissorEnable( GLScissorEnable_t *src ) { m_ScissorEnable.Write( src ); }
  1154. FORCEINLINE void WriteScissorBox( GLScissorBox_t *src ) { m_ScissorBox.Write( src ); }
  1155. FORCEINLINE void WriteViewportBox( GLViewportBox_t *src ) { m_ViewportBox.Write( src ); }
  1156. FORCEINLINE void WriteViewportDepthRange( GLViewportDepthRange_t *src ) { m_ViewportDepthRange.Write( src ); }
  1157. FORCEINLINE void WriteColorMaskSingle( GLColorMaskSingle_t *src ) { m_ColorMaskSingle.Write( src ); }
  1158. FORCEINLINE void WriteColorMaskMultiple( GLColorMaskMultiple_t *src, int which ) { m_ColorMaskMultiple.WriteIndex( src, which ); }
  1159. FORCEINLINE void WriteBlendEnable( GLBlendEnable_t *src ) { m_BlendEnable.Write( src ); }
  1160. FORCEINLINE void WriteBlendFactor( GLBlendFactor_t *src ) { m_BlendFactor.Write( src ); }
  1161. FORCEINLINE void WriteBlendEquation( GLBlendEquation_t *src ) { m_BlendEquation.Write( src ); }
  1162. FORCEINLINE void WriteBlendColor( GLBlendColor_t *src ) { m_BlendColor.Write( src ); }
  1163. FORCEINLINE void WriteBlendEnableSRGB( GLBlendEnableSRGB_t *src )
  1164. {
  1165. if (m_caps.m_hasGammaWrites) // only if caps allow do we actually push it through to the extension
  1166. {
  1167. m_BlendEnableSRGB.Write( src );
  1168. }
  1169. else
  1170. {
  1171. m_FakeBlendEnableSRGB = src->enable != 0;
  1172. }
  1173. // note however that we're still tracking what this mode should be, so FlushDrawStates can look at it and adjust the pixel shader
  1174. // if fake SRGB mode is in place (m_caps.m_hasGammaWrites is false)
  1175. }
  1176. FORCEINLINE void WriteDepthTestEnable( GLDepthTestEnable_t *src ) { m_DepthTestEnable.Write( src ); }
  1177. FORCEINLINE void WriteDepthFunc( GLDepthFunc_t *src ) { m_DepthFunc.Write( src ); }
  1178. FORCEINLINE void WriteDepthMask( GLDepthMask_t *src ) { m_DepthMask.Write( src ); }
  1179. FORCEINLINE void WriteStencilTestEnable( GLStencilTestEnable_t *src ) { m_StencilTestEnable.Write( src ); }
  1180. FORCEINLINE void WriteStencilFunc( GLStencilFunc_t *src ) { m_StencilFunc.Write( src ); }
  1181. FORCEINLINE void WriteStencilOp( GLStencilOp_t *src, int which ) { m_StencilOp.WriteIndex( src, which ); }
  1182. FORCEINLINE void WriteStencilWriteMask( GLStencilWriteMask_t *src ) { m_StencilWriteMask.Write( src ); }
  1183. FORCEINLINE void WriteClearColor( GLClearColor_t *src ) { m_ClearColor.Write( src ); }
  1184. FORCEINLINE void WriteClearDepth( GLClearDepth_t *src ) { m_ClearDepth.Write( src ); }
  1185. FORCEINLINE void WriteClearStencil( GLClearStencil_t *src ) { m_ClearStencil.Write( src ); }
  1186. // debug stuff
  1187. void BeginFrame( void );
  1188. void EndFrame( void );
  1189. // new interactive debug stuff
  1190. #if GLMDEBUG
  1191. void DebugDump( GLMDebugHookInfo *info, uint options, uint vertDumpMode );
  1192. void DebugHook( GLMDebugHookInfo *info );
  1193. void DebugPresent( void );
  1194. void DebugClear( void );
  1195. #endif
  1196. FORCEINLINE void SetMaxUsedVertexShaderConstantsHint( uint nMaxConstants );
  1197. FORCEINLINE ThreadId_t GetCurrentOwnerThreadId() const { return m_nCurOwnerThreadId; }
  1198. protected:
  1199. friend class GLMgr; // only GLMgr can make GLMContext objects
  1200. friend class GLMRendererInfo; // only GLMgr can make GLMContext objects
  1201. friend class CGLMTex; // tex needs to be able to do binds
  1202. friend class CGLMFBO; // fbo needs to be able to do binds
  1203. friend class CGLMProgram;
  1204. friend class CGLMShaderPair;
  1205. friend class CGLMShaderPairCache;
  1206. friend class CGLMBuffer;
  1207. friend class CGLMBufferSpanManager;
  1208. friend class GLMTester; // tester class needs access back into GLMContext
  1209. friend struct IDirect3D9;
  1210. friend struct IDirect3DDevice9;
  1211. friend struct IDirect3DQuery9;
  1212. // methods------------------------------------------
  1213. // old GLMContext( GLint displayMask, GLint rendererID, PseudoNSGLContextPtr nsglShareCtx );
  1214. GLMContext( IDirect3DDevice9 *pDevice, GLMDisplayParams *params );
  1215. ~GLMContext();
  1216. #ifndef OSX
  1217. FORCEINLINE GLuint FindSamplerObject( const GLMTexSamplingParams &desiredParams );
  1218. #endif
  1219. FORCEINLINE void SetBufAndVertexAttribPointer( uint nIndex, GLuint nGLName, GLuint stride, GLuint datatype, GLboolean normalized, GLuint nCompCount, const void *pBuf, uint nRevision )
  1220. {
  1221. VertexAttribs_t &curAttribs = m_boundVertexAttribs[nIndex];
  1222. if ( nGLName != m_nBoundGLBuffer[kGLMVertexBuffer] )
  1223. {
  1224. m_nBoundGLBuffer[kGLMVertexBuffer] = nGLName;
  1225. gGL->glBindBufferARB( GL_ARRAY_BUFFER_ARB, nGLName );
  1226. }
  1227. else if ( ( curAttribs.m_pPtr == pBuf ) &&
  1228. ( curAttribs.m_revision == nRevision ) &&
  1229. ( curAttribs.m_stride == stride ) &&
  1230. ( curAttribs.m_datatype == datatype ) &&
  1231. ( curAttribs.m_normalized == normalized ) &&
  1232. ( curAttribs.m_nCompCount == nCompCount ) )
  1233. {
  1234. return;
  1235. }
  1236. curAttribs.m_nCompCount = nCompCount;
  1237. curAttribs.m_datatype = datatype;
  1238. curAttribs.m_normalized = normalized;
  1239. curAttribs.m_stride = stride;
  1240. curAttribs.m_pPtr = pBuf;
  1241. curAttribs.m_revision = nRevision;
  1242. gGL->glVertexAttribPointer( nIndex, nCompCount, datatype, normalized, stride, pBuf );
  1243. }
  1244. struct CurAttribs_t
  1245. {
  1246. uint m_nTotalBufferRevision;
  1247. IDirect3DVertexDeclaration9 *m_pVertDecl;
  1248. D3DStreamDesc m_streams[ D3D_MAX_STREAMS ];
  1249. uint64 m_vtxAttribMap[2];
  1250. };
  1251. CurAttribs_t m_CurAttribs;
  1252. FORCEINLINE void ClearCurAttribs()
  1253. {
  1254. m_CurAttribs.m_nTotalBufferRevision = 0;
  1255. m_CurAttribs.m_pVertDecl = NULL;
  1256. memset( m_CurAttribs.m_streams, 0, sizeof( m_CurAttribs.m_streams ) );
  1257. m_CurAttribs.m_vtxAttribMap[0] = 0xBBBBBBBBBBBBBBBBULL;
  1258. m_CurAttribs.m_vtxAttribMap[1] = 0xBBBBBBBBBBBBBBBBULL;
  1259. }
  1260. FORCEINLINE void ReleasedShader() { NullProgram(); }
  1261. // textures
  1262. FORCEINLINE void SelectTMU( int tmu )
  1263. {
  1264. if ( tmu != m_activeTexture )
  1265. {
  1266. gGL->glActiveTexture( GL_TEXTURE0 + tmu );
  1267. m_activeTexture = tmu;
  1268. }
  1269. }
  1270. void BindTexToTMU( CGLMTex *tex, int tmu );
  1271. // render targets / FBO's
  1272. void BindFBOToCtx( CGLMFBO *fbo, GLenum bindPoint = GL_FRAMEBUFFER_EXT ); // you can also choose GL_READ_FRAMEBUFFER_EXT / GL_DRAW_FRAMEBUFFER_EXT
  1273. // buffers
  1274. FORCEINLINE void BindGLBufferToCtx( GLenum nGLBufType, GLuint nGLName, bool bForce = false )
  1275. {
  1276. Assert( ( nGLBufType == GL_ARRAY_BUFFER_ARB ) || ( nGLBufType == GL_ELEMENT_ARRAY_BUFFER_ARB ) );
  1277. const uint nIndex = ( nGLBufType == GL_ARRAY_BUFFER_ARB ) ? kGLMVertexBuffer : kGLMIndexBuffer;
  1278. if ( ( bForce ) || ( m_nBoundGLBuffer[nIndex] != nGLName ) )
  1279. {
  1280. m_nBoundGLBuffer[nIndex] = nGLName;
  1281. gGL->glBindBufferARB( nGLBufType, nGLName );
  1282. }
  1283. }
  1284. void BindBufferToCtx( EGLMBufferType type, CGLMBuffer *buff, bool force = false ); // does not twiddle any enables.
  1285. FORCEINLINE void BindIndexBufferToCtx( CGLMBuffer *buff );
  1286. FORCEINLINE void BindVertexBufferToCtx( CGLMBuffer *buff );
  1287. // debug font
  1288. void GenDebugFontTex( void );
  1289. void DrawDebugText( float x, float y, float z, float drawCharWidth, float drawCharHeight, char *string );
  1290. #ifndef OSX
  1291. CPinnedMemoryBuffer *GetCurPinnedMemoryBuffer( ) { return &m_PinnedMemoryBuffers[m_nCurPinnedMemoryBuffer]; }
  1292. #endif
  1293. CPersistentBuffer* GetCurPersistentBuffer( EGLMBufferType type ) { return &( m_persistentBuffer[m_nCurPersistentBuffer][type] ); }
  1294. // members------------------------------------------
  1295. // context
  1296. ThreadId_t m_nCurOwnerThreadId;
  1297. uint m_nThreadOwnershipReleaseCounter;
  1298. bool m_bUseSamplerObjects;
  1299. bool m_bTexClientStorage;
  1300. IDirect3DDevice9 *m_pDevice;
  1301. GLMRendererInfoFields m_caps;
  1302. bool m_displayParamsValid; // is there a param block copied in yet
  1303. GLMDisplayParams m_displayParams; // last known display config, either via constructor, or by SetDisplayParams...
  1304. #if defined( USE_SDL )
  1305. int m_pixelFormatAttribs[100]; // more than enough
  1306. PseudoNSGLContextPtr m_nsctx;
  1307. void * m_ctx;
  1308. #elif defined( OSX )
  1309. CGLPixelFormatAttribute m_pixelFormatAttribs[100]; // more than enough
  1310. PseudoNSGLContextPtr m_nsctx;
  1311. CGLContextObj m_ctx;
  1312. #endif
  1313. bool m_oneCtxEnable; // true if we use the window's context directly instead of making a second one shared against it
  1314. bool m_bUseBoneUniformBuffers; // if true, we use two uniform buffers for vertex shader constants vs. one
  1315. // texture form table
  1316. CGLMTexLayoutTable *m_texLayoutTable;
  1317. // context state mirrors
  1318. GLState<GLAlphaTestEnable_t> m_AlphaTestEnable;
  1319. GLState<GLAlphaTestFunc_t> m_AlphaTestFunc;
  1320. GLState<GLCullFaceEnable_t> m_CullFaceEnable;
  1321. GLState<GLCullFrontFace_t> m_CullFrontFace;
  1322. GLState<GLPolygonMode_t> m_PolygonMode;
  1323. GLState<GLDepthBias_t> m_DepthBias;
  1324. GLStateArray<GLClipPlaneEnable_t,kGLMUserClipPlanes> m_ClipPlaneEnable;
  1325. GLStateArray<GLClipPlaneEquation_t,kGLMUserClipPlanes> m_ClipPlaneEquation; // dxabstract puts them directly into param slot 253(0) and 254(1)
  1326. GLState<GLScissorEnable_t> m_ScissorEnable;
  1327. GLState<GLScissorBox_t> m_ScissorBox;
  1328. GLState<GLAlphaToCoverageEnable_t> m_AlphaToCoverageEnable;
  1329. GLState<GLViewportBox_t> m_ViewportBox;
  1330. GLState<GLViewportDepthRange_t> m_ViewportDepthRange;
  1331. GLState<GLColorMaskSingle_t> m_ColorMaskSingle;
  1332. GLStateArray<GLColorMaskMultiple_t,8> m_ColorMaskMultiple; // need an official constant for the color buffers limit
  1333. GLState<GLBlendEnable_t> m_BlendEnable;
  1334. GLState<GLBlendFactor_t> m_BlendFactor;
  1335. GLState<GLBlendEquation_t> m_BlendEquation;
  1336. GLState<GLBlendColor_t> m_BlendColor;
  1337. GLState<GLBlendEnableSRGB_t> m_BlendEnableSRGB; // write to this one to transmit intent to write SRGB encoded pixels to drawing FB
  1338. bool m_FakeBlendEnableSRGB; // writes to above will be shunted here if fake SRGB is in effect.
  1339. GLState<GLDepthTestEnable_t> m_DepthTestEnable;
  1340. GLState<GLDepthFunc_t> m_DepthFunc;
  1341. GLState<GLDepthMask_t> m_DepthMask;
  1342. GLState<GLStencilTestEnable_t> m_StencilTestEnable; // global stencil test enable
  1343. GLState<GLStencilFunc_t> m_StencilFunc; // holds front and back stencil funcs
  1344. GLStateArray<GLStencilOp_t,2> m_StencilOp; // indexed: 0=front 1=back
  1345. GLState<GLStencilWriteMask_t> m_StencilWriteMask;
  1346. GLState<GLClearColor_t> m_ClearColor;
  1347. GLState<GLClearDepth_t> m_ClearDepth;
  1348. GLState<GLClearStencil_t> m_ClearStencil;
  1349. // texture bindings and sampler setup
  1350. int m_activeTexture; // mirror for glActiveTexture
  1351. GLMTexSampler m_samplers[GLM_SAMPLER_COUNT];
  1352. uint8 m_nDirtySamplerFlags[GLM_SAMPLER_COUNT]; // 0 if the sampler is dirty, 1 if not
  1353. uint32 m_nNumDirtySamplers; // # of unique dirty sampler indices in m_nDirtySamplers
  1354. uint8 m_nDirtySamplers[GLM_SAMPLER_COUNT + 1]; // dirty sampler indices
  1355. void MarkAllSamplersDirty();
  1356. struct SamplerHashEntry
  1357. {
  1358. GLuint m_samplerObject;
  1359. GLMTexSamplingParams m_params;
  1360. };
  1361. enum
  1362. {
  1363. cSamplerObjectHashBits = 9, cSamplerObjectHashSize = 1 << cSamplerObjectHashBits
  1364. };
  1365. SamplerHashEntry m_samplerObjectHash[cSamplerObjectHashSize];
  1366. uint m_nSamplerObjectHashNumEntries;
  1367. // texture lock tracking - CGLMTex objects share usage of this
  1368. CUtlVector< GLMTexLockDesc > m_texLocks;
  1369. // render target binding - check before draw
  1370. // similar to tex sampler mechanism, we track "bound" from "chosen for drawing" separately,
  1371. // so binding for creation/setup need not disrupt any notion of what will be used at draw time
  1372. CGLMFBO *m_boundDrawFBO; // FBO on GL_DRAW_FRAMEBUFFER bind point
  1373. CGLMFBO *m_boundReadFBO; // FBO on GL_READ_FRAMEBUFFER bind point
  1374. // ^ both are set if you bind to GL_FRAMEBUFFER_EXT
  1375. CGLMFBO *m_drawingFBO; // what FBO should be bound at draw time (to both read/draw bp's).
  1376. CGLMFBO *m_blitReadFBO;
  1377. CGLMFBO *m_blitDrawFBO; // scratch FBO's for framebuffer blit
  1378. CGLMFBO *m_scratchFBO[ kGLMScratchFBOCount ]; // general purpose FBO's for internal use
  1379. CUtlVector< CGLMFBO* > m_fboTable; // each live FBO goes in the table
  1380. uint m_fragDataMask;
  1381. // program bindings
  1382. EGLMProgramLang m_drawingLangAtFrameStart; // selector for start of frame (spills into m_drawingLang)
  1383. EGLMProgramLang m_drawingLang; // selector for which language we desire to draw with on the next batch
  1384. CGLMProgram *m_drawingProgram[ kGLMNumProgramTypes ];
  1385. bool m_bDirtyPrograms;
  1386. GLMProgramParamsF m_programParamsF[ kGLMNumProgramTypes ];
  1387. GLMProgramParamsB m_programParamsB[ kGLMNumProgramTypes ];
  1388. GLMProgramParamsI m_programParamsI[ kGLMNumProgramTypes ]; // two banks, but only the vertex one is used
  1389. EGLMParamWriteMode m_paramWriteMode;
  1390. CGLMProgram *m_pNullFragmentProgram; // write opaque black. Activate when caller asks for null FP
  1391. CGLMProgram *m_preloadTexVertexProgram; // programs to help preload textures (dummies)
  1392. CGLMProgram *m_preload2DTexFragmentProgram;
  1393. CGLMProgram *m_preload3DTexFragmentProgram;
  1394. CGLMProgram *m_preloadCubeTexFragmentProgram;
  1395. CGLMShaderPairCache *m_pairCache; // GLSL only
  1396. CGLMShaderPair *m_pBoundPair; // GLSL only
  1397. FORCEINLINE void NewLinkedProgram() { ClearCurAttribs(); }
  1398. //uint m_boundPairRevision; // GLSL only
  1399. //GLhandleARB m_boundPairProgram; // GLSL only
  1400. // buffer bindings
  1401. GLuint m_nBoundGLBuffer[kGLMNumBufferTypes];
  1402. struct VertexAttribs_t
  1403. {
  1404. GLuint m_nCompCount;
  1405. GLenum m_datatype;
  1406. GLboolean m_normalized;
  1407. GLuint m_stride;
  1408. const void *m_pPtr;
  1409. uint m_revision;
  1410. };
  1411. VertexAttribs_t m_boundVertexAttribs[ kGLMVertexAttributeIndexMax ]; // tracked per attrib for dupe-set-absorb
  1412. uint m_lastKnownVertexAttribMask; // tracked for dupe-enable-absorb
  1413. int m_nNumSetVertexAttributes;
  1414. // FIXME: Remove this, it's no longer used
  1415. GLMVertexSetup m_drawVertexSetup;
  1416. EGLMAttribWriteMode m_attribWriteMode;
  1417. bool m_slowCheckEnable; // turn this on or no native checking is done ("-glmassertslow" or "-glmsspewslow")
  1418. bool m_slowAssertEnable; // turn this on to assert on a non-native batch "-glmassertslow"
  1419. bool m_slowSpewEnable; // turn this on to log non-native batches to stdout "-glmspewslow"
  1420. bool m_checkglErrorsAfterEveryBatch; // turn this on to check for GL errors after each batch (slow) ("-glcheckerrors")
  1421. // debug font texture
  1422. CGLMTex *m_debugFontTex; // might be NULL unless you call GenDebugFontTex
  1423. CGLMBuffer *m_debugFontIndices; // up to 1024 indices (256 chars times 4)
  1424. CGLMBuffer *m_debugFontVertices; // up to 1024 verts
  1425. // batch/frame debugging support
  1426. int m_debugFrameIndex; // init to -1. Increment at BeginFrame
  1427. int m_nMaxUsedVertexProgramConstantsHint;
  1428. uint32 m_dwRenderThreadId;
  1429. volatile bool m_bIsThreading;
  1430. uint m_nCurFrame;
  1431. uint m_nBatchCounter;
  1432. #ifndef OSX
  1433. enum { cNumPinnedMemoryBuffers = 4 };
  1434. CPinnedMemoryBuffer m_PinnedMemoryBuffers[cNumPinnedMemoryBuffers];
  1435. uint m_nCurPinnedMemoryBuffer;
  1436. #endif
  1437. enum { cNumPersistentBuffers = 3 };
  1438. CPersistentBuffer m_persistentBuffer[cNumPersistentBuffers][kGLMNumBufferTypes];
  1439. uint m_nCurPersistentBuffer;
  1440. void SaveColorMaskAndSetToDefault();
  1441. void RestoreSavedColorMask();
  1442. GLColorMaskSingle_t m_SavedColorMask;
  1443. #if GLMDEBUG
  1444. // interactive (DebugHook) debug support
  1445. // using these you can implement frame advance, batch single step, and batch rewind (let it run til next frame and hold on prev batch #)
  1446. int m_holdFrameBegin; // -1 if no hold req'd, otherwise # of frame to hold at (at beginframe time)
  1447. int m_holdFrameEnd; // -1 if no hold req'd, otherwise # of frame to hold at (at endframe time)
  1448. int m_holdBatch,m_holdBatchFrame; // -1 if no hold, else # of batch&frame to hold at (both must be set)
  1449. // these can be expired/cleared to -1 if the frame passes without a hit
  1450. // may be desirable to re-pause in that event, as user was expecting a hold to occur
  1451. bool m_debugDelayEnable; // allow sleep delay
  1452. uint m_debugDelay; // sleep time per hook call in microseconds (for usleep())
  1453. // pre-draw global toggles / options
  1454. bool m_autoClearColor,m_autoClearDepth,m_autoClearStencil;
  1455. float m_autoClearColorValues[4];
  1456. // debug knobs
  1457. int m_selKnobIndex;
  1458. float m_selKnobMinValue,m_selKnobMaxValue,m_selKnobIncrement;
  1459. #endif
  1460. #ifdef _OSX
  1461. void UpdateSwapchainVariables( bool bForce );
  1462. bool m_bFramerateSmoothing;
  1463. bool m_bSwapLimit;
  1464. #endif
  1465. #if GL_BATCH_PERF_ANALYSIS
  1466. uint m_nTotalVSUniformCalls;
  1467. uint m_nTotalVSUniformBoneCalls;
  1468. uint m_nTotalVSUniformsSet;
  1469. uint m_nTotalVSUniformsBoneSet;
  1470. uint m_nTotalPSUniformCalls;
  1471. uint m_nTotalPSUniformsSet;
  1472. CFlushDrawStatesStats m_FlushStats;
  1473. #endif
  1474. void ProcessTextureDeletes();
  1475. CTSQueue<CGLMTex*> m_DeleteTextureQueue;
  1476. };
  1477. #ifndef OSX
  1478. FORCEINLINE void GLMContext::DrawRangeElements( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, uint baseVertex, CGLMBuffer *pIndexBuf )
  1479. {
  1480. #if GL_ENABLE_INDEX_VERIFICATION
  1481. DrawRangeElementsNonInline( mode, start, end, count, type, indices, baseVertex, pIndexBuf );
  1482. #else
  1483. #if GLMDEBUG
  1484. GLM_FUNC;
  1485. #else
  1486. //tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s %d-%d count:%d mode:%d type:%d", __FUNCTION__, start, end, count, mode, type );
  1487. #endif
  1488. ++m_nBatchCounter;
  1489. SetIndexBuffer( pIndexBuf );
  1490. void *indicesActual = (void*)indices;
  1491. if ( pIndexBuf->m_bPseudo )
  1492. {
  1493. // you have to pass actual address, not offset
  1494. indicesActual = (void*)( (intp)indicesActual + (intp)pIndexBuf->m_pPseudoBuf );
  1495. }
  1496. if (pIndexBuf->m_bUsingPersistentBuffer)
  1497. {
  1498. indicesActual = (void*)( (intp)indicesActual + (intp)pIndexBuf->m_nPersistentBufferStartOffset );
  1499. }
  1500. //#if GLMDEBUG
  1501. #if 0
  1502. bool hasVP = m_drawingProgram[ kGLMVertexProgram ] != NULL;
  1503. bool hasFP = m_drawingProgram[ kGLMFragmentProgram ] != NULL;
  1504. // init debug hook information
  1505. GLMDebugHookInfo info;
  1506. memset( &info, 0, sizeof(info) );
  1507. info.m_caller = eDrawElements;
  1508. // relay parameters we're operating under
  1509. info.m_drawMode = mode;
  1510. info.m_drawStart = start;
  1511. info.m_drawEnd = end;
  1512. info.m_drawCount = count;
  1513. info.m_drawType = type;
  1514. info.m_drawIndices = indices;
  1515. do
  1516. {
  1517. // obey global options re pre-draw clear
  1518. if ( m_autoClearColor || m_autoClearDepth || m_autoClearStencil )
  1519. {
  1520. GLMPRINTF(("-- DrawRangeElements auto clear" ));
  1521. this->DebugClear();
  1522. }
  1523. // always sync with editable shader text prior to draw
  1524. #if GLMDEBUG
  1525. //FIXME disengage this path if context is in GLSL mode..
  1526. // it will need fixes to get the shader pair re-linked etc if edits happen anyway.
  1527. if (m_drawingProgram[ kGLMVertexProgram ])
  1528. {
  1529. m_drawingProgram[ kGLMVertexProgram ]->SyncWithEditable();
  1530. }
  1531. else
  1532. {
  1533. AssertOnce(!"drawing with no vertex program bound");
  1534. }
  1535. if (m_drawingProgram[ kGLMFragmentProgram ])
  1536. {
  1537. m_drawingProgram[ kGLMFragmentProgram ]->SyncWithEditable();
  1538. }
  1539. else
  1540. {
  1541. AssertOnce(!"drawing with no fragment program bound");
  1542. }
  1543. #endif
  1544. // do the drawing
  1545. if (hasVP && hasFP)
  1546. {
  1547. gGL->glDrawRangeElementsBaseVertex( mode, start, end, count, type, indicesActual, baseVertex );
  1548. if ( m_slowCheckEnable )
  1549. {
  1550. CheckNative();
  1551. }
  1552. }
  1553. this->DebugHook( &info );
  1554. } while ( info.m_loop );
  1555. #else
  1556. Assert( m_drawingLang == kGLMGLSL );
  1557. if ( m_pBoundPair )
  1558. {
  1559. gGL->glDrawRangeElementsBaseVertex( mode, start, end, count, type, indicesActual, baseVertex );
  1560. #if GLMDEBUG
  1561. if ( m_slowCheckEnable )
  1562. {
  1563. CheckNative();
  1564. }
  1565. #endif
  1566. }
  1567. #endif
  1568. #endif // GL_ENABLE_INDEX_VERIFICATION
  1569. }
  1570. #endif // #ifndef OSX
  1571. FORCEINLINE void GLMContext::SetVertexProgram( CGLMProgram *pProg )
  1572. {
  1573. m_drawingProgram[kGLMVertexProgram] = pProg;
  1574. m_bDirtyPrograms = true;
  1575. }
  1576. FORCEINLINE void GLMContext::SetFragmentProgram( CGLMProgram *pProg )
  1577. {
  1578. m_drawingProgram[kGLMFragmentProgram] = pProg ? pProg : m_pNullFragmentProgram;
  1579. m_bDirtyPrograms = true;
  1580. }
  1581. // "slot" means a vec4-sized thing
  1582. // these write into .env parameter space
  1583. FORCEINLINE void GLMContext::SetProgramParametersF( EGLMProgramType type, uint baseSlot, float *slotData, uint slotCount )
  1584. {
  1585. #if GLMDEBUG
  1586. GLM_FUNC;
  1587. #endif
  1588. Assert( baseSlot < kGLMProgramParamFloat4Limit );
  1589. Assert( baseSlot+slotCount <= kGLMProgramParamFloat4Limit );
  1590. #if GLMDEBUG
  1591. GLMPRINTF(("-S-GLMContext::SetProgramParametersF %s slots %d - %d: ", (type==kGLMVertexProgram) ? "VS" : "FS", baseSlot, baseSlot + slotCount - 1 ));
  1592. for( uint i=0; i<slotCount; i++ )
  1593. {
  1594. GLMPRINTF(( "-S- %03d: [ %7.4f %7.4f %7.4f %7.4f ]",
  1595. baseSlot+i,
  1596. slotData[i*4], slotData[i*4+1], slotData[i*4+2], slotData[i*4+3]
  1597. ));
  1598. }
  1599. #endif
  1600. memcpy( &m_programParamsF[type].m_values[baseSlot][0], slotData, (4 * sizeof(float)) * slotCount );
  1601. if ( ( type == kGLMVertexProgram ) && ( m_bUseBoneUniformBuffers ) )
  1602. {
  1603. // changes here to handle vertex shaders which use constants before and after the bone array i.e. before c58 and after c216
  1604. // a better change may be to modify the shaders and place the bone consts at either start or end - would simplify this and the flush code
  1605. // the current supporting code (shader translator(dx9asmtogl2), param setting(here) and flushing(glmgr_flush.inl) should work unchanged, even if the const mapping is changed.
  1606. int firstDirty = (int)baseSlot;
  1607. int highWater = (int)(baseSlot + slotCount);
  1608. if ( highWater <= DXABSTRACT_VS_FIRST_BONE_SLOT )
  1609. {
  1610. m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = MIN( m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone, firstDirty );
  1611. m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone, highWater );
  1612. }
  1613. else if ( highWater <= (DXABSTRACT_VS_LAST_BONE_SLOT+1) )
  1614. {
  1615. if ( firstDirty < DXABSTRACT_VS_FIRST_BONE_SLOT )
  1616. {
  1617. m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = MIN( m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone, firstDirty );
  1618. m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone, MIN( DXABSTRACT_VS_FIRST_BONE_SLOT, highWater ) );
  1619. firstDirty = DXABSTRACT_VS_FIRST_BONE_SLOT;
  1620. }
  1621. int nNumActualBones = ( firstDirty + slotCount ) - DXABSTRACT_VS_FIRST_BONE_SLOT;
  1622. m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone, nNumActualBones );
  1623. }
  1624. else
  1625. {
  1626. const int maxBoneSlots = ( DXABSTRACT_VS_LAST_BONE_SLOT + 1 ) - DXABSTRACT_VS_FIRST_BONE_SLOT;
  1627. if ( firstDirty > DXABSTRACT_VS_LAST_BONE_SLOT )
  1628. {
  1629. m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = MIN( m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone, firstDirty - maxBoneSlots );
  1630. m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone, highWater - maxBoneSlots );
  1631. }
  1632. else if ( firstDirty >= DXABSTRACT_VS_FIRST_BONE_SLOT )
  1633. {
  1634. m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone = DXABSTRACT_VS_LAST_BONE_SLOT + 1;
  1635. m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = MIN( m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone, DXABSTRACT_VS_FIRST_BONE_SLOT );
  1636. m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone, highWater - maxBoneSlots );
  1637. }
  1638. else
  1639. {
  1640. int nNumActualBones = ( DXABSTRACT_VS_LAST_BONE_SLOT + 1 ) - DXABSTRACT_VS_FIRST_BONE_SLOT;
  1641. m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone, nNumActualBones );
  1642. m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = MIN( m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone, firstDirty );
  1643. m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone, highWater - maxBoneSlots );
  1644. }
  1645. }
  1646. }
  1647. else
  1648. {
  1649. m_programParamsF[type].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[type].m_dirtySlotHighWaterNonBone, (int)(baseSlot + slotCount) );
  1650. m_programParamsF[type].m_firstDirtySlotNonBone = MIN( m_programParamsF[type].m_firstDirtySlotNonBone, (int)baseSlot );
  1651. }
  1652. }
  1653. FORCEINLINE void GLMContext::SetProgramParametersB( EGLMProgramType type, uint baseSlot, int *slotData, uint boolCount )
  1654. {
  1655. #if GLMDEBUG
  1656. GLM_FUNC;
  1657. #endif
  1658. Assert( m_drawingLang == kGLMGLSL );
  1659. Assert( type==kGLMVertexProgram || type==kGLMFragmentProgram );
  1660. Assert( baseSlot < kGLMProgramParamBoolLimit );
  1661. Assert( baseSlot+boolCount <= kGLMProgramParamBoolLimit );
  1662. #if GLMDEBUG
  1663. GLMPRINTF(("-S-GLMContext::SetProgramParametersB %s bools %d - %d: ", (type==kGLMVertexProgram) ? "VS" : "FS", baseSlot, baseSlot + boolCount - 1 ));
  1664. for( uint i=0; i<boolCount; i++ )
  1665. {
  1666. GLMPRINTF(( "-S- %03d: %d (bool)",
  1667. baseSlot+i,
  1668. slotData[i]
  1669. ));
  1670. }
  1671. #endif
  1672. memcpy( &m_programParamsB[type].m_values[baseSlot], slotData, sizeof(int) * boolCount );
  1673. if ( (baseSlot+boolCount) > m_programParamsB[type].m_dirtySlotCount)
  1674. m_programParamsB[type].m_dirtySlotCount = baseSlot+boolCount;
  1675. }
  1676. FORCEINLINE void GLMContext::SetProgramParametersI( EGLMProgramType type, uint baseSlot, int *slotData, uint slotCount ) // groups of 4 ints...
  1677. {
  1678. #if GLMDEBUG
  1679. GLM_FUNC;
  1680. #endif
  1681. Assert( m_drawingLang == kGLMGLSL );
  1682. Assert( type==kGLMVertexProgram );
  1683. Assert( baseSlot < kGLMProgramParamInt4Limit );
  1684. Assert( baseSlot+slotCount <= kGLMProgramParamInt4Limit );
  1685. #if GLMDEBUG
  1686. GLMPRINTF(("-S-GLMContext::SetProgramParametersI %s slots %d - %d: ", (type==kGLMVertexProgram) ? "VS" : "FS", baseSlot, baseSlot + slotCount - 1 ));
  1687. for( uint i=0; i<slotCount; i++ )
  1688. {
  1689. GLMPRINTF(( "-S- %03d: %d %d %d %d (int4)",
  1690. baseSlot+i,
  1691. slotData[i*4],slotData[i*4+1],slotData[i*4+2],slotData[i*4+3]
  1692. ));
  1693. }
  1694. #endif
  1695. memcpy( &m_programParamsI[type].m_values[baseSlot][0], slotData, (4*sizeof(int)) * slotCount );
  1696. if ( (baseSlot + slotCount) > m_programParamsI[type].m_dirtySlotCount)
  1697. {
  1698. m_programParamsI[type].m_dirtySlotCount = baseSlot + slotCount;
  1699. }
  1700. }
  1701. FORCEINLINE void GLMContext::SetSamplerDirty( int sampler )
  1702. {
  1703. Assert( sampler < GLM_SAMPLER_COUNT );
  1704. m_nDirtySamplers[m_nNumDirtySamplers] = sampler;
  1705. m_nNumDirtySamplers += m_nDirtySamplerFlags[sampler];
  1706. m_nDirtySamplerFlags[sampler] = 0;
  1707. }
  1708. FORCEINLINE void GLMContext::SetSamplerTex( int sampler, CGLMTex *tex )
  1709. {
  1710. Assert( sampler < GLM_SAMPLER_COUNT );
  1711. m_samplers[sampler].m_pBoundTex = tex;
  1712. if ( tex )
  1713. {
  1714. if ( !gGL->m_bHave_GL_EXT_direct_state_access )
  1715. {
  1716. if ( sampler != m_activeTexture )
  1717. {
  1718. gGL->glActiveTexture( GL_TEXTURE0 + sampler );
  1719. m_activeTexture = sampler;
  1720. }
  1721. gGL->glBindTexture( tex->m_texGLTarget, tex->m_texName );
  1722. }
  1723. else
  1724. {
  1725. gGL->glBindMultiTextureEXT( GL_TEXTURE0 + sampler, tex->m_texGLTarget, tex->m_texName );
  1726. }
  1727. }
  1728. if ( !m_bUseSamplerObjects )
  1729. {
  1730. SetSamplerDirty( sampler );
  1731. }
  1732. }
  1733. FORCEINLINE void GLMContext::SetSamplerMinFilter( int sampler, GLenum Value )
  1734. {
  1735. Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MIN_FILTER_BITS ) );
  1736. m_samplers[sampler].m_samp.m_packed.m_minFilter = Value;
  1737. }
  1738. FORCEINLINE void GLMContext::SetSamplerMagFilter( int sampler, GLenum Value )
  1739. {
  1740. Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MAG_FILTER_BITS ) );
  1741. m_samplers[sampler].m_samp.m_packed.m_magFilter = Value;
  1742. }
  1743. FORCEINLINE void GLMContext::SetSamplerMipFilter( int sampler, GLenum Value )
  1744. {
  1745. Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MIP_FILTER_BITS ) );
  1746. m_samplers[sampler].m_samp.m_packed.m_mipFilter = Value;
  1747. }
  1748. FORCEINLINE void GLMContext::SetSamplerAddressU( int sampler, GLenum Value )
  1749. {
  1750. Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) );
  1751. m_samplers[sampler].m_samp.m_packed.m_addressU = Value;
  1752. }
  1753. FORCEINLINE void GLMContext::SetSamplerAddressV( int sampler, GLenum Value )
  1754. {
  1755. Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) );
  1756. m_samplers[sampler].m_samp.m_packed.m_addressV = Value;
  1757. }
  1758. FORCEINLINE void GLMContext::SetSamplerAddressW( int sampler, GLenum Value )
  1759. {
  1760. Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) );
  1761. m_samplers[sampler].m_samp.m_packed.m_addressW = Value;
  1762. }
  1763. FORCEINLINE void GLMContext::SetSamplerStates( int sampler, GLenum AddressU, GLenum AddressV, GLenum AddressW, GLenum minFilter, GLenum magFilter, GLenum mipFilter )
  1764. {
  1765. Assert( AddressU < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) );
  1766. Assert( AddressV < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) );
  1767. Assert( AddressW < ( 1 << GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS) );
  1768. Assert( minFilter < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MIN_FILTER_BITS ) );
  1769. Assert( magFilter < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MAG_FILTER_BITS ) );
  1770. Assert( mipFilter < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MIP_FILTER_BITS ) );
  1771. GLMTexSamplingParams &params = m_samplers[sampler].m_samp;
  1772. params.m_packed.m_addressU = AddressU;
  1773. params.m_packed.m_addressV = AddressV;
  1774. params.m_packed.m_addressW = AddressW;
  1775. params.m_packed.m_minFilter = minFilter;
  1776. params.m_packed.m_magFilter = magFilter;
  1777. params.m_packed.m_mipFilter = mipFilter;
  1778. }
  1779. FORCEINLINE void GLMContext::SetSamplerBorderColor( int sampler, DWORD Value )
  1780. {
  1781. m_samplers[sampler].m_samp.m_borderColor = Value;
  1782. }
  1783. FORCEINLINE void GLMContext::SetSamplerMipMapLODBias( int sampler, DWORD Value )
  1784. {
  1785. // not currently supported
  1786. }
  1787. FORCEINLINE void GLMContext::SetSamplerMaxMipLevel( int sampler, DWORD Value )
  1788. {
  1789. Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MIN_LOD_BITS ) );
  1790. m_samplers[sampler].m_samp.m_packed.m_minLOD = Value;
  1791. }
  1792. FORCEINLINE void GLMContext::SetSamplerMaxAnisotropy( int sampler, DWORD Value )
  1793. {
  1794. Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_MAX_ANISO_BITS ) );
  1795. m_samplers[sampler].m_samp.m_packed.m_maxAniso = Value;
  1796. }
  1797. FORCEINLINE void GLMContext::SetSamplerSRGBTexture( int sampler, DWORD Value )
  1798. {
  1799. Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_SRGB_BITS ) );
  1800. m_samplers[sampler].m_samp.m_packed.m_srgb = Value;
  1801. }
  1802. FORCEINLINE void GLMContext::SetShadowFilter( int sampler, DWORD Value )
  1803. {
  1804. Assert( Value < ( 1 << GLM_PACKED_SAMPLER_PARAMS_COMPARE_MODE_BITS ) );
  1805. m_samplers[sampler].m_samp.m_packed.m_compareMode = Value;
  1806. }
  1807. FORCEINLINE void GLMContext::BindIndexBufferToCtx( CGLMBuffer *buff )
  1808. {
  1809. GLMPRINTF(( "--- GLMContext::BindIndexBufferToCtx buff %p, GL name %d", buff, (buff) ? buff->m_nHandle : -1 ));
  1810. Assert( !buff || ( buff->m_buffGLTarget == GL_ELEMENT_ARRAY_BUFFER_ARB ) );
  1811. GLuint nGLName = buff ? buff->GetHandle() : 0;
  1812. if ( m_nBoundGLBuffer[ kGLMIndexBuffer] == nGLName )
  1813. return;
  1814. m_nBoundGLBuffer[ kGLMIndexBuffer] = nGLName;
  1815. gGL->glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, nGLName );
  1816. }
  1817. FORCEINLINE void GLMContext::BindVertexBufferToCtx( CGLMBuffer *buff )
  1818. {
  1819. GLMPRINTF(( "--- GLMContext::BindVertexBufferToCtx buff %p, GL name %d", buff, (buff) ? buff->m_nHandle : -1 ));
  1820. Assert( !buff || ( buff->m_buffGLTarget == GL_ARRAY_BUFFER_ARB ) );
  1821. GLuint nGLName = buff ? buff->GetHandle() : 0;
  1822. if ( m_nBoundGLBuffer[ kGLMVertexBuffer] == nGLName )
  1823. return;
  1824. m_nBoundGLBuffer[ kGLMVertexBuffer] = nGLName;
  1825. gGL->glBindBufferARB( GL_ARRAY_BUFFER_ARB, nGLName );
  1826. }
  1827. FORCEINLINE void GLMContext::SetMaxUsedVertexShaderConstantsHint( uint nMaxConstants )
  1828. {
  1829. static bool bUseMaxVertexShadeConstantHints = !CommandLine()->CheckParm("-disablemaxvertexshaderconstanthints");
  1830. if ( bUseMaxVertexShadeConstantHints )
  1831. {
  1832. m_nMaxUsedVertexProgramConstantsHint = nMaxConstants;
  1833. }
  1834. }
  1835. struct GLMTestParams
  1836. {
  1837. GLMContext *m_ctx;
  1838. int *m_testList; // -1 termed
  1839. bool m_glErrToDebugger;
  1840. bool m_glErrToConsole;
  1841. bool m_intlErrToDebugger;
  1842. bool m_intlErrToConsole;
  1843. int m_frameCount; // how many frames to test.
  1844. };
  1845. class GLMTester
  1846. {
  1847. public:
  1848. GLMTester(GLMTestParams *params);
  1849. ~GLMTester();
  1850. // optionally callable by test routines to get basic drawables wired up
  1851. void StdSetup( void );
  1852. void StdCleanup( void );
  1853. // callable by test routines to clear the frame or present it
  1854. void Clear( void );
  1855. void Present( int seed );
  1856. // error reporting
  1857. void CheckGLError( const char *comment ); // obey m_params setting for console / debugger response
  1858. void InternalError( int errcode, char *comment ); // if errcode!=0, obey m_params setting for console / debugger response
  1859. void RunTests();
  1860. void RunOneTest( int testindex );
  1861. // test routines themselves
  1862. void Test0();
  1863. void Test1();
  1864. void Test2();
  1865. void Test3();
  1866. GLMTestParams m_params; // copy of caller's params, do not mutate...
  1867. // std-setup stuff
  1868. int m_drawWidth, m_drawHeight;
  1869. CGLMFBO *m_drawFBO;
  1870. CGLMTex *m_drawColorTex;
  1871. CGLMTex *m_drawDepthTex;
  1872. };
  1873. class CShowPixelsParams
  1874. {
  1875. public:
  1876. GLuint m_srcTexName;
  1877. int m_width,m_height;
  1878. bool m_vsyncEnable;
  1879. bool m_fsEnable; // want receiving view to be full screen. for now, just target the main screen. extend later.
  1880. bool m_useBlit; // use FBO blit - sending context says it is available.
  1881. bool m_noBlit; // the back buffer has already been populated by the caller (perhaps via direct MSAA resolve from multisampled RT tex)
  1882. bool m_onlySyncView; // react to full/windowed state change only, do not present bits
  1883. };
  1884. #define kMaxCrawlFrames 100
  1885. #define kMaxCrawlText (kMaxCrawlFrames * 256)
  1886. class CStackCrawlParams
  1887. {
  1888. public:
  1889. uint m_frameLimit; // input: max frames to retrieve
  1890. uint m_frameCount; // output: frames found
  1891. void *m_crawl[kMaxCrawlFrames]; // call site addresses
  1892. char *m_crawlNames[kMaxCrawlFrames]; // pointers into text following, one per decoded name
  1893. char m_crawlText[kMaxCrawlText];
  1894. };
  1895. #endif // GLMGR_H