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