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