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