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