]> git.mxchange.org Git - simgear.git/blob - simgear/screen/RenderTexture.cpp
Move SGReadFileCallback from model.cxx to public class ModelRegistry
[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     _hPreviousDrawable(0),
150     _hPreviousContext(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 = NULL;
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 #ifdef WIN32
671         int iFormat = 0;
672         int iNumFormats;
673         int attrib = 0;
674 #endif
675         for (int i=0;i<nConfigs;i++)
676         {
677             _hPBuffer = glXCreateGLXPbufferPtr(_pDisplay, fbConfigs[i], 
678                                                _iWidth, _iHeight, NULL);
679             if (_hPBuffer) 
680             {
681                 _hGLContext = glXCreateContextWithConfigPtr(_pDisplay, 
682                                                              fbConfigs[i], 
683                                                              GLX_RGBA_TYPE, 
684                                                              _bShareObjects ? context : NULL, 
685                                                              True);
686                 break;
687             }
688         }
689     }
690     XFree( fbConfigs );
691     
692     if (!_hPBuffer)
693     {
694         SG_LOG(SG_GL, SG_ALERT, 
695                 "RenderTexture Error: glXCreateGLXPbufferPtr() failed.");
696         return false;
697     }
698     
699     if(!_hGLContext)
700     {
701         // Try indirect
702         _hGLContext = glXCreateContext(_pDisplay, visInfo, 
703                                        _bShareObjects ? context : NULL, False);
704         if ( !_hGLContext )
705         {
706             SG_LOG(SG_GL, SG_ALERT, 
707                     "RenderTexture Error: glXCreateContext() failed.");
708             return false;
709         }
710     }
711     
712     if (!glXVersion1_3Present)
713     {
714         glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_WIDTH_SGIX, 
715                                   (GLuint*)&_iWidth);
716         glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_HEIGHT_SGIX, 
717                                   (GLuint*)&_iHeight);
718     }
719     
720     _bInitialized = true;
721     
722     // XXX Query the color format
723     
724 #endif
725
726     
727     // Now that the pbuffer is created, allocate any texture objects needed,
728     // and initialize them (for CTT updates only).  These must be allocated
729     // in the context of the pbuffer, though, or the RT won't work without
730     // wglShareLists.
731 #ifdef _WIN32
732     if (false == wglMakeCurrent( _hDC, _hGLContext))
733     {
734         _wglGetLastError();
735         return false;
736     }
737 #elif defined( __MACH__ )
738     CGLError err;
739     if (err = CGLSetCurrentContext(_hGLContext))
740     {
741         _cglCheckError(err);
742         return false;
743     }
744 #else
745     _hPreviousContext = glXGetCurrentContext();
746     _hPreviousDrawable = glXGetCurrentDrawable();
747     
748     if (False == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext)) 
749     {
750         return false;
751     }
752 #endif
753     
754     bool result = _InitializeTextures();   
755 #ifdef _WIN32
756     BindBuffer(WGL_FRONT_LEFT_ARB);
757     _BindDepthBuffer();
758 #endif
759
760     
761 #ifdef _WIN32 
762     // make the previous rendering context current 
763     if (false == wglMakeCurrent( hdc, hglrc))
764     {
765         _wglGetLastError();
766         return false;
767     }
768 #elif defined( __MACH__ )
769     if (err = CGLSetCurrentContext(_hPreviousContext))
770     {
771         _cglCheckError(err);
772         return false;
773     }
774 #else
775     if (False == glXMakeCurrent(_pDisplay, 
776                                 _hPreviousDrawable, _hPreviousContext))
777     {
778         return false;
779     }
780     if (glXVersion1_3Present)
781     {
782         GLXDrawable draw = glXGetCurrentDrawable();
783         glXQueryDrawablePtr(_pDisplay, draw, GLX_WIDTH, (unsigned int*)&_iWidth);
784         glXQueryDrawablePtr(_pDisplay, draw, GLX_HEIGHT, (unsigned int*)&_iHeight);
785     }
786 #endif
787
788     return result;
789 }
790
791
792 //---------------------------------------------------------------------------
793 // Function             : RenderTexture::_Invalidate
794 // Description      : 
795 //---------------------------------------------------------------------------
796 /**
797 * @fn RenderTexture::_Invalidate()
798 * @brief Returns the pbuffer memory to the graphics device.
799
800 */ 
801 bool RenderTexture::_Invalidate()
802 {
803     _iNumColorBits[0] = _iNumColorBits[1] = 
804         _iNumColorBits[2] = _iNumColorBits[3] = 0;
805     _iNumDepthBits = 0;
806     _iNumStencilBits = 0;
807     
808     if (_bIsTexture)
809         glDeleteTextures(1, &_iTextureID);
810     if (_bIsDepthTexture) 
811     {
812         // [Redge]
813         if (!_bHasARBDepthTexture) delete[] _pPoorDepthTexture;
814         // [/Redge]
815         glDeleteTextures(1, &_iDepthTextureID);
816     }
817     
818 #ifdef _WIN32
819     if ( _hPBuffer )
820     {
821         // Check if we are currently rendering in the pbuffer
822         if (wglGetCurrentContext() == _hGLContext)
823             wglMakeCurrent(0,0);
824         if (!_bCopyContext) 
825             wglDeleteContext( _hGLContext);
826         wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
827         wglDestroyPbufferARBPtr( _hPBuffer );
828         _hPBuffer = 0;
829         return true;
830     }
831 #elif defined( __MACH__ )
832     if ( _hPBuffer )
833     {
834         if (CGLGetCurrentContext() == _hGLContext)
835             CGLSetCurrentContext(NULL);
836         if (!_bCopyContext)
837             CGLDestroyContext(_hGLContext);
838         CGLDestroyPBuffer(_hPBuffer);
839         _hPBuffer = NULL;
840         return true;
841     }
842 #else
843     if ( _hPBuffer )
844     {
845         if(glXGetCurrentContext() == _hGLContext)
846             // XXX I don't know if this is right at all
847             glXMakeCurrent(_pDisplay, _hPBuffer, 0);
848         glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
849         _hPBuffer = 0;
850         return true;
851     }
852 #endif
853
854     // [WVB] do we need to call _ReleaseBoundBuffers() too?
855     return false;
856 }
857
858
859 //---------------------------------------------------------------------------
860 // Function             : RenderTexture::Reset
861 // Description      : 
862 //---------------------------------------------------------------------------
863 /**
864 * @fn RenderTexture::Reset()
865 * @brief Resets the resolution of the offscreen buffer.
866
867 * Causes the buffer to delete itself.  User must call Initialize() again
868 * before use.
869 */ 
870 bool RenderTexture::Reset(const char *strMode, ...)
871 {
872     _iWidth = 0; _iHeight = 0; 
873     _bIsTexture = false; _bIsDepthTexture = false,
874     _bHasARBDepthTexture = true;
875 #if defined(_WIN32) || defined(__MACH__)
876     _eUpdateMode = RT_RENDER_TO_TEXTURE;
877 #else
878     _eUpdateMode = RT_COPY_TO_TEXTURE;
879 #endif
880     _bInitialized = false;
881     _iNumAuxBuffers = 0; 
882     _bIsBufferBound = false;
883     _iCurrentBoundBuffer = 0;
884     _iNumDepthBits = 0; _iNumStencilBits = 0;
885     _bDoubleBuffered = false;
886     _bFloat = false; _bPowerOf2 = true;
887     _bRectangle = false; _bMipmap = false; 
888     _bShareObjects = false; _bCopyContext = false; 
889     _iTextureTarget = GL_NONE; _iTextureID = 0; 
890     _iDepthTextureID = 0;
891     _pPoorDepthTexture = 0;
892     _pixelFormatAttribs.clear();
893     _pbufferAttribs.clear();
894
895     if (IsInitialized() && !_Invalidate())
896     {
897         SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Reset(): failed to invalidate.");
898         return false;
899     }
900     
901     _iNumColorBits[0] = _iNumColorBits[1] = 
902         _iNumColorBits[2] = _iNumColorBits[3] = 0;
903
904 #ifdef _WIN32
905     _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
906     _pixelFormatAttribs.push_back(true);
907     _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
908     _pixelFormatAttribs.push_back(true);
909     
910     _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
911     _pbufferAttribs.push_back(true);
912 #elif defined( __MACH__ )
913     //_pixelFormatAttribs.push_back(kCGLPFANoRecovery);
914     _pixelFormatAttribs.push_back(kCGLPFAAccelerated);
915     _pixelFormatAttribs.push_back(kCGLPFAWindow);
916     _pixelFormatAttribs.push_back(kCGLPFAPBuffer);
917 #else
918     _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
919     _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
920     _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
921     _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
922 #endif
923
924     va_list args;
925     char strBuffer[256];
926     va_start(args,strMode);
927 #if defined _WIN32 && !defined __CYGWIN__
928     _vsnprintf( strBuffer, 256, strMode, args );
929 #else
930     vsnprintf( strBuffer, 256, strMode, args );
931 #endif
932     va_end(args);
933
934     _ParseModeString(strBuffer, _pixelFormatAttribs, _pbufferAttribs);
935
936 #ifdef _WIN32
937     _pixelFormatAttribs.push_back(0);
938     _pbufferAttribs.push_back(0);
939 #elif defined(__MACH__)
940     _pixelFormatAttribs.push_back((CGLPixelFormatAttribute)0);
941 #else
942     _pixelFormatAttribs.push_back(None);
943 #endif
944     return true;
945 }
946
947 //------------------------------------------------------------------------------
948 // Function               : RenderTexture::Resize
949 // Description      : 
950 //------------------------------------------------------------------------------
951 /**
952  * @fn RenderTexture::Resize(int iWidth, int iHeight)
953  * @brief Changes the size of the offscreen buffer.
954  * 
955  * Like Reset() this causes the buffer to delete itself.  
956  * But unlike Reset(), this call re-initializes the RenderTexture.
957  * Note that Resize() will not work after calling Reset(), or before
958  * calling Initialize() the first time.
959  */ 
960 bool RenderTexture::Resize(int iWidth, int iHeight)
961 {
962     if (!_bInitialized) {
963         SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): must Initialize() first.");
964         return false;
965     }
966     if (iWidth == _iWidth && iHeight == _iHeight) {
967         return true;
968     }
969     
970     // Do same basic work as _Invalidate, but don't reset all our flags
971     if (_bIsTexture)
972         glDeleteTextures(1, &_iTextureID);
973     if (_bIsDepthTexture)
974         glDeleteTextures(1, &_iDepthTextureID);
975 #ifdef _WIN32
976     if ( _hPBuffer )
977     {
978         // Check if we are currently rendering in the pbuffer
979         if (wglGetCurrentContext() == _hGLContext)
980             wglMakeCurrent(0,0);
981         if (!_bCopyContext) 
982             wglDeleteContext( _hGLContext);
983         wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
984         wglDestroyPbufferARBPtr( _hPBuffer );
985         _hPBuffer = 0;
986         return true;
987     }
988 #elif defined( __MACH__ )
989     if ( _hPBuffer )
990     {
991         if (CGLGetCurrentContext() == _hGLContext)
992             CGLSetCurrentContext(NULL);
993         if (!_bCopyContext)
994             CGLDestroyContext(_hGLContext);
995         CGLDestroyPBuffer(_hPBuffer);
996         _hPBuffer = NULL;
997         return true;
998     }
999 #else
1000     if ( _hPBuffer )
1001     {
1002         if(glXGetCurrentContext() == _hGLContext)
1003             // XXX I don't know if this is right at all
1004             glXMakeCurrent(_pDisplay, _hPBuffer, 0);
1005         glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
1006         _hPBuffer = 0;
1007     }
1008 #endif
1009     else {
1010         SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): failed to resize.");
1011         return false;
1012     }
1013     _bInitialized = false;
1014     return Initialize(iWidth, iHeight, _bShareObjects, _bCopyContext);
1015 }
1016
1017 //---------------------------------------------------------------------------
1018 // Function             : RenderTexture::BeginCapture
1019 // Description      : 
1020 //---------------------------------------------------------------------------
1021 /**
1022 * @fn RenderTexture::BeginCapture()
1023 * @brief Activates rendering to the RenderTexture.
1024 */ 
1025 bool RenderTexture::BeginCapture()
1026 {
1027     if (!_bInitialized)
1028     {
1029         SG_LOG(SG_GL, SG_ALERT, 
1030                 "RenderTexture::BeginCapture(): Texture is not initialized!");
1031         return false;
1032     }
1033 #ifdef _WIN32
1034     // cache the current context so we can reset it when EndCapture() is called.
1035     _hPreviousDC      = wglGetCurrentDC();
1036     if (NULL == _hPreviousDC)
1037         _wglGetLastError();
1038     _hPreviousContext = wglGetCurrentContext();
1039     if (NULL == _hPreviousContext)
1040         _wglGetLastError();
1041 #elif defined( __MACH__ )
1042     _hPreviousContext = CGLGetCurrentContext();
1043 #else
1044     _hPreviousContext = glXGetCurrentContext();
1045     _hPreviousDrawable = glXGetCurrentDrawable();
1046 #endif
1047
1048     _ReleaseBoundBuffers();
1049
1050     return _MakeCurrent();
1051 }
1052
1053
1054 //---------------------------------------------------------------------------
1055 // Function             : RenderTexture::EndCapture
1056 // Description      : 
1057 //---------------------------------------------------------------------------
1058 /**
1059 * @fn RenderTexture::EndCapture()
1060 * @brief Ends rendering to the RenderTexture.
1061 */ 
1062 bool RenderTexture::EndCapture()
1063 {    
1064     if (!_bInitialized)
1065     {
1066         SG_LOG(SG_GL, SG_ALERT, 
1067                 "RenderTexture::EndCapture() : Texture is not initialized!");
1068         return false;
1069     }
1070
1071     glFlush();  // Added by a-lex
1072
1073     _MaybeCopyBuffer();
1074
1075 #ifdef _WIN32
1076     // make the previous rendering context current 
1077     if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
1078     {
1079         _wglGetLastError();
1080         return false;
1081     }
1082 #elif defined( __MACH__ )
1083     CGLError err;
1084     if (err = CGLSetCurrentContext(_hPreviousContext))
1085     {
1086             _cglCheckError(err);
1087             return false;
1088     }
1089 #else
1090     if (False == glXMakeCurrent(_pDisplay, _hPreviousDrawable, 
1091                                 _hPreviousContext))
1092     {
1093         return false;
1094     }
1095 #endif
1096
1097     // rebind the textures to a buffers for RTT
1098     BindBuffer(_iCurrentBoundBuffer);
1099     _BindDepthBuffer();
1100
1101     return true;
1102 }
1103
1104 //---------------------------------------------------------------------------
1105 // Function               : RenderTexture::BeginCapture(RenderTexture*)
1106 // Description      : 
1107 //---------------------------------------------------------------------------
1108 /**
1109  * @fn RenderTexture::BeginCapture(RenderTexture* other)
1110  * @brief Ends capture of 'other', begins capture on 'this'
1111  *
1112  * When performing a series of operations where you modify one texture after 
1113  * another, it is more efficient to use this method instead of the equivalent
1114  * 'EndCapture'/'BeginCapture' pair.  This method switches directly to the 
1115  * new context rather than changing to the default context, and then to the 
1116  * new context.
1117  *
1118  * RenderTexture doesn't have any mechanism for determining if 
1119  * 'current' really is currently active, so no error will be thrown 
1120  * if it is not. 
1121  */ 
1122 bool RenderTexture::BeginCapture(RenderTexture* current)
1123 {
1124     // bool bContextReset = false;
1125     
1126     if (current == this) {
1127         return true; // no switch necessary
1128     }
1129     if (!current) {
1130         // treat as normal Begin if current is 0.
1131         return BeginCapture();
1132     }
1133     if (!_bInitialized)
1134     {
1135         SG_LOG(SG_GL, SG_ALERT, 
1136             "RenderTexture::BeginCapture(RenderTexture*): Texture is not initialized!");
1137         return false;
1138     }
1139     if (!current->_bInitialized)
1140     {
1141         SG_LOG(SG_GL, SG_ALERT, 
1142             "RenderTexture::BeginCapture(RenderTexture): 'current' texture is not initialized!");
1143         return false;
1144     }
1145     
1146     // Sync current pbuffer with its CTT texture if necessary
1147     current->_MaybeCopyBuffer();
1148
1149     // pass along the previous context so we can reset it when 
1150     // EndCapture() is called.
1151 #ifdef _WIN32
1152     _hPreviousDC      = current->_hPreviousDC;
1153     if (NULL == _hPreviousDC)
1154         _wglGetLastError();
1155     _hPreviousContext = current->_hPreviousContext;
1156     if (NULL == _hPreviousContext)
1157         _wglGetLastError();
1158 #elif defined( __MACH__ )
1159     _hPreviousContext = current->_hPreviousContext;
1160 #else
1161     _hPreviousContext = current->_hPreviousContext;
1162     _hPreviousDrawable = current->_hPreviousDrawable;
1163 #endif    
1164
1165     // Unbind textures before making context current
1166     if (!_ReleaseBoundBuffers()) 
1167       return false;
1168
1169     // Make the pbuffer context current
1170     if (!_MakeCurrent())
1171         return false;
1172
1173     // Rebind buffers of initial RenderTexture
1174     current->BindBuffer(_iCurrentBoundBuffer);
1175     current->_BindDepthBuffer();
1176     
1177     return true;
1178 }
1179
1180
1181
1182 //---------------------------------------------------------------------------
1183 // Function             : RenderTexture::Bind
1184 // Description      : 
1185 //---------------------------------------------------------------------------
1186 /**
1187 * @fn RenderTexture::Bind()
1188 * @brief Binds RGB texture.
1189 */ 
1190 void RenderTexture::Bind() const 
1191
1192     if (_bInitialized && _bIsTexture) 
1193     {
1194         glBindTexture(_iTextureTarget, _iTextureID);
1195     }    
1196 }
1197
1198
1199 //---------------------------------------------------------------------------
1200 // Function             : RenderTexture::BindDepth
1201 // Description      : 
1202 //---------------------------------------------------------------------------
1203 /**
1204 * @fn RenderTexture::BindDepth()
1205 * @brief Binds depth texture.
1206 */ 
1207 void RenderTexture::BindDepth() const 
1208
1209     if (_bInitialized && _bIsDepthTexture) 
1210     {
1211         glBindTexture(_iTextureTarget, _iDepthTextureID); 
1212     }
1213 }
1214
1215
1216 //---------------------------------------------------------------------------
1217 // Function             : RenderTexture::BindBuffer
1218 // Description      : 
1219 //---------------------------------------------------------------------------
1220 /**
1221 * @fn RenderTexture::BindBuffer()
1222 * @brief Associate the RTT texture id with 'iBuffer' (e.g. WGL_FRONT_LEFT_ARB)
1223 */ 
1224 bool RenderTexture::BindBuffer( int iBuffer )
1225
1226     // Must bind the texture too
1227     if (_bInitialized && _bIsTexture) 
1228     {
1229         glBindTexture(_iTextureTarget, _iTextureID);
1230         
1231 #ifdef _WIN32
1232         if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
1233             (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
1234         {
1235             if (FALSE == wglBindTexImageARBPtr(_hPBuffer, iBuffer))
1236             {
1237                 //  WVB: WGL API considers binding twice to the same buffer
1238                 //  to be an error.  But we don't want to 
1239                 //_wglGetLastError();
1240                 //return false;
1241                 SetLastError(0);
1242             }
1243             _bIsBufferBound = true;
1244             _iCurrentBoundBuffer = iBuffer;
1245         }
1246 #elif defined(__MACH__)
1247     if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
1248          (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
1249     {
1250         CGLError err;
1251         if (err=CGLTexImagePBuffer(CGLGetCurrentContext(), _hPBuffer, iBuffer))
1252         {
1253             _cglCheckError(err);
1254         }
1255         _bIsBufferBound = true;
1256         _iCurrentBoundBuffer = iBuffer;
1257      }
1258 #endif
1259     }    
1260     return true;
1261 }
1262
1263
1264 //---------------------------------------------------------------------------
1265 // Function             : RenderTexture::BindDepthBuffer
1266 // Description      : 
1267 //---------------------------------------------------------------------------
1268 /**
1269 * @fn RenderTexture::_BindDepthBuffer()
1270 * @brief Associate the RTT depth texture id with the depth buffer
1271 */ 
1272 bool RenderTexture::_BindDepthBuffer() const
1273 {
1274 #ifdef WIN32
1275     if (_bInitialized && _bIsDepthTexture && 
1276         RT_RENDER_TO_TEXTURE == _eUpdateMode)
1277     {
1278         glBindTexture(_iTextureTarget, _iDepthTextureID);
1279         if (FALSE == wglBindTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1280         {
1281             _wglGetLastError();
1282             return false;
1283         }
1284     }
1285 #elif defined(__MACH__)
1286     if (_bInitialized && _bIsDepthTexture &&
1287         RT_RENDER_TO_TEXTURE == _eUpdateMode)
1288     {
1289         glBindTexture(_iTextureTarget, _iDepthTextureID);
1290         //if (FALSE == CGLTexImagePBuffer(<#CGLContextObj ctx#>,<#CGLPBufferObj pbuffer#>,<#unsigned long source#>)(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1291         //{
1292         //    _wglGetLastError();
1293         //    return false;
1294         //}
1295     }
1296 #endif
1297     return true;
1298 }
1299
1300 //---------------------------------------------------------------------------
1301 // Function             : RenderTexture::_ParseModeString
1302 // Description      : 
1303 //---------------------------------------------------------------------------
1304 /**
1305 * @fn RenderTexture::_ParseModeString()
1306 * @brief Parses the user-specified mode string for RenderTexture parameters.
1307 */ 
1308 void RenderTexture::_ParseModeString(const char *modeString, 
1309                                      vector<int> &pfAttribs, 
1310                                      vector<int> &pbAttribs)
1311 {
1312     if (!modeString || strcmp(modeString, "") == 0)
1313         return;
1314
1315         _iNumComponents = 0;
1316 #if defined(_WIN32) || defined(__MACH__)
1317     _eUpdateMode = RT_RENDER_TO_TEXTURE;
1318 #else
1319     _eUpdateMode = RT_COPY_TO_TEXTURE;
1320 #endif
1321     
1322     int  iDepthBits = 0;
1323     bool bHasStencil = false;
1324     bool bBind2D   = false;
1325     bool bBindRECT = false;
1326     bool bBindCUBE = false;
1327     
1328     char *mode = strdup(modeString);
1329     
1330
1331     vector<string> tokens;
1332     char *buf = strtok(mode, " ");
1333     while (buf != NULL)
1334     {
1335         tokens.push_back(buf);
1336         buf = strtok(NULL, " ");
1337     }
1338     free(mode);
1339     for (unsigned int i = 0; i < tokens.size(); i++)
1340     {
1341         string token = tokens[i];
1342
1343         KeyVal kv = _GetKeyValuePair(token);
1344         
1345         
1346         if (kv.first == "rgb" && (_iNumComponents <= 1))
1347         {           
1348             if (kv.second.find("f") != kv.second.npos)
1349                 _bFloat = true;
1350
1351             vector<int> bitVec = _ParseBitVector(kv.second);
1352
1353             if (bitVec.size() < 3) // expand the scalar to a vector
1354             {
1355                 bitVec.push_back(bitVec[0]);
1356                 bitVec.push_back(bitVec[0]);
1357             }
1358
1359 #ifdef _WIN32
1360             pfAttribs.push_back(WGL_RED_BITS_ARB);
1361             pfAttribs.push_back(bitVec[0]);
1362             pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1363             pfAttribs.push_back(bitVec[1]);
1364             pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1365             pfAttribs.push_back(bitVec[2]);
1366 #elif defined( __MACH__ )
1367 # if 0
1368             pfAttribs.push_back(AGL_RED_SIZE);
1369             pfAttribs.push_back(bitVec[0]);
1370             pfAttribs.push_back(AGL_GREEN_SIZE);
1371             pfAttribs.push_back(bitVec[1]);
1372             pfAttribs.push_back(AGL_BLUE_SIZE);
1373             pfAttribs.push_back(bitVec[2]);
1374 # else
1375             pfAttribs.push_back(kCGLPFAColorSize);
1376             pfAttribs.push_back(bitVec[0] + bitVec[1] + bitVec[2]);
1377 # endif
1378 #else
1379             pfAttribs.push_back(GLX_RED_SIZE);
1380             pfAttribs.push_back(bitVec[0]);
1381             pfAttribs.push_back(GLX_GREEN_SIZE);
1382             pfAttribs.push_back(bitVec[1]);
1383             pfAttribs.push_back(GLX_BLUE_SIZE);
1384             pfAttribs.push_back(bitVec[2]);
1385 #endif
1386             _iNumComponents += 3;
1387             continue;
1388         }
1389                 else if (kv.first == "rgb") 
1390             SG_LOG(SG_GL, SG_ALERT, 
1391                     "RenderTexture Warning: mistake in components definition "
1392                     "(rgb + " << _iNumComponents << ").");
1393         
1394         if (kv.first == "rgba" && (_iNumComponents == 0))
1395         {
1396             if (kv.second.find("f") != kv.second.npos)
1397                 _bFloat = true;
1398
1399             vector<int> bitVec = _ParseBitVector(kv.second);
1400
1401             if (bitVec.size() < 4) // expand the scalar to a vector
1402             {
1403                 bitVec.push_back(bitVec[0]);
1404                 bitVec.push_back(bitVec[0]);
1405                 bitVec.push_back(bitVec[0]);
1406             }
1407
1408 #ifdef _WIN32
1409             pfAttribs.push_back(WGL_RED_BITS_ARB);
1410             pfAttribs.push_back(bitVec[0]);
1411             pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1412             pfAttribs.push_back(bitVec[1]);
1413             pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1414             pfAttribs.push_back(bitVec[2]);
1415             pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1416             pfAttribs.push_back(bitVec[3]);
1417 #elif defined( __MACH__ )
1418 # if 0 
1419             pfAttribs.push_back(AGL_RED_SIZE);
1420             pfAttribs.push_back(bitVec[0]);
1421             pfAttribs.push_back(AGL_GREEN_SIZE);
1422             pfAttribs.push_back(bitVec[1]);
1423             pfAttribs.push_back(AGL_BLUE_SIZE);
1424             pfAttribs.push_back(bitVec[2]);
1425             pfAttribs.push_back(AGL_ALPHA_SIZE);
1426             pfAttribs.push_back(bitVec[3]);
1427 # else
1428             pfAttribs.push_back(kCGLPFAColorSize);
1429             pfAttribs.push_back(bitVec[0] + bitVec[1] + bitVec[2] + bitVec[3]);
1430             //pfAttribs.push_back(kCGLPFAAlphaSize);
1431             //pfAttribs.push_back(bitVec[3]);
1432             // printf("Color size: %d\n", bitVec[0] + bitVec[1] + bitVec[2] + bitVec[3]);
1433
1434 # endif
1435 #else
1436             pfAttribs.push_back(GLX_RED_SIZE);
1437             pfAttribs.push_back(bitVec[0]);
1438             pfAttribs.push_back(GLX_GREEN_SIZE);
1439             pfAttribs.push_back(bitVec[1]);
1440             pfAttribs.push_back(GLX_BLUE_SIZE);
1441             pfAttribs.push_back(bitVec[2]);
1442             pfAttribs.push_back(GLX_ALPHA_SIZE);
1443             pfAttribs.push_back(bitVec[3]);
1444 #endif
1445             _iNumComponents = 4;
1446             continue;
1447         }
1448                 else if (kv.first == "rgba") 
1449             SG_LOG(SG_GL, SG_ALERT, 
1450                     "RenderTexture Warning: mistake in components definition "
1451                     "(rgba + " << _iNumComponents << ").");
1452         
1453         if (kv.first == "r" && (_iNumComponents <= 1))
1454         {
1455             if (kv.second.find("f") != kv.second.npos)
1456                 _bFloat = true;
1457
1458             vector<int> bitVec = _ParseBitVector(kv.second);
1459
1460 #ifdef _WIN32
1461             pfAttribs.push_back(WGL_RED_BITS_ARB);
1462             pfAttribs.push_back(bitVec[0]);
1463 #elif defined( __MACH__ )
1464 # if 0
1465             pfAttribs.push_back(AGL_RED_SIZE);
1466             pfAttribs.push_back(bitVec[0]);
1467 # else
1468             pfAttribs.push_back(kCGLPFAColorSize);
1469             pfAttribs.push_back(bitVec[0]);
1470 # endif
1471 #else
1472             pfAttribs.push_back(GLX_RED_SIZE);
1473             pfAttribs.push_back(bitVec[0]);
1474 #endif
1475                         _iNumComponents++;
1476             continue;
1477         }
1478         else if (kv.first == "r") 
1479             SG_LOG(SG_GL, SG_ALERT, 
1480                     "RenderTexture Warning: mistake in components definition "
1481                     "(r + " << _iNumComponents << ").");
1482
1483         if (kv.first == "rg" && (_iNumComponents <= 1))
1484         {
1485             if (kv.second.find("f") != kv.second.npos)
1486                 _bFloat = true;
1487
1488             vector<int> bitVec = _ParseBitVector(kv.second);
1489
1490             if (bitVec.size() < 2) // expand the scalar to a vector
1491             {
1492                 bitVec.push_back(bitVec[0]);
1493             }
1494
1495 #ifdef _WIN32
1496             pfAttribs.push_back(WGL_RED_BITS_ARB);
1497             pfAttribs.push_back(bitVec[0]);
1498             pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1499             pfAttribs.push_back(bitVec[1]);
1500 #elif defined( __MACH__ )
1501 # if 0
1502             pfAttribs.push_back(AGL_RED_SIZE);
1503             pfAttribs.push_back(bitVec[0]);
1504             pfAttribs.push_back(AGL_GREEN_SIZE);
1505             pfAttribs.push_back(bitVec[1]);
1506 # else
1507             pfAttribs.push_back(kCGLPFAColorSize);
1508             pfAttribs.push_back(bitVec[0] + bitVec[1]);
1509 # endif
1510 #else
1511             pfAttribs.push_back(GLX_RED_SIZE);
1512             pfAttribs.push_back(bitVec[0]);
1513             pfAttribs.push_back(GLX_GREEN_SIZE);
1514             pfAttribs.push_back(bitVec[1]);
1515 #endif
1516                         _iNumComponents += 2;
1517             continue;
1518         }
1519                 else if (kv.first == "rg") 
1520             SG_LOG(SG_GL, SG_ALERT, 
1521                     "RenderTexture Warning: mistake in components definition "
1522                     "(rg + " << _iNumComponents << ").");
1523
1524         if (kv.first == "depth")
1525         {
1526             if (kv.second == "")
1527                 iDepthBits = 24;
1528             else
1529                 iDepthBits = strtol(kv.second.c_str(), 0, 10);
1530             continue;
1531         }
1532
1533         if (kv.first == "stencil")
1534         {
1535             bHasStencil = true;
1536 #ifdef _WIN32
1537             pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1538 #elif defined( __MACH__ )
1539 # if 0
1540             pfAttribs.push_back(AGL_STENCIL_SIZE);
1541 # else
1542             pfAttribs.push_back(kCGLPFAStencilSize);
1543 # endif
1544 #else
1545             pfAttribs.push_back(GLX_STENCIL_SIZE);
1546 #endif
1547             if (kv.second == "")
1548                 pfAttribs.push_back(8);
1549             else
1550                 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1551             continue;
1552         }
1553
1554         if (kv.first == "samples")
1555         {
1556 #ifdef _WIN32
1557             pfAttribs.push_back(WGL_SAMPLE_BUFFERS_ARB);
1558             pfAttribs.push_back(1);
1559             pfAttribs.push_back(WGL_SAMPLES_ARB);
1560             pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1561 #elif defined( __MACH__ )
1562 # if 0
1563             pfAttribs.push_back(AGL_SAMPLE_BUFFERS_ARB);
1564             pfAttribs.push_back(1);
1565             pfAttribs.push_back(AGL_SAMPLES_ARB);
1566 # else
1567             pfAttribs.push_back(kCGLPFAMultisample);
1568             pfAttribs.push_back(kCGLPFASamples);
1569 # endif
1570             pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1571 #else
1572             pfAttribs.push_back(GLX_SAMPLE_BUFFERS_ARB);
1573             pfAttribs.push_back(1);
1574             pfAttribs.push_back(GLX_SAMPLES_ARB);
1575             pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1576 #endif
1577             continue;
1578
1579         }
1580
1581         if (kv.first == "doublebuffer" || kv.first == "double")
1582         {
1583 #ifdef _WIN32
1584             pfAttribs.push_back(WGL_DOUBLE_BUFFER_ARB);
1585             pfAttribs.push_back(true);
1586 #elif defined( __MACH__ )
1587 # if 0
1588             pfAttribs.push_back(AGL_DOUBLEBUFFER);
1589             pfAttribs.push_back(True);
1590 # else
1591             pfAttribs.push_back(kCGLPFADoubleBuffer);
1592 # endif
1593 #else
1594             pfAttribs.push_back(GLX_DOUBLEBUFFER);
1595             pfAttribs.push_back(True);
1596 #endif
1597             continue;
1598         }  
1599         
1600         if (kv.first == "aux")
1601         {
1602 #ifdef _WIN32
1603             pfAttribs.push_back(WGL_AUX_BUFFERS_ARB);
1604 #elif defined( __MACH__ )
1605 # if 0
1606             pfAttribs.push_back(AGL_AUX_BUFFERS);
1607 # else
1608             pfAttribs.push_back(kCGLPFAAuxBuffers);
1609 # endif
1610 #else
1611             pfAttribs.push_back(GLX_AUX_BUFFERS);
1612 #endif
1613             if (kv.second == "")
1614                 pfAttribs.push_back(0);
1615             else
1616                 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1617             continue;
1618         }
1619         
1620         if (token.find("tex") == 0)
1621         {            
1622             _bIsTexture = true;
1623             
1624             if ((kv.first == "texRECT") && (GL_NV_texture_rectangle ||
1625                                             GL_EXT_texture_rectangle))
1626             {
1627                 _bRectangle = true;
1628                 bBindRECT = true;
1629             }
1630             else if (kv.first == "texCUBE")
1631             {
1632                 bBindCUBE = true;
1633             }
1634             else
1635             {
1636                 bBind2D = true;
1637             }
1638
1639             continue;
1640         }
1641
1642         if (token.find("depthTex") == 0)
1643         {
1644             _bIsDepthTexture = true;
1645             
1646             if ((kv.first == "depthTexRECT") && (GL_NV_texture_rectangle ||
1647                                                  GL_EXT_texture_rectangle))
1648             {
1649                 _bRectangle = true;
1650                 bBindRECT = true;
1651             }
1652             else if (kv.first == "depthTexCUBE")
1653             {
1654                 bBindCUBE = true;
1655             }
1656             else
1657             {
1658                 bBind2D = true;
1659             }
1660
1661             continue;
1662         }
1663
1664         if (kv.first == "mipmap")
1665         {
1666             _bMipmap = true;    
1667             continue;
1668         }
1669
1670         if (kv.first == "rtt")
1671         {
1672             _eUpdateMode = RT_RENDER_TO_TEXTURE;
1673             continue;
1674         }
1675         
1676         if (kv.first == "ctt")
1677         {
1678             _eUpdateMode = RT_COPY_TO_TEXTURE;
1679             continue;
1680         }
1681
1682         SG_LOG(SG_GL, SG_ALERT, 
1683                 "RenderTexture Error: Unknown pbuffer attribute: " <<
1684                 token.c_str());
1685     }
1686
1687     // Processing of some options must be last because of interactions.
1688
1689     // Check for inconsistent texture targets
1690     if (_bIsTexture && _bIsDepthTexture && !(bBind2D ^ bBindRECT ^ bBindCUBE))
1691     {
1692         SG_LOG(SG_GL, SG_ALERT,
1693                 "RenderTexture Warning: Depth and Color texture targets "
1694                 "should match.");
1695     }
1696
1697     // Apply default bit format if none specified
1698 #ifdef _WIN32
1699     if (0 == _iNumComponents)
1700     {
1701         pfAttribs.push_back(WGL_RED_BITS_ARB);
1702         pfAttribs.push_back(8);
1703         pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1704         pfAttribs.push_back(8);
1705         pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1706         pfAttribs.push_back(8);
1707         pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1708         pfAttribs.push_back(8);
1709         _iNumComponents = 4;
1710     }
1711 #endif
1712
1713     // Depth bits
1714     if (_bIsDepthTexture && !iDepthBits)
1715         iDepthBits = 24;
1716
1717 #ifdef _WIN32
1718     pfAttribs.push_back(WGL_DEPTH_BITS_ARB);
1719 #elif defined( __MACH__ )
1720 # if 0
1721     pfAttribs.push_back(AGL_DEPTH_SIZE);
1722 # else
1723     pfAttribs.push_back(kCGLPFADepthSize);
1724 # endif
1725 #else
1726     pfAttribs.push_back(GLX_DEPTH_SIZE);
1727 #endif
1728     pfAttribs.push_back(iDepthBits); // default
1729     
1730     if (!bHasStencil)
1731     {
1732 #ifdef _WIN32
1733         pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1734         pfAttribs.push_back(0);
1735 #elif defined( __MACH__ )
1736 # if 0
1737         pfAttribs.push_back(AGL_STENCIL_SIZE);
1738 # else
1739         pfAttribs.push_back(kCGLPFAStencilSize);
1740 # endif
1741         pfAttribs.push_back(0);
1742 #else
1743         pfAttribs.push_back(GLX_STENCIL_SIZE);
1744         pfAttribs.push_back(0);
1745 #endif
1746
1747     }
1748     if (_iNumComponents < 4)
1749     {
1750         // Can't do this right now -- on NVIDIA drivers, currently get 
1751         // a non-functioning pbuffer if ALPHA_BITS=0 and 
1752         // WGL_BIND_TO_TEXTURE_RGB_ARB=true
1753         
1754         //pfAttribs.push_back(WGL_ALPHA_BITS_ARB); 
1755         //pfAttribs.push_back(0);
1756     }
1757
1758 #ifdef _WIN32
1759     if (!WGL_NV_render_depth_texture && _bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1760     {
1761 #if defined(DEBUG) || defined(_DEBUG)
1762         SG_LOG(SG_GL, SG_ALERT, "RenderTexture Warning: No support found for "
1763                 "render to depth texture.");
1764 #endif
1765         _bIsDepthTexture = false;
1766     }
1767 #endif
1768     
1769     if ((_bIsTexture || _bIsDepthTexture) && 
1770         (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1771     {
1772 #ifdef _WIN32                   
1773         if (bBindRECT)
1774         {
1775             pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1776             pbAttribs.push_back(WGL_TEXTURE_RECTANGLE_NV);
1777         }
1778         else if (bBindCUBE)
1779         {
1780             pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1781             pbAttribs.push_back(WGL_TEXTURE_CUBE_MAP_ARB);
1782         }
1783         else if (bBind2D)
1784         {
1785             pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1786             pbAttribs.push_back(WGL_TEXTURE_2D_ARB);
1787         }
1788             
1789         if (_bMipmap)
1790         {
1791             pbAttribs.push_back(WGL_MIPMAP_TEXTURE_ARB);
1792             pbAttribs.push_back(true);
1793         }
1794 #elif defined(__MACH__)
1795 #elif defined(DEBUG) || defined(_DEBUG)
1796         SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: Render to Texture not "
1797                "supported in Linux or MacOS");
1798 #endif  
1799     }
1800
1801     // Set the pixel type
1802     if (_bFloat)
1803     {
1804 #ifdef _WIN32
1805         if (WGL_NV_float_buffer)
1806         {
1807             pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1808             pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1809
1810             pfAttribs.push_back(WGL_FLOAT_COMPONENTS_NV);
1811             pfAttribs.push_back(true);
1812         }
1813         else
1814         {
1815             pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1816             pfAttribs.push_back(WGL_TYPE_RGBA_FLOAT_ATI);
1817         }
1818 #elif defined( __MACH__ )
1819         // if (GL_MACH_float_pixels) // FIXME
1820         {
1821             pfAttribs.push_back(kCGLPFAColorFloat);
1822         }
1823 #else
1824         if (GLX_NV_float_buffer)
1825         {
1826             pfAttribs.push_back(GLX_FLOAT_COMPONENTS_NV);
1827             pfAttribs.push_back(1);
1828         }
1829 #endif
1830     }
1831     else
1832     {
1833 #ifdef _WIN32
1834         pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1835         pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1836 #endif
1837     }
1838
1839     // Set up texture binding for render to texture
1840     if (_bIsTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1841     {
1842         
1843 #ifdef _WIN32
1844         if (_bFloat)
1845         {
1846             if (WGL_NV_float_buffer)
1847             {
1848                 switch(_iNumComponents)
1849                 {
1850                 case 1:
1851                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
1852                     pfAttribs.push_back(true);
1853                     
1854                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1855                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_R_NV);
1856                     break;
1857                 case 2:
1858                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
1859                     pfAttribs.push_back(true);
1860                     
1861                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1862                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_RG_NV);
1863                     break;
1864                 case 3:
1865                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
1866                     pfAttribs.push_back(true);
1867                     
1868                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1869                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGB_NV);
1870                     break;
1871                 case 4:
1872                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
1873                     pfAttribs.push_back(true);
1874                     
1875                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1876                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGBA_NV);
1877                     break;
1878                 default:
1879                     SG_LOG(SG_GL, SG_ALERT, 
1880                             "RenderTexture Warning: Bad number of components "
1881                             "(r=1,rg=2,rgb=3,rgba=4): " <<
1882                             _iNumComponents);
1883                     break;
1884                 }
1885             }
1886             else
1887             {
1888                 if (4 == _iNumComponents)
1889                 {
1890                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1891                     pfAttribs.push_back(true);
1892                     
1893                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1894                     pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1895                 }
1896                 else 
1897                 {
1898                     // standard ARB_render_texture only supports 3 or 4 channels
1899                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1900                     pfAttribs.push_back(true);
1901                     
1902                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1903                     pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1904                 }
1905             }
1906             
1907         } 
1908         else
1909         {
1910             switch(_iNumComponents)
1911             {
1912             case 3:
1913                 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1914                 pfAttribs.push_back(true);
1915                 
1916                 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1917                 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1918                 break;
1919             case 4:
1920                 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1921                 pfAttribs.push_back(true);
1922                 
1923                 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1924                 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1925                 break;
1926             default:
1927                 SG_LOG(SG_GL, SG_ALERT, 
1928                         "RenderTexture Warning: Bad number of components "
1929                         "(r=1,rg=2,rgb=3,rgba=4): " << _iNumComponents);
1930                 break;
1931             }
1932         }
1933 #elif defined(__MACH__)
1934         if (_bFloat)
1935         {
1936                        /*
1937             //if (WGLEW_NV_float_buffer)       // FIXME
1938             {
1939                 switch(_iNumComponents)
1940                 {
1941                 case 1:
1942                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
1943                     pfAttribs.push_back(true);
1944
1945                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1946                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_R_NV);
1947                     break;
1948                 case 2:
1949                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
1950                     pfAttribs.push_back(true);
1951
1952                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1953                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_RG_NV);
1954                     break;
1955                 case 3:
1956                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
1957                     pfAttribs.push_back(true);
1958
1959                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1960                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGB_NV);
1961                     break;
1962                 case 4:
1963                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
1964                     pfAttribs.push_back(true);
1965
1966                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1967                     pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGBA_NV);
1968                     break;
1969                 default:
1970                     fprintf(stderr,
1971                             "RenderTexture Warning: Bad number of components "
1972                             "(r=1,rg=2,rgb=3,rgba=4): %d.\n",
1973                             _iNumComponents);
1974                     break;
1975                 }
1976            }
1977             else
1978             {
1979                 if (4 == _iNumComponents)
1980                 {
1981                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1982                     pfAttribs.push_back(true);
1983
1984                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1985                     pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1986                 }
1987                 else
1988                 {
1989                     // standard ARB_render_texture only supports 3 or 4 channels
1990                     pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1991                     pfAttribs.push_back(true);
1992
1993                     pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1994                     pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1995                 }
1996             }
1997             */
1998         }
1999         else
2000         {
2001                        /*
2002             switch(_iNumComponents)
2003             {
2004             case 3:
2005                 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
2006                 pfAttribs.push_back(true);
2007
2008                 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2009                 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
2010                 break;
2011             case 4:
2012                 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
2013                 pfAttribs.push_back(true);
2014
2015                 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2016                 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
2017                 break;
2018             default:
2019                 fprintf(stderr,
2020                         "RenderTexture Warning: Bad number of components "
2021                         "(r=1,rg=2,rgb=3,rgba=4): %d.\n", _iNumComponents);
2022                 break;
2023             }
2024                        */
2025         }
2026 #elif defined(DEBUG) || defined(_DEBUG)
2027         SG_LOG(SG_GL, SG_ALERT, 
2028                 "RenderTexture Error: Render to Texture not supported in "
2029                 "Linux or MacOS\ n");
2030 #endif  
2031     }
2032         
2033     if (_bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
2034     {  
2035 #ifdef _WIN32
2036         if (_bRectangle)
2037         {
2038             pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV);
2039             pfAttribs.push_back(true);
2040         
2041             pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
2042             pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
2043         }
2044         else 
2045         {
2046             pfAttribs.push_back(WGL_BIND_TO_TEXTURE_DEPTH_NV);
2047             pfAttribs.push_back(true);
2048         
2049             pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
2050             pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
2051         }
2052 #elif defined(__MACH__)
2053 #elif defined(DEBUG) || defined(_DEBUG)
2054         SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: Render to Texture not supported in "
2055                "Linux or MacOS");
2056 #endif 
2057     }
2058 }
2059
2060 //---------------------------------------------------------------------------
2061 // Function             : RenderTexture::_GetKeyValuePair
2062 // Description      : 
2063 //---------------------------------------------------------------------------
2064 /**
2065 * @fn RenderTexture::_GetKeyValuePair()
2066 * @brief Parses expressions of the form "X=Y" into a pair (X,Y).
2067 */ 
2068 RenderTexture::KeyVal RenderTexture::_GetKeyValuePair(string token)
2069 {
2070     string::size_type pos = 0;
2071     if ((pos = token.find("=")) != token.npos)
2072     {
2073         string key = token.substr(0, pos);
2074         string value = token.substr(pos+1, token.length()-pos+1);
2075         return KeyVal(key, value);
2076     }
2077     else
2078         return KeyVal(token, "");
2079 }
2080
2081 //---------------------------------------------------------------------------
2082 // Function             : RenderTexture::_ParseBitVector
2083 // Description      : 
2084 //---------------------------------------------------------------------------
2085 /**
2086 * @fn RenderTexture::_ParseBitVector()
2087 * @brief Parses expressions of the form "=r,g,b,a" into a vector: (r,g,b,a)
2088 */ 
2089 vector<int> RenderTexture::_ParseBitVector(string bitVector)
2090 {
2091     vector<string> pieces;
2092     vector<int> bits;
2093
2094     if (bitVector == "")
2095     {
2096         bits.push_back(8);  // if a depth isn't specified, use default 8 bits
2097         return bits;
2098     }
2099
2100     string::size_type pos = 0; 
2101     string::size_type nextpos = 0;
2102     do
2103     { 
2104         nextpos = bitVector.find_first_of(", ", pos);
2105         pieces.push_back(string(bitVector, pos, nextpos - pos)); 
2106         pos = nextpos+1; 
2107     } while (nextpos != bitVector.npos );
2108
2109     for ( vector<string>::iterator it = pieces.begin(); it != pieces.end(); it++)
2110     {
2111         bits.push_back(strtol(it->c_str(), 0, 10));
2112     }
2113     
2114     return bits;
2115 }
2116
2117 //---------------------------------------------------------------------------
2118 // Function             : RenderTexture::_VerifyExtensions
2119 // Description      : 
2120 //---------------------------------------------------------------------------
2121 /**
2122 * @fn RenderTexture::_VerifyExtensions()
2123 * @brief Checks that the necessary extensions are available based on RT mode.
2124 */ 
2125 bool RenderTexture::_VerifyExtensions()
2126 {
2127 #ifdef _WIN32
2128         // a second call to _VerifyExtensions will allways return true, causing a crash
2129         // if the extension is not supported
2130     if ( true || !fctPtrInited )
2131     {
2132         fctPtrInited = true;
2133         wglGetExtensionsStringARBProc wglGetExtensionsStringARBPtr = (wglGetExtensionsStringARBProc)wglGetProcAddress( "wglGetExtensionsStringARB" );
2134         if ( wglGetExtensionsStringARBPtr == 0 )
2135         {
2136             PrintExtensionError("WGL_ARB_extensions_string");
2137             return false;
2138         }
2139         string wglExtensionsString = wglGetExtensionsStringARBPtr( wglGetCurrentDC() );
2140         if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pixel_format" ) )
2141         {
2142             wglChoosePixelFormatARBPtr = (wglChoosePixelFormatARBProc)SGLookupFunction("wglChoosePixelFormatARB");
2143             wglGetPixelFormatAttribivARBPtr = (wglGetPixelFormatAttribivARBProc)SGLookupFunction("wglGetPixelFormatAttribivARB");
2144         }
2145         else
2146         {
2147             PrintExtensionError("WGL_ARB_pixel_format");
2148             return false;
2149         }
2150         if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pbuffer" ) )
2151         {
2152             wglCreatePbufferARBPtr = (wglCreatePbufferARBProc)SGLookupFunction("wglCreatePbufferARB");
2153             wglGetPbufferDCARBPtr = (wglGetPbufferDCARBProc)SGLookupFunction("wglGetPbufferDCARB");
2154             wglQueryPbufferARBPtr = (wglQueryPbufferARBProc)SGLookupFunction("wglQueryPbufferARB");
2155             wglReleasePbufferDCARBPtr = (wglReleasePbufferDCARBProc)SGLookupFunction("wglReleasePbufferDCARB");
2156             wglDestroyPbufferARBPtr = (wglDestroyPbufferARBProc)SGLookupFunction("wglDestroyPbufferARB");
2157         }
2158         else
2159         {
2160             PrintExtensionError("WGL_ARB_pbuffer");
2161             return false;
2162         }
2163         if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_render_texture" ) )
2164         {
2165             wglBindTexImageARBPtr = (wglBindTexImageARBProc)SGLookupFunction("wglBindTexImageARB");
2166             wglReleaseTexImageARBPtr = (wglReleaseTexImageARBProc)SGLookupFunction("wglReleaseTexImageARB");
2167         }
2168         else if ( _bIsTexture )
2169         {
2170             PrintExtensionError("WGL_ARB_render_texture");
2171             return false;
2172         }
2173         if (_bRectangle && !SGIsOpenGLExtensionSupported( "GL_NV_texture_rectangle" ))
2174         {
2175             PrintExtensionError("GL_NV_texture_rectangle");
2176             return false;
2177         }
2178         if (_bFloat && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) ||
2179             SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ATI_pixel_format_float" )))
2180         {
2181             PrintExtensionError("GL_NV_float_buffer or GL_ATI_pixel_format_float");
2182             return false;
2183         
2184         }
2185         if (_bFloat && _bIsTexture && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) || SGIsOpenGLExtensionSupported( "GL_ATI_texture_float" )))
2186         {
2187             PrintExtensionError("NV_float_buffer or ATI_texture_float");
2188         }
2189         if (_bIsDepthTexture && !SGIsOpenGLExtensionSupported( "GL_ARB_depth_texture" ))
2190         {
2191             // [Redge]
2192 #if defined(_DEBUG) | defined(DEBUG)
2193             SG_LOG(SG_GL, SG_ALERT, 
2194                     "RenderTexture Warning: "
2195                     "OpenGL extension GL_ARB_depth_texture not available."
2196                     "         Using glReadPixels() to emulate behavior.");
2197 #endif   
2198             _bHasARBDepthTexture = false;
2199             //PrintExtensionError("GL_ARB_depth_texture");
2200             //return false;
2201             // [/Redge]
2202         }
2203         SetLastError(0);
2204     }
2205 #elif defined( __MACH__ )
2206     // FIXME! Check extensions!
2207 #else
2208     Display* dpy = glXGetCurrentDisplay();
2209     int minor = 0, major = 0;
2210     if (!glXQueryVersion(dpy, &major, &minor))
2211         return false;
2212
2213     int screen = DefaultScreen(dpy);
2214     const char* extString = glXQueryExtensionsString(dpy, screen);
2215     if (!SGSearchExtensionsString(extString, "GLX_SGIX_fbconfig") ||
2216         !SGSearchExtensionsString(extString, "GLX_SGIX_pbuffer"))
2217         return false;
2218
2219     // First try the glX version 1.3 functions.
2220     glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfig");
2221     glXCreatePbufferPtr = (glXCreatePbufferProc)SGLookupFunction("glXCreatePbuffer");
2222     glXGetVisualFromFBConfigPtr = (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfig");
2223     glXCreateContextPtr = (glXCreateContextProc)SGLookupFunction("glXCreateContext");
2224     glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyPbuffer");
2225     glXQueryDrawablePtr = (glXQueryDrawableProc)SGLookupFunction("glXQueryDrawable");
2226
2227     if (((1 <= major && 3 <= minor) || 2 <= major) &&
2228         glXChooseFBConfigPtr &&
2229         glXCreatePbufferPtr &&
2230         glXGetVisualFromFBConfigPtr &&
2231         glXCreateContextPtr &&
2232         glXDestroyPbufferPtr &&
2233         glXQueryDrawablePtr)
2234         glXVersion1_3Present = true;
2235     else
2236     {
2237         glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfigSGIX");
2238         glXCreateGLXPbufferPtr = (glXCreateGLXPbufferProc)SGLookupFunction("glXCreateGLXPbufferSGIX");
2239         glXGetVisualFromFBConfigPtr =  (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfigSGIX");
2240         glXCreateContextWithConfigPtr = (glXCreateContextWithConfigProc)SGLookupFunction("glXCreateContextWithConfigSGIX");
2241         glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyGLXPbufferSGIX");
2242         glXQueryGLXPbufferSGIXPtr = (glXQueryGLXPbufferSGIXProc)SGLookupFunction("glXQueryGLXPbufferSGIX");
2243
2244
2245         if (!glXChooseFBConfigPtr ||
2246             !glXCreateGLXPbufferPtr ||
2247             !glXGetVisualFromFBConfigPtr ||
2248             !glXCreateContextWithConfigPtr ||
2249             !glXDestroyPbufferPtr ||
2250             !glXQueryGLXPbufferSGIXPtr)
2251             return false;
2252     }
2253
2254     if (_bIsDepthTexture && !GL_ARB_depth_texture)
2255     {
2256         PrintExtensionError("GL_ARB_depth_texture");
2257         return false;
2258     }
2259     if (_bFloat && _bIsTexture && !GLX_NV_float_buffer)
2260     {
2261         PrintExtensionError("GLX_NV_float_buffer");
2262         return false;
2263     }
2264     if (_eUpdateMode == RT_RENDER_TO_TEXTURE)
2265     {
2266         PrintExtensionError("Some GLX render texture extension: Please implement me!");
2267         return false;
2268     }
2269 #endif
2270   
2271     return true;
2272 }
2273
2274 //---------------------------------------------------------------------------
2275 // Function             : RenderTexture::_InitializeTextures
2276 // Description      : 
2277 //---------------------------------------------------------------------------
2278 /**
2279 * @fn RenderTexture::_InitializeTextures()
2280 * @brief Initializes the state of textures used by the RenderTexture.
2281 */ 
2282 bool RenderTexture::_InitializeTextures()
2283 {
2284     // Determine the appropriate texture formats and filtering modes.
2285     if (_bIsTexture || _bIsDepthTexture)
2286     {
2287         if (_bRectangle && GL_NV_texture_rectangle)
2288             _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
2289         else if (_bRectangle && GL_EXT_texture_rectangle)
2290             _iTextureTarget = GL_TEXTURE_RECTANGLE_EXT;
2291         else
2292             _iTextureTarget = GL_TEXTURE_2D;
2293     }
2294
2295     if (_bIsTexture)
2296     {
2297         glGenTextures(1, (GLuint*)&_iTextureID);
2298         glBindTexture(_iTextureTarget, _iTextureID);  
2299         
2300         // Use clamp to edge as the default texture wrap mode for all tex
2301         glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2302         glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
2303         // Use NEAREST as the default texture filtering mode.
2304         glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2305         glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2306
2307
2308         if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2309         {
2310             GLuint iInternalFormat;
2311             GLuint iFormat;
2312
2313             if (_bFloat)
2314             {                             
2315                 if (_bMipmap)
2316                 {
2317                     SG_LOG(SG_GL, SG_ALERT, 
2318                         "RenderTexture Error: mipmapped float textures not "
2319                         "supported.");
2320                     return false;
2321                 }
2322             
2323                 switch(_iNumComponents) 
2324                 {
2325                 case 1:
2326                     if (GL_NV_float_buffer)
2327                     {
2328                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
2329                             GL_FLOAT_R32_NV : GL_FLOAT_R16_NV;
2330                     }
2331                     else if (GL_ATI_texture_float)
2332                     {
2333                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
2334                             GL_LUMINANCE_FLOAT32_ATI : 
2335                             GL_LUMINANCE_FLOAT16_ATI;
2336                     }
2337                     iFormat = GL_LUMINANCE;
2338                         break;
2339                 case 2:
2340                     if (GL_NV_float_buffer)
2341                     {
2342                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
2343                             GL_FLOAT_RG32_NV : GL_FLOAT_RG16_NV;
2344                     }
2345                     else if (GL_ATI_texture_float)
2346                     {
2347                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
2348                             GL_LUMINANCE_ALPHA_FLOAT32_ATI : 
2349                             GL_LUMINANCE_ALPHA_FLOAT16_ATI;
2350                     }
2351                     iFormat = GL_LUMINANCE_ALPHA;
2352                         break;
2353                 case 3:
2354                     if (GL_NV_float_buffer)
2355                     {
2356                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
2357                             GL_FLOAT_RGB32_NV : GL_FLOAT_RGB16_NV;
2358                     }
2359                     else if (GL_ATI_texture_float)
2360                     {
2361                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
2362                             GL_RGB_FLOAT32_ATI : GL_RGB_FLOAT16_ATI;
2363                     }
2364                     iFormat = GL_RGB;
2365                     break;
2366                 case 4:
2367                     if (GL_NV_float_buffer)
2368                     {
2369                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
2370                             GL_FLOAT_RGBA32_NV : GL_FLOAT_RGBA16_NV;
2371                     }
2372                     else if (GL_ATI_texture_float)
2373                     {
2374                         iInternalFormat = (_iNumColorBits[0] > 16) ? 
2375                             GL_RGBA_FLOAT32_ATI : GL_RGBA_FLOAT16_ATI;
2376                     }
2377                     iFormat = GL_RGBA;
2378                     break;
2379                 default:
2380                     SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: "
2381                            "Invalid number of components: " <<
2382                            _iNumComponents);
2383                     return false;
2384                 }
2385             }
2386             else // non-float
2387             {                        
2388                 if (4 == _iNumComponents)
2389                 {
2390                     iInternalFormat = GL_RGBA8;
2391                     iFormat = GL_RGBA;
2392                 }
2393                 else 
2394                 {
2395                     iInternalFormat = GL_RGB8;
2396                     iFormat = GL_RGB;
2397                 }
2398             }
2399         
2400             // Allocate the texture image (but pass it no data for now).
2401             glTexImage2D(_iTextureTarget, 0, iInternalFormat, 
2402                          _iWidth, _iHeight, 0, iFormat, GL_FLOAT, NULL);
2403         } 
2404     }
2405   
2406     if (_bIsDepthTexture)
2407     { 
2408         glGenTextures(1, (GLuint*)&_iDepthTextureID);
2409         glBindTexture(_iTextureTarget, _iDepthTextureID);  
2410         
2411         // Use clamp to edge as the default texture wrap mode for all tex
2412         glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2413         glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
2414         // Use NEAREST as the default texture filtering mode.
2415         glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2416         glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2417                
2418         if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2419         {
2420             // [Redge]
2421             if (_bHasARBDepthTexture) 
2422             {
2423                 // Allocate the texture image (but pass it no data for now).
2424                 glTexImage2D(_iTextureTarget, 0, GL_DEPTH_COMPONENT, 
2425                              _iWidth, _iHeight, 0, GL_DEPTH_COMPONENT, 
2426                              GL_FLOAT, NULL);
2427             } 
2428             else 
2429             {
2430                 // allocate memory for depth texture
2431                 // Since this is slow, we warn the user in debug mode. (above)
2432                 _pPoorDepthTexture = new unsigned short[_iWidth * _iHeight];
2433                 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16, 
2434                              _iWidth, _iHeight, 0, GL_LUMINANCE, 
2435                              GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2436             }
2437             // [/Redge]
2438         }
2439     }
2440
2441     return true;
2442 }
2443
2444
2445 //---------------------------------------------------------------------------
2446 // Function             : RenderTexture::_MaybeCopyBuffer
2447 // Description      : 
2448 //---------------------------------------------------------------------------
2449 /**
2450 * @fn RenderTexture::_MaybeCopyBuffer()
2451 * @brief Does the actual copying for RenderTextures with RT_COPY_TO_TEXTURE
2452 */ 
2453 void RenderTexture::_MaybeCopyBuffer()
2454 {
2455 #ifdef _WIN32
2456     if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2457     {
2458         if (_bIsTexture)
2459         {
2460             glBindTexture(_iTextureTarget, _iTextureID);
2461             glCopyTexSubImage2D(_iTextureTarget, 
2462                                 0, 0, 0, 0, 0, _iWidth, _iHeight);
2463         }
2464         if (_bIsDepthTexture)
2465         {
2466             glBindTexture(_iTextureTarget, _iDepthTextureID);
2467             // HOW TO COPY DEPTH TEXTURE??? Supposedly this just magically works...
2468             // [Redge]
2469             if (_bHasARBDepthTexture) 
2470             {
2471                 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, 
2472                                     _iWidth, _iHeight);
2473             } 
2474             else 
2475             {
2476                 // no 'real' depth texture available, so behavior has to be emulated
2477                 // using glReadPixels (beware, this is (naturally) slow ...)
2478                 glReadPixels(0, 0, _iWidth, _iHeight, GL_DEPTH_COMPONENT, 
2479                              GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2480                 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
2481                              _iWidth, _iHeight, 0, GL_LUMINANCE, 
2482                              GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2483             }
2484             // [/Redge]
2485         }
2486     }
2487     
2488 #elif defined(__MACH__)
2489     if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2490     {
2491        if (_bIsTexture)
2492        {
2493          glBindTexture(_iTextureTarget, _iTextureID);
2494          glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2495        }
2496        if (_bIsDepthTexture)
2497        {
2498          glBindTexture(_iTextureTarget, _iDepthTextureID);
2499          assert(_bHasARBDepthTexture);
2500          glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2501        }
2502     }
2503 #else
2504     if (_bIsTexture)
2505     {
2506       glBindTexture(_iTextureTarget, _iTextureID);
2507       glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2508     }
2509     if (_bIsDepthTexture)
2510     {
2511       glBindTexture(_iTextureTarget, _iDepthTextureID);
2512       assert(_bHasARBDepthTexture);
2513       glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2514     }
2515 #endif
2516
2517 }
2518
2519 //---------------------------------------------------------------------------
2520 // Function             : RenderTexture::_ReleaseBoundBuffers
2521 // Description      : 
2522 //---------------------------------------------------------------------------
2523 /**
2524 * @fn RenderTexture::_ReleaseBoundBuffers()
2525 * @brief Releases buffer bindings on RenderTextures with RT_RENDER_TO_TEXTURE
2526 */ 
2527 bool RenderTexture::_ReleaseBoundBuffers()
2528 {
2529 #ifdef _WIN32
2530     if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2531     {
2532         glBindTexture(_iTextureTarget, _iTextureID);
2533         
2534         // release the pbuffer from the render texture object
2535         if (0 != _iCurrentBoundBuffer && _bIsBufferBound)
2536         {
2537             if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, _iCurrentBoundBuffer))
2538             {
2539                 _wglGetLastError();
2540                 return false;
2541             }
2542             _bIsBufferBound = false;
2543         }
2544     }
2545     
2546     if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2547     {
2548         glBindTexture(_iTextureTarget, _iDepthTextureID);
2549         
2550         // release the pbuffer from the render texture object
2551         if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
2552         {
2553             _wglGetLastError();
2554             return false;
2555         }
2556     }
2557     
2558 #else
2559     // textures can't be bound in Linux
2560 #endif
2561     return true;
2562 }
2563
2564 //---------------------------------------------------------------------------
2565 // Function             : RenderTexture::_MakeCurrent
2566 // Description      : 
2567 //---------------------------------------------------------------------------
2568 /**
2569 * @fn RenderTexture::_MakeCurrent()
2570 * @brief Makes the RenderTexture's context current
2571 */ 
2572
2573 bool RenderTexture::_MakeCurrent() 
2574 {
2575 #ifdef _WIN32
2576     // make the pbuffer's rendering context current.
2577     if (FALSE == wglMakeCurrent( _hDC, _hGLContext))
2578     {
2579         _wglGetLastError();
2580         return false;
2581     }
2582 #elif defined( __MACH__ )
2583     CGLError err;
2584
2585     if (err = CGLSetCurrentContext(_hGLContext))
2586     {
2587         _cglCheckError(err);
2588         return false;
2589     }
2590 #else
2591     if (false == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext)) 
2592     {
2593         return false;
2594     }
2595 #endif
2596
2597     return true;
2598 }
2599
2600 /////////////////////////////////////////////////////////////////////////////
2601 //
2602 // Begin Deprecated Interface
2603 //
2604 /////////////////////////////////////////////////////////////////////////////
2605
2606 //---------------------------------------------------------------------------
2607 // Function      : RenderTexture::RenderTexture
2608 // Description   : 
2609 //---------------------------------------------------------------------------
2610 /**
2611 * @fn RenderTexture::RenderTexture()
2612 * @brief Constructor.
2613 */ 
2614 RenderTexture::RenderTexture(int width, int height,
2615                                bool bIsTexture /* = true */,
2616                                bool bIsDepthTexture /* = false */)
2617 :   _iWidth(width), 
2618     _iHeight(height), 
2619     _bIsTexture(bIsTexture),
2620     _bIsDepthTexture(bIsDepthTexture),
2621     _bHasARBDepthTexture(true),            // [Redge]
2622     _eUpdateMode(RT_RENDER_TO_TEXTURE),
2623     _bInitialized(false),
2624     _iNumAuxBuffers(0),
2625     _iCurrentBoundBuffer(0),
2626     _iNumDepthBits(0),
2627     _iNumStencilBits(0),
2628     _bFloat(false),
2629     _bDoubleBuffered(false),
2630     _bPowerOf2(true),
2631     _bRectangle(false),
2632     _bMipmap(false),
2633     _bShareObjects(false),
2634     _bCopyContext(false),
2635 #ifdef _WIN32
2636     _hDC(NULL), 
2637     _hGLContext(NULL), 
2638     _hPBuffer(NULL),
2639     _hPreviousDC(0),
2640     _hPreviousContext(0),
2641 #elif defined( __MACH__ )
2642     _hGLContext(NULL),
2643     _hPBuffer(NULL),
2644     _hPreviousContext(NULL),
2645 #else
2646     _pDisplay(NULL),
2647     _hGLContext(NULL),
2648     _hPBuffer(0),
2649     _hPreviousDrawable(0),
2650     _hPreviousContext(0),
2651 #endif
2652     _iTextureTarget(GL_NONE),
2653     _iTextureID(0),
2654     _iDepthTextureID(0),
2655     _pPoorDepthTexture(0) // [Redge]
2656 {
2657     assert(width > 0 && height > 0);
2658 #if defined DEBUG || defined _DEBUG
2659     SG_LOG(SG_GL, SG_ALERT, 
2660             "RenderTexture Warning: Deprecated Contructor interface used.");
2661 #endif
2662     
2663     _iNumColorBits[0] = _iNumColorBits[1] = 
2664         _iNumColorBits[2] = _iNumColorBits[3] = 0;
2665     _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
2666 }
2667
2668 //------------------------------------------------------------------------------
2669 // Function             : RenderTexture::Initialize
2670 // Description      : 
2671 //------------------------------------------------------------------------------
2672 /**
2673 * @fn RenderTexture::Initialize(bool bShare, bool bDepth, bool bStencil, bool bMipmap, unsigned int iRBits, unsigned int iGBits, unsigned int iBBits, unsigned int iABits);
2674 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
2675
2676 * This function actually does the creation of the p-buffer.  It can only be called 
2677 * once a GL context has already been created.  Note that if the texture is not
2678 * power of two dimensioned, or has more than 8 bits per channel, enabling mipmapping
2679 * will cause an error.
2680 */ 
2681 bool RenderTexture::Initialize(bool         bShare       /* = true */, 
2682                                 bool         bDepth       /* = false */, 
2683                                 bool         bStencil     /* = false */, 
2684                                 bool         bMipmap      /* = false */, 
2685                                 bool         bAnisoFilter /* = false */,
2686                                 unsigned int iRBits       /* = 8 */, 
2687                                 unsigned int iGBits       /* = 8 */, 
2688                                 unsigned int iBBits       /* = 8 */, 
2689                                 unsigned int iABits       /* = 8 */,
2690                                 UpdateMode   updateMode   /* = RT_RENDER_TO_TEXTURE */)
2691 {   
2692     if (0 == _iWidth || 0 == _iHeight)
2693         return false;
2694
2695 #if defined DEBUG || defined _DEBUG
2696     SG_LOG(SG_GL, SG_ALERT, 
2697             "RenderTexture Warning: Deprecated Initialize() interface used.");
2698 #endif   
2699
2700     // create a mode string.
2701     string mode = "";
2702     if (bDepth)
2703         mode.append("depth ");
2704     if (bStencil)
2705         mode.append("stencil ");
2706     if (bMipmap)
2707         mode.append("mipmap ");
2708     if (iRBits + iGBits + iBBits + iABits > 0)
2709     {
2710         if (iRBits > 0)
2711             mode.append("r");
2712         if (iGBits > 0)
2713             mode.append("g");
2714         if (iBBits > 0)
2715             mode.append("b");
2716         if (iABits > 0)
2717             mode.append("a");
2718         mode.append("=");
2719         char bitVector[100];
2720         snprintf( bitVector, 100,
2721             "%d%s,%d%s,%d%s,%d%s",
2722             iRBits, (iRBits >= 16) ? "f" : "",
2723             iGBits, (iGBits >= 16) ? "f" : "",
2724             iBBits, (iBBits >= 16) ? "f" : "",
2725             iABits, (iABits >= 16) ? "f" : "");
2726         mode.append(bitVector);
2727         mode.append(" ");
2728     }
2729     if (_bIsTexture)
2730     {
2731         if ((GL_NV_texture_rectangle || GL_EXT_texture_rectangle) && 
2732             ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2733               || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2734             mode.append("texRECT ");
2735         else
2736             mode.append("tex2D ");
2737     }
2738     if (_bIsDepthTexture)
2739     {
2740         if ((GL_NV_texture_rectangle || GL_EXT_texture_rectangle) && 
2741             ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2742               || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2743             mode.append("texRECT ");
2744         else
2745             mode.append("tex2D ");
2746     }
2747     if (RT_COPY_TO_TEXTURE == updateMode)
2748         mode.append("ctt");
2749
2750     _pixelFormatAttribs.clear();
2751     _pbufferAttribs.clear();
2752
2753 #ifdef _WIN32
2754     _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
2755     _pixelFormatAttribs.push_back(true);
2756     _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
2757     _pixelFormatAttribs.push_back(true);
2758     
2759     _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
2760     _pbufferAttribs.push_back(true);
2761 #elif defined( __MACH__ )
2762     //_pixelFormatAttribs.push_back(kCGLPFANoRecovery);
2763     _pixelFormatAttribs.push_back(kCGLPFAAccelerated);
2764     _pixelFormatAttribs.push_back(kCGLPFAWindow);
2765     _pixelFormatAttribs.push_back(kCGLPFAPBuffer);
2766 #else
2767     _pixelFormatAttribs.push_back(GLX_RENDER_TYPE_SGIX);
2768     _pixelFormatAttribs.push_back(GLX_RGBA_BIT_SGIX);
2769     _pixelFormatAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
2770     _pixelFormatAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
2771 #endif
2772
2773     _ParseModeString(mode.c_str(), _pixelFormatAttribs, _pbufferAttribs);
2774
2775 #ifdef _WIN32
2776     _pixelFormatAttribs.push_back(0);
2777     _pbufferAttribs.push_back(0);
2778 #elif defined(__MACH__)
2779     _pixelFormatAttribs.push_back(0);
2780 #else
2781     _pixelFormatAttribs.push_back(None);
2782 #endif
2783
2784     Initialize(_iWidth, _iHeight, bShare);
2785     
2786     return true;
2787 }
2788
2789
2790 //---------------------------------------------------------------------------
2791 // Function             : RenderTexture::Reset
2792 // Description      : 
2793 //---------------------------------------------------------------------------
2794 /**
2795 * @fn RenderTexture::Reset(int iWidth, int iHeight, unsigned int iMode, bool bIsTexture, bool bIsDepthTexture)
2796 * @brief Resets the resolution of the offscreen buffer.
2797
2798 * Causes the buffer to delete itself.  User must call Initialize() again
2799 * before use.
2800 */ 
2801 bool RenderTexture::Reset(int iWidth, int iHeight)
2802 {
2803     SG_LOG(SG_GL, SG_ALERT, 
2804             "RenderTexture Warning: Deprecated Reset() interface used.");
2805
2806     if (!_Invalidate())
2807     {
2808         SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Reset(): failed to invalidate.");
2809         return false;
2810     }
2811     _iWidth     = iWidth;
2812     _iHeight    = iHeight;
2813     
2814     return true;
2815 }