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