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