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