From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/driver__opengl_8cpp-source.html | 2443 ++++++++++++++++++++++ 1 file changed, 2443 insertions(+) create mode 100644 docs/doxygen/nel/driver__opengl_8cpp-source.html (limited to 'docs/doxygen/nel/driver__opengl_8cpp-source.html') diff --git a/docs/doxygen/nel/driver__opengl_8cpp-source.html b/docs/doxygen/nel/driver__opengl_8cpp-source.html new file mode 100644 index 00000000..a4db00b3 --- /dev/null +++ b/docs/doxygen/nel/driver__opengl_8cpp-source.html @@ -0,0 +1,2443 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# Home   # nevrax.com   
+ + + + +
Nevrax
+ + + + + + + + + + +
+ + +
+ Nevrax.org
+ + + + + + + +
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
+
+ + +
+ + +
+Docs + +
+  + + + + + +
Documentation 
+ +
+Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  
+

driver_opengl.cpp

Go to the documentation of this file.
00001 
+00009 /* Copyright, 2000 Nevrax Ltd.
+00010  *
+00011  * This file is part of NEVRAX NEL.
+00012  * NEVRAX NEL is free software; you can redistribute it and/or modify
+00013  * it under the terms of the GNU General Public License as published by
+00014  * the Free Software Foundation; either version 2, or (at your option)
+00015  * any later version.
+00016 
+00017  * NEVRAX NEL is distributed in the hope that it will be useful, but
+00018  * WITHOUT ANY WARRANTY; without even the implied warranty of
+00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+00020  * General Public License for more details.
+00021 
+00022  * You should have received a copy of the GNU General Public License
+00023  * along with NEVRAX NEL; see the file COPYING. If not, write to the
+00024  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+00025  * MA 02111-1307, USA.
+00026  */
+00027 
+00028 #include "stdopengl.h"
+00029 
+00030 #ifdef NL_OS_WINDOWS
+00031 
+00032 #define WIN32_LEAN_AND_MEAN
+00033 #include <windows.h>
+00034 #include <windowsx.h>
+00035 #include <string>
+00036 
+00037 
+00038 #else // NL_OS_UNIX
+00039 
+00040 #include <GL/glx.h>
+00041 
+00042 #endif // NL_OS_UNIX
+00043 
+00044 #include <vector>
+00045 #include <GL/gl.h>
+00046 
+00047 #include "nel/3d/viewport.h"
+00048 #include "nel/3d/scissor.h"
+00049 #include "nel/3d/u_driver.h"
+00050 #include "3d/vertex_buffer.h"
+00051 #include "3d/light.h"
+00052 #include "3d/primitive_block.h"
+00053 #include "nel/misc/rect.h"
+00054 #include "nel/misc/di_event_emitter.h"
+00055 #include "driver_opengl_vertex_buffer_hard.h"
+00056 
+00057 
+00058 using namespace std;
+00059 using namespace NLMISC;
+00060 
+00061 
+00062 
+00063 // ***************************************************************************
+00064 // try to allocate 16Mo by default of AGP Ram.
+00065 #define NL3D_DRV_VERTEXARRAY_AGP_INIT_SIZE              (16384*1024)
+00066 
+00067 
+00068 // ***************************************************************************
+00069 #ifdef NL_OS_WINDOWS
+00070 // dllmain::
+00071 BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved)
+00072 {
+00073         if (fdwReason == DLL_PROCESS_ATTACH)
+00074         {
+00075                 // Yoyo: Vianney change: don't need to call initDebug() anymore.
+00076                 // initDebug();
+00077         }
+00078         return true;
+00079 }
+00080 #endif
+00081 
+00082 
+00083 namespace NL3D
+00084 {
+00085 
+00086 #ifdef NL_OS_WINDOWS
+00087 uint CDriverGL::_Registered=0;
+00088 #endif // NL_OS_WINDOWS
+00089 
+00090 // Version of the driver. Not the interface version!! Increment when implementation of the driver change.
+00091 const uint32            CDriverGL::ReleaseVersion = 0x8;
+00092 
+00093 #ifdef NL_OS_WINDOWS
+00094 
+00095 __declspec(dllexport) IDriver* NL3D_createIDriverInstance ()
+00096 {
+00097         return new CDriverGL;
+00098 }
+00099 
+00100 __declspec(dllexport) uint32 NL3D_interfaceVersion ()
+00101 {
+00102         return IDriver::InterfaceVersion;
+00103 }
+00104 
+00105 static void GlWndProc(CDriverGL *driver, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+00106 {
+00107         if(message == WM_SIZE)
+00108         {
+00109                 RECT rect;
+00110                 if (driver != NULL)
+00111                 {
+00112                         GetClientRect (driver->_hWnd, &rect);
+00113 
+00114                         // Setup gl viewport
+00115                         driver->_WindowWidth = rect.right-rect.left;
+00116                         driver->_WindowHeight = rect.bottom-rect.top;
+00117                 }
+00118         }
+00119 
+00120         if (driver->_EventEmitter.getNumEmitters() > 0)
+00121         {
+00122                 CWinEventEmitter *we = NLMISC::safe_cast<CWinEventEmitter *>(driver->_EventEmitter.getEmitter(0));
+00123                 // Process the message by the emitter
+00124                 we->setHWnd((uint32)hWnd);
+00125                 we->processMessage ((uint32)hWnd, message, wParam, lParam);
+00126         }
+00127 }
+00128 
+00129 static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+00130 {
+00131         // Get the driver pointer..
+00132         CDriverGL *pDriver=(CDriverGL*)GetWindowLong (hWnd, GWL_USERDATA);
+00133         if (pDriver != NULL)
+00134         {
+00135                 GlWndProc (pDriver, hWnd, message, wParam, lParam);
+00136         }
+00137         return DefWindowProc(hWnd, message, wParam, lParam);
+00138 }
+00139 
+00140 #elif defined (NL_OS_UNIX)
+00141 
+00142 extern "C"
+00143 {
+00144 IDriver* NL3D_createIDriverInstance ()
+00145 {
+00146         return new CDriverGL;
+00147 }
+00148 
+00149 uint32 NL3D_interfaceVersion ()
+00150 {
+00151         return IDriver::InterfaceVersion;
+00152 }
+00153 }
+00154 /*
+00155 static Bool WndProc(Display *d, XEvent *e, char *arg)
+00156 {
+00157   nlinfo("glop %d %d", e->type, e->xmap.window);
+00158   CDriverGL *pDriver = (CDriverGL*)arg;
+00159   if (pDriver != NULL)
+00160     {
+00161       // Process the message by the emitter
+00162       pDriver->_EventEmitter.processMessage();
+00163     }
+00164   // TODO i'don t know what to return exactly
+00165   return (e->type == MapNotify) && (e->xmap.window == (Window) arg);
+00166 }
+00167 */
+00168 #endif // NL_OS_UNIX
+00169 
+00170 
+00171 // ***************************************************************************
+00172 CDriverGL::CDriverGL()
+00173 {       
+00174         _OffScreen = false;
+00175 
+00176 #ifdef NL_OS_WINDOWS
+00177         _PBuffer = NULL;
+00178         _hWnd = NULL;
+00179         _hRC = NULL;
+00180         _hDC = NULL;
+00181         _NeedToRestaureGammaRamp = false;
+00182 #elif defined (NL_OS_UNIX) // NL_OS_WINDOWS
+00183 
+00184         cursor = None;
+00185         
+00186 #ifdef XF86VIDMODE
+00187         // zero the old screen mode
+00188         memset(&_OldScreenMode, 0, sizeof(_OldScreenMode));
+00189 #endif //XF86VIDMODE
+00190 
+00191 #endif // NL_OS_UNIX
+00192 
+00193         _FullScreen= false;
+00194 
+00195         _CurrentMaterial=NULL;
+00196         _Initialized = false;
+00197 
+00198         _FogEnabled= false;
+00199         _CurrentFogColor[0]= 0;
+00200         _CurrentFogColor[1]= 0;
+00201         _CurrentFogColor[2]= 0;
+00202         _CurrentFogColor[3]= 0;
+00203 
+00204 
+00205         _LightSetupDirty= false;
+00206         _ModelViewMatrixDirty= false;
+00207         _RenderSetupDirty= false;
+00208         
+00209 
+00210         _CurrentGlNormalize= false;
+00211         _ForceNormalize= false;
+00212 
+00213         _AGPVertexArrayRange= NULL;
+00214         _VRAMVertexArrayRange= NULL;
+00215         _CurrentVertexArrayRange= NULL;
+00216         _CurrentVertexBufferHard= NULL;
+00217         _NVCurrentVARPtr= NULL;
+00218         _NVCurrentVARSize= 0;
+00219         _SupportVBHard= false;
+00220         _SlowUnlockVBHard= false;
+00221         _MaxVerticesByVBHard= 0;
+00222 
+00223         _AllocatedTextureMemory= 0;
+00224 
+00225         _ForceDXTCCompression= false;
+00226         _ForceTextureResizePower= 0;
+00227 
+00228         _SumTextureMemoryUsed = false;
+00229 
+00230         _NVTextureShaderEnabled = false;
+00231 
+00232 
+00233         // Compute the Flag which say if one texture has been changed in CMaterial.
+00234         uint    i;
+00235         _MaterialAllTextureTouchedFlag= 0;
+00236         for(i=0; i < IDRV_MAT_MAXTEXTURES; i++)
+00237         {
+00238                 _MaterialAllTextureTouchedFlag|= IDRV_TOUCHED_TEX[i];
+00239                 _CurrentTexAddrMode[i] = GL_NONE;
+00240         }
+00241 
+00242 
+00243         _UserTexMatEnabled = 0;
+00244         
+00245         // Ligtmap preca.
+00246         _LastVertexSetupIsLightMap= false;
+00247         for(i=0; i < IDRV_MAT_MAXTEXTURES; i++)
+00248                 _LightMapUVMap[i]= -1;
+00249         // reserve enough space to never reallocate, nor test for reallocation.
+00250         _LightMapLUT.resize(NL3D_DRV_MAX_LIGHTMAP);
+00251         // must set replace for alpha part.
+00252         _LightMapLastStageEnv.Env.OpAlpha= CMaterial::Replace;
+00253         _LightMapLastStageEnv.Env.SrcArg0Alpha= CMaterial::Texture;
+00254         _LightMapLastStageEnv.Env.OpArg0Alpha= CMaterial::SrcAlpha;
+00255 
+00256         _ProjMatDirty = true;
+00257 
+00258         std::fill(_StageSupportEMBM, _StageSupportEMBM + IDRV_MAT_MAXTEXTURES, false);
+00259 
+00261 
+00262 }
+00263 
+00264 
+00265 // ***************************************************************************
+00266 CDriverGL::~CDriverGL()
+00267 {
+00268         release();
+00269 }
+00270 
+00271 // ***************************************************************************
+00272 bool CDriverGL::init()
+00273 {
+00274 #ifdef WIN32
+00275         WNDCLASS                wc;
+00276 
+00277         if (!_Registered)
+00278         {
+00279                 memset(&wc,0,sizeof(wc));
+00280                 wc.style                        = CS_HREDRAW | CS_VREDRAW ;//| CS_DBLCLKS;
+00281                 wc.lpfnWndProc          = (WNDPROC)WndProc;
+00282                 wc.cbClsExtra           = 0;
+00283                 wc.cbWndExtra           = 0;
+00284                 wc.hInstance            = GetModuleHandle(NULL);
+00285                 wc.hIcon                        = NULL;
+00286                 wc.hCursor                      = LoadCursor(NULL,IDC_ARROW);
+00287                 wc.hbrBackground        = WHITE_BRUSH;
+00288                 wc.lpszClassName        = "NLClass";
+00289                 wc.lpszMenuName         = NULL;
+00290                 if ( !RegisterClass(&wc) ) 
+00291                 {
+00292                         return false;
+00293                 }
+00294                 _Registered=1;
+00295         }
+00296 
+00297         // Backup monitor color parameters
+00298         HDC dc = CreateDC ("DISPLAY", NULL, NULL, NULL);
+00299         if (dc)
+00300         {
+00301                 _NeedToRestaureGammaRamp = GetDeviceGammaRamp (dc, _GammaRampBackuped) != FALSE;
+00302 
+00303                 // Release the DC
+00304                 ReleaseDC (NULL, dc);
+00305         }
+00306         else
+00307         {
+00308                 nlwarning ("(CDriverGL::init): can't create DC");
+00309         }
+00310 
+00311 #endif
+00312         return true;
+00313 }
+00314 
+00315 // --------------------------------------------------
+00316 
+00317 ModeList CDriverGL::enumModes()
+00318 {
+00319         ModeList        ML;
+00320 #ifdef NL_OS_WINDOWS
+00321         DEVMODE         devmode;
+00322         sint            n;
+00323         GfxMode         Mode;
+00324 
+00325         n=0;
+00326         while( EnumDisplaySettings(NULL, n, &devmode) )
+00327         {
+00328                 Mode.Windowed=false;
+00329                 Mode.Width=(uint16)devmode.dmPelsWidth;
+00330                 Mode.Height=(uint16)devmode.dmPelsHeight;       
+00331                 Mode.Depth=(uint8)devmode.dmBitsPerPel; 
+00332                 ML.push_back(Mode);
+00333                 n++;    
+00334         }
+00335 #endif // NL_OS_WINDOWS
+00336         return ML;
+00337 }
+00338 
+00339 // --------------------------------------------------
+00340 
+00341 void CDriverGL::disableHardwareVertexProgram()
+00342 {
+00343         _Extensions.DisableHardwareVertexProgram= true;
+00344 }
+00345 
+00346 void CDriverGL::disableHardwareVertexArrayAGP()
+00347 {
+00348         _Extensions.DisableHardwareVertexArrayAGP= true;
+00349 }
+00350 
+00351 void CDriverGL::disableHardwareTextureShader()
+00352 {
+00353         _Extensions.DisableHardwareTextureShader= true;
+00354 }
+00355 
+00356 // --------------------------------------------------
+00357 
+00358 bool CDriverGL::setDisplay(void *wnd, const GfxMode &mode) throw(EBadDisplay)
+00359 {
+00360         uint width = mode.Width;
+00361         uint height = mode.Height;
+00362 
+00363 #ifdef NL_OS_WINDOWS
+00364         
+00365         // Driver caps.
+00366         //=============
+00367         // Retrieve the WGL extensions before init the driver.
+00368         int                                             pf;
+00369 
+00370         _OffScreen = mode.OffScreen;
+00371 
+00372         // Init pointers
+00373         _PBuffer = NULL;
+00374         _hWnd = NULL;
+00375         _WindowWidth = _WindowHeight = 0;
+00376         _hRC = NULL;
+00377         _hDC = NULL;
+00378 
+00379         // Offscreen mode ?
+00380         if (_OffScreen)
+00381         {
+00382                 // Get a hdc
+00383 
+00384                 ULONG WndFlags=WS_OVERLAPPEDWINDOW+WS_CLIPCHILDREN+WS_CLIPSIBLINGS;
+00385                 WndFlags&=~WS_VISIBLE;
+00386                 RECT    WndRect;
+00387                 WndRect.left=0;
+00388                 WndRect.top=0;
+00389                 WndRect.right=width;
+00390                 WndRect.bottom=height;
+00391                 AdjustWindowRect(&WndRect,WndFlags,FALSE);
+00392                 HWND tmpHWND = CreateWindow(    "NLClass",
+00393                                                                         "",
+00394                                                                         WndFlags,
+00395                                                                         CW_USEDEFAULT,CW_USEDEFAULT,
+00396                                                                         WndRect.right,WndRect.bottom,
+00397                                                                         NULL,
+00398                                                                         NULL,
+00399                                                                         GetModuleHandle(NULL),
+00400                                                                         NULL);
+00401                 if (!tmpHWND) 
+00402                 {
+00403                         nlwarning ("CDriverGL::setDisplay: CreateWindow failed");
+00404                         return false;
+00405                 }
+00406 
+00407                 // resize the window
+00408                 RECT rc;
+00409                 SetRect (&rc, 0, 0, width, height);
+00410                 _WindowWidth = width;
+00411                 _WindowHeight = height;
+00412                 AdjustWindowRectEx (&rc, GetWindowStyle (_hWnd), GetMenu (_hWnd) != NULL, GetWindowExStyle (_hWnd));
+00413                 SetWindowPos (_hWnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
+00414 
+00415                 // Get the 
+00416                 HDC tempHDC = GetDC(tmpHWND);
+00417 
+00418                 _Depth=GetDeviceCaps(tempHDC,BITSPIXEL);
+00419 
+00420                 // ---
+00421                 memset(&_pfd,0,sizeof(_pfd));
+00422                 _pfd.nSize        = sizeof(_pfd);
+00423                 _pfd.nVersion     = 1;
+00424                 _pfd.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+00425                 _pfd.iPixelType   = PFD_TYPE_RGBA;
+00426                 _pfd.cColorBits   = (char)_Depth;
+00427 
+00428                 // Choose best suited Depth Buffer.
+00429                 if(_Depth<=16)
+00430                 {
+00431                         _pfd.cDepthBits   = 16;
+00432                 }
+00433                 else
+00434                 {
+00435                         _pfd.cDepthBits = 24;
+00436                         _pfd.cAlphaBits = 8;
+00437                 }
+00438                 _pfd.iLayerType   = PFD_MAIN_PLANE;
+00439                 pf=ChoosePixelFormat(tempHDC,&_pfd);
+00440                 if (!pf) 
+00441                 {
+00442                         nlwarning ("CDriverGL::setDisplay: ChoosePixelFormat failed");
+00443                         DestroyWindow (tmpHWND);
+00444                         return false;
+00445                 } 
+00446                 if ( !SetPixelFormat(tempHDC,pf,&_pfd) ) 
+00447                 {
+00448                         nlwarning ("CDriverGL::setDisplay: SetPixelFormat failed");
+00449                         DestroyWindow (tmpHWND);
+00450                         return false;
+00451                 } 
+00452 
+00453                 // Create gl context
+00454                 HGLRC tempGLRC = wglCreateContext(tempHDC);
+00455                 if (tempGLRC == NULL)
+00456                 {
+00457                         DWORD error = GetLastError ();
+00458                         nlwarning ("CDriverGL::setDisplay: wglCreateContext failed: 0x%x", error);
+00459                         DestroyWindow (tmpHWND);
+00460                         _PBuffer = NULL;
+00461                         _hWnd = NULL;
+00462                         _hRC = NULL;
+00463                         _hDC = NULL;
+00464                         return false;
+00465                 }
+00466 
+00467                 // Make the context current
+00468                 if (!wglMakeCurrent(tempHDC,tempGLRC))
+00469                 {
+00470                         DWORD error = GetLastError ();
+00471                         nlwarning ("CDriverGL::setDisplay: wglMakeCurrent failed: 0x%x", error);
+00472                         wglDeleteContext (tempGLRC);
+00473                         DestroyWindow (tmpHWND);
+00474                         _PBuffer = NULL;
+00475                         _hWnd = NULL;
+00476                         _hRC = NULL;
+00477                         _hDC = NULL;
+00478                         return false;
+00479                 }
+00480 
+00481                 // Register WGL functions
+00482                 registerWGlExtensions (_Extensions, tempHDC);
+00483 
+00484                 HDC hdc = wglGetCurrentDC ();
+00485                 if (hdc == NULL)
+00486                 {
+00487                         DWORD error = GetLastError ();
+00488                         nlwarning ("CDriverGL::setDisplay: wglGetCurrentDC failed: 0x%x", error);
+00489                         DestroyWindow (tmpHWND);
+00490                         _PBuffer = NULL;
+00491                         _hWnd = NULL;
+00492                         _hRC = NULL;
+00493                         _hDC = NULL;
+00494                         return false;
+00495                 }
+00496 
+00497                 // Get ready to query for a suitable pixel format that meets our
+00498                 // minimum requirements.
+00499                 int iattributes[2*20];
+00500                 float fattributes[2*20];
+00501                 int nfattribs = 0;
+00502                 int niattribs = 0;
+00503 
+00504                 // Attribute arrays must be “0” terminated – for simplicity, first
+00505                 // just zero-out the array then fill from left to right.
+00506                 for ( int a = 0; a < 2*20; a++ )
+00507                 {
+00508                         iattributes[a] = 0;
+00509                         fattributes[a] = 0;
+00510                 }
+00511                 
+00512                 // Since we are trying to create a pbuffer, the pixel format we
+00513                 // request (and subsequently use) must be “p-buffer capable”.
+00514                 iattributes[2*niattribs ] = WGL_DRAW_TO_PBUFFER_ARB;
+00515                 iattributes[2*niattribs+1] = true;
+00516                 niattribs++;
+00517                 
+00518                 // We require a minimum of 24-bit depth.
+00519                 iattributes[2*niattribs ] = WGL_DEPTH_BITS_ARB;
+00520                 iattributes[2*niattribs+1] = 24;
+00521                 niattribs++;
+00522                 
+00523                 // We require a minimum of 8-bits for each R, G, B, and A.
+00524                 iattributes[2*niattribs ] = WGL_RED_BITS_ARB;
+00525                 iattributes[2*niattribs+1] = 8;
+00526                 niattribs++;
+00527                 iattributes[2*niattribs ] = WGL_GREEN_BITS_ARB;
+00528                 iattributes[2*niattribs+1] = 8;
+00529                 niattribs++;
+00530                 iattributes[2*niattribs ] = WGL_BLUE_BITS_ARB;
+00531                 iattributes[2*niattribs+1] = 8;
+00532                 niattribs++;
+00533                 iattributes[2*niattribs ] = WGL_ALPHA_BITS_ARB;
+00534                 iattributes[2*niattribs+1] = 8;
+00535                 niattribs++;
+00536                 
+00537                 // Now obtain a list of pixel formats that meet these minimum
+00538                 // requirements.
+00539                 int pformat[20];
+00540                 unsigned int nformats;
+00541                 if ( !wglChoosePixelFormatARB ( hdc, iattributes, fattributes,
+00542                         20, pformat, &nformats ) )
+00543                 {
+00544                         nlwarning ( "pbuffer creation error: Couldn't find a suitable pixel format.\n" );
+00545                         wglDeleteContext (tempGLRC);
+00546                         DestroyWindow (tmpHWND);
+00547                         return false;
+00548                 }
+00549 
+00550                 /* After determining a compatible pixel format, the next step is to create a pbuffer of the
+00551                         chosen format. Fortunately this step is fairly easy, as you merely select one of the formats
+00552                         returned in the list in step #2 and call the function: */
+00553                 int iattributes2[1] = {0};
+00554                 // int iattributes2[] = {WGL_PBUFFER_LARGEST_ARB, 1, 0};
+00555                 _PBuffer = wglCreatePbufferARB( hdc, pformat[0], width, height, iattributes2 );
+00556                 if (_PBuffer == NULL)
+00557                 {
+00558                         DWORD error = GetLastError ();
+00559                         nlwarning ("CDriverGL::setDisplay: wglCreatePbufferARB failed: 0x%x", error);
+00560                         wglDeleteContext (tempGLRC);
+00561                         DestroyWindow (tmpHWND);
+00562                         _PBuffer = NULL;
+00563                         _hWnd = NULL;
+00564                         _hRC = NULL;
+00565                         _hDC = NULL;
+00566                         return false;
+00567                 }
+00568 
+00569                 /* After creating a pbuffer, you may use this functions to determine the dimensions of the pbuffer actually created. */
+00570                 if ( !wglQueryPbufferARB( _PBuffer, WGL_PBUFFER_WIDTH_ARB, (int*)&width ) )
+00571                 {
+00572                         DWORD error = GetLastError ();
+00573                         nlwarning ("CDriverGL::setDisplay: wglQueryPbufferARB failed: 0x%x", error);
+00574                         wglDeleteContext (tempGLRC);
+00575                         DestroyWindow (tmpHWND);
+00576                         _PBuffer = NULL;
+00577                         _hWnd = NULL;
+00578                         _hRC = NULL;
+00579                         _hDC = NULL;
+00580                         return false;
+00581                 }
+00582                 if ( !wglQueryPbufferARB( _PBuffer, WGL_PBUFFER_HEIGHT_ARB, (int*)&height ) )
+00583                 {
+00584                         DWORD error = GetLastError ();
+00585                         nlwarning ("CDriverGL::setDisplay: wglQueryPbufferARB failed: 0x%x", error);
+00586                         wglDeleteContext (tempGLRC);
+00587                         DestroyWindow (tmpHWND);
+00588                         _PBuffer = NULL;
+00589                         _hWnd = NULL;
+00590                         _hRC = NULL;
+00591                         _hDC = NULL;
+00592                         return false;
+00593                 }
+00594                 _WindowWidth = width;
+00595                 _WindowHeight = height;
+00596 
+00597                 /* The next step is to create a device context for the newly created pbuffer. To do this,
+00598                         call the the function: */
+00599                 _hDC = wglGetPbufferDCARB( _PBuffer );
+00600                 if (_hDC == NULL)
+00601                 {
+00602                         DWORD error = GetLastError ();
+00603                         nlwarning ("CDriverGL::setDisplay: wglGetPbufferDCARB failed: 0x%x", error);
+00604                         wglDestroyPbufferARB( _PBuffer );
+00605                         wglDeleteContext (tempGLRC);
+00606                         DestroyWindow (tmpHWND);
+00607                         _PBuffer = NULL;
+00608                         _hWnd = NULL;
+00609                         _hRC = NULL;
+00610                         _hDC = NULL;
+00611                         return false;
+00612                 }
+00613 
+00614 
+00615                 /* The final step of pbuffer creation is to create an OpenGL rendering context and
+00616                         associate it with the handle for the pbuffer’s device context created in step #4. This is done as follows */
+00617                 _hRC = wglCreateContext( _hDC );
+00618                 if (_hRC == NULL)
+00619                 {
+00620                         DWORD error = GetLastError ();
+00621                         nlwarning ("CDriverGL::setDisplay: wglCreateContext failed: 0x%x", error);
+00622                         wglReleasePbufferDCARB( _PBuffer, _hDC );
+00623                         wglDestroyPbufferARB( _PBuffer );
+00624                         wglDeleteContext (tempGLRC);
+00625                         DestroyWindow (tmpHWND);
+00626                         _PBuffer = NULL;
+00627                         _hWnd = NULL;
+00628                         _hRC = NULL;
+00629                         _hDC = NULL;
+00630                         return false;
+00631                 }
+00632 
+00633                 // Get the depth
+00634                 _Depth = GetDeviceCaps (_hDC, BITSPIXEL);
+00635 
+00636                 // Destroy the temp gl context
+00637                 if (!wglDeleteContext (tempGLRC))
+00638                 {
+00639                         DWORD error = GetLastError ();
+00640                         nlwarning ("CDriverGL::setDisplay: wglDeleteContext failed: 0x%x", error);
+00641                 }
+00642 
+00643                 // Destroy the temp windows
+00644                 if (!DestroyWindow (tmpHWND))
+00645                         nlwarning ("CDriverGL::setDisplay: DestroyWindow failed");
+00646 
+00647                 /* After a pbuffer has been successfully created you can use it for off-screen rendering. To do
+00648                         so, you’ll first need to bind the pbuffer, or more precisely, make its GL rendering context
+00649                         the current context that will interpret all OpenGL commands and state changes. */
+00650                 if (!wglMakeCurrent(_hDC,_hRC))
+00651                 {
+00652                         DWORD error = GetLastError ();
+00653                         nlwarning ("CDriverGL::setDisplay: wglMakeCurrent failed: 0x%x", error);
+00654                         wglDeleteContext (_hRC);
+00655                         wglReleasePbufferDCARB( _PBuffer, _hDC );
+00656                         wglDestroyPbufferARB( _PBuffer );
+00657                         DestroyWindow (tmpHWND);
+00658                         _PBuffer = NULL;
+00659                         _hWnd = NULL;
+00660                         _hRC = NULL;
+00661                         _hDC = NULL;
+00662                         return false;
+00663                 }
+00664         }
+00665         else
+00666         {
+00667                 _FullScreen= false;
+00668                 if (wnd)
+00669                 {
+00670                         _hWnd=(HWND)wnd;
+00671                         _DestroyWindow=false;
+00672                 }
+00673                 else
+00674                 {
+00675                         ULONG   WndFlags;
+00676                         RECT    WndRect;
+00677 
+00678                         // Must destroy this window
+00679                         _DestroyWindow=true;
+00680 
+00681                         if(mode.Windowed)
+00682                                 WndFlags=WS_OVERLAPPEDWINDOW+WS_CLIPCHILDREN+WS_CLIPSIBLINGS;
+00683                         else
+00684                         {
+00685                                 WndFlags=WS_POPUP;
+00686 
+00687                                 _FullScreen= true;
+00688                                 DEVMODE         devMode;
+00689                                 _OldScreenMode.dmSize= sizeof(DEVMODE);
+00690                                 _OldScreenMode.dmDriverExtra= 0;
+00691                                 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &_OldScreenMode);
+00692                                 _OldScreenMode.dmFields= DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY ;
+00693 
+00694                                 devMode.dmSize= sizeof(DEVMODE);
+00695                                 devMode.dmDriverExtra= 0;
+00696                                 devMode.dmFields= DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+00697                                 devMode.dmPelsWidth= width;
+00698                                 devMode.dmPelsHeight= height;
+00699                                 devMode.dmBitsPerPel= mode.Depth;
+00700                                 ChangeDisplaySettings(&devMode, CDS_FULLSCREEN);
+00701                         }
+00702                         WndRect.left=0;
+00703                         WndRect.top=0;
+00704                         WndRect.right=width;
+00705                         WndRect.bottom=height;
+00706                         AdjustWindowRect(&WndRect,WndFlags,FALSE);
+00707                         _hWnd = CreateWindow(   "NLClass",
+00708                                                                         "",
+00709                                                                         WndFlags,
+00710                                                                         CW_USEDEFAULT,CW_USEDEFAULT,
+00711                                                                         WndRect.right,WndRect.bottom,
+00712                                                                         NULL,
+00713                                                                         NULL,
+00714                                                                         GetModuleHandle(NULL),
+00715                                                                         NULL);
+00716                         if (!_hWnd) 
+00717                         {
+00718                                 return false;
+00719                         }
+00720 
+00721                         SetWindowLong (_hWnd, GWL_USERDATA, (LONG)this);
+00722 
+00723                         // resize the window
+00724                         RECT rc;
+00725                         SetRect (&rc, 0, 0, width, height);
+00726                         AdjustWindowRectEx (&rc, GetWindowStyle (_hWnd), GetMenu (_hWnd) != NULL, GetWindowExStyle (_hWnd));
+00727                         SetWindowPos (_hWnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
+00728 
+00729                         ShowWindow(_hWnd,SW_SHOW);
+00730                 }
+00731 
+00732                 // Init Window Width and Height
+00733                 RECT clientRect;
+00734                 GetClientRect (_hWnd, &clientRect);
+00735                 _WindowWidth = clientRect.right-clientRect.left;
+00736                 _WindowHeight = clientRect.bottom-clientRect.top;
+00737 
+00738                 _hDC=GetDC(_hWnd);
+00739                 wglMakeCurrent(_hDC,NULL);
+00740                 _Depth=GetDeviceCaps(_hDC,BITSPIXEL);
+00741                 // ---
+00742                 memset(&_pfd,0,sizeof(_pfd));
+00743                 _pfd.nSize        = sizeof(_pfd);
+00744                 _pfd.nVersion     = 1;
+00745                 _pfd.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+00746                 _pfd.iPixelType   = PFD_TYPE_RGBA;
+00747                 _pfd.cColorBits   = (char)_Depth;
+00748                 // Choose best suited Depth Buffer.
+00749                 if(_Depth<=16)
+00750                 {
+00751                         _pfd.cDepthBits   = 16;
+00752                 }
+00753                 else
+00754                 {
+00755                         _pfd.cDepthBits = 24;
+00756                         _pfd.cAlphaBits = 8;
+00757                 }
+00758                 _pfd.iLayerType   = PFD_MAIN_PLANE;
+00759                 pf=ChoosePixelFormat(_hDC,&_pfd);
+00760                 if (!pf) 
+00761                 {
+00762                         return false;
+00763                 }
+00764 
+00765                 if ( !SetPixelFormat(_hDC,pf,&_pfd) ) 
+00766                 {
+00767                         return false;
+00768                 } 
+00769                 _hRC=wglCreateContext(_hDC);
+00770                 wglMakeCurrent(_hDC,_hRC);
+00771         }
+00772 
+00774         while (_EventEmitter.getNumEmitters() != 0)
+00775         {
+00776                 _EventEmitter.removeEmitter(_EventEmitter.getEmitter(_EventEmitter.getNumEmitters() - 1));
+00777         }
+00778         NLMISC::CWinEventEmitter *we = new NLMISC::CWinEventEmitter;
+00779         // setup the event emitter, and try to retrieve a direct input interface
+00780         _EventEmitter.addEmitter(we, true /*must delete*/); // the main emitter
+00782         try
+00783         {
+00784                 NLMISC::CDIEventEmitter *diee = NLMISC::CDIEventEmitter::create(GetModuleHandle(NULL), _hWnd, we);
+00785                 if (diee)
+00786                 {
+00787                         _EventEmitter.addEmitter(diee, true);
+00788                 }
+00789         }
+00790         catch(EDirectInput &e)
+00791         {
+00792                 nlinfo(e.what());
+00793         }
+00794 
+00795 #elif defined(NL_OS_UNIX) // NL_OS_WINDOWS
+00796 
+00797         dpy = XOpenDisplay(NULL);
+00798         if (dpy == NULL)
+00799         {
+00800           nlerror ("XOpenDisplay failed on '%s'",getenv("DISPLAY"));
+00801         }
+00802         else
+00803           {
+00804             nldebug("XOpenDisplay on '%s' OK", getenv("DISPLAY"));
+00805           }
+00806 
+00807         int sAttribList[] =
+00808         {
+00809           GLX_RGBA,
+00810           GLX_DOUBLEBUFFER,
+00811           //GLX_BUFFER_SIZE, 16,
+00812           GLX_DEPTH_SIZE, 16,
+00813           GLX_RED_SIZE, 4,
+00814           GLX_GREEN_SIZE, 4,
+00815           GLX_BLUE_SIZE, 4,
+00816           //GLX_ALPHA_SIZE, 8,
+00817           None
+00818         };
+00819         /*
+00820         int sAttribList[] =
+00821         {
+00822           GLX_RGBA,
+00823           GLX_DOUBLEBUFFER,
+00824           //GLX_BUFFER_SIZE, 32,
+00825           GLX_DEPTH_SIZE, 32,
+00826           GLX_RED_SIZE, 8,
+00827           GLX_GREEN_SIZE, 8,
+00828           GLX_BLUE_SIZE, 8,
+00829           GLX_ALPHA_SIZE, 8,
+00830           None
+00831           };
+00832         */
+00833         XVisualInfo *visual_info = glXChooseVisual (dpy, DefaultScreen(dpy), sAttribList);
+00834 
+00835         if(visual_info == NULL)
+00836           {
+00837             nlerror("glXChooseVisual() failed");
+00838           }
+00839         else
+00840           {
+00841             nldebug("glXChooseVisual OK");
+00842           }
+00843 
+00844         ctx = glXCreateContext (dpy, visual_info, None, GL_TRUE);
+00845 
+00846         if(ctx == NULL)
+00847           {
+00848             nlerror("glXCreateContext() failed");
+00849           }
+00850         else
+00851           {
+00852             nldebug("glXCreateContext() OK");
+00853           }
+00854 
+00855         Colormap cmap = XCreateColormap (dpy, RootWindow(dpy, DefaultScreen(dpy)), visual_info->visual, AllocNone);
+00856 
+00857         XSetWindowAttributes attr;
+00858         attr.colormap = cmap;
+00859         attr.background_pixel = BlackPixel(dpy, DefaultScreen(dpy));
+00860         
+00861 #ifdef XF86VIDMODE
+00862         // If we're going to attempt fullscreen, we need to set redirect to True,
+00863         // This basically places the window with no borders in the top left 
+00864         // corner of the screen.
+00865         if (mode.Windowed)
+00866         {
+00867                 attr.override_redirect = False;
+00868         }
+00869         else
+00870         {
+00871                 attr.override_redirect = True;
+00872         }
+00873 #else
+00874         attr.override_redirect = False;
+00875 #endif
+00876 
+00877         int attr_flags = CWOverrideRedirect | CWColormap | CWBackPixel;
+00878 
+00879         win = XCreateWindow (dpy, RootWindow(dpy, DefaultScreen(dpy)), 0, 0, width, height, 0, visual_info->depth, InputOutput, visual_info->visual, attr_flags, &attr);        
+00880 
+00881         if(!win)
+00882           {
+00883             nlerror("XCreateWindow() failed");
+00884           }
+00885         else
+00886           {
+00887             nldebug("XCreateWindow() OK");
+00888           }
+00889 
+00890         XSizeHints size_hints;
+00891         size_hints.x = 0;
+00892         size_hints.y = 0;
+00893         size_hints.width = width;
+00894         size_hints.height = height;
+00895         size_hints.flags = PSize | PMinSize | PMaxSize;
+00896         size_hints.min_width = width;
+00897         size_hints.min_height = height;
+00898         size_hints.max_width = width;
+00899         size_hints.max_height = height;
+00900 
+00901         XTextProperty text_property;
+00902         char *title="NeL window";
+00903         XStringListToTextProperty(&title, 1, &text_property);
+00904 
+00905         XSetWMProperties (dpy, win, &text_property, &text_property,  0, 0, &size_hints, 0, 0);
+00906         glXMakeCurrent (dpy, win, ctx);
+00907         XMapRaised (dpy, win);
+00908 
+00909         XSelectInput (dpy, win,
+00910                       KeyPressMask|
+00911                       KeyReleaseMask|
+00912                       ButtonPressMask|
+00913                       ButtonReleaseMask|
+00914                       PointerMotionMask
+00915                       );
+00916 
+00917         XMapWindow(dpy, win);
+00918 
+00919         _EventEmitter.init (dpy, win);
+00920 
+00921 //      XEvent event;
+00922 //      XIfEvent(dpy, &event, WaitForNotify, (char *)this);
+00923 
+00924 #ifdef XF86VIDMODE
+00925         if (!mode.Windowed)
+00926         {
+00927 
+00928                 // Set window to the right size, map it to the display, and raise it
+00929                 // to the front
+00930                 XResizeWindow(dpy,win,width,height);
+00931                 XMapRaised(dpy,win);
+00932                 XRaiseWindow(dpy, win);
+00933 
+00934                 // grab the mouse and keyboard on the fullscreen window 
+00935                 if ((XGrabPointer(dpy, win, True, 0,
+00936                                                   GrabModeAsync, GrabModeAsync,
+00937                                                   win, None, CurrentTime) != GrabSuccess) ||
+00938                         (XGrabKeyboard(dpy, win, True,
+00939                                                    GrabModeAsync, GrabModeAsync, CurrentTime) != 0) )
+00940                 {
+00941                         // Until I work out how to deal with this nicely, it just gives
+00942                         // an error and exits the prorgam.
+00943                         nlerror("Unable to grab keyboard and mouse\n");
+00944                 }
+00945                 else
+00946                 {
+00947                         // Save the old screen mode and dotclock
+00948                         memset(&_OldScreenMode, 0, sizeof(_OldScreenMode));
+00949                         XF86VidModeGetModeLine(dpy, 
+00950                                                                    DefaultScreen(dpy),
+00951                                                                    &_OldDotClock,
+00952                                                                    &_OldScreenMode);
+00953                         // Save the old viewport
+00954                         XF86VidModeGetViewPort(dpy, 
+00955                                                                    DefaultScreen(dpy),
+00956                                                                    &_OldX,
+00957                                                                    &_OldY);
+00958     
+00959                         // get a list of modes, search for an appropriate one.
+00960                         XF86VidModeModeInfo **modes;
+00961                         int nmodes;
+00962                         if (XF86VidModeGetAllModeLines(dpy,
+00963                                                                                    DefaultScreen(dpy),
+00964                                                                                    &nmodes,&modes))
+00965                         {
+00966                                 int mode_index = -1; // Gah, magic numbers all bad. 
+00967                                 for (int i = 0; i < nmodes; i++)
+00968                                 {
+00969                                         nldebug("Available mode - %dx%d\n",width,height);
+00970                                         if( (modes[i]->hdisplay == width) &&
+00971                                                 (modes[i]->vdisplay == height))
+00972                                         {
+00973                                                 mode_index = i;
+00974                                         }
+00975                                 }
+00976                                 // Switch to the mode
+00977                                 if (mode_index != -1)
+00978                                 {
+00979                                         if(XF86VidModeSwitchToMode(dpy,
+00980                                                                                            DefaultScreen(dpy), 
+00981                                                                                            modes[mode_index]))
+00982                                         {
+00983                                                 nlinfo("Switching to mode %dx%d,\n",width, 
+00984                                                            height);
+00985                                                 XF86VidModeSetViewPort(dpy,DefaultScreen(dpy),0, 0);
+00986                                                 _FullScreen = true;
+00987                                         }
+00988                                 }
+00989                                 else
+00990                                 {
+00991                                         // This is a problem, since we've nuked the border from 
+00992                                         // window in the setup stage, until I work out how
+00993                                         // to get it back (recreate window? seems excessive)
+00994                                         nlerror("Couldn't find an appropriate mode %dx%d\n",
+00995                                                         width,
+00996                                                         height);
+00997                                 }
+00998                         }
+00999                 }
+01000         }
+01001 
+01002 #endif // XF86VIDMODE
+01003 
+01004 #endif // NL_OS_UNIX
+01005 
+01006 
+01007         // Driver caps.
+01008         //=============
+01009         // Retrieve the extensions for the current context.
+01010         NL3D::registerGlExtensions (_Extensions);
+01011 #ifdef NL_OS_WINDOWS
+01012         NL3D::registerWGlExtensions (_Extensions, _hDC);
+01013 #endif // ifdef NL_OS_WINDOWS
+01014 
+01015         // Check required extensions!!
+01016         // ARBMultiTexture is a opengl 1.2 required extension.
+01017         if(!_Extensions.ARBMultiTexture)
+01018         {
+01019                 nlwarning("Missing Required GL extension: GL_ARB_multitexture. Update your driver");
+01020                 throw EBadDisplay("Missing Required GL extension: GL_ARB_multitexture. Update your driver");
+01021         }
+01022         if(!_Extensions.EXTTextureEnvCombine)
+01023         {
+01024                 nlwarning("Missing Important GL extension: GL_EXT_texture_env_combine => All envcombine are setup to GL_MODULATE!!!");
+01025         }
+01026 
+01027 
+01028         // init _DriverGLStates
+01029         _DriverGLStates.init(_Extensions.ARBTextureCubeMap);
+01030 
+01031 
+01032         // Init OpenGL/Driver defaults.
+01033         //=============================
+01034         glViewport(0,0,width,height);
+01035         glMatrixMode(GL_PROJECTION);
+01036         glLoadIdentity();
+01037         glOrtho(0,width,height,0,-1.0f,1.0f);   
+01038         glMatrixMode(GL_MODELVIEW);
+01039         glLoadIdentity();
+01040         glDisable(GL_AUTO_NORMAL);
+01041         glDisable(GL_COLOR_MATERIAL);
+01042         glEnable(GL_DITHER);
+01043         glDisable(GL_FOG);
+01044         glDisable(GL_LINE_SMOOTH);
+01045         glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+01046         glEnable(GL_DEPTH_TEST);
+01047         glDisable(GL_NORMALIZE);
+01048         _CurrentGlNormalize= false;
+01049         _ForceNormalize= false;
+01050         // Setup defaults for blend, lighting ...
+01051         _DriverGLStates.forceDefaults(inlGetNumTextStages());
+01052         // Default delta camera pos.
+01053         _PZBCameraPos= CVector::Null;
+01054 
+01055         if (_NVTextureShaderEnabled)
+01056         {
+01057                 enableNVTextureShader(false);           
+01058         }
+01059 
+01060         // Be always in EXTSeparateSpecularColor.
+01061         if(_Extensions.EXTSeparateSpecularColor)
+01062         {
+01063                 glLightModeli((GLenum)GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SEPARATE_SPECULAR_COLOR_EXT);
+01064         }
+01065 
+01066         _VertexProgramEnabled= false;
+01067         _LastSetupGLArrayVertexProgram= false;
+01068 
+01069 
+01070         // Init VertexArrayRange according to supported extenstion.
+01071         _SupportVBHard= false;
+01072         _SlowUnlockVBHard= false;
+01073         _MaxVerticesByVBHard= 0;
+01074         // Try with NVidia ext first.
+01075         if(_Extensions.NVVertexArrayRange)
+01076         {
+01077                 _AGPVertexArrayRange= new CVertexArrayRangeNVidia(this);
+01078                 _VRAMVertexArrayRange= new CVertexArrayRangeNVidia(this);
+01079                 _SupportVBHard= true;
+01080                 _MaxVerticesByVBHard= _Extensions.NVVertexArrayRangeMaxVertex;
+01081         }
+01082         // Else, try with ATI ext
+01083         else if(_Extensions.ATIVertexArrayObject)
+01084         {
+01085                 _AGPVertexArrayRange= new CVertexArrayRangeATI(this);
+01086                 _VRAMVertexArrayRange= new CVertexArrayRangeATI(this);
+01087                 _SupportVBHard= true;
+01088                 // BAD ATI extension scheme.
+01089                 _SlowUnlockVBHard= true;                
+01090                 //_MaxVerticesByVBHard= 65000;
+01091                 _MaxVerticesByVBHard= 32767;
+01092         }
+01093 
+01094         // Reset VertexArrayRange.
+01095         _CurrentVertexArrayRange= NULL;
+01096         _CurrentVertexBufferHard= NULL;
+01097         _NVCurrentVARPtr= NULL;
+01098         _NVCurrentVARSize= 0;
+01099         if(_SupportVBHard)
+01100         {
+01101                 // try to allocate 16Mo by default of AGP Ram.
+01102                 initVertexArrayRange(NL3D_DRV_VERTEXARRAY_AGP_INIT_SIZE, 0);
+01103 
+01104                 // If not success to allocate at least a minimum space in AGP, then disable completely VBHard feature
+01105                 if( _AGPVertexArrayRange->sizeAllocated()==0 )
+01106                 {
+01107                         // reset any allocated VRAM space.
+01108                         resetVertexArrayRange();
+01109 
+01110                         // delete containers
+01111                         delete _AGPVertexArrayRange;
+01112                         delete _VRAMVertexArrayRange;
+01113                         _AGPVertexArrayRange= NULL;
+01114                         _VRAMVertexArrayRange= NULL;
+01115 
+01116                         // disable.
+01117                         _SupportVBHard= false;
+01118                         _SlowUnlockVBHard= false;
+01119                         _MaxVerticesByVBHard= 0;
+01120                 }
+01121         }
+01122 
+01123         // Init embm if present
+01124         //===========================================================
+01125         initEMBM();
+01126 
+01127 
+01128         // Activate the default texture environnments for all stages.
+01129         //===========================================================
+01130         for(sint stage=0;stage<inlGetNumTextStages(); stage++)
+01131         {
+01132                 // init no texture.
+01133                 _CurrentTexture[stage]= NULL;
+01134                 _CurrentTextureInfoGL[stage]= NULL;
+01135                 // texture are disabled in DriverGLStates.forceDefaults().
+01136                 
+01137                 // init default env.
+01138                 CMaterial::CTexEnv      env;    // envmode init to default.
+01139                 env.ConstantColor.set(255,255,255,255);
+01140                 forceActivateTexEnvMode(stage, env);
+01141                 forceActivateTexEnvColor(stage, env);
+01142 
+01143                 // Not special TexEnv.
+01144                 _CurrentTexEnvSpecial[stage]= TexEnvSpecialDisabled;
+01145 
+01146                 resetTextureShaders();          
+01147         }
+01148 
+01149         // Get num of light for this driver
+01150         int numLight;
+01151         glGetIntegerv (GL_MAX_LIGHTS, &numLight);
+01152         _MaxDriverLight=(uint)numLight;
+01153         if (_MaxDriverLight>MaxLight)
+01154                 _MaxDriverLight=MaxLight;
+01155 
+01156         // Reset the lights position flags
+01157         for (uint i=0; i<MaxLight; i++)
+01158                 _LightEnable[i]=false;
+01159 
+01160 
+01161         _PPLExponent = 1.f;
+01162         _PPLightDiffuseColor = NLMISC::CRGBA::White;
+01163         _PPLightSpecularColor = NLMISC::CRGBA::White;
+01164 
+01165         // Backward compatibility: default lighting is Light0 default openGL
+01166         // meaning that light direction is always (0,1,0) in eye-space
+01167         // use enableLighting(0....), to get normal behaviour
+01168         glEnable(GL_LIGHT0);
+01169 
+01170         _Initialized = true;
+01171 
+01172         _ForceDXTCCompression= false;
+01173         _ForceTextureResizePower= 0;
+01174 
+01175         // Reset profiling.
+01176         _AllocatedTextureMemory= 0;
+01177         _TextureUsed.clear();
+01178         _PrimitiveProfileIn.reset();
+01179         _PrimitiveProfileOut.reset();
+01180         _NbSetupMaterialCall= 0;
+01181         _NbSetupModelMatrixCall= 0;
+01182 
+01183         // check wether per pixel lighting shader is supported
+01184         checkForPerPixelLightingSupport();
+01185 
+01186         // if EXTVertexShader is used, bind  the standard GL arrays, and allocate constant
+01187         if (!_Extensions.NVVertexProgram && _Extensions.EXTVertexShader)
+01188         {
+01189                         _EVSPositionHandle = nglBindParameterEXT(GL_CURRENT_VERTEX_EXT);
+01190                         _EVSNormalHandle   = nglBindParameterEXT(GL_CURRENT_NORMAL);
+01191                         _EVSColorHandle    = nglBindParameterEXT(GL_CURRENT_COLOR);
+01192                         if (!_EVSPositionHandle || !_EVSNormalHandle || !_EVSColorHandle)
+01193                         {
+01194                                 nlwarning("Unable to bind input parameters for use with EXT_vertex_shader, vertex program support is disabled");
+01195                                 _Extensions.EXTVertexShader = false;
+01196                         }
+01197                         else
+01198                         {                       
+01199                                 // bind texture units
+01200                                 for(uint k = 0; k < 8; ++k)
+01201                                 {                               
+01202                                         _EVSTexHandle[k] = nglBindTextureUnitParameterEXT(GL_TEXTURE0_ARB + k, GL_CURRENT_TEXTURE_COORDS);
+01203                                 }
+01204                                 // Other attributes are managed using variant pointers :
+01205                                 // Secondary color
+01206                                 // Fog Coords
+01207                                 // Skin Weight
+01208                                 // Skin palette
+01209                                 // This mean that they must have 4 components
+01210 
+01211                                 // Allocate variants
+01212                                 _EVSConstantHandle = nglGenSymbolsEXT(GL_VECTOR_EXT, GL_INVARIANT_EXT, GL_FULL_RANGE_EXT, 97);          
+01213 
+01214                                 if (_EVSConstantHandle == 0)
+01215                                 {
+01216                                         nlwarning("Unable to allocate constants for EXT_vertex_shader, vertex program support is disabled");
+01217                                         _Extensions.EXTVertexShader = false;
+01218                                 }
+01219                         }
+01220         }
+01221 
+01222         return true;
+01223 }
+01224 
+01225 
+01226 void CDriverGL::resetTextureShaders()
+01227 {       
+01228         if (_Extensions.NVTextureShader)
+01229         {
+01230                 glEnable(GL_TEXTURE_SHADER_NV);
+01231                 for (uint stage = 0; stage < (uint) inlGetNumTextStages(); ++stage)
+01232                 {               
+01233                         _DriverGLStates.activeTextureARB(stage);
+01234                         if (stage != 0)
+01235                         {
+01236                                 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB + stage - 1);     
+01237                         }
+01238                         glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);       
+01239                         _CurrentTexAddrMode[stage] = GL_NONE;                   
+01240                 }
+01241                 glDisable(GL_TEXTURE_SHADER_NV);
+01242                 _NVTextureShaderEnabled = false;
+01243         }
+01244 }
+01245 
+01246 // --------------------------------------------------
+01247 
+01248 emptyProc CDriverGL::getWindowProc()
+01249 {
+01250 #ifdef NL_OS_WINDOWS
+01251         return (emptyProc)GlWndProc;
+01252 #else // NL_OS_WINDOWS
+01253         return NULL;
+01254 #endif // NL_OS_WINDOWS
+01255 }
+01256 
+01257 // --------------------------------------------------
+01258 
+01259 bool CDriverGL::activate()
+01260 {
+01261 #ifdef NL_OS_WINDOWS
+01262         HGLRC hglrc=wglGetCurrentContext();
+01263         if (hglrc!=_hRC)
+01264         {
+01265                 wglMakeCurrent(_hDC,_hRC);
+01266         }
+01267 #elif defined (NL_OS_UNIX)
+01268         GLXContext nctx=glXGetCurrentContext();
+01269         if (nctx != NULL && nctx!=ctx)
+01270         {
+01271                 glXMakeCurrent(dpy, win,ctx);
+01272         }
+01273 #endif // NL_OS_WINDOWS
+01274         return true;
+01275 }
+01276 
+01277 // --------------------------------------------------
+01278 
+01279 bool CDriverGL::isTextureExist(const ITexture&tex)
+01280 {
+01281         bool result;
+01282 
+01283         // Create the shared Name.
+01284         std::string     name;
+01285         getTextureShareName (tex, name);
+01286 
+01287         {
+01288                 CSynchronized<TTexDrvInfoPtrMap>::CAccessor access(&_SyncTexDrvInfos);
+01289                 TTexDrvInfoPtrMap &rTexDrvInfos = access.value();
+01290                 result = (rTexDrvInfos.find(name) != rTexDrvInfos.end());
+01291         }
+01292         return result;
+01293 }
+01294 
+01295 // --------------------------------------------------
+01296 
+01297 bool CDriverGL::clear2D(CRGBA rgba)
+01298 {
+01299         glClearColor((float)rgba.R/255.0f,(float)rgba.G/255.0f,(float)rgba.B/255.0f,(float)rgba.A/255.0f);
+01300         glClear(GL_COLOR_BUFFER_BIT);
+01301         return true;
+01302 }
+01303 
+01304 // --------------------------------------------------
+01305 
+01306 bool CDriverGL::clearZBuffer(float zval)
+01307 {
+01308         glClearDepth(zval);
+01309         _DriverGLStates.enableZWrite(true);
+01310         glClear(GL_DEPTH_BUFFER_BIT);
+01311         return true;
+01312 }
+01313 
+01314 // --------------------------------------------------
+01315 
+01316 void CDriverGL::setColorMask (bool bRed, bool bGreen, bool bBlue, bool bAlpha)
+01317 {
+01318         glColorMask (bRed, bGreen, bBlue, bAlpha);
+01319 }
+01320 
+01321 
+01322 // --------------------------------------------------
+01323 
+01324 bool CDriverGL::swapBuffers()
+01325 {       
+01326         // Reset texture shaders
+01327         //resetTextureShaders();
+01328         // Reset VertexArrayRange.
+01329         if(_CurrentVertexBufferHard)
+01330         {
+01331                 // Then, we'll wait for this VBHard to finish before this frame. Even if some rendering done
+01332                 _CurrentVertexBufferHard->lock();
+01333                 _CurrentVertexBufferHard->unlock();
+01334                 // and we disable it.
+01335                 _CurrentVertexBufferHard->disable();
+01336         }
+01337 
+01338 
+01339         // Because of Bug with GeForce, must finishFence() for all VBHard.
+01340         set<IVertexBufferHardGL*>::iterator             itVBHard= _VertexBufferHardSet.Set.begin();
+01341         while(itVBHard != _VertexBufferHardSet.Set.end() )
+01342         {
+01343                 // Need only to do it for NVidia VB ones.
+01344                 if((*itVBHard)->NVidiaVertexBufferHard)
+01345                 {
+01346                         CVertexBufferHardGLNVidia       *vbHardNV= static_cast<CVertexBufferHardGLNVidia*>(*itVBHard);
+01347                         // If needed, "flush" these VB.
+01348                         vbHardNV->finishFence();
+01349                         vbHardNV->GPURenderingAfterFence= false;
+01350                 }
+01351                 itVBHard++;
+01352         }
+01353 
+01354         /* Yoyo: must do this (GeForce bug ??) esle weird results if end render with a VBHard.
+01355                 Setup a std vertex buffer to ensure NVidia synchronisation.
+01356         */
+01357         static  CVertexBuffer   dummyVB;
+01358         static  bool                    dummyVBinit= false;
+01359         if(!dummyVBinit)
+01360         {
+01361                 // setup a full feature VB (maybe not usefull ... :( ).
+01362                 dummyVB.setVertexFormat(CVertexBuffer::PositionFlag|CVertexBuffer::NormalFlag|
+01363                         CVertexBuffer::PrimaryColorFlag|CVertexBuffer::SecondaryColorFlag|
+01364                         CVertexBuffer::TexCoord0Flag|CVertexBuffer::TexCoord1Flag|
+01365                         CVertexBuffer::TexCoord2Flag|CVertexBuffer::TexCoord3Flag
+01366                         );
+01367                 // some vertices.
+01368                 dummyVB.setNumVertices(10);
+01369         }
+01370         // activate each frame to close VBHard rendering.
+01371         activeVertexBuffer(dummyVB);
+01372 
+01373 
+01374 #ifdef NL_OS_WINDOWS
+01375         if (_EventEmitter.getNumEmitters() > 1) // is direct input running ?
+01376         {
+01377                 // flush direct input messages if any
+01378                 NLMISC::safe_cast<NLMISC::CDIEventEmitter *>(_EventEmitter.getEmitter(1))->poll();
+01379         }
+01380 #endif
+01381 
+01382 
+01383 #ifdef NL_OS_WINDOWS
+01384         SwapBuffers(_hDC);
+01385 #else // NL_OS_WINDOWS
+01386         glXSwapBuffers(dpy, win);
+01387 #endif // NL_OS_WINDOWS
+01388 
+01389         // Activate the default texture environnments for all stages.
+01390         //===========================================================
+01391         // This is not a requirement, but it ensure a more stable state each frame.
+01392         // (well, maybe the good reason is "it hides much more the bugs"  :o) ).
+01393         for(sint stage=0;stage<inlGetNumTextStages(); stage++)
+01394         {
+01395                 // init no texture.
+01396                 _CurrentTexture[stage]= NULL;
+01397                 _CurrentTextureInfoGL[stage]= NULL;
+01398                 // texture are disabled in DriverGLStates.forceDefaults().
+01399                 
+01400                 // init default env.
+01401                 CMaterial::CTexEnv      env;    // envmode init to default.
+01402                 env.ConstantColor.set(255,255,255,255);
+01403                 forceActivateTexEnvMode(stage, env);
+01404                 forceActivateTexEnvColor(stage, env);
+01405         }
+01406         
+01407 
+01408         // Activate the default material.
+01409         //===========================================================
+01410         // Same reasoning as textures :)
+01411         _DriverGLStates.forceDefaults(inlGetNumTextStages());
+01412         if (_NVTextureShaderEnabled)
+01413         {
+01414                 glDisable(GL_TEXTURE_SHADER_NV);
+01415                 _NVTextureShaderEnabled = false;
+01416         }
+01417         _CurrentMaterial= NULL;
+01418 
+01419 
+01420         // Reset the profiling counter.
+01421         _PrimitiveProfileIn.reset();
+01422         _PrimitiveProfileOut.reset();
+01423         _NbSetupMaterialCall= 0;
+01424         _NbSetupModelMatrixCall= 0;
+01425 
+01426         // Reset the texture set
+01427         _TextureUsed.clear();
+01428 
+01429         return true;
+01430 }
+01431 
+01432 // --------------------------------------------------
+01433 
+01434 bool CDriverGL::release()
+01435 {
+01436         // release only if the driver was initialized
+01437         if (!_Initialized) return true;
+01438 
+01439         // Call IDriver::release() before, to destroy textures, shaders and VBs...
+01440         IDriver::release();
+01441 
+01442         // release caustic cube map
+01443 //      _CauticCubeMap = NULL;
+01444 
+01445         // Reset VertexArrayRange.
+01446         resetVertexArrayRange();
+01447 
+01448         // delete containers
+01449         delete _AGPVertexArrayRange;
+01450         delete _VRAMVertexArrayRange;
+01451         _AGPVertexArrayRange= NULL;
+01452         _VRAMVertexArrayRange= NULL;
+01453 
+01454 #ifdef NL_OS_WINDOWS
+01455         // Then delete.
+01456         // wglMakeCurrent(NULL,NULL);
+01457 
+01458         // Off-screen rendering ?
+01459         if (_OffScreen)
+01460         {
+01461                 if (_PBuffer)
+01462                 {
+01463                         wglDeleteContext( _hRC );
+01464                         wglReleasePbufferDCARB( _PBuffer, _hDC );
+01465                         wglDestroyPbufferARB( _PBuffer );
+01466                 }
+01467         }
+01468         else
+01469         {
+01470                 if (_hRC)
+01471                         wglDeleteContext(_hRC);
+01472                 if (_hWnd&&_hDC)
+01473                 {
+01474                         ReleaseDC(_hWnd,_hDC);
+01475                         if (_DestroyWindow)
+01476                                 DestroyWindow (_hWnd);
+01477                 }
+01478 
+01479                 if(_FullScreen)
+01480                 {
+01481                         ChangeDisplaySettings(&_OldScreenMode, 0);
+01482                         _FullScreen= false;
+01483                 }
+01484         }
+01485 
+01486         _hRC=NULL;
+01487         _hDC=NULL;
+01488         _hWnd=NULL;
+01489         _PBuffer = NULL;
+01490 
+01491         // Restaure monitor color parameters
+01492         if (_NeedToRestaureGammaRamp)
+01493         {
+01494                 HDC dc = CreateDC ("DISPLAY", NULL, NULL, NULL);
+01495                 if (dc)
+01496                 {
+01497                         if (!SetDeviceGammaRamp (dc, _GammaRampBackuped))
+01498                                 nlwarning ("(CDriverGL::release): SetDeviceGammaRamp failed");
+01499 
+01500                         // Release the DC
+01501                         ReleaseDC (NULL, dc);
+01502                 }
+01503                 else
+01504                 {
+01505                         nlwarning ("(CDriverGL::release): can't create DC");
+01506                 }
+01507         }
+01508 
+01509 #elif defined (NL_OS_UNIX)// NL_OS_WINDOWS
+01510  
+01511 #ifdef XF86VIDMODE
+01512         if(_FullScreen)
+01513         {
+01514                 XF86VidModeModeInfo info;
+01515                 nlinfo("Switching back to original mode \n");
+01516  
+01517                 // This is a bit ugly - a quick hack to copy the ModeLine structure 
+01518                 // into the modeInfo structure.
+01519                 memcpy((XF86VidModeModeLine *)((char *)&info + sizeof(info.dotclock)),&_OldScreenMode, sizeof(XF86VidModeModeLine));
+01520                 info.dotclock = _OldDotClock;
+01521  
+01522                 nlinfo("Mode is %dx%d,\n",info.hdisplay,info.vdisplay);
+01523                 XF86VidModeSwitchToMode(dpy,DefaultScreen(dpy),&info);
+01524                 nlinfo("Switching viewporr to %d,%d,\n",_OldX, _OldY);
+01525                 XF86VidModeSetViewPort(dpy,DefaultScreen(dpy),_OldX,_OldY);
+01526                 // Ungrab the keyboard (probably not necessary);
+01527                 XUngrabKeyboard(dpy, CurrentTime);
+01528         }
+01529 #endif // XF86VIDMODE
+01530 
+01531 #endif // NL_OS_UNIX
+01532 
+01533 
+01534         // released
+01535         _Initialized= false;
+01536 
+01537         return true;
+01538 }
+01539 
+01540 // --------------------------------------------------
+01541 
+01542 IDriver::TMessageBoxId  CDriverGL::systemMessageBox (const char* message, const char* title, IDriver::TMessageBoxType type, TMessageBoxIcon icon)
+01543 {
+01544 #ifdef NL_OS_WINDOWS
+01545         switch (::MessageBox (NULL, message, title, ((type==retryCancelType)?MB_RETRYCANCEL:
+01546                                                                                 (type==yesNoCancelType)?MB_YESNOCANCEL:
+01547                                                                                 (type==okCancelType)?MB_OKCANCEL:
+01548                                                                                 (type==abortRetryIgnoreType)?MB_ABORTRETRYIGNORE:
+01549                                                                                 (type==yesNoType)?MB_YESNO|MB_ICONQUESTION:MB_OK)|
+01550                                                                                 
+01551                                                                                 ((icon==handIcon)?MB_ICONHAND:
+01552                                                                                 (icon==questionIcon)?MB_ICONQUESTION:
+01553                                                                                 (icon==exclamationIcon)?MB_ICONEXCLAMATION:
+01554                                                                                 (icon==asteriskIcon)?MB_ICONASTERISK:
+01555                                                                                 (icon==warningIcon)?MB_ICONWARNING:
+01556                                                                                 (icon==errorIcon)?MB_ICONERROR:
+01557                                                                                 (icon==informationIcon)?MB_ICONINFORMATION:
+01558                                                                                 (icon==stopIcon)?MB_ICONSTOP:0)))
+01559                                                                                 {
+01560                                                                                         case IDOK:
+01561                                                                                                 return okId;
+01562                                                                                         case IDCANCEL:
+01563                                                                                                 return cancelId;
+01564                                                                                         case IDABORT:
+01565                                                                                                 return abortId;
+01566                                                                                         case IDRETRY:
+01567                                                                                                 return retryId;
+01568                                                                                         case IDIGNORE:
+01569                                                                                                 return ignoreId;
+01570                                                                                         case IDYES:
+01571                                                                                                 return yesId;
+01572                                                                                         case IDNO:
+01573                                                                                                 return noId;
+01574                                                                                 }
+01575         nlstop;
+01576 #else // NL_OS_WINDOWS
+01577         // Call the console version!
+01578         IDriver::systemMessageBox (message, title, type, icon);
+01579 #endif // NL_OS_WINDOWS
+01580         return okId;
+01581 }
+01582 
+01583 // --------------------------------------------------
+01584 
+01585 void CDriverGL::setupViewport (const class CViewport& viewport)
+01586 {
+01587 #ifdef NL_OS_WINDOWS
+01588         if (_hWnd == NULL) return;
+01589 
+01590         // Setup gl viewport
+01591         int clientWidth = _WindowWidth;
+01592         int clientHeight = _WindowHeight;
+01593 
+01594 #else // NL_OS_WINDOWS
+01595 
+01596         XWindowAttributes win_attributes;
+01597         if (!XGetWindowAttributes(dpy, win, &win_attributes))
+01598                 throw EBadDisplay("Can't get window attributes.");
+01599 
+01600         // Setup gl viewport
+01601         int clientWidth=win_attributes.width;
+01602         int clientHeight=win_attributes.height;
+01603 
+01604 #endif // NL_OS_WINDOWS
+01605 
+01606         // Get viewport
+01607         float x;
+01608         float y;
+01609         float width;
+01610         float height;
+01611         viewport.getValues (x, y, width, height);
+01612 
+01613         // Setup gl viewport
+01614         int ix=(int)((float)clientWidth*x);
+01615         clamp (ix, 0, clientWidth);
+01616         int iy=(int)((float)clientHeight*y);
+01617         clamp (iy, 0, clientHeight);
+01618         int iwidth=(int)((float)clientWidth*width);
+01619         clamp (iwidth, 0, clientWidth-ix);
+01620         int iheight=(int)((float)clientHeight*height);
+01621         clamp (iheight, 0, clientHeight-iy);
+01622         glViewport (ix, iy, iwidth, iheight);
+01623 }
+01624 
+01625 
+01626 
+01627 // --------------------------------------------------
+01628 void    CDriverGL::setupScissor (const class CScissor& scissor)
+01629 {
+01630         // Get viewport
+01631         float x= scissor.X;
+01632         float width= scissor.Width;
+01633         float height= scissor.Height;
+01634 
+01635         if(x==0 && x==0 && width==1 && height==1)
+01636         {
+01637                 glDisable(GL_SCISSOR_TEST);
+01638         }
+01639         else
+01640         {
+01641 #ifdef NL_OS_WINDOWS
+01642 
+01643                 float y= scissor.Y;
+01644 
+01645                 if (_hWnd)
+01646                 {
+01647                         // Get window rect
+01648                         int clientWidth = _WindowWidth;
+01649                         int clientHeight = _WindowHeight;
+01650 
+01651                         // Setup gl scissor
+01652                         int ix0=(int)floor((float)clientWidth * x + 0.5f);
+01653                         clamp (ix0, 0, clientWidth);
+01654                         int iy0=(int)floor((float)clientHeight* y + 0.5f);
+01655                         clamp (iy0, 0, clientHeight);
+01656 
+01657                         int ix1=(int)floor((float)clientWidth * (x+width) + 0.5f );
+01658                         clamp (ix1, 0, clientWidth);
+01659                         int iy1=(int)floor((float)clientHeight* (y+height) + 0.5f );
+01660                         clamp (iy1, 0, clientHeight);
+01661 
+01662 
+01663                         int iwidth= ix1 - ix0;
+01664                         clamp (iwidth, 0, clientWidth);
+01665                         int iheight= iy1 - iy0;
+01666                         clamp (iheight, 0, clientHeight);
+01667 
+01668                         glScissor (ix0, iy0, iwidth, iheight);
+01669                         glEnable(GL_SCISSOR_TEST);
+01670                 }
+01671 #endif // NL_OS_WINDOWS
+01672         }
+01673 }
+01674 
+01675 
+01676 
+01677 // --------------------------------------------------
+01678 
+01679 void CDriverGL::showCursor(bool b)
+01680 {
+01681 #ifdef NL_OS_WINDOWS
+01682         ShowCursor(b);
+01683 #elif defined (NL_OS_UNIX)
+01684 
+01685         if (b)
+01686         {
+01687                 if (cursor != None)
+01688                 {
+01689                         XFreeCursor(dpy, cursor);
+01690                         cursor = None;
+01691                 }
+01692                 XUndefineCursor(dpy, win);
+01693         }
+01694         else
+01695         {
+01696                 if (cursor == None)
+01697                 {
+01698                         char bm_no_data[] = { 0,0,0,0, 0,0,0,0 };
+01699                         Pixmap pixmap_no_data = XCreateBitmapFromData (dpy, win, bm_no_data, 8, 8);
+01700                         XColor black;
+01701                         memset(&black, 0, sizeof (XColor));
+01702                         black.flags = DoRed | DoGreen | DoBlue;
+01703                         cursor = XCreatePixmapCursor (dpy, pixmap_no_data, pixmap_no_data, &black, &black, 0, 0);
+01704                         XFreePixmap(dpy, pixmap_no_data);
+01705                 }
+01706                 XDefineCursor(dpy, win, cursor);
+01707         }
+01708 #endif // NL_OS_UNIX
+01709 }
+01710 
+01711 
+01712 // --------------------------------------------------
+01713 
+01714 void CDriverGL::setMousePos(float x, float y)
+01715 {
+01716 #ifdef NL_OS_WINDOWS
+01717         if (_hWnd)
+01718         {
+01719                 // NeL window coordinate to MSWindows coordinates
+01720                 POINT pt;
+01721                 pt.x = (int)((float)(_WindowWidth)*x);
+01722                 pt.y = (int)((float)(_WindowHeight)*(1.0f-y));
+01723                 ClientToScreen (_hWnd, &pt);
+01724                 SetCursorPos(pt.x, pt.y);
+01725         }
+01726 #elif defined (NL_OS_UNIX)
+01727         XWindowAttributes xwa;
+01728         XGetWindowAttributes (dpy, win, &xwa);
+01729         int x1 = (int)(x * (float) xwa.width);
+01730         int y1 = (int)((1.0f - y) * (float) xwa.height);
+01731         XWarpPointer (dpy, None, win, None, None, None, None, x1, y1);
+01732 #endif // NL_OS_UNIX
+01733 }
+01734 
+01735 
+01736 void CDriverGL::getWindowSize(uint32 &width, uint32 &height)
+01737 {
+01738 #ifdef NL_OS_WINDOWS
+01739         // Off-srceen rendering ?
+01740         if (_OffScreen)
+01741         {
+01742                 if (_PBuffer)
+01743                 {
+01744                         wglQueryPbufferARB( _PBuffer, WGL_PBUFFER_WIDTH_ARB, (int*)&width );
+01745                         wglQueryPbufferARB( _PBuffer, WGL_PBUFFER_HEIGHT_ARB, (int*)&height );
+01746                 }
+01747         }
+01748         else
+01749         {
+01750                 if (_hWnd)
+01751                 {
+01752                         width = (uint32)(_WindowWidth);
+01753                         height = (uint32)(_WindowHeight);
+01754                 }
+01755         }
+01756 #elif defined (NL_OS_UNIX)
+01757         XWindowAttributes xwa;
+01758         XGetWindowAttributes (dpy, win, &xwa);
+01759         width = (uint32) xwa.width;
+01760         height = (uint32) xwa.height;
+01761 #endif // NL_OS_UNIX
+01762 }
+01763 
+01764 // --------------------------------------------------
+01765 
+01766 bool CDriverGL::isActive()
+01767 {
+01768 #ifdef NL_OS_WINDOWS
+01769         return (IsWindow(_hWnd) != 0);
+01770 #elif defined (NL_OS_UNIX)
+01771         return true;
+01772 #endif // NL_OS_UNIX
+01773 }
+01774 
+01775 uint8 CDriverGL::getBitPerPixel ()
+01776 {
+01777         return _Depth;
+01778 }
+01779 
+01780 const char *CDriverGL::getVideocardInformation ()
+01781 {
+01782         static char name[1024];
+01783 
+01784         if (!_Initialized) return "OpenGL isn't initialized";
+01785 
+01786         const char *vendor = (const char *) glGetString (GL_VENDOR);
+01787         const char *renderer = (const char *) glGetString (GL_RENDERER);
+01788         const char *version = (const char *) glGetString (GL_VERSION);
+01789 
+01790         smprintf(name, 1024, "%s / %s / %s", vendor, renderer, version);
+01791         return name;
+01792 }
+01793 
+01794 
+01795 void CDriverGL::setCapture (bool b)
+01796 {
+01797 #ifdef NL_OS_WINDOWS
+01798 
+01799         if (b)
+01800         {
+01801                 RECT client;
+01802                 GetClientRect (_hWnd, &client);
+01803                 POINT pt1,pt2;
+01804                 pt1.x = client.left;
+01805                 pt1.y = client.top;
+01806                 ClientToScreen (_hWnd, &pt1);
+01807                 pt2.x = client.right;
+01808                 pt2.y = client.bottom;
+01809                 ClientToScreen (_hWnd, &pt2);
+01810                 client.bottom = pt2.y;
+01811                 client.top = pt1.y;
+01812                 client.left = pt1.x;
+01813                 client.right = pt2.x;
+01814                 ClipCursor (&client);
+01815         }
+01816         else
+01817                 ClipCursor (NULL);
+01818 
+01819         /*
+01820         if (b)
+01821                 SetCapture (_hWnd);
+01822         else
+01823                 ReleaseCapture ();
+01824         */
+01825 
+01826 #elif defined (NL_OS_UNIX)
+01827 
+01828 #endif // NL_OS_UNIX
+01829 }
+01830 
+01831 
+01832 bool                    CDriverGL::clipRect(NLMISC::CRect &rect)
+01833 {
+01834         // Clip the wanted rectangle with window.
+01835         uint32 width, height;
+01836         getWindowSize(width, height);
+01837 
+01838         sint32  xr=rect.right() ,yr=rect.bottom();
+01839         
+01840         clamp((sint32&)rect.X, (sint32)0, (sint32)width);
+01841         clamp((sint32&)rect.Y, (sint32)0, (sint32)height);
+01842         clamp((sint32&)xr, (sint32)rect.X, (sint32)width);
+01843         clamp((sint32&)yr, (sint32)rect.Y, (sint32)height);
+01844         rect.Width= xr-rect.X;
+01845         rect.Height= yr-rect.Y;
+01846 
+01847         return rect.Width>0 && rect.Height>0;
+01848 }
+01849 
+01850 
+01851 
+01852 void                    CDriverGL::getBufferPart (CBitmap &bitmap, NLMISC::CRect &rect)
+01853 {
+01854         bitmap.reset();
+01855 
+01856         if(clipRect(rect))
+01857         {
+01858                 bitmap.resize(rect.Width, rect.Height, CBitmap::RGBA);
+01859                 vector<uint8> &d = bitmap.getPixels ();
+01860                 glReadPixels (rect.X, rect.Y, rect.Width, rect.Height, GL_RGBA, GL_UNSIGNED_BYTE, &(d[0]));
+01861         }
+01862 }
+01863 
+01864 
+01865 void                    CDriverGL::getZBufferPart (std::vector<float>  &zbuffer, NLMISC::CRect &rect)
+01866 {
+01867         zbuffer.clear();
+01868 
+01869         if(clipRect(rect))
+01870         {
+01871                 zbuffer.resize(rect.Width*rect.Height);
+01872                 glPixelTransferf(GL_DEPTH_SCALE, 1.0f) ;
+01873                 glPixelTransferf(GL_DEPTH_BIAS, 0.f) ;
+01874                 glReadPixels (rect.X, rect.Y, rect.Width, rect.Height, GL_DEPTH_COMPONENT , GL_FLOAT, &(zbuffer[0]));
+01875         }
+01876 }
+01877 
+01878 
+01879 void                    CDriverGL::getZBuffer (std::vector<float>  &zbuffer)
+01880 {
+01881         CRect   rect(0,0);
+01882         getWindowSize(rect.Width, rect.Height);
+01883         getZBufferPart(zbuffer, rect);
+01884 }
+01885 
+01886 void CDriverGL::getBuffer (CBitmap &bitmap)
+01887 {
+01888         CRect   rect(0,0);
+01889         getWindowSize(rect.Width, rect.Height);
+01890         getBufferPart(bitmap, rect);
+01891 }
+01892 
+01893 bool CDriverGL::fillBuffer (CBitmap &bitmap)
+01894 {
+01895         CRect   rect(0,0);
+01896         getWindowSize(rect.Width, rect.Height);
+01897         if( rect.Width!=bitmap.getWidth() || rect.Height!=bitmap.getHeight() || bitmap.getPixelFormat()!=CBitmap::RGBA )
+01898                 return false;
+01899 
+01900         glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+01901         glDrawPixels (rect.Width, rect.Height, GL_RGBA, GL_UNSIGNED_BYTE, &(bitmap.getPixels()[0]) );
+01902 
+01903         return true;
+01904 }
+01905 
+01906 
+01907 void CDriverGL::copyFrameBufferToTexture(ITexture *tex,
+01908                                                                                  uint32 level,
+01909                                                                                  uint32 offsetx,
+01910                                                                                  uint32 offsety,
+01911                                                                                  uint32 x,
+01912                                                                                  uint32 y,
+01913                                                                                  uint32 width,
+01914                                                                                  uint32 height                                                                                                          
+01915                                                                                 )
+01916 {
+01917         nlassert(!tex->isTextureCube());
+01918         bool compressed = false;
+01919         getGlTextureFormat(*tex, compressed);
+01920         nlassert(!compressed);  
+01921         // first, mark the texture as valid, and make sure there is a corresponding texture in the device memory        
+01922         setupTexture(*tex);     
+01923         CTextureDrvInfosGL*     gltext = (CTextureDrvInfosGL*)(ITextureDrvInfos*)(tex->TextureDrvShare->DrvTexture);
+01924         _DriverGLStates.activeTextureARB(0);
+01925         // setup texture mode, after activeTextureARB()
+01926         _DriverGLStates.setTextureMode(CDriverGLStates::Texture2D);
+01927         glBindTexture(GL_TEXTURE_2D, gltext->ID);       
+01928         glCopyTexSubImage2D(GL_TEXTURE_2D, level, offsetx, offsety, x, y, width, height);       
+01929         // disable texturing.
+01930         _DriverGLStates.setTextureMode(CDriverGLStates::TextureDisabled);
+01931         _CurrentTexture[0] = NULL;
+01932         _CurrentTextureInfoGL[0] = NULL;
+01933 }
+01934 
+01935 
+01936 void CDriverGL::setPolygonMode (TPolygonMode mode)
+01937 {
+01938         IDriver::setPolygonMode (mode);
+01939 
+01940         // Set the polygon mode
+01941         switch (_PolygonMode)
+01942         {
+01943         case Filled:
+01944                 glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+01945                 break;
+01946         case Line:
+01947                 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+01948                 break;
+01949         case Point:
+01950                 glPolygonMode (GL_FRONT_AND_BACK, GL_POINT);
+01951                 break;
+01952         }
+01953 }
+01954 
+01955 
+01956 bool                    CDriverGL::fogEnabled()
+01957 {
+01958         return _FogEnabled;
+01959 }
+01960 
+01961 void                    CDriverGL::enableFog(bool enable)
+01962 {
+01963         _FogEnabled= enable;
+01964         if(enable)
+01965                 glEnable(GL_FOG);
+01966         else
+01967                 glDisable(GL_FOG);
+01968 }
+01969 
+01970 void                    CDriverGL::setupFog(float start, float end, CRGBA color)
+01971 {
+01972         glFogf(GL_FOG_MODE, GL_LINEAR);
+01973         glFogf(GL_FOG_START, start);
+01974         glFogf(GL_FOG_END, end);
+01975 
+01976         _CurrentFogColor[0]= color.R/255.0f;
+01977         _CurrentFogColor[1]= color.G/255.0f;
+01978         _CurrentFogColor[2]= color.B/255.0f;
+01979         _CurrentFogColor[3]= color.A/255.0f;
+01980 
+01981         glFogfv(GL_FOG_COLOR, _CurrentFogColor);
+01982 
+01985         if (_Extensions.EXTVertexShader && !_Extensions.NVVertexProgram)
+01986         {
+01987                 // register 96 is used to store fog informations
+01988                 if (start != end)
+01989                 {               
+01990                         setConstant(96, 1.f / (start - end), - end / (start - end), 0, 0);
+01991                 }
+01992                 else
+01993                 {
+01994                         setConstant(96, 0.f, 0, 0, 0);
+01995                 }
+01996         }
+01997 }
+01998 
+01999 
+02000 
+02001 // ***************************************************************************
+02002 void                    CDriverGL::profileRenderedPrimitives(CPrimitiveProfile &pIn, CPrimitiveProfile &pOut)
+02003 {
+02004         pIn= _PrimitiveProfileIn;
+02005         pOut= _PrimitiveProfileOut;
+02006 }
+02007 
+02008 
+02009 // ***************************************************************************
+02010 uint32                  CDriverGL::profileAllocatedTextureMemory()
+02011 {
+02012         return _AllocatedTextureMemory;
+02013 }
+02014 
+02015 
+02016 // ***************************************************************************
+02017 uint32                  CDriverGL::profileSetupedMaterials() const
+02018 {
+02019         return _NbSetupMaterialCall;
+02020 }
+02021 
+02022 
+02023 // ***************************************************************************
+02024 uint32                  CDriverGL::profileSetupedModelMatrix() const
+02025 {
+02026         return _NbSetupModelMatrixCall;
+02027 }
+02028 
+02029 
+02030 // ***************************************************************************
+02031 void                    CDriverGL::enableUsedTextureMemorySum (bool enable)
+02032 {
+02033         if (enable)
+02034                 nlinfo ("PERFORMANCE INFO: enableUsedTextureMemorySum has been set to true in CDriverGL\n");
+02035         _SumTextureMemoryUsed=enable;
+02036 }
+02037 
+02038 
+02039 // ***************************************************************************
+02040 uint32                  CDriverGL::getUsedTextureMemory() const
+02041 {
+02042         // Sum memory used
+02043         uint32 memory=0;
+02044 
+02045         // For each texture used
+02046         set<CTextureDrvInfosGL*>::iterator ite=_TextureUsed.begin();
+02047         while (ite!=_TextureUsed.end())
+02048         {
+02049                 // Get the gl texture
+02050                 CTextureDrvInfosGL*     gltext;
+02051                 gltext= (*ite);
+02052 
+02053                 // Sum the memory used by this texture
+02054                 memory+=gltext->TextureMemory;
+02055 
+02056                 // Next texture
+02057                 ite++;
+02058         }
+02059 
+02060         // Return the count
+02061         return memory;
+02062 }
+02063 
+02064 
+02065 // ***************************************************************************
+02066 bool CDriverGL::supportTextureShaders() const
+02067 {
+02068         // fully supported by NV_TEXTURE_SHADER 
+02069         return _Extensions.NVTextureShader;
+02070 }
+02071 
+02072 // ***************************************************************************
+02073 bool CDriverGL::isTextureAddrModeSupported(CMaterial::TTexAddressingMode mode) const
+02074 {
+02075         if (_Extensions.NVTextureShader)
+02076         {
+02077                 // all the given addessing mode are supported with this extension
+02078                 return true;
+02079         }
+02080         else
+02081         {                       
+02082                 return false;
+02083         }
+02084 }
+02085 
+02086 // ***************************************************************************
+02087 void CDriverGL::setMatrix2DForTextureOffsetAddrMode(const uint stage, const float mat[4])
+02088 {
+02089         if (!supportTextureShaders()) return;
+02090         //nlassert(supportTextureShaders());
+02091         nlassert(stage < (uint) inlGetNumTextStages() )
+02092         _DriverGLStates.activeTextureARB(stage);
+02093         glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, mat);
+02094 }
+02095 
+02096 
+02097 // ***************************************************************************
+02098 void      CDriverGL::enableNVTextureShader(bool enabled)
+02099 {               
+02100         if (enabled != _NVTextureShaderEnabled)
+02101         {
+02102 
+02103                 if (enabled)
+02104                 {                                                       
+02105                         glEnable(GL_TEXTURE_SHADER_NV);                 
+02106                 }
+02107                 else
+02108                 {                                               
+02109                         glDisable(GL_TEXTURE_SHADER_NV);                
+02110                 }
+02111                 _NVTextureShaderEnabled = enabled;
+02112         }       
+02113 }
+02114 
+02115 // ***************************************************************************
+02116 void CDriverGL::checkForPerPixelLightingSupport()
+02117 {
+02118         // we need at least 3 texture stages and cube map support + EnvCombine4 or 3 support    
+02119         // TODO : support for EnvCombine3
+02120         // TODO : support for less than 3 stages
+02121 
+02122         _SupportPerPixelShaderNoSpec = (_Extensions.NVTextureEnvCombine4 /* || _Extensions.ATIXTextureEnvCombine3*/)
+02123                                                                    && _Extensions.ARBTextureCubeMap
+02124                                                                    && _Extensions.NbTextureStages >= 3
+02125                                                                    && (_Extensions.NVVertexProgram /* || _Extensions.EXTVertexShader*/);
+02126         
+02127         _SupportPerPixelShader = (_Extensions.NVTextureEnvCombine4 /*|| _Extensions.ATIXTextureEnvCombine3*/) 
+02128                                                          && _Extensions.ARBTextureCubeMap
+02129                                                          && _Extensions.NbTextureStages >= 2
+02130                                                          && (_Extensions.NVVertexProgram /*|| _Extensions.EXTVertexShader*/);   
+02131 }
+02132 
+02133 // ***************************************************************************
+02134 bool CDriverGL::supportPerPixelLighting(bool specular) const
+02135 {
+02136         return specular ? _SupportPerPixelShader : _SupportPerPixelShaderNoSpec;        
+02137 }
+02138 
+02139 // ***************************************************************************
+02140 void    CDriverGL::setPerPixelLightingLight(CRGBA diffuse, CRGBA specular, float shininess)
+02141 {
+02142         _PPLExponent = shininess;
+02143         _PPLightDiffuseColor = diffuse;
+02144         _PPLightSpecularColor = specular;
+02145 }
+02146 
+02147 // ***************************************************************************
+02148 NLMISC::IMouseDevice    *CDriverGL::enableLowLevelMouse(bool enable)
+02149 {
+02150         #ifdef NL_OS_WINDOWS
+02151                 if (_EventEmitter.getNumEmitters() < 2) return NULL;
+02152                 NLMISC::CDIEventEmitter *diee = NLMISC::safe_cast<CDIEventEmitter *>(_EventEmitter.getEmitter(1));              
+02153                 if (enable)
+02154                 {
+02155                         try
+02156                         {
+02157                                 NLMISC::IMouseDevice *md = diee->getMouseDevice();                              
+02158                                 return md;
+02159                         }
+02160                         catch (EDirectInput &)
+02161                         {
+02162                                 return NULL;
+02163                         }
+02164                 }
+02165                 else
+02166                 {
+02167                         diee->releaseMouse();                   
+02168                         return NULL;
+02169                 }
+02170         #else
+02171                 return NULL;
+02172         #endif
+02173 }
+02174                 
+02175 // ***************************************************************************
+02176 NLMISC::IKeyboardDevice         *CDriverGL::enableLowLevelKeyboard(bool enable)
+02177 {
+02178         #ifdef NL_OS_WINDOWS
+02179                 if (_EventEmitter.getNumEmitters() < 2) return NULL;
+02180                 NLMISC::CDIEventEmitter *diee = NLMISC::safe_cast<NLMISC::CDIEventEmitter *>(_EventEmitter.getEmitter(1));
+02181                 if (enable)
+02182                 {
+02183                         try
+02184                         {
+02185                                 NLMISC::IKeyboardDevice *md = diee->getKeyboardDevice();
+02186                                 return md;
+02187                         }
+02188                         catch (EDirectInput &)
+02189                         {
+02190                                 return NULL;
+02191                         }
+02192                 }
+02193                 else
+02194                 {
+02195                         diee->releaseKeyboard();
+02196                         return NULL;
+02197                 }
+02198         #else
+02199                 return NULL;
+02200         #endif
+02201 }
+02202 
+02203 // ***************************************************************************
+02204 NLMISC::IInputDeviceManager             *CDriverGL::getLowLevelInputDeviceManager()
+02205 {
+02206         #ifdef NL_OS_WINDOWS
+02207                 if (_EventEmitter.getNumEmitters() < 2) return NULL;
+02208                 NLMISC::CDIEventEmitter *diee = NLMISC::safe_cast<NLMISC::CDIEventEmitter *>(_EventEmitter.getEmitter(1));
+02209                 return diee;
+02210         #else
+02211                 return NULL;
+02212         #endif
+02213 }
+02214 
+02215 // ***************************************************************************
+02216 bool                    CDriverGL::supportBlendConstantColor() const
+02217 {
+02218         return _Extensions.EXTBlendColor;
+02219 }
+02220 // ***************************************************************************
+02221 void                    CDriverGL::setBlendConstantColor(NLMISC::CRGBA col)
+02222 {
+02223         // bkup
+02224         _CurrentBlendConstantColor= col;
+02225 
+02226         // update GL
+02227         if(!_Extensions.EXTBlendColor)
+02228                 return;
+02229         static const    float   OO255= 1.0f/255;
+02230         nglBlendColorEXT(col.R*OO255, col.G*OO255, col.B*OO255, col.A*OO255);
+02231 }
+02232 // ***************************************************************************
+02233 NLMISC::CRGBA   CDriverGL::getBlendConstantColor() const
+02234 {
+02235         return  _CurrentBlendConstantColor;
+02236 }
+02237 
+02238 // ***************************************************************************
+02239 sint                    CDriverGL::getNbTextureStages() const
+02240 {
+02241         return inlGetNumTextStages();
+02242 }
+02243 
+02244 
+02245 // ***************************************************************************
+02246 void CDriverGL::refreshProjMatrixFromGL()
+02247 {
+02248         if (!_ProjMatDirty) return;     
+02249         float mat[16];
+02250         glGetFloatv(GL_PROJECTION_MATRIX, mat);
+02251         _GLProjMat.set(mat);    
+02252         _ProjMatDirty = false;
+02253 }
+02254 
+02255 
+02256 // ***************************************************************************
+02257 bool                    CDriverGL::setMonitorColorProperties (const CMonitorColorProperties &properties)
+02258 {
+02259 #ifdef NL_OS_WINDOWS
+02260         
+02261         // Get a DC
+02262         HDC dc = CreateDC ("DISPLAY", NULL, NULL, NULL);
+02263         if (dc)
+02264         {
+02265                 // The ramp
+02266                 WORD ramp[256*3];
+02267 
+02268                 // For each composant
+02269                 uint c;
+02270                 for( c=0; c<3; c++ )
+02271                 {
+02272                         uint i;
+02273                         for( i=0; i<256; i++ )
+02274                         {
+02275                                 // Floating value
+02276                                 float value = (float)i / 256;
+02277 
+02278                                 // Contrast
+02279                                 value = (float) max (0.0f, (value-0.5f) * (float) pow (3.f, properties.Contrast[c]) + 0.5f );
+02280 
+02281                                 // Gamma
+02282                                 value = (float) pow (value, (properties.Gamma[c]>0) ? 1 - 3 * properties.Gamma[c] / 4 : 1 - properties.Gamma[c] );
+02283 
+02284                                 // Luminosity
+02285                                 value = value + properties.Luminosity[c] / 2.f;
+02286                                 ramp[i+(c<<8)] = min (65535, max (0, (int)(value * 65535)));
+02287                         }
+02288                 }
+02289 
+02290                 // Set the ramp
+02291                 bool result = SetDeviceGammaRamp (dc, ramp) != FALSE;
+02292                 
+02293                 // Release the DC
+02294                 ReleaseDC (NULL, dc);
+02295 
+02296                 // Returns result
+02297                 return result;
+02298         }
+02299         else
+02300         {
+02301                 nlwarning ("(CDriverGL::setMonitorColorProperties): can't create DC");
+02302                 return false;
+02303         }
+02304 
+02305 #else
+02306 
+02307         nlwarning ("CDriverGL::setMonitorColorProperties not implemented");
+02308         return false;
+02309 
+02310 #endif
+02311 }
+02312 
+02313 // ***************************************************************************
+02314 bool CDriverGL::supportEMBM() const
+02315 {
+02316         // For now, supported via ATI extension
+02317         return _Extensions.ATIEnvMapBumpMap;
+02318 }
+02319 
+02320 // ***************************************************************************
+02321 bool CDriverGL::isEMBMSupportedAtStage(uint stage) const
+02322 {
+02323         nlassert(supportEMBM());
+02324         nlassert(stage < IDRV_MAT_MAXTEXTURES)
+02325         return _StageSupportEMBM[stage];
+02326 
+02327 }
+02328 
+02329 // ***************************************************************************
+02330 void CDriverGL::setEMBMMatrix(const uint stage,const float mat[4])
+02331 {
+02332         nlassert(supportEMBM());
+02333         nlassert(stage < IDRV_MAT_MAXTEXTURES);
+02334         // 
+02335         if (_Extensions.ATIEnvMapBumpMap)
+02336         {
+02337                 _DriverGLStates.activeTextureARB(stage);
+02338                 nglTexBumpParameterfvATI(GL_BUMP_ROT_MATRIX_ATI, const_cast<float *>(mat));
+02339         }
+02340 }
+02341 
+02342 // ***************************************************************************
+02343 void CDriverGL::initEMBM()
+02344 {
+02345         if (supportEMBM())
+02346         {       
+02347                 std::fill(_StageSupportEMBM, _StageSupportEMBM + IDRV_MAT_MAXTEXTURES, false);
+02348                 if (_Extensions.ATIEnvMapBumpMap)
+02349                 {               
+02350                         // Test which stage support EMBM
+02351                         GLint numEMBMUnits;
+02352                         nglGetTexBumpParameterivATI(GL_BUMP_NUM_TEX_UNITS_ATI, &numEMBMUnits);
+02353                         std::vector<GLint> EMBMUnits(numEMBMUnits);
+02354                         // get array of units that supports EMBM
+02355                         nglGetTexBumpParameterivATI(GL_BUMP_TEX_UNITS_ATI, &EMBMUnits[0]);
+02356                         uint k;
+02357                         for(k = 0; k < (EMBMUnits.size() - 1); ++k)
+02358                         {
+02359                                 uint stage = EMBMUnits[k] - GL_TEXTURE0_ARB;
+02360                                 if (stage < (IDRV_MAT_MAXTEXTURES - 1))
+02361                                 {
+02362                                         _StageSupportEMBM[k] = true;
+02363                                 }               
+02364                         } 
+02365                         // setup each stage to apply the bump map to the next stage
+02366                         for(k = 0; k < IDRV_MAT_MAXTEXTURES - 1; ++k)
+02367                         {
+02368                                 if (_StageSupportEMBM[k])
+02369                                 {       
+02370                                         // setup each stage so that it apply EMBM on the next stage
+02371                                         _DriverGLStates.activeTextureARB(k);
+02372                                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);   
+02373                                         glTexEnvi(GL_TEXTURE_ENV, GL_BUMP_TARGET_ATI, GL_TEXTURE0_ARB + k + 1);                         
+02374                                 }
+02375                         }
+02376                         _DriverGLStates.activeTextureARB(0);
+02377                 }
+02378         }
+02379 }
+02380 
+02381 } // NL3D
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1