# 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