]> git.mxchange.org Git - simgear.git/blob - simgear/screen/RenderTexture.cpp
make headers include headers they depend on, don't rely on the c(xx)
[simgear.git] / simgear / screen / RenderTexture.cpp
1 // File : RenderTexture.cpp
2 //---------------------------------------------------------------------------
3 // Copyright (c) 2002-2004 Mark J. Harris
4 //---------------------------------------------------------------------------
5 // This software is provided 'as-is', without any express or implied
6 // warranty. In no event will the authors be held liable for any
7 // damages arising from the use of this software.
8 //
9 // Permission is granted to anyone to use this software for any
10 // purpose, including commercial applications, and to alter it and
11 // redistribute it freely, subject to the following restrictions:
12 //
13 // 1. The origin of this software must not be misrepresented; you
14 //    must not claim that you wrote the original software. If you use
15 //    this software in a product, an acknowledgment in the product
16 //    documentation would be appreciated but is not required.
17 //
18 // 2. Altered source versions must be plainly marked as such, and
19 //    must not be misrepresented as being the original software.
20 //
21 // 3. This notice may not be removed or altered from any source
22 //    distribution.
23 //
24 // --------------------------------------------------------------------------
25 // Credits:
26 // Original RenderTexture class: Mark J. Harris
27 // Original Render to Depth Texture support: Thorsten Scheuermann
28 // Linux Copy-to-texture: Eric Werness
29 // OS X: Alexander Powell (someone please help)
30 // Various Bug Fixes: Daniel (Redge) Sperl 
31 //                    Bill Baxter
32 //
33 // --------------------------------------------------------------------------
34 /**
35 * @file RenderTexture.cpp
36
37 * Implementation of class RenderTexture.  A multi-format render to 
38 * texture wrapper.
39 */
40 #pragma warning(disable:4786)
41
42 /*
43  * Changelog:
44  *
45  * Jan. 2005, Removed GLEW dependencies, Erik Hofman, Fred Bouvier
46  * Nov. 2005, Use the simgear logging facility, Erik Hofman
47  * Mar. 2006, Add MAC OS X support, Alexander Powell
48  */
49
50 #ifdef HAVE_CONFIG_H
51 #  include <simgear_config.h>
52 #endif
53
54 #ifdef HAVE_WINDOWS_H
55 #  include <windows.h>
56 #endif
57
58 #include <simgear/compiler.h>
59 #include <simgear/debug/logstream.hxx>
60 #include <simgear/screen/extensions.hxx>
61 #include <simgear/screen/RenderTexture.h>
62
63 #include <stdio.h>
64 #include <stdlib.h>
65 #include <assert.h>
66 #include <stdarg.h>
67
68 #ifdef _WIN32
69 #pragma comment(lib, "gdi32.lib") // required for GetPixelFormat()
70 #endif
71
72 using namespace std;
73
74 #ifdef _WIN32
75 static bool fctPtrInited = false;
76 /* WGL_ARB_pixel_format */
77 static wglChoosePixelFormatARBProc wglChoosePixelFormatARBPtr = 0;
78 static wglGetPixelFormatAttribivARBProc wglGetPixelFormatAttribivARBPtr = 0;
79 /* WGL_ARB_pbuffer */
80 static wglCreatePbufferARBProc wglCreatePbufferARBPtr = 0;
81 static wglGetPbufferDCARBProc wglGetPbufferDCARBPtr = 0;
82 static wglQueryPbufferARBProc wglQueryPbufferARBPtr = 0;
83 static wglReleasePbufferDCARBProc wglReleasePbufferDCARBPtr = 0;
84 static wglDestroyPbufferARBProc wglDestroyPbufferARBPtr = 0;
85 /* WGL_ARB_render_texture */
86 static wglBindTexImageARBProc wglBindTexImageARBPtr = 0;
87 static wglReleaseTexImageARBProc wglReleaseTexImageARBPtr = 0;
88
89 #elif defined( __MACH__ )
90 #else /* !_WIN32 */
91 static bool glXVersion1_3Present = false;
92 static glXChooseFBConfigProc glXChooseFBConfigPtr = 0;
93 static glXCreatePbufferProc glXCreatePbufferPtr = 0;
94 static glXCreateGLXPbufferProc glXCreateGLXPbufferPtr = 0;
95 static glXGetVisualFromFBConfigProc glXGetVisualFromFBConfigPtr = 0;
96 static glXCreateContextProc glXCreateContextPtr = 0;
97 static glXCreateContextWithConfigProc glXCreateContextWithConfigPtr = 0;
98 static glXDestroyPbufferProc glXDestroyPbufferPtr = 0;
99 static glXQueryDrawableProc glXQueryDrawablePtr = 0;
100 static glXQueryGLXPbufferSGIXProc glXQueryGLXPbufferSGIXPtr = 0;
101 #endif
102
103 //---------------------------------------------------------------------------
104 // Function      : RenderTexture::RenderTexture
105 // Description   : 
106 //---------------------------------------------------------------------------
107 /**
108 * @fn RenderTexture::RenderTexture()
109 * @brief Mode-string-based Constructor.
110 */ 
111 RenderTexture::RenderTexture(const char *strMode)
112 :   _iWidth(0), 
113     _iHeight(0), 
114     _bIsTexture(false),
115     _bIsDepthTexture(false),
116     _bHasARBDepthTexture(true),            // [Redge]
117 #if defined(_WIN32) || defined(__MACH__)
118     _eUpdateMode(RT_RENDER_TO_TEXTURE),
119 #else
120     _eUpdateMode(RT_COPY_TO_TEXTURE),
121 #endif
122     _bInitialized(false),
123     _iNumAuxBuffers(0),
124     _bIsBufferBound(false),
125     _iCurrentBoundBuffer(0),
126     _iNumDepthBits(0),
127     _iNumStencilBits(0),
128     _bFloat(false),
129     _bDoubleBuffered(false),
130     _bPowerOf2(true),
131     _bRectangle(false),
132     _bMipmap(false),
133     _bShareObjects(false),
134     _bCopyContext(false),
135 #ifdef _WIN32
136     _hDC(NULL), 
137     _hGLContext(NULL), 
138     _hPBuffer(NULL),
139     _hPreviousDC(0),
140     _hPreviousContext(0),
141 #elif defined( __MACH__ )
142     _hGLContext(NULL),
143     _hPBuffer(0),
144     _hPreviousContext(NULL),
145 #else
146     _pDisplay(NULL),
147     _hGLContext(NULL),
148     _hPBuffer(0),
149     _hPreviousContext(0),
150     _hPreviousDrawable(0),
151 #endif
152     _iTextureTarget(GL_NONE),
153     _iTextureID(0),
154     _iDepthTextureID(0),
155     _pPoorDepthTexture(0) // [Redge]
156 {
157     _iNumColorBits[0] = _iNumColorBits[1] = 
158         _iNumColorBits[2] = _iNumColorBits[3] = 0;
159
160 #ifdef _WIN32
161     _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
162     _pixelFormatAttribs.push_back(true);
163     _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
164     _pixelFormatAttribs.push_back(true);
165     
166     _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
167     _pbufferAttribs.push_back(true);
168 #elif defined( __MACH__ )
169     //_pixelFormatAttribs.push_back(kCGLPFANoRecovery);
170     _pixelFormatAttribs.push_back(kCGLPFAAccelerated);
171     _pixelFormatAttribs.push_back(kCGLPFAWindow);
172     _pixelFormatAttribs.push_back(kCGLPFAPBuffer);
173 #else
174     _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
175     _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
176     _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
177     _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
178 #endif
179
180     _ParseModeString(strMode, _pixelFormatAttribs, _pbufferAttribs);
181
182 #ifdef _WIN32
183     _pixelFormatAttribs.push_back(0);
184     _pbufferAttribs.push_back(0);
185 #elif defined(__MACH__)
186     _pixelFormatAttribs.push_back((CGLPixelFormatAttribute)0);
187     _pbufferAttribs.push_back((CGLPixelFormatAttribute)0);
188 #else
189     _pixelFormatAttribs.push_back(None);
190 #endif
191 }
192
193
194 //---------------------------------------------------------------------------
195 // Function             : RenderTexture::~RenderTexture
196 // Description      : 
197 //---------------------------------------------------------------------------
198 /**
199 * @fn RenderTexture::~RenderTexture()
200 * @brief Destructor.
201 */ 
202 RenderTexture::~RenderTexture()
203 {
204     _Invalidate();
205 }
206
207  //---------------------------------------------------------------------------
208 // Function            : _cglcheckError
209 // Description     :
210 //---------------------------------------------------------------------------
211 /**
212 * @fn _cglCheckError()
213 * @brief Prints to stderr a description when an OS X error is found.
214 */
215 #ifdef __MACH__
216 static void _cglCheckErrorHelper(CGLError err, char *sourceFile, int sourceLine)
217 {
218 # ifdef _DEBUG
219     if (err)
220     {
221        fprintf(stderr, "RenderTexture CGL Error:  %s at (%s,%d)",
222                         CGLErrorString(err), sourceFile, sourceLine);
223     }
224 # endif
225 }
226
227 # define _cglCheckError(err) _cglCheckErrorHelper(err,__FILE__,__LINE__)
228
229 #endif
230
231
232 //---------------------------------------------------------------------------
233 // Function             : _wglGetLastError
234 // Description      : 
235 //---------------------------------------------------------------------------
236 /**
237 * @fn wglGetLastError()
238 * @brief Returns the last windows error generated.
239 */ 
240 #ifdef _WIN32
241 void _wglGetLastError()
242 {
243 #ifdef _DEBUG
244     
245     DWORD err = GetLastError();
246     switch(err)
247     {
248     case ERROR_INVALID_PIXEL_FORMAT:
249         SG_LOG(SG_GL, SG_ALERT, 
250                 "RenderTexture Win32 Error:  ERROR_INVALID_PIXEL_FORMAT");
251         break;
252     case ERROR_NO_SYSTEM_RESOURCES:
253         SG_LOG(SG_GL, SG_ALERT, 
254                 "RenderTexture Win32 Error:  ERROR_NO_SYSTEM_RESOURCES");
255         break;
256     case ERROR_INVALID_DATA:
257         SG_LOG(SG_GL, SG_ALERT, 
258                 "RenderTexture Win32 Error:  ERROR_INVALID_DATA");
259         break;
260     case ERROR_INVALID_WINDOW_HANDLE:
261         SG_LOG(SG_GL, SG_ALERT, 
262                 "RenderTexture Win32 Error:  ERROR_INVALID_WINDOW_HANDLE");
263         break;
264     case ERROR_RESOURCE_TYPE_NOT_FOUND:
265         SG_LOG(SG_GL, SG_ALERT, 
266                 "RenderTexture Win32 Error:  ERROR_RESOURCE_TYPE_NOT_FOUND");
267         break;
268     case ERROR_SUCCESS:
269         // no error
270         break;
271     default:
272         LPVOID lpMsgBuf;
273         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
274             FORMAT_MESSAGE_FROM_SYSTEM | 
275             FORMAT_MESSAGE_IGNORE_INSERTS,
276             NULL,
277             err,
278             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
279             (LPTSTR) &lpMsgBuf,
280             0,
281             NULL);
282         
283         SG_LOG(SG_GL, SG_ALERT, "RenderTexture Win32 Error " <<  err << ":" << lpMsgBuf);
284         LocalFree( lpMsgBuf );
285         break;
286     }
287     SetLastError(0);
288     
289 #endif // _DEBUG
290 }
291 #endif
292
293 //---------------------------------------------------------------------------
294 // Function             : PrintExtensionError
295 // Description      : 
296 //---------------------------------------------------------------------------
297 /**
298 * @fn PrintExtensionError( char* strMsg, ... )
299 * @brief Prints an error about missing OpenGL extensions.
300 */ 
301 void PrintExtensionError( char* strMsg, ... )
302 {
303     SG_LOG(SG_GL, SG_ALERT, 
304             "Error: RenderTexture requires the following unsupported "
305             "OpenGL extensions: ");
306     char strBuffer[512];
307     va_list args;
308     va_start(args, strMsg);
309 #if defined _WIN32 && !defined __CYGWIN__
310     _vsnprintf( strBuffer, 512, strMsg, args );
311 #else
312     vsnprintf( strBuffer, 512, strMsg, args );
313 #endif
314     va_end(args);
315     
316     SG_LOG(SG_GL, SG_ALERT, strMsg);
317 }
318
319
320 //---------------------------------------------------------------------------
321 // Function             : RenderTexture::Initialize
322 // Description      : 
323 //---------------------------------------------------------------------------
324 /**
325 * @fn RenderTexture::Initialize(int width, int height, bool shareObjects, bool copyContext);
326 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
327
328 * This function creates of the p-buffer.  It can only be called once a GL 
329 * context has already been created.  
330 */ 
331 bool RenderTexture::Initialize(int width, int height,
332                                 bool shareObjects       /* = true */,
333                                 bool copyContext        /* = false */)
334 {
335     assert(width > 0 && height > 0);
336
337     _iWidth = width; _iHeight = height;
338     _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
339
340     _bShareObjects = shareObjects;
341     _bCopyContext  = copyContext;
342
343     // Check if this is an NVXX GPU and verify necessary extensions.
344     if (!_VerifyExtensions())
345         return false;
346     
347     if (_bInitialized)
348         _Invalidate();
349
350 #ifdef _WIN32
351     // Get the current context.
352     HDC hdc = wglGetCurrentDC();
353     if (NULL == hdc)
354         _wglGetLastError();
355     HGLRC hglrc = wglGetCurrentContext();
356     if (NULL == hglrc)
357         _wglGetLastError();
358     
359     int iFormat = 0;
360     unsigned int iNumFormats;
361     
362     if (_bCopyContext)
363     {
364         // Get the pixel format for the on-screen window.
365         iFormat = GetPixelFormat(hdc);
366         if (iFormat == 0)
367         {
368             SG_LOG(SG_GL, SG_ALERT, 
369                     "RenderTexture Error: GetPixelFormat() failed.");
370             return false;
371         }
372     }
373     else 
374     {
375         if (!wglChoosePixelFormatARBPtr(hdc, &_pixelFormatAttribs[0], NULL, 
376                                      1, &iFormat, &iNumFormats))
377         {
378             SG_LOG(SG_GL, SG_ALERT, 
379                 "RenderTexture Error: wglChoosePixelFormatARB() failed.");
380             _wglGetLastError();
381             return false;
382         }
383         if ( iNumFormats <= 0 )
384         {
385             SG_LOG(SG_GL, SG_ALERT, 
386                     "RenderTexture Error: Couldn't find a suitable "
387                     "pixel format.");
388             _wglGetLastError();
389             return false;
390         }
391     }
392     
393     // Create the p-buffer.    
394     _hPBuffer = wglCreatePbufferARBPtr(hdc, iFormat, _iWidth, _iHeight, 
395                                     &_pbufferAttribs[0]);
396     if (!_hPBuffer)
397     {
398         SG_LOG(SG_GL, SG_ALERT, 
399                 "RenderTexture Error: wglCreatePbufferARB() failed.");
400         _wglGetLastError();
401         return false;
402     }
403     
404     // Get the device context.
405     _hDC = wglGetPbufferDCARBPtr( _hPBuffer);
406     if ( !_hDC )
407     {
408         SG_LOG(SG_GL, SG_ALERT, 
409                 "RenderTexture Error: wglGetGetPbufferDCARB() failed.");
410         _wglGetLastError();
411         return false;
412     }
413     
414     // Create a gl context for the p-buffer.
415     if (_bCopyContext)
416     {
417         // Let's use the same gl context..
418         // Since the device contexts are compatible (i.e. same pixelformat),
419         // we should be able to use the same gl rendering context.
420         _hGLContext = hglrc;
421     }
422     else
423     {
424         _hGLContext = wglCreateContext( _hDC );
425         if ( !_hGLContext )
426         {
427             SG_LOG(SG_GL, SG_ALERT, 
428                     "RenderTexture Error: wglCreateContext() failed.");
429             _wglGetLastError();
430             return false;
431         }
432     }
433     
434     // Share lists, texture objects, and program objects.
435     if( _bShareObjects )
436     {
437         if( !wglShareLists(hglrc, _hGLContext) )
438         {
439             SG_LOG(SG_GL, SG_ALERT, 
440                     "RenderTexture Error: wglShareLists() failed.");
441             _wglGetLastError();
442             return false;
443         }
444     }
445     
446     // Determine the actual width and height we were able to create.
447     wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
448     wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
449     
450     _bInitialized = true;
451     
452     // get the actual number of bits allocated:
453     int attrib = WGL_RED_BITS_ARB;
454     //int bits[6];
455     int value;
456     _iNumColorBits[0] = 
457         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
458         ? value : 0;
459     attrib = WGL_GREEN_BITS_ARB;
460     _iNumColorBits[1] = 
461         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
462         ? value : 0;
463     attrib = WGL_BLUE_BITS_ARB;
464     _iNumColorBits[2] = 
465         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
466         ? value : 0;
467     attrib = WGL_ALPHA_BITS_ARB;
468     _iNumColorBits[3] = 
469         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
470         ? value : 0; 
471     attrib = WGL_DEPTH_BITS_ARB;
472     _iNumDepthBits = 
473         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
474         ? value : 0; 
475     attrib = WGL_STENCIL_BITS_ARB;
476     _iNumStencilBits = 
477         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
478         ? value : 0; 
479     attrib = WGL_DOUBLE_BUFFER_ARB;
480     _bDoubleBuffered = 
481         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
482         ? (value?true:false) : false; 
483     
484 #if defined(_DEBUG) | defined(DEBUG)
485     SG_LOG(SG_GL, SG_ALERT, "Created a " << _iWidth << "x" << _iHeight <<
486         " RenderTexture with BPP(" <<
487         _iNumColorBits[0] << "," << _iNumColorBits[1] << "," <<
488         _iNumColorBits[2] << "," << _iNumColorBits[3] << ")");
489     if (_iNumDepthBits) SG_LOG(SG_GL, SG_ALERT, " depth=" << _iNumDepthBits);
490     if (_iNumStencilBits) SG_LOG(SG_GL, SG_ALERT, " stencil=" << _iNumStencilBits);
491     if (_bDoubleBuffered) SG_LOG(SG_GL, SG_ALERT, " double buffered");
492 #endif
493
494 #elif defined( __MACH__ )
495     // Get the current context.
496     CGLContextObj hglrc = CGLGetCurrentContext();
497     if (NULL == hglrc)
498         fprintf(stderr, "Couldn't get current context!");
499    
500         CGLPixelFormatObj pixFormat = NULL;
501         long int iNumFormats;
502         CGLError error;
503
504         // Copy the _pixelFormatAttribs into another array to fix
505         // typecast issues
506         CGLPixelFormatAttribute *pixFormatAttribs =
507             (CGLPixelFormatAttribute *)malloc(sizeof(CGLPixelFormatAttribute)
508                                               * _pixelFormatAttribs.size());
509
510         for (unsigned int ii = 0; ii < _pixelFormatAttribs.size(); ii++)
511         {
512             pixFormatAttribs[ii] =
513                                (CGLPixelFormatAttribute)_pixelFormatAttribs[ii];
514         }
515
516         if (error =
517            CGLChoosePixelFormat(&pixFormatAttribs[0], &pixFormat, &iNumFormats))
518         {
519             fprintf(stderr,
520                     "RenderTexture Error: CGLChoosePixelFormat() failed.\n");
521             _cglCheckError(error);
522             return false;
523         }
524         if ( iNumFormats <= 0 )
525         {
526             SG_LOG(SG_GL, SG_ALERT,
527                     "RenderTexture Error: Couldn't find a suitable "
528                     "pixel format.");
529             return false;
530         }
531
532         // Free the copy of the _pixelFormatAttribs array
533         free(pixFormatAttribs);
534    
535        // Create the context.
536        error = CGLCreateContext(pixFormat, (_bShareObjects)
537                 ? CGLGetCurrentContext() : NULL, &_hGLContext);
538        if (error)
539        {
540            fprintf(stderr,
541                    "RenderTexture Error: CGLCreateContext() failed.\n");
542            _cglCheckError(error);
543            return false;
544        }
545        CGLDestroyPixelFormat(pixFormat);
546    
547        // Create the p-buffer.
548        error = CGLCreatePBuffer(_iWidth, _iHeight, (_bRectangle)
549             ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D, GL_RGBA, 0, &_hPBuffer);
550        if (error)
551        {
552            fprintf(stderr,
553                    "RenderTexture Error: CGLCreatePBuffer() failed.\n");
554            _cglCheckError(error);
555            return false;
556        }
557
558        long screen;
559        if (error = CGLGetVirtualScreen(CGLGetCurrentContext(), &screen))
560        {
561            _cglCheckError(error);
562            return false;
563        }
564        if (error = CGLSetPBuffer(_hGLContext, _hPBuffer, 0, 0, screen))
565        {
566            _cglCheckError(error);
567            return false;
568        }
569    
570        // Determine the actual width and height we were able to create.
571        //wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
572        //wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
573    
574        _bInitialized = true;
575    
576        /*
577        // get the actual number of bits allocated:
578        int attrib = WGL_RED_BITS_ARB;
579        //int bits[6];
580        int value;
581        _iNumColorBits[0] =
582             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
583             ? value : 0;
584        attrib = WGL_GREEN_BITS_ARB;
585        _iNumColorBits[1] =
586             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
587             ? value : 0;
588        attrib = WGL_BLUE_BITS_ARB;
589        _iNumColorBits[2] =
590             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
591             ? value : 0;
592        attrib = WGL_ALPHA_BITS_ARB;
593        _iNumColorBits[3] =
594             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
595             ? value : 0;
596        attrib = WGL_DEPTH_BITS_ARB;
597        _iNumDepthBits =
598             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
599             ? value : 0;
600        attrib = WGL_STENCIL_BITS_ARB;
601        _iNumStencilBits =
602             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
603             ? value : 0;
604        attrib = WGL_DOUBLE_BUFFER_ARB;
605        _bDoubleBuffered =
606             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
607              ? (value?true:false) : false;
608        */
609
610 #if defined(_DEBUG) | defined(DEBUG)
611        fprintf(stderr, "Created a %dx%d RenderTexture with BPP(%d, %d, %d, %d)",
612            _iWidth, _iHeight,
613            _iNumColorBits[0], _iNumColorBits[1],
614            _iNumColorBits[2], _iNumColorBits[3]);
615        if (_iNumDepthBits) fprintf(stderr, " depth=%d", _iNumDepthBits);
616        if (_iNumStencilBits) fprintf(stderr, " stencil=%d", _iNumStencilBits);
617        if (_bDoubleBuffered) fprintf(stderr, " double buffered");
618        fprintf(stderr, "\n");
619 #endif
620
621 #else // !_WIN32, !__MACH_
622     _pDisplay = glXGetCurrentDisplay();
623     GLXContext context = glXGetCurrentContext();
624     int screen = DefaultScreen(_pDisplay);
625     XVisualInfo *visInfo;
626     
627     GLXFBConfig *fbConfigs;
628     int nConfigs;
629     
630     fbConfigs = glXChooseFBConfigPtr(_pDisplay, screen, 
631                                       &_pixelFormatAttribs[0], &nConfigs);
632     
633     if (nConfigs == 0 || !fbConfigs) 
634     {
635         SG_LOG(SG_GL, SG_ALERT,
636             "RenderTexture Error: Couldn't find a suitable pixel format.");
637         return false;
638     }
639     
640     // Pick the first returned format that will return a pbuffer
641     if (glXVersion1_3Present)
642     {
643         int pbufAttrib[] = {
644             GLX_PBUFFER_WIDTH,   _iWidth,
645             GLX_PBUFFER_HEIGHT,  _iHeight,
646             GLX_LARGEST_PBUFFER, False,
647             None
648         };
649         for (int i=0;i<nConfigs;i++)
650         {
651             _hPBuffer = glXCreatePbufferPtr(_pDisplay, fbConfigs[i], pbufAttrib);
652             if (_hPBuffer)
653             {
654                 XVisualInfo *visInfo = glXGetVisualFromFBConfigPtr(_pDisplay, fbConfigs[i]);
655
656                 _hGLContext = glXCreateContextPtr(_pDisplay, visInfo,
657                                                _bShareObjects ? context : NULL,
658                                                True);
659                 if (!_hGLContext)
660                 {
661                     return false;
662                 }
663                 XFree( visInfo );
664                 break;
665             }
666         }
667     }
668     else
669     {
670         int iFormat = 0;
671         int iNumFormats;
672         int attrib = 0;
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
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     _bDoubleBuffered(false),
2627     _bFloat(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     _hPreviousContext(0),
2648     _hPreviousDrawable(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 }