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