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