]> git.mxchange.org Git - simgear.git/blob - simgear/screen/RenderTexture.cpp
4f046c88863d72971878652a10fd69b62351e471
[simgear.git] / simgear / screen / RenderTexture.cpp
1 //---------------------------------------------------------------------------
2 // File : RenderTexture.cpp
3 //---------------------------------------------------------------------------
4 // Copyright (c) 2002-2004 Mark J. Harris
5 //---------------------------------------------------------------------------
6 // This software is provided 'as-is', without any express or implied
7 // warranty. In no event will the authors be held liable for any
8 // damages arising from the use of this software.
9 //
10 // Permission is granted to anyone to use this software for any
11 // purpose, including commercial applications, and to alter it and
12 // redistribute it freely, subject to the following restrictions:
13 //
14 // 1. The origin of this software must not be misrepresented; you
15 //    must not claim that you wrote the original software. If you use
16 //    this software in a product, an acknowledgment in the product
17 //    documentation would be appreciated but is not required.
18 //
19 // 2. Altered source versions must be plainly marked as such, and
20 //    must not be misrepresented as being the original software.
21 //
22 // 3. This notice may not be removed or altered from any source
23 //    distribution.
24 //
25 // --------------------------------------------------------------------------
26 // Credits:
27 // Original RenderTexture class: Mark J. Harris
28 // Original Render to Depth Texture support: Thorsten Scheuermann
29 // Linux Copy-to-texture: Eric Werness
30 // Various Bug Fixes: Daniel (Redge) Sperl 
31 //                    Bill Baxter
32 //
33 // --------------------------------------------------------------------------
34 /**
35 * @file RenderTexture.cpp
36
37 * Implementation of class RenderTexture.  A multi-format render to 
38 * texture wrapper.
39 */
40 #pragma warning(disable:4786)
41
42 /*
43  * Changelog:
44  *
45  * Jan. 2005, Removed GLEW dependencies, Erik Hofman, Fred Bouvier
46  * Nov. 2005, Use the simgear logging facility, Erik Hofman
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #  include <simgear_config.h>
51 #endif
52
53 #ifdef HAVE_WINDOWS_H
54 #  include <windows.h>
55 #endif
56
57 #include <simgear/compiler.h>
58 #include <simgear/debug/logstream.hxx>
59 #include <simgear/screen/extensions.hxx>
60 #include <simgear/screen/RenderTexture.h>
61
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <assert.h>
65 #include <stdarg.h>
66
67 #ifdef _WIN32
68 #pragma comment(lib, "gdi32.lib") // required for GetPixelFormat()
69 #endif
70
71 using namespace std;
72
73 #ifdef _WIN32
74 static bool fctPtrInited = false;
75 /* WGL_ARB_pixel_format */
76 static wglChoosePixelFormatARBProc wglChoosePixelFormatARBPtr = 0;
77 static wglGetPixelFormatAttribivARBProc wglGetPixelFormatAttribivARBPtr = 0;
78 /* WGL_ARB_pbuffer */
79 static wglCreatePbufferARBProc wglCreatePbufferARBPtr = 0;
80 static wglGetPbufferDCARBProc wglGetPbufferDCARBPtr = 0;
81 static wglQueryPbufferARBProc wglQueryPbufferARBPtr = 0;
82 static wglReleasePbufferDCARBProc wglReleasePbufferDCARBPtr = 0;
83 static wglDestroyPbufferARBProc wglDestroyPbufferARBPtr = 0;
84 /* WGL_ARB_render_texture */
85 static wglBindTexImageARBProc wglBindTexImageARBPtr = 0;
86 static wglReleaseTexImageARBProc wglReleaseTexImageARBPtr = 0;
87
88 #elif defined( __APPLE__ )
89 #else /* !_WIN32 */
90 static bool glXVersion1_3Present = false;
91 static glXChooseFBConfigProc glXChooseFBConfigPtr = 0;
92 static glXCreatePbufferProc glXCreatePbufferPtr = 0;
93 static glXCreateGLXPbufferProc glXCreateGLXPbufferPtr = 0;
94 static glXGetVisualFromFBConfigProc glXGetVisualFromFBConfigPtr = 0;
95 static glXCreateContextProc glXCreateContextPtr = 0;
96 static glXCreateContextWithConfigProc glXCreateContextWithConfigPtr = 0;
97 static glXDestroyPbufferProc glXDestroyPbufferPtr = 0;
98 static glXQueryDrawableProc glXQueryDrawablePtr = 0;
99 static glXQueryGLXPbufferSGIXProc glXQueryGLXPbufferSGIXPtr = 0;
100 #endif
101
102 //---------------------------------------------------------------------------
103 // Function      : RenderTexture::RenderTexture
104 // Description   : 
105 //---------------------------------------------------------------------------
106 /**
107 * @fn RenderTexture::RenderTexture()
108 * @brief Mode-string-based Constructor.
109 */ 
110 RenderTexture::RenderTexture(const char *strMode)
111 :   _iWidth(0), 
112     _iHeight(0), 
113     _bIsTexture(false),
114     _bIsDepthTexture(false),
115     _bHasARBDepthTexture(true),            // [Redge]
116 #ifdef _WIN32
117     _eUpdateMode(RT_RENDER_TO_TEXTURE),
118 #else
119     _eUpdateMode(RT_COPY_TO_TEXTURE),
120 #endif
121     _bInitialized(false),
122     _iNumAuxBuffers(0),
123     _bIsBufferBound(false),
124     _iCurrentBoundBuffer(0),
125     _iNumDepthBits(0),
126     _iNumStencilBits(0),
127     _bFloat(false),
128     _bDoubleBuffered(false),
129     _bPowerOf2(true),
130     _bRectangle(false),
131     _bMipmap(false),
132     _bShareObjects(false),
133     _bCopyContext(false),
134 #ifdef _WIN32
135     _hDC(NULL), 
136     _hGLContext(NULL), 
137     _hPBuffer(NULL),
138     _hPreviousDC(0),
139     _hPreviousContext(0),
140 #elif defined( __APPLE__ )
141 #else
142     _pDisplay(NULL),
143     _hGLContext(NULL),
144     _hPBuffer(0),
145     _hPreviousContext(0),
146     _hPreviousDrawable(0),
147 #endif
148     _iTextureTarget(GL_NONE),
149     _iTextureID(0),
150     _iDepthTextureID(0),
151     _pPoorDepthTexture(0) // [Redge]
152 {
153     _iNumColorBits[0] = _iNumColorBits[1] = 
154         _iNumColorBits[2] = _iNumColorBits[3] = 0;
155
156 #ifdef _WIN32
157     _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
158     _pixelFormatAttribs.push_back(true);
159     _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
160     _pixelFormatAttribs.push_back(true);
161     
162     _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
163     _pbufferAttribs.push_back(true);
164 #elif defined( __APPLE__ )
165 #else
166     _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
167     _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
168     _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
169     _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
170 #endif
171
172     _ParseModeString(strMode, _pixelFormatAttribs, _pbufferAttribs);
173
174 #ifdef _WIN32
175     _pixelFormatAttribs.push_back(0);
176     _pbufferAttribs.push_back(0);
177 #else
178     _pixelFormatAttribs.push_back(None);
179 #endif
180 }
181
182
183 //---------------------------------------------------------------------------
184 // Function             : RenderTexture::~RenderTexture
185 // Description      : 
186 //---------------------------------------------------------------------------
187 /**
188 * @fn RenderTexture::~RenderTexture()
189 * @brief Destructor.
190 */ 
191 RenderTexture::~RenderTexture()
192 {
193     _Invalidate();
194 }
195
196
197 //---------------------------------------------------------------------------
198 // Function             : _wglGetLastError
199 // Description      : 
200 //---------------------------------------------------------------------------
201 /**
202 * @fn wglGetLastError()
203 * @brief Returns the last windows error generated.
204 */ 
205 #ifdef _WIN32
206 void _wglGetLastError()
207 {
208 #ifdef _DEBUG
209     
210     DWORD err = GetLastError();
211     switch(err)
212     {
213     case ERROR_INVALID_PIXEL_FORMAT:
214         SG_LOG(SG_GL, SG_ALERT, 
215                 "RenderTexture Win32 Error:  ERROR_INVALID_PIXEL_FORMAT");
216         break;
217     case ERROR_NO_SYSTEM_RESOURCES:
218         SG_LOG(SG_GL, SG_ALERT, 
219                 "RenderTexture Win32 Error:  ERROR_NO_SYSTEM_RESOURCES");
220         break;
221     case ERROR_INVALID_DATA:
222         SG_LOG(SG_GL, SG_ALERT, 
223                 "RenderTexture Win32 Error:  ERROR_INVALID_DATA");
224         break;
225     case ERROR_INVALID_WINDOW_HANDLE:
226         SG_LOG(SG_GL, SG_ALERT, 
227                 "RenderTexture Win32 Error:  ERROR_INVALID_WINDOW_HANDLE");
228         break;
229     case ERROR_RESOURCE_TYPE_NOT_FOUND:
230         SG_LOG(SG_GL, SG_ALERT, 
231                 "RenderTexture Win32 Error:  ERROR_RESOURCE_TYPE_NOT_FOUND");
232         break;
233     case ERROR_SUCCESS:
234         // no error
235         break;
236     default:
237         LPVOID lpMsgBuf;
238         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
239             FORMAT_MESSAGE_FROM_SYSTEM | 
240             FORMAT_MESSAGE_IGNORE_INSERTS,
241             NULL,
242             err,
243             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
244             (LPTSTR) &lpMsgBuf,
245             0,
246             NULL);
247         
248         SG_LOG(SG_GL, SG_ALERT, "RenderTexture Win32 Error %d: %s", err, lpMsgBuf);
249         LocalFree( lpMsgBuf );
250         break;
251     }
252     SetLastError(0);
253     
254 #endif // _DEBUG
255 }
256 #endif
257
258 //---------------------------------------------------------------------------
259 // Function             : PrintExtensionError
260 // Description      : 
261 //---------------------------------------------------------------------------
262 /**
263 * @fn PrintExtensionError( char* strMsg, ... )
264 * @brief Prints an error about missing OpenGL extensions.
265 */ 
266 void PrintExtensionError( char* strMsg, ... )
267 {
268     SG_LOG(SG_GL, SG_ALERT, 
269             "Error: RenderTexture requires the following unsupported "
270             "OpenGL extensions: ");
271     char strBuffer[512];
272     va_list args;
273     va_start(args, strMsg);
274 #if defined _WIN32 && !defined __CYGWIN__
275     _vsnprintf( strBuffer, 512, strMsg, args );
276 #else
277     vsnprintf( strBuffer, 512, strMsg, args );
278 #endif
279     va_end(args);
280     
281     SG_LOG(SG_GL, SG_ALERT, strMsg);
282 }
283
284
285 //---------------------------------------------------------------------------
286 // Function             : RenderTexture::Initialize
287 // Description      : 
288 //---------------------------------------------------------------------------
289 /**
290 * @fn RenderTexture::Initialize(int width, int height, bool shareObjects, bool copyContext);
291 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
292
293 * This function creates of the p-buffer.  It can only be called once a GL 
294 * context has already been created.  
295 */ 
296 bool RenderTexture::Initialize(int width, int height,
297                                 bool shareObjects       /* = true */,
298                                 bool copyContext        /* = false */)
299 {
300     assert(width > 0 && height > 0);
301
302     _iWidth = width; _iHeight = height;
303     _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
304
305     _bShareObjects = shareObjects;
306     _bCopyContext  = copyContext;
307
308     // Check if this is an NVXX GPU and verify necessary extensions.
309     if (!_VerifyExtensions())
310         return false;
311     
312     if (_bInitialized)
313         _Invalidate();
314
315 #ifdef _WIN32
316     // Get the current context.
317     HDC hdc = wglGetCurrentDC();
318     if (NULL == hdc)
319         _wglGetLastError();
320     HGLRC hglrc = wglGetCurrentContext();
321     if (NULL == hglrc)
322         _wglGetLastError();
323     
324     int iFormat = 0;
325     unsigned int iNumFormats;
326     
327     if (_bCopyContext)
328     {
329         // Get the pixel format for the on-screen window.
330         iFormat = GetPixelFormat(hdc);
331         if (iFormat == 0)
332         {
333             SG_LOG(SG_GL, SG_ALERT, 
334                     "RenderTexture Error: GetPixelFormat() failed.");
335             return false;
336         }
337     }
338     else 
339     {
340         if (!wglChoosePixelFormatARBPtr(hdc, &_pixelFormatAttribs[0], NULL, 
341                                      1, &iFormat, &iNumFormats))
342         {
343             SG_LOG(SG_GL, SG_ALERT, 
344                 "RenderTexture Error: wglChoosePixelFormatARB() failed.");
345             _wglGetLastError();
346             return false;
347         }
348         if ( iNumFormats <= 0 )
349         {
350             SG_LOG(SG_GL, SG_ALERT, 
351                     "RenderTexture Error: Couldn't find a suitable "
352                     "pixel format.");
353             _wglGetLastError();
354             return false;
355         }
356     }
357     
358     // Create the p-buffer.    
359     _hPBuffer = wglCreatePbufferARBPtr(hdc, iFormat, _iWidth, _iHeight, 
360                                     &_pbufferAttribs[0]);
361     if (!_hPBuffer)
362     {
363         SG_LOG(SG_GL, SG_ALERT, 
364                 "RenderTexture Error: wglCreatePbufferARB() failed.");
365         _wglGetLastError();
366         return false;
367     }
368     
369     // Get the device context.
370     _hDC = wglGetPbufferDCARBPtr( _hPBuffer);
371     if ( !_hDC )
372     {
373         SG_LOG(SG_GL, SG_ALERT, 
374                 "RenderTexture Error: wglGetGetPbufferDCARB() failed.");
375         _wglGetLastError();
376         return false;
377     }
378     
379     // Create a gl context for the p-buffer.
380     if (_bCopyContext)
381     {
382         // Let's use the same gl context..
383         // Since the device contexts are compatible (i.e. same pixelformat),
384         // we should be able to use the same gl rendering context.
385         _hGLContext = hglrc;
386     }
387     else
388     {
389         _hGLContext = wglCreateContext( _hDC );
390         if ( !_hGLContext )
391         {
392             SG_LOG(SG_GL, SG_ALERT, 
393                     "RenderTexture Error: wglCreateContext() failed.");
394             _wglGetLastError();
395             return false;
396         }
397     }
398     
399     // Share lists, texture objects, and program objects.
400     if( _bShareObjects )
401     {
402         if( !wglShareLists(hglrc, _hGLContext) )
403         {
404             SG_LOG(SG_GL, SG_ALERT, 
405                     "RenderTexture Error: wglShareLists() failed.");
406             _wglGetLastError();
407             return false;
408         }
409     }
410     
411     // Determine the actual width and height we were able to create.
412     wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
413     wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
414     
415     _bInitialized = true;
416     
417     // get the actual number of bits allocated:
418     int attrib = WGL_RED_BITS_ARB;
419     //int bits[6];
420     int value;
421     _iNumColorBits[0] = 
422         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
423         ? value : 0;
424     attrib = WGL_GREEN_BITS_ARB;
425     _iNumColorBits[1] = 
426         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
427         ? value : 0;
428     attrib = WGL_BLUE_BITS_ARB;
429     _iNumColorBits[2] = 
430         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
431         ? value : 0;
432     attrib = WGL_ALPHA_BITS_ARB;
433     _iNumColorBits[3] = 
434         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
435         ? value : 0; 
436     attrib = WGL_DEPTH_BITS_ARB;
437     _iNumDepthBits = 
438         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
439         ? value : 0; 
440     attrib = WGL_STENCIL_BITS_ARB;
441     _iNumStencilBits = 
442         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
443         ? value : 0; 
444     attrib = WGL_DOUBLE_BUFFER_ARB;
445     _bDoubleBuffered = 
446         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
447         ? (value?true:false) : false; 
448     
449 #if defined(_DEBUG) | defined(DEBUG)
450     SG_LOG(SG_GL, SG_ALERT, "Created a %dx%d RenderTexture with BPP(%d, %d, %d, %d)",
451         _iWidth, _iHeight, 
452         _iNumColorBits[0], _iNumColorBits[1], 
453         _iNumColorBits[2], _iNumColorBits[3]);
454     if (_iNumDepthBits) SG_LOG(SG_GL, SG_ALERT, " depth=%d", _iNumDepthBits);
455     if (_iNumStencilBits) SG_LOG(SG_GL, SG_ALERT, " stencil=%d", _iNumStencilBits);
456     if (_bDoubleBuffered) SG_LOG(SG_GL, SG_ALERT, " double buffered");
457     SG_LOG(SG_GL, SG_ALERT, "");
458 #endif
459
460 #elif defined( __APPLE__ )
461 #else // !_WIN32
462     _pDisplay = glXGetCurrentDisplay();
463     GLXContext context = glXGetCurrentContext();
464     int screen = DefaultScreen(_pDisplay);
465     XVisualInfo *visInfo;
466     
467     GLXFBConfig *fbConfigs;
468     int nConfigs;
469     
470     fbConfigs = glXChooseFBConfigPtr(_pDisplay, screen, 
471                                       &_pixelFormatAttribs[0], &nConfigs);
472     
473     if (nConfigs == 0 || !fbConfigs) 
474     {
475         SG_LOG(SG_GL, SG_ALERT,
476             "RenderTexture Error: Couldn't find a suitable pixel format.");
477         return false;
478     }
479     
480     // Pick the first returned format that will return a pbuffer
481     if (glXVersion1_3Present)
482     {
483         int pbufAttrib[] = {
484             GLX_PBUFFER_WIDTH,   _iWidth,
485             GLX_PBUFFER_HEIGHT,  _iHeight,
486             GLX_LARGEST_PBUFFER, False,
487             None
488         };
489         for (int i=0;i<nConfigs;i++)
490         {
491             _hPBuffer = glXCreatePbufferPtr(_pDisplay, fbConfigs[i], pbufAttrib);
492             if (_hPBuffer)
493             {
494                 XVisualInfo *visInfo = glXGetVisualFromFBConfigPtr(_pDisplay, fbConfigs[i]);
495
496                 _hGLContext = glXCreateContextPtr(_pDisplay, visInfo,
497                                                _bShareObjects ? context : NULL,
498                                                GL_TRUE);
499                 if (!_hGLContext)
500                 {
501                     return false;
502                 }
503                 XFree( visInfo );
504                 break;
505             }
506         }
507     }
508     else
509     {
510         int iFormat = 0;
511         int iNumFormats;
512         int attrib = 0;
513         for (int i=0;i<nConfigs;i++)
514         {
515             _hPBuffer = glXCreateGLXPbufferPtr(_pDisplay, fbConfigs[i], 
516                                                _iWidth, _iHeight, NULL);
517             if (_hPBuffer) 
518             {
519                 _hGLContext = glXCreateContextWithConfigPtr(_pDisplay, 
520                                                              fbConfigs[i], 
521                                                              GLX_RGBA_TYPE, 
522                                                              _bShareObjects ? context : NULL, 
523                                                              True);
524                 break;
525             }
526         }
527     }
528     XFree( fbConfigs );
529     
530     if (!_hPBuffer)
531     {
532         SG_LOG(SG_GL, SG_ALERT, 
533                 "RenderTexture Error: glXCreateGLXPbufferPtr() failed.");
534         return false;
535     }
536     
537     if(!_hGLContext)
538     {
539         // Try indirect
540         _hGLContext = glXCreateContext(_pDisplay, visInfo, 
541                                        _bShareObjects ? context : NULL, False);
542         if ( !_hGLContext )
543         {
544             SG_LOG(SG_GL, SG_ALERT, 
545                     "RenderTexture Error: glXCreateContext() failed.");
546             return false;
547         }
548     }
549     
550     if (!glXVersion1_3Present)
551     {
552         glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_WIDTH_SGIX, 
553                                   (GLuint*)&_iWidth);
554         glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_HEIGHT_SGIX, 
555                                   (GLuint*)&_iHeight);
556     }
557     
558     _bInitialized = true;
559     
560     // XXX Query the color format
561     
562 #endif
563
564     
565     // Now that the pbuffer is created, allocate any texture objects needed,
566     // and initialize them (for CTT updates only).  These must be allocated
567     // in the context of the pbuffer, though, or the RT won't work without
568     // wglShareLists.
569 #ifdef _WIN32
570     if (false == wglMakeCurrent( _hDC, _hGLContext))
571     {
572         _wglGetLastError();
573         return false;
574     }
575 #elif defined( __APPLE__ )
576 #else
577     _hPreviousContext = glXGetCurrentContext();
578     _hPreviousDrawable = glXGetCurrentDrawable();
579     
580     if (False == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext)) 
581     {
582         return false;
583     }
584 #endif
585     
586     bool result = _InitializeTextures();   
587 #ifdef _WIN32
588     BindBuffer(WGL_FRONT_LEFT_ARB);
589     _BindDepthBuffer();
590 #endif
591
592     
593 #ifdef _WIN32 
594     // make the previous rendering context current 
595     if (false == wglMakeCurrent( hdc, hglrc))
596     {
597         _wglGetLastError();
598         return false;
599     }
600 #elif defined( __APPLE__ )
601 #else
602     if (False == glXMakeCurrent(_pDisplay, 
603                                 _hPreviousDrawable, _hPreviousContext))
604     {
605         return false;
606     }
607     if (glXVersion1_3Present)
608     {
609         GLXDrawable draw = glXGetCurrentDrawable();
610         glXQueryDrawablePtr(_pDisplay, draw, GLX_WIDTH, (unsigned int*)&_iWidth);
611         glXQueryDrawablePtr(_pDisplay, draw, GLX_HEIGHT, (unsigned int*)&_iHeight);
612     }
613 #endif
614
615     return result;
616 }
617
618
619 //---------------------------------------------------------------------------
620 // Function             : RenderTexture::_Invalidate
621 // Description      : 
622 //---------------------------------------------------------------------------
623 /**
624 * @fn RenderTexture::_Invalidate()
625 * @brief Returns the pbuffer memory to the graphics device.
626
627 */ 
628 bool RenderTexture::_Invalidate()
629 {
630     _iNumColorBits[0] = _iNumColorBits[1] = 
631         _iNumColorBits[2] = _iNumColorBits[3] = 0;
632     _iNumDepthBits = 0;
633     _iNumStencilBits = 0;
634     
635     if (_bIsTexture)
636         glDeleteTextures(1, &_iTextureID);
637     if (_bIsDepthTexture) 
638     {
639         // [Redge]
640         if (!_bHasARBDepthTexture) delete[] _pPoorDepthTexture;
641         // [/Redge]
642         glDeleteTextures(1, &_iDepthTextureID);
643     }
644     
645 #ifdef _WIN32
646     if ( _hPBuffer )
647     {
648         // Check if we are currently rendering in the pbuffer
649         if (wglGetCurrentContext() == _hGLContext)
650             wglMakeCurrent(0,0);
651         if (!_bCopyContext) 
652             wglDeleteContext( _hGLContext);
653         wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
654         wglDestroyPbufferARBPtr( _hPBuffer );
655         _hPBuffer = 0;
656         return true;
657     }
658 #elif defined( __APPLE__ )
659 #else
660     if ( _hPBuffer )
661     {
662         if(glXGetCurrentContext() == _hGLContext)
663             // XXX I don't know if this is right at all
664             glXMakeCurrent(_pDisplay, _hPBuffer, 0);
665         glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
666         _hPBuffer = 0;
667         return true;
668     }
669 #endif
670
671     // [WVB] do we need to call _ReleaseBoundBuffers() too?
672     return false;
673 }
674
675
676 //---------------------------------------------------------------------------
677 // Function             : RenderTexture::Reset
678 // Description      : 
679 //---------------------------------------------------------------------------
680 /**
681 * @fn RenderTexture::Reset()
682 * @brief Resets the resolution of the offscreen buffer.
683
684 * Causes the buffer to delete itself.  User must call Initialize() again
685 * before use.
686 */ 
687 bool RenderTexture::Reset(const char *strMode, ...)
688 {
689     _iWidth = 0; _iHeight = 0; 
690     _bIsTexture = false; _bIsDepthTexture = false,
691     _bHasARBDepthTexture = true;
692 #ifdef _WIN32
693     _eUpdateMode = RT_RENDER_TO_TEXTURE;
694 #else
695     _eUpdateMode = RT_COPY_TO_TEXTURE;
696 #endif
697     _bInitialized = false;
698     _iNumAuxBuffers = 0; 
699     _bIsBufferBound = false;
700     _iCurrentBoundBuffer = 0;
701     _iNumDepthBits = 0; _iNumStencilBits = 0;
702     _bDoubleBuffered = false;
703     _bFloat = false; _bPowerOf2 = true;
704     _bRectangle = false; _bMipmap = false; 
705     _bShareObjects = false; _bCopyContext = false; 
706     _iTextureTarget = GL_NONE; _iTextureID = 0; 
707     _iDepthTextureID = 0;
708     _pPoorDepthTexture = 0;
709     _pixelFormatAttribs.clear();
710     _pbufferAttribs.clear();
711
712     if (IsInitialized() && !_Invalidate())
713     {
714         SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Reset(): failed to invalidate.");
715         return false;
716     }
717     
718     _iNumColorBits[0] = _iNumColorBits[1] = 
719         _iNumColorBits[2] = _iNumColorBits[3] = 0;
720
721 #ifdef _WIN32
722     _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
723     _pixelFormatAttribs.push_back(true);
724     _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
725     _pixelFormatAttribs.push_back(true);
726     
727     _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
728     _pbufferAttribs.push_back(true);
729 #elif defined( __APPLE__ )
730 #else
731     _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
732     _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
733     _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
734     _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
735 #endif
736
737     va_list args;
738     char strBuffer[256];
739     va_start(args,strMode);
740 #if defined _WIN32 && !defined __CYGWIN__
741     _vsnprintf( strBuffer, 256, strMode, args );
742 #else
743     vsnprintf( strBuffer, 256, strMode, args );
744 #endif
745     va_end(args);
746
747     _ParseModeString(strBuffer, _pixelFormatAttribs, _pbufferAttribs);
748
749 #ifdef _WIN32
750     _pixelFormatAttribs.push_back(0);
751     _pbufferAttribs.push_back(0);
752 #else
753     _pixelFormatAttribs.push_back(None);
754 #endif
755     return true;
756 }
757
758 //------------------------------------------------------------------------------
759 // Function               : RenderTexture::Resize
760 // Description      : 
761 //------------------------------------------------------------------------------
762 /**
763  * @fn RenderTexture::Resize(int iWidth, int iHeight)
764  * @brief Changes the size of the offscreen buffer.
765  * 
766  * Like Reset() this causes the buffer to delete itself.  
767  * But unlike Reset(), this call re-initializes the RenderTexture.
768  * Note that Resize() will not work after calling Reset(), or before
769  * calling Initialize() the first time.
770  */ 
771 bool RenderTexture::Resize(int iWidth, int iHeight)
772 {
773     if (!_bInitialized) {
774         SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): must Initialize() first.");
775         return false;
776     }
777     if (iWidth == _iWidth && iHeight == _iHeight) {
778         return true;
779     }
780     
781     // Do same basic work as _Invalidate, but don't reset all our flags
782     if (_bIsTexture)
783         glDeleteTextures(1, &_iTextureID);
784     if (_bIsDepthTexture)
785         glDeleteTextures(1, &_iDepthTextureID);
786 #ifdef _WIN32
787     if ( _hPBuffer )
788     {
789         // Check if we are currently rendering in the pbuffer
790         if (wglGetCurrentContext() == _hGLContext)
791             wglMakeCurrent(0,0);
792         if (!_bCopyContext) 
793             wglDeleteContext( _hGLContext);
794         wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
795         wglDestroyPbufferARBPtr( _hPBuffer );
796         _hPBuffer = 0;
797         return true;
798     }
799 #elif defined( __APPLE__ )
800 #else
801     if ( _hPBuffer )
802     {
803         if(glXGetCurrentContext() == _hGLContext)
804             // XXX I don't know if this is right at all
805             glXMakeCurrent(_pDisplay, _hPBuffer, 0);
806         glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
807         _hPBuffer = 0;
808     }
809 #endif
810     else {
811         SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): failed to resize.");
812         return false;
813     }
814     _bInitialized = false;
815     return Initialize(iWidth, iHeight, _bShareObjects, _bCopyContext);
816 }
817
818 //---------------------------------------------------------------------------
819 // Function             : RenderTexture::BeginCapture
820 // Description      : 
821 //---------------------------------------------------------------------------
822 /**
823 * @fn RenderTexture::BeginCapture()
824 * @brief Activates rendering to the RenderTexture.
825 */ 
826 bool RenderTexture::BeginCapture()
827 {
828     if (!_bInitialized)
829     {
830         SG_LOG(SG_GL, SG_ALERT, 
831                 "RenderTexture::BeginCapture(): Texture is not initialized!");
832         return false;
833     }
834 #ifdef _WIN32
835     // cache the current context so we can reset it when EndCapture() is called.
836     _hPreviousDC      = wglGetCurrentDC();
837     if (NULL == _hPreviousDC)
838         _wglGetLastError();
839     _hPreviousContext = wglGetCurrentContext();
840     if (NULL == _hPreviousContext)
841         _wglGetLastError();
842 #elif defined( __APPLE__ )
843 #else
844     _hPreviousContext = glXGetCurrentContext();
845     _hPreviousDrawable = glXGetCurrentDrawable();
846 #endif
847
848     _ReleaseBoundBuffers();
849
850     return _MakeCurrent();
851 }
852
853
854 //---------------------------------------------------------------------------
855 // Function             : RenderTexture::EndCapture
856 // Description      : 
857 //---------------------------------------------------------------------------
858 /**
859 * @fn RenderTexture::EndCapture()
860 * @brief Ends rendering to the RenderTexture.
861 */ 
862 bool RenderTexture::EndCapture()
863 {    
864     if (!_bInitialized)
865     {
866         SG_LOG(SG_GL, SG_ALERT, 
867                 "RenderTexture::EndCapture() : Texture is not initialized!");
868         return false;
869     }
870
871     _MaybeCopyBuffer();
872
873 #ifdef _WIN32
874     // make the previous rendering context current 
875     if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
876     {
877         _wglGetLastError();
878         return false;
879     }
880 #elif defined( __APPLE__ )
881 #else
882     if (False == glXMakeCurrent(_pDisplay, _hPreviousDrawable, 
883                                 _hPreviousContext))
884     {
885         return false;
886     }
887 #endif
888
889     // rebind the textures to a buffers for RTT
890     BindBuffer(_iCurrentBoundBuffer);
891     _BindDepthBuffer();
892
893     return true;
894 }
895
896 //---------------------------------------------------------------------------
897 // Function               : RenderTexture::BeginCapture(RenderTexture*)
898 // Description      : 
899 //---------------------------------------------------------------------------
900 /**
901  * @fn RenderTexture::BeginCapture(RenderTexture* other)
902  * @brief Ends capture of 'other', begins capture on 'this'
903  *
904  * When performing a series of operations where you modify one texture after 
905  * another, it is more efficient to use this method instead of the equivalent
906  * 'EndCapture'/'BeginCapture' pair.  This method switches directly to the 
907  * new context rather than changing to the default context, and then to the 
908  * new context.
909  *
910  * RenderTexture doesn't have any mechanism for determining if 
911  * 'current' really is currently active, so no error will be thrown 
912  * if it is not. 
913  */ 
914 bool RenderTexture::BeginCapture(RenderTexture* current)
915 {
916     bool bContextReset = false;
917     
918     if (current == this) {
919         return true; // no switch necessary
920     }
921     if (!current) {
922         // treat as normal Begin if current is 0.
923         return BeginCapture();
924     }
925     if (!_bInitialized)
926     {
927         SG_LOG(SG_GL, SG_ALERT, 
928             "RenderTexture::BeginCapture(RenderTexture*): Texture is not initialized!");
929         return false;
930     }
931     if (!current->_bInitialized)
932     {
933         SG_LOG(SG_GL, SG_ALERT, 
934             "RenderTexture::BeginCapture(RenderTexture): 'current' texture is not initialized!");
935         return false;
936     }
937     
938     // Sync current pbuffer with its CTT texture if necessary
939     current->_MaybeCopyBuffer();
940
941     // pass along the previous context so we can reset it when 
942     // EndCapture() is called.
943 #ifdef _WIN32
944     _hPreviousDC      = current->_hPreviousDC;
945     if (NULL == _hPreviousDC)
946         _wglGetLastError();
947     _hPreviousContext = current->_hPreviousContext;
948     if (NULL == _hPreviousContext)
949         _wglGetLastError();
950 #elif defined( __APPLE__ )
951 #else
952     _hPreviousContext = current->_hPreviousContext;
953     _hPreviousDrawable = current->_hPreviousDrawable;
954 #endif    
955
956     // Unbind textures before making context current
957     if (!_ReleaseBoundBuffers()) 
958       return false;
959
960     // Make the pbuffer context current
961     if (!_MakeCurrent())
962         return false;
963
964     // Rebind buffers of initial RenderTexture
965     current->BindBuffer(_iCurrentBoundBuffer);
966     current->_BindDepthBuffer();
967     
968     return true;
969 }
970
971
972
973 //---------------------------------------------------------------------------
974 // Function             : RenderTexture::Bind
975 // Description      : 
976 //---------------------------------------------------------------------------
977 /**
978 * @fn RenderTexture::Bind()
979 * @brief Binds RGB texture.
980 */ 
981 void RenderTexture::Bind() const 
982
983     if (_bInitialized && _bIsTexture) 
984     {
985         glBindTexture(_iTextureTarget, _iTextureID);
986     }    
987 }
988
989
990 //---------------------------------------------------------------------------
991 // Function             : RenderTexture::BindDepth
992 // Description      : 
993 //---------------------------------------------------------------------------
994 /**
995 * @fn RenderTexture::BindDepth()
996 * @brief Binds depth texture.
997 */ 
998 void RenderTexture::BindDepth() const 
999
1000     if (_bInitialized && _bIsDepthTexture) 
1001     {
1002         glBindTexture(_iTextureTarget, _iDepthTextureID); 
1003     }
1004 }
1005
1006
1007 //---------------------------------------------------------------------------
1008 // Function             : RenderTexture::BindBuffer
1009 // Description      : 
1010 //---------------------------------------------------------------------------
1011 /**
1012 * @fn RenderTexture::BindBuffer()
1013 * @brief Associate the RTT texture id with 'iBuffer' (e.g. WGL_FRONT_LEFT_ARB)
1014 */ 
1015 bool RenderTexture::BindBuffer( int iBuffer )
1016
1017     // Must bind the texture too
1018     if (_bInitialized && _bIsTexture) 
1019     {
1020         glBindTexture(_iTextureTarget, _iTextureID);
1021         
1022 #ifdef _WIN32
1023         if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
1024             (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
1025         {
1026             if (FALSE == wglBindTexImageARBPtr(_hPBuffer, iBuffer))
1027             {
1028                 //  WVB: WGL API considers binding twice to the same buffer
1029                 //  to be an error.  But we don't want to 
1030                 //_wglGetLastError();
1031                 //return false;
1032                 SetLastError(0);
1033             }
1034             _bIsBufferBound = true;
1035             _iCurrentBoundBuffer = iBuffer;
1036         }
1037 #endif
1038     }    
1039     return true;
1040 }
1041
1042
1043 //---------------------------------------------------------------------------
1044 // Function             : RenderTexture::BindBuffer
1045 // Description      : 
1046 //---------------------------------------------------------------------------
1047 /**
1048 * @fn RenderTexture::_BindDepthBuffer()
1049 * @brief Associate the RTT depth texture id with the depth buffer
1050 */ 
1051 bool RenderTexture::_BindDepthBuffer() const
1052 {
1053 #ifdef WIN32
1054     if (_bInitialized && _bIsDepthTexture && 
1055         RT_RENDER_TO_TEXTURE == _eUpdateMode)
1056     {
1057         glBindTexture(_iTextureTarget, _iDepthTextureID);
1058         if (FALSE == wglBindTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1059         {
1060             _wglGetLastError();
1061             return false;
1062         }
1063     }
1064 #endif
1065     return true;
1066 }
1067
1068 //---------------------------------------------------------------------------
1069 // Function             : RenderTexture::_ParseModeString
1070 // Description      : 
1071 //---------------------------------------------------------------------------
1072 /**
1073 * @fn RenderTexture::_ParseModeString()
1074 * @brief Parses the user-specified mode string for RenderTexture parameters.
1075 */ 
1076 void RenderTexture::_ParseModeString(const char *modeString, 
1077                                      vector<int> &pfAttribs, 
1078                                      vector<int> &pbAttribs)
1079 {
1080     if (!modeString || strcmp(modeString, "") == 0)
1081         return;
1082
1083         _iNumComponents = 0;
1084 #ifdef _WIN32
1085     _eUpdateMode = RT_RENDER_TO_TEXTURE;
1086 #else
1087     _eUpdateMode = RT_COPY_TO_TEXTURE;
1088 #endif
1089     
1090     int  iDepthBits = 0;
1091     bool bHasStencil = false;
1092     bool bBind2D   = false;
1093     bool bBindRECT = false;
1094     bool bBindCUBE = false;
1095     
1096     char *mode = strdup(modeString);
1097     
1098
1099     vector<string> tokens;
1100     char *buf = strtok(mode, " ");
1101     while (buf != NULL)
1102     {
1103         tokens.push_back(buf);
1104         buf = strtok(NULL, " ");
1105     }
1106
1107     for (unsigned int i = 0; i < tokens.size(); i++)
1108     {
1109         string token = tokens[i];
1110
1111         KeyVal kv = _GetKeyValuePair(token);
1112         
1113         
1114         if (kv.first == "rgb" && (_iNumComponents <= 1))
1115         {           
1116             if (kv.second.find("f") != kv.second.npos)
1117                 _bFloat = true;
1118
1119             vector<int> bitVec = _ParseBitVector(kv.second);
1120
1121             if (bitVec.size() < 3) // expand the scalar to a vector
1122             {
1123                 bitVec.push_back(bitVec[0]);
1124                 bitVec.push_back(bitVec[0]);
1125             }
1126
1127 #ifdef _WIN32
1128             pfAttribs.push_back(WGL_RED_BITS_ARB);
1129             pfAttribs.push_back(bitVec[0]);
1130             pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1131             pfAttribs.push_back(bitVec[1]);
1132             pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1133             pfAttribs.push_back(bitVec[2]);
1134 #elif defined( __APPLE__ )
1135             pfAttribs.push_back(AGL_RED_SIZE);
1136             pfAttribs.push_back(bitVec[0]);
1137             pfAttribs.push_back(AGL_GREEN_SIZE);
1138             pfAttribs.push_back(bitVec[1]);
1139             pfAttribs.push_back(AGL_BLUE_SIZE);
1140             pfAttribs.push_back(bitVec[2]);
1141 #else
1142             pfAttribs.push_back(GLX_RED_SIZE);
1143             pfAttribs.push_back(bitVec[0]);
1144             pfAttribs.push_back(GLX_GREEN_SIZE);
1145             pfAttribs.push_back(bitVec[1]);
1146             pfAttribs.push_back(GLX_BLUE_SIZE);
1147             pfAttribs.push_back(bitVec[2]);
1148 #endif
1149             _iNumComponents += 3;
1150             continue;
1151         }
1152                 else if (kv.first == "rgb") 
1153             SG_LOG(SG_GL, SG_ALERT, 
1154                     "RenderTexture Warning: mistake in components definition "
1155                     "(rgb + " << _iNumComponents << ").");
1156         
1157         if (kv.first == "rgba" && (_iNumComponents == 0))
1158         {
1159             if (kv.second.find("f") != kv.second.npos)
1160                 _bFloat = true;
1161
1162             vector<int> bitVec = _ParseBitVector(kv.second);
1163
1164             if (bitVec.size() < 4) // expand the scalar to a vector
1165             {
1166                 bitVec.push_back(bitVec[0]);
1167                 bitVec.push_back(bitVec[0]);
1168                 bitVec.push_back(bitVec[0]);
1169             }
1170
1171 #ifdef _WIN32
1172             pfAttribs.push_back(WGL_RED_BITS_ARB);
1173             pfAttribs.push_back(bitVec[0]);
1174             pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1175             pfAttribs.push_back(bitVec[1]);
1176             pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1177             pfAttribs.push_back(bitVec[2]);
1178             pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1179             pfAttribs.push_back(bitVec[3]);
1180 #elif defined( __APPLE__ )
1181             pfAttribs.push_back(AGL_RED_SIZE);
1182             pfAttribs.push_back(bitVec[0]);
1183             pfAttribs.push_back(AGL_GREEN_SIZE);
1184             pfAttribs.push_back(bitVec[1]);
1185             pfAttribs.push_back(AGL_BLUE_SIZE);
1186             pfAttribs.push_back(bitVec[2]);
1187             pfAttribs.push_back(AGL_ALPHA_SIZE);
1188             pfAttribs.push_back(bitVec[3]);
1189 #else
1190             pfAttribs.push_back(GLX_RED_SIZE);
1191             pfAttribs.push_back(bitVec[0]);
1192             pfAttribs.push_back(GLX_GREEN_SIZE);
1193             pfAttribs.push_back(bitVec[1]);
1194             pfAttribs.push_back(GLX_BLUE_SIZE);
1195             pfAttribs.push_back(bitVec[2]);
1196             pfAttribs.push_back(GLX_ALPHA_SIZE);
1197             pfAttribs.push_back(bitVec[3]);
1198 #endif
1199             _iNumComponents = 4;
1200             continue;
1201         }
1202                 else if (kv.first == "rgba") 
1203             SG_LOG(SG_GL, SG_ALERT, 
1204                     "RenderTexture Warning: mistake in components definition "
1205                     "(rgba + " << _iNumComponents << ").");
1206         
1207         if (kv.first == "r" && (_iNumComponents <= 1))
1208         {
1209             if (kv.second.find("f") != kv.second.npos)
1210                 _bFloat = true;
1211
1212             vector<int> bitVec = _ParseBitVector(kv.second);
1213
1214 #ifdef _WIN32
1215             pfAttribs.push_back(WGL_RED_BITS_ARB);
1216             pfAttribs.push_back(bitVec[0]);
1217 #elif defined( __APPLE__ )
1218             pfAttribs.push_back(AGL_RED_SIZE);
1219             pfAttribs.push_back(bitVec[0]);
1220 #else
1221             pfAttribs.push_back(GLX_RED_SIZE);
1222             pfAttribs.push_back(bitVec[0]);
1223 #endif
1224                         _iNumComponents++;
1225             continue;
1226         }
1227                 else if (kv.first == "r") 
1228             SG_LOG(SG_GL, SG_ALERT, 
1229                     "RenderTexture Warning: mistake in components definition "
1230                     "(r + " << _iNumComponents << ").");
1231
1232         if (kv.first == "rg" && (_iNumComponents <= 1))
1233         {
1234             if (kv.second.find("f") != kv.second.npos)
1235                 _bFloat = true;
1236
1237             vector<int> bitVec = _ParseBitVector(kv.second);
1238
1239             if (bitVec.size() < 2) // expand the scalar to a vector
1240             {
1241                 bitVec.push_back(bitVec[0]);
1242             }
1243
1244 #ifdef _WIN32
1245             pfAttribs.push_back(WGL_RED_BITS_ARB);
1246             pfAttribs.push_back(bitVec[0]);
1247             pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1248             pfAttribs.push_back(bitVec[1]);
1249 #elif defined( __APPLE__ )
1250             pfAttribs.push_back(AGL_RED_SIZE);
1251             pfAttribs.push_back(bitVec[0]);
1252             pfAttribs.push_back(AGL_GREEN_SIZE);
1253             pfAttribs.push_back(bitVec[1]);
1254 #else
1255             pfAttribs.push_back(GLX_RED_SIZE);
1256             pfAttribs.push_back(bitVec[0]);
1257             pfAttribs.push_back(GLX_GREEN_SIZE);
1258             pfAttribs.push_back(bitVec[1]);
1259 #endif
1260                         _iNumComponents += 2;
1261             continue;
1262         }
1263                 else if (kv.first == "rg") 
1264             SG_LOG(SG_GL, SG_ALERT, 
1265                     "RenderTexture Warning: mistake in components definition "
1266                     "(rg + " << _iNumComponents << ").");
1267
1268         if (kv.first == "depth")
1269         {
1270             if (kv.second == "")
1271                 iDepthBits = 24;
1272             else
1273                 iDepthBits = strtol(kv.second.c_str(), 0, 10);
1274             continue;
1275         }
1276
1277         if (kv.first == "stencil")
1278         {
1279             bHasStencil = true;
1280 #ifdef _WIN32
1281             pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1282 #elif defined( __APPLE__ )
1283             pfAttribs.push_back(AGL_STENCIL_SIZE);
1284 #else
1285             pfAttribs.push_back(GLX_STENCIL_SIZE);
1286 #endif
1287             if (kv.second == "")
1288                 pfAttribs.push_back(8);
1289             else
1290                 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1291             continue;
1292         }
1293
1294         if (kv.first == "samples")
1295         {
1296 #ifdef _WIN32
1297             pfAttribs.push_back(WGL_SAMPLE_BUFFERS_ARB);
1298             pfAttribs.push_back(1);
1299             pfAttribs.push_back(WGL_SAMPLES_ARB);
1300             pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1301 #elif defined( __APPLE__ )
1302             pfAttribs.push_back(AGL_SAMPLE_BUFFERS_ARB);
1303             pfAttribs.push_back(1);
1304             pfAttribs.push_back(AGL_SAMPLES_ARB);
1305             pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1306 #else
1307             pfAttribs.push_back(GLX_SAMPLE_BUFFERS_ARB);
1308             pfAttribs.push_back(1);
1309             pfAttribs.push_back(GLX_SAMPLES_ARB);
1310             pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1311 #endif
1312             continue;
1313
1314         }
1315
1316         if (kv.first == "doublebuffer" || kv.first == "double")
1317         {
1318 #ifdef _WIN32
1319             pfAttribs.push_back(WGL_DOUBLE_BUFFER_ARB);
1320             pfAttribs.push_back(true);
1321 #elif defined( __APPLE__ )
1322             pfAttribs.push_back(AGL_DOUBLEBUFFER);
1323             pfAttribs.push_back(True);
1324 #else
1325             pfAttribs.push_back(GLX_DOUBLEBUFFER);
1326             pfAttribs.push_back(True);
1327 #endif
1328             continue;
1329         }  
1330         
1331         if (kv.first == "aux")
1332         {
1333 #ifdef _WIN32
1334             pfAttribs.push_back(WGL_AUX_BUFFERS_ARB);
1335 #elif defined( __APPLE__ )
1336             pfAttribs.push_back(AGL_AUX_BUFFERS);
1337 #else
1338             pfAttribs.push_back(GLX_AUX_BUFFERS);
1339 #endif
1340             if (kv.second == "")
1341                 pfAttribs.push_back(0);
1342             else
1343                 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1344             continue;
1345         }
1346         
1347         if (token.find("tex") == 0)
1348         {            
1349             _bIsTexture = true;
1350             
1351             if ((kv.first == "texRECT") && GL_NV_texture_rectangle)
1352             {
1353                 _bRectangle = true;
1354                 bBindRECT = true;
1355             }
1356             else if (kv.first == "texCUBE")
1357             {
1358                 bBindCUBE = true;
1359             }
1360             else
1361             {
1362                 bBind2D = true;
1363             }
1364
1365             continue;
1366         }
1367
1368         if (token.find("depthTex") == 0)
1369         {
1370             _bIsDepthTexture = true;
1371             
1372             if ((kv.first == "depthTexRECT") && GL_NV_texture_rectangle)
1373             {
1374                 _bRectangle = true;
1375                 bBindRECT = true;
1376             }
1377             else if (kv.first == "depthTexCUBE")
1378             {
1379                 bBindCUBE = true;
1380             }
1381             else
1382             {
1383                 bBind2D = true;
1384             }
1385
1386             continue;
1387         }
1388
1389         if (kv.first == "mipmap")
1390         {
1391             _bMipmap = true;    
1392             continue;
1393         }
1394
1395         if (kv.first == "rtt")
1396         {
1397             _eUpdateMode = RT_RENDER_TO_TEXTURE;
1398             continue;
1399         }
1400         
1401         if (kv.first == "ctt")
1402         {
1403             _eUpdateMode = RT_COPY_TO_TEXTURE;
1404             continue;
1405         }
1406
1407         SG_LOG(SG_GL, SG_ALERT, 
1408                 "RenderTexture Error: Unknown pbuffer attribute: " <<
1409                 token.c_str());
1410     }
1411
1412     // Processing of some options must be last because of interactions.
1413
1414     // Check for inconsistent texture targets
1415     if (_bIsTexture && _bIsDepthTexture && !(bBind2D ^ bBindRECT ^ bBindCUBE))
1416     {
1417         SG_LOG(SG_GL, SG_ALERT,
1418                 "RenderTexture Warning: Depth and Color texture targets "
1419                 "should match.");
1420     }
1421
1422     // Apply default bit format if none specified
1423 #ifdef _WIN32
1424     if (0 == _iNumComponents)
1425     {
1426         pfAttribs.push_back(WGL_RED_BITS_ARB);
1427         pfAttribs.push_back(8);
1428         pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1429         pfAttribs.push_back(8);
1430         pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1431         pfAttribs.push_back(8);
1432         pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1433         pfAttribs.push_back(8);
1434         _iNumComponents = 4;
1435     }
1436 #endif
1437
1438     // Depth bits
1439     if (_bIsDepthTexture && !iDepthBits)
1440         iDepthBits = 24;
1441
1442 #ifdef _WIN32
1443     pfAttribs.push_back(WGL_DEPTH_BITS_ARB);
1444 #elif defined( __APPLE__ )
1445     pfAttribs.push_back(AGL_DEPTH_SIZE);
1446 #else
1447     pfAttribs.push_back(GLX_DEPTH_SIZE);
1448 #endif
1449     pfAttribs.push_back(iDepthBits); // default
1450     
1451     if (!bHasStencil)
1452     {
1453 #ifdef _WIN32
1454         pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1455         pfAttribs.push_back(0);
1456 #elif defined( __APPLE__ )
1457         pfAttribs.push_back(AGL_STENCIL_SIZE);
1458         pfAttribs.push_back(0);
1459 #else
1460         pfAttribs.push_back(GLX_STENCIL_SIZE);
1461         pfAttribs.push_back(0);
1462 #endif
1463
1464     }
1465     if (_iNumComponents < 4)
1466     {
1467         // Can't do this right now -- on NVIDIA drivers, currently get 
1468         // a non-functioning pbuffer if ALPHA_BITS=0 and 
1469         // WGL_BIND_TO_TEXTURE_RGB_ARB=true
1470         
1471         //pfAttribs.push_back(WGL_ALPHA_BITS_ARB); 
1472         //pfAttribs.push_back(0);
1473     }
1474
1475 #ifdef _WIN32
1476     if (!WGL_NV_render_depth_texture && _bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1477     {
1478 #if defined(DEBUG) || defined(_DEBUG)
1479         SG_LOG(SG_GL, SG_ALERT, "RenderTexture Warning: No support found for "
1480                 "render to depth texture.");
1481 #endif
1482         _bIsDepthTexture = false;
1483     }
1484 #endif
1485     
1486     if ((_bIsTexture || _bIsDepthTexture) && 
1487         (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1488     {
1489 #ifdef _WIN32                   
1490         if (bBindRECT)
1491         {
1492             pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1493             pbAttribs.push_back(WGL_TEXTURE_RECTANGLE_NV);
1494         }
1495         else if (bBindCUBE)
1496         {
1497             pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1498             pbAttribs.push_back(WGL_TEXTURE_CUBE_MAP_ARB);
1499         }
1500         else if (bBind2D)
1501         {
1502             pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1503             pbAttribs.push_back(WGL_TEXTURE_2D_ARB);
1504         }
1505             
1506         if (_bMipmap)
1507         {
1508             pbAttribs.push_back(WGL_MIPMAP_TEXTURE_ARB);
1509             pbAttribs.push_back(true);
1510         }
1511
1512 #elif defined(DEBUG) || defined(_DEBUG)
1513         SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: Render to Texture not "
1514                "supported in Linux or MacOS");
1515 #endif  
1516     }
1517
1518     // Set the pixel type
1519     if (_bFloat)
1520     {
1521 #ifdef _WIN32
1522         if (WGL_NV_float_buffer)
1523         {
1524             pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1525             pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1526
1527             pfAttribs.push_back(WGL_FLOAT_COMPONENTS_NV);
1528             pfAttribs.push_back(true);
1529         }
1530         else
1531         {
1532             pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1533             pfAttribs.push_back(WGL_TYPE_RGBA_FLOAT_ATI);
1534         }
1535 #elif defined( __APPLE__ )
1536 #else
1537         if (GLX_NV_float_buffer)
1538         {
1539             pfAttribs.push_back(GLX_FLOAT_COMPONENTS_NV);
1540             pfAttribs.push_back(1);
1541         }
1542 #endif
1543     }
1544     else
1545     {
1546 #ifdef _WIN32
1547         pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1548         pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1549 #endif
1550     }
1551
1552     // Set up texture binding for render to texture
1553     if (_bIsTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1554     {
1555         
1556 #ifdef _WIN32
1557         if (_bFloat)
1558         {
1559             if (WGL_NV_float_buffer)
1560             {
1561                 switch(_iNumComponents)
1562                 {
1563                 case 1:
1564                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
1565                     pfAttribs.push_back(true);
1566                     
1567                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1568                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_R_NV);
1569                     break;
1570                 case 2:
1571                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
1572                     pfAttribs.push_back(true);
1573                     
1574                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1575                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_RG_NV);
1576                     break;
1577                 case 3:
1578                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
1579                     pfAttribs.push_back(true);
1580                     
1581                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1582                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGB_NV);
1583                     break;
1584                 case 4:
1585                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
1586                     pfAttribs.push_back(true);
1587                     
1588                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1589                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGBA_NV);
1590                     break;
1591                 default:
1592                     SG_LOG(SG_GL, SG_ALERT, 
1593                             "RenderTexture Warning: Bad number of components "
1594                             "(r=1,rg=2,rgb=3,rgba=4): %d.", 
1595                             _iNumComponents);
1596                     break;
1597                 }
1598             }
1599             else
1600             {
1601                 if (4 == _iNumComponents)
1602                 {
1603                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1604                     pfAttribs.push_back(true);
1605                     
1606                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1607                     pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1608                 }
1609                 else 
1610                 {
1611                     // standard ARB_render_texture only supports 3 or 4 channels
1612                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1613                     pfAttribs.push_back(true);
1614                     
1615                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1616                     pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1617                 }
1618             }
1619             
1620         } 
1621         else
1622         {
1623             switch(_iNumComponents)
1624             {
1625             case 3:
1626                 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1627                 pfAttribs.push_back(true);
1628                 
1629                 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1630                 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1631                 break;
1632             case 4:
1633                 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1634                 pfAttribs.push_back(true);
1635                 
1636                 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1637                 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1638                 break;
1639             default:
1640                 SG_LOG(SG_GL, SG_ALERT, 
1641                         "RenderTexture Warning: Bad number of components "
1642                         "(r=1,rg=2,rgb=3,rgba=4): %d.", _iNumComponents);
1643                 break;
1644             }
1645         }         
1646 #elif defined(DEBUG) || defined(_DEBUG)
1647         SG_LOG(SG_GL, SG_ALERT, 
1648                 "RenderTexture Error: Render to Texture not supported in "
1649                 "Linux or MacOS\ n");
1650 #endif  
1651     }
1652         
1653     if (_bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1654     {  
1655 #ifdef _WIN32
1656         if (_bRectangle)
1657         {
1658             pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV);
1659             pfAttribs.push_back(true);
1660         
1661             pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
1662             pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
1663         }
1664         else 
1665         {
1666             pfAttribs.push_back(WGL_BIND_TO_TEXTURE_DEPTH_NV);
1667             pfAttribs.push_back(true);
1668         
1669             pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
1670             pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
1671         }
1672 #elif defined(DEBUG) || defined(_DEBUG)
1673         SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: Render to Texture not supported in "
1674                "Linux or MacOS");
1675 #endif 
1676     }
1677 }
1678
1679 //---------------------------------------------------------------------------
1680 // Function             : RenderTexture::_GetKeyValuePair
1681 // Description      : 
1682 //---------------------------------------------------------------------------
1683 /**
1684 * @fn RenderTexture::_GetKeyValuePair()
1685 * @brief Parses expressions of the form "X=Y" into a pair (X,Y).
1686 */ 
1687 RenderTexture::KeyVal RenderTexture::_GetKeyValuePair(string token)
1688 {
1689     string::size_type pos = 0;
1690     if ((pos = token.find("=")) != token.npos)
1691     {
1692         string key = token.substr(0, pos);
1693         string value = token.substr(pos+1, token.length()-pos+1);
1694         return KeyVal(key, value);
1695     }
1696     else
1697         return KeyVal(token, "");
1698 }
1699
1700 //---------------------------------------------------------------------------
1701 // Function             : RenderTexture::_ParseBitVector
1702 // Description      : 
1703 //---------------------------------------------------------------------------
1704 /**
1705 * @fn RenderTexture::_ParseBitVector()
1706 * @brief Parses expressions of the form "=r,g,b,a" into a vector: (r,g,b,a)
1707 */ 
1708 vector<int> RenderTexture::_ParseBitVector(string bitVector)
1709 {
1710     vector<string> pieces;
1711     vector<int> bits;
1712
1713     if (bitVector == "")
1714     {
1715         bits.push_back(8);  // if a depth isn't specified, use default 8 bits
1716         return bits;
1717     }
1718
1719     string::size_type pos = 0; 
1720     string::size_type nextpos = 0;
1721     do
1722     { 
1723         nextpos = bitVector.find_first_of(", ", pos);
1724         pieces.push_back(string(bitVector, pos, nextpos - pos)); 
1725         pos = nextpos+1; 
1726     } while (nextpos != bitVector.npos );
1727
1728     for ( vector<string>::iterator it = pieces.begin(); it != pieces.end(); it++)
1729     {
1730         bits.push_back(strtol(it->c_str(), 0, 10));
1731     }
1732     
1733     return bits;
1734 }
1735
1736 //---------------------------------------------------------------------------
1737 // Function             : RenderTexture::_VerifyExtensions
1738 // Description      : 
1739 //---------------------------------------------------------------------------
1740 /**
1741 * @fn RenderTexture::_VerifyExtensions()
1742 * @brief Checks that the necessary extensions are available based on RT mode.
1743 */ 
1744 bool RenderTexture::_VerifyExtensions()
1745 {
1746 #ifdef _WIN32
1747         // a second call to _VerifyExtensions will allways return true, causing a crash
1748         // if the extension is not supported
1749     if ( true || !fctPtrInited )
1750     {
1751         fctPtrInited = true;
1752         wglGetExtensionsStringARBProc wglGetExtensionsStringARBPtr = (wglGetExtensionsStringARBProc)wglGetProcAddress( "wglGetExtensionsStringARB" );
1753         if ( wglGetExtensionsStringARBPtr == 0 )
1754         {
1755             PrintExtensionError("WGL_ARB_extensions_string");
1756             return false;
1757         }
1758         string wglExtensionsString = wglGetExtensionsStringARBPtr( wglGetCurrentDC() );
1759         if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pixel_format" ) )
1760         {
1761             wglChoosePixelFormatARBPtr = (wglChoosePixelFormatARBProc)SGLookupFunction("wglChoosePixelFormatARB");
1762             wglGetPixelFormatAttribivARBPtr = (wglGetPixelFormatAttribivARBProc)SGLookupFunction("wglGetPixelFormatAttribivARB");
1763         }
1764         else
1765         {
1766             PrintExtensionError("WGL_ARB_pixel_format");
1767             return false;
1768         }
1769         if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pbuffer" ) )
1770         {
1771             wglCreatePbufferARBPtr = (wglCreatePbufferARBProc)SGLookupFunction("wglCreatePbufferARB");
1772             wglGetPbufferDCARBPtr = (wglGetPbufferDCARBProc)SGLookupFunction("wglGetPbufferDCARB");
1773             wglQueryPbufferARBPtr = (wglQueryPbufferARBProc)SGLookupFunction("wglQueryPbufferARB");
1774             wglReleasePbufferDCARBPtr = (wglReleasePbufferDCARBProc)SGLookupFunction("wglReleasePbufferDCARB");
1775             wglDestroyPbufferARBPtr = (wglDestroyPbufferARBProc)SGLookupFunction("wglDestroyPbufferARB");
1776         }
1777         else
1778         {
1779             PrintExtensionError("WGL_ARB_pbuffer");
1780             return false;
1781         }
1782         if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_render_texture" ) )
1783         {
1784             wglBindTexImageARBPtr = (wglBindTexImageARBProc)SGLookupFunction("wglBindTexImageARB");
1785             wglReleaseTexImageARBPtr = (wglReleaseTexImageARBProc)SGLookupFunction("wglReleaseTexImageARB");
1786         }
1787         else if ( _bIsTexture )
1788         {
1789             PrintExtensionError("WGL_ARB_render_texture");
1790             return false;
1791         }
1792         if (_bRectangle && !SGIsOpenGLExtensionSupported( "GL_NV_texture_rectangle" ))
1793         {
1794             PrintExtensionError("GL_NV_texture_rectangle");
1795             return false;
1796         }
1797         if (_bFloat && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) || SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ATI_pixel_format_float" )))
1798         {
1799             PrintExtensionError("GL_NV_float_buffer or GL_ATI_pixel_format_float");
1800             return false;
1801         
1802         }
1803         if (_bFloat && _bIsTexture && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) || SGIsOpenGLExtensionSupported( "GL_ATI_texture_float" )))
1804         {
1805             PrintExtensionError("NV_float_buffer or ATI_texture_float");
1806         }
1807         if (_bIsDepthTexture && !SGIsOpenGLExtensionSupported( "GL_ARB_depth_texture" ))
1808         {
1809             // [Redge]
1810 #if defined(_DEBUG) | defined(DEBUG)
1811             SG_LOG(SG_GL, SG_ALERT, 
1812                     "RenderTexture Warning: "
1813                     "OpenGL extension GL_ARB_depth_texture not available."
1814                     "         Using glReadPixels() to emulate behavior.");
1815 #endif   
1816             _bHasARBDepthTexture = false;
1817             //PrintExtensionError("GL_ARB_depth_texture");
1818             //return false;
1819             // [/Redge]
1820         }
1821         SetLastError(0);
1822     }
1823 #elif defined( __APPLE__ )
1824 #else
1825
1826     // First try the glX version 1.3 functions.
1827     glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfig");
1828     glXCreatePbufferPtr = (glXCreatePbufferProc)SGLookupFunction("glXCreatePbuffer");
1829     glXGetVisualFromFBConfigPtr = (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfig");
1830     glXCreateContextPtr = (glXCreateContextProc)SGLookupFunction("glXCreateContext");
1831     glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyPbuffer");
1832     glXQueryDrawablePtr = (glXQueryDrawableProc)SGLookupFunction("glXQueryDrawable");
1833
1834     if (glXChooseFBConfigPtr &&
1835         glXCreatePbufferPtr &&
1836         glXGetVisualFromFBConfigPtr &&
1837         glXCreateContextPtr &&
1838         glXDestroyPbufferPtr &&
1839         glXQueryDrawablePtr)
1840         glXVersion1_3Present = true;
1841     else
1842     {
1843         glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfigSGIX");
1844         glXCreateGLXPbufferPtr = (glXCreateGLXPbufferProc)SGLookupFunction("glXCreateGLXPbufferSGIX");
1845         glXGetVisualFromFBConfigPtr =  (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfigSGIX");
1846         glXCreateContextWithConfigPtr = (glXCreateContextWithConfigProc)SGLookupFunction("glXCreateContextWithConfigSGIX");
1847         glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyGLXPbufferSGIX");
1848         glXQueryGLXPbufferSGIXPtr = (glXQueryGLXPbufferSGIXProc)SGLookupFunction("glXQueryGLXPbufferSGIX");
1849
1850
1851         if (!glXChooseFBConfigPtr ||
1852             !glXCreateGLXPbufferPtr ||
1853             !glXGetVisualFromFBConfigPtr ||
1854             !glXCreateContextWithConfigPtr ||
1855             !glXDestroyPbufferPtr ||
1856             !glXQueryGLXPbufferSGIXPtr)
1857             return false;
1858     }
1859
1860     if (_bIsDepthTexture && !GL_ARB_depth_texture)
1861     {
1862         PrintExtensionError("GL_ARB_depth_texture");
1863         return false;
1864     }
1865     if (_bFloat && _bIsTexture && !GLX_NV_float_buffer)
1866     {
1867         PrintExtensionError("GLX_NV_float_buffer");
1868         return false;
1869     }
1870     if (_eUpdateMode == RT_RENDER_TO_TEXTURE)
1871     {
1872         PrintExtensionError("Some GLX render texture extension: Please implement me!");
1873         return false;
1874     }
1875 #endif
1876   
1877     return true;
1878 }
1879
1880 //---------------------------------------------------------------------------
1881 // Function             : RenderTexture::_InitializeTextures
1882 // Description      : 
1883 //---------------------------------------------------------------------------
1884 /**
1885 * @fn RenderTexture::_InitializeTextures()
1886 * @brief Initializes the state of textures used by the RenderTexture.
1887 */ 
1888 bool RenderTexture::_InitializeTextures()
1889 {
1890     // Determine the appropriate texture formats and filtering modes.
1891     if (_bIsTexture || _bIsDepthTexture)
1892     {
1893         if (_bRectangle && GL_NV_texture_rectangle)
1894             _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
1895         else
1896             _iTextureTarget = GL_TEXTURE_2D;
1897     }
1898
1899     if (_bIsTexture)
1900     {
1901         glGenTextures(1, (GLuint*)&_iTextureID);
1902         glBindTexture(_iTextureTarget, _iTextureID);  
1903         
1904         // Use clamp to edge as the default texture wrap mode for all tex
1905         glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1906         glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
1907         // Use NEAREST as the default texture filtering mode.
1908         glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1909         glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1910
1911
1912         if (RT_COPY_TO_TEXTURE == _eUpdateMode)
1913         {
1914             GLuint iInternalFormat;
1915             GLuint iFormat;
1916
1917             if (_bFloat)
1918             {                             
1919                 if (_bMipmap)
1920                 {
1921                     SG_LOG(SG_GL, SG_ALERT, 
1922                         "RenderTexture Error: mipmapped float textures not "
1923                         "supported.");
1924                     return false;
1925                 }
1926             
1927                 switch(_iNumComponents) 
1928                 {
1929                 case 1:
1930                     if (GL_NV_float_buffer)
1931                     {
1932                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
1933                             GL_FLOAT_R32_NV : GL_FLOAT_R16_NV;
1934                     }
1935                     else if (GL_ATI_texture_float)
1936                     {
1937                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
1938                             GL_LUMINANCE_FLOAT32_ATI : 
1939                             GL_LUMINANCE_FLOAT16_ATI;
1940                     }
1941                     iFormat = GL_LUMINANCE;
1942                         break;
1943                 case 2:
1944                     if (GL_NV_float_buffer)
1945                     {
1946                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
1947                             GL_FLOAT_RG32_NV : GL_FLOAT_RG16_NV;
1948                     }
1949                     else if (GL_ATI_texture_float)
1950                     {
1951                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
1952                             GL_LUMINANCE_ALPHA_FLOAT32_ATI : 
1953                             GL_LUMINANCE_ALPHA_FLOAT16_ATI;
1954                     }
1955                     iFormat = GL_LUMINANCE_ALPHA;
1956                         break;
1957                 case 3:
1958                     if (GL_NV_float_buffer)
1959                     {
1960                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
1961                             GL_FLOAT_RGB32_NV : GL_FLOAT_RGB16_NV;
1962                     }
1963                     else if (GL_ATI_texture_float)
1964                     {
1965                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
1966                             GL_RGB_FLOAT32_ATI : GL_RGB_FLOAT16_ATI;
1967                     }
1968                     iFormat = GL_RGB;
1969                     break;
1970                 case 4:
1971                     if (GL_NV_float_buffer)
1972                     {
1973                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
1974                             GL_FLOAT_RGBA32_NV : GL_FLOAT_RGBA16_NV;
1975                     }
1976                     else if (GL_ATI_texture_float)
1977                     {
1978                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
1979                             GL_RGBA_FLOAT32_ATI : GL_RGBA_FLOAT16_ATI;
1980                     }
1981                     iFormat = GL_RGBA;
1982                     break;
1983                 default:
1984                     SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: "
1985                            "Invalid number of components: " <<
1986                            _iNumComponents);
1987                     return false;
1988                 }
1989             }
1990             else // non-float
1991             {                        
1992                 if (4 == _iNumComponents)
1993                 {
1994                     iInternalFormat = GL_RGBA8;
1995                     iFormat = GL_RGBA;
1996                 }
1997                 else 
1998                 {
1999                     iInternalFormat = GL_RGB8;
2000                     iFormat = GL_RGB;
2001                 }
2002             }
2003         
2004             // Allocate the texture image (but pass it no data for now).
2005             glTexImage2D(_iTextureTarget, 0, iInternalFormat, 
2006                          _iWidth, _iHeight, 0, iFormat, GL_FLOAT, NULL);
2007         } 
2008     }
2009   
2010     if (_bIsDepthTexture)
2011     { 
2012         glGenTextures(1, (GLuint*)&_iDepthTextureID);
2013         glBindTexture(_iTextureTarget, _iDepthTextureID);  
2014         
2015         // Use clamp to edge as the default texture wrap mode for all tex
2016         glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2017         glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
2018         // Use NEAREST as the default texture filtering mode.
2019         glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2020         glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2021                
2022         if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2023         {
2024             // [Redge]
2025             if (_bHasARBDepthTexture) 
2026             {
2027                 // Allocate the texture image (but pass it no data for now).
2028                 glTexImage2D(_iTextureTarget, 0, GL_DEPTH_COMPONENT, 
2029                              _iWidth, _iHeight, 0, GL_DEPTH_COMPONENT, 
2030                              GL_FLOAT, NULL);
2031             } 
2032             else 
2033             {
2034                 // allocate memory for depth texture
2035                 // Since this is slow, we warn the user in debug mode. (above)
2036                 _pPoorDepthTexture = new unsigned short[_iWidth * _iHeight];
2037                 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16, 
2038                              _iWidth, _iHeight, 0, GL_LUMINANCE, 
2039                              GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2040             }
2041             // [/Redge]
2042         }
2043     }
2044
2045     return true;
2046 }
2047
2048
2049 //---------------------------------------------------------------------------
2050 // Function             : RenderTexture::_MaybeCopyBuffer
2051 // Description      : 
2052 //---------------------------------------------------------------------------
2053 /**
2054 * @fn RenderTexture::_MaybeCopyBuffer()
2055 * @brief Does the actual copying for RenderTextures with RT_COPY_TO_TEXTURE
2056 */ 
2057 void RenderTexture::_MaybeCopyBuffer()
2058 {
2059 #ifdef _WIN32
2060     if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2061     {
2062         if (_bIsTexture)
2063         {
2064             glBindTexture(_iTextureTarget, _iTextureID);
2065             glCopyTexSubImage2D(_iTextureTarget, 
2066                                 0, 0, 0, 0, 0, _iWidth, _iHeight);
2067         }
2068         if (_bIsDepthTexture)
2069         {
2070             glBindTexture(_iTextureTarget, _iDepthTextureID);
2071             // HOW TO COPY DEPTH TEXTURE??? Supposedly this just magically works...
2072             // [Redge]
2073             if (_bHasARBDepthTexture) 
2074             {
2075                 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, 
2076                                     _iWidth, _iHeight);
2077             } 
2078             else 
2079             {
2080                 // no 'real' depth texture available, so behavior has to be emulated
2081                 // using glReadPixels (beware, this is (naturally) slow ...)
2082                 glReadPixels(0, 0, _iWidth, _iHeight, GL_DEPTH_COMPONENT, 
2083                              GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2084                 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
2085                              _iWidth, _iHeight, 0, GL_LUMINANCE, 
2086                              GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2087             }
2088             // [/Redge]
2089         }
2090     }
2091     
2092 #else
2093     if (_bIsTexture)
2094     {
2095       glBindTexture(_iTextureTarget, _iTextureID);
2096       glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2097     }
2098     if (_bIsDepthTexture)
2099     {
2100       glBindTexture(_iTextureTarget, _iDepthTextureID);
2101       assert(_bHasARBDepthTexture);
2102       glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2103     }
2104 #endif
2105
2106 }
2107
2108 //---------------------------------------------------------------------------
2109 // Function             : RenderTexture::_ReleaseBoundBuffers
2110 // Description      : 
2111 //---------------------------------------------------------------------------
2112 /**
2113 * @fn RenderTexture::_ReleaseBoundBuffers()
2114 * @brief Releases buffer bindings on RenderTextures with RT_RENDER_TO_TEXTURE
2115 */ 
2116 bool RenderTexture::_ReleaseBoundBuffers()
2117 {
2118 #ifdef _WIN32
2119     if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2120     {
2121         glBindTexture(_iTextureTarget, _iTextureID);
2122         
2123         // release the pbuffer from the render texture object
2124         if (0 != _iCurrentBoundBuffer && _bIsBufferBound)
2125         {
2126             if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, _iCurrentBoundBuffer))
2127             {
2128                 _wglGetLastError();
2129                 return false;
2130             }
2131             _bIsBufferBound = false;
2132         }
2133     }
2134     
2135     if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2136     {
2137         glBindTexture(_iTextureTarget, _iDepthTextureID);
2138         
2139         // release the pbuffer from the render texture object
2140         if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
2141         {
2142             _wglGetLastError();
2143             return false;
2144         }
2145     }
2146     
2147 #else
2148     // textures can't be bound in Linux
2149 #endif
2150     return true;
2151 }
2152
2153 //---------------------------------------------------------------------------
2154 // Function             : RenderTexture::_MakeCurrent
2155 // Description      : 
2156 //---------------------------------------------------------------------------
2157 /**
2158 * @fn RenderTexture::_MakeCurrent()
2159 * @brief Makes the RenderTexture's context current
2160 */ 
2161
2162 bool RenderTexture::_MakeCurrent() 
2163 {
2164 #ifdef _WIN32
2165     // make the pbuffer's rendering context current.
2166     if (FALSE == wglMakeCurrent( _hDC, _hGLContext))
2167     {
2168         _wglGetLastError();
2169         return false;
2170     }
2171 #elif defined( __APPLE__ )
2172 #else
2173     if (false == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext)) 
2174     {
2175         return false;
2176     }
2177 #endif
2178
2179     return true;
2180 }
2181
2182 /////////////////////////////////////////////////////////////////////////////
2183 //
2184 // Begin Deprecated Interface
2185 //
2186 /////////////////////////////////////////////////////////////////////////////
2187
2188 //---------------------------------------------------------------------------
2189 // Function      : RenderTexture::RenderTexture
2190 // Description   : 
2191 //---------------------------------------------------------------------------
2192 /**
2193 * @fn RenderTexture::RenderTexture()
2194 * @brief Constructor.
2195 */ 
2196 RenderTexture::RenderTexture(int width, int height,
2197                                bool bIsTexture /* = true */,
2198                                bool bIsDepthTexture /* = false */)
2199 :   _iWidth(width), 
2200     _iHeight(height), 
2201     _bIsTexture(bIsTexture),
2202     _bIsDepthTexture(bIsDepthTexture),
2203     _bHasARBDepthTexture(true),            // [Redge]
2204     _eUpdateMode(RT_RENDER_TO_TEXTURE),
2205     _bInitialized(false),
2206     _iNumAuxBuffers(0),
2207     _iCurrentBoundBuffer(0),
2208     _iNumDepthBits(0),
2209     _iNumStencilBits(0),
2210     _bDoubleBuffered(false),
2211     _bFloat(false),
2212     _bPowerOf2(true),
2213     _bRectangle(false),
2214     _bMipmap(false),
2215     _bShareObjects(false),
2216     _bCopyContext(false),
2217 #ifdef _WIN32
2218     _hDC(NULL), 
2219     _hGLContext(NULL), 
2220     _hPBuffer(NULL),
2221     _hPreviousDC(0),
2222     _hPreviousContext(0),
2223 #elif defined( __APPLE__ )
2224 #else
2225     _pDisplay(NULL),
2226     _hGLContext(NULL),
2227     _hPBuffer(0),
2228     _hPreviousContext(0),
2229     _hPreviousDrawable(0),
2230 #endif
2231     _iTextureTarget(GL_NONE),
2232     _iTextureID(0),
2233     _iDepthTextureID(0),
2234     _pPoorDepthTexture(0) // [Redge]
2235 {
2236     assert(width > 0 && height > 0);
2237 #if defined DEBUG || defined _DEBUG
2238     SG_LOG(SG_GL, SG_ALERT, 
2239             "RenderTexture Warning: Deprecated Contructor interface used.");
2240 #endif
2241     
2242     _iNumColorBits[0] = _iNumColorBits[1] = 
2243         _iNumColorBits[2] = _iNumColorBits[3] = 0;
2244     _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
2245 }
2246
2247 //------------------------------------------------------------------------------
2248 // Function             : RenderTexture::Initialize
2249 // Description      : 
2250 //------------------------------------------------------------------------------
2251 /**
2252 * @fn RenderTexture::Initialize(bool bShare, bool bDepth, bool bStencil, bool bMipmap, unsigned int iRBits, unsigned int iGBits, unsigned int iBBits, unsigned int iABits);
2253 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
2254
2255 * This function actually does the creation of the p-buffer.  It can only be called 
2256 * once a GL context has already been created.  Note that if the texture is not
2257 * power of two dimensioned, or has more than 8 bits per channel, enabling mipmapping
2258 * will cause an error.
2259 */ 
2260 bool RenderTexture::Initialize(bool         bShare       /* = true */, 
2261                                 bool         bDepth       /* = false */, 
2262                                 bool         bStencil     /* = false */, 
2263                                 bool         bMipmap      /* = false */, 
2264                                 bool         bAnisoFilter /* = false */,
2265                                 unsigned int iRBits       /* = 8 */, 
2266                                 unsigned int iGBits       /* = 8 */, 
2267                                 unsigned int iBBits       /* = 8 */, 
2268                                 unsigned int iABits       /* = 8 */,
2269                                 UpdateMode   updateMode   /* = RT_RENDER_TO_TEXTURE */)
2270 {   
2271     if (0 == _iWidth || 0 == _iHeight)
2272         return false;
2273
2274 #if defined DEBUG || defined _DEBUG
2275     SG_LOG(SG_GL, SG_ALERT, 
2276             "RenderTexture Warning: Deprecated Initialize() interface used.");
2277 #endif   
2278
2279     // create a mode string.
2280     string mode = "";
2281     if (bDepth)
2282         mode.append("depth ");
2283     if (bStencil)
2284         mode.append("stencil ");
2285     if (bMipmap)
2286         mode.append("mipmap ");
2287     if (iRBits + iGBits + iBBits + iABits > 0)
2288     {
2289         if (iRBits > 0)
2290             mode.append("r");
2291         if (iGBits > 0)
2292             mode.append("g");
2293         if (iBBits > 0)
2294             mode.append("b");
2295         if (iABits > 0)
2296             mode.append("a");
2297         mode.append("=");
2298         char bitVector[100];
2299         snprintf( bitVector, 100,
2300             "%d%s,%d%s,%d%s,%d%s",
2301             iRBits, (iRBits >= 16) ? "f" : "",
2302             iGBits, (iGBits >= 16) ? "f" : "",
2303             iBBits, (iBBits >= 16) ? "f" : "",
2304             iABits, (iABits >= 16) ? "f" : "");
2305         mode.append(bitVector);
2306         mode.append(" ");
2307     }
2308     if (_bIsTexture)
2309     {
2310         if (GL_NV_texture_rectangle && 
2311             ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2312               || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2313             mode.append("texRECT ");
2314         else
2315             mode.append("tex2D ");
2316     }
2317     if (_bIsDepthTexture)
2318     {
2319         if (GL_NV_texture_rectangle && 
2320             ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2321               || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2322             mode.append("texRECT ");
2323         else
2324             mode.append("tex2D ");
2325     }
2326     if (RT_COPY_TO_TEXTURE == updateMode)
2327         mode.append("ctt");
2328
2329     _pixelFormatAttribs.clear();
2330     _pbufferAttribs.clear();
2331
2332 #ifdef _WIN32
2333     _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
2334     _pixelFormatAttribs.push_back(true);
2335     _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
2336     _pixelFormatAttribs.push_back(true);
2337     
2338     _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
2339     _pbufferAttribs.push_back(true);
2340 #elif defined( __APPLE__ )
2341 #else
2342     _pixelFormatAttribs.push_back(GLX_RENDER_TYPE_SGIX);
2343     _pixelFormatAttribs.push_back(GLX_RGBA_BIT_SGIX);
2344     _pixelFormatAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
2345     _pixelFormatAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
2346 #endif
2347
2348     _ParseModeString(mode.c_str(), _pixelFormatAttribs, _pbufferAttribs);
2349
2350 #ifdef _WIN32
2351     _pixelFormatAttribs.push_back(0);
2352     _pbufferAttribs.push_back(0);
2353 #else
2354     _pixelFormatAttribs.push_back(None);
2355 #endif
2356
2357     Initialize(_iWidth, _iHeight, bShare);
2358     
2359     return true;
2360 }
2361
2362
2363 //---------------------------------------------------------------------------
2364 // Function             : RenderTexture::Reset
2365 // Description      : 
2366 //---------------------------------------------------------------------------
2367 /**
2368 * @fn RenderTexture::Reset(int iWidth, int iHeight, unsigned int iMode, bool bIsTexture, bool bIsDepthTexture)
2369 * @brief Resets the resolution of the offscreen buffer.
2370
2371 * Causes the buffer to delete itself.  User must call Initialize() again
2372 * before use.
2373 */ 
2374 bool RenderTexture::Reset(int iWidth, int iHeight)
2375 {
2376     SG_LOG(SG_GL, SG_ALERT, 
2377             "RenderTexture Warning: Deprecated Reset() interface used.");
2378
2379     if (!_Invalidate())
2380     {
2381         SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Reset(): failed to invalidate.");
2382         return false;
2383     }
2384     _iWidth     = iWidth;
2385     _iHeight    = iHeight;
2386     
2387     return true;
2388 }