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.

1028 lines
39 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. #include "glmgr/glmdebug.h"
  12. #include "glmgr/glmdisplay.h"
  13. #include "glmgr/glmgrext.h"
  14. #include "glmgr/glmgrbasics.h"
  15. #include "glmgr/cglmtex.h"
  16. #include "glmgr/cglmfbo.h"
  17. #include "glmgr/cglmprogram.h"
  18. #include "glmgr/cglmbuffer.h"
  19. #include "glmgr/cglmquery.h"
  20. //===============================================================================
  21. // glue to call out to Obj-C land (these are in glmgrcocoa.mm)
  22. bool NewNSGLContext( unsigned long *attribs, PseudoNSGLContextPtr nsglShareCtx, PseudoNSGLContextPtr *nsglCtxOut, CGLContextObj *cglCtxOut );
  23. CGLContextObj GetCGLContextFromNSGL( PseudoNSGLContextPtr nsglCtx );
  24. void DelNSGLContext( PseudoNSGLContextPtr nsglCtx );
  25. //===============================================================================
  26. // parrot the D3D present parameters, more or less... "adapter" translates into "active display index" per the m_activeDisplayCount below.
  27. class GLMDisplayParams
  28. {
  29. public:
  30. // presumption, these indices are in sync with the current display DB that GLMgr has handy
  31. //int m_rendererIndex; // index of renderer (-1 if root context)
  32. //int m_displayIndex; // index of display in renderer - for FS
  33. //int m_modeIndex; // index of mode in display - for FS
  34. void *m_focusWindow; // (VD3DHWND aka WindowRef) - what window does this context display into
  35. bool m_fsEnable; // fullscreen on or not
  36. bool m_vsyncEnable; // vsync on or not
  37. // height and width have to match the display mode info if full screen.
  38. uint m_backBufferWidth; // pixel width (aka screen h-resolution if full screen)
  39. uint m_backBufferHeight; // pixel height (aka screen v-resolution if full screen)
  40. D3DFORMAT m_backBufferFormat; // pixel format
  41. uint m_multiSampleCount; // 0 means no MSAA, 2 means 2x MSAA, etc
  42. // uint m_multiSampleQuality; // no MSAA quality control yet
  43. bool m_enableAutoDepthStencil; // generally set to 'TRUE' per CShaderDeviceDx8::SetPresentParameters
  44. D3DFORMAT m_autoDepthStencilFormat;
  45. uint m_fsRefreshHz; // if full screen, this refresh rate (likely 0 for LCD's)
  46. //uint m_rootRendererID; // only used if m_rendererIndex is -1.
  47. //uint m_rootDisplayMask; // only used if m_rendererIndex is -1.
  48. bool m_mtgl; // enable multi threaded GL driver
  49. };
  50. //===============================================================================
  51. class GLMgr
  52. {
  53. public:
  54. //===========================================================================
  55. // class methods - singleton
  56. static void NewGLMgr( void ); // instantiate singleton..
  57. static GLMgr *aGLMgr( void ); // return singleton..
  58. static void DelGLMgr( void ); // tear down singleton..
  59. //===========================================================================
  60. // plain methods
  61. #if 0 // turned all these off while new approach is coded
  62. void RefreshDisplayDB( void ); // blow away old display DB, make a new one
  63. GLMDisplayDB *GetDisplayDB( void ); // get a ptr to the one GLMgr keeps. only valid til next refresh.
  64. // eligible renderers will be ranked by desirability starting at index 0 within the db
  65. // within each renderer, eligible displays will be ranked some kind of desirability (area? dist from menu bar?)
  66. // within each display, eligible modes will be ranked by descending areas
  67. // calls supplying indices are implicitly making reference to the current DB
  68. bool CaptureDisplay( int rendIndex, int displayIndex, bool captureAll ); // capture one display or all displays
  69. void ReleaseDisplays( void ); // release all captures
  70. int GetDisplayMode( int rendIndex, int displayIndex ); // retrieve current display res (returns modeIndex)
  71. void SetDisplayMode( GLMDisplayParams *params ); // set the display res (only useful for FS)
  72. #endif
  73. GLMContext *NewContext( GLMDisplayParams *params ); // this will have to change
  74. void DelContext( GLMContext *context );
  75. // with usage of CGLMacro.h we could dispense with the "current context" thing
  76. // and just declare a member variable of GLMContext, allowing each glXXX call to be routed directly
  77. // to the correct context
  78. void SetCurrentContext( GLMContext *context ); // make current in calling thread only
  79. GLMContext *GetCurrentContext( void );
  80. protected:
  81. friend class GLMContext;
  82. GLMgr();
  83. ~GLMgr();
  84. };
  85. //===========================================================================//
  86. // helper function to do enable or disable in one step
  87. inline void glSetEnable( GLenum which, bool enable )
  88. {
  89. if (enable)
  90. glEnable(which);
  91. else
  92. glDisable(which);
  93. }
  94. // helper function for int vs enum clarity
  95. inline void glGetEnumv( GLenum which, GLenum *dst )
  96. {
  97. glGetIntegerv( which, (int*)dst );
  98. }
  99. //===========================================================================//
  100. //
  101. // types to support the GLMContext
  102. //
  103. //===========================================================================//
  104. // Each state set/get path we are providing caching for, needs its own struct and a comparison operator.
  105. // we also provide an enum of how many such types there are, handy for building dirty masks etc.
  106. // shorthand macros
  107. #define EQ(fff) ( (src.fff) == (fff) )
  108. //rasterizer
  109. struct GLAlphaTestEnable_t { GLint enable; bool operator==(const GLAlphaTestEnable_t& src) const { return EQ(enable); } };
  110. struct GLAlphaTestFunc_t { GLenum func; GLclampf ref; bool operator==(const GLAlphaTestFunc_t& src) const { return EQ(func) && EQ(ref); } };
  111. struct GLCullFaceEnable_t { GLint enable; bool operator==(const GLCullFaceEnable_t& src) const { return EQ(enable); } };
  112. struct GLCullFrontFace_t { GLenum value; bool operator==(const GLCullFrontFace_t& src) const { return EQ(value); } };
  113. struct GLPolygonMode_t { GLenum values[2]; bool operator==(const GLPolygonMode_t& src) const { return EQ(values[0]) && EQ(values[1]); } };
  114. struct GLDepthBias_t { GLfloat factor; GLfloat units; bool operator==(const GLDepthBias_t& src) const { return EQ(factor) && EQ(units); } };
  115. struct GLScissorEnable_t { GLint enable; bool operator==(const GLScissorEnable_t& src) const { return EQ(enable); } };
  116. struct GLScissorBox_t { GLint x,y; GLsizei width, height; bool operator==(const GLScissorBox_t& src) const { return EQ(x) && EQ(y) && EQ(width) && EQ(height); } };
  117. struct GLAlphaToCoverageEnable_t{ GLint enable; bool operator==(const GLAlphaToCoverageEnable_t& src) const { return EQ(enable); } };
  118. struct GLViewportBox_t { GLint x,y; GLsizei width, height; bool operator==(const GLViewportBox_t& src) const { return EQ(x) && EQ(y) && EQ(width) && EQ(height); } };
  119. struct GLViewportDepthRange_t { GLdouble near,far; bool operator==(const GLViewportDepthRange_t& src) const { return EQ(near) && EQ(far); } };
  120. struct GLClipPlaneEnable_t { GLint enable; bool operator==(const GLClipPlaneEnable_t& src) const { return EQ(enable); } };
  121. struct GLClipPlaneEquation_t { GLfloat x,y,z,w; bool operator==(const GLClipPlaneEquation_t& src) const { return EQ(x) && EQ(y) && EQ(z) && EQ(w); } };
  122. //blend
  123. struct GLColorMaskSingle_t { char r,g,b,a; bool operator==(const GLColorMaskSingle_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } };
  124. struct GLColorMaskMultiple_t { char r,g,b,a; bool operator==(const GLColorMaskMultiple_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } };
  125. struct GLBlendEnable_t { GLint enable; bool operator==(const GLBlendEnable_t& src) const { return EQ(enable); } };
  126. struct GLBlendFactor_t { GLenum srcfactor,dstfactor; bool operator==(const GLBlendFactor_t& src) const { return EQ(srcfactor) && EQ(dstfactor); } };
  127. struct GLBlendEquation_t { GLenum equation; bool operator==(const GLBlendEquation_t& src) const { return EQ(equation); } };
  128. struct GLBlendColor_t { GLfloat r,g,b,a; bool operator==(const GLBlendColor_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } };
  129. struct GLBlendEnableSRGB_t { GLint enable; bool operator==(const GLBlendEnableSRGB_t& src) const { return EQ(enable); } };
  130. //depth
  131. struct GLDepthTestEnable_t { GLint enable; bool operator==(const GLDepthTestEnable_t& src) const { return EQ(enable); } };
  132. struct GLDepthFunc_t { GLenum func; bool operator==(const GLDepthFunc_t& src) const { return EQ(func); } };
  133. struct GLDepthMask_t { char mask; bool operator==(const GLDepthMask_t& src) const { return EQ(mask); } };
  134. //stencil
  135. struct GLStencilTestEnable_t { GLint enable; bool operator==(const GLStencilTestEnable_t& src) const { return EQ(enable); } };
  136. struct GLStencilFunc_t { GLenum frontfunc, backfunc; GLint ref; GLuint mask; bool operator==(const GLStencilFunc_t& src) const { return EQ(frontfunc) && EQ(backfunc) && EQ(ref) && EQ(mask); } };
  137. struct GLStencilOp_t { GLenum sfail; GLenum dpfail; GLenum dppass; bool operator==(const GLStencilOp_t& src) const { return EQ(sfail) && EQ(dpfail) && EQ(dppass); } };
  138. struct GLStencilWriteMask_t { GLint mask; bool operator==(const GLStencilWriteMask_t& src) const { return EQ(mask); } };
  139. //clearing
  140. struct GLClearColor_t { GLfloat r,g,b,a; bool operator==(const GLClearColor_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } };
  141. struct GLClearDepth_t { GLdouble d; bool operator==(const GLClearDepth_t& src) const { return EQ(d); } };
  142. struct GLClearStencil_t { GLint s; bool operator==(const GLClearStencil_t& src) const { return EQ(s); } };
  143. #undef EQ
  144. enum EGLMStateBlockType
  145. {
  146. kGLAlphaTestEnable,
  147. kGLAlphaTestFunc,
  148. kGLCullFaceEnable,
  149. kGLCullFrontFace,
  150. kGLPolygonMode,
  151. kGLDepthBias,
  152. kGLScissorEnable,
  153. kGLScissorBox,
  154. kGLViewportBox,
  155. kGLViewportDepthRange,
  156. kGLClipPlaneEnable,
  157. kGLClipPlaneEquation,
  158. kGLColorMaskSingle,
  159. kGLColorMaskMultiple,
  160. kGLBlendEnable,
  161. kGLBlendFactor,
  162. kGLBlendEquation,
  163. kGLBlendColor,
  164. kGLBlendEnableSRGB,
  165. kGLDepthTestEnable,
  166. kGLDepthFunc,
  167. kGLDepthMask,
  168. kGLStencilTestEnable,
  169. kGLStencilFunc,
  170. kGLStencilOp,
  171. kGLStencilWriteMask,
  172. kGLClearColor,
  173. kGLClearDepth,
  174. kGLClearStencil,
  175. kGLAlphaToCoverageEnable,
  176. kGLMStateBlockLimit
  177. };
  178. //===========================================================================//
  179. // templated functions representing GL R/W bottlenecks
  180. // one set of set/get/getdefault is instantiated for each of the GL*** types above.
  181. // use these from the non array state objects
  182. template<typename T> void GLContextSet( T *src );
  183. template<typename T> void GLContextGet( T *dst );
  184. template<typename T> void GLContextGetDefault( T *dst );
  185. // use these from the array state objects
  186. template<typename T> void GLContextSetIndexed( T *src, int index );
  187. template<typename T> void GLContextGetIndexed( T *dst, int index );
  188. template<typename T> void GLContextGetDefaultIndexed( T *dst, int index );
  189. //===========================================================================//
  190. // caching state object template. One of these is instantiated in the context per unique struct type above
  191. template<typename T> class GLState
  192. {
  193. public:
  194. GLState<T>()
  195. {
  196. dirty = false;
  197. memset( &data, 0, sizeof(data) );
  198. };
  199. // write: client src into cache
  200. // common case is both false. dirty is calculated, context write is deferred.
  201. void Write( T *src, bool noCompare=false, bool noDefer=false )
  202. {
  203. if (noCompare)
  204. {
  205. dirty = true;
  206. }
  207. else
  208. {
  209. // only == is implemented, so test for equal and negate
  210. // note, you only set dirty if mismatch, you never clear it until flush
  211. if ( !(data == *src) )
  212. {
  213. dirty = true;
  214. }
  215. }
  216. data = *src;
  217. if (noDefer)
  218. {
  219. Flush( true ); // dirty becomes false
  220. }
  221. };
  222. // write cache->context if dirty or forced.
  223. void Flush( bool noDefer=false )
  224. {
  225. if (dirty || noDefer)
  226. {
  227. GLContextSet( &data );
  228. GLMCheckError();
  229. // good place for some error checking here
  230. dirty = false;
  231. }
  232. };
  233. // default: write default value to cache, optionally write through
  234. void Default( bool noDefer=false )
  235. {
  236. GLContextGetDefault( &data ); // read default values directly to our cache copy
  237. dirty = true;
  238. Flush(noDefer);
  239. };
  240. // read: sel = 0 for cache, 1 for context
  241. void Read( T *dst, int sel )
  242. {
  243. if (sel==0)
  244. {
  245. *dst = data;
  246. }
  247. else
  248. {
  249. GLContextGet( dst );
  250. GLMCheckError();
  251. }
  252. };
  253. // check: verify that context equals cache, return true if mismatched or if illegal values seen
  254. bool Check ( void )
  255. {
  256. T temp;
  257. bool result;
  258. GLContextGet( &temp );
  259. GLMCheckError();
  260. result = !(temp == data);
  261. return result;
  262. };
  263. protected:
  264. T data;
  265. bool dirty;
  266. };
  267. // caching state object template - with multiple values behind it that are indexed
  268. template<typename T, int COUNT> class GLStateArray
  269. {
  270. public:
  271. GLStateArray<T,COUNT>()
  272. {
  273. memset( &dirty, 0, sizeof(dirty) );
  274. memset( &data, 0, sizeof(data) );
  275. };
  276. // write: client src into cache
  277. // common case is both false. dirty is calculated, context write is deferred.
  278. void WriteIndex( T *src, int index, bool noCompare=false, bool noDefer=false )
  279. {
  280. if (noCompare)
  281. {
  282. dirty[index] = true;
  283. }
  284. else
  285. {
  286. // only == is implemented, so test for equal and negate
  287. // note, you only set dirty if mismatch, you never clear it until flush
  288. if (! (data[index] == *src) )
  289. {
  290. dirty[index] = true;
  291. }
  292. }
  293. data[index] = *src;
  294. if (noDefer)
  295. {
  296. FlushIndex( index, true ); // dirty becomes false
  297. }
  298. };
  299. // write cache->context if dirty or forced.
  300. void FlushIndex( int index, bool noDefer=false )
  301. {
  302. if (dirty[index] || noDefer)
  303. {
  304. GLContextSetIndexed( &data[index], index );
  305. GLMCheckError();
  306. dirty[index] = false;
  307. }
  308. };
  309. // write all slots in the array
  310. void Flush( bool noDefer=false )
  311. {
  312. for( int i=0; i<COUNT; i++)
  313. {
  314. FlushIndex( i, noDefer );
  315. }
  316. }
  317. // default: write default value to cache, optionally write through
  318. void DefaultIndex( int index, bool noDefer=false )
  319. {
  320. GLContextGetDefaultIndexed( &data[index], index ); // read default values directly to our cache copy
  321. dirty[index] = true;
  322. Flush(noDefer);
  323. };
  324. void Default( void )
  325. {
  326. for( int i=0; i<COUNT; i++)
  327. {
  328. DefaultIndex( i );
  329. }
  330. }
  331. // read: sel = 0 for cache, 1 for context
  332. void ReadIndex( T *dst, int index, int sel )
  333. {
  334. if (sel==0)
  335. {
  336. *dst = data[index];
  337. }
  338. else
  339. {
  340. GLContextGetIndexed( dst, index );
  341. GLMCheckError();
  342. }
  343. };
  344. // check: verify that context equals cache, return true if mismatched or if illegal values seen
  345. bool CheckIndex( int index )
  346. {
  347. T temp;
  348. bool result;
  349. GLContextGetIndexed( &temp, index );
  350. GLMCheckError();
  351. result = !(temp == data[index]);
  352. return result;
  353. };
  354. bool Check( void )
  355. {
  356. T temp;
  357. bool result = false;
  358. for( int i=0; i<COUNT; i++)
  359. {
  360. result |= CheckIndex( i );
  361. }
  362. return result;
  363. };
  364. protected:
  365. T data [COUNT];
  366. bool dirty [COUNT];
  367. };
  368. //===========================================================================//
  369. struct GLMTexSampler
  370. {
  371. GLMTexSamplingParams m_samp;
  372. CGLMTex *m_drawTex; // tex which must be bound at time of draw
  373. CGLMTex *m_boundTex; // tex which is actually bound now (if does not match, a rebind is needed to draw)
  374. };
  375. //===========================================================================//
  376. enum GLMVertexAttributeIndex
  377. {
  378. kGLMGenericAttr00 = 0,
  379. kGLMGenericAttr01,
  380. kGLMGenericAttr02,
  381. kGLMGenericAttr03,
  382. kGLMGenericAttr04,
  383. kGLMGenericAttr05,
  384. kGLMGenericAttr06,
  385. kGLMGenericAttr07,
  386. kGLMGenericAttr08,
  387. kGLMGenericAttr09,
  388. kGLMGenericAttr10,
  389. kGLMGenericAttr11,
  390. kGLMGenericAttr12,
  391. kGLMGenericAttr13,
  392. kGLMGenericAttr14,
  393. kGLMGenericAttr15,
  394. kGLMVertexAttributeIndexMax // ideally < 32
  395. };
  396. struct GLMVertexAttributeDesc // all the info you need to do vertex setup for one attribute
  397. {
  398. CGLMBuffer *m_buffer; // NULL allowed in which case m_offset is the full 32-bit pointer.. so you can draw from plain RAM if desired
  399. GLuint m_datasize; // comp count of the attribute (1-4)
  400. GLenum m_datatype; // data type of the attribute (GL_FLOAT, GL_UNSIGNED_BYTE, etc)
  401. GLuint m_stride;
  402. GLuint m_offset; // net offset to attribute 'zero' within the buffer.
  403. GLboolean m_normalized; // apply to any fixed point data that needs normalizing, esp color bytes
  404. // may need a seed value at some point to be able to disambiguate re-lifed buffers holding same pointer
  405. // simpler alternative is to do shoot-down inside the vertex/index buffer free calls.
  406. // I'd rather not have to have each attribute fiddling a ref count on the buffer to which it refers..
  407. #define EQ(fff) ( (src.fff) == (fff) )
  408. // test in decreasing order of likelihood of difference, but do not include the buffer revision as caller is not supplying it..
  409. bool operator==(const GLMVertexAttributeDesc& src) const { return EQ(m_buffer) && EQ(m_offset) && EQ(m_stride) && EQ(m_datatype) && EQ(m_normalized) && EQ(m_datasize); }
  410. #undef EQ
  411. uint m_bufferRevision; // only set in GLM context's copy, to disambiguate references that are same offset / same buffer but cross an orphan event
  412. };
  413. // GLMContext will maintain one of these structures inside the context to represent the current state.
  414. // Client can supply a new one when it wants to change the setup.
  415. //FIXME GLMContext can do the work to migrate from old setup to new setup as efficiently as possible (but it doesn't yet)
  416. struct GLMVertexSetup
  417. {
  418. uint m_attrMask; // which attrs are enabled (1<<n) mask where n is a GLMVertexAttributeIndex.
  419. GLMVertexAttributeDesc m_attrs[ kGLMVertexAttributeIndexMax ];
  420. // copied in from dxabstract, not strictly needed for operation, helps debugging
  421. unsigned char m_vtxAttribMap[16];
  422. /* high nibble is usage per _D3DDECLUSAGE
  423. typedef enum _D3DDECLUSAGE
  424. {
  425. D3DDECLUSAGE_POSITION = 0,
  426. D3DDECLUSAGE_BLENDWEIGHT = 1,
  427. D3DDECLUSAGE_BLENDINDICES = 2,
  428. D3DDECLUSAGE_NORMAL = 3,
  429. D3DDECLUSAGE_PSIZE = 4,
  430. D3DDECLUSAGE_TEXCOORD = 5,
  431. D3DDECLUSAGE_TANGENT = 6,
  432. D3DDECLUSAGE_BINORMAL = 7,
  433. D3DDECLUSAGE_TESSFACTOR = 8,
  434. D3DDECLUSAGE_PLUGH = 9, // mystery value
  435. D3DDECLUSAGE_COLOR = 10,
  436. D3DDECLUSAGE_FOG = 11,
  437. D3DDECLUSAGE_DEPTH = 12,
  438. D3DDECLUSAGE_SAMPLE = 13,
  439. } D3DDECLUSAGE;
  440. low nibble is usageindex (i.e. POSITION0, POSITION1, etc)
  441. array position is attrib number.
  442. */
  443. };
  444. //===========================================================================//
  445. //FIXME magic numbers here
  446. #define kGLMProgramParamFloat4Limit 256
  447. #define kGLMProgramParamBoolLimit 16
  448. #define kGLMProgramParamInt4Limit 16
  449. #define kGLMVertexProgramParamFloat4Limit 256
  450. #define kGLMFragmentProgramParamFloat4Limit 32
  451. struct GLMProgramParamsF
  452. {
  453. float m_values[kGLMProgramParamFloat4Limit][4]; // float4's 256 of them
  454. uint m_dirtySlotCount; // index of slot past highest dirty (assume 0 for base of range)
  455. };
  456. struct GLMProgramParamsB
  457. {
  458. int m_values[kGLMProgramParamBoolLimit]; // bools, 4 of them
  459. uint m_dirtySlotCount;
  460. };
  461. struct GLMProgramParamsI
  462. {
  463. int m_values[kGLMProgramParamInt4Limit][4]; // int4s, 16 of them
  464. uint m_dirtySlotCount;
  465. };
  466. enum EGLMParamWriteMode
  467. {
  468. eParamWriteAllSlots, // glUniform4fv of the maximum size (not recommended if shader is down-sizing the decl)
  469. eParamWriteShaderSlots, // glUniform4fv of the active slot count ("highwater")
  470. eParamWriteShaderSlotsOptional, // glUniform4fv of the active slot count ("highwater") - but only if at least one has been written - it's optional
  471. eParamWriteDirtySlotRange // glUniform4fv of the 0-N range where N is highest dirty slot
  472. };
  473. enum EGLMAttribWriteMode
  474. {
  475. eAttribWriteAll,
  476. eAttribWriteDirty
  477. };
  478. //===========================================================================//
  479. #if GLMDEBUG
  480. enum EGLMDebugCallSite
  481. {
  482. eBeginFrame, // inside begin frame func - frame number has been inc'd, batch number should be -1
  483. eClear, // inside clear func
  484. eDrawElements, // inside repeat loop, prior to draw call - batch numberhas been inc'd
  485. eEndFrame, // end frame
  486. ePresent // before showing pixels
  487. };
  488. // caller should zero one of these out and fill in the m_caller before invoking the hook
  489. struct GLMDebugHookInfo
  490. {
  491. // info from the caller to the debug hook
  492. EGLMDebugCallSite m_caller;
  493. // state the hook uses to keep track of progress within a single run of the caller
  494. int m_iteration; // which call to the hook is this. if it's zero, it precedes any action in the caller.
  495. // bools used to communicate between caller and hook
  496. bool m_loop; // hook tells caller to loop around again (don't exit)
  497. bool m_holding; // current mood of hook, are we holding on this batch (i.e. rerun)
  498. // specific info for a draw call
  499. GLenum m_drawMode;
  500. GLuint m_drawStart;
  501. GLuint m_drawEnd;
  502. GLsizei m_drawCount;
  503. GLenum m_drawType;
  504. const GLvoid *m_drawIndices;
  505. };
  506. #endif
  507. //===========================================================================//
  508. #define kGLMUserClipPlanes 2
  509. #define kGLMScratchFBOCount 4
  510. class GLMContext
  511. {
  512. public:
  513. // set/check current context (perq for many other calls)
  514. void MakeCurrent( void );
  515. void CheckCurrent( void ); // verify that this context is current if you think it is. (help catch violations)
  516. void PopulateCaps( void ); // fill out later portions of renderer info record which need context queries
  517. void DumpCaps( void ); // printf all the caps info (you can call this in release too)
  518. const GLMRendererInfoFields& Caps( void ); // peek at the caps record
  519. // state cache/mirror
  520. void SetDefaultStates( void );
  521. void FlushStates( bool noDefer = false );
  522. void VerifyStates( void );
  523. // textures
  524. // Lock and Unlock reqs go directly to the tex object
  525. CGLMTex *NewTex( GLMTexLayoutKey *key, const char *debugLabel=NULL );
  526. void DelTex( CGLMTex *tex );
  527. // options for Blit (replacement for ResolveTex and BlitTex)
  528. // 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.
  529. void Blit2( CGLMTex *srcTex, GLMRect *srcRect, int srcFace, int srcMip, CGLMTex *dstTex, GLMRect *dstRect, int dstFace, int dstMip, uint filter );
  530. // tex blit (via FBO blit)
  531. void BlitTex( CGLMTex *srcTex, GLMRect *srcRect, int srcFace, int srcMip, CGLMTex *dstTex, GLMRect *dstRect, int dstFace, int dstMip, uint filter, bool useBlitFB = true );
  532. // MSAA resolve - we do this in GLMContext because it has to do a bunch of FBO/blit gymnastics
  533. void ResolveTex( CGLMTex *tex, bool forceDirty=false );
  534. // texture pre-load (residency forcing) - normally done one-time but you can force it
  535. void PreloadTex( CGLMTex *tex, bool force=false );
  536. // samplers
  537. void SetSamplerTex( int sampler, CGLMTex *tex );
  538. void SetSamplerParams( int sampler, GLMTexSamplingParams *params );
  539. // render targets (FBO's)
  540. CGLMFBO *NewFBO( void );
  541. void DelFBO( CGLMFBO *fbo );
  542. void SetDrawingFBO( CGLMFBO *fbo ); // as with samplers, the notion of the target FBO is latched til draw time and then checked
  543. // programs
  544. CGLMProgram *NewProgram( EGLMProgramType type, char *progString );
  545. void DelProgram( CGLMProgram *prog );
  546. void NullProgram( void ); // de-ac all shader state
  547. void SetDrawingProgram( EGLMProgramType type, CGLMProgram *prog ); // set NULL for no program
  548. void SetDrawingLang( EGLMProgramLang lang, bool immediate=false ); // choose ARB or GLSL. immediate=false defers lang change to top of frame
  549. void LinkShaderPair( CGLMProgram *vp, CGLMProgram *fp ); // ensure this combo has been linked and is in the GLSL pair cache
  550. void ClearShaderPairCache( void ); // call this to shoot down all the linked pairs
  551. void QueryShaderPair( int index, GLMShaderPairInfo *infoOut ); // this lets you query the shader pair cache for saving its state
  552. // buffers
  553. // Lock and Unlock reqs go directly to the buffer object
  554. CGLMBuffer *NewBuffer( EGLMBufferType type, uint size, uint options );
  555. void DelBuffer( CGLMBuffer *buff );
  556. void SetIndexBuffer( CGLMBuffer *buff );
  557. void SetVertexAttributes( GLMVertexSetup *setup );
  558. // note, no API is exposed for setting a single attribute source.
  559. // come prepared with a complete block of attributes to use.
  560. // Queries
  561. CGLMQuery *NewQuery( GLMQueryParams *params );
  562. void DelQuery( CGLMQuery *query );
  563. // "slot" means a vec4-sized thing
  564. // these write into .env parameter space
  565. void SetProgramParametersF( EGLMProgramType type, uint baseSlot, float *slotData, uint slotCount ); // take vec4f's
  566. void SetProgramParametersB( EGLMProgramType type, uint baseSlot, int *slotData, uint boolCount ); // take "BOOL" aka int
  567. void SetProgramParametersI( EGLMProgramType type, uint baseSlot, int *slotData, uint slotCount ); // take int4s
  568. // state sync
  569. void FlushDrawStates( bool shadersOn=true ); // pushes all drawing state - samplers, tex, programs, etc.
  570. // drawing
  571. void DrawRangeElements( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices );
  572. void CheckNative( void );
  573. // clearing
  574. void Clear( bool color, unsigned long colorValue, bool depth, float depthValue, bool stencil, unsigned int stencilValue, GLScissorBox_t *rect = NULL );
  575. // display
  576. //void SetVSyncEnable( bool vsyncOn );
  577. //void SetFullScreen( bool fsOn, int screenIndex ); // will be latched for next BeginFrame
  578. //void ActivateFullScreen( bool fsOn, int screenIndex ); // will be called by BeginFrame
  579. bool SetDisplayParams( GLMDisplayParams *params ); // either the first time setup, or a change to new setup
  580. void Present( CGLMTex *tex ); // somewhat hardwired for the time being
  581. // mode switch / reset
  582. void Reset( void ); // not a lot of args for now..
  583. // writers for the state block inputs
  584. void WriteAlphaTestEnable ( GLAlphaTestEnable_t *src );
  585. void WriteAlphaTestFunc ( GLAlphaTestFunc_t *src );
  586. void WriteCullFaceEnable ( GLCullFaceEnable_t *src );
  587. void WriteCullFrontFace ( GLCullFrontFace_t *src );
  588. void WritePolygonMode ( GLPolygonMode_t *src );
  589. void WriteDepthBias ( GLDepthBias_t *src );
  590. void WriteClipPlaneEnable ( GLClipPlaneEnable_t *src, int which );
  591. void WriteClipPlaneEquation ( GLClipPlaneEquation_t *src, int which );
  592. void WriteScissorEnable ( GLScissorEnable_t *src );
  593. void WriteScissorBox ( GLScissorBox_t *src );
  594. void WriteAlphaToCoverageEnable ( GLAlphaToCoverageEnable_t *src );
  595. void WriteViewportBox ( GLViewportBox_t *src );
  596. void WriteViewportDepthRange ( GLViewportDepthRange_t *src );
  597. void WriteColorMaskSingle ( GLColorMaskSingle_t *src );
  598. void WriteColorMaskMultiple ( GLColorMaskMultiple_t *src, int which );
  599. void WriteBlendEnable ( GLBlendEnable_t *src );
  600. void WriteBlendFactor ( GLBlendFactor_t *src );
  601. void WriteBlendEquation ( GLBlendEquation_t *src );
  602. void WriteBlendColor ( GLBlendColor_t *src );
  603. void WriteBlendEnableSRGB ( GLBlendEnableSRGB_t *src );
  604. void WriteDepthTestEnable ( GLDepthTestEnable_t *src );
  605. void WriteDepthFunc ( GLDepthFunc_t *src );
  606. void WriteDepthMask ( GLDepthMask_t *src );
  607. void WriteStencilTestEnable ( GLStencilTestEnable_t *src );
  608. void WriteStencilFunc ( GLStencilFunc_t *src );
  609. void WriteStencilOp ( GLStencilOp_t *src, int which );
  610. void WriteStencilWriteMask ( GLStencilWriteMask_t *src );
  611. void WriteClearColor ( GLClearColor_t *src );
  612. void WriteClearDepth ( GLClearDepth_t *src );
  613. void WriteClearStencil ( GLClearStencil_t *src );
  614. // debug stuff
  615. void BeginFrame( void );
  616. void EndFrame( void );
  617. // new interactive debug stuff
  618. #if GLMDEBUG
  619. void DebugDump( GLMDebugHookInfo *info, uint options, uint vertDumpMode );
  620. void DebugHook( GLMDebugHookInfo *info );
  621. void DebugPresent( void );
  622. void DebugClear( void );
  623. #endif
  624. protected:
  625. friend class GLMgr; // only GLMgr can make GLMContext objects
  626. friend class GLMRendererInfo; // only GLMgr can make GLMContext objects
  627. friend class CGLMTex; // tex needs to be able to do binds
  628. friend class CGLMFBO; // fbo needs to be able to do binds
  629. friend class CGLMProgram;
  630. friend class CGLMShaderPair;
  631. friend class CGLMShaderPairCache;
  632. friend class CGLMBuffer;
  633. friend class GLMTester; // tester class needs access back into GLMContext
  634. friend class IDirect3D9;
  635. friend class IDirect3DDevice9;
  636. // methods------------------------------------------
  637. // old GLMContext( GLint displayMask, GLint rendererID, PseudoNSGLContextPtr nsglShareCtx );
  638. GLMContext( GLMDisplayParams *params );
  639. ~GLMContext();
  640. // textures
  641. void SelectTMU( int tmu ); // wrapper for glActiveTexture()
  642. int BindTexToTMU( CGLMTex *tex, int tmu, bool noCheck=false );
  643. // render targets / FBO's
  644. void BindFBOToCtx( CGLMFBO *fbo, GLenum bindPoint = GL_FRAMEBUFFER_EXT ); // you can also choose GL_READ_FRAMEBUFFER_EXT / GL_DRAW_FRAMEBUFFER_EXT
  645. // programs
  646. //void BindProgramToCtx( EGLMProgramType type, CGLMProgram *prog ); // will set program mode enable appropriately
  647. // buffers
  648. void BindBufferToCtx( EGLMBufferType type, CGLMBuffer *buff, bool force = false ); // does not twiddle any enables.
  649. // debug font
  650. void GenDebugFontTex( void );
  651. void DrawDebugText( float x, float y, float z, float drawCharWidth, float drawCharHeight, char *string );
  652. // members------------------------------------------
  653. // context
  654. GLMRendererInfoFields m_caps;
  655. bool m_displayParamsValid; // is there a param block copied in yet
  656. GLMDisplayParams m_displayParams; // last known display config, either via constructor, or by SetDisplayParams...
  657. CGLPixelFormatAttribute m_pixelFormatAttribs[100]; // more than enough
  658. PseudoNSGLContextPtr m_nsctx;
  659. CGLContextObj m_ctx;
  660. bool m_oneCtxEnable; // true if we use the window's context directly instead of making a second one shared against it
  661. // texture form table
  662. CGLMTexLayoutTable *m_texLayoutTable;
  663. // context state mirrors
  664. GLState<GLAlphaTestEnable_t> m_AlphaTestEnable;
  665. GLState<GLAlphaTestFunc_t> m_AlphaTestFunc;
  666. GLState<GLCullFaceEnable_t> m_CullFaceEnable;
  667. GLState<GLCullFrontFace_t> m_CullFrontFace;
  668. GLState<GLPolygonMode_t> m_PolygonMode;
  669. GLState<GLDepthBias_t> m_DepthBias;
  670. GLStateArray<GLClipPlaneEnable_t,kGLMUserClipPlanes> m_ClipPlaneEnable;
  671. GLStateArray<GLClipPlaneEquation_t,kGLMUserClipPlanes> m_ClipPlaneEquation; // dxabstract puts them directly into param slot 253(0) and 254(1)
  672. GLState<GLScissorEnable_t> m_ScissorEnable;
  673. GLState<GLScissorBox_t> m_ScissorBox;
  674. GLState<GLAlphaToCoverageEnable_t> m_AlphaToCoverageEnable;
  675. GLState<GLViewportBox_t> m_ViewportBox;
  676. GLState<GLViewportDepthRange_t> m_ViewportDepthRange;
  677. GLState<GLColorMaskSingle_t> m_ColorMaskSingle;
  678. GLStateArray<GLColorMaskMultiple_t,8> m_ColorMaskMultiple; // need an official constant for the color buffers limit
  679. GLState<GLBlendEnable_t> m_BlendEnable;
  680. GLState<GLBlendFactor_t> m_BlendFactor;
  681. GLState<GLBlendEquation_t> m_BlendEquation;
  682. GLState<GLBlendColor_t> m_BlendColor;
  683. GLState<GLBlendEnableSRGB_t> m_BlendEnableSRGB; // write to this one to transmit intent to write SRGB encoded pixels to drawing FB
  684. bool m_FakeBlendEnableSRGB; // writes to above will be shunted here if fake SRGB is in effect.
  685. GLState<GLDepthTestEnable_t> m_DepthTestEnable;
  686. GLState<GLDepthFunc_t> m_DepthFunc;
  687. GLState<GLDepthMask_t> m_DepthMask;
  688. GLState<GLStencilTestEnable_t> m_StencilTestEnable; // global stencil test enable
  689. GLState<GLStencilFunc_t> m_StencilFunc; // holds front and back stencil funcs
  690. GLStateArray<GLStencilOp_t,2> m_StencilOp; // indexed: 0=front 1=back
  691. GLState<GLStencilWriteMask_t> m_StencilWriteMask;
  692. GLState<GLClearColor_t> m_ClearColor;
  693. GLState<GLClearDepth_t> m_ClearDepth;
  694. GLState<GLClearStencil_t> m_ClearStencil;
  695. // texture bindings and sampler setup
  696. int m_activeTexture; // mirror for glActiveTexture
  697. GLMTexSampler m_samplers[GLM_SAMPLER_COUNT];
  698. // texture lock tracking - CGLMTex objects share usage of this
  699. CUtlVector< GLMTexLockDesc > m_texLocks;
  700. // render target binding - check before draw
  701. // similar to tex sampler mechanism, we track "bound" from "chosen for drawing" separately,
  702. // so binding for creation/setup need not disrupt any notion of what will be used at draw time
  703. CGLMFBO *m_boundDrawFBO; // FBO on GL_DRAW_FRAMEBUFFER bind point
  704. CGLMFBO *m_boundReadFBO; // FBO on GL_READ_FRAMEBUFFER bind point
  705. // ^ both are set if you bind to GL_FRAMEBUFFER_EXT
  706. CGLMFBO *m_drawingFBO; // what FBO should be bound at draw time (to both read/draw bp's).
  707. CGLMFBO *m_blitReadFBO;
  708. CGLMFBO *m_blitDrawFBO; // scratch FBO's for framebuffer blit
  709. CGLMFBO *m_scratchFBO[ kGLMScratchFBOCount ]; // general purpose FBO's for internal use
  710. CUtlVector< CGLMFBO* > m_fboTable; // each live FBO goes in the table
  711. // program bindings
  712. EGLMProgramLang m_drawingLangAtFrameStart; // selector for start of frame (spills into m_drawingLang)
  713. EGLMProgramLang m_drawingLang; // selector for which language we desire to draw with on the next batch
  714. CGLMProgram *m_drawingProgram[ kGLMNumProgramTypes ];
  715. GLMProgramParamsF m_programParamsF[ kGLMNumProgramTypes ];
  716. GLMProgramParamsB m_programParamsB[ kGLMNumProgramTypes ]; // two banks, but only the vertex one is used
  717. GLMProgramParamsI m_programParamsI[ kGLMNumProgramTypes ]; // two banks, but only the vertex one is used
  718. EGLMParamWriteMode m_paramWriteMode;
  719. CGLMProgram *m_nullFragmentProgram; // write opaque black. Activate when caller asks for null FP
  720. CGLMProgram *m_preloadTexVertexProgram; // programs to help preload textures (dummies)
  721. CGLMProgram *m_preload2DTexFragmentProgram;
  722. CGLMProgram *m_preload3DTexFragmentProgram;
  723. CGLMProgram *m_preloadCubeTexFragmentProgram;
  724. CGLMProgram *m_boundProgram[ kGLMNumProgramTypes ];
  725. CGLMShaderPairCache *m_pairCache; // GLSL only
  726. CGLMShaderPair *m_boundPair; // GLSL only
  727. uint m_boundPairRevision; // GLSL only
  728. GLhandleARB m_boundPairProgram; // GLSL only
  729. // buffer bindings
  730. CGLMBuffer *m_lastKnownBufferBinds[ kGLMNumBufferTypes ]; // tracked per bind point for dupe-bind-absorb
  731. GLMVertexAttributeDesc m_lastKnownVertexAttribs[ kGLMVertexAttributeIndexMax ]; // tracked per attrib for dupe-set-absorb
  732. uint m_lastKnownVertexAttribMask; // tracked for dupe-enable-absorb
  733. CGLMBuffer *m_drawIndexBuffer; // ... ? do we need dupe tracking for index buffer setup? ?
  734. GLMVertexSetup m_drawVertexSetup;
  735. EGLMAttribWriteMode m_attribWriteMode;
  736. bool m_slowCheckEnable; // turn this on or no native checking is done ("-glmassertslow" or "-glmsspewslow")
  737. bool m_slowAssertEnable; // turn this on to assert on a non-native batch "-glmassertslow"
  738. bool m_slowSpewEnable; // turn this on to log non-native batches to stdout "-glmspewslow"
  739. // debug font texture
  740. CGLMTex *m_debugFontTex; // might be NULL unless you call GenDebugFontTex
  741. CGLMBuffer *m_debugFontIndices; // up to 1024 indices (256 chars times 4)
  742. CGLMBuffer *m_debugFontVertices; // up to 1024 verts
  743. // batch/frame debugging support
  744. int m_debugFrameIndex; // init to -1. Increment at BeginFrame
  745. int m_debugBatchIndex; // init to -1. Increment at any draw call
  746. #if GLMDEBUG
  747. // interactive (DebugHook) debug support
  748. // using these you can implement frame advance, batch single step, and batch rewind (let it run til next frame and hold on prev batch #)
  749. int m_holdFrameBegin; // -1 if no hold req'd, otherwise # of frame to hold at (at beginframe time)
  750. int m_holdFrameEnd; // -1 if no hold req'd, otherwise # of frame to hold at (at endframe time)
  751. int m_holdBatch,m_holdBatchFrame; // -1 if no hold, else # of batch&frame to hold at (both must be set)
  752. // these can be expired/cleared to -1 if the frame passes without a hit
  753. // may be desirable to re-pause in that event, as user was expecting a hold to occur
  754. bool m_debugDelayEnable; // allow sleep delay
  755. uint m_debugDelay; // sleep time per hook call in microseconds (for usleep())
  756. // pre-draw global toggles / options
  757. bool m_autoClearColor,m_autoClearDepth,m_autoClearStencil;
  758. float m_autoClearColorValues[4];
  759. // debug knobs
  760. int m_selKnobIndex;
  761. float m_selKnobMinValue,m_selKnobMaxValue,m_selKnobIncrement;
  762. #endif
  763. };
  764. struct GLMTestParams
  765. {
  766. GLMContext *m_ctx;
  767. int *m_testList; // -1 termed
  768. bool m_glErrToDebugger;
  769. bool m_glErrToConsole;
  770. bool m_intlErrToDebugger;
  771. bool m_intlErrToConsole;
  772. int m_frameCount; // how many frames to test.
  773. };
  774. class GLMTester
  775. {
  776. public:
  777. GLMTester(GLMTestParams *params);
  778. ~GLMTester();
  779. // optionally callable by test routines to get basic drawables wired up
  780. void StdSetup( void );
  781. void StdCleanup( void );
  782. // callable by test routines to clear the frame or present it
  783. void Clear( void );
  784. void Present( int seed );
  785. // error reporting
  786. void CheckGLError( const char *comment ); // obey m_params setting for console / debugger response
  787. void InternalError( int errcode, char *comment ); // if errcode!=0, obey m_params setting for console / debugger response
  788. void RunTests();
  789. void RunOneTest( int testindex );
  790. // test routines themselves
  791. void Test0();
  792. void Test1();
  793. void Test2();
  794. void Test3();
  795. GLMTestParams m_params; // copy of caller's params, do not mutate...
  796. // std-setup stuff
  797. int m_drawWidth, m_drawHeight;
  798. CGLMFBO *m_drawFBO;
  799. CGLMTex *m_drawColorTex;
  800. CGLMTex *m_drawDepthTex;
  801. };
  802. #endif