Change Encyclo button name and macros icon
[ryzomcore.git] / nel / src / 3d / driver / opengl / driver_opengl_texture.cpp
blobe2a5978844d26156844c9bc68a67d59f3a3fe322
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013-2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "stdopengl.h"
22 #include "driver_opengl.h"
23 #include "nel/3d/texture_cube.h"
24 #include "nel/3d/texture_bloom.h"
25 #include "nel/misc/rect.h"
26 #include "nel/misc/file.h" // temp
28 // Define this to force nearest filter (debug)
29 // #define NEL_FORCE_NEAREST
31 using namespace NLMISC;
32 using namespace std;
34 #ifdef DEBUG_NEW
35 #define new DEBUG_NEW
36 #endif
38 //#define NEL_DUMP_UPLOAD_TIME
41 #ifdef NEL_DUMP_UPLOAD_TIME
42 #define NEL_MEASURE_UPLOAD_TIME_START NLMISC::TTicks startTick = CTime::getPerformanceTime();
43 #define NEL_MEASURE_UPLOAD_TIME_END NLMISC::TTicks endTick = CTime::getPerformanceTime(); \
44 nlinfo("3D: upload time = %.2f ms", (float) (1000 * (CTime::ticksToSecond(endTick) - CTime::ticksToSecond(startTick))));
45 #else
46 #define NEL_MEASURE_UPLOAD_TIME_START
47 #define NEL_MEASURE_UPLOAD_TIME_END
48 #endif
50 namespace NL3D {
52 #ifdef NL_STATIC
53 #ifdef USE_OPENGLES
54 namespace NLDRIVERGLES {
55 #else
56 namespace NLDRIVERGL {
57 #endif
58 #endif
60 // ***************************************************************************
61 CTextureDrvInfosGL::CTextureDrvInfosGL(IDriver *drv, ItTexDrvInfoPtrMap it, CDriverGL *drvGl, bool isRectangleTexture) : ITextureDrvInfos(drv, it)
63 H_AUTO_OGL(CTextureDrvInfosGL_CTextureDrvInfosGL)
64 //nldebug("3D: CTextureDrvInfosGL::ctor()");
65 // The id is auto created here.
66 glGenTextures(1,&ID);
68 Compressed = false;
69 MipMap = false;
70 TextureMemory = 0;
72 // Nb: at Driver dtor, all tex infos are deleted, so _Driver is always valid.
73 _Driver= drvGl;
75 #ifdef USE_OPENGLES
76 TextureMode = GL_TEXTURE_2D;
77 #else
78 TextureMode = isRectangleTexture?GL_TEXTURE_RECTANGLE_NV:GL_TEXTURE_2D;
79 #endif
81 FBOId = 0;
82 InitFBO = false;
83 AttachDepthStencil = true;
85 TextureUsedIdx = 0;
87 // ***************************************************************************
88 CTextureDrvInfosGL::~CTextureDrvInfosGL()
90 H_AUTO_OGL(CTextureDrvInfosGL_CTextureDrvInfosGLDtor)
91 // The id is auto deleted here.
92 glDeleteTextures(1,&ID);
94 // release profiling texture mem.
95 _Driver->_AllocatedTextureMemory-= TextureMemory;
97 // release in TextureUsed.
98 if (TextureUsedIdx < _Driver->_TextureUsed.size() && _Driver->_TextureUsed[TextureUsedIdx] == this)
100 _Driver->_TextureUsed[TextureUsedIdx] = NULL;
104 CDepthStencilFBO::CDepthStencilFBO(CDriverGL *driver, uint width, uint height)
106 //nldebug("3D: Init shared FBO");
108 m_Driver = driver;
109 Width = width;
110 Height = height;
112 bool packedDepthStencil = driver->supportPackedDepthStencil();
113 nglGenRenderbuffersEXT(1, &DepthFBOId);
114 if (packedDepthStencil)
115 StencilFBOId = DepthFBOId;
116 else
117 nglGenRenderbuffersEXT(1, &StencilFBOId);
119 if (packedDepthStencil)
121 //nldebug("3D: using packed depth stencil");
122 nglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilFBOId);
123 nglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, width, height);
125 else
127 nglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthFBOId);
128 nglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height);
130 nglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilFBOId);
131 nglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT, width, height);
135 nlassert(DepthFBOId);
136 nlassert(StencilFBOId);
138 driver->_DepthStencilFBOs.push_back(this);
141 CDepthStencilFBO::~CDepthStencilFBO()
143 // driver remove
144 m_Driver->_DepthStencilFBOs.erase(std::find(m_Driver->_DepthStencilFBOs.begin(), m_Driver->_DepthStencilFBOs.end(), this));
146 if (DepthFBOId)
148 //nldebug("3D: Release shared FBO");
149 nglDeleteRenderbuffersEXT(1, &DepthFBOId);
150 if (StencilFBOId == DepthFBOId)
151 StencilFBOId = 0;
152 DepthFBOId = 0;
154 if (StencilFBOId)
156 nglDeleteRenderbuffersEXT(1, &StencilFBOId);
157 StencilFBOId = 0;
161 // ***************************************************************************
162 bool CTextureDrvInfosGL::initFrameBufferObject(ITexture * tex)
164 if (!InitFBO)
166 if (tex->isBloomTexture())
168 AttachDepthStencil = !((CTextureBloom*)tex)->isMode2D();
171 // generate IDs
172 nglGenFramebuffersEXT(1, &FBOId);
174 //nldebug("3D: using depth %d and stencil %d", DepthFBOId, StencilFBOId);
176 // initialize FBO
177 nglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBOId);
178 nglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, TextureMode, ID, 0);
180 // attach depth stencil
181 if (AttachDepthStencil)
183 for (std::vector<CDepthStencilFBO *>::iterator it(_Driver->_DepthStencilFBOs.begin()), end(_Driver->_DepthStencilFBOs.end()); it != end; ++it)
185 if ((*it)->Width == tex->getWidth() && (*it)->Height == tex->getHeight())
187 DepthStencilFBO = (*it);
188 break;
191 if (!DepthStencilFBO)
193 DepthStencilFBO = new CDepthStencilFBO(_Driver, tex->getWidth(), tex->getHeight());
195 nglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
196 GL_RENDERBUFFER_EXT, DepthStencilFBO->DepthFBOId);
197 //nldebug("3D: glFramebufferRenderbufferExt(depth:24) = %X", nglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
198 nglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
199 GL_RENDERBUFFER_EXT, DepthStencilFBO->StencilFBOId);
200 //nldebug("3D: glFramebufferRenderbufferExt(stencil:8) = %X", nglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
203 // check status
204 GLenum status = (GLenum) nglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
206 switch(status) {
207 #ifdef GL_FRAMEBUFFER_COMPLETE_EXT
208 case GL_FRAMEBUFFER_COMPLETE_EXT:
209 InitFBO = true;
210 break;
211 #endif
212 #ifdef GL_FRAMEBUFFER_COMPLETE_OES
213 case GL_FRAMEBUFFER_COMPLETE_OES:
214 InitFBO = true;
215 break;
216 #endif
217 #ifdef GL_FRAMEBUFFER_UNSUPPORTED_EXT
218 case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
219 nlwarning("Unsupported framebuffer format");
220 break;
221 #endif
222 #ifdef GL_FRAMEBUFFER_UNSUPPORTED_OES
223 case GL_FRAMEBUFFER_UNSUPPORTED_OES:
224 nlwarning("Unsupported framebuffer format");
225 break;
226 #endif
227 #ifdef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
228 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
229 nlwarning("Framebuffer incomplete attachment");
230 break;
231 #endif
232 #ifdef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES
233 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES:
234 nlwarning("Framebuffer incomplete attachment");
235 break;
236 #endif
237 #ifdef GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT
238 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
239 nlwarning("Framebuffer incomplete, missing attachment");
240 break;
241 #endif
242 #ifdef GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES
243 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES:
244 nlwarning("Framebuffer incomplete, missing attachment");
245 break;
246 #endif
247 #ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT
248 case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
249 nlwarning("Framebuffer incomplete, duplicate attachment");
250 break;
251 #endif
252 #ifdef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT
253 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
254 nlwarning("Framebuffer incomplete, attached images must have same dimensions");
255 break;
256 #endif
257 #ifdef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES
258 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES:
259 nlwarning("Framebuffer incomplete, attached images must have same dimensions");
260 break;
261 #endif
262 #ifdef GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT
263 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
264 nlwarning("Framebuffer incomplete, attached images must have same format");
265 break;
266 #endif
267 #ifdef GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES
268 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES:
269 nlwarning("Framebuffer incomplete, attached images must have same format");
270 break;
271 #endif
272 #ifdef GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT
273 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
274 nlwarning("Framebuffer incomplete, missing draw buffer");
275 break;
276 #endif
277 #ifdef GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT
278 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
279 nlwarning("Framebuffer incomplete, missing read buffer");
280 break;
281 #endif
282 #ifdef GL_FRAMEBUFFER_BINDING_EXT
283 case GL_FRAMEBUFFER_BINDING_EXT:
284 nlwarning("Framebuffer BINDING_EXT");
285 break;
286 #endif
287 #ifdef GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
288 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
289 nlwarning("Framebuffer incomplete multisample");
290 break;
291 #endif
292 #ifdef GL_FRAMEBUFFER_BINDING_OES
293 case GL_FRAMEBUFFER_BINDING_OES:
294 nlwarning("Framebuffer BINDING_EXT");
295 break;
296 #endif
297 default:
298 nlwarning("Framebuffer incomplete status %d", (sint)status);
299 //nlassert(0);
302 // clean up resources if allocation failed
303 if (!InitFBO)
305 nglDeleteFramebuffersEXT(1, &FBOId);
307 if (AttachDepthStencil)
309 DepthStencilFBO = NULL;
315 return InitFBO;
318 // ***************************************************************************
319 bool CTextureDrvInfosGL::activeFrameBufferObject(ITexture * tex)
321 if(tex)
323 if(initFrameBufferObject(tex))
325 glBindTexture(TextureMode, 0);
326 nglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBOId);
328 else
329 return false;
331 else
333 nglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
336 return true;
339 // ***************************************************************************
340 // Get the glText mirror of an existing setuped texture.
341 static inline CTextureDrvInfosGL* getTextureGl(ITexture& tex)
343 H_AUTO_OGL(getTextureGl)
344 CTextureDrvInfosGL* gltex;
345 gltex= (CTextureDrvInfosGL*)(ITextureDrvInfos*)(tex.TextureDrvShare->DrvTexture);
346 return gltex;
349 // ***************************************************************************
350 // Translation of TexFmt mode.
351 GLint CDriverGL::getGlTextureFormat(ITexture& tex, bool &compressed)
353 H_AUTO_OGL(CDriverGL_getGlTextureFormat)
354 ITexture::TUploadFormat texfmt= tex.getUploadFormat();
356 // If auto, retrieve the pixel format of the bitmap.
357 if(texfmt== ITexture::Auto)
359 switch(tex.getPixelFormat())
361 case CBitmap::RGBA:
362 if(_ForceDXTCCompression && tex.allowDegradation() )
363 texfmt= ITexture::DXTC5;
364 else
365 texfmt= ITexture::RGBA8888;
366 break;
367 case CBitmap::DXTC1: texfmt= ITexture::DXTC1; break;
368 case CBitmap::DXTC1Alpha: texfmt= ITexture::DXTC1Alpha; break;
369 case CBitmap::DXTC3: texfmt= ITexture::DXTC3; break;
370 case CBitmap::DXTC5: texfmt= ITexture::DXTC5; break;
371 case CBitmap::Luminance: texfmt= ITexture::Luminance; break;
372 case CBitmap::Alpha: texfmt= ITexture::Alpha; break;
373 case CBitmap::AlphaLuminance: texfmt= ITexture::AlphaLuminance; break;
374 case CBitmap::DsDt: texfmt= ITexture::DsDt; break;
375 default: texfmt= ITexture::RGBA8888; break;
379 // Get gl tex format, try S3TC compressed ones.
380 if(_Extensions.EXTTextureCompressionS3TC)
382 compressed= true;
383 // Try Compressed ones.
384 switch(texfmt)
386 #ifdef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
387 case ITexture::DXTC1: return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
388 #endif
389 #ifdef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
390 case ITexture::DXTC1Alpha: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
391 #endif
392 #ifdef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
393 case ITexture::DXTC3: return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
394 #endif
395 #ifdef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
396 case ITexture::DXTC5: return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
397 #endif
398 default: break;
402 // Get standard gl tex format.
403 compressed= false;
404 switch(texfmt)
406 #ifdef USE_OPENGLES
407 case ITexture::RGBA8888: return GL_RGBA;
408 // case ITexture::RGBA4444: return GL_RGBA4_OES;
409 // case ITexture::RGBA5551: return GL_RGB5_A1_OES;
410 case ITexture::RGB888: return GL_RGB;
411 // case ITexture::RGB565: return GL_RGB5_OES;
412 case ITexture::Luminance: return GL_LUMINANCE;
413 case ITexture::Alpha: return GL_ALPHA;
414 case ITexture::AlphaLuminance: return GL_LUMINANCE_ALPHA;
415 #else
416 case ITexture::RGBA8888: return GL_RGBA8;
417 case ITexture::RGBA4444: return GL_RGBA4;
418 case ITexture::RGBA5551: return GL_RGB5_A1;
419 case ITexture::RGB888: return GL_RGB8;
420 case ITexture::RGB565: return GL_RGB5;
421 case ITexture::Luminance: return GL_LUMINANCE8;
422 case ITexture::Alpha: return GL_ALPHA8;
423 case ITexture::AlphaLuminance: return GL_LUMINANCE8_ALPHA8;
424 case ITexture::DsDt:
425 if (_Extensions.NVTextureShader) return GL_DSDT_NV;
426 else if (_Extensions.ATIEnvMapBumpMap || _Extensions.ATIFragmentShader)
428 return GL_DU8DV8_ATI;
430 else
432 nlassert(0);
433 return 0;
435 break;
436 #endif
437 default:
438 break;
441 return GL_RGBA8;
444 // ***************************************************************************
445 static GLint getGlSrcTextureFormat(ITexture &tex, GLint glfmt)
447 H_AUTO_OGL(getGlSrcTextureFormat)
449 // Is destination format is alpha or lumiance ?
450 if ((glfmt==GL_ALPHA8)||(glfmt==GL_LUMINANCE8_ALPHA8)||(glfmt==GL_LUMINANCE8))
452 switch(tex.getPixelFormat())
454 case CBitmap::Alpha: return GL_ALPHA;
455 case CBitmap::AlphaLuminance: return GL_LUMINANCE_ALPHA;
456 case CBitmap::Luminance: return GL_LUMINANCE;
457 default: break;
461 #ifndef USE_OPENGLES
462 if (glfmt == GL_DSDT_NV)
464 return GL_DSDT_NV;
467 if (glfmt == GL_DU8DV8_ATI)
469 return GL_DUDV_ATI;
471 #endif
473 // Else, not a Src format for upload, or RGBA.
474 return GL_RGBA;
477 // ***************************************************************************
478 static GLenum getGlSrcTextureComponentType(GLint texSrcFormat)
480 H_AUTO_OGL(getGlSrcTextureComponentType);
482 #ifndef USE_OPENGLES
483 switch (texSrcFormat)
485 case GL_DSDT_NV:
486 case GL_DUDV_ATI:
487 return GL_BYTE; // these are signed format
488 break;
489 default:
490 break;
492 #endif
494 return GL_UNSIGNED_BYTE;
497 // ***************************************************************************
498 uint CDriverGL::computeMipMapMemoryUsage(uint w, uint h, GLint glfmt) const
500 H_AUTO_OGL(CDriverGL_computeMipMapMemoryUsage)
501 switch(glfmt)
503 case GL_RGBA8: return w*h* 4;
504 // Well this is ugly, but simple :). GeForce 888 is stored as 32 bits.
505 case GL_RGB8: return w*h* 4;
506 #ifdef GL_RGBA4
507 case GL_RGBA4: return w*h* 2;
508 #endif
509 #ifdef GL_RGB5_A1
510 case GL_RGB5_A1: return w*h* 2;
511 #endif
512 #ifdef GL_RGB5
513 case GL_RGB5: return w*h* 2;
514 #endif
515 case GL_LUMINANCE8: return w*h* 1;
516 case GL_ALPHA8: return w*h* 1;
517 case GL_LUMINANCE8_ALPHA8: return w*h* 2;
518 #ifdef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
519 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return w*h /2;
520 #endif
521 #ifdef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
522 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return w*h /2;
523 #endif
524 #ifdef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
525 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return w*h* 1;
526 #endif
527 #ifdef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
528 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return w*h* 1;
529 #endif
530 #ifdef GL_DU8DV8_ATI
531 case GL_DU8DV8_ATI:
532 #endif
533 #ifdef GL_DSDT_NV
534 case GL_DSDT_NV: return w*h* 2;
535 #endif
538 // One format has not been coded.
539 nlstop;
541 /// ???
542 return w*h* 4;
545 // ***************************************************************************
546 // Translation of Wrap mode.
547 static inline GLenum translateWrapToGl(ITexture::TWrapMode mode, const CGlExtensions &extensions)
549 H_AUTO_OGL(translateWrapToGl)
550 if(mode== ITexture::Repeat)
551 return GL_REPEAT;
553 #ifdef USE_OPENGLES
554 return GL_CLAMP_TO_EDGE;
555 #else
556 if(extensions.Version1_2)
557 return GL_CLAMP_TO_EDGE;
559 return GL_CLAMP;
560 #endif
563 // ***************************************************************************
564 static inline GLenum translateMagFilterToGl(CTextureDrvInfosGL *glText)
566 H_AUTO_OGL(translateMagFilterToGl)
567 #ifdef NEL_FORCE_NEAREST
568 return GL_NEAREST;
569 #else // NEL_FORCE_NEAREST
570 switch(glText->MagFilter)
572 case ITexture::Linear: return GL_LINEAR;
573 case ITexture::Nearest: return GL_NEAREST;
574 default: break;
577 nlstop;
578 return GL_LINEAR;
579 #endif // NEL_FORCE_NEAREST
583 // ***************************************************************************
584 static inline GLenum translateMinFilterToGl(CTextureDrvInfosGL *glText)
586 H_AUTO_OGL(translateMinFilterToGl)
587 #ifdef NEL_FORCE_NEAREST
588 return GL_NEAREST;
589 #else // NEL_FORCE_NEAREST
591 if(glText->MipMap)
593 switch(glText->MinFilter)
595 case ITexture::NearestMipMapOff: return GL_NEAREST;
596 case ITexture::NearestMipMapNearest: return GL_NEAREST_MIPMAP_NEAREST;
597 case ITexture::NearestMipMapLinear: return GL_NEAREST_MIPMAP_LINEAR;
598 case ITexture::LinearMipMapOff: return GL_LINEAR;
599 case ITexture::LinearMipMapNearest: return GL_LINEAR_MIPMAP_NEAREST;
600 case ITexture::LinearMipMapLinear: return GL_LINEAR_MIPMAP_LINEAR;
601 default: break;
604 else
606 switch(glText->MinFilter)
608 case ITexture::NearestMipMapOff:
609 case ITexture::NearestMipMapNearest:
610 case ITexture::NearestMipMapLinear:
611 return GL_NEAREST;
612 case ITexture::LinearMipMapOff:
613 case ITexture::LinearMipMapNearest:
614 case ITexture::LinearMipMapLinear:
615 return GL_LINEAR;
616 default: break;
620 nlstop;
621 return GL_LINEAR;
622 #endif // NEL_FORCE_NEAREST
625 // ***************************************************************************
626 static inline bool sameDXTCFormat(ITexture &tex, GLint glfmt)
628 H_AUTO_OGL(sameDXTCFormat);
630 #ifdef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
631 if(glfmt==GL_COMPRESSED_RGB_S3TC_DXT1_EXT && tex.PixelFormat==CBitmap::DXTC1)
632 return true;
633 #endif
635 #ifdef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
636 if(glfmt==GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && tex.PixelFormat==CBitmap::DXTC1Alpha)
637 return true;
638 #endif
640 #ifdef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
641 if(glfmt==GL_COMPRESSED_RGBA_S3TC_DXT3_EXT && tex.PixelFormat==CBitmap::DXTC3)
642 return true;
643 #endif
645 #ifdef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
646 if(glfmt==GL_COMPRESSED_RGBA_S3TC_DXT5_EXT && tex.PixelFormat==CBitmap::DXTC5)
647 return true;
648 #endif
650 return false;
653 // ***************************************************************************
654 static inline bool isDXTCFormat(GLint glfmt)
656 H_AUTO_OGL(isDXTCFormat);
658 #ifdef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
659 if(glfmt==GL_COMPRESSED_RGB_S3TC_DXT1_EXT)
660 return true;
661 #endif
663 #ifdef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
664 if(glfmt==GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
665 return true;
666 #endif
668 #ifdef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
669 if(glfmt==GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)
670 return true;
671 #endif
673 #ifdef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
674 if(glfmt==GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
675 return true;
676 #endif
678 return false;
681 // ***************************************************************************
682 bool CDriverGL::setupTexture (ITexture& tex)
684 H_AUTO_OGL(setupTexture)
685 bool nTmp;
686 return setupTextureEx (tex, true, nTmp);
689 // ***************************************************************************
690 #ifndef NL_DEBUG
691 inline
692 #endif
693 void CDriverGL::bindTextureWithMode(ITexture &tex)
695 CTextureDrvInfosGL* gltext;
696 gltext= getTextureGl(tex);
697 // system of "backup the previous binded texture" seems to not work with some drivers....
698 _DriverGLStates.activeTextureARB(0);
699 if(tex.isTextureCube())
701 if (_Extensions.ARBTextureCubeMap)
703 _DriverGLStates.setTextureMode(CDriverGLStates::TextureCubeMap);
704 // Bind this texture
705 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, gltext->ID);
708 else
710 CDriverGLStates::TTextureMode textureMode= CDriverGLStates::Texture2D;
711 #ifndef USE_OPENGLES
712 if(gltext->TextureMode == GL_TEXTURE_RECTANGLE_NV)
713 textureMode = CDriverGLStates::TextureRect;
714 #endif
716 _DriverGLStates.setTextureMode(textureMode);
717 // Bind this texture
718 glBindTexture(gltext->TextureMode, gltext->ID);
722 // ***************************************************************************
723 #ifndef NL_DEBUG
724 inline
725 #endif
726 void CDriverGL::setupTextureBasicParameters(ITexture &tex)
728 CTextureDrvInfosGL* gltext;
729 gltext= getTextureGl(tex);
730 // TODO: possible cache here, but beware, this is called just after texture creation as well, so these fields
731 // haven't ever been filled.
732 gltext->WrapS= tex.getWrapS();
733 gltext->WrapT= tex.getWrapT();
734 gltext->MagFilter= tex.getMagFilter();
735 gltext->MinFilter= tex.getMinFilter();
736 if(tex.isTextureCube())
738 if (_Extensions.ARBTextureCubeMap)
740 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_WRAP_S, translateWrapToGl(ITexture::Clamp, _Extensions));
741 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_WRAP_T, translateWrapToGl(ITexture::Clamp, _Extensions));
742 #ifndef USE_OPENGLES
743 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_WRAP_R, translateWrapToGl(ITexture::Clamp, _Extensions));
744 #endif
745 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_MAG_FILTER, translateMagFilterToGl(gltext));
746 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_MIN_FILTER, translateMinFilterToGl(gltext));
748 if (_AnisotropicFilter > 1.f && gltext->MinFilter > ITexture::NearestMipMapLinear)
749 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAX_ANISOTROPY_EXT, _AnisotropicFilter);
752 else
754 glTexParameteri(gltext->TextureMode,GL_TEXTURE_WRAP_S, translateWrapToGl(gltext->WrapS, _Extensions));
755 glTexParameteri(gltext->TextureMode,GL_TEXTURE_WRAP_T, translateWrapToGl(gltext->WrapT, _Extensions));
756 glTexParameteri(gltext->TextureMode,GL_TEXTURE_MAG_FILTER, translateMagFilterToGl(gltext));
757 glTexParameteri(gltext->TextureMode,GL_TEXTURE_MIN_FILTER, translateMinFilterToGl(gltext));
759 if (_AnisotropicFilter > 1.f && gltext->MinFilter > ITexture::NearestMipMapLinear)
760 glTexParameteri(gltext->TextureMode, GL_TEXTURE_MAX_ANISOTROPY_EXT, _AnisotropicFilter);
763 tex.clearFilterOrWrapModeTouched();
766 // ***************************************************************************
767 bool CDriverGL::setupTextureEx (ITexture& tex, bool bUpload, bool &bAllUploaded, bool bMustRecreateSharedTexture)
769 H_AUTO_OGL(setupTextureEx)
770 //nldebug("3D: CDriverGL::setupTextureEx(%016p, %d, %d, %d)", &tex, bUpload, bAllUploaded, bMustRecreateSharedTexture);
771 bAllUploaded = false;
773 if(tex.isTextureCube() && (!_Extensions.ARBTextureCubeMap))
774 return true;
776 // 0. Create/Retrieve the driver texture.
777 //=======================================
778 bool mustCreate = false;
779 if ( !tex.TextureDrvShare )
781 //nldebug("3D: creating CTextureDrvShare()");
782 // insert into driver list. (so it is deleted when driver is deleted).
783 ItTexDrvSharePtrList it= _TexDrvShares.insert(_TexDrvShares.end(), (NL3D::CTextureDrvShare*)NULL);
784 // create and set iterator, for future deletion.
785 *it= tex.TextureDrvShare= new CTextureDrvShare(this, it, &tex);
787 // Must (re)-create the texture.
788 mustCreate = true;
791 // Does the texture has been touched ?
792 if ( (!tex.touched()) && (!mustCreate) )
794 // if wrap mode or filter mode is touched, update it here
795 if (tex.filterOrWrapModeTouched())
797 activateTexture(0, NULL); // unbind any previous texture
798 bindTextureWithMode(tex);
800 setupTextureBasicParameters(tex); // setup what has changed (will reset the touch flag)
802 // Disable texture 0
803 _CurrentTexture[0]= NULL;
804 _CurrentTextureInfoGL[0]= NULL;
805 _DriverGLStates.setTextureMode(CDriverGLStates::TextureDisabled);
809 return true; // Do not do anything
812 // 1. If modified, may (re)load texture part or all of the texture.
813 //=================================================================
815 bool mustLoadAll= false;
816 bool mustLoadPart= false;
818 // To avoid any delete/new ptr problem, disable all texturing.
819 /* If an old texture is deleted, _CurrentTexture[*] and _CurrentTextureInfoGL[*] are invalid.
820 But this is grave only if a new texture is created, with the same pointer (bad luck).
821 Since an newly allocated texture always pass here before use, we are sure to avoid any problems.
823 for(uint stage = 0; stage < inlGetNumTextStages(); stage++)
825 activateTexture(stage, NULL);
828 // A. Share mgt.
829 //==============
830 if(tex.supportSharing())
832 // Try to get the shared texture.
834 // Create the shared Name.
835 std::string name;
836 getTextureShareName (tex, name);
838 // insert or get the texture.
840 CSynchronized<TTexDrvInfoPtrMap>::CAccessor access(&_SyncTexDrvInfos);
841 TTexDrvInfoPtrMap &rTexDrvInfos = access.value();
843 ItTexDrvInfoPtrMap itTex;
844 itTex= rTexDrvInfos.find(name);
846 // texture not found?
847 if( itTex==rTexDrvInfos.end() )
849 // insert into driver map. (so it is deleted when driver is deleted).
850 itTex= (rTexDrvInfos.insert(make_pair(name, (ITextureDrvInfos*)NULL))).first;
851 // create and set iterator, for future deletion.
852 itTex->second= tex.TextureDrvShare->DrvTexture = new CTextureDrvInfosGL(this, itTex, this, isTextureRectangle(&tex));
854 // need to load ALL this texture.
855 mustLoadAll= true;
857 else
859 tex.TextureDrvShare->DrvTexture= itTex->second;
861 if(bMustRecreateSharedTexture)
862 // reload this shared texture (user request)
863 mustLoadAll= true;
864 else
865 // Do not need to reload this texture, even if the format/mipmap has changed, since we found this
866 // couple in the map.
867 mustLoadAll= false;
870 // Do not test if part of texture may need to be computed, because Rect invalidation is incompatible
871 // with texture sharing.
873 else
875 // If texture not already created.
876 if(!tex.TextureDrvShare->DrvTexture)
878 // Must create it. Create auto a GL id (in constructor).
879 // Do not insert into the map. This un-shared texture will be deleted at deletion of the texture.
880 // Inform ITextureDrvInfos by passing NULL _Driver.
881 tex.TextureDrvShare->DrvTexture = new CTextureDrvInfosGL(NULL, ItTexDrvInfoPtrMap(), this, isTextureRectangle(&tex));
883 // need to load ALL this texture.
884 mustLoadAll= true;
886 else if(tex.isAllInvalidated())
887 mustLoadAll= true;
888 else if(tex.touched())
889 mustLoadPart= true;
892 // B. Setup texture.
893 //==================
894 if(mustLoadAll || mustLoadPart)
896 // system of "backup the previous binded texture" seems to not work with some drivers....
897 bindTextureWithMode(tex);
899 CTextureDrvInfosGL* gltext;
900 gltext= getTextureGl(tex);
902 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
904 // a. Load All the texture case.
905 //==============================
906 if (mustLoadAll)
908 // profiling. sub old textre memory usage, and reset.
909 _AllocatedTextureMemory-= gltext->TextureMemory;
910 gltext->TextureMemory= 0;
913 if(tex.isTextureCube())
915 CTextureCube *pTC = NLMISC::safe_cast<CTextureCube *>(&tex);
917 // Regenerate all the texture.
918 tex.generate();
920 for(uint nText = 0; nText < 6; ++nText)
921 if(pTC->getTexture((CTextureCube::TFace)nText) != NULL)
923 ITexture *pTInTC = pTC->getTexture((CTextureCube::TFace)nText);
925 // In open GL, we have to flip the faces of the cube map
926 if( ((CTextureCube::TFace)nText) == CTextureCube::positive_x )
927 pTInTC->flipH();
928 if( ((CTextureCube::TFace)nText) == CTextureCube::negative_x )
929 pTInTC->flipH();
930 if( ((CTextureCube::TFace)nText) == CTextureCube::positive_y )
931 pTInTC->flipH();
932 if( ((CTextureCube::TFace)nText) == CTextureCube::negative_y )
933 pTInTC->flipH();
934 if( ((CTextureCube::TFace)nText) == CTextureCube::positive_z )
935 pTInTC->flipV();
936 if( ((CTextureCube::TFace)nText) == CTextureCube::negative_z )
937 pTInTC->flipV();
939 // Get the correct texture format from texture...
940 GLint glfmt= getGlTextureFormat(*pTInTC, gltext->Compressed);
941 GLint glSrcFmt= getGlSrcTextureFormat(*pTInTC, glfmt);
942 GLenum glSrcType= getGlSrcTextureComponentType(glSrcFmt);
944 sint nMipMaps;
945 if(glSrcFmt==GL_RGBA && pTInTC->getPixelFormat()!=CBitmap::RGBA )
946 pTInTC->convertToType(CBitmap::RGBA);
947 if(tex.mipMapOn())
949 pTInTC->buildMipMaps();
950 nMipMaps= pTInTC->getMipMapCount();
952 else
953 nMipMaps= 1;
955 // MipMap upload?
956 gltext->MipMap= nMipMaps>1;
958 // Fill mipmaps.
959 for(sint i=0;i<nMipMaps;i++)
961 void *ptr= pTInTC->getPixels(i).getPtr();
962 uint w= pTInTC->getWidth(i);
963 uint h= pTInTC->getHeight(i);
964 if (bUpload)
966 NEL_MEASURE_UPLOAD_TIME_START
967 glTexImage2D (NLCubeFaceToGLCubeFace[nText], i, glfmt, w, h, 0, glSrcFmt, glSrcType, ptr);
968 bAllUploaded = true;
969 NEL_MEASURE_UPLOAD_TIME_END
971 else
973 NEL_MEASURE_UPLOAD_TIME_START
974 glTexImage2D (NLCubeFaceToGLCubeFace[nText], i, glfmt, w, h, 0, glSrcFmt, glSrcType, NULL);
975 NEL_MEASURE_UPLOAD_TIME_END
977 // profiling: count TextureMemory usage.
978 gltext->TextureMemory+= computeMipMapMemoryUsage(w, h, glfmt);
982 else
984 // Regenerate all the texture.
985 tex.generate();
987 if(tex.getSize()>0)
989 // Get the correct texture format from texture...
990 GLint glfmt= getGlTextureFormat(tex, gltext->Compressed);
991 GLint glSrcFmt= getGlSrcTextureFormat(tex, glfmt);
992 GLenum glSrcType= getGlSrcTextureComponentType(glSrcFmt);
994 // DXTC: if same format, and same mipmapOn/Off, use glTexCompressedImage*.
995 // We cannot build the mipmaps if they are not here.
996 if(_Extensions.EXTTextureCompressionS3TC && sameDXTCFormat(tex, glfmt))
998 sint nMipMaps = 1;
1000 if(tex.mipMapOn())
1001 nMipMaps= tex.getMipMapCount();
1003 // MipMap upload?
1004 gltext->MipMap= nMipMaps>1;
1006 // Degradation in Size allowed only if DXTC texture are provided with mipmaps.
1007 // Because use them to resize !!!
1008 uint decalMipMapResize= 0;
1009 if(_ForceTextureResizePower>0 && tex.allowDegradation() && nMipMaps>1)
1011 decalMipMapResize= min(_ForceTextureResizePower, (uint)(nMipMaps-1));
1014 // Fill mipmaps.
1015 for(sint i=decalMipMapResize;i<nMipMaps;i++)
1017 void *ptr= tex.getPixels(i).getPtr();
1018 sint size= tex.getPixels(i).size();
1019 if (bUpload)
1021 #ifdef USE_OPENGLES
1022 glCompressedTexImage2D (GL_TEXTURE_2D, i-decalMipMapResize, glfmt,
1023 tex.getWidth(i),tex.getHeight(i), 0, size, ptr);
1024 #else
1025 nglCompressedTexImage2DARB (GL_TEXTURE_2D, i-decalMipMapResize, glfmt,
1026 tex.getWidth(i),tex.getHeight(i), 0, size, ptr);
1027 #endif
1028 bAllUploaded = true;
1030 else
1032 //glCompressedTexImage2DARB (GL_TEXTURE_2D, i-decalMipMapResize, glfmt,
1033 // tex.getWidth(i),tex.getHeight(i), 0, size, NULL);
1034 NEL_MEASURE_UPLOAD_TIME_START
1036 glTexImage2D (gltext->TextureMode, i-decalMipMapResize, glfmt, tex.getWidth(i), tex.getHeight(i),
1037 0, glSrcFmt, glSrcType, NULL);
1038 NEL_MEASURE_UPLOAD_TIME_END
1041 // profiling: count TextureMemory usage.
1042 gltext->TextureMemory+= tex.getPixels(i).size();
1045 else
1047 sint nMipMaps;
1048 if(glSrcFmt==GL_RGBA && tex.getPixelFormat()!=CBitmap::RGBA )
1050 bUpload = true; // Force all upload
1051 tex.convertToType(CBitmap::RGBA);
1054 // Degradation in Size.
1055 if(_ForceTextureResizePower>0 && tex.allowDegradation())
1057 uint w= tex.getWidth(0) >> _ForceTextureResizePower;
1058 uint h= tex.getHeight(0) >> _ForceTextureResizePower;
1059 w= max(1U, w);
1060 h= max(1U, h);
1061 tex.resample(w, h);
1064 if(tex.mipMapOn())
1066 tex.buildMipMaps();
1067 nMipMaps= tex.getMipMapCount();
1069 else
1070 nMipMaps= 1;
1072 // MipMap upload?
1073 gltext->MipMap= nMipMaps>1;
1075 // Fill mipmaps.
1076 for(sint i=0;i<nMipMaps;i++)
1078 void *ptr= tex.getPixels(i).getPtr();
1079 uint w= tex.getWidth(i);
1080 uint h= tex.getHeight(i);
1082 if (bUpload)
1084 NEL_MEASURE_UPLOAD_TIME_START
1085 glTexImage2D (gltext->TextureMode, i, glfmt, w, h, 0,glSrcFmt, glSrcType, ptr);
1086 NEL_MEASURE_UPLOAD_TIME_END
1087 bAllUploaded = true;
1089 else
1091 NEL_MEASURE_UPLOAD_TIME_START
1092 glTexImage2D (gltext->TextureMode, i, glfmt, w, h, 0,glSrcFmt, glSrcType, NULL);
1093 NEL_MEASURE_UPLOAD_TIME_END
1095 // profiling: count TextureMemory usage.
1096 gltext->TextureMemory += computeMipMapMemoryUsage (w, h, glfmt);
1101 //printf("%d,%d,%d\n", tex.getMipMapCount(), tex.getWidth(0), tex.getHeight(0));
1103 // profiling. add new TextureMemory usage.
1104 _AllocatedTextureMemory+= gltext->TextureMemory;
1106 // b. Load part of the texture case.
1107 //==================================
1108 // Replace parts of a compressed image. Maybe don't work with the actual system of invalidateRect()...
1109 else if (mustLoadPart && !gltext->Compressed)
1111 // Regenerate wanted part of the texture.
1112 tex.generate();
1114 if(tex.getSize()>0)
1116 // Get the correct texture format from texture...
1117 //===============================================
1118 bool dummy;
1119 GLint glfmt= getGlTextureFormat(tex, dummy);
1120 GLint glSrcFmt= getGlSrcTextureFormat(tex, glfmt);
1121 GLenum glSrcType= getGlSrcTextureComponentType(glSrcFmt);
1123 sint nMipMaps;
1124 if(glSrcFmt==GL_RGBA && tex.getPixelFormat()!=CBitmap::RGBA )
1125 tex.convertToType(CBitmap::RGBA);
1126 if(tex.mipMapOn())
1128 bool hadMipMap= tex.getMipMapCount()>1;
1129 tex.buildMipMaps();
1130 nMipMaps= tex.getMipMapCount();
1131 // If the texture had no mipmap before, release them.
1132 if(!hadMipMap)
1134 tex.releaseMipMaps();
1137 else
1138 nMipMaps= 1;
1140 // For all rect, update the texture/mipmap.
1141 //===============================================
1142 list<NLMISC::CRect>::iterator itRect;
1143 for(itRect=tex._ListInvalidRect.begin(); itRect!=tex._ListInvalidRect.end(); itRect++)
1145 CRect &rect= *itRect;
1146 sint x0= rect.X;
1147 sint y0= rect.Y;
1148 sint x1= rect.X+rect.Width;
1149 sint y1= rect.Y+rect.Height;
1151 // Fill mipmaps.
1152 for(sint i=0;i<nMipMaps;i++)
1154 void *ptr= tex.getPixels(i).getPtr();
1155 sint w= tex.getWidth(i);
1156 sint h= tex.getHeight(i);
1157 clamp(x0, 0, w);
1158 clamp(y0, 0, h);
1159 clamp(x1, x0, w);
1160 clamp(y1, y0, h);
1162 #ifdef USE_OPENGLES
1163 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1165 if (!bUpload)
1166 ptr = NULL;
1168 sint pixelSize = 4;
1170 if (glSrcFmt == GL_ALPHA)
1171 pixelSize = 1;
1173 for(sint yy = 0; yy < (y1-y0); yy++)
1175 char *row = (char*)ptr + ((yy + y0)*w + x0) * pixelSize;
1176 glTexSubImage2D (GL_TEXTURE_2D, i, x0, y0+yy, x1-x0, 1, glSrcFmt, glSrcType, row );
1178 #else
1179 glPixelStorei(GL_UNPACK_ROW_LENGTH, w);
1180 glPixelStorei(GL_UNPACK_SKIP_ROWS, y0);
1181 glPixelStorei(GL_UNPACK_SKIP_PIXELS, x0);
1182 if (bUpload)
1183 glTexSubImage2D (GL_TEXTURE_2D, i, x0, y0, x1-x0, y1-y0, glSrcFmt,glSrcType, ptr);
1184 else
1185 glTexSubImage2D (GL_TEXTURE_2D, i, x0, y0, x1-x0, y1-y0, glSrcFmt,glSrcType, NULL);
1186 #endif
1188 // Next mipmap!!
1189 // floor .
1190 x0= x0/2;
1191 y0= y0/2;
1192 // ceil.
1193 x1= (x1+1)/2;
1194 y1= (y1+1)/2;
1198 // Reset the transfer mode...
1199 #ifdef USE_OPENGLES
1200 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1201 #else
1202 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1203 glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1204 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1205 #endif
1209 // Release, if wanted.
1210 if(tex.getReleasable())
1211 tex.release();
1213 // Basic parameters.
1214 //==================
1215 setupTextureBasicParameters(tex);
1217 // Disable texture 0
1218 _CurrentTexture[0]= NULL;
1219 _CurrentTextureInfoGL[0]= NULL;
1220 _DriverGLStates.setTextureMode(CDriverGLStates::TextureDisabled);
1223 // The texture is correctly setuped.
1224 tex.clearTouched();
1225 return true;
1228 // ***************************************************************************
1229 bool CDriverGL::uploadTexture (ITexture& tex, CRect& rect, uint8 nNumMipMap)
1231 H_AUTO_OGL(uploadTexture)
1232 if (tex.TextureDrvShare == NULL)
1233 return false; // Texture not created
1234 if (tex.TextureDrvShare->DrvTexture == NULL)
1235 return false; // Texture not created
1236 if (tex.isTextureCube())
1237 return false;
1239 nlassert(nNumMipMap<(uint8)tex.getMipMapCount());
1241 // validate rect.
1242 sint x0 = rect.X;
1243 sint y0 = rect.Y;
1244 sint x1 = rect.X+rect.Width;
1245 sint y1 = rect.Y+rect.Height;
1246 sint w = tex.getWidth (nNumMipMap);
1247 sint h = tex.getHeight (nNumMipMap);
1248 clamp (x0, 0, w);
1249 clamp (y0, 0, h);
1250 clamp (x1, x0, w);
1251 clamp (y1, y0, h);
1253 // bind the texture to upload
1254 CTextureDrvInfosGL* gltext;
1255 gltext = getTextureGl (tex);
1257 // system of "backup the previous binded texture" seems to not work with some drivers....
1258 _DriverGLStates.activeTextureARB (0);
1259 CDriverGLStates::TTextureMode textureMode= CDriverGLStates::Texture2D;
1261 #ifndef USE_OPENGLES
1262 if(gltext->TextureMode == GL_TEXTURE_RECTANGLE_NV)
1263 textureMode = CDriverGLStates::TextureRect;
1264 #endif
1266 _DriverGLStates.setTextureMode (textureMode);
1267 // Bind this texture, for reload...
1268 glBindTexture (gltext->TextureMode, gltext->ID);
1270 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
1272 bool dummy;
1273 GLint glfmt = getGlTextureFormat (tex, dummy);
1274 GLint glSrcFmt = getGlSrcTextureFormat (tex, glfmt);
1275 GLenum glSrcType= getGlSrcTextureComponentType(glSrcFmt);
1277 // If DXTC format
1278 if (_Extensions.EXTTextureCompressionS3TC && sameDXTCFormat(tex, glfmt))
1281 sint nUploadMipMaps;
1282 if (tex.mipMapOn())
1283 nUploadMipMaps = tex.getMipMapCount();
1284 else
1285 nUploadMipMaps = 1;
1287 uint decalMipMapResize = 0;
1288 if (_ForceTextureResizePower>0 && tex.allowDegradation() && nUploadMipMaps>1)
1290 decalMipMapResize = min(_ForceTextureResizePower, (uint)(nUploadMipMaps-1));
1293 // Compute src compressed size and location
1294 sint imageSize = (x1-x0)*(y1-y0);
1295 void *ptr = tex.getPixels(nNumMipMap).getPtr();
1297 // If DXTC1 or DXTC1A, then 4 bits/texel else 8 bits/texel
1298 if (glfmt == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || glfmt == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
1300 imageSize /= 2;
1301 ptr = (uint8*)ptr + y0*w/2 + x0/2;
1303 else
1305 ptr = (uint8*)ptr + y0*w + x0;
1308 // Upload
1310 if (decalMipMapResize > nNumMipMap)
1312 _CurrentTexture[0]= NULL;
1313 _CurrentTextureInfoGL[0]= NULL;
1314 _DriverGLStates.setTextureMode (CDriverGLStates::TextureDisabled);
1315 return false;
1318 nlassert (((x0&3) == 0) && ((y0&3) == 0));
1319 if ((w>=4) && (h>=4))
1321 #ifdef USE_OPENGLES
1322 glCompressedTexSubImage2D (
1323 #else
1324 nglCompressedTexSubImage2DARB (
1325 #endif
1326 GL_TEXTURE_2D, nNumMipMap-decalMipMapResize,
1327 x0, y0, (x1-x0), (y1-y0), glfmt, imageSize, ptr );
1329 else
1331 // The CompressedTexSubImage2DARB function do not work properly if width or height
1332 // of the mipmap is less than 4 pixel so we use the other form. (its not really time critical
1333 // to upload 16 bytes so we can do it twice if texture is cut)
1334 imageSize = tex.getPixels(nNumMipMap).size();
1335 #ifdef USE_OPENGLES
1336 glCompressedTexImage2D (
1337 #else
1338 nglCompressedTexImage2DARB (
1339 #endif
1340 GL_TEXTURE_2D, nNumMipMap-decalMipMapResize,
1341 glfmt, w, h, 0, imageSize, ptr);
1344 else
1346 // glSrcFmt and ITexture format must be identical
1347 nlassert (glSrcFmt!=GL_RGBA || tex.getPixelFormat()==CBitmap::RGBA);
1349 void *ptr= tex.getPixels(nNumMipMap).getPtr();
1351 #ifdef USE_OPENGLES
1352 sint pixelSize = 4;
1354 if (glSrcFmt == GL_ALPHA)
1355 pixelSize = 1;
1357 for(sint yy = 0; yy < (y1-y0); yy++)
1359 char *row = (char*)ptr + ((yy + y0)*w + x0) * pixelSize;
1360 glTexSubImage2D (GL_TEXTURE_2D, nNumMipMap, x0, y0+yy, x1-x0, 1, glSrcFmt, glSrcType, row );
1363 // Reset the transfer mode...
1364 // glPixelStorei (GL_UNPACK_ALIGNMENT, 0);
1365 #else
1366 glPixelStorei (GL_UNPACK_ROW_LENGTH, w);
1367 glPixelStorei (GL_UNPACK_SKIP_ROWS, y0);
1368 glPixelStorei (GL_UNPACK_SKIP_PIXELS, x0);
1369 glTexSubImage2D (GL_TEXTURE_2D, nNumMipMap, x0, y0, x1-x0, y1-y0, glSrcFmt,glSrcType, ptr);
1371 // Reset the transfer mode...
1372 glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
1373 glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
1374 glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
1375 #endif
1378 // Disable texture 0
1379 _CurrentTexture[0]= NULL;
1380 _CurrentTextureInfoGL[0]= NULL;
1381 _DriverGLStates.setTextureMode (CDriverGLStates::TextureDisabled);
1383 return true;
1386 // ***************************************************************************
1387 bool CDriverGL::uploadTextureCube (ITexture& tex, CRect& /* rect */, uint8 /* nNumMipMap */, uint8 /* nNumFace */)
1389 H_AUTO_OGL(uploadTextureCube)
1390 if (tex.TextureDrvShare == NULL)
1391 return false; // Texture not created
1392 if (!tex.isTextureCube())
1393 return false;
1395 return true;
1398 // ***************************************************************************
1399 bool CDriverGL::activateTexture(uint stage, ITexture *tex)
1401 H_AUTO_OGL(activateTexture)
1402 if (this->_CurrentTexture[stage]!=tex)
1404 _DriverGLStates.activeTextureARB(stage);
1405 if(tex && tex->TextureDrvShare)
1407 // get the drv info. should be not NULL.
1408 CTextureDrvInfosGL* gltext;
1409 gltext= getTextureGl(*tex);
1411 // Profile, log the use of this texture
1412 //=========================================
1413 if (_SumTextureMemoryUsed)
1415 // Insert the pointer of this texture
1416 if (gltext->TextureUsedIdx >= _TextureUsed.size() || _TextureUsed[gltext->TextureUsedIdx] != gltext)
1418 gltext->TextureUsedIdx = _TextureUsed.size();
1419 _TextureUsed.push_back(gltext);
1423 if(tex->isTextureCube())
1425 // setup texture mode, after activeTextureARB()
1426 _DriverGLStates.setTextureMode(CDriverGLStates::TextureCubeMap);
1428 if(_Extensions.ARBTextureCubeMap)
1430 // Activate texturing...
1431 //======================
1433 // If the shared texture is the same than before, no op.
1434 if(_CurrentTextureInfoGL[stage] != gltext)
1436 // Cache setup.
1437 _CurrentTextureInfoGL[stage]= gltext;
1439 // setup this texture
1440 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, gltext->ID);
1442 // Change parameters of texture, if necessary.
1443 //============================================
1444 if(gltext->MagFilter!= tex->getMagFilter())
1446 gltext->MagFilter= tex->getMagFilter();
1447 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_MAG_FILTER, translateMagFilterToGl(gltext));
1449 if(gltext->MinFilter!= tex->getMinFilter())
1451 gltext->MinFilter= tex->getMinFilter();
1452 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_MIN_FILTER, translateMinFilterToGl(gltext));
1457 else
1459 // setup texture mode, after activeTextureARB()
1460 CDriverGLStates::TTextureMode textureMode= CDriverGLStates::Texture2D;
1461 #ifndef USE_OPENGLES
1462 if(gltext->TextureMode == GL_TEXTURE_RECTANGLE_NV)
1463 textureMode = CDriverGLStates::TextureRect;
1464 #endif
1465 _DriverGLStates.setTextureMode(/*CDriverGLStates::Texture2D*/textureMode);
1467 // Activate texture...
1468 //======================
1470 // If the shared texture is the same than before, no op.
1471 if(_CurrentTextureInfoGL[stage] != gltext)
1473 // Cache setup.
1474 _CurrentTextureInfoGL[stage]= gltext;
1476 // setup this texture
1477 glBindTexture(gltext->TextureMode, gltext->ID);
1480 // Change parameters of texture, if necessary.
1481 //============================================
1482 if(gltext->WrapS!= tex->getWrapS())
1484 gltext->WrapS= tex->getWrapS();
1485 glTexParameteri(gltext->TextureMode,GL_TEXTURE_WRAP_S, translateWrapToGl(gltext->WrapS, _Extensions));
1487 if(gltext->WrapT!= tex->getWrapT())
1489 gltext->WrapT= tex->getWrapT();
1490 glTexParameteri(gltext->TextureMode,GL_TEXTURE_WRAP_T, translateWrapToGl(gltext->WrapT, _Extensions));
1492 if(gltext->MagFilter!= tex->getMagFilter())
1494 gltext->MagFilter= tex->getMagFilter();
1495 glTexParameteri(gltext->TextureMode,GL_TEXTURE_MAG_FILTER, translateMagFilterToGl(gltext));
1497 if(gltext->MinFilter!= tex->getMinFilter())
1499 gltext->MinFilter= tex->getMinFilter();
1500 glTexParameteri(gltext->TextureMode,GL_TEXTURE_MIN_FILTER, translateMinFilterToGl(gltext));
1505 else
1507 // Force no texturing for this stage.
1508 _CurrentTextureInfoGL[stage]= NULL;
1509 // setup texture mode, after activeTextureARB()
1510 _DriverGLStates.setTextureMode(CDriverGLStates::TextureDisabled);
1512 #ifndef USE_OPENGLES
1513 if (_Extensions.ATITextureEnvCombine3)
1515 // very strange bug with ATI cards : when a texture is set to NULL at a stage, the stage is still active sometimes...
1516 activateTexEnvMode(stage, _TexEnvReplace); // set the whole stage to replace fix the problem
1518 #endif
1521 this->_CurrentTexture[stage]= tex;
1524 return true;
1528 // This maps the CMaterial::TTexOperator
1529 static const GLenum OperatorLUT[9]= { GL_REPLACE, GL_MODULATE, GL_ADD, GL_ADD_SIGNED_EXT, GL_INTERPOLATE_EXT, GL_INTERPOLATE_EXT, GL_INTERPOLATE_EXT, GL_INTERPOLATE_EXT, GL_BUMP_ENVMAP_ATI };
1531 // This maps the CMaterial::TTexSource
1532 static const GLenum SourceLUT[4]= { GL_TEXTURE, GL_PREVIOUS_EXT, GL_PRIMARY_COLOR_EXT, GL_CONSTANT_EXT };
1534 // This maps the CMaterial::TTexOperand
1535 static const GLenum OperandLUT[4]= { GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA };
1537 // This maps the CMaterial::TTexOperator, used for openGL Arg2 setup.
1538 static const GLenum InterpolateSrcLUT[8]= { GL_TEXTURE, GL_TEXTURE, GL_TEXTURE, GL_TEXTURE, GL_TEXTURE, GL_PREVIOUS_EXT, GL_PRIMARY_COLOR_EXT, GL_CONSTANT_EXT };
1540 #ifndef USE_OPENGLES
1542 // ***************************************************************************
1543 // Set general tex env using ENV_COMBINE4 for the current setupped stage (used by forceActivateTexEnvMode)
1544 static void forceActivateTexEnvModeEnvCombine4(const CMaterial::CTexEnv &env)
1546 H_AUTO_OGL(forceActivateTexEnvModeEnvCombine4);
1548 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
1550 //== RGB ==
1551 switch(env.Env.OpRGB)
1553 case CMaterial::Replace:
1554 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
1555 // Arg0 = env arg0
1556 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, SourceLUT[env.Env.SrcArg0RGB]);
1557 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, OperandLUT[env.Env.OpArg0RGB]);
1558 // Arg1 = 0
1559 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_ZERO);
1560 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_ONE_MINUS_SRC_COLOR);
1561 // Arg2 = 0
1562 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_ZERO);
1563 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);
1564 // Arg3 = 0
1565 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_ZERO);
1566 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR);
1567 break;
1568 case CMaterial::Add:
1569 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
1570 // Arg0 = env arg0
1571 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, SourceLUT[env.Env.SrcArg0RGB]);
1572 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, OperandLUT[env.Env.OpArg0RGB]);
1573 // Arg1 = 1
1574 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_ZERO);
1575 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_ONE_MINUS_SRC_COLOR);
1576 // Arg2 = env arg1
1577 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, SourceLUT[env.Env.SrcArg1RGB]);
1578 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, OperandLUT[env.Env.OpArg1RGB]);
1579 // Arg3 = 1
1580 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_ZERO);
1581 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_ONE_MINUS_SRC_COLOR);
1582 break;
1583 case CMaterial::AddSigned:
1584 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD_SIGNED_EXT);
1585 // Arg0 = env arg0
1586 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, SourceLUT[env.Env.SrcArg0RGB]);
1587 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, OperandLUT[env.Env.OpArg0RGB]);
1588 // Arg1 = 1
1589 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_ZERO);
1590 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_ONE_MINUS_SRC_COLOR);
1591 // Arg2 = env arg1
1592 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, SourceLUT[env.Env.SrcArg1RGB]);
1593 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, OperandLUT[env.Env.OpArg1RGB]);
1594 // Arg3 = 1
1595 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_ZERO);
1596 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_ONE_MINUS_SRC_COLOR);
1597 break;
1598 case CMaterial::InterpolateTexture:
1599 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
1600 // Arg0 = env arg0
1601 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, SourceLUT[env.Env.SrcArg0RGB]);
1602 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, OperandLUT[env.Env.OpArg0RGB]);
1603 // Arg1 = (1 - texture)
1604 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE);
1605 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_ONE_MINUS_SRC_ALPHA);
1606 // Arg2 = env arg1
1607 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, SourceLUT[env.Env.SrcArg1RGB]);
1608 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, OperandLUT[env.Env.OpArg1RGB]);
1609 // Arg3 = texture
1610 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_TEXTURE);
1611 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_ALPHA);
1612 break;
1613 case CMaterial::InterpolatePrevious:
1614 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
1615 // Arg0 = env arg0
1616 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, SourceLUT[env.Env.SrcArg0RGB]);
1617 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, OperandLUT[env.Env.OpArg0RGB]);
1618 // Arg1 = (1 - previous)
1619 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
1620 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_ONE_MINUS_SRC_ALPHA);
1621 // Arg2 = env arg1
1622 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, SourceLUT[env.Env.SrcArg1RGB]);
1623 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, OperandLUT[env.Env.OpArg1RGB]);
1624 // Arg3 = previous
1625 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_PREVIOUS_EXT);
1626 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_ALPHA);
1627 break;
1628 case CMaterial::InterpolateDiffuse:
1629 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
1630 // Arg0 = env arg0
1631 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, SourceLUT[env.Env.SrcArg0RGB]);
1632 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, OperandLUT[env.Env.OpArg0RGB]);
1633 // Arg1 = (1 - diffuse)
1634 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
1635 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_ONE_MINUS_SRC_ALPHA);
1636 // Arg2 = env arg1
1637 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, SourceLUT[env.Env.SrcArg1RGB]);
1638 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, OperandLUT[env.Env.OpArg1RGB]);
1639 // Arg3 = diffuse
1640 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_PRIMARY_COLOR_EXT);
1641 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_ALPHA);
1642 break;
1643 case CMaterial::InterpolateConstant:
1644 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
1645 // Arg0 = env arg0
1646 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, SourceLUT[env.Env.SrcArg0RGB]);
1647 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, OperandLUT[env.Env.OpArg0RGB]);
1648 // Arg1 = (1 - constant)
1649 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_CONSTANT_EXT);
1650 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_ONE_MINUS_SRC_ALPHA);
1651 // Arg2 = env arg1
1652 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, SourceLUT[env.Env.SrcArg1RGB]);
1653 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, OperandLUT[env.Env.OpArg1RGB]);
1654 // Arg3 = constant
1655 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_CONSTANT_EXT);
1656 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_ALPHA);
1657 break;
1658 case CMaterial::Mad:
1659 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
1660 // Arg0 = env arg0
1661 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, SourceLUT[env.Env.SrcArg0RGB]);
1662 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, OperandLUT[env.Env.OpArg0RGB]);
1663 // Arg1 = env arg1
1664 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, SourceLUT[env.Env.SrcArg1RGB]);
1665 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, OperandLUT[env.Env.OpArg1RGB]);
1666 // Arg2 = env arg2
1667 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, SourceLUT[env.Env.SrcArg2RGB]);
1668 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, OperandLUT[env.Env.OpArg2RGB]);
1669 // Arg3 = 1
1670 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_ZERO);
1671 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_ONE_MINUS_SRC_COLOR);
1672 break;
1673 default:
1674 // default is modulate
1675 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
1676 // Arg0 = env arg0
1677 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, SourceLUT[env.Env.SrcArg0RGB]);
1678 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, OperandLUT[env.Env.OpArg0RGB]);
1679 // Arg1 = env arg1
1680 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, SourceLUT[env.Env.SrcArg1RGB]);
1681 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, OperandLUT[env.Env.OpArg1RGB]);
1682 // Arg2 = 0
1683 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_ZERO);
1684 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);
1685 // Arg3 = 0
1686 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_ZERO);
1687 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR);
1688 break;
1690 //== Alpha part ==
1691 switch(env.Env.OpAlpha)
1693 case CMaterial::Replace:
1694 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
1695 // Arg0 = env arg0
1696 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, SourceLUT[env.Env.SrcArg0Alpha]);
1697 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, OperandLUT[env.Env.OpArg0Alpha]);
1698 // Arg1 = 0
1699 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_ZERO);
1700 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA);
1701 // Arg2 = 0
1702 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_ZERO);
1703 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
1704 // Arg3 = 0
1705 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO);
1706 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_SRC_ALPHA);
1707 break;
1708 case CMaterial::Add:
1709 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
1710 // Arg0 = env arg0
1711 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, SourceLUT[env.Env.SrcArg0Alpha]);
1712 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, OperandLUT[env.Env.OpArg0Alpha]);
1713 // Arg1 = 1
1714 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_ZERO);
1715 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA);
1716 // Arg2 = env arg1
1717 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, SourceLUT[env.Env.SrcArg1Alpha]);
1718 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, OperandLUT[env.Env.OpArg1Alpha]);
1719 // Arg3 = 1
1720 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO);
1721 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_ONE_MINUS_SRC_ALPHA);
1722 break;
1723 case CMaterial::AddSigned:
1724 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD_SIGNED_EXT);
1725 // Arg0 = env arg0
1726 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, SourceLUT[env.Env.SrcArg0Alpha]);
1727 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, OperandLUT[env.Env.OpArg0Alpha]);
1728 // Arg1 = 1
1729 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_ZERO);
1730 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA);
1731 // Arg2 = env arg1
1732 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, SourceLUT[env.Env.SrcArg1Alpha]);
1733 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, OperandLUT[env.Env.OpArg1Alpha]);
1734 // Arg3 = 1
1735 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO);
1736 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_ONE_MINUS_SRC_ALPHA);
1737 break;
1738 case CMaterial::InterpolateTexture:
1739 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
1740 // Arg0 = env arg0
1741 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, SourceLUT[env.Env.SrcArg0Alpha]);
1742 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, OperandLUT[env.Env.OpArg0Alpha]);
1743 // Arg1 = (1 - texture)
1744 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_TEXTURE);
1745 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA);
1746 // Arg2 = env arg1
1747 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, SourceLUT[env.Env.SrcArg1Alpha]);
1748 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, OperandLUT[env.Env.OpArg1Alpha]);
1749 // Arg3 = texture
1750 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_TEXTURE);
1751 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_SRC_ALPHA);
1752 break;
1753 case CMaterial::InterpolatePrevious:
1754 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
1755 // Arg0 = env arg0
1756 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, SourceLUT[env.Env.SrcArg0Alpha]);
1757 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, OperandLUT[env.Env.OpArg0Alpha]);
1758 // Arg1 = (1 - previous)
1759 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT);
1760 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA);
1761 // Arg2 = env arg1
1762 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, SourceLUT[env.Env.SrcArg1Alpha]);
1763 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, OperandLUT[env.Env.OpArg1Alpha]);
1764 // Arg3 = previous
1765 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_PREVIOUS_EXT);
1766 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_SRC_ALPHA);
1767 break;
1768 case CMaterial::InterpolateDiffuse:
1769 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
1770 // Arg0 = env arg0
1771 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, SourceLUT[env.Env.SrcArg0Alpha]);
1772 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, OperandLUT[env.Env.OpArg0Alpha]);
1773 // Arg1 = (1 - diffuse)
1774 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PRIMARY_COLOR_EXT);
1775 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA);
1776 // Arg2 = env arg1
1777 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, SourceLUT[env.Env.SrcArg1Alpha]);
1778 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, OperandLUT[env.Env.OpArg1Alpha]);
1779 // Arg3 = diffuse
1780 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_PRIMARY_COLOR_EXT);
1781 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_SRC_ALPHA);
1782 break;
1783 case CMaterial::InterpolateConstant:
1784 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
1785 // Arg0 = env arg0
1786 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, SourceLUT[env.Env.SrcArg0Alpha]);
1787 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, OperandLUT[env.Env.OpArg0Alpha]);
1788 // Arg1 = (1 - constant)
1789 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_CONSTANT_EXT);
1790 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA);
1791 // Arg2 = env arg1
1792 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, SourceLUT[env.Env.SrcArg1Alpha]);
1793 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, OperandLUT[env.Env.OpArg1Alpha]);
1794 // Arg3 = constant
1795 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_CONSTANT_EXT);
1796 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_SRC_ALPHA);
1797 break;
1798 case CMaterial::Mad:
1799 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
1800 // Arg0 = env arg0
1801 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, SourceLUT[env.Env.SrcArg0Alpha]);
1802 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, OperandLUT[env.Env.OpArg0Alpha]);
1803 // Arg1 = env arg1
1804 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, SourceLUT[env.Env.SrcArg1Alpha]);
1805 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, OperandLUT[env.Env.OpArg1Alpha]);
1806 // Arg2 = env arg2
1807 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, SourceLUT[env.Env.SrcArg2Alpha]);
1808 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, OperandLUT[env.Env.OpArg2Alpha]);
1809 // Arg3 = 1
1810 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO);
1811 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_ONE_MINUS_SRC_ALPHA);
1812 break;
1813 default:
1814 // default is modulate
1815 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
1816 // Arg0 = env arg0
1817 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, SourceLUT[env.Env.SrcArg0Alpha]);
1818 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, OperandLUT[env.Env.OpArg0Alpha]);
1819 // Arg1 = env arg1
1820 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, SourceLUT[env.Env.SrcArg1Alpha]);
1821 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, OperandLUT[env.Env.OpArg1Alpha]);
1822 // Arg2 = 0
1823 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_ZERO);
1824 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
1825 // Arg3 = 0
1826 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO);
1827 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_SRC_ALPHA);
1828 break;
1832 #endif
1834 // ***************************************************************************
1835 void CDriverGL::forceActivateTexEnvMode(uint stage, const CMaterial::CTexEnv &env)
1837 H_AUTO_OGL(forceActivateTexEnvMode)
1838 // cache mgt.
1839 _CurrentTexEnv[stage].EnvPacked= env.EnvPacked;
1840 // Disable Special tex env f().
1841 _CurrentTexEnvSpecial[stage]= TexEnvSpecialDisabled;
1844 // Setup the gl env mode.
1845 _DriverGLStates.activeTextureARB(stage);
1847 #ifdef USE_OPENGLES
1848 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1850 // RGB.
1851 //=====
1852 if (env.Env.OpRGB == CMaterial::Mad)
1855 if (false)
1857 // GL_MODULATE_ADD_ATI
1858 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
1859 // Arg0.
1860 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, SourceLUT[env.Env.SrcArg0RGB] );
1861 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, OperandLUT[env.Env.OpArg0RGB]);
1862 // Arg1.
1863 glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, SourceLUT[env.Env.SrcArg1RGB] );
1864 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, OperandLUT[env.Env.OpArg1RGB]);
1865 // Arg2.
1866 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, SourceLUT[env.Env.SrcArg2RGB] );
1867 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, OperandLUT[env.Env.OpArg2RGB]);
1869 else
1871 // fallback to modulate ..
1872 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
1874 // Arg0.
1875 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, SourceLUT[env.Env.SrcArg0RGB] );
1876 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, OperandLUT[env.Env.OpArg0RGB]);
1877 // Arg1.
1878 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, SourceLUT[env.Env.SrcArg1RGB] );
1879 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, OperandLUT[env.Env.OpArg1RGB]);
1882 else
1884 // Operator.
1885 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, OperatorLUT[env.Env.OpRGB] );
1886 // Arg0.
1887 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, SourceLUT[env.Env.SrcArg0RGB] );
1888 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, OperandLUT[env.Env.OpArg0RGB]);
1889 // Arg1.
1890 if(env.Env.OpRGB > CMaterial::Replace)
1892 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, SourceLUT[env.Env.SrcArg1RGB] );
1893 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, OperandLUT[env.Env.OpArg1RGB]);
1894 // Arg2.
1895 if(env.Env.OpRGB >= CMaterial::InterpolateTexture )
1897 glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, InterpolateSrcLUT[env.Env.OpRGB] );
1898 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
1902 // Alpha.
1903 //=====
1904 if (env.Env.OpAlpha == CMaterial::Mad)
1906 if (true)
1908 // GL_MODULATE_ADD_ATI
1909 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
1910 // Arg0.
1911 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, SourceLUT[env.Env.SrcArg0Alpha] );
1912 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, OperandLUT[env.Env.OpArg0Alpha]);
1913 // Arg1.
1914 glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_ALPHA, SourceLUT[env.Env.SrcArg1Alpha] );
1915 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, OperandLUT[env.Env.OpArg1Alpha]);
1916 // Arg2.
1917 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, SourceLUT[env.Env.SrcArg2Alpha] );
1918 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, OperandLUT[env.Env.OpArg2Alpha]);
1920 else
1922 // fallback to modulate ..
1923 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
1925 // Arg0.
1926 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, SourceLUT[env.Env.SrcArg0RGB] );
1927 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, OperandLUT[env.Env.OpArg0RGB]);
1928 // Arg1.
1929 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, SourceLUT[env.Env.SrcArg1RGB] );
1930 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, OperandLUT[env.Env.OpArg1RGB]);
1933 else
1935 // Operator.
1936 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, OperatorLUT[env.Env.OpAlpha] );
1937 // Arg0.
1938 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, SourceLUT[env.Env.SrcArg0Alpha] );
1939 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, OperandLUT[env.Env.OpArg0Alpha]);
1940 // Arg1.
1941 if(env.Env.OpAlpha > CMaterial::Replace)
1943 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, SourceLUT[env.Env.SrcArg1Alpha] );
1944 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, OperandLUT[env.Env.OpArg1Alpha]);
1945 // Arg2.
1946 if(env.Env.OpAlpha >= CMaterial::InterpolateTexture )
1948 glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_ALPHA, InterpolateSrcLUT[env.Env.OpAlpha] );
1949 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);
1953 #else
1954 // if the Mad operator is used, then
1955 // "Normal drivers", setup EnvCombine.
1956 if(_Extensions.EXTTextureEnvCombine)
1958 // if Mad operator is used, special setup
1959 if ((env.Env.OpAlpha == CMaterial::Mad || env.Env.OpRGB == CMaterial::Mad) && _Extensions.NVTextureEnvCombine4)
1961 forceActivateTexEnvModeEnvCombine4(env);
1963 else
1965 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1966 // RGB.
1967 //=====
1968 if (env.Env.OpRGB == CMaterial::Mad)
1971 if (_Extensions.ATITextureEnvCombine3)
1973 glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE_ADD_ATI);
1974 // Arg0.
1975 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, SourceLUT[env.Env.SrcArg0RGB] );
1976 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, OperandLUT[env.Env.OpArg0RGB]);
1977 // Arg1.
1978 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, SourceLUT[env.Env.SrcArg1RGB] );
1979 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, OperandLUT[env.Env.OpArg1RGB]);
1980 // Arg2.
1981 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, SourceLUT[env.Env.SrcArg2RGB] );
1982 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, OperandLUT[env.Env.OpArg2RGB]);
1984 else
1986 // fallback to modulate ..
1987 glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
1989 // Arg0.
1990 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, SourceLUT[env.Env.SrcArg0RGB] );
1991 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, OperandLUT[env.Env.OpArg0RGB]);
1992 // Arg1.
1993 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, SourceLUT[env.Env.SrcArg1RGB] );
1994 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, OperandLUT[env.Env.OpArg1RGB]);
1997 else
1999 // Operator.
2000 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, OperatorLUT[env.Env.OpRGB] );
2001 // Arg0.
2002 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, SourceLUT[env.Env.SrcArg0RGB] );
2003 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, OperandLUT[env.Env.OpArg0RGB]);
2004 // Arg1.
2005 if(env.Env.OpRGB > CMaterial::Replace)
2007 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, SourceLUT[env.Env.SrcArg1RGB] );
2008 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, OperandLUT[env.Env.OpArg1RGB]);
2009 // Arg2.
2010 if(env.Env.OpRGB >= CMaterial::InterpolateTexture )
2012 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, InterpolateSrcLUT[env.Env.OpRGB] );
2013 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
2017 // Alpha.
2018 //=====
2019 if (env.Env.OpAlpha == CMaterial::Mad)
2021 if (_Extensions.ATITextureEnvCombine3)
2023 glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE_ADD_ATI);
2024 // Arg0.
2025 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, SourceLUT[env.Env.SrcArg0Alpha] );
2026 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, OperandLUT[env.Env.OpArg0Alpha]);
2027 // Arg1.
2028 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, SourceLUT[env.Env.SrcArg1Alpha] );
2029 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, OperandLUT[env.Env.OpArg1Alpha]);
2030 // Arg2.
2031 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, SourceLUT[env.Env.SrcArg2Alpha] );
2032 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, OperandLUT[env.Env.OpArg2Alpha]);
2034 else
2036 // fallback to modulate ..
2037 glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE);
2039 // Arg0.
2040 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, SourceLUT[env.Env.SrcArg0RGB] );
2041 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, OperandLUT[env.Env.OpArg0RGB]);
2042 // Arg1.
2043 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, SourceLUT[env.Env.SrcArg1RGB] );
2044 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, OperandLUT[env.Env.OpArg1RGB]);
2047 else
2049 // Operator.
2050 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, OperatorLUT[env.Env.OpAlpha] );
2051 // Arg0.
2052 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, SourceLUT[env.Env.SrcArg0Alpha] );
2053 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, OperandLUT[env.Env.OpArg0Alpha]);
2054 // Arg1.
2055 if(env.Env.OpAlpha > CMaterial::Replace)
2057 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, SourceLUT[env.Env.SrcArg1Alpha] );
2058 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, OperandLUT[env.Env.OpArg1Alpha]);
2059 // Arg2.
2060 if(env.Env.OpAlpha >= CMaterial::InterpolateTexture )
2062 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, InterpolateSrcLUT[env.Env.OpAlpha] );
2063 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
2069 // Very Bad drivers.
2070 else
2072 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2074 #endif
2077 // ***************************************************************************
2078 void CDriverGL::activateTexEnvColor(uint stage, NLMISC::CRGBA col)
2080 H_AUTO_OGL(CDriverGL_activateTexEnvColor)
2081 if (col != _CurrentTexEnv[stage].ConstantColor)
2083 forceActivateTexEnvColor(stage, col);
2087 // ***************************************************************************
2088 void CDriverGL::activateTexEnvMode(uint stage, const CMaterial::CTexEnv &env)
2090 H_AUTO_OGL(CDriverGL_activateTexEnvMode)
2091 // If a special Texture environnement is setuped, or if not the same normal texture environnement,
2092 // must setup a new normal Texture environnement.
2093 if(_CurrentTexEnvSpecial[stage] != TexEnvSpecialDisabled || _CurrentTexEnv[stage].EnvPacked!= env.EnvPacked)
2095 forceActivateTexEnvMode(stage, env);
2100 // ***************************************************************************
2101 void CDriverGL::activateTexEnvColor(uint stage, const CMaterial::CTexEnv &env)
2103 H_AUTO_OGL(CDriverGL_activateTexEnvColor)
2104 if(_CurrentTexEnv[stage].ConstantColor!= env.ConstantColor)
2106 forceActivateTexEnvColor(stage, env);
2111 // ***************************************************************************
2112 void CDriverGL::forceDXTCCompression(bool dxtcComp)
2114 H_AUTO_OGL(CDriverGL_forceDXTCCompression)
2115 _ForceDXTCCompression= dxtcComp;
2118 // ***************************************************************************
2119 void CDriverGL::setAnisotropicFilter(sint filtering)
2121 H_AUTO_OGL(CDriverGL_setAnisotropicFiltering);
2123 if (!_Extensions.EXTTextureFilterAnisotropic) return;
2125 if (filtering < 0 || filtering > _Extensions.EXTTextureFilterAnisotropicMaximum)
2127 // set maximum value for anisotropic filter
2128 _AnisotropicFilter = _Extensions.EXTTextureFilterAnisotropicMaximum;
2130 else
2132 // set specified value for anisotropic filter
2133 _AnisotropicFilter = filtering;
2137 // ***************************************************************************
2138 uint CDriverGL::getAnisotropicFilter() const
2140 H_AUTO_OGL(CDriverGL_getAnisotropicFilter);
2142 return (uint)_AnisotropicFilter;
2145 // ***************************************************************************
2146 uint CDriverGL::getAnisotropicFilterMaximum() const
2148 H_AUTO_OGL(CDriverGL_getAnisotropicFilterMaximum);
2150 return (uint)_Extensions.EXTTextureFilterAnisotropicMaximum;
2153 // ***************************************************************************
2154 void CDriverGL::forceTextureResize(uint divisor)
2156 H_AUTO_OGL(CDriverGL_forceTextureResize)
2157 clamp(divisor, 1U, 256U);
2159 // 16 -> 4.
2160 _ForceTextureResizePower= getPowerOf2(divisor);
2164 // ***************************************************************************
2165 void CDriverGL::swapTextureHandle(ITexture &tex0, ITexture &tex1)
2167 H_AUTO_OGL(CDriverGL_swapTextureHandle)
2168 // ensure creation of both texture
2169 setupTexture(tex0);
2170 setupTexture(tex1);
2172 // avoid any problem, disable all textures
2173 for(uint stage = 0; stage < inlGetNumTextStages(); stage++)
2175 activateTexture(stage, NULL);
2178 // get the handle.
2179 CTextureDrvInfosGL *t0= getTextureGl(tex0);
2180 CTextureDrvInfosGL *t1= getTextureGl(tex1);
2182 /* Swap contents. Can't swap directly the pointers cause would have to change all CTextureDrvShare which point on
2183 Can't do swap(*t0, *t1), because must keep the correct _DriverIterator
2185 swap(t0->ID, t1->ID);
2186 swap(t0->MipMap, t1->MipMap);
2187 swap(t0->Compressed, t1->Compressed);
2188 swap(t0->TextureMemory, t1->TextureMemory);
2189 swap(t0->WrapS, t1->WrapS);
2190 swap(t0->WrapT, t1->WrapT);
2191 swap(t0->MagFilter, t1->MagFilter);
2192 swap(t0->MinFilter, t1->MinFilter);
2193 swap(t0->TextureMode, t1->TextureMode);
2194 swap(t0->FBOId, t1->FBOId);
2195 swap(t0->DepthStencilFBO, t1->DepthStencilFBO);
2196 swap(t0->InitFBO, t1->InitFBO);
2200 // ***************************************************************************
2201 uintptr_t CDriverGL::getTextureHandle(const ITexture &tex)
2203 H_AUTO_OGL(CDriverGL_getTextureHandle)
2204 // If DrvShare not setuped
2205 if(!tex.TextureDrvShare)
2206 return 0;
2208 // If DrvInfo not setuped
2209 const CTextureDrvInfosGL *t0= (const CTextureDrvInfosGL*)(const ITextureDrvInfos*)(tex.TextureDrvShare->DrvTexture);
2210 if(!t0)
2211 return 0;
2213 return t0->ID;
2216 // ***************************************************************************
2219 Under opengl, "render to texture" uses the frame buffer. The scene is rendered into the current frame buffer and the result
2220 is copied into the texture.
2222 setRenderTarget (tex) does nothing but backup the framebuffer area used and updates the viewport and scissor
2223 setRenderTarget (NULL) copies the modified framebuffer area into "tex" and then, updates the viewport and scissor
2226 bool CDriverGL::setRenderTarget (ITexture *tex, uint32 x, uint32 y, uint32 width, uint32 height, uint32 mipmapLevel, uint32 cubeFace)
2228 H_AUTO_OGL(CDriverGL_setRenderTarget )
2230 // make backup of offscreen buffer to old texture if not using FBOs
2231 if (!_RenderTargetFBO && _TextureTarget && _TextureTargetUpload && (_TextureTarget != tex || _TextureTargetCubeFace != cubeFace))
2233 // Flush it
2234 copyFrameBufferToTexture (_TextureTarget, _TextureTargetLevel, _TextureTargetX, _TextureTargetY, 0,
2235 0, _TextureTargetWidth, _TextureTargetHeight, _TextureTargetCubeFace);
2238 // Set a new texture as render target ?
2239 if (tex)
2241 // Check the texture is a render target
2242 nlassertex (tex->getRenderTarget(), ("The texture must be a render target. Call ITexture::setRenderTarget(true)."));
2244 if(tex->isBloomTexture() && supportBloomEffect())
2246 // NOTE: No support for mip map level here!
2248 uint32 w, h;
2249 getWindowSize(w, h);
2251 getViewport(_OldViewport);
2253 if (!width) width = tex->getWidth();
2254 if (!height) height = tex->getHeight();
2256 CViewport newVP;
2257 newVP.init(0, 0, ((float)width/(float)w), ((float)height/(float)h));
2258 setupViewport(newVP);
2260 _RenderTargetFBO = tex;
2262 return activeFrameBufferObject(tex);
2265 // Backup the parameters
2266 _TextureTargetLevel = mipmapLevel;
2267 _TextureTargetX = x;
2268 _TextureTargetY = y;
2269 _TextureTargetWidth = width;
2270 _TextureTargetHeight = height;
2271 _TextureTargetUpload = true;
2272 _TextureTargetCubeFace = cubeFace;
2274 else if (_RenderTargetFBO)
2276 activeFrameBufferObject(NULL);
2277 setupViewport(_OldViewport);
2278 _OldViewport = _CurrViewport;
2280 _RenderTargetFBO = NULL;
2281 return false;
2284 // Backup the texture
2285 _TextureTarget = tex;
2287 // Update the viewport
2288 setupViewport (_CurrViewport);
2290 // Update the scissor
2291 setupScissor (_CurrScissor);
2293 _RenderTargetFBO = NULL;
2294 _OldViewport = _CurrViewport;
2296 return true;
2299 ITexture *CDriverGL::getRenderTarget() const
2301 return _RenderTargetFBO ? _RenderTargetFBO : _TextureTarget;
2304 // ***************************************************************************
2306 bool CDriverGL::copyTargetToTexture (ITexture *tex,
2307 uint32 offsetx,
2308 uint32 offsety,
2309 uint32 x,
2310 uint32 y,
2311 uint32 width,
2312 uint32 height,
2313 uint32 mipmapLevel)
2315 H_AUTO_OGL(CDriverGL_copyTargetToTexture)
2316 if (!_TextureTarget)
2317 return false;
2318 _TextureTargetUpload = false;
2319 if ((width == 0) || (height == 0))
2321 uint32 _width;
2322 uint32 _height;
2323 getRenderTargetSize (_width, _height);
2324 if (width == 0)
2325 width = _width;
2326 if (height == 0)
2327 height = _height;
2329 copyFrameBufferToTexture(tex, mipmapLevel, offsetx, offsety, x, y, width, height);
2330 return true;
2333 // ***************************************************************************
2335 bool CDriverGL::getRenderTargetSize (uint32 &width, uint32 &height)
2337 H_AUTO_OGL(CDriverGL_getRenderTargetSize)
2338 NLMISC::CSmartPtr<ITexture> tex = _RenderTargetFBO ? _RenderTargetFBO : (_TextureTarget ? _TextureTarget : NULL);
2339 if (tex)
2341 width = tex->getWidth();
2342 height = tex->getHeight();
2344 else
2346 getWindowSize(width, height);
2349 return false;
2352 // ***************************************************************************
2354 #ifdef NL_STATIC
2355 } // NLDRIVERGL/ES
2356 #endif
2358 } // NL3D