1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010 Robert TIMM (rti) <mail@rtti.de>
6 // Copyright (C) 2013-2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "stdopengl.h"
22 #include "driver_opengl.h"
23 #include "driver_opengl_extension.h"
25 // by default, we disable the windows menu keys (F10, ALT and ALT+SPACE key doesn't freeze or open the menu)
26 #define NL_DISABLE_MENU
28 #include "nel/3d/viewport.h"
29 #include "nel/3d/scissor.h"
30 #include "nel/3d/u_driver.h"
31 #include "nel/3d/vertex_buffer.h"
32 #include "nel/3d/light.h"
33 #include "nel/3d/index_buffer.h"
34 #include "nel/misc/rect.h"
35 #include "nel/misc/hierarchical_timer.h"
36 #include "nel/misc/dynloadlib.h"
37 #include "driver_opengl_vertex_buffer_hard.h"
41 using namespace NLMISC
;
50 // ***************************************************************************
51 // try to allocate 16Mo by default of AGP Ram.
52 #define NL3D_DRV_VERTEXARRAY_AGP_INIT_SIZE (16384*1024)
56 // ***************************************************************************
61 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
,ULONG fdwReason
,LPVOID lpvReserved
)
63 if (fdwReason
== DLL_PROCESS_ATTACH
)
65 // Yoyo: Vianney change: don't need to call initDebug() anymore.
71 #endif /* NL_OS_WINDOWS */
75 class CDriverGLEsNelLibrary
: public INelLibrary
{
76 void onLibraryLoaded(bool firstTime
) { }
77 void onLibraryUnloaded(bool lastTime
) { }
79 NLMISC_DECL_PURE_LIB(CDriverGLEsNelLibrary
)
83 class CDriverGLNelLibrary
: public INelLibrary
{
84 void onLibraryLoaded(bool firstTime
) { }
85 void onLibraryUnloaded(bool lastTime
) { }
87 NLMISC_DECL_PURE_LIB(CDriverGLNelLibrary
)
91 #endif /* #ifndef NL_STATIC */
99 IDriver
* createGlEsDriverInstance ()
101 return new NLDRIVERGLES::CDriverGL
;
106 IDriver
* createGlDriverInstance ()
108 return new NLDRIVERGL::CDriverGL
;
120 __declspec(dllexport
) IDriver
* NL3D_createIDriverInstance ()
122 return new CDriverGL
;
125 __declspec(dllexport
) uint32
NL3D_interfaceVersion ()
127 return IDriver::InterfaceVersion
;
132 #elif defined (NL_OS_UNIX)
136 IDriver
* NL3D_createIDriverInstance ()
138 return new CDriverGL
;
141 uint32
NL3D_interfaceVersion ()
143 return IDriver::InterfaceVersion
;
147 #endif // NL_OS_WINDOWS
153 namespace NLDRIVERGLES
{
155 namespace NLDRIVERGL
{
159 CMaterial::CTexEnv
CDriverGL::_TexEnvReplace
;
163 uint
CDriverGL::_Registered
=0;
164 #endif // NL_OS_WINDOWS
166 // Version of the driver. Not the interface version!! Increment when implementation of the driver change.
167 const uint32
CDriverGL::ReleaseVersion
= 0x11;
169 // Number of register to allocate for the EXTVertexShader extension
170 const uint
CDriverGL::_EVSNumConstant
= 97;
172 GLenum
CDriverGL::NLCubeFaceToGLCubeFace
[6] =
174 GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
,
175 GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
,
176 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
,
177 GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
,
178 GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
,
179 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
182 // ***************************************************************************
183 CDriverGL::CDriverGL()
185 H_AUTO_OGL(CDriverGL_CDriverGL
)
193 #elif defined(NL_OS_WINDOWS)
199 #elif defined(NL_OS_MAC)
203 _backBufferHeight
= 0;
204 _backBufferWidth
= 0;
206 #elif defined (NL_OS_UNIX)
212 // zero the old screen mode
213 memset(&_OldScreenMode
, 0, sizeof(_OldScreenMode
));
214 # endif //XF86VIDMODE
218 _ColorDepth
= ColorDepth32
;
220 _DefaultCursor
= EmptyCursor
;
221 _BlankCursor
= EmptyCursor
;
223 _AlphaBlendedCursorSupported
= false;
224 _AlphaBlendedCursorSupportRetrieved
= false;
225 _CurrCol
= CRGBA::White
;
230 _MouseCaptured
= false;
232 _NeedToRestoreGammaRamp
= false;
238 _WindowVisible
= true;
239 _DestroyWindow
= false;
242 _CurrentMode
.Width
= 0;
243 _CurrentMode
.Height
= 0;
244 _CurrentMode
.Depth
= 0;
245 _CurrentMode
.OffScreen
= false;
246 _CurrentMode
.Windowed
= true;
247 _CurrentMode
.AntiAlias
= -1;
252 _DecorationWidth
= 0;
253 _DecorationHeight
= 0;
255 _CurrentMaterial
=NULL
;
256 _Initialized
= false;
259 _FogEnd
= _FogStart
= 0.f
;
260 _CurrentFogColor
[0]= 0;
261 _CurrentFogColor
[1]= 0;
262 _CurrentFogColor
[2]= 0;
263 _CurrentFogColor
[3]= 0;
265 _LightSetupDirty
= false;
266 _ModelViewMatrixDirty
= false;
267 _RenderSetupDirty
= false;
268 // All lights default pos.
270 for(i
=0;i
<MaxLight
;i
++)
271 _LightDirty
[i
]= false;
273 _CurrentGlNormalize
= false;
274 _ForceNormalize
= false;
276 _AGPVertexArrayRange
= NULL
;
277 _VRAMVertexArrayRange
= NULL
;
278 _CurrentVertexArrayRange
= NULL
;
279 _CurrentVertexBufferHard
= NULL
;
280 _NVCurrentVARPtr
= NULL
;
281 _NVCurrentVARSize
= 0;
282 _SupportVBHard
= false;
283 _SlowUnlockVBHard
= false;
284 _MaxVerticesByVBHard
= 0;
286 _AllocatedTextureMemory
= 0;
288 _ForceDXTCCompression
= false;
289 _ForceTextureResizePower
= 0;
290 _ForceNativeFragmentPrograms
= true;
292 _SumTextureMemoryUsed
= false;
294 _NVTextureShaderEnabled
= false;
296 _AnisotropicFilter
= 0.f
;
298 // Compute the Flag which say if one texture has been changed in CMaterial.
299 _MaterialAllTextureTouchedFlag
= 0;
300 for(i
=0; i
< IDRV_MAT_MAXTEXTURES
; i
++)
302 _MaterialAllTextureTouchedFlag
|= IDRV_TOUCHED_TEX
[i
];
304 _CurrentTexAddrMode
[i
] = GL_NONE
;
306 _CurrentTexAddrMode
[i
] = 0;
310 _UserTexMatEnabled
= 0;
313 _LastVertexSetupIsLightMap
= false;
314 for(i
=0; i
< IDRV_MAT_MAXTEXTURES
; i
++)
315 _LightMapUVMap
[i
]= -1;
316 // reserve enough space to never reallocate, nor test for reallocation.
317 _LightMapLUT
.resize(NL3D_DRV_MAX_LIGHTMAP
);
318 // must set replace for alpha part.
319 _LightMapLastStageEnv
.Env
.OpAlpha
= CMaterial::Replace
;
320 _LightMapLastStageEnv
.Env
.SrcArg0Alpha
= CMaterial::Texture
;
321 _LightMapLastStageEnv
.Env
.OpArg0Alpha
= CMaterial::SrcAlpha
;
323 _ProjMatDirty
= true;
325 std::fill(_StageSupportEMBM
, _StageSupportEMBM
+ IDRV_MAT_MAXTEXTURES
, false);
327 ATIWaterShaderHandleNoDiffuseMap
= 0;
328 ATIWaterShaderHandle
= 0;
329 ATICloudShaderHandle
= 0;
331 _ATIDriverVersion
= 0;
332 _ATIFogRangeFixed
= true;
334 std::fill(ARBWaterShader
, ARBWaterShader
+ 4, 0);
336 /// buildCausticCubeMapTex();
338 _SpecularBatchOn
= false;
340 _PolygonSmooth
= false;
342 _VBHardProfiling
= false;
343 _CurVBHardLockCount
= 0;
344 _NumVBHardProfileFrame
= 0;
346 _TexEnvReplace
.setDefault();
347 _TexEnvReplace
.Env
.OpAlpha
= CMaterial::Previous
;
348 _TexEnvReplace
.Env
.OpRGB
= CMaterial::Previous
;
352 _CurrentOcclusionQuery
= NULL
;
353 _SwapBufferCounter
= 0;
355 _LightMapDynamicLightEnabled
= false;
356 _LightMapDynamicLightDirty
= false;
358 _CurrentMaterialSupportedShader
= CMaterial::Normal
;
360 // to avoid any problem if light0 never setted up, and ligthmap rendered
361 _UserLight0
.setupDirectional(CRGBA::Black
, CRGBA::White
, CRGBA::White
, CVector::K
);
363 _TextureTargetCubeFace
= 0;
364 _TextureTargetUpload
= false;
367 // ***************************************************************************
368 CDriverGL::~CDriverGL()
370 H_AUTO_OGL(CDriverGL_CDriverGLDtor
)
374 // --------------------------------------------------
375 bool CDriverGL::setupDisplay()
377 H_AUTO_OGL(CDriverGL_setupDisplay
)
381 // Retrieve the extensions for the current context.
382 registerGlExtensions (_Extensions
);
383 vector
<string
> lines
;
384 explode(_Extensions
.toString(), string("\n"), lines
);
385 for(uint i
= 0; i
< lines
.size(); i
++)
386 nlinfo("3D: %s", lines
[i
].c_str());
389 registerEGlExtensions(_Extensions
, _EglDisplay
);
390 #elif defined(NL_OS_WINDOWS)
391 registerWGlExtensions(_Extensions
, _hDC
);
392 #elif defined(NL_OS_MAC)
393 #elif defined(NL_OS_UNIX)
394 registerGlXExtensions(_Extensions
, _dpy
, DefaultScreen(_dpy
));
395 #endif // NL_OS_WINDOWS
397 // Check required extensions!!
398 // ARBMultiTexture is a OpenGL 1.2 required extension.
399 if(!_Extensions
.ARBMultiTexture
)
401 nlwarning("Missing Required GL extension: GL_ARB_multitexture. Update your driver");
402 throw EBadDisplay("Missing Required GL extension: GL_ARB_multitexture. Update your driver");
405 if(!_Extensions
.EXTTextureEnvCombine
)
407 nlwarning("Missing Important GL extension: GL_EXT_texture_env_combine => All envcombine are setup to GL_MODULATE!!!");
410 // Get num of light for this driver
412 glGetIntegerv (GL_MAX_LIGHTS
, &numLight
);
413 _MaxDriverLight
=(uint
)numLight
;
414 if (_MaxDriverLight
>MaxLight
)
415 _MaxDriverLight
=MaxLight
;
417 // All User Light are disabled by Default
419 for(i
=0;i
<MaxLight
;i
++)
420 _UserLightEnable
[i
]= false;
422 // init _DriverGLStates
423 _DriverGLStates
.init(_Extensions
.ARBTextureCubeMap
, (_Extensions
.NVTextureRectangle
|| _Extensions
.EXTTextureRectangle
|| _Extensions
.ARBTextureRectangle
), _MaxDriverLight
);
425 // Init OpenGL/Driver defaults.
426 //=============================
427 glViewport(0,0,_CurrentMode
.Width
,_CurrentMode
.Height
);
428 glMatrixMode(GL_PROJECTION
);
430 glOrtho(0,_CurrentMode
.Width
,_CurrentMode
.Height
,0,-1.0f
,1.0f
);
431 glMatrixMode(GL_MODELVIEW
);
434 glDisable(GL_AUTO_NORMAL
);
436 glDisable(GL_COLOR_MATERIAL
);
441 glDisable(GL_LINE_SMOOTH
);
443 glPolygonMode(GL_FRONT_AND_BACK
,GL_FILL
);
445 glEnable(GL_DEPTH_TEST
);
446 glDisable(GL_NORMALIZE
);
448 glDisable(GL_COLOR_SUM_EXT
);
451 _CurrViewport
.init(0.f
, 0.f
, 1.f
, 1.f
);
452 _CurrScissor
.initFullScreen();
453 _CurrentGlNormalize
= false;
454 _ForceNormalize
= false;
455 // Setup defaults for blend, lighting ...
456 _DriverGLStates
.forceDefaults(inlGetNumTextStages());
457 // Default delta camera pos.
458 _PZBCameraPos
= CVector::Null
;
460 if (_NVTextureShaderEnabled
)
462 enableNVTextureShader(false);
465 // Be always in EXTSeparateSpecularColor.
466 if(_Extensions
.EXTSeparateSpecularColor
)
469 glLightModeli((GLenum
)GL_LIGHT_MODEL_COLOR_CONTROL_EXT
, GL_SEPARATE_SPECULAR_COLOR_EXT
);
473 if (_Extensions
.ARBFragmentShader
)
475 _ForceNativeFragmentPrograms
= false;
478 _VertexProgramEnabled
= false;
479 _PixelProgramEnabled
= false;
480 _LastSetupGLArrayVertexProgram
= false;
482 // Init VertexArrayRange according to supported extenstion.
483 _SupportVBHard
= false;
484 _SlowUnlockVBHard
= false;
485 _MaxVerticesByVBHard
= 0;
487 // Try with ARB ext first.
488 if (_Extensions
.ARBVertexBufferObject
)
490 _AGPVertexArrayRange
= new CVertexArrayRangeARB(this);
491 _VRAMVertexArrayRange
= new CVertexArrayRangeARB(this);
492 _SupportVBHard
= true;
493 _MaxVerticesByVBHard
= std::numeric_limits
<uint32
>::max(); // cant' know the value..
496 // Next with NVidia ext
497 else if(_Extensions
.NVVertexArrayRange
)
499 _AGPVertexArrayRange
= new CVertexArrayRangeNVidia(this);
500 _VRAMVertexArrayRange
= new CVertexArrayRangeNVidia(this);
501 _SupportVBHard
= true;
502 _MaxVerticesByVBHard
= _Extensions
.NVVertexArrayRangeMaxVertex
;
504 else if(_Extensions
.ATITextureEnvCombine3
&& _Extensions
.ATIVertexArrayObject
)
507 // on Radeon 9200 and below : ATI_vertex_array_object is better (no direct access to AGP with ARB_vertex_buffer_object -> slow unlock)
508 // on Radeon 9500 and above : ARB_vertex_buffer_object is better
509 if (!_Extensions
.ATIMapObjectBuffer
)
511 _AGPVertexArrayRange
= new CVertexArrayRangeATI(this);
512 _VRAMVertexArrayRange
= new CVertexArrayRangeATI(this);
513 // BAD ATI extension scheme.
514 _SlowUnlockVBHard
= true;
518 _AGPVertexArrayRange
= new CVertexArrayRangeMapObjectATI(this);
519 _VRAMVertexArrayRange
= new CVertexArrayRangeMapObjectATI(this);
521 _SupportVBHard
= true;
522 // _MaxVerticesByVBHard= 65535; // should always work with recent drivers.
524 _MaxVerticesByVBHard
= 16777216;
528 // Reset VertexArrayRange.
529 _CurrentVertexArrayRange
= NULL
;
530 _CurrentVertexBufferHard
= NULL
;
531 _NVCurrentVARPtr
= NULL
;
532 _NVCurrentVARSize
= 0;
536 // try to allocate 16Mo by default of AGP Ram.
537 initVertexBufferHard(NL3D_DRV_VERTEXARRAY_AGP_INIT_SIZE
, 0);
539 // If not success to allocate at least a minimum space in AGP, then disable completely VBHard feature
540 if( _AGPVertexArrayRange
->sizeAllocated()==0 )
542 // reset any allocated VRAM space.
543 resetVertexArrayRange();
546 delete _AGPVertexArrayRange
;
547 delete _VRAMVertexArrayRange
;
548 _AGPVertexArrayRange
= NULL
;
549 _VRAMVertexArrayRange
= NULL
;
552 _SupportVBHard
= false;
553 _SlowUnlockVBHard
= false;
554 _MaxVerticesByVBHard
= 0;
558 // Init embm if present
559 //===========================================================
562 // Init fragment shaders if present
563 //===========================================================
564 initFragmentShaders();
566 // Activate the default texture environnments for all stages.
567 //===========================================================
568 for(uint stage
=0;stage
<inlGetNumTextStages(); stage
++)
571 _CurrentTexture
[stage
]= NULL
;
572 _CurrentTextureInfoGL
[stage
]= NULL
;
573 // texture are disabled in DriverGLStates.forceDefaults().
576 CMaterial::CTexEnv env
; // envmode init to default.
577 env
.ConstantColor
.set(255,255,255,255);
578 forceActivateTexEnvMode(stage
, env
);
579 forceActivateTexEnvColor(stage
, env
);
581 // Not special TexEnv.
582 _CurrentTexEnvSpecial
[stage
]= TexEnvSpecialDisabled
;
584 // set All TexGen by default to identity matrix (prefer use the textureMatrix scheme)
585 _DriverGLStates
.activeTextureARB(stage
);
588 params
[0]=1; params
[1]=0; params
[2]=0; params
[3]=0;
589 glTexGenfv(GL_S
, GL_OBJECT_PLANE
, params
);
590 glTexGenfv(GL_S
, GL_EYE_PLANE
, params
);
591 params
[0]=0; params
[1]=1; params
[2]=0; params
[3]=0;
592 glTexGenfv(GL_T
, GL_OBJECT_PLANE
, params
);
593 glTexGenfv(GL_T
, GL_EYE_PLANE
, params
);
594 params
[0]=0; params
[1]=0; params
[2]=1; params
[3]=0;
595 glTexGenfv(GL_R
, GL_OBJECT_PLANE
, params
);
596 glTexGenfv(GL_R
, GL_EYE_PLANE
, params
);
597 params
[0]=0; params
[1]=0; params
[2]=0; params
[3]=1;
598 glTexGenfv(GL_Q
, GL_OBJECT_PLANE
, params
);
599 glTexGenfv(GL_Q
, GL_EYE_PLANE
, params
);
603 resetTextureShaders();
606 _PPLightDiffuseColor
= NLMISC::CRGBA::White
;
607 _PPLightSpecularColor
= NLMISC::CRGBA::White
;
609 // Backward compatibility: default lighting is Light0 default openGL
610 // meaning that light direction is always (0,1,0) in eye-space
611 // use enableLighting(0....), to get normal behaviour
612 _DriverGLStates
.enableLight(0, true);
613 _LightMode
[0] = CLight::DirectionalLight
;
614 _WorldLightDirection
[0] = CVector::Null
;
618 _ForceDXTCCompression
= false;
619 _ForceTextureResizePower
= 0;
622 _AllocatedTextureMemory
= 0;
623 _TextureUsed
.clear();
624 _PrimitiveProfileIn
.reset();
625 _PrimitiveProfileOut
.reset();
626 _NbSetupMaterialCall
= 0;
627 _NbSetupModelMatrixCall
= 0;
629 // check whether per pixel lighting shader is supported
630 checkForPerPixelLightingSupport();
633 // if EXTVertexShader is used, bind the standard GL arrays, and allocate constant
634 if (!_Extensions
.NVVertexProgram
&& !_Extensions
.ARBVertexProgram
&& _Extensions
.EXTVertexShader
)
636 _EVSPositionHandle
= nglBindParameterEXT(GL_CURRENT_VERTEX_EXT
);
637 _EVSNormalHandle
= nglBindParameterEXT(GL_CURRENT_NORMAL
);
638 _EVSColorHandle
= nglBindParameterEXT(GL_CURRENT_COLOR
);
640 if (!_EVSPositionHandle
|| !_EVSNormalHandle
|| !_EVSColorHandle
)
642 nlwarning("Unable to bind input parameters for use with EXT_vertex_shader, vertex program support is disabled");
643 _Extensions
.EXTVertexShader
= false;
647 // bind texture units
648 for(uint k
= 0; k
< 8; ++k
)
650 _EVSTexHandle
[k
] = nglBindTextureUnitParameterEXT(GL_TEXTURE0_ARB
+ k
, GL_CURRENT_TEXTURE_COORDS
);
652 // Other attributes are managed using variant pointers :
657 // This mean that they must have 4 components
659 // Allocate invariants. One assitionnal variant is needed for fog coordinate if fog bug is not fixed in driver version
660 _EVSConstantHandle
= nglGenSymbolsEXT(GL_VECTOR_EXT
, GL_INVARIANT_EXT
, GL_FULL_RANGE_EXT
, _EVSNumConstant
+ (_ATIFogRangeFixed
? 0 : 1));
662 if (_EVSConstantHandle
== 0)
664 nlwarning("Unable to allocate constants for EXT_vertex_shader, vertex program support is disabled");
665 _Extensions
.EXTVertexShader
= false;
671 // Get initial VBL interval
672 _Interval
= getSwapVBLInterval();
677 // ***************************************************************************
678 bool CDriverGL::stretchRect(ITexture
* /* srcText */, NLMISC::CRect
&/* srcRect */, ITexture
* /* destText */, NLMISC::CRect
&/* destRect */)
680 H_AUTO_OGL(CDriverGL_stretchRect
)
685 // ***************************************************************************
686 bool CDriverGL::supportBloomEffect() const
688 return (supportVertexProgram(CVertexProgram::nelvp
) && supportFrameBufferObject() && supportPackedDepthStencil() && supportTextureRectangle());
691 // ***************************************************************************
692 bool CDriverGL::supportNonPowerOfTwoTextures() const
694 return _Extensions
.ARBTextureNonPowerOfTwo
;
697 // ***************************************************************************
698 bool CDriverGL::isTextureRectangle(ITexture
* tex
) const
700 return (!supportNonPowerOfTwoTextures() && supportTextureRectangle() && tex
->isBloomTexture() && tex
->mipMapOff()
701 && (!isPowerOf2(tex
->getWidth()) || !isPowerOf2(tex
->getHeight())));
704 // ***************************************************************************
705 bool CDriverGL::activeFrameBufferObject(ITexture
* tex
)
707 if(supportFrameBufferObject()/* && supportPackedDepthStencil()*/)
711 CTextureDrvInfosGL
* gltext
= (CTextureDrvInfosGL
*)(ITextureDrvInfos
*)(tex
->TextureDrvShare
->DrvTexture
);
712 return gltext
->activeFrameBufferObject(tex
);
716 nglBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0);
724 // --------------------------------------------------
725 void CDriverGL::disableHardwareVertexProgram()
727 H_AUTO_OGL(CDriverGL_disableHardwareVertexProgram
)
728 _Extensions
.DisableHardwareVertexProgram
= true;
731 void CDriverGL::disableHardwarePixelProgram()
733 H_AUTO_OGL(CDriverGL_disableHardwarePixelProgram
)
734 _Extensions
.DisableHardwarePixelProgram
= true;
737 // ***************************************************************************
738 void CDriverGL::disableHardwareVertexArrayAGP()
740 H_AUTO_OGL(CDriverGL_disableHardwareVertexArrayAGP
)
741 _Extensions
.DisableHardwareVertexArrayAGP
= true;
744 // ***************************************************************************
745 void CDriverGL::disableHardwareTextureShader()
747 H_AUTO_OGL(CDriverGL_disableHardwareTextureShader
)
748 _Extensions
.DisableHardwareTextureShader
= true;
751 // --------------------------------------------------
752 void CDriverGL::resetTextureShaders()
754 H_AUTO_OGL(CDriverGL_resetTextureShaders
);
757 if (_Extensions
.NVTextureShader
)
759 glEnable(GL_TEXTURE_SHADER_NV
);
761 for (uint stage
= 0; stage
< inlGetNumTextStages(); ++stage
)
763 _DriverGLStates
.activeTextureARB(stage
);
766 glTexEnvi(GL_TEXTURE_SHADER_NV
, GL_PREVIOUS_TEXTURE_INPUT_NV
, GL_TEXTURE0_ARB
+ stage
- 1);
769 glTexEnvi(GL_TEXTURE_SHADER_NV
, GL_SHADER_OPERATION_NV
, GL_NONE
);
771 _CurrentTexAddrMode
[stage
] = GL_NONE
;
774 glDisable(GL_TEXTURE_SHADER_NV
);
776 _NVTextureShaderEnabled
= false;
781 // --------------------------------------------------
782 bool CDriverGL::isTextureExist(const ITexture
&tex
)
784 H_AUTO_OGL(CDriverGL_isTextureExist
)
787 // Create the shared Name.
789 getTextureShareName (tex
, name
);
792 CSynchronized
<TTexDrvInfoPtrMap
>::CAccessor
access(&_SyncTexDrvInfos
);
793 TTexDrvInfoPtrMap
&rTexDrvInfos
= access
.value();
794 result
= (rTexDrvInfos
.find(name
) != rTexDrvInfos
.end());
799 // --------------------------------------------------
800 bool CDriverGL::clear2D(CRGBA rgba
)
802 H_AUTO_OGL(CDriverGL_clear2D
)
803 glClearColor((float)rgba
.R
/255.0f
,(float)rgba
.G
/255.0f
,(float)rgba
.B
/255.0f
,(float)rgba
.A
/255.0f
);
805 glClear(GL_COLOR_BUFFER_BIT
);
810 // --------------------------------------------------
811 bool CDriverGL::clearZBuffer(float zval
)
813 H_AUTO_OGL(CDriverGL_clearZBuffer
);
821 _DriverGLStates
.enableZWrite(true);
822 glClear(GL_DEPTH_BUFFER_BIT
);
827 // --------------------------------------------------
828 bool CDriverGL::clearStencilBuffer(float stencilval
)
830 H_AUTO_OGL(CDriverGL_clearStencilBuffer
)
831 glClearStencil((int)stencilval
);
833 glClear(GL_STENCIL_BUFFER_BIT
);
838 // --------------------------------------------------
839 void CDriverGL::setColorMask (bool bRed
, bool bGreen
, bool bBlue
, bool bAlpha
)
841 H_AUTO_OGL(CDriverGL_setColorMask
)
842 glColorMask (bRed
, bGreen
, bBlue
, bAlpha
);
845 // --------------------------------------------------
846 bool CDriverGL::swapBuffers()
848 H_AUTO_OGL(CDriverGL_swapBuffers
)
850 ++ _SwapBufferCounter
;
851 // Reset texture shaders
852 //resetTextureShaders();
853 activeVertexProgram(NULL
);
854 activePixelProgram(NULL
);
857 /* Yoyo: must do this (GeForce bug ??) else weird results if end render with a VBHard.
858 Setup a std vertex buffer to ensure NVidia synchronisation.
860 if (!_Extensions
.ARBVertexBufferObject
&& _Extensions
.NVVertexArrayRange
)
862 static CVertexBuffer dummyVB
;
863 static bool dummyVBinit
= false;
867 // setup a full feature VB (maybe not useful ... :( ).
868 dummyVB
.setVertexFormat(CVertexBuffer::PositionFlag
|CVertexBuffer::NormalFlag
|
869 CVertexBuffer::PrimaryColorFlag
|CVertexBuffer::SecondaryColorFlag
|
870 CVertexBuffer::TexCoord0Flag
|CVertexBuffer::TexCoord1Flag
|
871 CVertexBuffer::TexCoord2Flag
|CVertexBuffer::TexCoord3Flag
874 dummyVB
.setNumVertices(10);
876 // activate each frame to close VBHard rendering.
877 // NVidia: This also force a SetFence on if last VB was a VBHard, "closing" it before swap.
879 activeVertexBuffer(dummyVB
);
880 nlassert(_CurrentVertexBufferHard
==NULL
);
883 /* PATCH For Possible NVidia Synchronisation.
885 // Because of Bug with GeForce, must finishFence() for all VBHard.
886 /*set<IVertexBufferHardGL*>::iterator itVBHard= _VertexBufferHardSet.Set.begin();
887 while(itVBHard != _VertexBufferHardSet.Set.end() )
889 // Need only to do it for NVidia VB ones.
890 if((*itVBHard)->NVidiaVertexBufferHard)
892 CVertexBufferHardGLNVidia *vbHardNV= static_cast<CVertexBufferHardGLNVidia*>(*itVBHard);
893 // If needed, "flush" these VB.
894 vbHardNV->finishFence();
898 /* Need to Do this code only if Synchronisation PATCH before not done!
899 AS NV_Fence GeForce Implementation says. Test each frame the NVFence, until completion.
900 NB: finish is not required here. Just test. This is like a "non block synchronisation"
902 if (!_Extensions
.ARBVertexBufferObject
&& _Extensions
.NVVertexArrayRange
)
904 set
<IVertexBufferHardGL
*>::iterator itVBHard
= _VertexBufferHardSet
.Set
.begin();
905 while(itVBHard
!= _VertexBufferHardSet
.Set
.end() )
907 if((*itVBHard
)->VBType
== IVertexBufferHardGL::NVidiaVB
)
909 CVertexBufferHardGLNVidia
*vbHardNV
= static_cast<CVertexBufferHardGLNVidia
*>(*itVBHard
);
910 if(vbHardNV
->isFenceSet())
912 // update Fence Cache.
913 vbHardNV
->testFence();
923 if (_AGPVertexArrayRange
) _AGPVertexArrayRange
->updateLostBuffers();
924 if (_VRAMVertexArrayRange
) _VRAMVertexArrayRange
->updateLostBuffers();
929 eglSwapBuffers (_EglDisplay
, _EglSurface
);
931 #elif defined(NL_OS_WINDOWS)
935 #elif defined(NL_OS_MAC)
939 #elif defined (NL_OS_UNIX)
941 glXSwapBuffers(_dpy
, _win
);
943 #endif // NL_OS_WINDOWS
946 // Activate the default texture environnments for all stages.
947 //===========================================================
948 // This is not a requirement, but it ensure a more stable state each frame.
949 // (well, maybe the good reason is "it hides much more the bugs" :o) ).
950 for(uint stage
=0;stage
<inlGetNumTextStages(); stage
++)
953 _CurrentTexture
[stage
]= NULL
;
954 _CurrentTextureInfoGL
[stage
]= NULL
;
955 // texture are disabled in DriverGLStates.forceDefaults().
958 CMaterial::CTexEnv env
; // envmode init to default.
959 env
.ConstantColor
.set(255,255,255,255);
960 forceActivateTexEnvMode(stage
, env
);
961 forceActivateTexEnvColor(stage
, env
);
964 // Activate the default material.
965 //===========================================================
966 // Same reasoning as textures :)
967 _DriverGLStates
.forceDefaults(inlGetNumTextStages());
968 if (_NVTextureShaderEnabled
)
970 glDisable(GL_TEXTURE_SHADER_NV
);
971 _NVTextureShaderEnabled
= false;
975 _CurrentMaterial
= NULL
;
977 // Reset the profiling counter.
978 _PrimitiveProfileIn
.reset();
979 _PrimitiveProfileOut
.reset();
980 _NbSetupMaterialCall
= 0;
981 _NbSetupModelMatrixCall
= 0;
983 // Reset the texture set
984 _TextureUsed
.clear();
986 // Reset Profile VBHardLock
989 _CurVBHardLockCount
= 0;
990 _NumVBHardProfileFrame
++;
992 // on ati, if the window is inactive, check all vertex buffer to see which one are lost
993 if (_AGPVertexArrayRange
) _AGPVertexArrayRange
->updateLostBuffers();
994 if (_VRAMVertexArrayRange
) _VRAMVertexArrayRange
->updateLostBuffers();
998 // --------------------------------------------------
999 bool CDriverGL::release()
1001 H_AUTO_OGL(CDriverGL_release
)
1003 // release only if the driver was initialized
1004 if (!_Initialized
) return true;
1009 // Call IDriver::release() before, to destroy textures, shaders and VBs...
1012 nlassert(_DepthStencilFBOs
.empty());
1014 _SwapBufferCounter
= 0;
1017 while (!_OcclusionQueryList
.empty())
1019 deleteOcclusionQuery(_OcclusionQueryList
.front());
1022 deleteFragmentShaders();
1024 // release caustic cube map
1025 // _CauticCubeMap = NULL;
1027 // Reset VertexArrayRange.
1028 resetVertexArrayRange();
1030 // delete containers
1031 delete _AGPVertexArrayRange
;
1032 delete _VRAMVertexArrayRange
;
1033 _AGPVertexArrayRange
= NULL
;
1034 _VRAMVertexArrayRange
= NULL
;
1036 // destroy window and associated ressources
1039 // other uninitializations
1043 _Initialized
= false;
1048 // --------------------------------------------------
1049 void CDriverGL::setupViewport (const class CViewport
& viewport
)
1051 H_AUTO_OGL(CDriverGL_setupViewport
)
1053 if (_win
== EmptyWindow
) return;
1055 // Setup gl viewport
1056 uint32 clientWidth
, clientHeight
;
1057 getRenderTargetSize(clientWidth
, clientHeight
);
1059 // Backup the viewport
1060 _CurrViewport
= viewport
;
1067 viewport
.getValues (x
, y
, width
, height
);
1069 // Render to texture : adjuste the viewport
1075 factorX
= (float)_TextureTarget
->getWidth() / (float)clientWidth
;
1077 factorY
= (float)_TextureTarget
->getHeight() / (float)clientHeight
;
1084 // Setup gl viewport
1085 sint ix
=(sint
)((float)clientWidth
*x
+0.5f
);
1086 clamp (ix
, 0, (sint
)clientWidth
);
1087 sint iy
=(sint
)((float)clientHeight
*y
+0.5f
);
1088 clamp (iy
, 0, (sint
)clientHeight
);
1089 sint iwidth
=(sint
)((float)clientWidth
*width
+0.5f
);
1090 clamp (iwidth
, 0, (sint
)clientWidth
-ix
);
1091 sint iheight
=(sint
)((float)clientHeight
*height
+0.5f
);
1092 clamp (iheight
, 0, (sint
)clientHeight
-iy
);
1093 glViewport (ix
, iy
, iwidth
, iheight
);
1096 // --------------------------------------------------
1097 void CDriverGL::getViewport(CViewport
&viewport
)
1099 H_AUTO_OGL(CDriverGL_getViewport
)
1100 viewport
= _CurrViewport
;
1103 // --------------------------------------------------
1104 void CDriverGL::setupScissor (const class CScissor
& scissor
)
1106 H_AUTO_OGL(CDriverGL_setupScissor
)
1108 if (_win
== EmptyWindow
) return;
1110 // Setup gl viewport
1111 uint32 clientWidth
, clientHeight
;
1112 getRenderTargetSize(clientWidth
, clientHeight
);
1114 // Backup the scissor
1115 _CurrScissor
= scissor
;
1120 float width
= scissor
.Width
;
1121 float height
= scissor
.Height
;
1123 // Render to texture : adjuste the scissor
1129 factorX
= (float) _TextureTarget
->getWidth() / (float)clientWidth
;
1131 factorY
= (float) _TextureTarget
->getHeight() / (float)clientHeight
;
1138 // enable or disable Scissor, but AFTER textureTarget adjust
1139 if(x
==0.f
&& y
==0.f
&& width
>=1.f
&& height
>=1.f
)
1141 glDisable(GL_SCISSOR_TEST
);
1146 sint ix0
=(sint
)floor((float)clientWidth
* x
+ 0.5f
);
1147 clamp (ix0
, 0, (sint
)clientWidth
);
1148 sint iy0
=(sint
)floor((float)clientHeight
* y
+ 0.5f
);
1149 clamp (iy0
, 0, (sint
)clientHeight
);
1151 sint ix1
=(sint
)floor((float)clientWidth
* (x
+width
) + 0.5f
);
1152 clamp (ix1
, 0, (sint
)clientWidth
);
1153 sint iy1
=(sint
)floor((float)clientHeight
* (y
+height
) + 0.5f
);
1154 clamp (iy1
, 0, (sint
)clientHeight
);
1156 sint iwidth
= ix1
- ix0
;
1157 clamp (iwidth
, 0, (sint
)clientWidth
);
1158 sint iheight
= iy1
- iy0
;
1159 clamp (iheight
, 0, (sint
)clientHeight
);
1161 glScissor (ix0
, iy0
, iwidth
, iheight
);
1162 glEnable(GL_SCISSOR_TEST
);
1166 uint8
CDriverGL::getBitPerPixel ()
1168 H_AUTO_OGL(CDriverGL_getBitPerPixel
)
1169 return _CurrentMode
.Depth
;
1172 const char *CDriverGL::getVideocardInformation ()
1174 H_AUTO_OGL(CDriverGL_getVideocardInformation
)
1175 static char name
[1024];
1177 if (!_Initialized
) return "OpenGL isn't initialized";
1179 const char *vendor
= (const char *) glGetString (GL_VENDOR
);
1180 const char *renderer
= (const char *) glGetString (GL_RENDERER
);
1181 const char *version
= (const char *) glGetString (GL_VERSION
);
1183 smprintf(name
, 1024, "OpenGL / %s / %s / %s", vendor
, renderer
, version
);
1187 sint
CDriverGL::getTotalVideoMemory() const
1189 H_AUTO_OGL(CDriverGL_getTotalVideoMemory
);
1191 #ifndef USE_OPENGLES
1192 if (_Extensions
.NVXGPUMemoryInfo
)
1194 GLint memoryInKiB
= 0;
1195 glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX
, &memoryInKiB
);
1197 nlinfo("3D: GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX returned %d KiB", memoryInKiB
);
1201 if (_Extensions
.ATIMeminfo
)
1204 glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI
, params
);
1206 nlinfo("3D: GL_TEXTURE_FREE_MEMORY_ATI returned %d KiB", params
[0]);
1210 #if defined(NL_OS_WINDOWS)
1211 if (_Extensions
.WGLAMDGPUAssociation
)
1213 GLuint uNoOfGPUs
= nwglGetGPUIDsAMD(0, 0);
1214 GLuint
*uGPUIDs
= new GLuint
[uNoOfGPUs
];
1215 nwglGetGPUIDsAMD(uNoOfGPUs
, uGPUIDs
);
1217 GLuint memoryInMiB
= 0;
1218 nwglGetGPUInfoAMD(uGPUIDs
[0], WGL_GPU_RAM_AMD
, GL_UNSIGNED_INT
, sizeof(GLuint
), &memoryInMiB
);
1222 nlinfo("3D: WGL_GPU_RAM_AMD returned %d MiB", memoryInMiB
);
1223 return memoryInMiB
* 1024;
1225 #elif defined(NL_OS_MAC)
1228 // get current renderer ID
1229 CGLError error
= CGLGetParameter([_ctx CGLContextObj
], kCGLCPCurrentRendererID
, &rendererID
);
1231 if (error
== kCGLNoError
)
1234 CGLRendererInfoObj rend
;
1236 // get renderer info for all renderers
1237 error
= CGLQueryRendererInfo(0xffffffff, &rend
, &nrend
);
1239 if (error
== kCGLNoError
)
1241 for (GLint i
= 0; i
< nrend
; ++i
)
1243 GLint thisRendererID
;
1244 error
= CGLDescribeRenderer(rend
, i
, kCGLRPRendererID
, &thisRendererID
);
1246 if (error
== kCGLNoError
)
1248 // see if this is the one we want
1249 if (thisRendererID
== rendererID
)
1251 GLint memoryInMiB
= 0;
1252 CGLError error
= CGLDescribeRenderer(rend
, i
, kCGLRPVideoMemoryMegabytes
, &memoryInMiB
);
1254 if (error
== kCGLNoError
)
1257 return memoryInMiB
* 1024;
1261 nlwarning("3D: Unable to get video memory (%s)", CGLErrorString(error
));
1267 nlwarning("3D: Unable to get renderer ID (%s)", CGLErrorString(error
));
1271 CGLDestroyRendererInfo(rend
);
1275 nlwarning("3D: Unable to get renderers info (%s)", CGLErrorString(error
));
1280 nlerror("3D: Unable to get current renderer ID (%s)", CGLErrorString(error
));
1283 if (_Extensions
.GLXMESAQueryRenderer
)
1285 uint32 memoryInMiB
= 0;
1287 if (nglXQueryCurrentRendererIntegerMESA(GLX_RENDERER_VIDEO_MEMORY_MESA
, &memoryInMiB
))
1289 nlinfo("3D: GLX_RENDERER_VIDEO_MEMORY_MESA returned %u MiB", memoryInMiB
);
1290 return memoryInMiB
* 1024;
1296 // TODO: implement for OpenGL ES
1302 bool CDriverGL::clipRect(NLMISC::CRect
&rect
)
1304 H_AUTO_OGL(CDriverGL_clipRect
)
1305 // Clip the wanted rectangle with window.
1306 uint32 width
, height
;
1307 getWindowSize(width
, height
);
1309 sint32 xr
=rect
.right() ,yr
=rect
.bottom();
1311 clamp((sint32
&)rect
.X
, (sint32
)0, (sint32
)width
);
1312 clamp((sint32
&)rect
.Y
, (sint32
)0, (sint32
)height
);
1313 clamp((sint32
&)xr
, (sint32
)rect
.X
, (sint32
)width
);
1314 clamp((sint32
&)yr
, (sint32
)rect
.Y
, (sint32
)height
);
1315 rect
.Width
= xr
-rect
.X
;
1316 rect
.Height
= yr
-rect
.Y
;
1318 return rect
.Width
>0 && rect
.Height
>0;
1321 void CDriverGL::getBufferPart (CBitmap
&bitmap
, NLMISC::CRect
&rect
)
1323 H_AUTO_OGL(CDriverGL_getBufferPart
)
1328 bitmap
.resize(rect
.Width
, rect
.Height
, CBitmap::RGBA
);
1329 glReadPixels (rect
.X
, rect
.Y
, rect
.Width
, rect
.Height
, GL_RGBA
, GL_UNSIGNED_BYTE
, bitmap
.getPixels ().getPtr());
1333 void CDriverGL::getZBufferPart (std::vector
<float> &zbuffer
, NLMISC::CRect
&rect
)
1335 H_AUTO_OGL(CDriverGL_getZBufferPart
)
1340 zbuffer
.resize(rect
.Width
*rect
.Height
);
1343 glReadPixels (rect
.X
, rect
.Y
, rect
.Width
, rect
.Height
, GL_DEPTH_COMPONENT16_OES
, GL_FLOAT
, &(zbuffer
[0]));
1345 glPixelTransferf(GL_DEPTH_SCALE
, 1.0f
);
1346 glPixelTransferf(GL_DEPTH_BIAS
, 0.f
);
1347 glReadPixels(rect
.X
, rect
.Y
, rect
.Width
, rect
.Height
, GL_DEPTH_COMPONENT
, GL_FLOAT
, &(zbuffer
[0]));
1352 void CDriverGL::getZBuffer (std::vector
<float> &zbuffer
)
1354 H_AUTO_OGL(CDriverGL_getZBuffer
)
1356 getWindowSize(rect
.Width
, rect
.Height
);
1357 getZBufferPart(zbuffer
, rect
);
1360 void CDriverGL::getBuffer (CBitmap
&bitmap
)
1362 H_AUTO_OGL(CDriverGL_getBuffer
)
1364 getWindowSize(rect
.Width
, rect
.Height
);
1365 getBufferPart(bitmap
, rect
);
1369 bool CDriverGL::fillBuffer (CBitmap
&bitmap
)
1371 H_AUTO_OGL(CDriverGL_fillBuffer
)
1373 getWindowSize(rect
.Width
, rect
.Height
);
1374 if( rect
.Width
!=bitmap
.getWidth() || rect
.Height
!=bitmap
.getHeight() || bitmap
.getPixelFormat()!=CBitmap::RGBA
)
1379 glGenTextures(1, &textureId
);
1380 glBindTexture(GL_TEXTURE_2D
, textureId
);
1381 glPixelStorei(GL_UNPACK_ALIGNMENT
,1);
1382 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
1383 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
1384 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
1385 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
1386 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_MODULATE
);
1387 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, rect
.Width
, rect
.Height
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, &(bitmap
.getPixels()[0]));
1388 // glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, smBackgroundCrop,0);
1389 nglDrawTexfOES(0.f
, 0.f
, 0.f
, 1.f
, 1.f
);
1391 glPixelStorei(GL_UNPACK_ALIGNMENT
,1);
1392 glDrawPixels (rect
.Width
, rect
.Height
, GL_RGBA
, GL_UNSIGNED_BYTE
, &(bitmap
.getPixels()[0]) );
1398 // ***************************************************************************
1399 void CDriverGL::copyFrameBufferToTexture(ITexture
*tex
,
1407 uint cubeFace
/*= 0*/
1410 H_AUTO_OGL(CDriverGL_copyFrameBufferToTexture
)
1411 bool compressed
= false;
1412 getGlTextureFormat(*tex
, compressed
);
1413 nlassert(!compressed
);
1414 // first, mark the texture as valid, and make sure there is a corresponding texture in the device memory
1416 CTextureDrvInfosGL
* gltext
= (CTextureDrvInfosGL
*)(ITextureDrvInfos
*)(tex
->TextureDrvShare
->DrvTexture
);
1417 //if (_RenderTargetFBO)
1418 // gltext->activeFrameBufferObject(NULL);
1419 _DriverGLStates
.activeTextureARB(0);
1420 // setup texture mode, after activeTextureARB()
1421 CDriverGLStates::TTextureMode textureMode
= CDriverGLStates::Texture2D
;
1423 #ifndef USE_OPENGLES
1424 if(gltext
->TextureMode
== GL_TEXTURE_RECTANGLE_NV
)
1425 textureMode
= CDriverGLStates::TextureRect
;
1428 _DriverGLStates
.setTextureMode(textureMode
);
1429 if (tex
->isTextureCube())
1431 if(_Extensions
.ARBTextureCubeMap
)
1433 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB
, gltext
->ID
);
1434 glCopyTexSubImage2D(NLCubeFaceToGLCubeFace
[cubeFace
], level
, offsetx
, offsety
, x
, y
, width
, height
);
1439 glBindTexture(gltext
->TextureMode
, gltext
->ID
);
1440 glCopyTexSubImage2D(gltext
->TextureMode
, level
, offsetx
, offsety
, x
, y
, width
, height
);
1442 // disable texturing.
1443 _DriverGLStates
.setTextureMode(CDriverGLStates::TextureDisabled
);
1444 _CurrentTexture
[0] = NULL
;
1445 _CurrentTextureInfoGL
[0] = NULL
;
1446 //if (_RenderTargetFBO)
1447 // gltext->activeFrameBufferObject(tex);
1450 // ***************************************************************************
1451 void CDriverGL::setPolygonMode (TPolygonMode mode
)
1453 H_AUTO_OGL(CDriverGL_setPolygonMode
)
1454 IDriver::setPolygonMode (mode
);
1456 #ifndef USE_OPENGLES
1457 // Set the polygon mode
1458 switch (_PolygonMode
)
1461 glPolygonMode (GL_FRONT_AND_BACK
, GL_FILL
);
1464 glPolygonMode (GL_FRONT_AND_BACK
, GL_LINE
);
1467 glPolygonMode (GL_FRONT_AND_BACK
, GL_POINT
);
1473 // ***************************************************************************
1474 bool CDriverGL::fogEnabled()
1476 H_AUTO_OGL(CDriverGL_fogEnabled
)
1480 // ***************************************************************************
1481 void CDriverGL::enableFog(bool enable
)
1483 H_AUTO_OGL(CDriverGL_enableFog
)
1484 _DriverGLStates
.enableFog(enable
);
1485 _FogEnabled
= enable
;
1488 // ***************************************************************************
1489 void CDriverGL::setupFog(float start
, float end
, CRGBA color
)
1491 H_AUTO_OGL(CDriverGL_setupFog
)
1492 glFogf(GL_FOG_MODE
, GL_LINEAR
);
1493 glFogf(GL_FOG_START
, start
);
1494 glFogf(GL_FOG_END
, end
);
1496 _CurrentFogColor
[0]= color
.R
/255.0f
;
1497 _CurrentFogColor
[1]= color
.G
/255.0f
;
1498 _CurrentFogColor
[2]= color
.B
/255.0f
;
1499 _CurrentFogColor
[3]= color
.A
/255.0f
;
1501 glFogfv(GL_FOG_COLOR
, _CurrentFogColor
);
1503 #ifndef USE_OPENGLES
1504 /** Special : with vertex program, using the extension EXT_vertex_shader, fog is emulated using 1 more constant to scale result to [0, 1]
1506 if (_Extensions
.EXTVertexShader
&& !_Extensions
.NVVertexProgram
&& !_Extensions
.ARBVertexProgram
)
1508 if (!_ATIFogRangeFixed
)
1510 // last constant is used to store fog information (fog must be rescaled to [0, 1], because of a driver bug)
1513 float datas
[] = { 1.f
/ (start
- end
), - end
/ (start
- end
), 0, 0 };
1514 nglSetInvariantEXT(_EVSConstantHandle
+ _EVSNumConstant
, GL_FLOAT
, datas
);
1518 float datas
[] = { 0.f
, 0, 0, 0 };
1519 nglSetInvariantEXT(_EVSConstantHandle
+ _EVSNumConstant
, GL_FLOAT
, datas
);
1529 // ***************************************************************************
1530 float CDriverGL::getFogStart() const
1532 H_AUTO_OGL(CDriverGL_getFogStart
)
1536 // ***************************************************************************
1537 float CDriverGL::getFogEnd() const
1539 H_AUTO_OGL(CDriverGL_getFogEnd
)
1543 // ***************************************************************************
1544 CRGBA
CDriverGL::getFogColor() const
1546 H_AUTO_OGL(CDriverGL_getFogColor
)
1548 ret
.R
= (uint8
)(_CurrentFogColor
[0]*255);
1549 ret
.G
= (uint8
)(_CurrentFogColor
[1]*255);
1550 ret
.B
= (uint8
)(_CurrentFogColor
[2]*255);
1551 ret
.A
= (uint8
)(_CurrentFogColor
[3]*255);
1556 // ***************************************************************************
1557 void CDriverGL::profileRenderedPrimitives(CPrimitiveProfile
&pIn
, CPrimitiveProfile
&pOut
)
1559 H_AUTO_OGL(CDriverGL_profileRenderedPrimitives
)
1560 pIn
= _PrimitiveProfileIn
;
1561 pOut
= _PrimitiveProfileOut
;
1565 // ***************************************************************************
1566 uint32
CDriverGL::profileAllocatedTextureMemory()
1568 H_AUTO_OGL(CDriverGL_profileAllocatedTextureMemory
)
1569 return _AllocatedTextureMemory
;
1573 // ***************************************************************************
1574 uint32
CDriverGL::profileSetupedMaterials() const
1576 H_AUTO_OGL(CDriverGL_profileSetupedMaterials
)
1577 return _NbSetupMaterialCall
;
1581 // ***************************************************************************
1582 uint32
CDriverGL::profileSetupedModelMatrix() const
1584 H_AUTO_OGL(CDriverGL_profileSetupedModelMatrix
)
1586 return _NbSetupModelMatrixCall
;
1590 // ***************************************************************************
1591 void CDriverGL::enableUsedTextureMemorySum (bool enable
)
1593 H_AUTO_OGL(CDriverGL_enableUsedTextureMemorySum
)
1597 nlinfo ("3D: PERFORMANCE INFO: enableUsedTextureMemorySum has been set to true in CDriverGL");
1598 _TextureUsed
.reserve(512);
1600 _SumTextureMemoryUsed
=enable
;
1604 // ***************************************************************************
1605 uint32
CDriverGL::getUsedTextureMemory() const
1607 H_AUTO_OGL(CDriverGL_getUsedTextureMemory
)
1612 // For each texture used
1613 std::vector
<CTextureDrvInfosGL
*>::const_iterator ite
= _TextureUsed
.begin();
1614 while (ite
!=_TextureUsed
.end())
1616 // Get the gl texture
1617 CTextureDrvInfosGL
* gltext
;
1620 // Sum the memory used by this texture
1622 memory
+=gltext
->TextureMemory
;
1633 // ***************************************************************************
1634 bool CDriverGL::supportTextureShaders() const
1636 H_AUTO_OGL(CDriverGL_supportTextureShaders
)
1638 // fully supported by NV_TEXTURE_SHADER
1639 return _Extensions
.NVTextureShader
;
1642 // ***************************************************************************
1643 bool CDriverGL::supportWaterShader() const
1645 H_AUTO_OGL(CDriverGL_supportWaterShader
);
1647 if(_Extensions
.ARBFragmentProgram
&& ARBWaterShader
[0] != 0) return true;
1649 if (!_Extensions
.EXTVertexShader
&& !_Extensions
.NVVertexProgram
&& !_Extensions
.ARBVertexProgram
) return false; // should support vertex programs
1650 if (!_Extensions
.NVTextureShader
&& !_Extensions
.ATIFragmentShader
&& !_Extensions
.ARBFragmentProgram
) return false;
1654 // ***************************************************************************
1655 bool CDriverGL::supportTextureAddrMode(CMaterial::TTexAddressingMode
/* mode */) const
1657 H_AUTO_OGL(CDriverGL_supportTextureAddrMode
)
1659 if (_Extensions
.NVTextureShader
)
1661 // all the given addessing mode are supported with this extension
1670 // ***************************************************************************
1671 void CDriverGL::setMatrix2DForTextureOffsetAddrMode(const uint stage
, const float mat
[4])
1673 H_AUTO_OGL(CDriverGL_setMatrix2DForTextureOffsetAddrMode
)
1675 if (!supportTextureShaders()) return;
1676 //nlassert(supportTextureShaders());
1677 nlassert(stage
< inlGetNumTextStages() );
1678 _DriverGLStates
.activeTextureARB(stage
);
1680 #ifndef USE_OPENGLES
1681 glTexEnvfv(GL_TEXTURE_SHADER_NV
, GL_OFFSET_TEXTURE_MATRIX_NV
, mat
);
1686 // ***************************************************************************
1687 void CDriverGL::enableNVTextureShader(bool enabled
)
1689 H_AUTO_OGL(CDriverGL_enableNVTextureShader
)
1691 if (enabled
!= _NVTextureShaderEnabled
)
1693 #ifndef USE_OPENGLES
1696 glEnable(GL_TEXTURE_SHADER_NV
);
1700 glDisable(GL_TEXTURE_SHADER_NV
);
1703 _NVTextureShaderEnabled
= enabled
;
1707 // ***************************************************************************
1708 void CDriverGL::checkForPerPixelLightingSupport()
1710 H_AUTO_OGL(CDriverGL_checkForPerPixelLightingSupport
)
1712 // we need at least 3 texture stages and cube map support + EnvCombine4 or 3 support
1713 // TODO : support for EnvCombine3
1714 // TODO : support for less than 3 stages
1716 _SupportPerPixelShaderNoSpec
= (_Extensions
.NVTextureEnvCombine4
|| _Extensions
.ATITextureEnvCombine3
)
1717 && _Extensions
.ARBTextureCubeMap
1718 && _Extensions
.NbTextureStages
>= 3
1719 && (_Extensions
.NVVertexProgram
|| _Extensions
.ARBVertexProgram
|| _Extensions
.EXTVertexShader
);
1721 _SupportPerPixelShader
= (_Extensions
.NVTextureEnvCombine4
|| _Extensions
.ATITextureEnvCombine3
)
1722 && _Extensions
.ARBTextureCubeMap
1723 && _Extensions
.NbTextureStages
>= 2
1724 && (_Extensions
.NVVertexProgram
|| _Extensions
.ARBVertexProgram
|| _Extensions
.EXTVertexShader
);
1727 // ***************************************************************************
1728 bool CDriverGL::supportPerPixelLighting(bool specular
) const
1730 H_AUTO_OGL(CDriverGL_supportPerPixelLighting
)
1732 return specular
? _SupportPerPixelShader
: _SupportPerPixelShaderNoSpec
;
1735 // ***************************************************************************
1736 void CDriverGL::setPerPixelLightingLight(CRGBA diffuse
, CRGBA specular
, float shininess
)
1738 H_AUTO_OGL(CDriverGL_setPerPixelLightingLight
)
1740 _PPLExponent
= shininess
;
1741 _PPLightDiffuseColor
= diffuse
;
1742 _PPLightSpecularColor
= specular
;
1745 // ***************************************************************************
1746 bool CDriverGL::supportBlendConstantColor() const
1748 H_AUTO_OGL(CDriverGL_supportBlendConstantColor
)
1749 return _Extensions
.EXTBlendColor
;
1752 // ***************************************************************************
1753 void CDriverGL::setBlendConstantColor(NLMISC::CRGBA col
)
1755 H_AUTO_OGL(CDriverGL_setBlendConstantColor
)
1758 _CurrentBlendConstantColor
= col
;
1761 if(!_Extensions
.EXTBlendColor
)
1764 #ifndef USE_OPENGLES
1765 static const float OO255
= 1.0f
/255;
1766 nglBlendColorEXT(col
.R
*OO255
, col
.G
*OO255
, col
.B
*OO255
, col
.A
*OO255
);
1770 // ***************************************************************************
1771 NLMISC::CRGBA
CDriverGL::getBlendConstantColor() const
1773 H_AUTO_OGL(CDriverGL_CDriverGL
)
1775 return _CurrentBlendConstantColor
;
1778 // ***************************************************************************
1779 uint
CDriverGL::getNbTextureStages() const
1781 H_AUTO_OGL(CDriverGL_getNbTextureStages
)
1782 return inlGetNumTextStages();
1785 // ***************************************************************************
1786 void CDriverGL::refreshProjMatrixFromGL()
1788 H_AUTO_OGL(CDriverGL_refreshProjMatrixFromGL
)
1790 if (!_ProjMatDirty
) return;
1792 glGetFloatv(GL_PROJECTION_MATRIX
, mat
);
1793 _GLProjMat
.set(mat
);
1794 _ProjMatDirty
= false;
1797 // ***************************************************************************
1798 bool CDriverGL::supportEMBM() const
1800 H_AUTO_OGL(CDriverGL_supportEMBM
);
1802 // For now, supported via ATI extension
1803 return _Extensions
.ATIEnvMapBumpMap
;
1806 // ***************************************************************************
1807 bool CDriverGL::isEMBMSupportedAtStage(uint stage
) const
1809 H_AUTO_OGL(CDriverGL_isEMBMSupportedAtStage
)
1811 nlassert(supportEMBM());
1812 nlassert(stage
< IDRV_MAT_MAXTEXTURES
);
1813 return _StageSupportEMBM
[stage
];
1816 // ***************************************************************************
1817 void CDriverGL::setEMBMMatrix(const uint stage
,const float mat
[4])
1819 H_AUTO_OGL(CDriverGL_setEMBMMatrix
)
1821 #ifndef USE_OPENGLES
1822 nlassert(supportEMBM());
1823 nlassert(stage
< IDRV_MAT_MAXTEXTURES
);
1825 if (_Extensions
.ATIEnvMapBumpMap
)
1827 _DriverGLStates
.activeTextureARB(stage
);
1828 nglTexBumpParameterfvATI(GL_BUMP_ROT_MATRIX_ATI
, const_cast<float *>(mat
));
1833 // ***************************************************************************
1834 void CDriverGL::initEMBM()
1836 H_AUTO_OGL(CDriverGL_initEMBM
);
1838 #ifndef USE_OPENGLES
1841 std::fill(_StageSupportEMBM
, _StageSupportEMBM
+ IDRV_MAT_MAXTEXTURES
, false);
1842 if (_Extensions
.ATIEnvMapBumpMap
)
1844 // Test which stage support EMBM
1847 nglGetTexBumpParameterivATI(GL_BUMP_NUM_TEX_UNITS_ATI
, &numEMBMUnits
);
1849 std::vector
<GLint
> EMBMUnits(numEMBMUnits
);
1851 // get array of units that supports EMBM
1852 nglGetTexBumpParameterivATI(GL_BUMP_TEX_UNITS_ATI
, &EMBMUnits
[0]);
1854 numEMBMUnits
= std::min(numEMBMUnits
, (GLint
) _Extensions
.NbTextureStages
);
1856 EMBMUnits
.resize(numEMBMUnits
);
1859 for(k
= 0; k
< EMBMUnits
.size(); ++k
)
1861 uint stage
= EMBMUnits
[k
] - GL_TEXTURE0_ARB
;
1862 if (stage
< (IDRV_MAT_MAXTEXTURES
- 1))
1864 _StageSupportEMBM
[stage
] = true;
1867 // setup each stage to apply the bump map to the next stage (or previous if there's an unit at the last stage)
1868 for(k
= 0; k
< (uint
) _Extensions
.NbTextureStages
; ++k
)
1870 if (_StageSupportEMBM
[k
])
1872 // setup each stage so that it apply EMBM on the next stage
1873 _DriverGLStates
.activeTextureARB(k
);
1874 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE_EXT
);
1875 if (k
!= (uint
) (_Extensions
.NbTextureStages
- 1))
1877 glTexEnvi(GL_TEXTURE_ENV
, GL_BUMP_TARGET_ATI
, GL_TEXTURE0_ARB
+ k
+ 1);
1881 glTexEnvi(GL_TEXTURE_ENV
, GL_BUMP_TARGET_ATI
, GL_TEXTURE0_ARB
);
1885 _DriverGLStates
.activeTextureARB(0);
1891 // ***************************************************************************
1892 /** Water fragment program with extension ARB_fragment_program
1894 static const char *WaterCodeNoDiffuseForARBFragmentProgram
=
1896 OPTION ARB_precision_hint_nicest; \n\
1897 PARAM bump0ScaleBias = program.env[0]; \n\
1898 PARAM bump1ScaleBias = program.env[1]; \n\
1899 ATTRIB bump0TexCoord = fragment.texcoord[0]; \n\
1900 ATTRIB bump1TexCoord = fragment.texcoord[1]; \n\
1901 ATTRIB envMapTexCoord = fragment.texcoord[2]; \n\
1902 OUTPUT oCol = result.color; \n\
1904 #read bump map 0 \n\
1905 TEX bmValue, bump0TexCoord, texture[0], 2D; \n\
1906 #bias result (include scaling) \n\
1907 MAD bmValue, bmValue, bump0ScaleBias.xxxx, bump0ScaleBias.yyzz; \n\
1908 ADD bmValue, bmValue, bump1TexCoord; \n\
1909 #read bump map 1 \n\
1910 TEX bmValue, bmValue, texture[1], 2D; \n\
1911 #bias result (include scaling) \n\
1912 MAD bmValue, bmValue, bump1ScaleBias.xxxx, bump1ScaleBias.yyzz; \n\
1913 #add envmap coord \n\
1914 ADD bmValue, bmValue, envMapTexCoord; \n\
1916 TEX oCol, bmValue, texture[2], 2D; \n\
1919 static const char *WaterCodeNoDiffuseWithFogForARBFragmentProgram
=
1921 OPTION ARB_precision_hint_nicest; \n\
1922 PARAM bump0ScaleBias = program.env[0]; \n\
1923 PARAM bump1ScaleBias = program.env[1]; \n\
1924 PARAM fogColor = state.fog.color; \n\
1925 PARAM fogFactor = program.env[2]; \n\
1926 ATTRIB bump0TexCoord = fragment.texcoord[0]; \n\
1927 ATTRIB bump1TexCoord = fragment.texcoord[1]; \n\
1928 ATTRIB envMapTexCoord = fragment.texcoord[2]; \n\
1929 ATTRIB fogValue = fragment.fogcoord; \n\
1930 OUTPUT oCol = result.color; \n\
1934 #read bump map 0 \n\
1935 TEX bmValue, bump0TexCoord, texture[0], 2D; \n\
1936 #bias result (include scaling) \n\
1937 MAD bmValue, bmValue, bump0ScaleBias.xxxx, bump0ScaleBias.yyzz; \n\
1938 ADD bmValue, bmValue, bump1TexCoord; \n\
1939 #read bump map 1 \n\
1940 TEX bmValue, bmValue, texture[1], 2D; \n\
1941 #bias result (include scaling) \n\
1942 MAD bmValue, bmValue, bump1ScaleBias.xxxx, bump1ScaleBias.yyzz; \n\
1943 #add envmap coord \n\
1944 ADD bmValue, bmValue, envMapTexCoord; \n\
1946 TEX envMap, bmValue, texture[2], 2D; \n\
1948 MAD_SAT tmpFog, fogValue.x, fogFactor.x, fogFactor.y; \n\
1949 LRP oCol, tmpFog.x, envMap, fogColor; \n\
1952 // **************************************************************************************
1953 /** Water fragment program with extension ARB_fragment_program and a diffuse map applied
1955 static const char *WaterCodeForARBFragmentProgram
=
1957 OPTION ARB_precision_hint_nicest; \n\
1958 PARAM bump0ScaleBias = program.env[0]; \n\
1959 PARAM bump1ScaleBias = program.env[1]; \n\
1960 ATTRIB bump0TexCoord = fragment.texcoord[0]; \n\
1961 ATTRIB bump1TexCoord = fragment.texcoord[1]; \n\
1962 ATTRIB envMapTexCoord = fragment.texcoord[2]; \n\
1963 ATTRIB diffuseTexCoord = fragment.texcoord[3]; \n\
1964 OUTPUT oCol = result.color; \n\
1968 #read bump map 0 \n\
1969 TEX bmValue, bump0TexCoord, texture[0], 2D; \n\
1970 #bias result (include scaling) \n\
1971 MAD bmValue, bmValue, bump0ScaleBias.xxxx, bump0ScaleBias.yyzz; \n\
1972 ADD bmValue, bmValue, bump1TexCoord; \n\
1973 #read bump map 1 \n\
1974 TEX bmValue, bmValue, texture[1], 2D; \n\
1975 #bias result (include scaling) \n\
1976 MAD bmValue, bmValue, bump1ScaleBias.xxxx, bump1ScaleBias.yyzz; \n\
1977 #add envmap coord \n\
1978 ADD bmValue, bmValue, envMapTexCoord; \n\
1980 TEX envMap, bmValue, texture[2], 2D; \n\
1982 TEX diffuse, diffuseTexCoord, texture[3], 2D; \n\
1983 #modulate diffuse and envmap to get result \n\
1984 MUL oCol, diffuse, envMap; \n\
1987 static const char *WaterCodeWithFogForARBFragmentProgram
=
1989 OPTION ARB_precision_hint_nicest; \n\
1990 PARAM bump0ScaleBias = program.env[0]; \n\
1991 PARAM bump1ScaleBias = program.env[1]; \n\
1992 PARAM fogColor = state.fog.color; \n\
1993 PARAM fogFactor = program.env[2]; \n\
1994 ATTRIB bump0TexCoord = fragment.texcoord[0]; \n\
1995 ATTRIB bump1TexCoord = fragment.texcoord[1]; \n\
1996 ATTRIB envMapTexCoord = fragment.texcoord[2]; \n\
1997 ATTRIB diffuseTexCoord = fragment.texcoord[3]; \n\
1998 ATTRIB fogValue = fragment.fogcoord; \n\
1999 OUTPUT oCol = result.color; \n\
2004 #read bump map 0 \n\
2005 TEX bmValue, bump0TexCoord, texture[0], 2D; \n\
2006 #bias result (include scaling) \n\
2007 MAD bmValue, bmValue, bump0ScaleBias.xxxx, bump0ScaleBias.yyzz; \n\
2008 ADD bmValue, bmValue, bump1TexCoord; \n\
2009 #read bump map 1 \n\
2010 TEX bmValue, bmValue, texture[1], 2D; \n\
2011 #bias result (include scaling) \n\
2012 MAD bmValue, bmValue, bump1ScaleBias.xxxx, bump1ScaleBias.yyzz; \n\
2013 #add envmap coord \n\
2014 ADD bmValue, bmValue, envMapTexCoord; \n\
2015 TEX envMap, bmValue, texture[2], 2D; \n\
2016 TEX diffuse, diffuseTexCoord, texture[3], 2D; \n\
2017 MAD_SAT tmpFog, fogValue.x, fogFactor.x, fogFactor.y; \n\
2018 #modulate diffuse and envmap to get result \n\
2019 MUL diffuse, diffuse, envMap; \n\
2020 LRP oCol, tmpFog.x, diffuse, fogColor; \n\
2023 // ***************************************************************************
2024 /** Load a ARB_fragment_program_code, and ensure it is loaded natively
2026 uint
loadARBFragmentProgramStringNative(const char *prog
, bool forceNativePrograms
)
2028 H_AUTO_OGL(loadARBFragmentProgramStringNative
);
2031 nlwarning("The param 'prog' is null, cannot load");
2035 #ifndef USE_OPENGLES
2037 nglGenProgramsARB(1, &progID
);
2040 nlwarning("glGenProgramsARB returns a progID NULL");
2043 nglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB
, progID
);
2044 GLint errorPos
, isNative
;
2045 nglProgramStringARB(GL_FRAGMENT_PROGRAM_ARB
, GL_PROGRAM_FORMAT_ASCII_ARB
, (GLsizei
)strlen(prog
), prog
);
2046 nglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB
, 0);
2047 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB
, &errorPos
);
2048 nglGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB
, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB
, &isNative
);
2051 if (!isNative
&& forceNativePrograms
)
2053 nlwarning("Fragment program isn't supported natively; purging program");
2054 nglDeleteProgramsARB(1, &progID
);
2061 nlwarning("init fragment program failed: errorPos: %d isNative: %d: %s", errorPos
, isNative
, (const char*)glGetString(GL_PROGRAM_ERROR_STRING_ARB
));
2068 // ***************************************************************************
2069 /** R200 Fragment Shader :
2070 * Send fragment shader to fetch a perturbed envmap from the addition of 2 bumpmap
2071 * The result is in R2 after the 2nd pass
2073 static void fetchPerturbedEnvMapR200()
2075 H_AUTO_OGL(CDriverGL_fetchPerturbedEnvMapR200
);
2077 #ifndef USE_OPENGLES
2081 nglSampleMapATI(GL_REG_0_ATI
, GL_TEXTURE0_ARB
, GL_SWIZZLE_STR_ATI
); // sample bump map 0
2082 nglSampleMapATI(GL_REG_1_ATI
, GL_TEXTURE1_ARB
, GL_SWIZZLE_STR_ATI
); // sample bump map 1
2083 nglPassTexCoordATI(GL_REG_2_ATI
, GL_TEXTURE2_ARB
, GL_SWIZZLE_STR_ATI
); // get texcoord for envmap
2085 nglColorFragmentOp3ATI(GL_MAD_ATI
, GL_REG_2_ATI
, GL_NONE
, GL_NONE
, GL_REG_0_ATI
, GL_NONE
, GL_BIAS_BIT_ATI
|GL_2X_BIT_ATI
, GL_CON_0_ATI
, GL_NONE
, GL_NONE
, GL_REG_2_ATI
, GL_NONE
, GL_NONE
); // scale bumpmap 1 & add envmap coords
2086 nglColorFragmentOp3ATI(GL_MAD_ATI
, GL_REG_2_ATI
, GL_NONE
, GL_NONE
, GL_REG_1_ATI
, GL_NONE
, GL_BIAS_BIT_ATI
|GL_2X_BIT_ATI
, GL_CON_1_ATI
, GL_NONE
, GL_NONE
, GL_REG_2_ATI
, GL_NONE
, GL_NONE
); // scale bumpmap 2 & add to bump map 1
2091 nglSampleMapATI(GL_REG_2_ATI
, GL_REG_2_ATI
, GL_SWIZZLE_STR_ATI
); // fetch envmap at perturbed texcoords
2095 // ***************************************************************************
2096 void CDriverGL::initFragmentShaders()
2098 H_AUTO_OGL(CDriverGL_initFragmentShaders
);
2100 #ifndef USE_OPENGLES
2105 // the ARB_fragment_program is prioritary over other extensions when present
2106 if (_Extensions
.ARBFragmentProgram
)
2108 nlinfo("WATER: Try ARB_fragment_program");
2109 ARBWaterShader
[0] = loadARBFragmentProgramStringNative(WaterCodeNoDiffuseForARBFragmentProgram
, _ForceNativeFragmentPrograms
);
2110 ARBWaterShader
[1] = loadARBFragmentProgramStringNative(WaterCodeNoDiffuseWithFogForARBFragmentProgram
, _ForceNativeFragmentPrograms
);
2111 ARBWaterShader
[2] = loadARBFragmentProgramStringNative(WaterCodeForARBFragmentProgram
, _ForceNativeFragmentPrograms
);
2112 ARBWaterShader
[3] = loadARBFragmentProgramStringNative(WaterCodeWithFogForARBFragmentProgram
, _ForceNativeFragmentPrograms
);
2114 for(uint k
= 0; k
< 4; ++k
)
2116 if (!ARBWaterShader
[k
])
2119 deleteARBFragmentPrograms();
2120 nlwarning("WATER: fragment %d is not loaded, not using ARB_fragment_program at all", k
);
2126 nlinfo("WATER: ARB_fragment_program OK, Use it");
2131 if (_Extensions
.ATIFragmentShader
)
2133 nlinfo("WATER: Try ATI_fragment_program");
2137 ATIWaterShaderHandleNoDiffuseMap
= nglGenFragmentShadersATI(1);
2139 ATIWaterShaderHandle
= nglGenFragmentShadersATI(1);
2141 if (!ATIWaterShaderHandle
|| !ATIWaterShaderHandleNoDiffuseMap
)
2143 ATIWaterShaderHandleNoDiffuseMap
= ATIWaterShaderHandle
= 0;
2144 nlwarning("Couldn't generate water shader using ATI_fragment_shader !");
2149 // Water shader for R200 : we just add the 2 bump map contributions (du, dv). We then use this contribution to perturbate the envmap
2150 nglBindFragmentShaderATI(ATIWaterShaderHandleNoDiffuseMap
);
2151 nglBeginFragmentShaderATI();
2153 fetchPerturbedEnvMapR200();
2154 nglColorFragmentOp1ATI(GL_MOV_ATI
, GL_REG_0_ATI
, GL_NONE
, GL_NONE
, GL_REG_2_ATI
, GL_NONE
, GL_NONE
);
2155 nglAlphaFragmentOp1ATI(GL_MOV_ATI
, GL_REG_0_ATI
, GL_NONE
, GL_REG_2_ATI
, GL_NONE
, GL_NONE
);
2157 nglEndFragmentShaderATI();
2158 GLenum error
= glGetError();
2159 nlassert(error
== GL_NONE
);
2161 // The same but with a diffuse map added
2162 nglBindFragmentShaderATI(ATIWaterShaderHandle
);
2163 nglBeginFragmentShaderATI();
2165 fetchPerturbedEnvMapR200();
2167 nglSampleMapATI(GL_REG_3_ATI
, GL_TEXTURE3_ARB
, GL_SWIZZLE_STR_ATI
); // fetch envmap at perturbed texcoords
2168 nglColorFragmentOp2ATI(GL_MUL_ATI
, GL_REG_0_ATI
, GL_NONE
, GL_NONE
, GL_REG_3_ATI
, GL_NONE
, GL_NONE
, GL_REG_2_ATI
, GL_NONE
, GL_NONE
); // scale bumpmap 1 & add envmap coords
2169 nglAlphaFragmentOp2ATI(GL_MUL_ATI
, GL_REG_0_ATI
, GL_NONE
, GL_REG_3_ATI
, GL_NONE
, GL_NONE
, GL_REG_2_ATI
, GL_NONE
, GL_NONE
);
2171 nglEndFragmentShaderATI();
2172 error
= glGetError();
2173 nlassert(error
== GL_NONE
);
2174 nglBindFragmentShaderATI(0);
2180 ATICloudShaderHandle
= nglGenFragmentShadersATI(1);
2182 if (!ATICloudShaderHandle
)
2184 nlwarning("Couldn't generate cloud shader using ATI_fragment_shader !");
2189 nglBindFragmentShaderATI(ATICloudShaderHandle
);
2190 nglBeginFragmentShaderATI();
2192 nglSampleMapATI(GL_REG_0_ATI
, GL_TEXTURE0_ARB
, GL_SWIZZLE_STR_ATI
); // sample texture 0
2193 nglSampleMapATI(GL_REG_1_ATI
, GL_TEXTURE1_ARB
, GL_SWIZZLE_STR_ATI
); // sample texture 1
2194 // lerp between tex 0 & tex 1 using diffuse alpha
2195 nglAlphaFragmentOp3ATI(GL_LERP_ATI
, GL_REG_0_ATI
, GL_NONE
, GL_PRIMARY_COLOR_ARB
, GL_NONE
, GL_NONE
, GL_REG_0_ATI
, GL_NONE
, GL_NONE
, GL_REG_1_ATI
, GL_NONE
, GL_NONE
);
2196 //nglAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_REG_0_ATI, GL_NONE, GL_NONE);
2198 //nglColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, GL_ZERO, GL_NONE, GL_NONE);
2199 // output alpha multiplied by constant 0
2200 nglAlphaFragmentOp2ATI(GL_MUL_ATI
, GL_REG_0_ATI
, GL_NONE
, GL_REG_0_ATI
, GL_NONE
, GL_NONE
, GL_CON_0_ATI
, GL_NONE
, GL_NONE
);
2201 nglEndFragmentShaderATI();
2202 GLenum error
= glGetError();
2203 nlassert(error
== GL_NONE
);
2204 nglBindFragmentShaderATI(0);
2208 // if none of the previous programs worked, fallback on NV_texture_shader, or (todo) simpler shader
2212 // ***************************************************************************
2213 void CDriverGL::deleteARBFragmentPrograms()
2215 H_AUTO_OGL(CDriverGL_deleteARBFragmentPrograms
);
2217 #ifndef USE_OPENGLES
2218 for(uint k
= 0; k
< 4; ++k
)
2220 if (ARBWaterShader
[k
])
2222 GLuint progId
= (GLuint
) ARBWaterShader
[k
];
2223 nglDeleteProgramsARB(1, &progId
);
2224 ARBWaterShader
[k
] = 0;
2230 // ***************************************************************************
2231 void CDriverGL::deleteFragmentShaders()
2233 H_AUTO_OGL(CDriverGL_deleteFragmentShaders
)
2235 #ifndef USE_OPENGLES
2236 deleteARBFragmentPrograms();
2238 if (ATIWaterShaderHandleNoDiffuseMap
)
2240 nglDeleteFragmentShaderATI((GLuint
) ATIWaterShaderHandleNoDiffuseMap
);
2241 ATIWaterShaderHandleNoDiffuseMap
= 0;
2243 if (ATIWaterShaderHandle
)
2245 nglDeleteFragmentShaderATI((GLuint
) ATIWaterShaderHandle
);
2246 ATIWaterShaderHandle
= 0;
2248 if (ATICloudShaderHandle
)
2250 nglDeleteFragmentShaderATI((GLuint
) ATICloudShaderHandle
);
2251 ATICloudShaderHandle
= 0;
2256 // ***************************************************************************
2257 void CDriverGL::finish()
2259 H_AUTO_OGL(CDriverGL_finish
)
2263 // ***************************************************************************
2264 void CDriverGL::flush()
2266 H_AUTO_OGL(CDriverGL_flush
)
2270 // ***************************************************************************
2271 void CDriverGL::setSwapVBLInterval(uint interval
)
2273 H_AUTO_OGL(CDriverGL_setSwapVBLInterval
);
2277 nlwarning("OpenGL driver not initialized when calling setSwapVBLInterval");
2283 // don't try to change VBL if interval didn't change
2284 if (_Interval
== interval
) return;
2287 res
= eglSwapInterval(_EglDisplay
, interval
) == EGL_TRUE
;
2288 #elif defined(NL_OS_WINDOWS)
2289 if(_Extensions
.WGLEXTSwapControl
)
2291 res
= nwglSwapIntervalEXT(interval
) == TRUE
;
2293 #elif defined(NL_OS_MAC)
2294 [_ctx setValues
:(GLint
*)&interval forParameter
:NSOpenGLCPSwapInterval
];
2295 #elif defined(NL_OS_UNIX)
2296 if (_win
&& _Extensions
.GLXEXTSwapControl
)
2298 nglXSwapIntervalEXT(_dpy
, _win
, interval
);
2300 else if (_Extensions
.GLXSGISwapControl
)
2302 res
= nglXSwapIntervalSGI(interval
) == 0;
2304 else if (_Extensions
.GLXMESASwapControl
)
2306 res
= nglXSwapIntervalMESA(interval
) == 0;
2312 _Interval
= interval
;
2316 nlwarning("Could not set swap interval");
2320 // ***************************************************************************
2321 uint
CDriverGL::getSwapVBLInterval()
2323 H_AUTO_OGL(CDriverGL_getSwapVBLInterval
)
2326 #elif defined(NL_OS_WINDOWS)
2327 if(_Extensions
.WGLEXTSwapControl
)
2329 return nwglGetSwapIntervalEXT();
2331 #elif defined(NL_OS_MAC)
2332 #elif defined(NL_OS_UNIX)
2333 if (_win
&& _Extensions
.GLXEXTSwapControl
)
2336 glXQueryDrawable(_dpy
, _win
, GLX_SWAP_INTERVAL_EXT
, &swap
);
2337 glXQueryDrawable(_dpy
, _win
, GLX_MAX_SWAP_INTERVAL_EXT
, &maxSwap
);
2338 nlwarning("The swap interval is %u and the max swap interval is %u", swap
, maxSwap
);
2341 else if (_Extensions
.GLXMESASwapControl
)
2343 return nglXGetSwapIntervalMESA();
2350 // ***************************************************************************
2351 void CDriverGL::enablePolygonSmoothing(bool smooth
)
2353 H_AUTO_OGL(CDriverGL_enablePolygonSmoothing
);
2355 if (_PolygonSmooth
== smooth
) return;
2357 #ifndef USE_OPENGLES
2359 glEnable(GL_POLYGON_SMOOTH
);
2361 glDisable(GL_POLYGON_SMOOTH
);
2364 _PolygonSmooth
= smooth
;
2367 // ***************************************************************************
2368 bool CDriverGL::isPolygonSmoothingEnabled() const
2370 H_AUTO_OGL(CDriverGL_isPolygonSmoothingEnabled
)
2372 return _PolygonSmooth
;
2375 // ***************************************************************************
2376 void CDriverGL::startProfileVBHardLock()
2378 if(_VBHardProfiling
)
2382 _VBHardProfiles
.clear();
2383 _VBHardProfiles
.reserve(50);
2384 _VBHardProfiling
= true;
2385 _CurVBHardLockCount
= 0;
2386 _NumVBHardProfileFrame
= 0;
2389 // ***************************************************************************
2390 void CDriverGL::endProfileVBHardLock(vector
<std::string
> &result
)
2392 if(!_VBHardProfiling
)
2397 result
.resize(_VBHardProfiles
.size() + 1);
2399 for(uint i
=0;i
<_VBHardProfiles
.size();i
++)
2401 const uint tmpSize
= 256;
2403 CVBHardProfile
&vbProf
= _VBHardProfiles
[i
];
2405 if(vbProf
.VBHard
&& !vbProf
.VBHard
->getName().empty())
2407 vbName
= vbProf
.VBHard
->getName().c_str();
2414 float timeLock
= (float)CTime::ticksToSecond(vbProf
.AccumTime
)*1000 / max(_NumVBHardProfileFrame
,1U);
2415 smprintf(tmp
, tmpSize
, "%16s%c: %2.3f ms", vbName
, vbProf
.Change
?'*':' ', timeLock
);
2420 result
[_VBHardProfiles
.size()]= toString("Total: %2.3f", total
);
2423 _VBHardProfiling
= false;
2424 contReset(_VBHardProfiles
);
2427 // ***************************************************************************
2428 void CDriverGL::appendVBHardLockProfile(NLMISC::TTicks time
, CVertexBuffer
*vb
)
2430 // must allocate a new place?
2431 if(_CurVBHardLockCount
>=_VBHardProfiles
.size())
2433 _VBHardProfiles
.resize(_VBHardProfiles
.size()+1);
2434 // set the original VBHard
2435 _VBHardProfiles
[_CurVBHardLockCount
].VBHard
= vb
;
2439 _VBHardProfiles
[_CurVBHardLockCount
].AccumTime
+= time
;
2440 // if change of VBHard for this chrono place
2441 if(_VBHardProfiles
[_CurVBHardLockCount
].VBHard
!= vb
)
2443 // flag, and set new
2444 _VBHardProfiles
[_CurVBHardLockCount
].VBHard
= vb
;
2445 _VBHardProfiles
[_CurVBHardLockCount
].Change
= true;
2449 _CurVBHardLockCount
++;
2452 // ***************************************************************************
2453 void CDriverGL::startProfileIBLock()
2458 // ***************************************************************************
2459 void CDriverGL::endProfileIBLock(std::vector
<std::string
> &/* result */)
2464 // ***************************************************************************
2465 void CDriverGL::profileIBAllocation(std::vector
<std::string
> &/* result */)
2470 // ***************************************************************************
2471 void CDriverGL::profileVBHardAllocation(std::vector
<std::string
> &result
)
2474 result
.reserve(1000);
2475 result
.push_back(toString("Memory Allocated: %4d Ko in AGP / %4d Ko in VRAM",
2476 getAvailableVertexAGPMemory()/1000, getAvailableVertexVRAMMemory()/1000 ));
2477 result
.push_back(toString("Num VBHard: %d", _VertexBufferHardSet
.Set
.size()));
2479 uint totalMemUsed
= 0;
2480 set
<IVertexBufferHardGL
*>::iterator it
;
2481 for(it
= _VertexBufferHardSet
.Set
.begin(); it
!=_VertexBufferHardSet
.Set
.end(); it
++)
2483 IVertexBufferHardGL
*vbHard
= *it
;
2486 uint vSize
= vbHard
->VB
->getVertexSize();
2487 uint numVerts
= vbHard
->VB
->getNumVertices();
2488 totalMemUsed
+= vSize
*numVerts
;
2491 result
.push_back(toString("Mem Used: %4d Ko", totalMemUsed
/1000) );
2493 for(it
= _VertexBufferHardSet
.Set
.begin(); it
!=_VertexBufferHardSet
.Set
.end(); it
++)
2495 IVertexBufferHardGL
*vbHard
= *it
;
2498 uint vSize
= vbHard
->VB
->getVertexSize();
2499 uint numVerts
= vbHard
->VB
->getNumVertices();
2500 result
.push_back(toString(" %16s: %4d ko (format: %d / numVerts: %d)",
2501 vbHard
->VB
->getName().c_str(), vSize
*numVerts
/1000, vSize
, numVerts
));
2506 // ***************************************************************************
2507 bool CDriverGL::supportCloudRenderSinglePass() const
2509 H_AUTO_OGL(CDriverGL_supportCloudRenderSinglePass
)
2511 //return _Extensions.NVTextureEnvCombine4 || (_Extensions.ATIXTextureEnvRoute && _Extensions.EXTTextureEnvCombine);
2512 // there are slowdown for now with ati fragment shader... don't know why
2513 return _Extensions
.NVTextureEnvCombine4
|| _Extensions
.ATIFragmentShader
;
2516 // ***************************************************************************
2517 void CDriverGL::retrieveATIDriverVersion()
2519 H_AUTO_OGL(CDriverGL_retrieveATIDriverVersion
)
2520 _ATIDriverVersion
= 0;
2521 // we may need this driver version to fix flaws of previous ati drivers version (fog issue with V.P)
2522 #ifdef NL_OS_WINDOWS
2523 // get from the registry
2525 // open key about current video card
2526 LONG result
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}", 0, KEY_READ
, &parentKey
);
2527 if (result
== ERROR_SUCCESS
)
2531 uint latestConfigVersion
= 0;
2532 char subKeyName
[256];
2533 char latestSubKeyName
[256] = "";
2534 DWORD nameBufferSize
= sizeof(subKeyName
) / sizeof(subKeyName
[0]);
2535 FILETIME lastWriteTime
;
2536 bool configFound
= false;
2539 nameBufferSize
= sizeof(subKeyName
) / sizeof(subKeyName
[0]);
2540 result
= RegEnumKeyExA(parentKey
, keyIndex
, subKeyName
, &nameBufferSize
, NULL
, NULL
, NULL
, &lastWriteTime
);
2541 if (result
== ERROR_NO_MORE_ITEMS
) break;
2542 if (result
== ERROR_SUCCESS
)
2544 // see if the name is numerical.
2545 bool isNumerical
= true;
2546 for(uint k
= 0; k
< nameBufferSize
; ++k
)
2548 if (!isdigit(subKeyName
[k
]))
2550 isNumerical
= false;
2557 fromString((const char*)subKeyName
, configVersion
);
2558 if (configVersion
>= latestConfigVersion
)
2561 latestConfigVersion
= configVersion
;
2562 strcpy(latestSubKeyName
, subKeyName
);
2569 RegCloseKey(parentKey
);
2576 result
= RegOpenKeyExA(parentKey
, latestSubKeyName
, 0, KEY_READ
, &subKey
);
2577 if (result
== ERROR_SUCCESS
)
2579 // see if it is a radeon card
2581 char driverDesc
[256];
2582 DWORD driverDescBufSize
= sizeof(driverDesc
) / sizeof(driverDesc
[0]);
2583 result
= RegQueryValueExA(subKey
, "DriverDesc", NULL
, &valueType
, (unsigned char *) driverDesc
, &driverDescBufSize
);
2584 if (result
== ERROR_SUCCESS
&& valueType
== REG_SZ
)
2586 toLowerAscii(driverDesc
);
2587 if (strstr(driverDesc
, "radeon")) // is it a radeon card ?
2589 char driverVersion
[256];
2590 DWORD driverVersionBufSize
= sizeof(driverVersion
) / sizeof(driverVersion
[0]);
2591 result
= RegQueryValueExA(subKey
, "DriverVersion", NULL
, &valueType
, (unsigned char *) driverVersion
, &driverVersionBufSize
);
2592 if (result
== ERROR_SUCCESS
&& valueType
== REG_SZ
)
2594 int subVersionNumber
[4];
2595 if (sscanf(driverVersion
, "%d.%d.%d.%d", &subVersionNumber
[0], &subVersionNumber
[1], &subVersionNumber
[2], &subVersionNumber
[3]) == 4)
2597 _ATIDriverVersion
= (uint
) subVersionNumber
[3];
2598 /** see if fog range for V.P is bad in that driver version (is so, do a fix during vertex program conversion to EXT_vertex_shader
2599 * In earlier versions of the driver, fog coordinates had to be output in the [0, 1] range
2600 * From the 6.14.10.6343 driver, fog output must be in world units
2602 if (_ATIDriverVersion
< 6343)
2604 _ATIFogRangeFixed
= false;
2611 RegCloseKey(subKey
);
2613 RegCloseKey(parentKey
);
2615 #elif defined(NL_OS_MAC)
2616 // TODO: Missing Mac Implementation for ATI version retrieval
2617 #elif defined (NL_OS_UNIX)
2618 // TODO for Linux: implement retrieveATIDriverVersion... assuming versions under linux are probably different
2622 // ***************************************************************************
2623 bool CDriverGL::supportMADOperator() const
2625 H_AUTO_OGL(CDriverGL_supportMADOperator
)
2627 return _Extensions
.NVTextureEnvCombine4
|| _Extensions
.ATITextureEnvCombine3
;
2630 // ***************************************************************************
2631 uint
CDriverGL::getNumAdapter() const
2633 H_AUTO_OGL(CDriverGL_getNumAdapter
)
2638 // ***************************************************************************
2639 bool CDriverGL::getAdapter(uint adapter
, CAdapter
&desc
) const
2641 H_AUTO_OGL(CDriverGL_getAdapter
)
2645 desc
.DeviceName
= (const char *) glGetString (GL_RENDERER
);
2646 desc
.Driver
= (const char *) glGetString (GL_VERSION
);
2647 desc
.Vendor
= (const char *) glGetString (GL_VENDOR
);
2649 desc
.Description
= "Default OpenGL adapter";
2651 desc
.DriverVersion
= 0;
2655 desc
.VideoMemory
= getTotalVideoMemory();
2661 // ***************************************************************************
2662 bool CDriverGL::setAdapter(uint adapter
)
2664 H_AUTO_OGL(CDriverGL_setAdapter
)
2666 return adapter
== 0;
2669 // ***************************************************************************
2670 CVertexBuffer::TVertexColorType
CDriverGL::getVertexColorFormat() const
2672 H_AUTO_OGL(CDriverGL_CDriverGL
)
2674 return CVertexBuffer::TRGBA
;
2677 // ***************************************************************************
2678 void CDriverGL::startBench (bool wantStandardDeviation
, bool quick
, bool reset
)
2680 CHTimer::startBench (wantStandardDeviation
, quick
, reset
);
2683 // ***************************************************************************
2684 void CDriverGL::endBench ()
2686 CHTimer::endBench ();
2689 // ***************************************************************************
2690 void CDriverGL::displayBench (class NLMISC::CLog
*log
)
2693 CHTimer::displayHierarchicalByExecutionPathSorted(log
, CHTimer::TotalTime
, true, 48, 2);
2694 CHTimer::displayHierarchical(log
, true, 48, 2);
2695 CHTimer::displayByExecutionPath(log
, CHTimer::TotalTime
);
2696 CHTimer::display(log
, CHTimer::TotalTime
);
2697 CHTimer::display(log
, CHTimer::TotalTimeWithoutSons
);
2701 void CDriverGL::dumpMappedBuffers()
2703 _AGPVertexArrayRange
->dumpMappedBuffers();
2707 // ***************************************************************************
2708 void CDriverGL::checkTextureOn() const
2710 H_AUTO_OGL(CDriverGL_checkTextureOn
)
2712 CDriverGLStates
&dgs
= const_cast<CDriverGLStates
&>(_DriverGLStates
);
2713 uint currTexStage
= dgs
.getActiveTextureARB();
2714 for(uint k
= 0; k
< this->getNbTextureStages(); ++k
)
2716 dgs
.activeTextureARB(k
);
2720 glGetBooleanv(GL_TEXTURE_2D
, &flag2D
);
2721 glGetBooleanv(GL_TEXTURE_CUBE_MAP_ARB
, &flagCM
);
2723 flagTR
= true; // always true in OpenGL ES
2725 glGetBooleanv(GL_TEXTURE_RECTANGLE_NV
, &flagTR
);
2727 switch(dgs
.getTextureMode())
2729 case CDriverGLStates::TextureDisabled
:
2733 case CDriverGLStates::Texture2D
:
2737 case CDriverGLStates::TextureRect
:
2741 case CDriverGLStates::TextureCubeMap
:
2749 dgs
.activeTextureARB(currTexStage
);
2752 // ***************************************************************************
2753 bool CDriverGL::supportOcclusionQuery() const
2755 H_AUTO_OGL(CDriverGL_supportOcclusionQuery
)
2756 return _Extensions
.NVOcclusionQuery
|| _Extensions
.ARBOcclusionQuery
;
2759 // ***************************************************************************
2760 bool CDriverGL::supportTextureRectangle() const
2762 H_AUTO_OGL(CDriverGL_supportTextureRectangle
);
2764 return (_Extensions
.NVTextureRectangle
|| _Extensions
.EXTTextureRectangle
|| _Extensions
.ARBTextureRectangle
);
2767 // ***************************************************************************
2768 bool CDriverGL::supportPackedDepthStencil() const
2770 H_AUTO_OGL(CDriverGL_supportPackedDepthStencil
);
2772 return _Extensions
.PackedDepthStencil
;
2775 // ***************************************************************************
2776 bool CDriverGL::supportFrameBufferObject() const
2778 H_AUTO_OGL(CDriverGL_supportFrameBufferObject
);
2780 return _Extensions
.FrameBufferObject
;
2783 // ***************************************************************************
2784 IOcclusionQuery
*CDriverGL::createOcclusionQuery()
2786 H_AUTO_OGL(CDriverGL_createOcclusionQuery
)
2787 nlassert(_Extensions
.NVOcclusionQuery
|| _Extensions
.ARBOcclusionQuery
);
2789 #ifndef USE_OPENGLES
2791 if (_Extensions
.NVOcclusionQuery
)
2792 nglGenOcclusionQueriesNV(1, &id
);
2794 nglGenQueriesARB(1, &id
);
2795 if (id
== 0) return NULL
;
2796 COcclusionQueryGL
*oqgl
= new COcclusionQueryGL
;
2797 oqgl
->Driver
= this;
2799 oqgl
->OcclusionType
= IOcclusionQuery::NotAvailable
;
2800 _OcclusionQueryList
.push_front(oqgl
);
2801 oqgl
->Iterator
= _OcclusionQueryList
.begin();
2802 oqgl
->VisibleCount
= 0;
2809 // ***************************************************************************
2810 void CDriverGL::deleteOcclusionQuery(IOcclusionQuery
*oq
)
2812 H_AUTO_OGL(CDriverGL_deleteOcclusionQuery
);
2814 #ifndef USE_OPENGLES
2816 COcclusionQueryGL
*oqgl
= NLMISC::safe_cast
<COcclusionQueryGL
*>(oq
);
2817 nlassert((CDriverGL
*) oqgl
->Driver
== this); // should come from the same driver
2818 oqgl
->Driver
= NULL
;
2819 nlassert(oqgl
->ID
!= 0);
2820 GLuint id
= oqgl
->ID
;
2821 if (_Extensions
.NVOcclusionQuery
)
2822 nglDeleteOcclusionQueriesNV(1, &id
);
2824 nglDeleteQueriesARB(1, &id
);
2825 _OcclusionQueryList
.erase(oqgl
->Iterator
);
2826 if (oqgl
== _CurrentOcclusionQuery
)
2828 _CurrentOcclusionQuery
= NULL
;
2834 // ***************************************************************************
2835 void COcclusionQueryGL::begin()
2837 H_AUTO_OGL(COcclusionQueryGL_begin
);
2839 #ifndef USE_OPENGLES
2841 nlassert(Driver
->_CurrentOcclusionQuery
== NULL
); // only one query at a time
2843 if (Driver
->_Extensions
.NVOcclusionQuery
)
2844 nglBeginOcclusionQueryNV(ID
);
2846 nglBeginQueryARB(GL_SAMPLES_PASSED
, ID
);
2847 Driver
->_CurrentOcclusionQuery
= this;
2848 OcclusionType
= NotAvailable
;
2853 // ***************************************************************************
2854 void COcclusionQueryGL::end()
2856 H_AUTO_OGL(COcclusionQueryGL_end
);
2858 #ifndef USE_OPENGLES
2860 nlassert(Driver
->_CurrentOcclusionQuery
== this); // only one query at a time
2862 if (Driver
->_Extensions
.NVOcclusionQuery
)
2863 nglEndOcclusionQueryNV();
2865 nglEndQueryARB(GL_SAMPLES_PASSED
);
2866 Driver
->_CurrentOcclusionQuery
= NULL
;
2870 // ***************************************************************************
2871 IOcclusionQuery::TOcclusionType
COcclusionQueryGL::getOcclusionType()
2873 H_AUTO_OGL(COcclusionQueryGL_getOcclusionType
);
2875 #ifndef USE_OPENGLES
2878 nlassert(Driver
->_CurrentOcclusionQuery
!= this); // can't query result between a begin/end pair!
2879 if (OcclusionType
== NotAvailable
)
2881 if (Driver
->_Extensions
.NVOcclusionQuery
)
2885 nglGetOcclusionQueryuivNV(ID
, GL_PIXEL_COUNT_AVAILABLE_NV
, &result
);
2886 if (result
!= GL_FALSE
)
2888 nglGetOcclusionQueryuivNV(ID
, GL_PIXEL_COUNT_NV
, &result
);
2889 OcclusionType
= result
!= 0 ? NotOccluded
: Occluded
;
2890 VisibleCount
= (uint
) result
;
2891 // Note : we could return the exact number of pixels that passed the z-test, but this value is not supported by all implementation (Direct3D ...)
2897 nglGetQueryObjectuivARB(ID
, GL_QUERY_RESULT_AVAILABLE
, &result
);
2898 if (result
!= GL_FALSE
)
2900 nglGetQueryObjectuivARB(ID
, GL_QUERY_RESULT
, &result
);
2901 OcclusionType
= result
!= 0 ? NotOccluded
: Occluded
;
2902 VisibleCount
= (uint
) result
;
2907 return OcclusionType
;
2910 // ***************************************************************************
2911 uint
COcclusionQueryGL::getVisibleCount()
2913 H_AUTO_OGL(COcclusionQueryGL_getVisibleCount
)
2916 nlassert(Driver
->_CurrentOcclusionQuery
!= this); // can't query result between a begin/end pair!
2917 if (getOcclusionType() == NotAvailable
) return 0;
2918 return VisibleCount
;
2921 // ***************************************************************************
2922 void CDriverGL::setDepthRange(float znear
, float zfar
)
2924 H_AUTO_OGL(CDriverGL_setDepthRange
)
2925 _DriverGLStates
.setDepthRange(znear
, zfar
);
2928 // ***************************************************************************
2929 void CDriverGL::getDepthRange(float &znear
, float &zfar
) const
2931 H_AUTO_OGL(CDriverGL_getDepthRange
)
2932 _DriverGLStates
.getDepthRange(znear
, zfar
);
2935 // ***************************************************************************
2936 void CDriverGL::setCullMode(TCullMode cullMode
)
2938 H_AUTO_OGL(CDriverGL_setCullMode
)
2939 _DriverGLStates
.setCullMode((CDriverGLStates::TCullMode
) cullMode
);
2942 // ***************************************************************************
2943 CDriverGL::TCullMode
CDriverGL::getCullMode() const
2945 H_AUTO_OGL(CDriverGL_CDriverGL
)
2946 return (CDriverGL::TCullMode
) _DriverGLStates
.getCullMode();
2949 // ***************************************************************************
2950 void CDriverGL::enableStencilTest(bool enable
)
2952 H_AUTO_OGL(CDriverGL_CDriverGL
)
2953 _DriverGLStates
.enableStencilTest(enable
);
2956 // ***************************************************************************
2957 bool CDriverGL::isStencilTestEnabled() const
2959 H_AUTO_OGL(CDriverGL_CDriverGL
)
2960 return _DriverGLStates
.isStencilTestEnabled();
2963 // ***************************************************************************
2964 void CDriverGL::stencilFunc(TStencilFunc stencilFunc
, int ref
, uint mask
)
2966 H_AUTO_OGL(CDriverGL_CDriverGL
)
2968 GLenum glstencilFunc
= 0;
2972 case IDriver::never
: glstencilFunc
=GL_NEVER
; break;
2973 case IDriver::less
: glstencilFunc
=GL_LESS
; break;
2974 case IDriver::lessequal
: glstencilFunc
=GL_LEQUAL
; break;
2975 case IDriver::equal
: glstencilFunc
=GL_EQUAL
; break;
2976 case IDriver::notequal
: glstencilFunc
=GL_NOTEQUAL
; break;
2977 case IDriver::greaterequal
: glstencilFunc
=GL_GEQUAL
; break;
2978 case IDriver::greater
: glstencilFunc
=GL_GREATER
; break;
2979 case IDriver::always
: glstencilFunc
=GL_ALWAYS
; break;
2983 _DriverGLStates
.stencilFunc(glstencilFunc
, (GLint
)ref
, (GLuint
)mask
);
2986 // ***************************************************************************
2987 void CDriverGL::stencilOp(TStencilOp fail
, TStencilOp zfail
, TStencilOp zpass
)
2989 H_AUTO_OGL(CDriverGL_CDriverGL
)
2991 GLenum glFail
= 0, glZFail
= 0, glZPass
= 0;
2995 case IDriver::keep
: glFail
=GL_KEEP
; break;
2996 case IDriver::zero
: glFail
=GL_ZERO
; break;
2997 case IDriver::replace
: glFail
=GL_REPLACE
; break;
2998 case IDriver::incr
: glFail
=GL_INCR
; break;
2999 case IDriver::decr
: glFail
=GL_DECR
; break;
3000 case IDriver::invert
: glFail
=GL_INVERT
; break;
3006 case IDriver::keep
: glZFail
=GL_KEEP
; break;
3007 case IDriver::zero
: glZFail
=GL_ZERO
; break;
3008 case IDriver::replace
: glZFail
=GL_REPLACE
; break;
3009 case IDriver::incr
: glZFail
=GL_INCR
; break;
3010 case IDriver::decr
: glZFail
=GL_DECR
; break;
3011 case IDriver::invert
: glZFail
=GL_INVERT
; break;
3017 case IDriver::keep
: glZPass
=GL_KEEP
; break;
3018 case IDriver::zero
: glZPass
=GL_ZERO
; break;
3019 case IDriver::replace
: glZPass
=GL_REPLACE
; break;
3020 case IDriver::incr
: glZPass
=GL_INCR
; break;
3021 case IDriver::decr
: glZPass
=GL_DECR
; break;
3022 case IDriver::invert
: glZPass
=GL_INVERT
; break;
3026 _DriverGLStates
.stencilOp(glFail
, glZFail
, glZPass
);
3029 // ***************************************************************************
3030 void CDriverGL::stencilMask(uint mask
)
3032 H_AUTO_OGL(CDriverGL_CDriverGL
)
3034 _DriverGLStates
.stencilMask((GLuint
)mask
);
3037 // ***************************************************************************
3038 void CDriverGL::getNumPerStageConstant(uint
&lightedMaterial
, uint
&unlightedMaterial
) const
3040 lightedMaterial
= inlGetNumTextStages();
3041 unlightedMaterial
= inlGetNumTextStages();
3044 // ***************************************************************************
3045 void CDriverGL::beginDialogMode()
3049 // ***************************************************************************
3050 void CDriverGL::endDialogMode()
3054 // ***************************************************************************
3055 void displayGLError(GLenum error
)
3059 case GL_NO_ERROR
: nlwarning("GL_NO_ERROR"); break;
3060 case GL_INVALID_ENUM
: nlwarning("GL_INVALID_ENUM"); break;
3061 case GL_INVALID_VALUE
: nlwarning("GL_INVALID_VALUE"); break;
3062 case GL_INVALID_OPERATION
: nlwarning("GL_INVALID_OPERATION"); break;
3063 case GL_STACK_OVERFLOW
: nlwarning("GL_STACK_OVERFLOW"); break;
3064 case GL_STACK_UNDERFLOW
: nlwarning("GL_STACK_UNDERFLOW"); break;
3065 case GL_OUT_OF_MEMORY
: nlwarning("GL_OUT_OF_MEMORY"); break;
3067 nlwarning("GL_ERROR");