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