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