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