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