]> git.mxchange.org Git - simgear.git/blob - simgear/screen/RenderTexture.cpp
warning fixes
[simgear.git] / simgear / screen / RenderTexture.cpp
1 // File : RenderTexture.cpp
2 //---------------------------------------------------------------------------
3 // Copyright (c) 2002-2004 Mark J. Harris
4 //---------------------------------------------------------------------------
5 // This software is provided 'as-is', without any express or implied
6 // warranty. In no event will the authors be held liable for any
7 // damages arising from the use of this software.
8 //
9 // Permission is granted to anyone to use this software for any
10 // purpose, including commercial applications, and to alter it and
11 // redistribute it freely, subject to the following restrictions:
12 //
13 // 1. The origin of this software must not be misrepresented; you
14 //    must not claim that you wrote the original software. If you use
15 //    this software in a product, an acknowledgment in the product
16 //    documentation would be appreciated but is not required.
17 //
18 // 2. Altered source versions must be plainly marked as such, and
19 //    must not be misrepresented as being the original software.
20 //
21 // 3. This notice may not be removed or altered from any source
22 //    distribution.
23 //
24 // --------------------------------------------------------------------------
25 // Credits:
26 // Original RenderTexture class: Mark J. Harris
27 // Original Render to Depth Texture support: Thorsten Scheuermann
28 // Linux Copy-to-texture: Eric Werness
29 // OS X: Alexander Powell (someone please help)
30 // Various Bug Fixes: Daniel (Redge) Sperl 
31 //                    Bill Baxter
32 // Ubuntu 8.04 64bit: Geoff McLane - 2009-07-01
33 // to work even when version 1.2 is returned.
34 //
35 // --------------------------------------------------------------------------
36 /**
37 * @file RenderTexture.cpp
38
39 * Implementation of class RenderTexture.  A multi-format render to 
40 * texture wrapper.
41 */
42 #pragma warning(disable:4786)
43
44 /*
45  * Changelog:
46  *
47  * Jan. 2005, Removed GLEW dependencies, Erik Hofman, Fred Bouvier
48  * Nov. 2005, Use the simgear logging facility, Erik Hofman
49  * Mar. 2006, Add MAC OS X support, Alexander Powell
50  */
51
52 #ifdef HAVE_CONFIG_H
53 #  include <simgear_config.h>
54 #endif
55
56 #include <simgear/compiler.h>
57 #include <simgear/debug/logstream.hxx>
58 #include <simgear/screen/extensions.hxx>
59 #include <simgear/screen/RenderTexture.h>
60
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <assert.h>
64 #include <stdarg.h>
65
66 #include <cstring>
67
68 #ifdef _WIN32
69 #pragma comment(lib, "gdi32.lib") // required for GetPixelFormat()
70 #endif
71
72 using namespace std;
73
74 // DEBUG - add a lot of noise
75 //#ifndef _DEBUG
76 //#define _DEBUG
77 //#endif
78
79 #ifdef _DEBUG
80 #define dbg_printf printf
81 const char * get_attr_name( int val, int * pdef );
82 #else
83 #define dbg_printf
84 #endif
85
86 // CHOP/NOT CHOP SOME CODE TO GET SOMETHING WORKING!
87 #define ADD_QUERY_BUFFER    
88 #define ADD_GET_DRAWABLE
89 // =======================================
90
91
92 #ifdef _WIN32
93 static bool fctPtrInited = false;
94 /* WGL_ARB_pixel_format */
95 static wglChoosePixelFormatARBProc wglChoosePixelFormatARBPtr = 0;
96 static wglGetPixelFormatAttribivARBProc wglGetPixelFormatAttribivARBPtr = 0;
97 /* WGL_ARB_pbuffer */
98 static wglCreatePbufferARBProc wglCreatePbufferARBPtr = 0;
99 static wglGetPbufferDCARBProc wglGetPbufferDCARBPtr = 0;
100 static wglQueryPbufferARBProc wglQueryPbufferARBPtr = 0;
101 static wglReleasePbufferDCARBProc wglReleasePbufferDCARBPtr = 0;
102 static wglDestroyPbufferARBProc wglDestroyPbufferARBPtr = 0;
103 /* WGL_ARB_render_texture */
104 static wglBindTexImageARBProc wglBindTexImageARBPtr = 0;
105 static wglReleaseTexImageARBProc wglReleaseTexImageARBPtr = 0;
106
107 #elif defined( __MACH__ )
108 #else /* !_WIN32 */
109 static bool glXVersion1_3Present = false;
110 static glXChooseFBConfigProc glXChooseFBConfigPtr = 0;
111 static glXCreatePbufferProc glXCreatePbufferPtr = 0;
112 static glXCreateGLXPbufferProc glXCreateGLXPbufferPtr = 0;
113 static glXGetVisualFromFBConfigProc glXGetVisualFromFBConfigPtr = 0;
114 static glXCreateContextProc glXCreateContextPtr = 0;
115 static glXCreateContextWithConfigProc glXCreateContextWithConfigPtr = 0;
116 static glXDestroyPbufferProc glXDestroyPbufferPtr = 0;
117 static glXQueryDrawableProc glXQueryDrawablePtr = 0;
118 static glXQueryGLXPbufferSGIXProc glXQueryGLXPbufferSGIXPtr = 0;
119 #endif
120
121 //---------------------------------------------------------------------------
122 // Function      : RenderTexture::RenderTexture
123 // Description   : 
124 //---------------------------------------------------------------------------
125 /**
126 * @fn RenderTexture::RenderTexture()
127 * @brief Mode-string-based Constructor.
128 */ 
129 RenderTexture::RenderTexture(const char *strMode)
130 :   _iWidth(0), 
131     _iHeight(0), 
132     _bIsTexture(false),
133     _bIsDepthTexture(false),
134     _bHasARBDepthTexture(true),            // [Redge]
135 #if defined(_WIN32) || defined(__MACH__)
136     _eUpdateMode(RT_RENDER_TO_TEXTURE),
137 #else
138     _eUpdateMode(RT_COPY_TO_TEXTURE),
139 #endif
140     _bInitialized(false),
141     _iNumAuxBuffers(0),
142     _bIsBufferBound(false),
143     _iCurrentBoundBuffer(0),
144     _iNumDepthBits(0),
145     _iNumStencilBits(0),
146     _bFloat(false),
147     _bDoubleBuffered(false),
148     _bPowerOf2(true),
149     _bRectangle(false),
150     _bMipmap(false),
151     _bShareObjects(false),
152     _bCopyContext(false),
153 #ifdef _WIN32
154     _hDC(NULL), 
155     _hGLContext(NULL), 
156     _hPBuffer(NULL),
157     _hPreviousDC(0),
158     _hPreviousContext(0),
159 #elif defined( __MACH__ )
160     _hGLContext(NULL),
161     _hPBuffer(0),
162     _hPreviousContext(NULL),
163 #else
164     _pDisplay(NULL),
165     _hGLContext(NULL),
166     _hPBuffer(0),
167     _hPreviousDrawable(0),
168     _hPreviousContext(0),
169 #endif
170     _iTextureTarget(GL_NONE),
171     _iTextureID(0),
172     _iDepthTextureID(0),
173     _pPoorDepthTexture(0) // [Redge]
174 {
175     dbg_printf("RenderTexture::RenderTexture(%s) BGN instantiation.\n", strMode );
176     _iNumColorBits[0] = _iNumColorBits[1] = 
177         _iNumColorBits[2] = _iNumColorBits[3] = 0;
178
179 #ifdef _WIN32
180     dbg_printf("RenderTexture::RenderTexture in _WIN32.\n" );
181     _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
182     _pixelFormatAttribs.push_back(true);
183     _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
184     _pixelFormatAttribs.push_back(true);
185     
186     _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
187     _pbufferAttribs.push_back(true);
188 #elif defined( __MACH__ )
189     dbg_printf("RenderTexture::RenderTexture in __MACH__.\n" );
190     //_pixelFormatAttribs.push_back(kCGLPFANoRecovery);
191     _pixelFormatAttribs.push_back(kCGLPFAAccelerated);
192     _pixelFormatAttribs.push_back(kCGLPFAWindow);
193     _pixelFormatAttribs.push_back(kCGLPFAPBuffer);
194 #else
195     dbg_printf("RenderTexture::RenderTexture !_WIN32 and !__MACH__.\n" );
196     _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
197     _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
198     _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
199     _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
200 #endif
201
202     _ParseModeString(strMode, _pixelFormatAttribs, _pbufferAttribs);
203
204 #ifdef _WIN32
205     _pixelFormatAttribs.push_back(0);
206     _pbufferAttribs.push_back(0);
207 #elif defined(__MACH__)
208     _pixelFormatAttribs.push_back((CGLPixelFormatAttribute)0);
209     _pbufferAttribs.push_back((CGLPixelFormatAttribute)0);
210 #else
211     _pixelFormatAttribs.push_back(None);
212 #endif
213
214     dbg_printf("RenderTexture::RenderTexture(%s) END instantiation. pf=%d pb=%d\n",
215       strMode, _pixelFormatAttribs.size(), _pbufferAttribs.size() );
216
217 }
218
219
220 //---------------------------------------------------------------------------
221 // Function             : RenderTexture::~RenderTexture
222 // Description      : 
223 //---------------------------------------------------------------------------
224 /**
225 * @fn RenderTexture::~RenderTexture()
226 * @brief Destructor.
227 */ 
228 RenderTexture::~RenderTexture()
229 {
230     dbg_printf("RenderTexture::~RenderTexture: destructor.\n" );
231     _Invalidate();
232 }
233
234  //---------------------------------------------------------------------------
235 // Function            : _cglcheckError
236 // Description     :
237 //---------------------------------------------------------------------------
238 /**
239 * @fn _cglCheckError()
240 * @brief Prints to stderr a description when an OS X error is found.
241 */
242 #ifdef __MACH__
243 static void _cglCheckErrorHelper(CGLError err, char *sourceFile, int sourceLine)
244 {
245 # ifdef _DEBUG
246     if (err)
247     {
248        fprintf(stderr, "RenderTexture CGL Error:  %s at (%s,%d)",
249                         CGLErrorString(err), sourceFile, sourceLine);
250     }
251 # endif
252 }
253
254 # define _cglCheckError(err) _cglCheckErrorHelper(err,__FILE__,__LINE__)
255
256 #endif
257
258
259 //---------------------------------------------------------------------------
260 // Function             : _wglGetLastError
261 // Description      : 
262 //---------------------------------------------------------------------------
263 /**
264 * @fn wglGetLastError()
265 * @brief Returns the last windows error generated.
266 */ 
267 #ifdef _WIN32
268 void _wglGetLastError()
269 {
270 #ifdef _DEBUG
271     
272     DWORD err = GetLastError();
273     switch(err)
274     {
275     case ERROR_INVALID_PIXEL_FORMAT:
276         SG_LOG(SG_GL, SG_ALERT, 
277                 "RenderTexture Win32 Error:  ERROR_INVALID_PIXEL_FORMAT");
278         break;
279     case ERROR_NO_SYSTEM_RESOURCES:
280         SG_LOG(SG_GL, SG_ALERT, 
281                 "RenderTexture Win32 Error:  ERROR_NO_SYSTEM_RESOURCES");
282         break;
283     case ERROR_INVALID_DATA:
284         SG_LOG(SG_GL, SG_ALERT, 
285                 "RenderTexture Win32 Error:  ERROR_INVALID_DATA");
286         break;
287     case ERROR_INVALID_WINDOW_HANDLE:
288         SG_LOG(SG_GL, SG_ALERT, 
289                 "RenderTexture Win32 Error:  ERROR_INVALID_WINDOW_HANDLE");
290         break;
291     case ERROR_RESOURCE_TYPE_NOT_FOUND:
292         SG_LOG(SG_GL, SG_ALERT, 
293                 "RenderTexture Win32 Error:  ERROR_RESOURCE_TYPE_NOT_FOUND");
294         break;
295     case ERROR_SUCCESS:
296         // no error
297         break;
298     default:
299         LPVOID lpMsgBuf;
300         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
301             FORMAT_MESSAGE_FROM_SYSTEM | 
302             FORMAT_MESSAGE_IGNORE_INSERTS,
303             NULL,
304             err,
305             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
306             (LPTSTR) &lpMsgBuf,
307             0,
308             NULL);
309         
310         SG_LOG(SG_GL, SG_ALERT, "RenderTexture Win32 Error " <<  err << ":" << lpMsgBuf);
311         LocalFree( lpMsgBuf );
312         break;
313     }
314     SetLastError(0);
315     
316 #endif // _DEBUG
317 }
318 #endif
319
320 //---------------------------------------------------------------------------
321 // Function             : PrintExtensionError
322 // Description      : 
323 //---------------------------------------------------------------------------
324 /**
325 * @fn PrintExtensionError( char* strMsg, ... )
326 * @brief Prints an error about missing OpenGL extensions.
327 */ 
328 void PrintExtensionError( const char* strMsg, ... )
329 {
330     SG_LOG(SG_GL, SG_ALERT, 
331             "Error: RenderTexture requires the following unsupported "
332             "OpenGL extensions: ");
333     char strBuffer[512];
334     va_list args;
335     va_start(args, strMsg);
336 #if defined _WIN32 && !defined __CYGWIN__
337     _vsnprintf( strBuffer, 512, strMsg, args );
338 #else
339     vsnprintf( strBuffer, 512, strMsg, args );
340 #endif
341     va_end(args);
342     
343     SG_LOG(SG_GL, SG_ALERT, strMsg);
344     dbg_printf("Error: RenderTexture requires the following unsupported OpenGL extensions: \n[%s]\n", strMsg);
345 }
346
347 //---------------------------------------------------------------------------
348 // Function             : RenderTexture::Initialize
349 // Description      : 
350 //---------------------------------------------------------------------------
351 /**
352 * @fn RenderTexture::Initialize(int width, int height, bool shareObjects, bool copyContext);
353 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
354
355 * This function creates of the p-buffer.  It can only be called once a GL 
356 * context has already been created.  
357 */ 
358 bool RenderTexture::Initialize(int width, int height,
359                                 bool shareObjects       /* = true */,
360                                 bool copyContext        /* = false */)
361 {
362     assert(width > 0 && height > 0);
363
364     dbg_printf("RenderTexture::Initialize w=%d h=%d\n", width, height );
365     
366     _iWidth = width; _iHeight = height;
367     _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
368
369     _bShareObjects = shareObjects;
370     _bCopyContext  = copyContext;
371
372     // Check if this is an NVXX GPU and verify necessary extensions.
373     if (!_VerifyExtensions()) {
374        dbg_printf("RenderTexture::Initialize: _VerifyExtensions() FAILED - returning false.\n" );
375        return false;
376     }
377     
378     if (_bInitialized)
379         _Invalidate();
380
381 #ifdef _WIN32
382     // Get the current context.
383     HDC hdc = wglGetCurrentDC();
384     if (NULL == hdc)
385         _wglGetLastError();
386     HGLRC hglrc = wglGetCurrentContext();
387     if (NULL == hglrc)
388         _wglGetLastError();
389     
390     int iFormat = 0;
391     unsigned int iNumFormats;
392     
393     if (_bCopyContext)
394     {
395         // Get the pixel format for the on-screen window.
396         iFormat = GetPixelFormat(hdc);
397         if (iFormat == 0)
398         {
399             SG_LOG(SG_GL, SG_ALERT, 
400                     "RenderTexture Error: GetPixelFormat() failed.");
401             return false;
402         }
403     }
404     else 
405     {
406         if (!wglChoosePixelFormatARBPtr(hdc, &_pixelFormatAttribs[0], NULL, 
407                                      1, &iFormat, &iNumFormats))
408         {
409             SG_LOG(SG_GL, SG_ALERT, 
410                 "RenderTexture Error: wglChoosePixelFormatARB() failed.");
411             _wglGetLastError();
412             return false;
413         }
414         if ( iNumFormats <= 0 )
415         {
416             SG_LOG(SG_GL, SG_ALERT, 
417                     "RenderTexture Error: Couldn't find a suitable "
418                     "pixel format.");
419             _wglGetLastError();
420             return false;
421         }
422     }
423     
424     // Create the p-buffer.    
425     _hPBuffer = wglCreatePbufferARBPtr(hdc, iFormat, _iWidth, _iHeight, 
426                                     &_pbufferAttribs[0]);
427     if (!_hPBuffer)
428     {
429         SG_LOG(SG_GL, SG_ALERT, 
430                 "RenderTexture Error: wglCreatePbufferARB() failed.");
431         _wglGetLastError();
432         return false;
433     }
434     
435     // Get the device context.
436     _hDC = wglGetPbufferDCARBPtr( _hPBuffer);
437     if ( !_hDC )
438     {
439         SG_LOG(SG_GL, SG_ALERT, 
440                 "RenderTexture Error: wglGetGetPbufferDCARB() failed.");
441         _wglGetLastError();
442         return false;
443     }
444     
445     // Create a gl context for the p-buffer.
446     if (_bCopyContext)
447     {
448         // Let's use the same gl context..
449         // Since the device contexts are compatible (i.e. same pixelformat),
450         // we should be able to use the same gl rendering context.
451         _hGLContext = hglrc;
452     }
453     else
454     {
455         _hGLContext = wglCreateContext( _hDC );
456         if ( !_hGLContext )
457         {
458             SG_LOG(SG_GL, SG_ALERT, 
459                     "RenderTexture Error: wglCreateContext() failed.");
460             _wglGetLastError();
461             return false;
462         }
463     }
464     
465     // Share lists, texture objects, and program objects.
466     if( _bShareObjects )
467     {
468         if( !wglShareLists(hglrc, _hGLContext) )
469         {
470             SG_LOG(SG_GL, SG_ALERT, 
471                     "RenderTexture Error: wglShareLists() failed.");
472             _wglGetLastError();
473             return false;
474         }
475     }
476     
477     // Determine the actual width and height we were able to create.
478     wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
479     wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
480     
481     _bInitialized = true;
482     
483     // get the actual number of bits allocated:
484     int attrib = WGL_RED_BITS_ARB;
485     //int bits[6];
486     int value;
487     _iNumColorBits[0] = 
488         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
489         ? value : 0;
490     attrib = WGL_GREEN_BITS_ARB;
491     _iNumColorBits[1] = 
492         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
493         ? value : 0;
494     attrib = WGL_BLUE_BITS_ARB;
495     _iNumColorBits[2] = 
496         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
497         ? value : 0;
498     attrib = WGL_ALPHA_BITS_ARB;
499     _iNumColorBits[3] = 
500         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
501         ? value : 0; 
502     attrib = WGL_DEPTH_BITS_ARB;
503     _iNumDepthBits = 
504         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
505         ? value : 0; 
506     attrib = WGL_STENCIL_BITS_ARB;
507     _iNumStencilBits = 
508         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
509         ? value : 0; 
510     attrib = WGL_DOUBLE_BUFFER_ARB;
511     _bDoubleBuffered = 
512         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
513         ? (value?true:false) : false; 
514     
515 #if defined(_DEBUG) | defined(DEBUG)
516     SG_LOG(SG_GL, SG_ALERT, "Created a " << _iWidth << "x" << _iHeight <<
517         " RenderTexture with BPP(" <<
518         _iNumColorBits[0] << "," << _iNumColorBits[1] << "," <<
519         _iNumColorBits[2] << "," << _iNumColorBits[3] << ")");
520     if (_iNumDepthBits) SG_LOG(SG_GL, SG_ALERT, " depth=" << _iNumDepthBits);
521     if (_iNumStencilBits) SG_LOG(SG_GL, SG_ALERT, " stencil=" << _iNumStencilBits);
522     if (_bDoubleBuffered) SG_LOG(SG_GL, SG_ALERT, " double buffered");
523 #endif
524
525 #elif defined( __MACH__ )
526     // Get the current context.
527     CGLContextObj hglrc = CGLGetCurrentContext();
528     if (NULL == hglrc)
529         fprintf(stderr, "Couldn't get current context!");
530    
531         CGLPixelFormatObj pixFormat = NULL;
532         GLint iNumFormats;
533         CGLError error;
534
535         // Copy the _pixelFormatAttribs into another array to fix
536         // typecast issues
537         CGLPixelFormatAttribute *pixFormatAttribs =
538             (CGLPixelFormatAttribute *)malloc(sizeof(CGLPixelFormatAttribute)
539                                               * _pixelFormatAttribs.size());
540
541         for (unsigned int ii = 0; ii < _pixelFormatAttribs.size(); ii++)
542         {
543             pixFormatAttribs[ii] =
544                                (CGLPixelFormatAttribute)_pixelFormatAttribs[ii];
545         }
546
547         if (error =
548            CGLChoosePixelFormat(&pixFormatAttribs[0], &pixFormat, &iNumFormats))
549         {
550             fprintf(stderr,
551                     "RenderTexture Error: CGLChoosePixelFormat() failed.\n");
552             _cglCheckError(error);
553             return false;
554         }
555         if ( iNumFormats <= 0 )
556         {
557             SG_LOG(SG_GL, SG_ALERT,
558                     "RenderTexture Error: Couldn't find a suitable "
559                     "pixel format.");
560             return false;
561         }
562
563         // Free the copy of the _pixelFormatAttribs array
564         free(pixFormatAttribs);
565    
566        // Create the context.
567        error = CGLCreateContext(pixFormat, (_bShareObjects)
568                 ? CGLGetCurrentContext() : NULL, &_hGLContext);
569        if (error)
570        {
571            fprintf(stderr,
572                    "RenderTexture Error: CGLCreateContext() failed.\n");
573            _cglCheckError(error);
574            return false;
575        }
576        CGLDestroyPixelFormat(pixFormat);
577    
578        // Create the p-buffer.
579        error = CGLCreatePBuffer(_iWidth, _iHeight, (_bRectangle)
580             ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D, GL_RGBA, 0, &_hPBuffer);
581        if (error)
582        {
583            fprintf(stderr,
584                    "RenderTexture Error: CGLCreatePBuffer() failed.\n");
585            _cglCheckError(error);
586            return false;
587        }
588
589        GLint screen;
590        if (error = CGLGetVirtualScreen(CGLGetCurrentContext(), &screen))
591        {
592            _cglCheckError(error);
593            return false;
594        }
595        if (error = CGLSetPBuffer(_hGLContext, _hPBuffer, 0, 0, screen))
596        {
597            _cglCheckError(error);
598            return false;
599        }
600    
601        // Determine the actual width and height we were able to create.
602        //wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
603        //wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
604    
605        _bInitialized = true;
606    
607        /*
608        // get the actual number of bits allocated:
609        int attrib = WGL_RED_BITS_ARB;
610        //int bits[6];
611        int value;
612        _iNumColorBits[0] =
613             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
614             ? value : 0;
615        attrib = WGL_GREEN_BITS_ARB;
616        _iNumColorBits[1] =
617             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
618             ? value : 0;
619        attrib = WGL_BLUE_BITS_ARB;
620        _iNumColorBits[2] =
621             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
622             ? value : 0;
623        attrib = WGL_ALPHA_BITS_ARB;
624        _iNumColorBits[3] =
625             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
626             ? value : 0;
627        attrib = WGL_DEPTH_BITS_ARB;
628        _iNumDepthBits =
629             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
630             ? value : 0;
631        attrib = WGL_STENCIL_BITS_ARB;
632        _iNumStencilBits =
633             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
634             ? value : 0;
635        attrib = WGL_DOUBLE_BUFFER_ARB;
636        _bDoubleBuffered =
637             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
638              ? (value?true:false) : false;
639        */
640
641 #if defined(_DEBUG) | defined(DEBUG)
642        fprintf(stderr, "Created a %dx%d RenderTexture with BPP(%d, %d, %d, %d)",
643            _iWidth, _iHeight,
644            _iNumColorBits[0], _iNumColorBits[1],
645            _iNumColorBits[2], _iNumColorBits[3]);
646        if (_iNumDepthBits) fprintf(stderr, " depth=%d", _iNumDepthBits);
647        if (_iNumStencilBits) fprintf(stderr, " stencil=%d", _iNumStencilBits);
648        if (_bDoubleBuffered) fprintf(stderr, " double buffered");
649        fprintf(stderr, "\n");
650 #endif
651
652 #else // !_WIN32, !__MACH_
653
654     _pDisplay = glXGetCurrentDisplay();
655     if ( !_pDisplay ) {
656         dbg_printf("RenderTexture::Initialize: ERROR: glXGetCurrentDisplay() returned NULL! return false\n");
657         return false;
658     }
659     dbg_printf("RenderTexture::Initialize: got glXGetCurrentDisplay() _pDisplay=[%p]\n", _pDisplay);
660     // glXGetCurrentContext returns the current context, as specified by glXMakeCurrent.
661     // If there is no current context, NULL is returned.
662     GLXContext context = glXGetCurrentContext();
663     if ( !context ) {
664         dbg_printf("RenderTexture::Initialize: ERROR: glXGetCurrentContext() returned NULL! return false\n");
665         return false;
666     }
667     dbg_printf("RenderTexture::Initialize: got glXGetCurrentContext() context=[%p]\n", context);
668     int screen = DefaultScreen(_pDisplay);
669     dbg_printf("RenderTexture::Initialize: DefaultScreen(_pDisplay) screen=%d\n", screen);
670     
671     XVisualInfo *visInfo = NULL;
672     
673     GLXFBConfig *fbConfigs;
674     int nConfigs;
675 #ifdef _DEBUG
676     dbg_printf("Using %d pixelFormatAttribs array\n", _pixelFormatAttribs.size());
677     size_t max = _pixelFormatAttribs.size() / 2;
678     int dat = 0;
679     size_t n;
680     for (n = 0; n < max; n++) {
681       const char * cp = get_attr_name(_pixelFormatAttribs[n*2], &dat);
682       printf( "%s(%d) = %d (def=%d)\n",
683        cp, _pixelFormatAttribs[n*2], _pixelFormatAttribs[(n*2)+1], dat );
684     }
685     n *= 2;
686     if ( n < _pixelFormatAttribs.size() )
687       printf( "Array ends with %d\n", _pixelFormatAttribs[n] );
688     else
689       printf( "WARNING: Array does not appear ODD! which is ODD\n" );
690       
691 #endif
692     fbConfigs = glXChooseFBConfigPtr(_pDisplay, screen, 
693                                       &_pixelFormatAttribs[0], &nConfigs);
694     // NOTE: ref: http://www.opengl.org/sdk/docs/man/xhtml/glXChooseFBConfig.xml says
695     // Next, call glXGetFBConfigAttrib to retrieve additional attributes for the frame buffer configurations and then select between them.
696     
697     if (nConfigs <= 0 || !fbConfigs) 
698     {
699         SG_LOG(SG_GL, SG_ALERT,
700             "RenderTexture Error: Couldn't find a suitable pixel format.");
701         dbg_printf("RenderTexture Error: Couldn't find a suitable pixel format. return false\n");
702         return false;
703     }
704     
705     dbg_printf("RenderTexture::Initialize: glXChooseFBConfigPtr() nConfigs = %d, fbConfigs=[%p]\n", nConfigs, fbConfigs);
706     
707     int pbufAttrib[] = {
708       GLX_PBUFFER_WIDTH,   _iWidth,
709       GLX_PBUFFER_HEIGHT,  _iHeight,
710       GLX_LARGEST_PBUFFER, False,
711       None
712     };
713     // Pick the first returned format that will return a pbuffer
714     // if (glXVersion1_3Present)
715     if (glXCreatePbufferPtr && glXGetVisualFromFBConfigPtr && glXCreateContextPtr) 
716     {
717         dbg_printf("RenderTexture::Initialize: glXVersion1_3Present = TRUE\n");
718         for (int i=0;i<nConfigs;i++)
719         {
720             _hPBuffer = glXCreatePbufferPtr(_pDisplay, fbConfigs[i], pbufAttrib);
721             if (_hPBuffer)
722             {
723                 XVisualInfo *visInfo = glXGetVisualFromFBConfigPtr(_pDisplay, fbConfigs[i]);
724
725                 _hGLContext = glXCreateContextPtr(_pDisplay, visInfo,
726                                                _bShareObjects ? context : NULL,
727                                                True);
728                 if (!_hGLContext)
729                 {
730                     dbg_printf("RenderTexture Error: glXCreateContextPtr(_pDisplay, visInfo,..) FAILED! return false\n");
731                     return false;
732                 }
733                 XFree( visInfo );
734                 break;
735             }
736         }
737     }
738     else
739     {
740 #ifdef WIN32
741         int iFormat = 0;
742         int iNumFormats;
743         int attrib = 0;
744 #endif
745         dbg_printf("RenderTexture::Initialize: glXVersion1_3Present = FALSE w=%d h=%d\n", _iWidth, _iHeight);
746         for (int i=0; i < nConfigs; i++)
747         {
748              dbg_printf("RenderTexture::Initialize: %d: glXCreateGLXPbufferPtr() get buffer ptr\n", (i + 1));
749             _hPBuffer = glXCreateGLXPbufferPtr(_pDisplay, fbConfigs[i], 
750                                                _iWidth, _iHeight,
751                                                &pbufAttrib[0] ); //NULL);
752             if (_hPBuffer) 
753             {
754                 dbg_printf("RenderTexture::Initialize: %d: glXCreateGLXPbufferPtr() got buffer [%p]\n", (i + 1), _hPBuffer);
755                 _hGLContext = glXCreateContextWithConfigPtr(_pDisplay, 
756                                                              fbConfigs[i], 
757                                                              GLX_RGBA_TYPE, 
758                                                              _bShareObjects ? context : NULL, 
759                                                              True);
760                 dbg_printf("RenderTexture::Initialize: %d: glXCreateContextWithConfigPtr() _hGLContext=[%p]\n", (i + 1), _hGLContext);
761                 break;
762             } else {
763                 dbg_printf("RenderTexture::Initialize: %d: glXCreateGLXPbufferPtr() NO buffer\n", (i + 1));
764             }
765         }
766     }
767     
768     dbg_printf("RenderTexture::Initialize: doing XFree( fbConfigs=[%p].\n", fbConfigs);
769     XFree( fbConfigs );
770     
771     if (!_hPBuffer)
772     {
773         SG_LOG(SG_GL, SG_ALERT, 
774                 "RenderTexture Error: glXCreateGLXPbufferPtr() failed.");
775         dbg_printf("RenderTexture Error: glXCreateGLXPbufferPtr() failed.\n");
776         return false;
777     }
778     
779     if(!_hGLContext)
780     {
781         // Try indirect
782         _hGLContext = glXCreateContext(_pDisplay, visInfo, 
783                                        _bShareObjects ? context : NULL, False);
784         if ( !_hGLContext )
785         {
786             SG_LOG(SG_GL, SG_ALERT, 
787                     "RenderTexture Error: glXCreateContext() failed.");
788             dbg_printf("RenderTexture Error: glXCreateContext() failed. return false\n");
789             return false;
790         }
791     }
792     
793     // if (!glXVersion1_3Present)
794     if ((!glXCreatePbufferPtr || !glXGetVisualFromFBConfigPtr || !glXCreateContextPtr) &&
795         (!glXVersion1_3Present))
796     {
797 #ifdef ADD_QUERY_BUFFER    
798         dbg_printf("RenderTexture::Initialize: Doing glXQueryGLXPbufferSGIXPtr with GLX_WIDTH_SGIX\n");
799         glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_WIDTH_SGIX, 
800                                   (GLuint*)&_iWidth);
801         dbg_printf("RenderTexture::Initialize: Doing glXQueryGLXPbufferSGIXPtr with GLX_HEIGHT_SGIX\n");
802         glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_HEIGHT_SGIX, 
803                                   (GLuint*)&_iHeight);
804 #else
805         dbg_printf("RenderTexture::Initialize: SKIPPED doing glXQueryGLXPbufferSGIXPtr with GLX_WIDTH_SGIX and GLX_HEIGHT_SGIX\n");
806 #endif // #ifdef ADD_QUERY_BUFFER    
807     }
808     
809     _bInitialized = true;
810     dbg_printf( "RenderTexture::Initialize: _bIniialized set TRUE\n" );
811     // XXX Query the color format
812     
813 #endif
814
815     
816     // Now that the pbuffer is created, allocate any texture objects needed,
817     // and initialize them (for CTT updates only).  These must be allocated
818     // in the context of the pbuffer, though, or the RT won't work without
819     // wglShareLists.
820 #ifdef _WIN32
821     if (false == wglMakeCurrent( _hDC, _hGLContext))
822     {
823         _wglGetLastError();
824         return false;
825     }
826 #elif defined( __MACH__ )
827     CGLError err;
828     if (err = CGLSetCurrentContext(_hGLContext))
829     {
830         _cglCheckError(err);
831         return false;
832     }
833 #else
834
835 #ifdef ADD_GET_DRAWABLE
836      dbg_printf( "RenderTexture::Initialize: doing glXGetCurrentContext()\n" );
837     _hPreviousContext = glXGetCurrentContext();
838      dbg_printf( "RenderTexture::Initialize: doing glXGetCurrentDrawable()\n" );
839     _hPreviousDrawable = glXGetCurrentDrawable();
840 #else
841     _hPreviousContext = context;
842     _hPreviousDrawable = 0;
843      dbg_printf( "RenderTexture::Initialize: SKIPPED doing glXGetCurrentContext(2nd) AND glXGetCurrentDrawable()\n" );
844 #endif // #ifdef ADD_GET_DRAWABLE
845     
846     dbg_printf( "RenderTexture::Initialize: doing glXMakeCurrent(_pDisplay(%p), _hPBuffer(%p), _hGLContext(%p))\n",
847        _pDisplay, _hPBuffer, _hGLContext );
848     if (False == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext)) 
849     {
850         dbg_printf( "glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext) FAILED. return false\n" );
851         return false;
852     }
853     
854 #endif
855     
856     bool result = _InitializeTextures();   
857 #ifdef _WIN32
858     BindBuffer(WGL_FRONT_LEFT_ARB);
859     _BindDepthBuffer();
860 #endif
861
862     
863 #ifdef _WIN32 
864     // make the previous rendering context current 
865     if (false == wglMakeCurrent( hdc, hglrc))
866     {
867         _wglGetLastError();
868         return false;
869     }
870 #elif defined( __MACH__ )
871     if (err = CGLSetCurrentContext(_hPreviousContext))
872     {
873         _cglCheckError(err);
874         return false;
875     }
876 #else
877     if (False == glXMakeCurrent(_pDisplay, 
878                                 _hPreviousDrawable, _hPreviousContext))
879     {
880         dbg_printf("glXMakeCurrent(_pDisplay, _hPreviousDrawable, _hPreviousContext)) FAILED! return false\n" );
881         return false;
882     }
883     
884     if (glXVersion1_3Present)
885     //if ((glXVersion1_3Present) ||
886     //    (glXCreatePbufferPtr && glXGetVisualFromFBConfigPtr && glXCreateContextPtr && glXQueryDrawablePtr)) 
887     {
888         dbg_printf( "RenderTexture::Initialize: doing glXGetCurrentDrawable()\n" );
889         GLXDrawable draw = glXGetCurrentDrawable();
890         dbg_printf( "RenderTexture::Initialize: doing glXQueryDrawablePtr for GLX_WIDTH and GLX_HEIGHT\n" );
891         glXQueryDrawablePtr(_pDisplay, draw, GLX_WIDTH, (unsigned int*)&_iWidth);
892         glXQueryDrawablePtr(_pDisplay, draw, GLX_HEIGHT, (unsigned int*)&_iHeight);
893     }
894 #endif
895
896     dbg_printf( "RenderTexture::Initialize(w=%d,h=%d): returning %s\n", _iWidth, _iHeight, (result ? "TRUE" : "FALSE") );
897     return result;
898 }
899
900
901 //---------------------------------------------------------------------------
902 // Function             : RenderTexture::_Invalidate
903 // Description      : 
904 //---------------------------------------------------------------------------
905 /**
906 * @fn RenderTexture::_Invalidate()
907 * @brief Returns the pbuffer memory to the graphics device.
908
909 */ 
910 bool RenderTexture::_Invalidate()
911 {
912     dbg_printf( "RenderTexture::_Invalidate() called...\n" );
913     
914     _iNumColorBits[0] = _iNumColorBits[1] = 
915         _iNumColorBits[2] = _iNumColorBits[3] = 0;
916     _iNumDepthBits = 0;
917     _iNumStencilBits = 0;
918     
919     if (_bIsTexture)
920         glDeleteTextures(1, &_iTextureID);
921     if (_bIsDepthTexture) 
922     {
923         // [Redge]
924         if (!_bHasARBDepthTexture) delete[] _pPoorDepthTexture;
925         // [/Redge]
926         glDeleteTextures(1, &_iDepthTextureID);
927     }
928     
929 #ifdef _WIN32
930     if ( _hPBuffer )
931     {
932         // Check if we are currently rendering in the pbuffer
933         if (wglGetCurrentContext() == _hGLContext)
934             wglMakeCurrent(0,0);
935         if (!_bCopyContext) 
936             wglDeleteContext( _hGLContext);
937         wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
938         wglDestroyPbufferARBPtr( _hPBuffer );
939         _hPBuffer = 0;
940         return true;
941     }
942 #elif defined( __MACH__ )
943     if ( _hPBuffer )
944     {
945         if (CGLGetCurrentContext() == _hGLContext)
946             CGLSetCurrentContext(NULL);
947         if (!_bCopyContext)
948             CGLDestroyContext(_hGLContext);
949         CGLDestroyPBuffer(_hPBuffer);
950         _hPBuffer = NULL;
951         return true;
952     }
953 #else
954     if ( _hPBuffer )
955     {
956         if(glXGetCurrentContext() == _hGLContext)
957             // XXX I don't know if this is right at all
958             glXMakeCurrent(_pDisplay, _hPBuffer, 0);
959         glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
960         _hPBuffer = 0;
961        dbg_printf( "RenderTexture::_Invalidate: glXDestroyPbufferPtr(_pDisplay, _hPBuffer); return true\n" );
962         return true;
963     }
964 #endif
965
966     dbg_printf( "RenderTexture::_Invalidate: return false\n" );
967     // [WVB] do we need to call _ReleaseBoundBuffers() too?
968     return false;
969 }
970
971
972 //---------------------------------------------------------------------------
973 // Function             : RenderTexture::Reset
974 // Description      : 
975 //---------------------------------------------------------------------------
976 /**
977 * @fn RenderTexture::Reset()
978 * @brief Resets the resolution of the offscreen buffer.
979
980 * Causes the buffer to delete itself.  User must call Initialize() again
981 * before use.
982 */ 
983 bool RenderTexture::Reset(const char *strMode, ...)
984 {
985    dbg_printf("RenderTexure:Reset(): with %s\n", strMode);
986    
987     _iWidth = 0; _iHeight = 0; 
988     _bIsTexture = false; _bIsDepthTexture = false,
989     _bHasARBDepthTexture = true;
990 #if defined(_WIN32) || defined(__MACH__)
991     _eUpdateMode = RT_RENDER_TO_TEXTURE;
992 #else
993     _eUpdateMode = RT_COPY_TO_TEXTURE;
994 #endif
995     _bInitialized = false;
996     _iNumAuxBuffers = 0; 
997     _bIsBufferBound = false;
998     _iCurrentBoundBuffer = 0;
999     _iNumDepthBits = 0; _iNumStencilBits = 0;
1000     _bDoubleBuffered = false;
1001     _bFloat = false; _bPowerOf2 = true;
1002     _bRectangle = false; _bMipmap = false; 
1003     _bShareObjects = false; _bCopyContext = false; 
1004     _iTextureTarget = GL_NONE; _iTextureID = 0; 
1005     _iDepthTextureID = 0;
1006     _pPoorDepthTexture = 0;
1007     _pixelFormatAttribs.clear();
1008     _pbufferAttribs.clear();
1009     if (IsInitialized())
1010     {
1011       if (!_Invalidate())
1012       {
1013         dbg_printf( "RenderTexture::Reset(): failed to invalidate. return false\n");
1014         return false;
1015       }
1016       else
1017       {
1018         dbg_printf( "RenderTexture::Reset(): was Initialized, and now _Invalidate() ok.");
1019       }
1020     }
1021     else
1022     {
1023       dbg_printf("RenderTexure:Reset(): previous NOT initialised!\n");
1024     }
1025     
1026     _iNumColorBits[0] = _iNumColorBits[1] = 
1027         _iNumColorBits[2] = _iNumColorBits[3] = 0;
1028
1029 #ifdef _WIN32
1030     _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
1031     _pixelFormatAttribs.push_back(true);
1032     _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
1033     _pixelFormatAttribs.push_back(true);
1034     
1035     _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
1036     _pbufferAttribs.push_back(true);
1037 #elif defined( __MACH__ )
1038     //_pixelFormatAttribs.push_back(kCGLPFANoRecovery);
1039     _pixelFormatAttribs.push_back(kCGLPFAAccelerated);
1040     _pixelFormatAttribs.push_back(kCGLPFAWindow);
1041     _pixelFormatAttribs.push_back(kCGLPFAPBuffer);
1042 #else
1043     _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
1044     _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
1045     _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
1046     _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
1047 #endif
1048
1049     va_list args;
1050     char strBuffer[256];
1051     va_start(args,strMode);
1052 #if defined _WIN32 && !defined __CYGWIN__
1053     _vsnprintf( strBuffer, 256, strMode, args );
1054 #else
1055     vsnprintf( strBuffer, 256, strMode, args );
1056 #endif
1057     va_end(args);
1058
1059     _ParseModeString(strBuffer, _pixelFormatAttribs, _pbufferAttribs);
1060
1061 #ifdef _WIN32
1062     _pixelFormatAttribs.push_back(0);
1063     _pbufferAttribs.push_back(0);
1064 #elif defined(__MACH__)
1065     _pixelFormatAttribs.push_back((CGLPixelFormatAttribute)0);
1066 #else
1067     _pixelFormatAttribs.push_back(None);
1068 #endif
1069     dbg_printf("RenderTexure:Reset(): returning true.\n");
1070     return true;
1071 }
1072
1073 //------------------------------------------------------------------------------
1074 // Function               : RenderTexture::Resize
1075 // Description      : 
1076 //------------------------------------------------------------------------------
1077 /**
1078  * @fn RenderTexture::Resize(int iWidth, int iHeight)
1079  * @brief Changes the size of the offscreen buffer.
1080  * 
1081  * Like Reset() this causes the buffer to delete itself.  
1082  * But unlike Reset(), this call re-initializes the RenderTexture.
1083  * Note that Resize() will not work after calling Reset(), or before
1084  * calling Initialize() the first time.
1085  */ 
1086 bool RenderTexture::Resize(int iWidth, int iHeight)
1087 {
1088     if (!_bInitialized) {
1089         SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): must Initialize() first.");
1090         return false;
1091     }
1092     if (iWidth == _iWidth && iHeight == _iHeight) {
1093         return true;
1094     }
1095     
1096     // Do same basic work as _Invalidate, but don't reset all our flags
1097     if (_bIsTexture)
1098         glDeleteTextures(1, &_iTextureID);
1099     if (_bIsDepthTexture)
1100         glDeleteTextures(1, &_iDepthTextureID);
1101 #ifdef _WIN32
1102     if ( _hPBuffer )
1103     {
1104         // Check if we are currently rendering in the pbuffer
1105         if (wglGetCurrentContext() == _hGLContext)
1106             wglMakeCurrent(0,0);
1107         if (!_bCopyContext) 
1108             wglDeleteContext( _hGLContext);
1109         wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
1110         wglDestroyPbufferARBPtr( _hPBuffer );
1111         _hPBuffer = 0;
1112         return true;
1113     }
1114 #elif defined( __MACH__ )
1115     if ( _hPBuffer )
1116     {
1117         if (CGLGetCurrentContext() == _hGLContext)
1118             CGLSetCurrentContext(NULL);
1119         if (!_bCopyContext)
1120             CGLDestroyContext(_hGLContext);
1121         CGLDestroyPBuffer(_hPBuffer);
1122         _hPBuffer = NULL;
1123         return true;
1124     }
1125 #else
1126     if ( _hPBuffer )
1127     {
1128         if(glXGetCurrentContext() == _hGLContext)
1129             // XXX I don't know if this is right at all
1130             glXMakeCurrent(_pDisplay, _hPBuffer, 0);
1131         glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
1132         _hPBuffer = 0;
1133     }
1134 #endif
1135     else {
1136         SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): failed to resize.");
1137         return false;
1138     }
1139     _bInitialized = false;
1140     return Initialize(iWidth, iHeight, _bShareObjects, _bCopyContext);
1141 }
1142
1143 //---------------------------------------------------------------------------
1144 // Function             : RenderTexture::BeginCapture
1145 // Description      : 
1146 //---------------------------------------------------------------------------
1147 /**
1148 * @fn RenderTexture::BeginCapture()
1149 * @brief Activates rendering to the RenderTexture.
1150 */ 
1151 bool RenderTexture::BeginCapture()
1152 {
1153     if (!_bInitialized)
1154     {
1155         SG_LOG(SG_GL, SG_ALERT, 
1156                 "RenderTexture::BeginCapture(): Texture is not initialized!");
1157         return false;
1158     }
1159 #ifdef _WIN32
1160     // cache the current context so we can reset it when EndCapture() is called.
1161     _hPreviousDC      = wglGetCurrentDC();
1162     if (NULL == _hPreviousDC)
1163         _wglGetLastError();
1164     _hPreviousContext = wglGetCurrentContext();
1165     if (NULL == _hPreviousContext)
1166         _wglGetLastError();
1167 #elif defined( __MACH__ )
1168     _hPreviousContext = CGLGetCurrentContext();
1169 #else
1170     _hPreviousContext = glXGetCurrentContext();
1171     _hPreviousDrawable = glXGetCurrentDrawable();
1172 #endif
1173
1174     _ReleaseBoundBuffers();
1175
1176     return _MakeCurrent();
1177 }
1178
1179
1180 //---------------------------------------------------------------------------
1181 // Function             : RenderTexture::EndCapture
1182 // Description      : 
1183 //---------------------------------------------------------------------------
1184 /**
1185 * @fn RenderTexture::EndCapture()
1186 * @brief Ends rendering to the RenderTexture.
1187 */ 
1188 bool RenderTexture::EndCapture()
1189 {    
1190     if (!_bInitialized)
1191     {
1192         SG_LOG(SG_GL, SG_ALERT, 
1193                 "RenderTexture::EndCapture() : Texture is not initialized!");
1194         return false;
1195     }
1196
1197     glFlush();  // Added by a-lex
1198
1199     _MaybeCopyBuffer();
1200
1201 #ifdef _WIN32
1202     // make the previous rendering context current 
1203     if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
1204     {
1205         _wglGetLastError();
1206         return false;
1207     }
1208 #elif defined( __MACH__ )
1209     CGLError err;
1210     if (err = CGLSetCurrentContext(_hPreviousContext))
1211     {
1212             _cglCheckError(err);
1213             return false;
1214     }
1215 #else
1216     if (False == glXMakeCurrent(_pDisplay, _hPreviousDrawable, 
1217                                 _hPreviousContext))
1218     {
1219         return false;
1220     }
1221 #endif
1222
1223     // rebind the textures to a buffers for RTT
1224     BindBuffer(_iCurrentBoundBuffer);
1225     _BindDepthBuffer();
1226
1227     return true;
1228 }
1229
1230 //---------------------------------------------------------------------------
1231 // Function               : RenderTexture::BeginCapture(RenderTexture*)
1232 // Description      : 
1233 //---------------------------------------------------------------------------
1234 /**
1235  * @fn RenderTexture::BeginCapture(RenderTexture* other)
1236  * @brief Ends capture of 'other', begins capture on 'this'
1237  *
1238  * When performing a series of operations where you modify one texture after 
1239  * another, it is more efficient to use this method instead of the equivalent
1240  * 'EndCapture'/'BeginCapture' pair.  This method switches directly to the 
1241  * new context rather than changing to the default context, and then to the 
1242  * new context.
1243  *
1244  * RenderTexture doesn't have any mechanism for determining if 
1245  * 'current' really is currently active, so no error will be thrown 
1246  * if it is not. 
1247  */ 
1248 bool RenderTexture::BeginCapture(RenderTexture* current)
1249 {
1250     // bool bContextReset = false;
1251     
1252     if (current == this) {
1253         return true; // no switch necessary
1254     }
1255     if (!current) {
1256         // treat as normal Begin if current is 0.
1257         return BeginCapture();
1258     }
1259     if (!_bInitialized)
1260     {
1261         SG_LOG(SG_GL, SG_ALERT, 
1262             "RenderTexture::BeginCapture(RenderTexture*): Texture is not initialized!");
1263         return false;
1264     }
1265     if (!current->_bInitialized)
1266     {
1267         SG_LOG(SG_GL, SG_ALERT, 
1268             "RenderTexture::BeginCapture(RenderTexture): 'current' texture is not initialized!");
1269         return false;
1270     }
1271     
1272     // Sync current pbuffer with its CTT texture if necessary
1273     current->_MaybeCopyBuffer();
1274
1275     // pass along the previous context so we can reset it when 
1276     // EndCapture() is called.
1277 #ifdef _WIN32
1278     _hPreviousDC      = current->_hPreviousDC;
1279     if (NULL == _hPreviousDC)
1280         _wglGetLastError();
1281     _hPreviousContext = current->_hPreviousContext;
1282     if (NULL == _hPreviousContext)
1283         _wglGetLastError();
1284 #elif defined( __MACH__ )
1285     _hPreviousContext = current->_hPreviousContext;
1286 #else
1287     _hPreviousContext = current->_hPreviousContext;
1288     _hPreviousDrawable = current->_hPreviousDrawable;
1289 #endif    
1290
1291     // Unbind textures before making context current
1292     if (!_ReleaseBoundBuffers()) 
1293       return false;
1294
1295     // Make the pbuffer context current
1296     if (!_MakeCurrent())
1297         return false;
1298
1299     // Rebind buffers of initial RenderTexture
1300     current->BindBuffer(_iCurrentBoundBuffer);
1301     current->_BindDepthBuffer();
1302     
1303     return true;
1304 }
1305
1306
1307
1308 //---------------------------------------------------------------------------
1309 // Function             : RenderTexture::Bind
1310 // Description      : 
1311 //---------------------------------------------------------------------------
1312 /**
1313 * @fn RenderTexture::Bind()
1314 * @brief Binds RGB texture.
1315 */ 
1316 void RenderTexture::Bind() const 
1317
1318     if (_bInitialized && _bIsTexture) 
1319     {
1320         glBindTexture(_iTextureTarget, _iTextureID);
1321     }    
1322 }
1323
1324
1325 //---------------------------------------------------------------------------
1326 // Function             : RenderTexture::BindDepth
1327 // Description      : 
1328 //---------------------------------------------------------------------------
1329 /**
1330 * @fn RenderTexture::BindDepth()
1331 * @brief Binds depth texture.
1332 */ 
1333 void RenderTexture::BindDepth() const 
1334
1335     if (_bInitialized && _bIsDepthTexture) 
1336     {
1337         glBindTexture(_iTextureTarget, _iDepthTextureID); 
1338     }
1339 }
1340
1341
1342 //---------------------------------------------------------------------------
1343 // Function             : RenderTexture::BindBuffer
1344 // Description      : 
1345 //---------------------------------------------------------------------------
1346 /**
1347 * @fn RenderTexture::BindBuffer()
1348 * @brief Associate the RTT texture id with 'iBuffer' (e.g. WGL_FRONT_LEFT_ARB)
1349 */ 
1350 bool RenderTexture::BindBuffer( int iBuffer )
1351
1352     // Must bind the texture too
1353     if (_bInitialized && _bIsTexture) 
1354     {
1355         glBindTexture(_iTextureTarget, _iTextureID);
1356         
1357 #ifdef _WIN32
1358         if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
1359             (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
1360         {
1361             if (FALSE == wglBindTexImageARBPtr(_hPBuffer, iBuffer))
1362             {
1363                 //  WVB: WGL API considers binding twice to the same buffer
1364                 //  to be an error.  But we don't want to 
1365                 //_wglGetLastError();
1366                 //return false;
1367                 SetLastError(0);
1368             }
1369             _bIsBufferBound = true;
1370             _iCurrentBoundBuffer = iBuffer;
1371         }
1372 #elif defined(__MACH__)
1373     if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
1374          (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
1375     {
1376         CGLError err;
1377         if (err=CGLTexImagePBuffer(CGLGetCurrentContext(), _hPBuffer, iBuffer))
1378         {
1379             _cglCheckError(err);
1380         }
1381         _bIsBufferBound = true;
1382         _iCurrentBoundBuffer = iBuffer;
1383      }
1384 #endif
1385     }    
1386     return true;
1387 }
1388
1389
1390 //---------------------------------------------------------------------------
1391 // Function             : RenderTexture::BindDepthBuffer
1392 // Description      : 
1393 //---------------------------------------------------------------------------
1394 /**
1395 * @fn RenderTexture::_BindDepthBuffer()
1396 * @brief Associate the RTT depth texture id with the depth buffer
1397 */ 
1398 bool RenderTexture::_BindDepthBuffer() const
1399 {
1400 #ifdef WIN32
1401     if (_bInitialized && _bIsDepthTexture && 
1402         RT_RENDER_TO_TEXTURE == _eUpdateMode)
1403     {
1404         glBindTexture(_iTextureTarget, _iDepthTextureID);
1405         if (FALSE == wglBindTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1406         {
1407             _wglGetLastError();
1408             return false;
1409         }
1410     }
1411 #elif defined(__MACH__)
1412     if (_bInitialized && _bIsDepthTexture &&
1413         RT_RENDER_TO_TEXTURE == _eUpdateMode)
1414     {
1415         glBindTexture(_iTextureTarget, _iDepthTextureID);
1416         //if (FALSE == CGLTexImagePBuffer(<#CGLContextObj ctx#>,<#CGLPBufferObj pbuffer#>,<#unsigned long source#>)(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1417         //{
1418         //    _wglGetLastError();
1419         //    return false;
1420         //}
1421     }
1422 #endif
1423     return true;
1424 }
1425
1426 //---------------------------------------------------------------------------
1427 // Function             : RenderTexture::_ParseModeString
1428 // Description      : 
1429 //---------------------------------------------------------------------------
1430 /**
1431 * @fn RenderTexture::_ParseModeString()
1432 * @brief Parses the user-specified mode string for RenderTexture parameters.
1433 */ 
1434 void RenderTexture::_ParseModeString(const char *modeString, 
1435                                      vector<int> &pfAttribs, 
1436                                      vector<int> &pbAttribs)
1437 {
1438     dbg_printf("RenderTexture::_ParseModeString(%s). BGN vf=%d vp=%d\n", modeString, pfAttribs.size(), pbAttribs.size() );
1439     if (!modeString || strcmp(modeString, "") == 0)
1440         return;
1441
1442         _iNumComponents = 0;
1443 #if defined(_WIN32) || defined(__MACH__)
1444     _eUpdateMode = RT_RENDER_TO_TEXTURE;
1445 #else
1446     _eUpdateMode = RT_COPY_TO_TEXTURE;
1447 #endif
1448     
1449     int  iDepthBits = 0;
1450     bool bHasStencil = false;
1451     bool bBind2D   = false;
1452     bool bBindRECT = false;
1453     bool bBindCUBE = false;
1454     
1455     char *mode = strdup(modeString);
1456     
1457
1458     vector<string> tokens;
1459     char *buf = strtok(mode, " ");
1460     while (buf != NULL)
1461     {
1462         tokens.push_back(buf);
1463         buf = strtok(NULL, " ");
1464     }
1465     free(mode);
1466     for (unsigned int i = 0; i < tokens.size(); i++)
1467     {
1468         string token = tokens[i];
1469
1470         KeyVal kv = _GetKeyValuePair(token);
1471         
1472         
1473         if (kv.first == "rgb" && (_iNumComponents <= 1))
1474         {           
1475             if (kv.second.find("f") != kv.second.npos)
1476                 _bFloat = true;
1477
1478             vector<int> bitVec = _ParseBitVector(kv.second);
1479
1480             if (bitVec.size() < 3) // expand the scalar to a vector
1481             {
1482                 bitVec.push_back(bitVec[0]);
1483                 bitVec.push_back(bitVec[0]);
1484             }
1485
1486 #ifdef _WIN32
1487             pfAttribs.push_back(WGL_RED_BITS_ARB);
1488             pfAttribs.push_back(bitVec[0]);
1489             pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1490             pfAttribs.push_back(bitVec[1]);
1491             pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1492             pfAttribs.push_back(bitVec[2]);
1493 #elif defined( __MACH__ )
1494 # if 0
1495             pfAttribs.push_back(AGL_RED_SIZE);
1496             pfAttribs.push_back(bitVec[0]);
1497             pfAttribs.push_back(AGL_GREEN_SIZE);
1498             pfAttribs.push_back(bitVec[1]);
1499             pfAttribs.push_back(AGL_BLUE_SIZE);
1500             pfAttribs.push_back(bitVec[2]);
1501 # else
1502             pfAttribs.push_back(kCGLPFAColorSize);
1503             pfAttribs.push_back(bitVec[0] + bitVec[1] + bitVec[2]);
1504 # endif
1505 #else
1506             pfAttribs.push_back(GLX_RED_SIZE);
1507             pfAttribs.push_back(bitVec[0]);
1508             pfAttribs.push_back(GLX_GREEN_SIZE);
1509             pfAttribs.push_back(bitVec[1]);
1510             pfAttribs.push_back(GLX_BLUE_SIZE);
1511             pfAttribs.push_back(bitVec[2]);
1512 #endif
1513             _iNumComponents += 3;
1514             continue;
1515         }
1516                 else if (kv.first == "rgb")
1517        {
1518             SG_LOG(SG_GL, SG_ALERT, 
1519                     "RenderTexture Warning: mistake in components definition "
1520                     "(rgb + " << _iNumComponents << ").");
1521             dbg_printf("RenderTexture Warning 1: mistake in components definition "
1522                     "(rgb + %d).\n", _iNumComponents );
1523        }
1524         
1525         if (kv.first == "rgba" && (_iNumComponents == 0))
1526         {
1527             if (kv.second.find("f") != kv.second.npos)
1528                 _bFloat = true;
1529
1530             vector<int> bitVec = _ParseBitVector(kv.second);
1531
1532             if (bitVec.size() < 4) // expand the scalar to a vector
1533             {
1534                 bitVec.push_back(bitVec[0]);
1535                 bitVec.push_back(bitVec[0]);
1536                 bitVec.push_back(bitVec[0]);
1537             }
1538
1539 #ifdef _WIN32
1540             pfAttribs.push_back(WGL_RED_BITS_ARB);
1541             pfAttribs.push_back(bitVec[0]);
1542             pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1543             pfAttribs.push_back(bitVec[1]);
1544             pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1545             pfAttribs.push_back(bitVec[2]);
1546             pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1547             pfAttribs.push_back(bitVec[3]);
1548 #elif defined( __MACH__ )
1549 # if 0 
1550             pfAttribs.push_back(AGL_RED_SIZE);
1551             pfAttribs.push_back(bitVec[0]);
1552             pfAttribs.push_back(AGL_GREEN_SIZE);
1553             pfAttribs.push_back(bitVec[1]);
1554             pfAttribs.push_back(AGL_BLUE_SIZE);
1555             pfAttribs.push_back(bitVec[2]);
1556             pfAttribs.push_back(AGL_ALPHA_SIZE);
1557             pfAttribs.push_back(bitVec[3]);
1558 # else
1559             pfAttribs.push_back(kCGLPFAColorSize);
1560             pfAttribs.push_back(bitVec[0] + bitVec[1] + bitVec[2] + bitVec[3]);
1561             //pfAttribs.push_back(kCGLPFAAlphaSize);
1562             //pfAttribs.push_back(bitVec[3]);
1563             // printf("Color size: %d\n", bitVec[0] + bitVec[1] + bitVec[2] + bitVec[3]);
1564
1565 # endif
1566 #else
1567             pfAttribs.push_back(GLX_RED_SIZE);
1568             pfAttribs.push_back(bitVec[0]);
1569             pfAttribs.push_back(GLX_GREEN_SIZE);
1570             pfAttribs.push_back(bitVec[1]);
1571             pfAttribs.push_back(GLX_BLUE_SIZE);
1572             pfAttribs.push_back(bitVec[2]);
1573             pfAttribs.push_back(GLX_ALPHA_SIZE);
1574             pfAttribs.push_back(bitVec[3]);
1575 #endif
1576             _iNumComponents = 4;
1577             continue;
1578         }
1579                 else if (kv.first == "rgba") 
1580       {
1581             SG_LOG(SG_GL, SG_ALERT, 
1582                     "RenderTexture Warning: mistake in components definition "
1583                     "(rgba + " << _iNumComponents << ").");
1584             dbg_printf("RenderTexture Warning 2: mistake in components definition "
1585                     "(rgb + %d).\n", _iNumComponents );
1586       }
1587         
1588         if (kv.first == "r" && (_iNumComponents <= 1))
1589         {
1590             if (kv.second.find("f") != kv.second.npos)
1591                 _bFloat = true;
1592
1593             vector<int> bitVec = _ParseBitVector(kv.second);
1594
1595 #ifdef _WIN32
1596             pfAttribs.push_back(WGL_RED_BITS_ARB);
1597             pfAttribs.push_back(bitVec[0]);
1598 #elif defined( __MACH__ )
1599 # if 0
1600             pfAttribs.push_back(AGL_RED_SIZE);
1601             pfAttribs.push_back(bitVec[0]);
1602 # else
1603             pfAttribs.push_back(kCGLPFAColorSize);
1604             pfAttribs.push_back(bitVec[0]);
1605 # endif
1606 #else
1607             pfAttribs.push_back(GLX_RED_SIZE);
1608             pfAttribs.push_back(bitVec[0]);
1609 #endif
1610                         _iNumComponents++;
1611             continue;
1612         }
1613         else if (kv.first == "r") 
1614    {
1615             SG_LOG(SG_GL, SG_ALERT, 
1616                     "RenderTexture Warning: mistake in components definition "
1617                     "(r + " << _iNumComponents << ").");
1618             dbg_printf("RenderTexture Warning 3: mistake in components definition "
1619                     "(rgb + %d).\n", _iNumComponents );
1620    }
1621         if (kv.first == "rg" && (_iNumComponents <= 1))
1622         {
1623             if (kv.second.find("f") != kv.second.npos)
1624                 _bFloat = true;
1625
1626             vector<int> bitVec = _ParseBitVector(kv.second);
1627
1628             if (bitVec.size() < 2) // expand the scalar to a vector
1629             {
1630                 bitVec.push_back(bitVec[0]);
1631             }
1632
1633 #ifdef _WIN32
1634             pfAttribs.push_back(WGL_RED_BITS_ARB);
1635             pfAttribs.push_back(bitVec[0]);
1636             pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1637             pfAttribs.push_back(bitVec[1]);
1638 #elif defined( __MACH__ )
1639 # if 0
1640             pfAttribs.push_back(AGL_RED_SIZE);
1641             pfAttribs.push_back(bitVec[0]);
1642             pfAttribs.push_back(AGL_GREEN_SIZE);
1643             pfAttribs.push_back(bitVec[1]);
1644 # else
1645             pfAttribs.push_back(kCGLPFAColorSize);
1646             pfAttribs.push_back(bitVec[0] + bitVec[1]);
1647 # endif
1648 #else
1649             pfAttribs.push_back(GLX_RED_SIZE);
1650             pfAttribs.push_back(bitVec[0]);
1651             pfAttribs.push_back(GLX_GREEN_SIZE);
1652             pfAttribs.push_back(bitVec[1]);
1653 #endif
1654                         _iNumComponents += 2;
1655             continue;
1656         }
1657                 else if (kv.first == "rg") 
1658       {
1659             SG_LOG(SG_GL, SG_ALERT, 
1660                     "RenderTexture Warning: mistake in components definition "
1661                     "(rg + " << _iNumComponents << ").");
1662             dbg_printf("RenderTexture Warning 4: mistake in components definition "
1663                     "(rgb + %d).\n", _iNumComponents );
1664       }
1665
1666         if (kv.first == "depth")
1667         {
1668             if (kv.second == "")
1669                 iDepthBits = 24;
1670             else
1671                 iDepthBits = strtol(kv.second.c_str(), 0, 10);
1672             continue;
1673         }
1674
1675         if (kv.first == "stencil")
1676         {
1677             bHasStencil = true;
1678 #ifdef _WIN32
1679             pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1680 #elif defined( __MACH__ )
1681 # if 0
1682             pfAttribs.push_back(AGL_STENCIL_SIZE);
1683 # else
1684             pfAttribs.push_back(kCGLPFAStencilSize);
1685 # endif
1686 #else
1687             pfAttribs.push_back(GLX_STENCIL_SIZE);
1688 #endif
1689             if (kv.second == "")
1690                 pfAttribs.push_back(8);
1691             else
1692                 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1693             continue;
1694         }
1695
1696         if (kv.first == "samples")
1697         {
1698 #ifdef _WIN32
1699             pfAttribs.push_back(WGL_SAMPLE_BUFFERS_ARB);
1700             pfAttribs.push_back(1);
1701             pfAttribs.push_back(WGL_SAMPLES_ARB);
1702             pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1703 #elif defined( __MACH__ )
1704 # if 0
1705             pfAttribs.push_back(AGL_SAMPLE_BUFFERS_ARB);
1706             pfAttribs.push_back(1);
1707             pfAttribs.push_back(AGL_SAMPLES_ARB);
1708 # else
1709             pfAttribs.push_back(kCGLPFAMultisample);
1710             pfAttribs.push_back(kCGLPFASamples);
1711 # endif
1712             pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1713 #else
1714             pfAttribs.push_back(GLX_SAMPLE_BUFFERS_ARB);
1715             pfAttribs.push_back(1);
1716             pfAttribs.push_back(GLX_SAMPLES_ARB);
1717             pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1718 #endif
1719             continue;
1720
1721         }
1722
1723         if (kv.first == "doublebuffer" || kv.first == "double")
1724         {
1725 #ifdef _WIN32
1726             pfAttribs.push_back(WGL_DOUBLE_BUFFER_ARB);
1727             pfAttribs.push_back(true);
1728 #elif defined( __MACH__ )
1729 # if 0
1730             pfAttribs.push_back(AGL_DOUBLEBUFFER);
1731             pfAttribs.push_back(True);
1732 # else
1733             pfAttribs.push_back(kCGLPFADoubleBuffer);
1734 # endif
1735 #else
1736             pfAttribs.push_back(GLX_DOUBLEBUFFER);
1737             pfAttribs.push_back(True);
1738 #endif
1739             continue;
1740         }  
1741         
1742         if (kv.first == "aux")
1743         {
1744 #ifdef _WIN32
1745             pfAttribs.push_back(WGL_AUX_BUFFERS_ARB);
1746 #elif defined( __MACH__ )
1747 # if 0
1748             pfAttribs.push_back(AGL_AUX_BUFFERS);
1749 # else
1750             pfAttribs.push_back(kCGLPFAAuxBuffers);
1751 # endif
1752 #else
1753             pfAttribs.push_back(GLX_AUX_BUFFERS);
1754 #endif
1755             if (kv.second == "")
1756                 pfAttribs.push_back(0);
1757             else
1758                 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1759             continue;
1760         }
1761         
1762         if (token.find("tex") == 0)
1763         {            
1764             _bIsTexture = true;
1765             
1766             if ((kv.first == "texRECT") && (GL_NV_texture_rectangle ||
1767                                             GL_EXT_texture_rectangle))
1768             {
1769                 _bRectangle = true;
1770                 bBindRECT = true;
1771             }
1772             else if (kv.first == "texCUBE")
1773             {
1774                 bBindCUBE = true;
1775             }
1776             else
1777             {
1778                 bBind2D = true;
1779             }
1780
1781             continue;
1782         }
1783
1784         if (token.find("depthTex") == 0)
1785         {
1786             _bIsDepthTexture = true;
1787             
1788             if ((kv.first == "depthTexRECT") && (GL_NV_texture_rectangle ||
1789                                                  GL_EXT_texture_rectangle))
1790             {
1791                 _bRectangle = true;
1792                 bBindRECT = true;
1793             }
1794             else if (kv.first == "depthTexCUBE")
1795             {
1796                 bBindCUBE = true;
1797             }
1798             else
1799             {
1800                 bBind2D = true;
1801             }
1802
1803             continue;
1804         }
1805
1806         if (kv.first == "mipmap")
1807         {
1808             _bMipmap = true;    
1809             continue;
1810         }
1811
1812         if (kv.first == "rtt")
1813         {
1814             _eUpdateMode = RT_RENDER_TO_TEXTURE;
1815             continue;
1816         }
1817         
1818         if (kv.first == "ctt")
1819         {
1820             _eUpdateMode = RT_COPY_TO_TEXTURE;
1821             continue;
1822         }
1823
1824         SG_LOG(SG_GL, SG_ALERT, 
1825                 "RenderTexture Error: Unknown pbuffer attribute: " <<
1826                 token.c_str());
1827         dbg_printf("RenderTexture Error: Uknown pbuffer attribute: %s\n",
1828             token.c_str() );
1829     }
1830
1831     // Processing of some options must be last because of interactions.
1832
1833     // Check for inconsistent texture targets
1834     if (_bIsTexture && _bIsDepthTexture && !(bBind2D ^ bBindRECT ^ bBindCUBE))
1835     {
1836         SG_LOG(SG_GL, SG_ALERT,
1837                 "RenderTexture Warning: Depth and Color texture targets "
1838                 "should match.");
1839         dbg_printf( "RenderTexture Warning: Depth and Color texture targets should match.\n");
1840     }
1841
1842     // Apply default bit format if none specified
1843 #ifdef _WIN32
1844     if (0 == _iNumComponents)
1845     {
1846         pfAttribs.push_back(WGL_RED_BITS_ARB);
1847         pfAttribs.push_back(8);
1848         pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1849         pfAttribs.push_back(8);
1850         pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1851         pfAttribs.push_back(8);
1852         pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1853         pfAttribs.push_back(8);
1854         _iNumComponents = 4;
1855     }
1856 #endif
1857
1858     // Depth bits
1859     if (_bIsDepthTexture && !iDepthBits)
1860         iDepthBits = 24;
1861
1862 #ifdef _WIN32
1863     pfAttribs.push_back(WGL_DEPTH_BITS_ARB);
1864 #elif defined( __MACH__ )
1865 # if 0
1866     pfAttribs.push_back(AGL_DEPTH_SIZE);
1867 # else
1868     pfAttribs.push_back(kCGLPFADepthSize);
1869 # endif
1870 #else
1871     pfAttribs.push_back(GLX_DEPTH_SIZE);
1872 #endif
1873     pfAttribs.push_back(iDepthBits); // default
1874     
1875     if (!bHasStencil)
1876     {
1877 #ifdef _WIN32
1878         pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1879         pfAttribs.push_back(0);
1880 #elif defined( __MACH__ )
1881 # if 0
1882         pfAttribs.push_back(AGL_STENCIL_SIZE);
1883 # else
1884         pfAttribs.push_back(kCGLPFAStencilSize);
1885 # endif
1886         pfAttribs.push_back(0);
1887 #else
1888         pfAttribs.push_back(GLX_STENCIL_SIZE);
1889         pfAttribs.push_back(0);
1890 #endif
1891
1892     }
1893     if (_iNumComponents < 4)
1894     {
1895         // Can't do this right now -- on NVIDIA drivers, currently get 
1896         // a non-functioning pbuffer if ALPHA_BITS=0 and 
1897         // WGL_BIND_TO_TEXTURE_RGB_ARB=true
1898         
1899         //pfAttribs.push_back(WGL_ALPHA_BITS_ARB); 
1900         //pfAttribs.push_back(0);
1901     }
1902
1903 #ifdef _WIN32
1904     if (!WGL_NV_render_depth_texture && _bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1905     {
1906 #if defined(DEBUG) || defined(_DEBUG)
1907         SG_LOG(SG_GL, SG_ALERT, "RenderTexture Warning: No support found for "
1908                 "render to depth texture.");
1909 #endif
1910         dbg_printf("RenderTexture Warning: No support found for render to depth texture.\n");
1911         _bIsDepthTexture = false;
1912     }
1913 #endif
1914     
1915     if ((_bIsTexture || _bIsDepthTexture) && 
1916         (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1917     {
1918 #ifdef _WIN32                   
1919         if (bBindRECT)
1920         {
1921             pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1922             pbAttribs.push_back(WGL_TEXTURE_RECTANGLE_NV);
1923         }
1924         else if (bBindCUBE)
1925         {
1926             pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1927             pbAttribs.push_back(WGL_TEXTURE_CUBE_MAP_ARB);
1928         }
1929         else if (bBind2D)
1930         {
1931             pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1932             pbAttribs.push_back(WGL_TEXTURE_2D_ARB);
1933         }
1934             
1935         if (_bMipmap)
1936         {
1937             pbAttribs.push_back(WGL_MIPMAP_TEXTURE_ARB);
1938             pbAttribs.push_back(true);
1939         }
1940 #elif defined(__MACH__)
1941 #elif defined(DEBUG) || defined(_DEBUG)
1942         SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: Render to Texture not "
1943                "supported in Linux or MacOS");
1944 #endif  
1945     }
1946
1947     // Set the pixel type
1948     if (_bFloat)
1949     {
1950 #ifdef _WIN32
1951         if (WGL_NV_float_buffer)
1952         {
1953             pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1954             pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1955
1956             pfAttribs.push_back(WGL_FLOAT_COMPONENTS_NV);
1957             pfAttribs.push_back(true);
1958         }
1959         else
1960         {
1961             pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1962             pfAttribs.push_back(WGL_TYPE_RGBA_FLOAT_ATI);
1963         }
1964 #elif defined( __MACH__ )
1965         // if (GL_MACH_float_pixels) // FIXME
1966         {
1967             pfAttribs.push_back(kCGLPFAColorFloat);
1968         }
1969 #else
1970         if (GLX_NV_float_buffer)
1971         {
1972             pfAttribs.push_back(GLX_FLOAT_COMPONENTS_NV);
1973             pfAttribs.push_back(1);
1974         }
1975 #endif
1976     }
1977     else
1978     {
1979 #ifdef _WIN32
1980         pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1981         pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1982 #endif
1983     }
1984
1985     // Set up texture binding for render to texture
1986     if (_bIsTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1987     {
1988         
1989 #ifdef _WIN32
1990         if (_bFloat)
1991         {
1992             if (WGL_NV_float_buffer)
1993             {
1994                 switch(_iNumComponents)
1995                 {
1996                 case 1:
1997                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
1998                     pfAttribs.push_back(true);
1999                     
2000                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2001                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_R_NV);
2002                     break;
2003                 case 2:
2004                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
2005                     pfAttribs.push_back(true);
2006                     
2007                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2008                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_RG_NV);
2009                     break;
2010                 case 3:
2011                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
2012                     pfAttribs.push_back(true);
2013                     
2014                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2015                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGB_NV);
2016                     break;
2017                 case 4:
2018                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
2019                     pfAttribs.push_back(true);
2020                     
2021                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2022                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGBA_NV);
2023                     break;
2024                 default:
2025                     SG_LOG(SG_GL, SG_ALERT, 
2026                             "RenderTexture Warning: Bad number of components "
2027                             "(r=1,rg=2,rgb=3,rgba=4): " <<
2028                             _iNumComponents);
2029                     dbg_printf("RenderTexture Warning 1: Bad number of components (r=1,rg=2,rgb=3,rgba=4): %d\n",
2030                             _iNumComponents);
2031                     break;
2032                 }
2033             }
2034             else
2035             {
2036                 if (4 == _iNumComponents)
2037                 {
2038                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
2039                     pfAttribs.push_back(true);
2040                     
2041                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2042                     pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
2043                 }
2044                 else 
2045                 {
2046                     // standard ARB_render_texture only supports 3 or 4 channels
2047                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
2048                     pfAttribs.push_back(true);
2049                     
2050                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2051                     pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
2052                 }
2053             }
2054             
2055         } 
2056         else
2057         {
2058             switch(_iNumComponents)
2059             {
2060             case 3:
2061                 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
2062                 pfAttribs.push_back(true);
2063                 
2064                 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2065                 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
2066                 break;
2067             case 4:
2068                 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
2069                 pfAttribs.push_back(true);
2070                 
2071                 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2072                 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
2073                 break;
2074             default:
2075                 SG_LOG(SG_GL, SG_ALERT, 
2076                         "RenderTexture Warning: Bad number of components "
2077                         "(r=1,rg=2,rgb=3,rgba=4): " << _iNumComponents);
2078                 dbg_printf("RenderTexture Warning 2: Bad number of components (r=1,rg=2,rgb=3,rgba=4): %d\n",
2079                             _iNumComponents);
2080                 break;
2081             }
2082         }
2083 #elif defined(__MACH__)
2084         if (_bFloat)
2085         {
2086                        /*
2087             //if (WGLEW_NV_float_buffer)       // FIXME
2088             {
2089                 switch(_iNumComponents)
2090                 {
2091                 case 1:
2092                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
2093                     pfAttribs.push_back(true);
2094
2095                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2096                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_R_NV);
2097                     break;
2098                 case 2:
2099                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
2100                     pfAttribs.push_back(true);
2101
2102                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2103                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_RG_NV);
2104                     break;
2105                 case 3:
2106                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
2107                     pfAttribs.push_back(true);
2108
2109                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2110                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGB_NV);
2111                     break;
2112                 case 4:
2113                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
2114                     pfAttribs.push_back(true);
2115
2116                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2117                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGBA_NV);
2118                     break;
2119                 default:
2120                     fprintf(stderr,
2121                             "RenderTexture Warning: Bad number of components "
2122                             "(r=1,rg=2,rgb=3,rgba=4): %d.\n",
2123                             _iNumComponents);
2124                     break;
2125                 }
2126            }
2127             else
2128             {
2129                 if (4 == _iNumComponents)
2130                 {
2131                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
2132                     pfAttribs.push_back(true);
2133
2134                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2135                     pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
2136                 }
2137                 else
2138                 {
2139                     // standard ARB_render_texture only supports 3 or 4 channels
2140                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
2141                     pfAttribs.push_back(true);
2142
2143                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2144                     pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
2145                 }
2146             }
2147             */
2148         }
2149         else
2150         {
2151                        /*
2152             switch(_iNumComponents)
2153             {
2154             case 3:
2155                 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
2156                 pfAttribs.push_back(true);
2157
2158                 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2159                 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
2160                 break;
2161             case 4:
2162                 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
2163                 pfAttribs.push_back(true);
2164
2165                 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2166                 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
2167                 break;
2168             default:
2169                 fprintf(stderr,
2170                         "RenderTexture Warning: Bad number of components "
2171                         "(r=1,rg=2,rgb=3,rgba=4): %d.\n", _iNumComponents);
2172                 break;
2173             }
2174                        */
2175         }
2176 #elif defined(DEBUG) || defined(_DEBUG)
2177         SG_LOG(SG_GL, SG_ALERT, 
2178                 "RenderTexture Error: Render to Texture not supported in Linux or MacOS");
2179 #endif  
2180       dbg_printf( "RenderTexture Error 1: Render to Texture not supported in Linux or MacOS\n");
2181     }
2182         
2183     if (_bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
2184     {  
2185 #ifdef _WIN32
2186         if (_bRectangle)
2187         {
2188             pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV);
2189             pfAttribs.push_back(true);
2190         
2191             pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
2192             pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
2193         }
2194         else 
2195         {
2196             pfAttribs.push_back(WGL_BIND_TO_TEXTURE_DEPTH_NV);
2197             pfAttribs.push_back(true);
2198         
2199             pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
2200             pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
2201         }
2202 #elif defined(__MACH__)
2203 #elif defined(DEBUG) || defined(_DEBUG)
2204         SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: Render to Texture not supported in "
2205                "Linux or MacOS");
2206 #endif 
2207       dbg_printf( "RenderTexture Error 2: Render to Texture not supported in Linux or MacOS\n");
2208     }
2209     dbg_printf("RenderTexture::_ParseModeString(%s). END vf=%d vp=%d\n", modeString, pfAttribs.size(), pbAttribs.size() );
2210
2211 }
2212
2213 //---------------------------------------------------------------------------
2214 // Function             : RenderTexture::_GetKeyValuePair
2215 // Description      : 
2216 //---------------------------------------------------------------------------
2217 /**
2218 * @fn RenderTexture::_GetKeyValuePair()
2219 * @brief Parses expressions of the form "X=Y" into a pair (X,Y).
2220 */ 
2221 RenderTexture::KeyVal RenderTexture::_GetKeyValuePair(string token)
2222 {
2223     string::size_type pos = 0;
2224     if ((pos = token.find("=")) != token.npos)
2225     {
2226         string key = token.substr(0, pos);
2227         string value = token.substr(pos+1, token.length()-pos+1);
2228         return KeyVal(key, value);
2229     }
2230     else
2231         return KeyVal(token, "");
2232 }
2233
2234 //---------------------------------------------------------------------------
2235 // Function             : RenderTexture::_ParseBitVector
2236 // Description      : 
2237 //---------------------------------------------------------------------------
2238 /**
2239 * @fn RenderTexture::_ParseBitVector()
2240 * @brief Parses expressions of the form "=r,g,b,a" into a vector: (r,g,b,a)
2241 */ 
2242 vector<int> RenderTexture::_ParseBitVector(string bitVector)
2243 {
2244     vector<string> pieces;
2245     vector<int> bits;
2246
2247     if (bitVector == "")
2248     {
2249         bits.push_back(8);  // if a depth isn't specified, use default 8 bits
2250         return bits;
2251     }
2252
2253     string::size_type pos = 0; 
2254     string::size_type nextpos = 0;
2255     do
2256     { 
2257         nextpos = bitVector.find_first_of(", ", pos);
2258         pieces.push_back(string(bitVector, pos, nextpos - pos)); 
2259         pos = nextpos+1; 
2260     } while (nextpos != bitVector.npos );
2261
2262     for ( vector<string>::iterator it = pieces.begin(); it != pieces.end(); it++)
2263     {
2264         bits.push_back(strtol(it->c_str(), 0, 10));
2265     }
2266     
2267     return bits;
2268 }
2269
2270 //---------------------------------------------------------------------------
2271 // Function             : RenderTexture::_VerifyExtensions
2272 // Description      : 
2273 //---------------------------------------------------------------------------
2274 /**
2275 * @fn RenderTexture::_VerifyExtensions()
2276 * @brief Checks that the necessary extensions are available based on RT mode.
2277 */ 
2278 bool RenderTexture::_VerifyExtensions()
2279 {
2280    dbg_printf("RenderTexture::_VerifyExtensions() called...\n");
2281 #ifdef _WIN32
2282         // a second call to _VerifyExtensions will allways return true, causing a crash
2283         // if the extension is not supported
2284     if ( true || !fctPtrInited )
2285     {
2286         fctPtrInited = true;
2287         wglGetExtensionsStringARBProc wglGetExtensionsStringARBPtr = (wglGetExtensionsStringARBProc)wglGetProcAddress( "wglGetExtensionsStringARB" );
2288         if ( wglGetExtensionsStringARBPtr == 0 )
2289         {
2290             PrintExtensionError("WGL_ARB_extensions_string");
2291             return false;
2292         }
2293         string wglExtensionsString = wglGetExtensionsStringARBPtr( wglGetCurrentDC() );
2294         if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pixel_format" ) )
2295         {
2296             wglChoosePixelFormatARBPtr = (wglChoosePixelFormatARBProc)SGLookupFunction("wglChoosePixelFormatARB");
2297             wglGetPixelFormatAttribivARBPtr = (wglGetPixelFormatAttribivARBProc)SGLookupFunction("wglGetPixelFormatAttribivARB");
2298         }
2299         else
2300         {
2301             PrintExtensionError("WGL_ARB_pixel_format");
2302             return false;
2303         }
2304         if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pbuffer" ) )
2305         {
2306             wglCreatePbufferARBPtr = (wglCreatePbufferARBProc)SGLookupFunction("wglCreatePbufferARB");
2307             wglGetPbufferDCARBPtr = (wglGetPbufferDCARBProc)SGLookupFunction("wglGetPbufferDCARB");
2308             wglQueryPbufferARBPtr = (wglQueryPbufferARBProc)SGLookupFunction("wglQueryPbufferARB");
2309             wglReleasePbufferDCARBPtr = (wglReleasePbufferDCARBProc)SGLookupFunction("wglReleasePbufferDCARB");
2310             wglDestroyPbufferARBPtr = (wglDestroyPbufferARBProc)SGLookupFunction("wglDestroyPbufferARB");
2311         }
2312         else
2313         {
2314             PrintExtensionError("WGL_ARB_pbuffer");
2315             return false;
2316         }
2317         if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_render_texture" ) )
2318         {
2319             wglBindTexImageARBPtr = (wglBindTexImageARBProc)SGLookupFunction("wglBindTexImageARB");
2320             wglReleaseTexImageARBPtr = (wglReleaseTexImageARBProc)SGLookupFunction("wglReleaseTexImageARB");
2321         }
2322         else if ( _bIsTexture )
2323         {
2324             PrintExtensionError("WGL_ARB_render_texture");
2325             return false;
2326         }
2327         if (_bRectangle && !SGIsOpenGLExtensionSupported( "GL_NV_texture_rectangle" ))
2328         {
2329             PrintExtensionError("GL_NV_texture_rectangle");
2330             return false;
2331         }
2332         if (_bFloat && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) ||
2333             SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ATI_pixel_format_float" )))
2334         {
2335             PrintExtensionError("GL_NV_float_buffer or GL_ATI_pixel_format_float");
2336             return false;
2337         
2338         }
2339         if (_bFloat && _bIsTexture && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) || SGIsOpenGLExtensionSupported( "GL_ATI_texture_float" )))
2340         {
2341             PrintExtensionError("NV_float_buffer or ATI_texture_float");
2342         }
2343         if (_bIsDepthTexture && !SGIsOpenGLExtensionSupported( "GL_ARB_depth_texture" ))
2344         {
2345             // [Redge]
2346 #if defined(_DEBUG) | defined(DEBUG)
2347             SG_LOG(SG_GL, SG_ALERT, 
2348                     "RenderTexture Warning: "
2349                     "OpenGL extension GL_ARB_depth_texture not available."
2350                     "         Using glReadPixels() to emulate behavior.");
2351 #endif   
2352             _bHasARBDepthTexture = false;
2353             //PrintExtensionError("GL_ARB_depth_texture");
2354             //return false;
2355             // [/Redge]
2356         }
2357         SetLastError(0);
2358     }
2359 #elif defined( __MACH__ )
2360     // FIXME! Check extensions!
2361 #else
2362     Display* dpy = glXGetCurrentDisplay();
2363     int minor = 0, major = 0;
2364     if (!dpy) {
2365         dbg_printf("_VerifyExtensions: glXGetCurrentDisplay() returned NULL! returning false\n");
2366         return false;
2367     }
2368     if (!glXQueryVersion(dpy, &major, &minor)) 
2369     {
2370         dbg_printf("_VerifyExtensions: glXQueryVersion(dpy, &major, &minor) FAILED! returning false\n");
2371         return false;
2372     }
2373     else
2374     {
2375         dbg_printf("_VerifyExtensions: glXQueryVersion(dpy, major=%d, minor=%d)\n", major, minor);
2376     }
2377
2378     int screen = DefaultScreen(dpy);
2379     const char* extString = glXQueryExtensionsString(dpy, screen);
2380     dbg_printf("_VerifyExtensions: glXQueryExtensionsString(dpy, screen) returned -\n[%s]\n",
2381       (extString ? extString : "<NULL>") );
2382     if (!SGSearchExtensionsString(extString, "GLX_SGIX_fbconfig") ||
2383         !SGSearchExtensionsString(extString, "GLX_SGIX_pbuffer"))
2384     {
2385         dbg_printf("_VerifyExtensions: glXQueryExtensionsString(dpy,screen) does NOT contain GLX_SGIX_fbconfig or GLX_SGIX_pbuffer!\n" );
2386         const char * extClient = glXGetClientString( dpy, GLX_EXTENSIONS );
2387         if (!extClient ||
2388             !SGSearchExtensionsString(extClient, "GLX_SGIX_fbconfig") ||
2389             !SGSearchExtensionsString(extClient, "GLX_SGIX_pbuffer"))
2390         {
2391             dbg_printf("_VerifyExtensions: AND glXGetClientString(dpy,GLX_EXTENSIONS) also! returning false\n" );
2392             return false;
2393         }
2394         else
2395         {
2396             dbg_printf("_VerifyExtensions: BUT glXGetClientString(dpy,GLX_EXTENSIONS) returned \n[%s]\n", extClient );
2397             dbg_printf("Since this DOES contain fbconfig and pbuffer, continuing...\n");
2398         }
2399     }
2400     // First try the glX version 1.3 functions.
2401     glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfig");
2402     glXCreatePbufferPtr = (glXCreatePbufferProc)SGLookupFunction("glXCreatePbuffer");
2403     glXGetVisualFromFBConfigPtr = (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfig");
2404     glXCreateContextPtr = (glXCreateContextProc)SGLookupFunction("glXCreateContext");
2405     glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyPbuffer");
2406     glXQueryDrawablePtr = (glXQueryDrawableProc)SGLookupFunction("glXQueryDrawable");
2407
2408     if (((1 <= major && 3 <= minor) || 2 <= major) &&
2409         glXChooseFBConfigPtr &&
2410         glXCreatePbufferPtr &&
2411         glXGetVisualFromFBConfigPtr &&
2412         glXCreateContextPtr &&
2413         glXDestroyPbufferPtr &&
2414         glXQueryDrawablePtr) {
2415         dbg_printf("_VerifyExtensions: setting glXVersion1_3Present TRUE\n" );
2416         glXVersion1_3Present = true;
2417     }
2418     else
2419     {
2420         dbg_printf("_VerifyExtensions: setting glXVersion1_3Present FALSE\n Reason: " );
2421         if ( !((1 <= major && 3 <= minor) || 2 <= major) ) { dbg_printf( "Version wrong %d.%d ", major, minor ); }
2422         if ( !glXChooseFBConfigPtr ) { dbg_printf( "missing glXChooseFBConfigPtr " ); }
2423         if ( !glXCreatePbufferPtr ) { dbg_printf( "missing glXCreatePbufferPtr " ); }
2424         if ( !glXGetVisualFromFBConfigPtr ) { dbg_printf( "missing glXGetVisualFromFBConfigPtr " ); }
2425         if ( !glXCreateContextPtr ) { dbg_printf( "missing glXCreateContextPtr " ); }
2426         if ( !glXDestroyPbufferPtr ) { dbg_printf( "missing glXDestroyPbufferPtr " ); }
2427         if ( !glXQueryDrawablePtr ) { dbg_printf( "missing glXQueryDrawablePtr " ); }
2428         dbg_printf("\n");
2429         
2430         glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfigSGIX");
2431         glXCreateGLXPbufferPtr = (glXCreateGLXPbufferProc)SGLookupFunction("glXCreateGLXPbufferSGIX");
2432         glXGetVisualFromFBConfigPtr =  (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfigSGIX");
2433         glXCreateContextWithConfigPtr = (glXCreateContextWithConfigProc)SGLookupFunction("glXCreateContextWithConfigSGIX");
2434         glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyGLXPbufferSGIX");
2435         glXQueryGLXPbufferSGIXPtr = (glXQueryGLXPbufferSGIXProc)SGLookupFunction("glXQueryGLXPbufferSGIX");
2436
2437         if (!glXChooseFBConfigPtr ||
2438             !glXCreateGLXPbufferPtr ||
2439             !glXGetVisualFromFBConfigPtr ||
2440             !glXCreateContextWithConfigPtr ||
2441             !glXDestroyPbufferPtr ||
2442             !glXQueryGLXPbufferSGIXPtr)
2443             {
2444                dbg_printf("_VerifyExtensions: some pointer is NULL! return false\n" );
2445                if ( !glXCreateGLXPbufferPtr ) {
2446                   dbg_printf("RenderTexture::Initialize: ERROR glXCreateGLXPbufferPtr = NULL!\n");
2447                } else if ( !glXCreateContextWithConfigPtr ) {
2448                   dbg_printf("RenderTexture::Initialize: ERROR glXCreateContextWithConfigPtr = NULL!\n");
2449                } else if ( !glXVersion1_3Present && !glXQueryGLXPbufferSGIXPtr ) {
2450                   dbg_printf("RenderTexture::Initialize: ERROR glXQueryGLXPbufferSGIXPtr = NULL!\n");
2451                }
2452                return false;
2453             } else {
2454                dbg_printf("_VerifyExtensions: appear to have all 'procs' glXCreateGLXPbufferPtr=[%p]\n", glXCreateGLXPbufferPtr );
2455             }
2456     }
2457
2458     if (_bIsDepthTexture && !GL_ARB_depth_texture)
2459     {
2460         PrintExtensionError("GL_ARB_depth_texture");
2461         return false;
2462     }
2463     if (_bFloat && _bIsTexture && !GLX_NV_float_buffer)
2464     {
2465         PrintExtensionError("GLX_NV_float_buffer");
2466         return false;
2467     }
2468     if (_eUpdateMode == RT_RENDER_TO_TEXTURE)
2469     {
2470         PrintExtensionError("Some GLX render texture extension: Please implement me!");
2471         return false;
2472     }
2473 #endif
2474   
2475     dbg_printf("RenderTexture::_VerifyExtensions: return true.\n");
2476     return true;
2477 }
2478
2479 //---------------------------------------------------------------------------
2480 // Function             : RenderTexture::_InitializeTextures
2481 // Description      : 
2482 //---------------------------------------------------------------------------
2483 /**
2484 * @fn RenderTexture::_InitializeTextures()
2485 * @brief Initializes the state of textures used by the RenderTexture.
2486 */ 
2487 bool RenderTexture::_InitializeTextures()
2488 {
2489    dbg_printf( "RenderTexture::_InitializeTextures() called\n" );
2490     // Determine the appropriate texture formats and filtering modes.
2491     
2492     if (_bIsTexture || _bIsDepthTexture)
2493     {
2494         if (_bRectangle && GL_NV_texture_rectangle)
2495             _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
2496         else if (_bRectangle && GL_EXT_texture_rectangle)
2497             _iTextureTarget = GL_TEXTURE_RECTANGLE_EXT;
2498         else
2499             _iTextureTarget = GL_TEXTURE_2D;
2500     }
2501
2502     if (_bIsTexture)
2503     {
2504         glGenTextures(1, (GLuint*)&_iTextureID);
2505         glBindTexture(_iTextureTarget, _iTextureID);  
2506         
2507         // Use clamp to edge as the default texture wrap mode for all tex
2508         glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2509         glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
2510         // Use NEAREST as the default texture filtering mode.
2511         glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2512         glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2513
2514
2515         if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2516         {
2517             GLuint iInternalFormat;
2518             GLuint iFormat;
2519
2520             if (_bFloat)
2521             {                             
2522                 if (_bMipmap)
2523                 {
2524                     SG_LOG(SG_GL, SG_ALERT, 
2525                         "RenderTexture Error: mipmapped float textures not "
2526                         "supported.");
2527                     dbg_printf( "RenderTexture Error: mipmapped float textures not supported. return false\n");
2528                     return false;
2529                 }
2530             
2531                 switch(_iNumComponents) 
2532                 {
2533                 case 1:
2534                     if (GL_NV_float_buffer)
2535                     {
2536                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
2537                             GL_FLOAT_R32_NV : GL_FLOAT_R16_NV;
2538                     }
2539                     else if (GL_ATI_texture_float)
2540                     {
2541                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
2542                             GL_LUMINANCE_FLOAT32_ATI : 
2543                             GL_LUMINANCE_FLOAT16_ATI;
2544                     }
2545                     iFormat = GL_LUMINANCE;
2546                         break;
2547                 case 2:
2548                     if (GL_NV_float_buffer)
2549                     {
2550                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
2551                             GL_FLOAT_RG32_NV : GL_FLOAT_RG16_NV;
2552                     }
2553                     else if (GL_ATI_texture_float)
2554                     {
2555                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
2556                             GL_LUMINANCE_ALPHA_FLOAT32_ATI : 
2557                             GL_LUMINANCE_ALPHA_FLOAT16_ATI;
2558                     }
2559                     iFormat = GL_LUMINANCE_ALPHA;
2560                         break;
2561                 case 3:
2562                     if (GL_NV_float_buffer)
2563                     {
2564                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
2565                             GL_FLOAT_RGB32_NV : GL_FLOAT_RGB16_NV;
2566                     }
2567                     else if (GL_ATI_texture_float)
2568                     {
2569                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
2570                             GL_RGB_FLOAT32_ATI : GL_RGB_FLOAT16_ATI;
2571                     }
2572                     iFormat = GL_RGB;
2573                     break;
2574                 case 4:
2575                     if (GL_NV_float_buffer)
2576                     {
2577                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
2578                             GL_FLOAT_RGBA32_NV : GL_FLOAT_RGBA16_NV;
2579                     }
2580                     else if (GL_ATI_texture_float)
2581                     {
2582                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
2583                             GL_RGBA_FLOAT32_ATI : GL_RGBA_FLOAT16_ATI;
2584                     }
2585                     iFormat = GL_RGBA;
2586                     break;
2587                 default:
2588                     SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: "
2589                            "Invalid number of components: " <<
2590                            _iNumComponents);
2591                     dbg_printf( "RenderTexture Error: Invalid number of components: %d - return false\n",
2592                         _iNumComponents);
2593                     return false;
2594                 }
2595             }
2596             else // non-float
2597             {                        
2598                 if (4 == _iNumComponents)
2599                 {
2600                     iInternalFormat = GL_RGBA8;
2601                     iFormat = GL_RGBA;
2602                 }
2603                 else 
2604                 {
2605                     iInternalFormat = GL_RGB8;
2606                     iFormat = GL_RGB;
2607                 }
2608             }
2609         
2610             // Allocate the texture image (but pass it no data for now).
2611             glTexImage2D(_iTextureTarget, 0, iInternalFormat, 
2612                          _iWidth, _iHeight, 0, iFormat, GL_FLOAT, NULL);
2613         } 
2614     }
2615   
2616     if (_bIsDepthTexture)
2617     { 
2618         glGenTextures(1, (GLuint*)&_iDepthTextureID);
2619         glBindTexture(_iTextureTarget, _iDepthTextureID);  
2620         
2621         // Use clamp to edge as the default texture wrap mode for all tex
2622         glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2623         glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
2624         // Use NEAREST as the default texture filtering mode.
2625         glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2626         glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2627                
2628         if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2629         {
2630             // [Redge]
2631             if (_bHasARBDepthTexture) 
2632             {
2633                 // Allocate the texture image (but pass it no data for now).
2634                 glTexImage2D(_iTextureTarget, 0, GL_DEPTH_COMPONENT, 
2635                              _iWidth, _iHeight, 0, GL_DEPTH_COMPONENT, 
2636                              GL_FLOAT, NULL);
2637             } 
2638             else 
2639             {
2640                 // allocate memory for depth texture
2641                 // Since this is slow, we warn the user in debug mode. (above)
2642                 _pPoorDepthTexture = new unsigned short[_iWidth * _iHeight];
2643                 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16, 
2644                              _iWidth, _iHeight, 0, GL_LUMINANCE, 
2645                              GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2646             }
2647             // [/Redge]
2648         }
2649     }
2650
2651     dbg_printf( "RenderTexture::_InitializeTextures() returning true\n" );
2652     return true;
2653 }
2654
2655
2656 //---------------------------------------------------------------------------
2657 // Function             : RenderTexture::_MaybeCopyBuffer
2658 // Description      : 
2659 //---------------------------------------------------------------------------
2660 /**
2661 * @fn RenderTexture::_MaybeCopyBuffer()
2662 * @brief Does the actual copying for RenderTextures with RT_COPY_TO_TEXTURE
2663 */ 
2664 void RenderTexture::_MaybeCopyBuffer()
2665 {
2666 #ifdef _WIN32
2667     if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2668     {
2669         if (_bIsTexture)
2670         {
2671             glBindTexture(_iTextureTarget, _iTextureID);
2672             glCopyTexSubImage2D(_iTextureTarget, 
2673                                 0, 0, 0, 0, 0, _iWidth, _iHeight);
2674         }
2675         if (_bIsDepthTexture)
2676         {
2677             glBindTexture(_iTextureTarget, _iDepthTextureID);
2678             // HOW TO COPY DEPTH TEXTURE??? Supposedly this just magically works...
2679             // [Redge]
2680             if (_bHasARBDepthTexture) 
2681             {
2682                 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, 
2683                                     _iWidth, _iHeight);
2684             } 
2685             else 
2686             {
2687                 // no 'real' depth texture available, so behavior has to be emulated
2688                 // using glReadPixels (beware, this is (naturally) slow ...)
2689                 glReadPixels(0, 0, _iWidth, _iHeight, GL_DEPTH_COMPONENT, 
2690                              GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2691                 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
2692                              _iWidth, _iHeight, 0, GL_LUMINANCE, 
2693                              GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2694             }
2695             // [/Redge]
2696         }
2697     }
2698     
2699 #elif defined(__MACH__)
2700     if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2701     {
2702        if (_bIsTexture)
2703        {
2704          glBindTexture(_iTextureTarget, _iTextureID);
2705          glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2706        }
2707        if (_bIsDepthTexture)
2708        {
2709          glBindTexture(_iTextureTarget, _iDepthTextureID);
2710          assert(_bHasARBDepthTexture);
2711          glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2712        }
2713     }
2714 #else
2715     if (_bIsTexture)
2716     {
2717       glBindTexture(_iTextureTarget, _iTextureID);
2718       glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2719     }
2720     if (_bIsDepthTexture)
2721     {
2722       glBindTexture(_iTextureTarget, _iDepthTextureID);
2723       assert(_bHasARBDepthTexture);
2724       glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2725     }
2726 #endif
2727
2728 }
2729
2730 //---------------------------------------------------------------------------
2731 // Function             : RenderTexture::_ReleaseBoundBuffers
2732 // Description      : 
2733 //---------------------------------------------------------------------------
2734 /**
2735 * @fn RenderTexture::_ReleaseBoundBuffers()
2736 * @brief Releases buffer bindings on RenderTextures with RT_RENDER_TO_TEXTURE
2737 */ 
2738 bool RenderTexture::_ReleaseBoundBuffers()
2739 {
2740 #ifdef _WIN32
2741     if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2742     {
2743         glBindTexture(_iTextureTarget, _iTextureID);
2744         
2745         // release the pbuffer from the render texture object
2746         if (0 != _iCurrentBoundBuffer && _bIsBufferBound)
2747         {
2748             if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, _iCurrentBoundBuffer))
2749             {
2750                 _wglGetLastError();
2751                 return false;
2752             }
2753             _bIsBufferBound = false;
2754         }
2755     }
2756     
2757     if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2758     {
2759         glBindTexture(_iTextureTarget, _iDepthTextureID);
2760         
2761         // release the pbuffer from the render texture object
2762         if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
2763         {
2764             _wglGetLastError();
2765             return false;
2766         }
2767     }
2768     
2769 #else
2770     // textures can't be bound in Linux
2771 #endif
2772     return true;
2773 }
2774
2775 //---------------------------------------------------------------------------
2776 // Function             : RenderTexture::_MakeCurrent
2777 // Description      : 
2778 //---------------------------------------------------------------------------
2779 /**
2780 * @fn RenderTexture::_MakeCurrent()
2781 * @brief Makes the RenderTexture's context current
2782 */ 
2783 bool RenderTexture::_MakeCurrent() 
2784 {
2785 #ifdef _WIN32
2786     // make the pbuffer's rendering context current.
2787     if (FALSE == wglMakeCurrent( _hDC, _hGLContext))
2788     {
2789         _wglGetLastError();
2790         return false;
2791     }
2792 #elif defined( __MACH__ )
2793     CGLError err;
2794
2795     if (err = CGLSetCurrentContext(_hGLContext))
2796     {
2797         _cglCheckError(err);
2798         return false;
2799     }
2800 #else
2801 static GLXContext last_hGLContext = 0;
2802     if (false == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext)) 
2803     {
2804         dbg_printf( "_MakeCurrent: glXMakeCurrent FAILED! returning false\n");
2805         return false;
2806     }
2807
2808     if ( last_hGLContext != _hGLContext ) {
2809       last_hGLContext = _hGLContext;
2810       dbg_printf( "_MakeCurrent: glXMakeCurrent set to [%p] SUCCESS! returning true\n", _hGLContext );
2811     }
2812 #endif
2813     return true;
2814 }
2815
2816 /////////////////////////////////////////////////////////////////////////////
2817 //
2818 // Begin Deprecated Interface
2819 //
2820 /////////////////////////////////////////////////////////////////////////////
2821
2822 //---------------------------------------------------------------------------
2823 // Function      : RenderTexture::RenderTexture
2824 // Description   : 
2825 //---------------------------------------------------------------------------
2826 /**
2827 * @fn RenderTexture::RenderTexture()
2828 * @brief Constructor.
2829 */ 
2830 RenderTexture::RenderTexture(int width, int height,
2831                                bool bIsTexture /* = true */,
2832                                bool bIsDepthTexture /* = false */)
2833 :   _iWidth(width), 
2834     _iHeight(height), 
2835     _bIsTexture(bIsTexture),
2836     _bIsDepthTexture(bIsDepthTexture),
2837     _bHasARBDepthTexture(true),            // [Redge]
2838     _eUpdateMode(RT_RENDER_TO_TEXTURE),
2839     _bInitialized(false),
2840     _iNumAuxBuffers(0),
2841     _iCurrentBoundBuffer(0),
2842     _iNumDepthBits(0),
2843     _iNumStencilBits(0),
2844     _bFloat(false),
2845     _bDoubleBuffered(false),
2846     _bPowerOf2(true),
2847     _bRectangle(false),
2848     _bMipmap(false),
2849     _bShareObjects(false),
2850     _bCopyContext(false),
2851 #ifdef _WIN32
2852     _hDC(NULL), 
2853     _hGLContext(NULL), 
2854     _hPBuffer(NULL),
2855     _hPreviousDC(0),
2856     _hPreviousContext(0),
2857 #elif defined( __MACH__ )
2858     _hGLContext(NULL),
2859     _hPBuffer(NULL),
2860     _hPreviousContext(NULL),
2861 #else
2862     _pDisplay(NULL),
2863     _hGLContext(NULL),
2864     _hPBuffer(0),
2865     _hPreviousDrawable(0),
2866     _hPreviousContext(0),
2867 #endif
2868     _iTextureTarget(GL_NONE),
2869     _iTextureID(0),
2870     _iDepthTextureID(0),
2871     _pPoorDepthTexture(0) // [Redge]
2872 {
2873     assert(width > 0 && height > 0);
2874 #if defined DEBUG || defined _DEBUG
2875     SG_LOG(SG_GL, SG_ALERT, 
2876             "RenderTexture Warning: Deprecated Contructor interface used.");
2877 #endif
2878     dbg_printf("RenderTexture Warning: Deprecated Contructor interface used.\n");
2879     
2880     _iNumColorBits[0] = _iNumColorBits[1] = 
2881         _iNumColorBits[2] = _iNumColorBits[3] = 0;
2882     _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
2883 }
2884
2885 //------------------------------------------------------------------------------
2886 // Function             : RenderTexture::Initialize
2887 // Description      : 
2888 //------------------------------------------------------------------------------
2889 /**
2890 * @fn RenderTexture::Initialize(bool bShare, bool bDepth, bool bStencil, bool bMipmap, unsigned int iRBits, unsigned int iGBits, unsigned int iBBits, unsigned int iABits);
2891 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
2892
2893 * This function actually does the creation of the p-buffer.  It can only be called 
2894 * once a GL context has already been created.  Note that if the texture is not
2895 * power of two dimensioned, or has more than 8 bits per channel, enabling mipmapping
2896 * will cause an error.
2897 */ 
2898 bool RenderTexture::Initialize(bool         bShare       /* = true */, 
2899                                 bool         bDepth       /* = false */, 
2900                                 bool         bStencil     /* = false */, 
2901                                 bool         bMipmap      /* = false */, 
2902                                 bool         bAnisoFilter /* = false */,
2903                                 unsigned int iRBits       /* = 8 */, 
2904                                 unsigned int iGBits       /* = 8 */, 
2905                                 unsigned int iBBits       /* = 8 */, 
2906                                 unsigned int iABits       /* = 8 */,
2907                                 UpdateMode   updateMode   /* = RT_RENDER_TO_TEXTURE */)
2908 {   
2909     if (0 == _iWidth || 0 == _iHeight)
2910         return false;
2911
2912 #if defined DEBUG || defined _DEBUG
2913     SG_LOG(SG_GL, SG_ALERT, 
2914             "RenderTexture Warning: Deprecated Initialize() interface used.");
2915 #endif   
2916     dbg_printf("RenderTexture Warning: Deprecated Initialize() interface used.\n");
2917
2918     // create a mode string.
2919     string mode = "";
2920     if (bDepth)
2921         mode.append("depth ");
2922     if (bStencil)
2923         mode.append("stencil ");
2924     if (bMipmap)
2925         mode.append("mipmap ");
2926     if (iRBits + iGBits + iBBits + iABits > 0)
2927     {
2928         if (iRBits > 0)
2929             mode.append("r");
2930         if (iGBits > 0)
2931             mode.append("g");
2932         if (iBBits > 0)
2933             mode.append("b");
2934         if (iABits > 0)
2935             mode.append("a");
2936         mode.append("=");
2937         char bitVector[100];
2938         snprintf( bitVector, 100,
2939             "%d%s,%d%s,%d%s,%d%s",
2940             iRBits, (iRBits >= 16) ? "f" : "",
2941             iGBits, (iGBits >= 16) ? "f" : "",
2942             iBBits, (iBBits >= 16) ? "f" : "",
2943             iABits, (iABits >= 16) ? "f" : "");
2944         mode.append(bitVector);
2945         mode.append(" ");
2946     }
2947     if (_bIsTexture)
2948     {
2949         if ((GL_NV_texture_rectangle || GL_EXT_texture_rectangle) && 
2950             ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2951               || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2952             mode.append("texRECT ");
2953         else
2954             mode.append("tex2D ");
2955     }
2956     if (_bIsDepthTexture)
2957     {
2958         if ((GL_NV_texture_rectangle || GL_EXT_texture_rectangle) && 
2959             ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2960               || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2961             mode.append("texRECT ");
2962         else
2963             mode.append("tex2D ");
2964     }
2965     if (RT_COPY_TO_TEXTURE == updateMode)
2966         mode.append("ctt");
2967
2968     _pixelFormatAttribs.clear();
2969     _pbufferAttribs.clear();
2970
2971 #ifdef _WIN32
2972     _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
2973     _pixelFormatAttribs.push_back(true);
2974     _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
2975     _pixelFormatAttribs.push_back(true);
2976     
2977     _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
2978     _pbufferAttribs.push_back(true);
2979 #elif defined( __MACH__ )
2980     //_pixelFormatAttribs.push_back(kCGLPFANoRecovery);
2981     _pixelFormatAttribs.push_back(kCGLPFAAccelerated);
2982     _pixelFormatAttribs.push_back(kCGLPFAWindow);
2983     _pixelFormatAttribs.push_back(kCGLPFAPBuffer);
2984 #else
2985     _pixelFormatAttribs.push_back(GLX_RENDER_TYPE_SGIX);
2986     _pixelFormatAttribs.push_back(GLX_RGBA_BIT_SGIX);
2987     _pixelFormatAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
2988     _pixelFormatAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
2989 #endif
2990
2991     _ParseModeString(mode.c_str(), _pixelFormatAttribs, _pbufferAttribs);
2992
2993 #ifdef _WIN32
2994     _pixelFormatAttribs.push_back(0);
2995     _pbufferAttribs.push_back(0);
2996 #elif defined(__MACH__)
2997     _pixelFormatAttribs.push_back(0);
2998 #else
2999     _pixelFormatAttribs.push_back(None);
3000 #endif
3001
3002     Initialize(_iWidth, _iHeight, bShare);
3003     
3004     return true;
3005 }
3006
3007
3008 //---------------------------------------------------------------------------
3009 // Function             : RenderTexture::Reset
3010 // Description      : 
3011 //---------------------------------------------------------------------------
3012 /**
3013 * @fn RenderTexture::Reset(int iWidth, int iHeight, unsigned int iMode, bool bIsTexture, bool bIsDepthTexture)
3014 * @brief Resets the resolution of the offscreen buffer.
3015
3016 * Causes the buffer to delete itself.  User must call Initialize() again
3017 * before use.
3018 */ 
3019 bool RenderTexture::Reset(int iWidth, int iHeight)
3020 {
3021     SG_LOG(SG_GL, SG_ALERT, 
3022             "RenderTexture Warning: Deprecated Reset() interface used.");
3023             
3024     dbg_printf("RenderTexture Warning: Deprecated Reset(x,y) interface used.\n");
3025
3026     if (!_Invalidate())
3027     {
3028         SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Reset(): failed to invalidate.");
3029         dbg_printf( "RenderTexture::Reset(x,y): failed to invalidate. returning false\n");
3030         return false;
3031     }
3032     _iWidth     = iWidth;
3033     _iHeight    = iHeight;
3034     
3035     dbg_printf( "RenderTexture::Reset(x,y): succeeded. returning true\n");
3036     return true;
3037 }
3038
3039 #if defined( _DEBUG ) && !defined( _WIN32 ) && !defined( __MACH__ )
3040 /* just some DEBUG ONLY code, to show the 'attributes' */
3041
3042 typedef struct tagPXATTS {
3043    int attr;
3044    const char * name;
3045    const char * desc;
3046    int def;
3047 }PXATTS, * PPXATTS;
3048
3049 static PXATTS pxAtts[] = {
3050    { GLX_FBCONFIG_ID, "GLX_FBCONFIG_ID",
3051      "followed by a valid XID that indicates the desired GLX frame buffer configuration. "
3052      "When a GLX_FBCONFIG_ID is specified, all attributes are ignored. The default value is GLX_DONT_CARE.",
3053      GLX_DONT_CARE },
3054    { GLX_BUFFER_SIZE, "GLX_BUFFER_SIZE",
3055    "Must be followed by a nonnegative integer that indicates the desired color index buffer size."
3056    "The smallest index buffer of at least the specified size is preferred. This attribute is ignored if GLX_COLOR_INDEX_BIT is not set "
3057    "in GLX_RENDER_TYPE. The default value is 0.",
3058     0 },
3059    { GLX_LEVEL, "GLX_LEVEL",
3060    "Must be followed by an integer buffer-level specification. This specification is honored exactly."
3061    "Buffer level 0 corresponds to the default frame buffer of the display. "
3062    "Buffer level 1 is the first overlay frame buffer, level two the second overlay frame buffer, and so on."
3063    "Negative buffer levels correspond to underlay frame buffers. The default value is 0.",
3064     0 },
3065    { GLX_DOUBLEBUFFER, "GLX_DOUBLEBUFFER",
3066    "Must be followed by True or False. If True is specified, then only double-buffered frame buffer configurations are considered;"
3067    "if False is specified, then only single-buffered frame buffer configurations are considered. The default value is GLX_DONT_CARE.",
3068     GLX_DONT_CARE },
3069    { GLX_STEREO, "GLX_STEREO",
3070    "Must be followed by True or False. If True is specified, then only stereo frame buffer configurations are considered;"
3071    " if False is specified, then only monoscopic frame buffer configurations are considered. The default value is False.",
3072    False },
3073    { GLX_AUX_BUFFERS, "GLX_AUX_BUFFERS",
3074    "Must be followed by a nonnegative integer that indicates the desired number of auxiliary buffers."
3075    " Configurations with the  smallest number of auxiliary buffers that meet or exceed the specified number are preferred."
3076    " The default value is 0.",
3077    0 },
3078    { GLX_RED_SIZE, "GLX_RED_SIZE",
3079    "must be followed by a nonnegative minimum size",
3080    0 },
3081    { GLX_GREEN_SIZE, "GLX_GREEN_SIZE",
3082    "must be followed by a nonnegative minimum size",
3083    0 },
3084    { GLX_BLUE_SIZE, "GLX_BLUE_SIZE",
3085    "must be followed by a nonnegative minimum size",
3086    0 },
3087    { GLX_ALPHA_SIZE, "GLX_ALPHA_SIZE",
3088    "Each attribute, if present, must be followed by a nonnegative minimum size specification or GLX_DONT_CARE."
3089    " The largest available total RGBA color buffer size (sum of GLX_RED_SIZE, GLX_GREEN_SIZE, GLX_BLUE_SIZE, and GLX_ALPHA_SIZE) "
3090    " of at least the minimum size specified for each color component is preferred. If the requested number of bits for a color "
3091    " component is 0 or GLX_DONT_CARE, it is not considered. The default value for each color component is 0.",
3092    0 },
3093    { GLX_DEPTH_SIZE, "GLX_DEPTH_SIZE",
3094    "Must be followed by a nonnegative minimum size specification. If this value is zero, "
3095    "frame buffer configurations with no depth buffer are preferred."
3096    "Otherwise, the largest available depth buffer of at least the minimum size is preferred. The default value is 0.",
3097    0 },
3098    { GLX_STENCIL_SIZE, "GLX_STENCIL_SIZE",
3099    "Must be followed by a nonnegative integer that indicates the desired number of stencil bitplanes."
3100    "The smallest stencil buffer of at least the specified size is preferred. If the desired value is zero,"
3101    " frame buffer configurations with no stencil buffer are preferred. The default value is 0.",
3102    0 },
3103    { GLX_ACCUM_RED_SIZE, "GLX_ACCUM_RED_SIZE",
3104    "Must be followed by a nonnegative minimum size specification. If this value is zero, "
3105    " frame buffer configurations with no red accumulation buffer are preferred."
3106    " Otherwise, the largest possible red accumulation buffer of at least the minimum size is preferred. The default value is 0.",
3107    0 },
3108    { GLX_ACCUM_GREEN_SIZE, "GLX_ACCUM_GREEN_SIZE",
3109    "Must be followed by a nonnegative minimum size specification. If this value is zero, "
3110    "frame buffer configurations with no green accumulation buffer are preferred. "
3111    "Otherwise, the largest possible green accumulation buffer of at least the minimum size is preferred. The default value is 0.",
3112    0 },
3113    { GLX_ACCUM_BLUE_SIZE, "GLX_ACCUM_BLUE_SIZE",
3114    "Must be followed by a nonnegative minimum size specification. If this value is zero, "
3115    "frame buffer configurations with no blue accumulation buffer are preferred. "
3116    "Otherwise, the largest possible blue accumulation buffer of at least the minimum size is preferred. The default value is 0.",
3117    0 },
3118    { GLX_ACCUM_ALPHA_SIZE, "GLX_ACCUM_ALPHA_SIZE",
3119    "Must be followed by a nonnegative minimum size specification. If this value is zero, "
3120    "frame buffer configurations with no alpha accumulation buffer are preferred. "
3121    "Otherwise, the largest possible alpha accumulation buffer of at least the minimum size is preferred. The default value is 0.",
3122    0 },
3123    { GLX_RENDER_TYPE, "GLX_RENDER_TYPE",
3124    "Must be followed by a mask indicating which OpenGL rendering modes the frame buffer configuration must support. "
3125    "Valid bits are GLX_RGBA_BIT and GLX_COLOR_INDEX_BIT. If the mask is set to GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT, "
3126    "then only frame buffer configurations that can be bound to both RGBA contexts and color index contexts will be considered. "
3127    "The default value is GLX_RGBA_BIT.",
3128     GLX_RGBA_BIT },
3129    { GLX_DRAWABLE_TYPE, "GLX_DRAWABLE_TYPE",
3130    "Must be followed by a mask indicating which GLX drawable types the frame buffer configuration must support. "
3131    "Valid bits are GLX_WINDOW_BIT, GLX_PIXMAP_BIT, and GLX_PBUFFER_BIT. For example, if mask is set to "
3132    "GLX_WINDOW_BIT | GLX_PIXMAP_BIT,  only frame buffer configurations that support both windows and GLX pixmaps "
3133    "will be considered. The default value is GLX_WINDOW_BIT.", 
3134    GLX_WINDOW_BIT },
3135    { GLX_X_RENDERABLE, "GLX_X_RENDERABLE",
3136    "Must be followed by True or False. If True is specified, then only frame buffer configurations that "
3137    "have associated X visuals (and can be used to render to Windows and/or GLX pixmaps) will be considered. "
3138    "The default value is GLX_DONT_CARE. ",
3139    GLX_DONT_CARE },
3140    { GLX_X_VISUAL_TYPE, "GLX_X_VISUAL_TYPE",
3141    "Must be followed by one of GLX_TRUE_COLOR, GLX_DIRECT_COLOR, GLX_PSEUDO_COLOR, GLX_STATIC_COLOR, "
3142    "GLX_GRAY_SCALE, or GLX_STATIC_GRAY, indicating the desired X visual type. "
3143    "Not all frame buffer configurations have an associated X visual. If GLX_DRAWABLE_TYPE is specified in attrib_list and the "
3144    "mask that follows does not have GLX_WINDOW_BIT set, then this value is ignored. It is also ignored if "
3145    "GLX_X_RENDERABLE is specified as False. RGBA rendering may be supported for visuals of type "
3146    "GLX_TRUE_COLOR, GLX_DIRECT_COLOR, GLX_PSEUDO_COLOR, or GLX_STATIC_COLOR, "
3147    "but color index rendering is only supported for visuals of type GLX_PSEUDO_COLOR or GLX_STATIC_COLOR "
3148    "(i.e., single-channel visuals). The tokens GLX_GRAY_SCALE and GLX_STATIC_GRAY will "
3149    "not match current OpenGL enabled visuals, but are included for future use."
3150    "The default value for GLX_X_VISUAL_TYPE is GLX_DONT_CARE.",
3151    GLX_DONT_CARE },
3152    { GLX_CONFIG_CAVEAT, "GLX_CONFIG_CAVEAT",
3153    "Must be followed by one of GLX_NONE, GLX_SLOW_CONFIG, GLX_NON_CONFORMANT_CONFIG. "
3154    "If GLX_NONE is specified, then only frame buffer configurations with "
3155    "no caveats will be considered; if GLX_SLOW_CONFIG is specified, then only slow frame buffer configurations will be considered; if "
3156    "GLX_NON_CONFORMANT_CONFIG is specified, then only nonconformant frame buffer configurations will be considered."
3157    "The default value is GLX_DONT_CARE.",
3158    GLX_DONT_CARE },
3159    { GLX_TRANSPARENT_TYPE, "GLX_TRANSPARENT_TYPE",
3160    "Must be followed by one of GLX_NONE, GLX_TRANSPARENT_RGB, GLX_TRANSPARENT_INDEX. "
3161    "If GLX_NONE is specified, then only opaque frame buffer configurations will be considered; "
3162    "if GLX_TRANSPARENT_RGB is specified, then only transparent frame buffer configurations that support RGBA rendering will be considered; "
3163    "if GLX_TRANSPARENT_INDEX is specified, then only transparent frame buffer configurations that support color index rendering will be considered."
3164    "The default value is GLX_NONE.",
3165     GLX_NONE },
3166    { GLX_TRANSPARENT_INDEX_VALUE, "GLX_TRANSPARENT_INDEX_VALUE",
3167    "Must be followed by an integer value indicating the transparent index value; the value must be between 0 and the maximum "
3168    "frame buffer value for indices. Only frame buffer configurations that use the "
3169    "specified transparent index value will be considered. The default value is GLX_DONT_CARE. "
3170    "This attribute is ignored unless GLX_TRANSPARENT_TYPE is included in attrib_list and specified as GLX_TRANSPARENT_INDEX.",
3171    GLX_DONT_CARE },
3172    { GLX_TRANSPARENT_RED_VALUE, "GLX_TRANSPARENT_RED_VALUE",
3173    "Must be followed by an integer value indicating the transparent red value; the value must be between 0 and the maximum "
3174    "frame buffer value for red. Only frame buffer configurations that use the specified transparent red value will be considered. "
3175    "The default value is GLX_DONT_CARE. This attribute is ignored unless GLX_TRANSPARENT_TYPE is included in "
3176    "attrib_list and specified as GLX_TRANSPARENT_RGB.",
3177    GLX_DONT_CARE },
3178    { GLX_TRANSPARENT_GREEN_VALUE, "GLX_TRANSPARENT_GREEN_VALUE",
3179    "Must be followed by an integer value indicating the transparent green value; the value must be between 0 and the maximum "
3180    "frame buffer value for green. Only frame buffer configurations that use the specified transparent green value will be considered."
3181    "The default value is GLX_DONT_CARE. This attribute is "
3182    "ignored unless GLX_TRANSPARENT_TYPE is included in attrib_list and specified as GLX_TRANSPARENT_RGB.",
3183    GLX_DONT_CARE },
3184    { GLX_TRANSPARENT_BLUE_VALUE, "GLX_TRANSPARENT_BLUE_VALUE",
3185    "Must be followed by an integer value indicating the transparent blue value; the value must be between 0 and the maximum "
3186    "frame buffer value for blue. Only frame buffer configurations that use the specified transparent blue value will be considered."
3187    "The default value is GLX_DONT_CARE. This attribute is ignored unless GLX_TRANSPARENT_TYPE is included in "
3188    "attrib_list and specified as GLX_TRANSPARENT_RGB. ",
3189    GLX_DONT_CARE },
3190    { GLX_TRANSPARENT_ALPHA_VALUE, "GLX_TRANSPARENT_ALPHA_VALUE",
3191    "Must be followed by an integer value indicating the transparent alpha value; the value must be between 0 and the maximum "
3192    "frame buffer value for alpha. Only frame buffer configurations that use the "
3193    "specified transparent alpha value will be considered. The default value is GLX_DONT_CARE.",
3194    GLX_DONT_CARE },
3195    { 0, NULL, NULL, -1 }
3196 };
3197
3198 const char * get_attr_name( int val, int * pdef )
3199 {
3200    PPXATTS pat = &pxAtts[0];
3201    while( pat->name )
3202    {
3203       if ( pat->attr == val ) {
3204          *pdef = pat->def;
3205          return pat->name;
3206       }
3207       pat++;
3208    }
3209    *pdef = -1;
3210    return "VALUE NOT IN LIST";
3211 }
3212
3213 #endif
3214 // eof - RenderTexture.cpp