PageRenderTime 51ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/Sources/Engine/Graphics/Gfx_OpenGL.cpp

https://gitlab.com/dahbearz/Serious-Engine
C++ | 931 lines | 635 code | 113 blank | 183 comment | 132 complexity | 5bed6f0993d0e82b84c14d523a64d54f MD5 | raw file
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. #include "stdh.h"
  13. #include <Engine/Graphics/GfxLibrary.h>
  14. #include <Engine/Base/Translation.h>
  15. #include <Engine/Base/ErrorReporting.h>
  16. #include <Engine/Base/Memory.h>
  17. #include <Engine/Base/Console.h>
  18. #include <Engine/Graphics/ViewPort.h>
  19. #include <Engine/Graphics/MultiMonitor.h>
  20. #include <Engine/Templates/DynamicContainer.cpp>
  21. #include <Engine/Templates/Stock_CTextureData.h>
  22. #include <Engine/Base/ListIterator.inl>
  23. extern INDEX ogl_iTBufferEffect;
  24. extern INDEX ogl_iTBufferSamples;
  25. // fog/haze textures
  26. extern ULONG _fog_ulTexture;
  27. extern ULONG _haze_ulTexture;
  28. // change control
  29. extern INDEX GFX_ctVertices;
  30. // attributes for t-buffer
  31. int aiAttribList[] = {
  32. WGL_DRAW_TO_WINDOW_EXT, TRUE,
  33. WGL_SUPPORT_OPENGL_EXT, TRUE,
  34. WGL_DOUBLE_BUFFER_EXT, TRUE,
  35. WGL_PIXEL_TYPE_EXT, WGL_TYPE_RGBA_EXT,
  36. WGL_COLOR_BITS_EXT, 16,
  37. WGL_DEPTH_BITS_EXT, 16,
  38. WGL_SAMPLE_BUFFERS_3DFX, 1,
  39. WGL_SAMPLES_3DFX, 4,
  40. 0, 0
  41. };
  42. int *piAttribList = aiAttribList;
  43. // engine's internal opengl state variables
  44. extern BOOL GFX_bDepthTest;
  45. extern BOOL GFX_bDepthWrite;
  46. extern BOOL GFX_bAlphaTest;
  47. extern BOOL GFX_bBlending;
  48. extern BOOL GFX_bDithering;
  49. extern BOOL GFX_bClipping;
  50. extern BOOL GFX_bClipPlane;
  51. extern BOOL GFX_bColorArray;
  52. extern BOOL GFX_bFrontFace;
  53. extern BOOL GFX_bTruform;
  54. extern INDEX GFX_iActiveTexUnit;
  55. extern FLOAT GFX_fMinDepthRange;
  56. extern FLOAT GFX_fMaxDepthRange;
  57. extern GfxBlend GFX_eBlendSrc;
  58. extern GfxBlend GFX_eBlendDst;
  59. extern GfxComp GFX_eDepthFunc;
  60. extern GfxFace GFX_eCullFace;
  61. extern INDEX GFX_iTexModulation[GFX_MAXTEXUNITS];
  62. extern BOOL glbUsingVARs = FALSE; // vertex_array_range
  63. // define gl function pointers
  64. #define DLLFUNCTION(dll, output, name, inputs, params, required) \
  65. output (__stdcall *p##name) inputs = NULL;
  66. #include "gl_functions.h"
  67. #undef DLLFUNCTION
  68. // extensions
  69. void (__stdcall *pglLockArraysEXT)(GLint first, GLsizei count) = NULL;
  70. void (__stdcall *pglUnlockArraysEXT)(void) = NULL;
  71. GLboolean (__stdcall *pwglSwapIntervalEXT)(GLint interval) = NULL;
  72. GLint (__stdcall *pwglGetSwapIntervalEXT)(void) = NULL;
  73. void (__stdcall *pglActiveTextureARB)(GLenum texunit) = NULL;
  74. void (__stdcall *pglClientActiveTextureARB)(GLenum texunit) = NULL;
  75. // t-buffer support
  76. char *(__stdcall *pwglGetExtensionsStringARB)(HDC hdc);
  77. BOOL (__stdcall *pwglChoosePixelFormatARB)(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
  78. BOOL (__stdcall *pwglGetPixelFormatAttribivARB)(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues);
  79. void (__stdcall *pglTBufferMask3DFX)(GLuint mask);
  80. // NV occlusion query
  81. void (__stdcall *pglGenOcclusionQueriesNV)( GLsizei n, GLuint *ids);
  82. void (__stdcall *pglDeleteOcclusionQueriesNV)( GLsizei n, const GLuint *ids);
  83. void (__stdcall *pglBeginOcclusionQueryNV)( GLuint id);
  84. void (__stdcall *pglEndOcclusionQueryNV)(void);
  85. void (__stdcall *pglGetOcclusionQueryivNV)( GLuint id, GLenum pname, GLint *params);
  86. void (__stdcall *pglGetOcclusionQueryuivNV)( GLuint id, GLenum pname, GLuint *params);
  87. GLboolean (__stdcall *pglIsOcclusionQueryNV)( GLuint id);
  88. // ATI GL_ATI_pn_triangles
  89. void (__stdcall *pglPNTrianglesiATI)( GLenum pname, GLint param);
  90. void (__stdcall *pglPNTrianglesfATI)( GLenum pname, GLfloat param);
  91. void WIN_CheckError(BOOL bRes, const char *strDescription)
  92. {
  93. if( bRes) return;
  94. DWORD dwWindowsErrorCode = GetLastError();
  95. if( dwWindowsErrorCode==ERROR_SUCCESS) return; // ignore stupid 'successful' error
  96. WarningMessage("%s: %s", strDescription, GetWindowsError(dwWindowsErrorCode));
  97. }
  98. static void FailFunction_t(const char *strName) {
  99. ThrowF_t(TRANS("Required function %s not found."), strName);
  100. }
  101. static void OGL_SetFunctionPointers_t(HINSTANCE hiOGL)
  102. {
  103. const char *strName;
  104. // get gl function pointers
  105. #define DLLFUNCTION(dll, output, name, inputs, params, required) \
  106. strName = #name; \
  107. p##name = (output (__stdcall*) inputs) GetProcAddress( hi##dll, strName); \
  108. if( required && p##name == NULL) FailFunction_t(strName);
  109. #include "gl_functions.h"
  110. #undef DLLFUNCTION
  111. }
  112. static void OGL_ClearFunctionPointers(void)
  113. {
  114. // clear gl function pointers
  115. #define DLLFUNCTION(dll, output, name, inputs, params, required) p##name = NULL;
  116. #include "gl_functions.h"
  117. #undef DLLFUNCTION
  118. }
  119. #define BACKOFF pwglMakeCurrent( NULL, NULL); \
  120. pwglDeleteContext( hglrc); \
  121. ReleaseDC( dummyhwnd, hdc); \
  122. DestroyWindow( dummyhwnd); \
  123. UnregisterClassA( classname, hInstance);
  124. // helper for choosing t-buffer's pixel format
  125. static BOOL _TBCapability = FALSE;
  126. static INDEX ChoosePixelFormatTB( HDC hdc, const PIXELFORMATDESCRIPTOR *ppfd,
  127. PIX pixResWidth, PIX pixResHeight)
  128. {
  129. _TBCapability = FALSE;
  130. char *extensions = NULL;
  131. char *wglextensions = NULL;
  132. HGLRC hglrc;
  133. HWND dummyhwnd;
  134. WNDCLASSA cls;
  135. HINSTANCE hInstance = GetModuleHandle(NULL);
  136. LPCSTR classname = "dummyOGLwin";
  137. cls.style = CS_OWNDC;
  138. cls.lpfnWndProc = DefWindowProc;
  139. cls.cbClsExtra = 0;
  140. cls.cbWndExtra = 0;
  141. cls.hInstance = hInstance;
  142. cls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  143. cls.hCursor = LoadCursor(NULL, IDC_WAIT);
  144. cls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  145. cls.lpszMenuName = NULL;
  146. cls.lpszClassName = classname;
  147. // didn't manage to register class?
  148. if( !RegisterClassA(&cls)) return 0;
  149. // create window fullscreen
  150. //CPrintF( " Dummy window: %d x %d\n", pixResWidth, pixResHeight);
  151. dummyhwnd = CreateWindowExA( WS_EX_TOPMOST, classname, "Dummy OGL window",
  152. WS_POPUP|WS_VISIBLE, 0, 0, pixResWidth, pixResHeight,
  153. NULL, NULL, hInstance, NULL);
  154. // didn't make it?
  155. if( dummyhwnd == NULL) {
  156. UnregisterClassA( classname, hInstance);
  157. return 0;
  158. }
  159. //CPrintF( " Dummy passed...\n");
  160. hdc = GetDC(dummyhwnd);
  161. // try to choose pixel format
  162. int iPixelFormat = pwglChoosePixelFormat( hdc, ppfd);
  163. if( !iPixelFormat) {
  164. ReleaseDC( dummyhwnd, hdc);
  165. DestroyWindow(dummyhwnd);
  166. UnregisterClassA( classname, hInstance);
  167. return 0;
  168. }
  169. //CPrintF( " Choose pixel format passed...\n");
  170. // try to set pixel format
  171. if( !pwglSetPixelFormat( hdc, iPixelFormat, ppfd)) {
  172. ReleaseDC( dummyhwnd, hdc);
  173. DestroyWindow(dummyhwnd);
  174. UnregisterClassA( classname, hInstance);
  175. return 0;
  176. }
  177. //CPrintF( " Set pixel format passed...\n");
  178. // create context using the default accelerated pixelformat that was passed
  179. hglrc = pwglCreateContext(hdc);
  180. pwglMakeCurrent( hdc, hglrc);
  181. // update the value list with information passed from the ppfd.
  182. aiAttribList[ 9] = ppfd->cColorBits;
  183. aiAttribList[11] = ppfd->cDepthBits;
  184. aiAttribList[15] = _pGfx->go_ctSampleBuffers;
  185. // get the extension list.
  186. extensions = (char*)pglGetString(GL_EXTENSIONS);
  187. // get the wgl extension list.
  188. if( strstr((const char*)extensions, "WGL_EXT_extensions_string ") != NULL)
  189. { // windows extension string supported
  190. pwglGetExtensionsStringARB = (char* (__stdcall*)(HDC))pwglGetProcAddress( "wglGetExtensionsStringARB");
  191. if( pwglGetExtensionsStringARB == NULL) {
  192. BACKOFF
  193. return 0;
  194. }
  195. //CPrintF( " WGL extension string passed...\n");
  196. // get WGL extension string
  197. wglextensions = (char*)pwglGetExtensionsStringARB(hdc);
  198. }
  199. else {
  200. BACKOFF
  201. return 0;
  202. }
  203. // check for the pixel format and multisample extension strings
  204. if( (strstr((const char*)wglextensions, "WGL_ARB_pixel_format ") != NULL) &&
  205. (strstr((const char*)extensions, "GL_3DFX_multisample ") != NULL)) {
  206. // 3dfx extensions present
  207. _TBCapability = TRUE;
  208. pwglChoosePixelFormatARB = (BOOL (__stdcall*)(HDC,const int*,const FLOAT*,UINT,int*,UINT*))pwglGetProcAddress( "wglChoosePixelFormatARB");
  209. pwglGetPixelFormatAttribivARB = (BOOL (__stdcall*)(HDC,int,int,UINT,int*,int*) )pwglGetProcAddress( "wglGetPixelFormatAttribivARB");
  210. pglTBufferMask3DFX = (void (__stdcall*)(GLuint))pwglGetProcAddress("glTBufferMask3DFX");
  211. if( pwglChoosePixelFormatARB==NULL && pglTBufferMask3DFX==NULL) {
  212. BACKOFF
  213. return 0;
  214. }
  215. //CPrintF( " WGL choose pixel format present...\n");
  216. int iAttribListNum = {WGL_NUMBER_PIXEL_FORMATS_EXT};
  217. int iMaxFormats = 1; // default number to return
  218. if( pwglGetPixelFormatAttribivARB!=NULL) {
  219. // get total number of formats supported.
  220. pwglGetPixelFormatAttribivARB( hdc, NULL, NULL, 1, &iAttribListNum, &iMaxFormats);
  221. //CPrintF( "Max formats: %d\n", iMaxFormats);
  222. }
  223. UINT uiNumFormats;
  224. int *piFormats = (int*)AllocMemory( sizeof(UINT) *iMaxFormats);
  225. // try to get all formats that fit the pixel format criteria
  226. if( !pwglChoosePixelFormatARB( hdc, piAttribList, NULL, iMaxFormats, piFormats, &uiNumFormats)) {
  227. FreeMemory(piFormats);
  228. BACKOFF
  229. return 0;
  230. }
  231. //CPrintF( " WGL choose pixel format passed...\n");
  232. // return the first match for now
  233. iPixelFormat = 0;
  234. if( uiNumFormats>0) {
  235. iPixelFormat = piFormats[0];
  236. //CPrintF( "Num formats: %d\n", uiNumFormats);
  237. //CPrintF( "First format: %d\n", iPixelFormat);
  238. }
  239. FreeMemory(piFormats);
  240. }
  241. else
  242. { // wglChoosePixelFormatARB extension does not exist :(
  243. iPixelFormat = 0;
  244. }
  245. BACKOFF
  246. return iPixelFormat;
  247. }
  248. // prepares pixel format for OpenGL context
  249. BOOL CGfxLibrary::SetupPixelFormat_OGL( HDC hdc, BOOL bReport/*=FALSE*/)
  250. {
  251. int iPixelFormat = 0;
  252. const PIX pixResWidth = gl_dmCurrentDisplayMode.dm_pixSizeI;
  253. const PIX pixResHeight = gl_dmCurrentDisplayMode.dm_pixSizeJ;
  254. const DisplayDepth dd = gl_dmCurrentDisplayMode.dm_ddDepth;
  255. PIXELFORMATDESCRIPTOR pfd;
  256. memset( &pfd, 0, sizeof(pfd));
  257. pfd.nSize = sizeof(pfd);
  258. pfd.nVersion = 1;
  259. pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
  260. pfd.iPixelType = PFD_TYPE_RGBA;
  261. // clamp depth/stencil values
  262. extern INDEX gap_iDepthBits;
  263. extern INDEX gap_iStencilBits;
  264. if( gap_iDepthBits <12) gap_iDepthBits = 0;
  265. else if( gap_iDepthBits <22) gap_iDepthBits = 16;
  266. else if( gap_iDepthBits <28) gap_iDepthBits = 24;
  267. else gap_iDepthBits = 32;
  268. if( gap_iStencilBits<3) gap_iStencilBits = 0;
  269. else if( gap_iStencilBits<7) gap_iStencilBits = 4;
  270. else gap_iStencilBits = 8;
  271. // set color/depth buffer values
  272. pfd.cColorBits = (dd!=DD_16BIT) ? 32 : 16;
  273. pfd.cDepthBits = gap_iDepthBits;
  274. pfd.cStencilBits = gap_iStencilBits;
  275. // must be required and works only in full screen via GDI functions
  276. ogl_iTBufferEffect = Clamp( ogl_iTBufferEffect, 0L, 2L);
  277. if( ogl_iTBufferEffect>0 && pixResWidth>0 && pixResHeight>0)
  278. { // lets T-buffer ... :)
  279. //CPrintF( "TBuffer init...\n");
  280. ogl_iTBufferSamples = (1L) << FastLog2(ogl_iTBufferSamples);
  281. if( ogl_iTBufferSamples<2) ogl_iTBufferSamples = 4;
  282. go_ctSampleBuffers = ogl_iTBufferSamples;
  283. go_iCurrentWriteBuffer = 0;
  284. iPixelFormat = ChoosePixelFormatTB( hdc, &pfd, pixResWidth, pixResHeight);
  285. // need to reset the desktop resolution because CPFTB() resets it
  286. BOOL bSuccess = CDS_SetMode( pixResWidth, pixResHeight, dd);
  287. if( !bSuccess) iPixelFormat = 0;
  288. // check T-buffer support
  289. if( _TBCapability) pglGetIntegerv( GL_SAMPLES_3DFX, (GLint*)&go_ctSampleBuffers);
  290. if( !iPixelFormat) { ogl_iTBufferEffect=0; CPrintF( TRANS("TBuffer initialization failed.\n")); }
  291. else CPrintF( TRANS("TBuffer initialization passed (%d buffers in use).\n"), go_ctSampleBuffers);
  292. }
  293. // if T-buffer didn't make it, let's try thru regular path
  294. if( !iPixelFormat) {
  295. go_ctSampleBuffers = 0;
  296. go_iCurrentWriteBuffer = 0;
  297. iPixelFormat = pwglChoosePixelFormat( hdc, &pfd);
  298. }
  299. if( !iPixelFormat) {
  300. WIN_CHECKERROR( 0, "ChoosePixelFormat");
  301. return FALSE;
  302. }
  303. if( !pwglSetPixelFormat( hdc, iPixelFormat, &pfd)) {
  304. WIN_CHECKERROR( 0, "SetPixelFormat");
  305. return FALSE;
  306. }
  307. // test acceleration
  308. memset( &pfd, 0, sizeof(pfd));
  309. if( !pwglDescribePixelFormat( hdc, iPixelFormat, sizeof(pfd), &pfd)) return FALSE;
  310. BOOL bGenericFormat = pfd.dwFlags & PFD_GENERIC_FORMAT;
  311. BOOL bGenericAccelerated = pfd.dwFlags & PFD_GENERIC_ACCELERATED;
  312. BOOL bHasAcceleration = (bGenericFormat && bGenericAccelerated) || // MCD
  313. (!bGenericFormat && !bGenericAccelerated); // ICD
  314. if( bHasAcceleration) gl_ulFlags |= GLF_HASACCELERATION;
  315. else gl_ulFlags &= ~GLF_HASACCELERATION;
  316. // done if report pixel format info isn't required
  317. if( !bReport) return TRUE;
  318. // prepare pixel type description
  319. CTString strPixelType;
  320. if( pfd.iPixelType==PFD_TYPE_RGBA) strPixelType = "TYPE_RGBA";
  321. else if( pfd.iPixelType&PFD_TYPE_COLORINDEX) strPixelType = "TYPE_COLORINDEX";
  322. else strPixelType = "unknown";
  323. // prepare flags description
  324. CTString strFlags = "";
  325. if( pfd.dwFlags&PFD_DRAW_TO_WINDOW) strFlags += "DRAW_TO_WINDOW ";
  326. if( pfd.dwFlags&PFD_DRAW_TO_BITMAP) strFlags += "DRAW_TO_BITMAP ";
  327. if( pfd.dwFlags&PFD_SUPPORT_GDI) strFlags += "SUPPORT_GDI ";
  328. if( pfd.dwFlags&PFD_SUPPORT_OPENGL) strFlags += "SUPPORT_OPENGL ";
  329. if( pfd.dwFlags&PFD_GENERIC_ACCELERATED) strFlags += "GENERIC_ACCELERATED ";
  330. if( pfd.dwFlags&PFD_GENERIC_FORMAT) strFlags += "GENERIC_FORMAT ";
  331. if( pfd.dwFlags&PFD_NEED_PALETTE) strFlags += "NEED_PALETTE ";
  332. if( pfd.dwFlags&PFD_NEED_SYSTEM_PALETTE) strFlags += "NEED_SYSTEM_PALETTE ";
  333. if( pfd.dwFlags&PFD_DOUBLEBUFFER) strFlags += "DOUBLEBUFFER ";
  334. if( pfd.dwFlags&PFD_STEREO) strFlags += "STEREO ";
  335. if( pfd.dwFlags&PFD_SWAP_LAYER_BUFFERS) strFlags += "SWAP_LAYER_BUFFERS ";
  336. if( pfd.dwFlags&PFD_DEPTH_DONTCARE) strFlags += "DEPTH_DONTCARE ";
  337. if( pfd.dwFlags&PFD_DOUBLEBUFFER_DONTCARE) strFlags += "DOUBLEBUFFER_DONTCARE ";
  338. if( pfd.dwFlags&PFD_STEREO_DONTCARE) strFlags += "STEREO_DONTCARE ";
  339. if( pfd.dwFlags&PFD_SWAP_COPY) strFlags += "SWAP_COPY ";
  340. if( pfd.dwFlags&PFD_SWAP_EXCHANGE) strFlags += "SWAP_EXCHANGE ";
  341. if( strFlags=="") strFlags = "none";
  342. // output pixel format description to console (for debugging purposes)
  343. CPrintF( TRANS("\nPixel Format Description:\n"));
  344. CPrintF( TRANS(" Number: %d (%s)\n"), iPixelFormat, strPixelType);
  345. CPrintF( TRANS(" Flags: %s\n"), strFlags);
  346. CPrintF( TRANS(" Color bits: %d (%d:%d:%d:%d)\n"), pfd.cColorBits,
  347. pfd.cRedBits, pfd.cGreenBits, pfd.cBlueBits, pfd.cAlphaBits);
  348. CPrintF( TRANS(" Depth bits: %d (%d for stencil)\n"), pfd.cDepthBits, pfd.cStencilBits);
  349. gl_iCurrentDepth = pfd.cDepthBits; // keep depth bits
  350. // all done
  351. CPrintF( "\n");
  352. return TRUE;
  353. }
  354. // test if an extension exists
  355. static BOOL HasExtension( const char *strAllExtensions, const char *strExtension)
  356. {
  357. // find substring
  358. const char *strFound = strstr( strAllExtensions, strExtension);
  359. // no extension if not found
  360. if( strFound==NULL) return FALSE;
  361. INDEX iExtensionLen = strlen(strExtension);
  362. // if found substring is substring of some other extension
  363. if( strFound[iExtensionLen]!=' ' && strFound[iExtensionLen]!=0) {
  364. // continue searching after that char
  365. return HasExtension( strFound+iExtensionLen, strExtension);
  366. }
  367. // extension found
  368. return TRUE;
  369. }
  370. // add OpenGL extensions to engine
  371. void CGfxLibrary::AddExtension_OGL( ULONG ulFlag, const char *strName)
  372. {
  373. gl_ulFlags = (gl_ulFlags & ~ulFlag) | ulFlag;
  374. go_strSupportedExtensions += strName;
  375. go_strSupportedExtensions += " ";
  376. }
  377. // determine OpenGL extensions that engine supports
  378. void CGfxLibrary::TestExtension_OGL( ULONG ulFlag, const char *strName)
  379. {
  380. if( HasExtension( go_strExtensions, strName)) AddExtension_OGL( ulFlag, strName);
  381. }
  382. // creates OpenGL drawing context
  383. BOOL CGfxLibrary::CreateContext_OGL(HDC hdc)
  384. {
  385. if( !SetupPixelFormat_OGL( hdc, TRUE)) return FALSE;
  386. go_hglRC = pwglCreateContext(hdc);
  387. if( go_hglRC==NULL) {
  388. WIN_CHECKERROR(0, "CreateContext");
  389. return FALSE;
  390. }
  391. if( !pwglMakeCurrent(hdc, go_hglRC)) {
  392. // NOTE: This error is sometimes reported without a reason on 3dfx hardware
  393. // so we just have to ignore it.
  394. //WIN_CHECKERROR(0, "MakeCurrent after CreateContext");
  395. return FALSE;
  396. }
  397. return TRUE;
  398. }
  399. // prepares OpenGL drawing context
  400. void CGfxLibrary::InitContext_OGL(void)
  401. {
  402. // must have context
  403. ASSERT( gl_pvpActive!=NULL);
  404. // reset engine's internal OpenGL state variables
  405. extern BOOL GFX_abTexture[GFX_MAXTEXUNITS];
  406. for( INDEX iUnit=0; iUnit<GFX_MAXTEXUNITS; iUnit++) {
  407. GFX_abTexture[iUnit] = FALSE;
  408. GFX_iTexModulation[iUnit] = 1;
  409. }
  410. // set default texture unit and modulation mode
  411. GFX_iActiveTexUnit = 0;
  412. gl_ctMaxStreams = 16; // GL always has enough "streams" for multi-texturing
  413. // reset frustum/ortho stuff
  414. extern BOOL GFX_bViewMatrix;
  415. extern FLOAT GFX_fLastL, GFX_fLastR, GFX_fLastT, GFX_fLastB, GFX_fLastN, GFX_fLastF;
  416. GFX_fLastL = GFX_fLastR = GFX_fLastT = GFX_fLastB = GFX_fLastN = GFX_fLastF = 0;
  417. GFX_bViewMatrix = TRUE;
  418. glbUsingVARs = FALSE;
  419. GFX_bTruform = FALSE;
  420. GFX_bClipping = TRUE;
  421. pglEnable( GL_TEXTURE_2D); GFX_abTexture[0] = TRUE;
  422. pglEnable( GL_DITHER); GFX_bDithering = TRUE;
  423. pglDisable( GL_BLEND); GFX_bBlending = FALSE;
  424. pglDisable( GL_DEPTH_TEST); GFX_bDepthTest = FALSE;
  425. pglDisable( GL_ALPHA_TEST); GFX_bAlphaTest = FALSE;
  426. pglDisable( GL_CLIP_PLANE0); GFX_bClipPlane = FALSE;
  427. pglDisable( GL_CULL_FACE); GFX_eCullFace = GFX_NONE;
  428. pglFrontFace( GL_CCW); GFX_bFrontFace = TRUE;
  429. pglDepthMask( GL_FALSE); GFX_bDepthWrite = FALSE;
  430. pglDepthFunc( GL_LEQUAL); GFX_eDepthFunc = GFX_LESS_EQUAL;
  431. pglBlendFunc( GL_ONE, GL_ONE); GFX_eBlendSrc = GFX_eBlendDst = GFX_ONE;
  432. pglDepthRange( 0.0f, 1.0f); GFX_fMinDepthRange = 0.0f;
  433. GFX_fMaxDepthRange = 1.0f;
  434. // (re)set some OpenGL defaults
  435. gfxPolygonMode( GFX_FILL);
  436. pglShadeModel( GL_SMOOTH);
  437. pglEnable( GL_SCISSOR_TEST);
  438. pglDrawBuffer( GL_BACK);
  439. pglAlphaFunc( GL_GEQUAL, 0.5f);
  440. pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f);
  441. pglMatrixMode( GL_MODELVIEW);
  442. pglLoadIdentity();
  443. pglMatrixMode( GL_TEXTURE);
  444. pglLoadIdentity();
  445. // enable rendering only thru vertex arrays by default
  446. pglEnableClientState( GL_VERTEX_ARRAY);
  447. pglDisableClientState( GL_NORMAL_ARRAY);
  448. pglDisableClientState( GL_TEXTURE_COORD_ARRAY);
  449. pglDisableClientState( GL_COLOR_ARRAY);
  450. GFX_bColorArray = FALSE;
  451. // set single byte pixel alignment
  452. pglPixelStorei( GL_PACK_ALIGNMENT, 1);
  453. pglPixelStorei( GL_UNPACK_ALIGNMENT, 1);
  454. // TEST EXTENSIONS
  455. CDisplayAdapter &da = gl_gaAPI[GAT_OGL].ga_adaAdapter[gl_iCurrentAdapter];
  456. da.da_strVendor = (const char*)pglGetString(GL_VENDOR);
  457. da.da_strRenderer = (const char*)pglGetString(GL_RENDERER);
  458. da.da_strVersion = (const char*)pglGetString(GL_VERSION);
  459. go_strExtensions = (const char*)pglGetString(GL_EXTENSIONS);
  460. // report
  461. CPrintF( TRANS("\n* OpenGL context created: *----------------------------------\n"));
  462. CPrintF( " (%s, %s, %s)\n\n", da.da_strVendor, da.da_strRenderer, da.da_strVersion);
  463. // test for used extensions
  464. GLint gliRet;
  465. GLfloat glfRet;
  466. go_strSupportedExtensions = "";
  467. // check for WGL extensions, too
  468. go_strWinExtensions = "";
  469. pwglGetExtensionsStringARB = (char* (__stdcall*)(HDC))pwglGetProcAddress("wglGetExtensionsStringARB");
  470. if( pwglGetExtensionsStringARB != NULL) {
  471. AddExtension_OGL( NONE, "WGL_ARB_extensions_string"); // register
  472. CTempDC tdc(gl_pvpActive->vp_hWnd);
  473. go_strWinExtensions = (char*)pwglGetExtensionsStringARB(tdc.hdc);
  474. }
  475. // multitexture is supported only thru GL_EXT_texture_env_combine extension
  476. gl_ctTextureUnits = 1;
  477. gl_ctRealTextureUnits = 1;
  478. pglActiveTextureARB = NULL;
  479. pglClientActiveTextureARB = NULL;
  480. if( HasExtension( go_strExtensions, "GL_ARB_multitexture")) {
  481. pglGetIntegerv( GL_MAX_TEXTURE_UNITS_ARB, (int*)&gl_ctRealTextureUnits); // get number of texture units
  482. if( gl_ctRealTextureUnits>1 && HasExtension( go_strExtensions, "GL_EXT_texture_env_combine")) {
  483. AddExtension_OGL( NONE, "GL_ARB_multitexture");
  484. AddExtension_OGL( NONE, "GL_EXT_texture_env_combine");
  485. pglActiveTextureARB = (void (__stdcall*)(GLenum))pwglGetProcAddress( "glActiveTextureARB");
  486. pglClientActiveTextureARB = (void (__stdcall*)(GLenum))pwglGetProcAddress( "glClientActiveTextureARB");
  487. ASSERT( pglActiveTextureARB!=NULL && pglClientActiveTextureARB!=NULL);
  488. gl_ctTextureUnits = Min( GFX_MAXTEXUNITS, gl_ctRealTextureUnits);
  489. } else {
  490. CPrintF( TRANS(" GL_TEXTURE_ENV_COMBINE extension missing - multi-texturing cannot be used.\n"));
  491. }
  492. }
  493. // find all supported texture compression extensions
  494. TestExtension_OGL( GLF_EXTC_ARB, "GL_ARB_texture_compression");
  495. TestExtension_OGL( GLF_EXTC_S3TC, "GL_EXT_texture_compression_s3tc");
  496. TestExtension_OGL( GLF_EXTC_FXT1, "GL_3DFX_texture_compression_FXT1");
  497. TestExtension_OGL( GLF_EXTC_LEGACY, "GL_S3_s3tc");
  498. // mark if there is at least one extension present
  499. gl_ulFlags &= ~GLF_TEXTURECOMPRESSION;
  500. if( (gl_ulFlags&GLF_EXTC_ARB) || (gl_ulFlags&GLF_EXTC_FXT1)
  501. || (gl_ulFlags&GLF_EXTC_S3TC) || (gl_ulFlags&GLF_EXTC_LEGACY)) {
  502. gl_ulFlags |= GLF_TEXTURECOMPRESSION;
  503. }
  504. // determine max supported dimension of texture
  505. pglGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*)&gl_pixMaxTextureDimension);
  506. OGL_CHECKERROR;
  507. // determine support for texture LOD biasing
  508. gl_fMaxTextureLODBias = 0.0f;
  509. if( HasExtension( go_strExtensions, "GL_EXT_texture_lod_bias")) {
  510. AddExtension_OGL( NONE, "GL_EXT_texture_lod_bias"); // register
  511. // check max possible lod bias (absolute)
  512. pglGetFloatv( GL_MAX_TEXTURE_LOD_BIAS_EXT, &glfRet);
  513. GLenum gleError = pglGetError(); // just because of invalid extension implementations (S3)
  514. if( gleError || glfRet<0.1f || glfRet>4.0f) glfRet = 4.0f;
  515. gl_fMaxTextureLODBias = glfRet;
  516. OGL_CHECKERROR;
  517. }
  518. // determine support for anisotropic filtering
  519. gl_iMaxTextureAnisotropy = 1;
  520. if( HasExtension( go_strExtensions, "GL_EXT_texture_filter_anisotropic")) {
  521. AddExtension_OGL( NONE, "GL_EXT_texture_filter_anisotropic"); // register
  522. // keep max allowed anisotropy degree
  523. pglGetIntegerv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gliRet);
  524. gl_iMaxTextureAnisotropy = gliRet;
  525. OGL_CHECKERROR;
  526. }
  527. // check support for compiled vertex arrays
  528. pglLockArraysEXT = NULL;
  529. pglUnlockArraysEXT = NULL;
  530. if( HasExtension( go_strExtensions, "GL_EXT_compiled_vertex_array")) {
  531. AddExtension_OGL( GLF_EXT_COMPILEDVERTEXARRAY, "GL_EXT_compiled_vertex_array");
  532. pglLockArraysEXT = (void (__stdcall*)(GLint,GLsizei))pwglGetProcAddress( "glLockArraysEXT");
  533. pglUnlockArraysEXT = (void (__stdcall*)(void) )pwglGetProcAddress( "glUnlockArraysEXT");
  534. ASSERT( pglLockArraysEXT!=NULL && pglUnlockArraysEXT!=NULL);
  535. }
  536. // check support for swap interval
  537. pwglSwapIntervalEXT = NULL;
  538. pwglGetSwapIntervalEXT = NULL;
  539. if( HasExtension( go_strExtensions, "WGL_EXT_swap_control")) {
  540. AddExtension_OGL( GLF_VSYNC, "WGL_EXT_swap_control");
  541. pwglSwapIntervalEXT = (GLboolean (__stdcall*)(GLint))pwglGetProcAddress( "wglSwapIntervalEXT");
  542. pwglGetSwapIntervalEXT = (GLint (__stdcall*)(void) )pwglGetProcAddress( "wglGetSwapIntervalEXT");
  543. ASSERT( pwglSwapIntervalEXT!=NULL && pwglGetSwapIntervalEXT!=NULL);
  544. }
  545. // determine support for ATI Truform technology
  546. extern INDEX truform_iLevel;
  547. extern BOOL truform_bLinear;
  548. truform_iLevel = -1;
  549. truform_bLinear = FALSE;
  550. pglPNTrianglesiATI = NULL;
  551. pglPNTrianglesfATI = NULL;
  552. gl_iTessellationLevel = 0;
  553. gl_iMaxTessellationLevel = 0;
  554. if( HasExtension( go_strExtensions, "GL_ATI_pn_triangles")) {
  555. AddExtension_OGL( NONE, "GL_ATI_pn_triangles");
  556. pglPNTrianglesiATI = (void (__stdcall*)(GLenum,GLint ))pwglGetProcAddress( "glPNTrianglesiATI");
  557. pglPNTrianglesfATI = (void (__stdcall*)(GLenum,GLfloat))pwglGetProcAddress( "glPNTrianglesfATI");
  558. ASSERT( pglPNTrianglesiATI!=NULL && pglPNTrianglesfATI!=NULL);
  559. // check max possible tessellation
  560. pglGetIntegerv( GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI, &gliRet);
  561. gl_iMaxTessellationLevel = gliRet;
  562. OGL_CHECKERROR;
  563. }
  564. // if T-buffer is supported
  565. if( _TBCapability) {
  566. // add extension and disable t-buffer usage by default
  567. AddExtension_OGL( GLF_EXT_TBUFFER, "GL_3DFX_multisample");
  568. pglDisable( GL_MULTISAMPLE_3DFX);
  569. OGL_CHECKERROR;
  570. }
  571. // test for clamp to edge
  572. TestExtension_OGL( GLF_EXT_EDGECLAMP, "GL_EXT_texture_edge_clamp");
  573. // test for clip volume hint
  574. TestExtension_OGL( GLF_EXT_CLIPHINT, "GL_EXT_clip_volume_hint");
  575. /*
  576. // test for occlusion culling
  577. TestExtension_OGL( GLF_EXT_OCCLUSIONTEST, "GL_HP_occlusion_test");
  578. pglGenOcclusionQueriesNV = NULL; pglDeleteOcclusionQueriesNV = NULL;
  579. pglBeginOcclusionQueryNV = NULL; pglEndOcclusionQueryNV = NULL;
  580. pglGetOcclusionQueryivNV = NULL; pglGetOcclusionQueryuivNV = NULL;
  581. pglIsOcclusionQueryNV = NULL;
  582. if( HasExtension( go_strExtensions, "GL_NV_occlusion_query"))
  583. { // prepare extension's functions
  584. AddExtension_OGL( GLF_EXT_OCCLUSIONQUERY, "GL_NV_occlusion_query");
  585. pglGenOcclusionQueriesNV = (void (__stdcall*)(GLsizei, GLuint*))pwglGetProcAddress( "glGenOcclusionQueriesNV");
  586. pglDeleteOcclusionQueriesNV = (void (__stdcall*)(GLsizei, const GLuint*))pwglGetProcAddress( "glDeleteOcclusionQueriesNV");
  587. pglBeginOcclusionQueryNV = (void (__stdcall*)(GLuint))pwglGetProcAddress( "glBeginOcclusionQueryNV");
  588. pglEndOcclusionQueryNV = (void (__stdcall*)(void))pwglGetProcAddress( "glEndOcclusionQueryNV");
  589. pglGetOcclusionQueryivNV = (void (__stdcall*)(GLuint, GLenum, GLint*))pwglGetProcAddress( "glGetOcclusionQueryivNV");
  590. pglGetOcclusionQueryuivNV = (void (__stdcall*)(GLuint, GLenum, GLuint*))pwglGetProcAddress( "glGetOcclusionQueryuivNV");
  591. pglIsOcclusionQueryNV = (GLboolean (__stdcall*)(GLuint))pwglGetProcAddress( "glIsOcclusionQueryNV");
  592. ASSERT( pglGenOcclusionQueriesNV!=NULL && pglDeleteOcclusionQueriesNV!=NULL
  593. && pglBeginOcclusionQueryNV!=NULL && pglEndOcclusionQueryNV!=NULL
  594. && pglGetOcclusionQueryivNV!=NULL && pglGetOcclusionQueryuivNV!=NULL
  595. && pglIsOcclusionQueryNV!=NULL);
  596. }
  597. */
  598. // done with seeking for supported extensions
  599. if( go_strSupportedExtensions=="") go_strSupportedExtensions = "none";
  600. // allocate vertex buffers
  601. // eglAdjustVertexBuffers(ogl_iVertexBufferSize*1024);
  602. // OGL_CHECKERROR;
  603. // check if 32-bit textures are supported
  604. GLuint uiTmpTex;
  605. const ULONG ulTmpTex = 0xFFFFFFFF;
  606. pglGenTextures( 1, &uiTmpTex);
  607. pglBindTexture( GL_TEXTURE_2D, uiTmpTex);
  608. pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, 1,1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &ulTmpTex);
  609. OGL_CHECKERROR;
  610. gl_ulFlags &= ~GLF_32BITTEXTURES;
  611. pglGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE, &gliRet);
  612. if( gliRet==8) gl_ulFlags |= GLF_32BITTEXTURES;
  613. pglDeleteTextures( 1, &uiTmpTex);
  614. OGL_CHECKERROR;
  615. // setup fog and haze textures
  616. extern PIX _fog_pixSizeH;
  617. extern PIX _fog_pixSizeL;
  618. extern PIX _haze_pixSize;
  619. pglGenTextures( 1, (GLuint*)&_fog_ulTexture);
  620. pglGenTextures( 1, (GLuint*)&_haze_ulTexture);
  621. _fog_pixSizeH = 0;
  622. _fog_pixSizeL = 0;
  623. _haze_pixSize = 0;
  624. OGL_CHECKERROR;
  625. // prepare pattern texture
  626. extern CTexParams _tpPattern;
  627. extern ULONG _ulPatternTexture;
  628. extern ULONG _ulLastUploadedPattern;
  629. pglGenTextures( 1, (GLuint*)&_ulPatternTexture);
  630. _ulLastUploadedPattern = 0;
  631. _tpPattern.Clear();
  632. // reset texture filtering and array locking
  633. _tpGlobal[0].Clear();
  634. _tpGlobal[1].Clear();
  635. _tpGlobal[2].Clear();
  636. _tpGlobal[3].Clear();
  637. GFX_ctVertices = 0;
  638. gl_dwVertexShader = NONE;
  639. // set default texture filtering/biasing
  640. extern INDEX gap_iTextureFiltering;
  641. extern INDEX gap_iTextureAnisotropy;
  642. extern FLOAT gap_fTextureLODBias;
  643. gfxSetTextureFiltering( gap_iTextureFiltering, gap_iTextureAnisotropy);
  644. gfxSetTextureBiasing( gap_fTextureLODBias);
  645. // mark pretouching and probing
  646. extern BOOL _bNeedPretouch;
  647. _bNeedPretouch = TRUE;
  648. gl_bAllowProbing = FALSE;
  649. // update console system vars
  650. extern void UpdateGfxSysCVars(void);
  651. UpdateGfxSysCVars();
  652. // reload all loaded textures and eventually shadows
  653. extern INDEX shd_bCacheAll;
  654. extern void ReloadTextures(void);
  655. extern void CacheShadows(void);
  656. ReloadTextures();
  657. if( shd_bCacheAll) CacheShadows();
  658. }
  659. // initialize OpenGL driver
  660. BOOL CGfxLibrary::InitDriver_OGL( BOOL b3Dfx/*=FALSE*/)
  661. {
  662. ASSERT( gl_hiDriver==NONE);
  663. UINT iOldErrorMode = SetErrorMode( SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS);
  664. CTString strDriverFileName = b3Dfx ? "3DFXVGL.DLL" : "OPENGL32.DLL";
  665. try
  666. { // if driver doesn't exists on disk
  667. char strBuffer[_MAX_PATH+1];
  668. char *strDummy;
  669. int iRes = SearchPathA( NULL, strDriverFileName, NULL, _MAX_PATH, strBuffer, &strDummy);
  670. if( iRes==0) ThrowF_t(TRANS("OpenGL driver '%s' not present"), strDriverFileName);
  671. // load opengl library
  672. gl_hiDriver = ::LoadLibraryA( strDriverFileName);
  673. // if it cannot be loaded (although it is present on disk)
  674. if( gl_hiDriver==NONE) {
  675. // if it is 3dfx stand-alone driver
  676. if( b3Dfx) {
  677. // do a fatal error and inform user to deinstall it,
  678. // since this loading attempt probably messed up the entire system
  679. FatalError(TRANS( "3Dfx OpenGL driver '%s' is installed, but cannot be loaded!\n"
  680. "If you previously had a 3Dfx card and it was removed,\n"
  681. "please deinstall the driver and restart windows before\n"
  682. "continuing.\n"), strDriverFileName);
  683. } // fail!
  684. ThrowF_t(TRANS("Cannot load OpenGL driver '%s'"), strDriverFileName);
  685. }
  686. // prepare functions
  687. OGL_SetFunctionPointers_t(gl_hiDriver);
  688. }
  689. catch( char *strError)
  690. { // didn't make it :(
  691. if( gl_hiDriver!=NONE) FreeLibrary(gl_hiDriver);
  692. gl_hiDriver = NONE;
  693. CPrintF( TRANS("Error starting OpenGL: %s\n"), strError);
  694. SetErrorMode(iOldErrorMode);
  695. return FALSE;
  696. }
  697. // revert to old error mode
  698. SetErrorMode(iOldErrorMode);
  699. // if default driver
  700. if( !b3Dfx) {
  701. // use GDI functions
  702. pwglSwapBuffers = ::SwapBuffers;
  703. pwglSetPixelFormat = ::SetPixelFormat;
  704. pwglChoosePixelFormat = ::ChoosePixelFormat;
  705. // NOTE:
  706. // some ICD implementations are not infact in OPENGL32.DLL, but in some
  707. // other installed DLL, which is loaded when original OPENGL32.DLL from MS is
  708. // loaded. For those, we in fact load OPENGL32.DLL from MS, so we must _not_
  709. // call these functions directly, because they are in MS dll. We must call
  710. // functions from GDI, which in turn call either OPENGL32.DLL, _or_ the client driver,
  711. // as appropriate.
  712. }
  713. // done
  714. return TRUE;
  715. }
  716. // shutdown OpenGL driver
  717. void CGfxLibrary::EndDriver_OGL(void)
  718. {
  719. // unbind all textures
  720. if( _pTextureStock!=NULL) {
  721. {FOREACHINDYNAMICCONTAINER( _pTextureStock->st_ctObjects, CTextureData, ittd) {
  722. CTextureData &td = *ittd;
  723. td.td_tpLocal.Clear();
  724. td.Unbind();
  725. }}
  726. }
  727. // unbind fog, haze and flat texture
  728. gfxDeleteTexture( _fog_ulTexture);
  729. gfxDeleteTexture( _haze_ulTexture);
  730. ASSERT( _ptdFlat!=NULL);
  731. _ptdFlat->td_tpLocal.Clear();
  732. _ptdFlat->Unbind();
  733. // shut the driver down
  734. if( go_hglRC!=NULL) {
  735. if( pwglMakeCurrent!=NULL) {
  736. BOOL bRes = pwglMakeCurrent(NULL, NULL);
  737. WIN_CHECKERROR( bRes, "MakeCurrent(NULL, NULL)");
  738. }
  739. ASSERT( pwglDeleteContext!=NULL);
  740. BOOL bRes = pwglDeleteContext(go_hglRC);
  741. WIN_CHECKERROR( bRes, "DeleteContext");
  742. go_hglRC = NULL;
  743. }
  744. OGL_ClearFunctionPointers();
  745. }
  746. // prepare current viewport for rendering thru OpenGL
  747. BOOL CGfxLibrary::SetCurrentViewport_OGL(CViewPort *pvp)
  748. {
  749. // if must init entire opengl
  750. if( gl_ulFlags & GLF_INITONNEXTWINDOW)
  751. {
  752. gl_ulFlags &= ~GLF_INITONNEXTWINDOW;
  753. // reopen window
  754. pvp->CloseCanvas();
  755. pvp->OpenCanvas();
  756. // init now
  757. CTempDC tdc(pvp->vp_hWnd);
  758. if( !CreateContext_OGL(tdc.hdc)) return FALSE;
  759. gl_pvpActive = pvp; // remember as current viewport (must do that BEFORE InitContext)
  760. InitContext_OGL();
  761. pvp->vp_ctDisplayChanges = gl_ctDriverChanges;
  762. return TRUE;
  763. }
  764. // if window was not set for this driver
  765. if( pvp->vp_ctDisplayChanges<gl_ctDriverChanges)
  766. {
  767. // reopen window
  768. pvp->CloseCanvas();
  769. pvp->OpenCanvas();
  770. // set it
  771. CTempDC tdc(pvp->vp_hWnd);
  772. if( !SetupPixelFormat_OGL(tdc.hdc)) return FALSE;
  773. pvp->vp_ctDisplayChanges = gl_ctDriverChanges;
  774. }
  775. if( gl_pvpActive!=NULL) {
  776. // fail, if only one window is allowed (3dfx driver), already initialized and trying to set non-primary viewport
  777. const BOOL bOneWindow = (gl_gaAPI[GAT_OGL].ga_adaAdapter[gl_iCurrentAdapter].da_ulFlags & DAF_ONEWINDOW);
  778. if( bOneWindow && gl_pvpActive->vp_hWnd!=NULL && gl_pvpActive->vp_hWnd!=pvp->vp_hWnd) return FALSE;
  779. // no need to set context if it is the same window as last time
  780. if( gl_pvpActive->vp_hWnd==pvp->vp_hWnd) return TRUE;
  781. }
  782. // try to set context to this window
  783. pwglMakeCurrent( NULL, NULL);
  784. CTempDC tdc(pvp->vp_hWnd);
  785. // fail, if cannot set context to this window
  786. if( !pwglMakeCurrent( tdc.hdc, go_hglRC)) return FALSE;
  787. // remember as current window
  788. gl_pvpActive = pvp;
  789. return TRUE;
  790. }
  791. /*
  792. * 3dfx t-buffer control
  793. */
  794. extern void SetTBufferEffect( BOOL bEnable)
  795. {
  796. // adjust console vars
  797. ogl_iTBufferEffect = Clamp( ogl_iTBufferEffect, 0L, 2L);
  798. ogl_iTBufferSamples = (1L) << FastLog2(ogl_iTBufferSamples);
  799. if( ogl_iTBufferSamples<2) ogl_iTBufferSamples = 4;
  800. // if supported
  801. if( _pGfx->gl_ulFlags&GLF_EXT_TBUFFER)
  802. { // disable multisampling if not required
  803. ASSERT( pglTBufferMask3DFX!=NULL);
  804. if( ogl_iTBufferEffect==0 || _pGfx->go_ctSampleBuffers<2 || !bEnable) pglDisable( GL_MULTISAMPLE_3DFX);
  805. else {
  806. pglEnable( GL_MULTISAMPLE_3DFX);
  807. UINT uiMask = 0xFFFFFFFF;
  808. // set one buffer in case of motion-blur
  809. if( ogl_iTBufferEffect==2) uiMask = (1UL) << _pGfx->go_iCurrentWriteBuffer;
  810. //pglTBufferMask3DFX(uiMask);
  811. }
  812. }
  813. }