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.

547 lines
22 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. // cglmtex.h
  26. // GLMgr textures
  27. //
  28. //===============================================================================
  29. #ifndef CGLMTEX_H
  30. #define CGLMTEX_H
  31. #pragma once
  32. #ifdef OSX
  33. #include "glmgrbasics.h"
  34. #endif
  35. #include "tier1/utlhash.h"
  36. #include "tier1/utlmap.h"
  37. //===============================================================================
  38. // forward declarations
  39. class GLMContext;
  40. class GLMTester;
  41. class CGLMTexLayoutTable;
  42. class CGLMTex;
  43. class CGLMFBO;
  44. struct IDirect3DSurface9;
  45. #if GLMDEBUG
  46. extern CGLMTex *g_pFirstCGMLTex;
  47. #endif
  48. // For GL_EXT_texture_sRGB_decode
  49. #ifndef GL_TEXTURE_SRGB_DECODE_EXT
  50. #define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48
  51. #endif
  52. #ifndef GL_DECODE_EXT
  53. #define GL_DECODE_EXT 0x8A49
  54. #endif
  55. #ifndef GL_SKIP_DECODE_EXT
  56. #define GL_SKIP_DECODE_EXT 0x8A4A
  57. #endif
  58. //===============================================================================
  59. struct GLMTexFormatDesc
  60. {
  61. const char *m_formatSummary; // for debug visibility
  62. D3DFORMAT m_d3dFormat; // what D3D knows it as; see public/bitmap/imageformat.h
  63. GLenum m_glIntFormat; // GL internal format
  64. GLenum m_glIntFormatSRGB; // internal format if SRGB flavor
  65. GLenum m_glDataFormat; // GL data format
  66. GLenum m_glDataType; // GL data type
  67. int m_chunkSize; // 1 or 4 - 4 is used for compressed textures
  68. int m_bytesPerSquareChunk; // how many bytes for the smallest quantum (m_chunkSize x m_chunkSize)
  69. // this description lets us calculate size cleanly without conditional logic for compression
  70. };
  71. const GLMTexFormatDesc *GetFormatDesc( D3DFORMAT format );
  72. //===============================================================================
  73. // utility function for generating slabs of texels. mostly for test.
  74. typedef struct
  75. {
  76. // in
  77. D3DFORMAT m_format;
  78. void *m_dest; // dest address
  79. int m_chunkCount; // square chunk count (single texels or compressed blocks)
  80. int m_byteCountLimit; // caller expectation of max number of bytes to write out
  81. float r,g,b,a; // color desired
  82. // out
  83. int m_bytesWritten;
  84. } GLMGenTexelParams;
  85. // return true if successful
  86. bool GLMGenTexels( GLMGenTexelParams *params );
  87. //===============================================================================
  88. struct GLMTexLayoutSlice
  89. {
  90. int m_xSize,m_ySize,m_zSize; //texel dimensions of this slice
  91. int m_storageOffset; //where in the storage slab does this slice live
  92. int m_storageSize; //how much storage does this slice occupy
  93. };
  94. enum EGLMTexFlags
  95. {
  96. kGLMTexMipped = 0x01,
  97. kGLMTexMippedAuto = 0x02,
  98. kGLMTexRenderable = 0x04,
  99. kGLMTexIsStencil = 0x08,
  100. kGLMTexIsDepth = 0x10,
  101. kGLMTexSRGB = 0x20,
  102. kGLMTexMultisampled = 0x40, // has an RBO backing it. Cannot combine with Mipped, MippedAuto. One slice maximum, only targeting GL_TEXTURE_2D.
  103. // actually not 100% positive on the mipmapping, the RBO itself can't be mipped, but the resulting texture could
  104. // have mipmaps generated.
  105. };
  106. //===============================================================================
  107. struct GLMTexLayoutKey
  108. {
  109. // input values: held const, these are the hash key for the form map
  110. GLenum m_texGLTarget; // flavor of texture: GL_TEXTURE_2D, GL_TEXTURE_3D, GLTEXTURE_CUBE_MAP
  111. D3DFORMAT m_texFormat; // D3D texel format
  112. unsigned long m_texFlags; // mipped, autogen mips, render target, ... ?
  113. unsigned long m_texSamples; // zero for a plain tex, 2/4/6/8 for "MSAA tex" (RBO backed)
  114. int m_xSize,m_ySize,m_zSize; // size of base mip
  115. };
  116. bool LessFunc_GLMTexLayoutKey( const GLMTexLayoutKey &a, const GLMTexLayoutKey &b );
  117. #define GLM_TEX_MAX_MIPS 14
  118. #define GLM_TEX_MAX_FACES 6
  119. #define GLM_TEX_MAX_SLICES (GLM_TEX_MAX_MIPS * GLM_TEX_MAX_FACES)
  120. #pragma warning( push )
  121. #pragma warning( disable : 4200 )
  122. struct GLMTexLayout
  123. {
  124. char *m_layoutSummary; // for debug visibility
  125. // const inputs used for hashing
  126. GLMTexLayoutKey m_key;
  127. // refcount
  128. int m_refCount;
  129. // derived values:
  130. GLMTexFormatDesc *m_format; // format specific info
  131. int m_mipCount; // derived by starying at base size and working down towards 1x1
  132. int m_faceCount; // 1 for 2d/3d, 6 for cubemap
  133. int m_sliceCount; // product of faces and mips
  134. int m_storageTotalSize; // size of storage slab required
  135. // slice array
  136. GLMTexLayoutSlice m_slices[0]; // dynamically allocated 2-d array [faces][mips]
  137. };
  138. #pragma warning( pop )
  139. class CGLMTexLayoutTable
  140. {
  141. public:
  142. CGLMTexLayoutTable();
  143. GLMTexLayout *NewLayoutRef( GLMTexLayoutKey *pDesiredKey ); // pass in a pointer to layout key - receive ptr to completed layout
  144. void DelLayoutRef( GLMTexLayout *layout ); // pass in pointer to completed layout. refcount is dropped.
  145. void DumpStats( void );
  146. protected:
  147. CUtlMap< GLMTexLayoutKey, GLMTexLayout* > m_layoutMap;
  148. };
  149. //===============================================================================
  150. // a sampler specifies desired state for drawing on a given sampler index
  151. // this is the combination of a texture choice and a set of sampler parameters
  152. // see http://msdn.microsoft.com/en-us/library/bb172602(VS.85).aspx
  153. struct GLMTexLockParams
  154. {
  155. // input params which identify the slice of interest
  156. CGLMTex *m_tex;
  157. int m_face;
  158. int m_mip;
  159. // identifies the region of the slice
  160. GLMRegion m_region;
  161. // tells GLM to force re-read of the texels back from GL
  162. // i.e. "I know I stepped on those texels with a draw or blit - the GLM copy is stale"
  163. bool m_readback;
  164. };
  165. struct GLMTexLockDesc
  166. {
  167. GLMTexLockParams m_req; // form of the lock request
  168. bool m_active; // set true at lock time. cleared at unlock time.
  169. int m_sliceIndex; // which slice in the layout
  170. int m_sliceBaseOffset; // where is that in the texture data
  171. int m_sliceRegionOffset; // offset to the start (lowest address corner) of the region requested
  172. };
  173. //===============================================================================
  174. #define GLM_SAMPLER_COUNT 16
  175. #define GLM_MAX_PIXEL_TEX_SAMPLERS 16
  176. #define GLM_MAX_VERTEX_TEX_SAMPLERS 0
  177. typedef CBitVec<GLM_SAMPLER_COUNT> CTexBindMask;
  178. enum EGLMTexSliceFlag
  179. {
  180. kSliceValid = 0x01, // slice has been teximage'd in whole at least once - set to 0 initially
  181. kSliceStorageValid = 0x02, // if backing store is available, this slice's data is a valid copy - set to 0 initially
  182. kSliceLocked = 0x04, // are one or more locks outstanding on this slice
  183. kSliceFullyDirty = 0x08, // does the slice need to be fully downloaded at unlock time (disregard dirty rects)
  184. };
  185. //===============================================================================
  186. #define GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS (2)
  187. #define GLM_PACKED_SAMPLER_PARAMS_MIN_FILTER_BITS (2)
  188. #define GLM_PACKED_SAMPLER_PARAMS_MAG_FILTER_BITS (2)
  189. #define GLM_PACKED_SAMPLER_PARAMS_MIP_FILTER_BITS (2)
  190. #define GLM_PACKED_SAMPLER_PARAMS_MIN_LOD_BITS (4)
  191. #define GLM_PACKED_SAMPLER_PARAMS_MAX_ANISO_BITS (5)
  192. #define GLM_PACKED_SAMPLER_PARAMS_COMPARE_MODE_BITS (1)
  193. #define GLM_PACKED_SAMPLER_PARAMS_SRGB_BITS (1)
  194. struct GLMTexPackedSamplingParams
  195. {
  196. uint32 m_addressU : GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS;
  197. uint32 m_addressV : GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS;
  198. uint32 m_addressW : GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS;
  199. uint32 m_minFilter : GLM_PACKED_SAMPLER_PARAMS_MIN_FILTER_BITS;
  200. uint32 m_magFilter : GLM_PACKED_SAMPLER_PARAMS_MAG_FILTER_BITS;
  201. uint32 m_mipFilter : GLM_PACKED_SAMPLER_PARAMS_MIP_FILTER_BITS;
  202. uint32 m_minLOD : GLM_PACKED_SAMPLER_PARAMS_MIN_LOD_BITS;
  203. uint32 m_maxAniso : GLM_PACKED_SAMPLER_PARAMS_MAX_ANISO_BITS;
  204. uint32 m_compareMode : GLM_PACKED_SAMPLER_PARAMS_COMPARE_MODE_BITS;
  205. uint32 m_srgb : GLM_PACKED_SAMPLER_PARAMS_SRGB_BITS;
  206. uint32 m_isValid : 1;
  207. };
  208. struct GLMTexSamplingParams
  209. {
  210. union
  211. {
  212. GLMTexPackedSamplingParams m_packed;
  213. uint32 m_bits;
  214. };
  215. uint32 m_borderColor;
  216. float m_lodBias;
  217. FORCEINLINE bool operator== (const GLMTexSamplingParams& rhs ) const
  218. {
  219. return ( m_bits == rhs.m_bits ) && ( m_borderColor == rhs.m_borderColor ) && ( m_lodBias == rhs.m_lodBias );
  220. }
  221. FORCEINLINE void SetToDefaults()
  222. {
  223. m_bits = 0;
  224. m_borderColor = 0;
  225. m_lodBias = 0.0f;
  226. m_packed.m_addressU = D3DTADDRESS_WRAP;
  227. m_packed.m_addressV = D3DTADDRESS_WRAP;
  228. m_packed.m_addressW = D3DTADDRESS_WRAP;
  229. m_packed.m_minFilter = D3DTEXF_POINT;
  230. m_packed.m_magFilter = D3DTEXF_POINT;
  231. m_packed.m_mipFilter = D3DTEXF_NONE;
  232. m_packed.m_maxAniso = 1;
  233. m_packed.m_compareMode = 0;
  234. m_packed.m_isValid = true;
  235. }
  236. #ifndef OSX
  237. FORCEINLINE void SetToSamplerObject( GLuint nSamplerObject ) const
  238. {
  239. static const GLenum dxtogl_addressMode[] = { GL_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, (GLenum)-1 };
  240. static const GLenum dxtogl_magFilter[4] = { GL_NEAREST, GL_NEAREST, GL_LINEAR, GL_LINEAR };
  241. static const GLenum dxtogl_minFilter[4][4] = // indexed by _D3DTEXTUREFILTERTYPE on both axes: [row is min filter][col is mip filter].
  242. {
  243. /* min = D3DTEXF_NONE */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 }, // D3DTEXF_NONE we just treat like POINT
  244. /* min = D3DTEXF_POINT */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 },
  245. /* min = D3DTEXF_LINEAR */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 },
  246. /* min = D3DTEXF_ANISOTROPIC */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 }, // no diff from prior row, set maxAniso to effect the sampling
  247. };
  248. gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_WRAP_S, dxtogl_addressMode[m_packed.m_addressU] );
  249. gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_WRAP_T, dxtogl_addressMode[m_packed.m_addressV] );
  250. gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_WRAP_R, dxtogl_addressMode[m_packed.m_addressW] );
  251. gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_MIN_FILTER, dxtogl_minFilter[m_packed.m_minFilter][m_packed.m_mipFilter] );
  252. gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_MAG_FILTER, dxtogl_magFilter[m_packed.m_magFilter] );
  253. gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_MAX_ANISOTROPY_EXT, m_packed.m_maxAniso );
  254. float flBorderColor[4] = { 0, 0, 0, 0 };
  255. if ( m_borderColor )
  256. {
  257. flBorderColor[0] = ((m_borderColor >> 16) & 0xFF) * (1.0f/255.0f); //R
  258. flBorderColor[1] = ((m_borderColor >> 8) & 0xFF) * (1.0f/255.0f); //G
  259. flBorderColor[2] = ((m_borderColor ) & 0xFF) * (1.0f/255.0f); //B
  260. flBorderColor[3] = ((m_borderColor >> 24) & 0xFF) * (1.0f/255.0f); //A
  261. }
  262. gGL->glSamplerParameterfv( nSamplerObject, GL_TEXTURE_BORDER_COLOR, flBorderColor ); // <-- this crashes ATI's driver, remark it out
  263. gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_MIN_LOD, m_packed.m_minLOD );
  264. gGL->glSamplerParameterfv( nSamplerObject, GL_TEXTURE_LOD_BIAS, &m_lodBias );
  265. gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_COMPARE_MODE_ARB, m_packed.m_compareMode ? GL_COMPARE_R_TO_TEXTURE_ARB : GL_NONE );
  266. gGL->glSamplerParameterf( nSamplerObject, GL_TEXTURE_LOD_BIAS, m_lodBias );
  267. if ( m_packed.m_compareMode )
  268. {
  269. gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL );
  270. }
  271. if ( gGL->m_bHave_GL_EXT_texture_sRGB_decode )
  272. {
  273. gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_SRGB_DECODE_EXT, m_packed.m_srgb ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT );
  274. }
  275. }
  276. #endif // !OSX
  277. inline void DeltaSetToTarget( GLenum target, const GLMTexSamplingParams &curState )
  278. {
  279. static const GLenum dxtogl_addressMode[] = { GL_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, (GLenum)-1 };
  280. static const GLenum dxtogl_magFilter[4] = { GL_NEAREST, GL_NEAREST, GL_LINEAR, GL_LINEAR };
  281. static const GLenum dxtogl_minFilter[4][4] = // indexed by _D3DTEXTUREFILTERTYPE on both axes: [row is min filter][col is mip filter].
  282. {
  283. /* min = D3DTEXF_NONE */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 }, // D3DTEXF_NONE we just treat like POINT
  284. /* min = D3DTEXF_POINT */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 },
  285. /* min = D3DTEXF_LINEAR */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 },
  286. /* min = D3DTEXF_ANISOTROPIC */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 }, // no diff from prior row, set maxAniso to effect the sampling
  287. };
  288. if ( m_packed.m_addressU != curState.m_packed.m_addressU )
  289. {
  290. gGL->glTexParameteri( target, GL_TEXTURE_WRAP_S, dxtogl_addressMode[m_packed.m_addressU] );
  291. }
  292. if ( m_packed.m_addressV != curState.m_packed.m_addressV )
  293. {
  294. gGL->glTexParameteri( target, GL_TEXTURE_WRAP_T, dxtogl_addressMode[m_packed.m_addressV] );
  295. }
  296. if ( m_packed.m_addressW != curState.m_packed.m_addressW )
  297. {
  298. gGL->glTexParameteri( target, GL_TEXTURE_WRAP_R, dxtogl_addressMode[m_packed.m_addressW] );
  299. }
  300. if ( ( m_packed.m_minFilter != curState.m_packed.m_minFilter ) ||
  301. ( m_packed.m_magFilter != curState.m_packed.m_magFilter ) ||
  302. ( m_packed.m_mipFilter != curState.m_packed.m_mipFilter ) ||
  303. ( m_packed.m_maxAniso != curState.m_packed.m_maxAniso ) )
  304. {
  305. gGL->glTexParameteri( target, GL_TEXTURE_MIN_FILTER, dxtogl_minFilter[m_packed.m_minFilter][m_packed.m_mipFilter] );
  306. gGL->glTexParameteri( target, GL_TEXTURE_MAG_FILTER, dxtogl_magFilter[m_packed.m_magFilter] );
  307. gGL->glTexParameteri( target, GL_TEXTURE_MAX_ANISOTROPY_EXT, m_packed.m_maxAniso );
  308. }
  309. if ( m_borderColor != curState.m_borderColor )
  310. {
  311. float flBorderColor[4] = { 0, 0, 0, 0 };
  312. if ( m_borderColor )
  313. {
  314. flBorderColor[0] = ((m_borderColor >> 16) & 0xFF) * (1.0f/255.0f); //R
  315. flBorderColor[1] = ((m_borderColor >> 8) & 0xFF) * (1.0f/255.0f); //G
  316. flBorderColor[2] = ((m_borderColor ) & 0xFF) * (1.0f/255.0f); //B
  317. flBorderColor[3] = ((m_borderColor >> 24) & 0xFF) * (1.0f/255.0f); //A
  318. }
  319. gGL->glTexParameterfv( target, GL_TEXTURE_BORDER_COLOR, flBorderColor ); // <-- this crashes ATI's driver, remark it out
  320. }
  321. if ( m_packed.m_minLOD != curState.m_packed.m_minLOD )
  322. {
  323. gGL->glTexParameteri( target, GL_TEXTURE_MIN_LOD, m_packed.m_minLOD );
  324. }
  325. if ( m_lodBias != curState.m_lodBias )
  326. {
  327. // Could use TexParameterf instead, but we don't currently grab it. This works fine, too.
  328. gGL->glTexParameterfv( target, GL_TEXTURE_LOD_BIAS, &m_lodBias );
  329. }
  330. if ( m_packed.m_compareMode != curState.m_packed.m_compareMode )
  331. {
  332. gGL->glTexParameteri( target, GL_TEXTURE_COMPARE_MODE_ARB, m_packed.m_compareMode ? GL_COMPARE_R_TO_TEXTURE_ARB : GL_NONE );
  333. if ( m_packed.m_compareMode )
  334. {
  335. gGL->glTexParameteri( target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL );
  336. }
  337. }
  338. if ( ( gGL->m_bHave_GL_EXT_texture_sRGB_decode ) && ( m_packed.m_srgb != curState.m_packed.m_srgb ) )
  339. {
  340. gGL->glTexParameteri( target, GL_TEXTURE_SRGB_DECODE_EXT, m_packed.m_srgb ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT );
  341. }
  342. }
  343. inline void SetToTarget( GLenum target )
  344. {
  345. static const GLenum dxtogl_addressMode[] = { GL_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, (GLenum)-1 };
  346. static const GLenum dxtogl_magFilter[4] = { GL_NEAREST, GL_NEAREST, GL_LINEAR, GL_LINEAR };
  347. static const GLenum dxtogl_minFilter[4][4] = // indexed by _D3DTEXTUREFILTERTYPE on both axes: [row is min filter][col is mip filter].
  348. {
  349. /* min = D3DTEXF_NONE */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 }, // D3DTEXF_NONE we just treat like POINT
  350. /* min = D3DTEXF_POINT */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 },
  351. /* min = D3DTEXF_LINEAR */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 },
  352. /* min = D3DTEXF_ANISOTROPIC */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 }, // no diff from prior row, set maxAniso to effect the sampling
  353. };
  354. gGL->glTexParameteri( target, GL_TEXTURE_WRAP_S, dxtogl_addressMode[m_packed.m_addressU] );
  355. gGL->glTexParameteri( target, GL_TEXTURE_WRAP_T, dxtogl_addressMode[m_packed.m_addressV] );
  356. gGL->glTexParameteri( target, GL_TEXTURE_WRAP_R, dxtogl_addressMode[m_packed.m_addressW] );
  357. gGL->glTexParameteri( target, GL_TEXTURE_MIN_FILTER, dxtogl_minFilter[m_packed.m_minFilter][m_packed.m_mipFilter] );
  358. gGL->glTexParameteri( target, GL_TEXTURE_MAG_FILTER, dxtogl_magFilter[m_packed.m_magFilter] );
  359. gGL->glTexParameteri( target, GL_TEXTURE_MAX_ANISOTROPY_EXT, m_packed.m_maxAniso );
  360. float flBorderColor[4] = { 0, 0, 0, 0 };
  361. if ( m_borderColor )
  362. {
  363. flBorderColor[0] = ((m_borderColor >> 16) & 0xFF) * (1.0f/255.0f); //R
  364. flBorderColor[1] = ((m_borderColor >> 8) & 0xFF) * (1.0f/255.0f); //G
  365. flBorderColor[2] = ((m_borderColor ) & 0xFF) * (1.0f/255.0f); //B
  366. flBorderColor[3] = ((m_borderColor >> 24) & 0xFF) * (1.0f/255.0f); //A
  367. }
  368. gGL->glTexParameterfv( target, GL_TEXTURE_BORDER_COLOR, flBorderColor ); // <-- this crashes ATI's driver, remark it out
  369. gGL->glTexParameteri( target, GL_TEXTURE_MIN_LOD, m_packed.m_minLOD );
  370. gGL->glTexParameterfv( target, GL_TEXTURE_LOD_BIAS, &m_lodBias );
  371. gGL->glTexParameteri( target, GL_TEXTURE_COMPARE_MODE_ARB, m_packed.m_compareMode ? GL_COMPARE_R_TO_TEXTURE_ARB : GL_NONE );
  372. if ( m_packed.m_compareMode )
  373. {
  374. gGL->glTexParameteri( target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL );
  375. }
  376. if ( gGL->m_bHave_GL_EXT_texture_sRGB_decode )
  377. {
  378. gGL->glTexParameteri( target, GL_TEXTURE_SRGB_DECODE_EXT, m_packed.m_srgb ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT );
  379. }
  380. }
  381. };
  382. //===============================================================================
  383. class CGLMTex
  384. {
  385. public:
  386. void Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut, int *zStrideOut );
  387. void Unlock( GLMTexLockParams *params );
  388. GLuint GetTexName() { return m_texName; }
  389. protected:
  390. friend class GLMContext; // only GLMContext can make CGLMTex objects
  391. friend class GLMTester;
  392. friend class CGLMFBO;
  393. friend struct IDirect3DDevice9;
  394. friend struct IDirect3DBaseTexture9;
  395. friend struct IDirect3DTexture9;
  396. friend struct IDirect3DSurface9;
  397. friend struct IDirect3DCubeTexture9;
  398. friend struct IDirect3DVolumeTexture9;
  399. CGLMTex( GLMContext *ctx, GLMTexLayout *layout, uint levels, const char *debugLabel = NULL );
  400. ~CGLMTex( );
  401. int CalcSliceIndex( int face, int mip );
  402. void CalcTexelDataOffsetAndStrides( int sliceIndex, int x, int y, int z, int *offsetOut, int *yStrideOut, int *zStrideOut );
  403. void ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice=true );
  404. void WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice=true, bool noDataWrite=false );
  405. // last param lets us send NULL data ptr (only legal with uncompressed formats, beware)
  406. // this helps out ResetSRGB.
  407. #if defined( OSX )
  408. void HandleSRGBMismatch( bool srgb, int &srgbFlipCount );
  409. void ResetSRGB( bool srgb, bool noDataWrite );
  410. // re-specify texture format to match desired sRGB form
  411. // noWrite means send NULL for texel source addresses instead of actual data - ideal for RT's
  412. #endif
  413. bool IsRBODirty() const;
  414. void ForceRBONonDirty();
  415. void ForceRBODirty();
  416. // re-specify texture format to match desired sRGB form
  417. // noWrite means send NULL for texel source addresses instead of actual data - ideal for RT's
  418. GLuint m_texName; // name of this texture in the context
  419. GLenum m_texGLTarget;
  420. uint m_nSamplerType; // SAMPLER_2D, etc.
  421. GLMTexSamplingParams m_SamplingParams;
  422. GLMTexLayout *m_layout; // layout of texture (shared across all tex with same layout)
  423. uint m_nLastResolvedBatchCounter;
  424. int m_minActiveMip;//index of lowest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL.
  425. int m_maxActiveMip;//index of highest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL.
  426. GLMContext *m_ctx; // link back to parent context
  427. CGLMFBO *m_pBlitSrcFBO;
  428. CGLMFBO *m_pBlitDstFBO;
  429. GLuint m_rboName; // name of MSAA RBO backing the tex if MSAA enabled (or zero)
  430. int m_rtAttachCount; // how many RT's have this texture attached somewhere
  431. char *m_backing; // backing storage if available
  432. int m_lockCount; // lock reqs are stored in the GLMContext for tracking
  433. CUtlVector<unsigned char> m_sliceFlags;
  434. char *m_debugLabel; // strdup() of debugLabel passed in, or NULL
  435. bool m_texClientStorage; // was CS selected for texture
  436. bool m_texPreloaded; // has it been kicked into VRAM with GLMContext::PreloadTex yet
  437. int m_srgbFlipCount;
  438. #if GLMDEBUG
  439. CGLMTex *m_pPrevTex;
  440. CGLMTex *m_pNextTex;
  441. #endif
  442. };
  443. #endif