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.

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