• Main Page
  • Namespaces
  • Classes
  • Files

RenderTexture.cpp

Go to the documentation of this file.
00001 // File : RenderTexture.cpp
00002 //---------------------------------------------------------------------------
00003 // Copyright (c) 2002-2004 Mark J. Harris
00004 //---------------------------------------------------------------------------
00005 // This software is provided 'as-is', without any express or implied
00006 // warranty. In no event will the authors be held liable for any
00007 // damages arising from the use of this software.
00008 //
00009 // Permission is granted to anyone to use this software for any
00010 // purpose, including commercial applications, and to alter it and
00011 // redistribute it freely, subject to the following restrictions:
00012 //
00013 // 1. The origin of this software must not be misrepresented; you
00014 //    must not claim that you wrote the original software. If you use
00015 //    this software in a product, an acknowledgment in the product
00016 //    documentation would be appreciated but is not required.
00017 //
00018 // 2. Altered source versions must be plainly marked as such, and
00019 //    must not be misrepresented as being the original software.
00020 //
00021 // 3. This notice may not be removed or altered from any source
00022 //    distribution.
00023 //
00024 // --------------------------------------------------------------------------
00025 // Credits:
00026 // Original RenderTexture class: Mark J. Harris
00027 // Original Render to Depth Texture support: Thorsten Scheuermann
00028 // Linux Copy-to-texture: Eric Werness
00029 // OS X: Alexander Powell (someone please help)
00030 // Various Bug Fixes: Daniel (Redge) Sperl 
00031 //                    Bill Baxter
00032 //
00033 // --------------------------------------------------------------------------
00040 #pragma warning(disable:4786)
00041 
00042 /*
00043  * Changelog:
00044  *
00045  * Jan. 2005, Removed GLEW dependencies, Erik Hofman, Fred Bouvier
00046  * Nov. 2005, Use the simgear logging facility, Erik Hofman
00047  * Mar. 2006, Add MAC OS X support, Alexander Powell
00048  */
00049 
00050 #ifdef HAVE_CONFIG_H
00051 #  include <simgear_config.h>
00052 #endif
00053 
00054 #include <simgear/compiler.h>
00055 #include <simgear/debug/logstream.hxx>
00056 #include <simgear/screen/extensions.hxx>
00057 #include <simgear/screen/RenderTexture.h>
00058 
00059 #include <stdio.h>
00060 #include <stdlib.h>
00061 #include <assert.h>
00062 #include <stdarg.h>
00063 
00064 #include <cstring>
00065 
00066 #ifdef _WIN32
00067 #pragma comment(lib, "gdi32.lib") // required for GetPixelFormat()
00068 #endif
00069 
00070 using namespace std;
00071 
00072 #ifdef _WIN32
00073 static bool fctPtrInited = false;
00074 /* WGL_ARB_pixel_format */
00075 static wglChoosePixelFormatARBProc wglChoosePixelFormatARBPtr = 0;
00076 static wglGetPixelFormatAttribivARBProc wglGetPixelFormatAttribivARBPtr = 0;
00077 /* WGL_ARB_pbuffer */
00078 static wglCreatePbufferARBProc wglCreatePbufferARBPtr = 0;
00079 static wglGetPbufferDCARBProc wglGetPbufferDCARBPtr = 0;
00080 static wglQueryPbufferARBProc wglQueryPbufferARBPtr = 0;
00081 static wglReleasePbufferDCARBProc wglReleasePbufferDCARBPtr = 0;
00082 static wglDestroyPbufferARBProc wglDestroyPbufferARBPtr = 0;
00083 /* WGL_ARB_render_texture */
00084 static wglBindTexImageARBProc wglBindTexImageARBPtr = 0;
00085 static wglReleaseTexImageARBProc wglReleaseTexImageARBPtr = 0;
00086 
00087 #elif defined( __MACH__ )
00088 #else /* !_WIN32 */
00089 static bool glXVersion1_3Present = false;
00090 static glXChooseFBConfigProc glXChooseFBConfigPtr = 0;
00091 static glXCreatePbufferProc glXCreatePbufferPtr = 0;
00092 static glXCreateGLXPbufferProc glXCreateGLXPbufferPtr = 0;
00093 static glXGetVisualFromFBConfigProc glXGetVisualFromFBConfigPtr = 0;
00094 static glXCreateContextProc glXCreateContextPtr = 0;
00095 static glXCreateContextWithConfigProc glXCreateContextWithConfigPtr = 0;
00096 static glXDestroyPbufferProc glXDestroyPbufferPtr = 0;
00097 static glXQueryDrawableProc glXQueryDrawablePtr = 0;
00098 static glXQueryGLXPbufferSGIXProc glXQueryGLXPbufferSGIXPtr = 0;
00099 #endif
00100 
00101 //---------------------------------------------------------------------------
00102 // Function      : RenderTexture::RenderTexture
00103 // Description   : 
00104 //---------------------------------------------------------------------------
00109 RenderTexture::RenderTexture(const char *strMode)
00110 :   _iWidth(0), 
00111     _iHeight(0), 
00112     _bIsTexture(false),
00113     _bIsDepthTexture(false),
00114     _bHasARBDepthTexture(true),            // [Redge]
00115 #if defined(_WIN32) || defined(__MACH__)
00116     _eUpdateMode(RT_RENDER_TO_TEXTURE),
00117 #else
00118     _eUpdateMode(RT_COPY_TO_TEXTURE),
00119 #endif
00120     _bInitialized(false),
00121     _iNumAuxBuffers(0),
00122     _bIsBufferBound(false),
00123     _iCurrentBoundBuffer(0),
00124     _iNumDepthBits(0),
00125     _iNumStencilBits(0),
00126     _bFloat(false),
00127     _bDoubleBuffered(false),
00128     _bPowerOf2(true),
00129     _bRectangle(false),
00130     _bMipmap(false),
00131     _bShareObjects(false),
00132     _bCopyContext(false),
00133 #ifdef _WIN32
00134     _hDC(NULL), 
00135     _hGLContext(NULL), 
00136     _hPBuffer(NULL),
00137     _hPreviousDC(0),
00138     _hPreviousContext(0),
00139 #elif defined( __MACH__ )
00140     _hGLContext(NULL),
00141     _hPBuffer(0),
00142     _hPreviousContext(NULL),
00143 #else
00144     _pDisplay(NULL),
00145     _hGLContext(NULL),
00146     _hPBuffer(0),
00147     _hPreviousDrawable(0),
00148     _hPreviousContext(0),
00149 #endif
00150     _iTextureTarget(GL_NONE),
00151     _iTextureID(0),
00152     _iDepthTextureID(0),
00153     _pPoorDepthTexture(0) // [Redge]
00154 {
00155     _iNumColorBits[0] = _iNumColorBits[1] = 
00156         _iNumColorBits[2] = _iNumColorBits[3] = 0;
00157 
00158 #ifdef _WIN32
00159     _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
00160     _pixelFormatAttribs.push_back(true);
00161     _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
00162     _pixelFormatAttribs.push_back(true);
00163     
00164     _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
00165     _pbufferAttribs.push_back(true);
00166 #elif defined( __MACH__ )
00167     //_pixelFormatAttribs.push_back(kCGLPFANoRecovery);
00168     _pixelFormatAttribs.push_back(kCGLPFAAccelerated);
00169     _pixelFormatAttribs.push_back(kCGLPFAWindow);
00170     _pixelFormatAttribs.push_back(kCGLPFAPBuffer);
00171 #else
00172     _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
00173     _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
00174     _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
00175     _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
00176 #endif
00177 
00178     _ParseModeString(strMode, _pixelFormatAttribs, _pbufferAttribs);
00179 
00180 #ifdef _WIN32
00181     _pixelFormatAttribs.push_back(0);
00182     _pbufferAttribs.push_back(0);
00183 #elif defined(__MACH__)
00184     _pixelFormatAttribs.push_back((CGLPixelFormatAttribute)0);
00185     _pbufferAttribs.push_back((CGLPixelFormatAttribute)0);
00186 #else
00187     _pixelFormatAttribs.push_back(None);
00188 #endif
00189 }
00190 
00191 
00192 //---------------------------------------------------------------------------
00193 // Function             : RenderTexture::~RenderTexture
00194 // Description      : 
00195 //---------------------------------------------------------------------------
00200 RenderTexture::~RenderTexture()
00201 {
00202     _Invalidate();
00203 }
00204 
00205  //---------------------------------------------------------------------------
00206 // Function            : _cglcheckError
00207 // Description     :
00208 //---------------------------------------------------------------------------
00213 #ifdef __MACH__
00214 static void _cglCheckErrorHelper(CGLError err, char *sourceFile, int sourceLine)
00215 {
00216 # ifdef _DEBUG
00217     if (err)
00218     {
00219        fprintf(stderr, "RenderTexture CGL Error:  %s at (%s,%d)",
00220                         CGLErrorString(err), sourceFile, sourceLine);
00221     }
00222 # endif
00223 }
00224 
00225 # define _cglCheckError(err) _cglCheckErrorHelper(err,__FILE__,__LINE__)
00226 
00227 #endif
00228 
00229 
00230 //---------------------------------------------------------------------------
00231 // Function             : _wglGetLastError
00232 // Description      : 
00233 //---------------------------------------------------------------------------
00238 #ifdef _WIN32
00239 void _wglGetLastError()
00240 {
00241 #ifdef _DEBUG
00242     
00243     DWORD err = GetLastError();
00244     switch(err)
00245     {
00246     case ERROR_INVALID_PIXEL_FORMAT:
00247         SG_LOG(SG_GL, SG_ALERT, 
00248                 "RenderTexture Win32 Error:  ERROR_INVALID_PIXEL_FORMAT");
00249         break;
00250     case ERROR_NO_SYSTEM_RESOURCES:
00251         SG_LOG(SG_GL, SG_ALERT, 
00252                 "RenderTexture Win32 Error:  ERROR_NO_SYSTEM_RESOURCES");
00253         break;
00254     case ERROR_INVALID_DATA:
00255         SG_LOG(SG_GL, SG_ALERT, 
00256                 "RenderTexture Win32 Error:  ERROR_INVALID_DATA");
00257         break;
00258     case ERROR_INVALID_WINDOW_HANDLE:
00259         SG_LOG(SG_GL, SG_ALERT, 
00260                 "RenderTexture Win32 Error:  ERROR_INVALID_WINDOW_HANDLE");
00261         break;
00262     case ERROR_RESOURCE_TYPE_NOT_FOUND:
00263         SG_LOG(SG_GL, SG_ALERT, 
00264                 "RenderTexture Win32 Error:  ERROR_RESOURCE_TYPE_NOT_FOUND");
00265         break;
00266     case ERROR_SUCCESS:
00267         // no error
00268         break;
00269     default:
00270         LPVOID lpMsgBuf;
00271         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
00272             FORMAT_MESSAGE_FROM_SYSTEM | 
00273             FORMAT_MESSAGE_IGNORE_INSERTS,
00274             NULL,
00275             err,
00276             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
00277             (LPTSTR) &lpMsgBuf,
00278             0,
00279             NULL);
00280         
00281         SG_LOG(SG_GL, SG_ALERT, "RenderTexture Win32 Error " <<  err << ":" << lpMsgBuf);
00282         LocalFree( lpMsgBuf );
00283         break;
00284     }
00285     SetLastError(0);
00286     
00287 #endif // _DEBUG
00288 }
00289 #endif
00290 
00291 //---------------------------------------------------------------------------
00292 // Function             : PrintExtensionError
00293 // Description      : 
00294 //---------------------------------------------------------------------------
00299 void PrintExtensionError( const char* strMsg, ... )
00300 {
00301     SG_LOG(SG_GL, SG_ALERT, 
00302             "Error: RenderTexture requires the following unsupported "
00303             "OpenGL extensions: ");
00304     char strBuffer[512];
00305     va_list args;
00306     va_start(args, strMsg);
00307 #if defined _WIN32 && !defined __CYGWIN__
00308     _vsnprintf( strBuffer, 512, strMsg, args );
00309 #else
00310     vsnprintf( strBuffer, 512, strMsg, args );
00311 #endif
00312     va_end(args);
00313     
00314     SG_LOG(SG_GL, SG_ALERT, strMsg);
00315 }
00316 
00317 
00318 //---------------------------------------------------------------------------
00319 // Function             : RenderTexture::Initialize
00320 // Description      : 
00321 //---------------------------------------------------------------------------
00329 bool RenderTexture::Initialize(int width, int height,
00330                                 bool shareObjects       /* = true */,
00331                                 bool copyContext        /* = false */)
00332 {
00333     assert(width > 0 && height > 0);
00334 
00335     _iWidth = width; _iHeight = height;
00336     _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
00337 
00338     _bShareObjects = shareObjects;
00339     _bCopyContext  = copyContext;
00340 
00341     // Check if this is an NVXX GPU and verify necessary extensions.
00342     if (!_VerifyExtensions())
00343         return false;
00344     
00345     if (_bInitialized)
00346         _Invalidate();
00347 
00348 #ifdef _WIN32
00349     // Get the current context.
00350     HDC hdc = wglGetCurrentDC();
00351     if (NULL == hdc)
00352         _wglGetLastError();
00353     HGLRC hglrc = wglGetCurrentContext();
00354     if (NULL == hglrc)
00355         _wglGetLastError();
00356     
00357     int iFormat = 0;
00358     unsigned int iNumFormats;
00359     
00360     if (_bCopyContext)
00361     {
00362         // Get the pixel format for the on-screen window.
00363         iFormat = GetPixelFormat(hdc);
00364         if (iFormat == 0)
00365         {
00366             SG_LOG(SG_GL, SG_ALERT, 
00367                     "RenderTexture Error: GetPixelFormat() failed.");
00368             return false;
00369         }
00370     }
00371     else 
00372     {
00373         if (!wglChoosePixelFormatARBPtr(hdc, &_pixelFormatAttribs[0], NULL, 
00374                                      1, &iFormat, &iNumFormats))
00375         {
00376             SG_LOG(SG_GL, SG_ALERT, 
00377                 "RenderTexture Error: wglChoosePixelFormatARB() failed.");
00378             _wglGetLastError();
00379             return false;
00380         }
00381         if ( iNumFormats <= 0 )
00382         {
00383             SG_LOG(SG_GL, SG_ALERT, 
00384                     "RenderTexture Error: Couldn't find a suitable "
00385                     "pixel format.");
00386             _wglGetLastError();
00387             return false;
00388         }
00389     }
00390     
00391     // Create the p-buffer.    
00392     _hPBuffer = wglCreatePbufferARBPtr(hdc, iFormat, _iWidth, _iHeight, 
00393                                     &_pbufferAttribs[0]);
00394     if (!_hPBuffer)
00395     {
00396         SG_LOG(SG_GL, SG_ALERT, 
00397                 "RenderTexture Error: wglCreatePbufferARB() failed.");
00398         _wglGetLastError();
00399         return false;
00400     }
00401     
00402     // Get the device context.
00403     _hDC = wglGetPbufferDCARBPtr( _hPBuffer);
00404     if ( !_hDC )
00405     {
00406         SG_LOG(SG_GL, SG_ALERT, 
00407                 "RenderTexture Error: wglGetGetPbufferDCARB() failed.");
00408         _wglGetLastError();
00409         return false;
00410     }
00411     
00412     // Create a gl context for the p-buffer.
00413     if (_bCopyContext)
00414     {
00415         // Let's use the same gl context..
00416         // Since the device contexts are compatible (i.e. same pixelformat),
00417         // we should be able to use the same gl rendering context.
00418         _hGLContext = hglrc;
00419     }
00420     else
00421     {
00422         _hGLContext = wglCreateContext( _hDC );
00423         if ( !_hGLContext )
00424         {
00425             SG_LOG(SG_GL, SG_ALERT, 
00426                     "RenderTexture Error: wglCreateContext() failed.");
00427             _wglGetLastError();
00428             return false;
00429         }
00430     }
00431     
00432     // Share lists, texture objects, and program objects.
00433     if( _bShareObjects )
00434     {
00435         if( !wglShareLists(hglrc, _hGLContext) )
00436         {
00437             SG_LOG(SG_GL, SG_ALERT, 
00438                     "RenderTexture Error: wglShareLists() failed.");
00439             _wglGetLastError();
00440             return false;
00441         }
00442     }
00443     
00444     // Determine the actual width and height we were able to create.
00445     wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
00446     wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
00447     
00448     _bInitialized = true;
00449     
00450     // get the actual number of bits allocated:
00451     int attrib = WGL_RED_BITS_ARB;
00452     //int bits[6];
00453     int value;
00454     _iNumColorBits[0] = 
00455         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
00456         ? value : 0;
00457     attrib = WGL_GREEN_BITS_ARB;
00458     _iNumColorBits[1] = 
00459         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
00460         ? value : 0;
00461     attrib = WGL_BLUE_BITS_ARB;
00462     _iNumColorBits[2] = 
00463         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
00464         ? value : 0;
00465     attrib = WGL_ALPHA_BITS_ARB;
00466     _iNumColorBits[3] = 
00467         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
00468         ? value : 0; 
00469     attrib = WGL_DEPTH_BITS_ARB;
00470     _iNumDepthBits = 
00471         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
00472         ? value : 0; 
00473     attrib = WGL_STENCIL_BITS_ARB;
00474     _iNumStencilBits = 
00475         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
00476         ? value : 0; 
00477     attrib = WGL_DOUBLE_BUFFER_ARB;
00478     _bDoubleBuffered = 
00479         (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value)) 
00480         ? (value?true:false) : false; 
00481     
00482 #if defined(_DEBUG) | defined(DEBUG)
00483     SG_LOG(SG_GL, SG_ALERT, "Created a " << _iWidth << "x" << _iHeight <<
00484         " RenderTexture with BPP(" <<
00485         _iNumColorBits[0] << "," << _iNumColorBits[1] << "," <<
00486         _iNumColorBits[2] << "," << _iNumColorBits[3] << ")");
00487     if (_iNumDepthBits) SG_LOG(SG_GL, SG_ALERT, " depth=" << _iNumDepthBits);
00488     if (_iNumStencilBits) SG_LOG(SG_GL, SG_ALERT, " stencil=" << _iNumStencilBits);
00489     if (_bDoubleBuffered) SG_LOG(SG_GL, SG_ALERT, " double buffered");
00490 #endif
00491 
00492 #elif defined( __MACH__ )
00493     // Get the current context.
00494     CGLContextObj hglrc = CGLGetCurrentContext();
00495     if (NULL == hglrc)
00496         fprintf(stderr, "Couldn't get current context!");
00497    
00498         CGLPixelFormatObj pixFormat = NULL;
00499         GLint iNumFormats;
00500         CGLError error;
00501 
00502         // Copy the _pixelFormatAttribs into another array to fix
00503         // typecast issues
00504         CGLPixelFormatAttribute *pixFormatAttribs =
00505             (CGLPixelFormatAttribute *)malloc(sizeof(CGLPixelFormatAttribute)
00506                                               * _pixelFormatAttribs.size());
00507 
00508         for (unsigned int ii = 0; ii < _pixelFormatAttribs.size(); ii++)
00509         {
00510             pixFormatAttribs[ii] =
00511                                (CGLPixelFormatAttribute)_pixelFormatAttribs[ii];
00512         }
00513 
00514         if (error =
00515            CGLChoosePixelFormat(&pixFormatAttribs[0], &pixFormat, &iNumFormats))
00516         {
00517             fprintf(stderr,
00518                     "RenderTexture Error: CGLChoosePixelFormat() failed.\n");
00519             _cglCheckError(error);
00520             return false;
00521         }
00522         if ( iNumFormats <= 0 )
00523         {
00524             SG_LOG(SG_GL, SG_ALERT,
00525                     "RenderTexture Error: Couldn't find a suitable "
00526                     "pixel format.");
00527             return false;
00528         }
00529 
00530         // Free the copy of the _pixelFormatAttribs array
00531         free(pixFormatAttribs);
00532    
00533        // Create the context.
00534        error = CGLCreateContext(pixFormat, (_bShareObjects)
00535                 ? CGLGetCurrentContext() : NULL, &_hGLContext);
00536        if (error)
00537        {
00538            fprintf(stderr,
00539                    "RenderTexture Error: CGLCreateContext() failed.\n");
00540            _cglCheckError(error);
00541            return false;
00542        }
00543        CGLDestroyPixelFormat(pixFormat);
00544    
00545        // Create the p-buffer.
00546        error = CGLCreatePBuffer(_iWidth, _iHeight, (_bRectangle)
00547             ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D, GL_RGBA, 0, &_hPBuffer);
00548        if (error)
00549        {
00550            fprintf(stderr,
00551                    "RenderTexture Error: CGLCreatePBuffer() failed.\n");
00552            _cglCheckError(error);
00553            return false;
00554        }
00555 
00556        GLint screen;
00557        if (error = CGLGetVirtualScreen(CGLGetCurrentContext(), &screen))
00558        {
00559            _cglCheckError(error);
00560            return false;
00561        }
00562        if (error = CGLSetPBuffer(_hGLContext, _hPBuffer, 0, 0, screen))
00563        {
00564            _cglCheckError(error);
00565            return false;
00566        }
00567    
00568        // Determine the actual width and height we were able to create.
00569        //wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
00570        //wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
00571    
00572        _bInitialized = true;
00573    
00574        /*
00575        // get the actual number of bits allocated:
00576        int attrib = WGL_RED_BITS_ARB;
00577        //int bits[6];
00578        int value;
00579        _iNumColorBits[0] =
00580             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
00581             ? value : 0;
00582        attrib = WGL_GREEN_BITS_ARB;
00583        _iNumColorBits[1] =
00584             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
00585             ? value : 0;
00586        attrib = WGL_BLUE_BITS_ARB;
00587        _iNumColorBits[2] =
00588             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
00589             ? value : 0;
00590        attrib = WGL_ALPHA_BITS_ARB;
00591        _iNumColorBits[3] =
00592             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
00593             ? value : 0;
00594        attrib = WGL_DEPTH_BITS_ARB;
00595        _iNumDepthBits =
00596             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
00597             ? value : 0;
00598        attrib = WGL_STENCIL_BITS_ARB;
00599        _iNumStencilBits =
00600             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
00601             ? value : 0;
00602        attrib = WGL_DOUBLE_BUFFER_ARB;
00603        _bDoubleBuffered =
00604             (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
00605              ? (value?true:false) : false;
00606        */
00607 
00608 #if defined(_DEBUG) | defined(DEBUG)
00609        fprintf(stderr, "Created a %dx%d RenderTexture with BPP(%d, %d, %d, %d)",
00610            _iWidth, _iHeight,
00611            _iNumColorBits[0], _iNumColorBits[1],
00612            _iNumColorBits[2], _iNumColorBits[3]);
00613        if (_iNumDepthBits) fprintf(stderr, " depth=%d", _iNumDepthBits);
00614        if (_iNumStencilBits) fprintf(stderr, " stencil=%d", _iNumStencilBits);
00615        if (_bDoubleBuffered) fprintf(stderr, " double buffered");
00616        fprintf(stderr, "\n");
00617 #endif
00618 
00619 #else // !_WIN32, !__MACH_
00620     _pDisplay = glXGetCurrentDisplay();
00621     GLXContext context = glXGetCurrentContext();
00622     int screen = DefaultScreen(_pDisplay);
00623     XVisualInfo *visInfo = NULL;
00624     
00625     GLXFBConfig *fbConfigs;
00626     int nConfigs;
00627     
00628     fbConfigs = glXChooseFBConfigPtr(_pDisplay, screen, 
00629                                       &_pixelFormatAttribs[0], &nConfigs);
00630     
00631     if (nConfigs == 0 || !fbConfigs) 
00632     {
00633         SG_LOG(SG_GL, SG_ALERT,
00634             "RenderTexture Error: Couldn't find a suitable pixel format.");
00635         return false;
00636     }
00637     
00638     // Pick the first returned format that will return a pbuffer
00639     if (glXVersion1_3Present)
00640     {
00641         int pbufAttrib[] = {
00642             GLX_PBUFFER_WIDTH,   _iWidth,
00643             GLX_PBUFFER_HEIGHT,  _iHeight,
00644             GLX_LARGEST_PBUFFER, False,
00645             None
00646         };
00647         for (int i=0;i<nConfigs;i++)
00648         {
00649             _hPBuffer = glXCreatePbufferPtr(_pDisplay, fbConfigs[i], pbufAttrib);
00650             if (_hPBuffer)
00651             {
00652                 XVisualInfo *visInfo = glXGetVisualFromFBConfigPtr(_pDisplay, fbConfigs[i]);
00653 
00654                 _hGLContext = glXCreateContextPtr(_pDisplay, visInfo,
00655                                                _bShareObjects ? context : NULL,
00656                                                True);
00657                 if (!_hGLContext)
00658                 {
00659                     return false;
00660                 }
00661                 XFree( visInfo );
00662                 break;
00663             }
00664         }
00665     }
00666     else
00667     {
00668 #ifdef WIN32
00669         int iFormat = 0;
00670         int iNumFormats;
00671         int attrib = 0;
00672 #endif
00673         for (int i=0;i<nConfigs;i++)
00674         {
00675             _hPBuffer = glXCreateGLXPbufferPtr(_pDisplay, fbConfigs[i], 
00676                                                _iWidth, _iHeight, NULL);
00677             if (_hPBuffer) 
00678             {
00679                 _hGLContext = glXCreateContextWithConfigPtr(_pDisplay, 
00680                                                              fbConfigs[i], 
00681                                                              GLX_RGBA_TYPE, 
00682                                                              _bShareObjects ? context : NULL, 
00683                                                              True);
00684                 break;
00685             }
00686         }
00687     }
00688     XFree( fbConfigs );
00689     
00690     if (!_hPBuffer)
00691     {
00692         SG_LOG(SG_GL, SG_ALERT, 
00693                 "RenderTexture Error: glXCreateGLXPbufferPtr() failed.");
00694         return false;
00695     }
00696     
00697     if(!_hGLContext)
00698     {
00699         // Try indirect
00700         _hGLContext = glXCreateContext(_pDisplay, visInfo, 
00701                                        _bShareObjects ? context : NULL, False);
00702         if ( !_hGLContext )
00703         {
00704             SG_LOG(SG_GL, SG_ALERT, 
00705                     "RenderTexture Error: glXCreateContext() failed.");
00706             return false;
00707         }
00708     }
00709     
00710     if (!glXVersion1_3Present)
00711     {
00712         glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_WIDTH_SGIX, 
00713                                   (GLuint*)&_iWidth);
00714         glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_HEIGHT_SGIX, 
00715                                   (GLuint*)&_iHeight);
00716     }
00717     
00718     _bInitialized = true;
00719     
00720     // XXX Query the color format
00721     
00722 #endif
00723 
00724     
00725     // Now that the pbuffer is created, allocate any texture objects needed,
00726     // and initialize them (for CTT updates only).  These must be allocated
00727     // in the context of the pbuffer, though, or the RT won't work without
00728     // wglShareLists.
00729 #ifdef _WIN32
00730     if (false == wglMakeCurrent( _hDC, _hGLContext))
00731     {
00732         _wglGetLastError();
00733         return false;
00734     }
00735 #elif defined( __MACH__ )
00736     CGLError err;
00737     if (err = CGLSetCurrentContext(_hGLContext))
00738     {
00739         _cglCheckError(err);
00740         return false;
00741     }
00742 #else
00743     _hPreviousContext = glXGetCurrentContext();
00744     _hPreviousDrawable = glXGetCurrentDrawable();
00745     
00746     if (False == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext)) 
00747     {
00748         return false;
00749     }
00750 #endif
00751     
00752     bool result = _InitializeTextures();   
00753 #ifdef _WIN32
00754     BindBuffer(WGL_FRONT_LEFT_ARB);
00755     _BindDepthBuffer();
00756 #endif
00757 
00758     
00759 #ifdef _WIN32 
00760     // make the previous rendering context current 
00761     if (false == wglMakeCurrent( hdc, hglrc))
00762     {
00763         _wglGetLastError();
00764         return false;
00765     }
00766 #elif defined( __MACH__ )
00767     if (err = CGLSetCurrentContext(_hPreviousContext))
00768     {
00769         _cglCheckError(err);
00770         return false;
00771     }
00772 #else
00773     if (False == glXMakeCurrent(_pDisplay, 
00774                                 _hPreviousDrawable, _hPreviousContext))
00775     {
00776         return false;
00777     }
00778     if (glXVersion1_3Present)
00779     {
00780         GLXDrawable draw = glXGetCurrentDrawable();
00781         glXQueryDrawablePtr(_pDisplay, draw, GLX_WIDTH, (unsigned int*)&_iWidth);
00782         glXQueryDrawablePtr(_pDisplay, draw, GLX_HEIGHT, (unsigned int*)&_iHeight);
00783     }
00784 #endif
00785 
00786     return result;
00787 }
00788 
00789 
00790 //---------------------------------------------------------------------------
00791 // Function             : RenderTexture::_Invalidate
00792 // Description      : 
00793 //---------------------------------------------------------------------------
00799 bool RenderTexture::_Invalidate()
00800 {
00801     _iNumColorBits[0] = _iNumColorBits[1] = 
00802         _iNumColorBits[2] = _iNumColorBits[3] = 0;
00803     _iNumDepthBits = 0;
00804     _iNumStencilBits = 0;
00805     
00806     if (_bIsTexture)
00807         glDeleteTextures(1, &_iTextureID);
00808     if (_bIsDepthTexture) 
00809     {
00810         // [Redge]
00811         if (!_bHasARBDepthTexture) delete[] _pPoorDepthTexture;
00812         // [/Redge]
00813         glDeleteTextures(1, &_iDepthTextureID);
00814     }
00815     
00816 #ifdef _WIN32
00817     if ( _hPBuffer )
00818     {
00819         // Check if we are currently rendering in the pbuffer
00820         if (wglGetCurrentContext() == _hGLContext)
00821             wglMakeCurrent(0,0);
00822         if (!_bCopyContext) 
00823             wglDeleteContext( _hGLContext);
00824         wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
00825         wglDestroyPbufferARBPtr( _hPBuffer );
00826         _hPBuffer = 0;
00827         return true;
00828     }
00829 #elif defined( __MACH__ )
00830     if ( _hPBuffer )
00831     {
00832         if (CGLGetCurrentContext() == _hGLContext)
00833             CGLSetCurrentContext(NULL);
00834         if (!_bCopyContext)
00835             CGLDestroyContext(_hGLContext);
00836         CGLDestroyPBuffer(_hPBuffer);
00837         _hPBuffer = NULL;
00838         return true;
00839     }
00840 #else
00841     if ( _hPBuffer )
00842     {
00843         if(glXGetCurrentContext() == _hGLContext)
00844             // XXX I don't know if this is right at all
00845             glXMakeCurrent(_pDisplay, _hPBuffer, 0);
00846         glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
00847         _hPBuffer = 0;
00848         return true;
00849     }
00850 #endif
00851 
00852     // [WVB] do we need to call _ReleaseBoundBuffers() too?
00853     return false;
00854 }
00855 
00856 
00857 //---------------------------------------------------------------------------
00858 // Function             : RenderTexture::Reset
00859 // Description      : 
00860 //---------------------------------------------------------------------------
00868 bool RenderTexture::Reset(const char *strMode, ...)
00869 {
00870     _iWidth = 0; _iHeight = 0; 
00871     _bIsTexture = false; _bIsDepthTexture = false,
00872     _bHasARBDepthTexture = true;
00873 #if defined(_WIN32) || defined(__MACH__)
00874     _eUpdateMode = RT_RENDER_TO_TEXTURE;
00875 #else
00876     _eUpdateMode = RT_COPY_TO_TEXTURE;
00877 #endif
00878     _bInitialized = false;
00879     _iNumAuxBuffers = 0; 
00880     _bIsBufferBound = false;
00881     _iCurrentBoundBuffer = 0;
00882     _iNumDepthBits = 0; _iNumStencilBits = 0;
00883     _bDoubleBuffered = false;
00884     _bFloat = false; _bPowerOf2 = true;
00885     _bRectangle = false; _bMipmap = false; 
00886     _bShareObjects = false; _bCopyContext = false; 
00887     _iTextureTarget = GL_NONE; _iTextureID = 0; 
00888     _iDepthTextureID = 0;
00889     _pPoorDepthTexture = 0;
00890     _pixelFormatAttribs.clear();
00891     _pbufferAttribs.clear();
00892 
00893     if (IsInitialized() && !_Invalidate())
00894     {
00895         SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Reset(): failed to invalidate.");
00896         return false;
00897     }
00898     
00899     _iNumColorBits[0] = _iNumColorBits[1] = 
00900         _iNumColorBits[2] = _iNumColorBits[3] = 0;
00901 
00902 #ifdef _WIN32
00903     _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
00904     _pixelFormatAttribs.push_back(true);
00905     _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
00906     _pixelFormatAttribs.push_back(true);
00907     
00908     _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
00909     _pbufferAttribs.push_back(true);
00910 #elif defined( __MACH__ )
00911     //_pixelFormatAttribs.push_back(kCGLPFANoRecovery);
00912     _pixelFormatAttribs.push_back(kCGLPFAAccelerated);
00913     _pixelFormatAttribs.push_back(kCGLPFAWindow);
00914     _pixelFormatAttribs.push_back(kCGLPFAPBuffer);
00915 #else
00916     _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
00917     _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
00918     _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
00919     _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
00920 #endif
00921 
00922     va_list args;
00923     char strBuffer[256];
00924     va_start(args,strMode);
00925 #if defined _WIN32 && !defined __CYGWIN__
00926     _vsnprintf( strBuffer, 256, strMode, args );
00927 #else
00928     vsnprintf( strBuffer, 256, strMode, args );
00929 #endif
00930     va_end(args);
00931 
00932     _ParseModeString(strBuffer, _pixelFormatAttribs, _pbufferAttribs);
00933 
00934 #ifdef _WIN32
00935     _pixelFormatAttribs.push_back(0);
00936     _pbufferAttribs.push_back(0);
00937 #elif defined(__MACH__)
00938     _pixelFormatAttribs.push_back((CGLPixelFormatAttribute)0);
00939 #else
00940     _pixelFormatAttribs.push_back(None);
00941 #endif
00942     return true;
00943 }
00944 
00945 //------------------------------------------------------------------------------
00946 // Function               : RenderTexture::Resize
00947 // Description      : 
00948 //------------------------------------------------------------------------------
00958 bool RenderTexture::Resize(int iWidth, int iHeight)
00959 {
00960     if (!_bInitialized) {
00961         SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): must Initialize() first.");
00962         return false;
00963     }
00964     if (iWidth == _iWidth && iHeight == _iHeight) {
00965         return true;
00966     }
00967     
00968     // Do same basic work as _Invalidate, but don't reset all our flags
00969     if (_bIsTexture)
00970         glDeleteTextures(1, &_iTextureID);
00971     if (_bIsDepthTexture)
00972         glDeleteTextures(1, &_iDepthTextureID);
00973 #ifdef _WIN32
00974     if ( _hPBuffer )
00975     {
00976         // Check if we are currently rendering in the pbuffer
00977         if (wglGetCurrentContext() == _hGLContext)
00978             wglMakeCurrent(0,0);
00979         if (!_bCopyContext) 
00980             wglDeleteContext( _hGLContext);
00981         wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
00982         wglDestroyPbufferARBPtr( _hPBuffer );
00983         _hPBuffer = 0;
00984         return true;
00985     }
00986 #elif defined( __MACH__ )
00987     if ( _hPBuffer )
00988     {
00989         if (CGLGetCurrentContext() == _hGLContext)
00990             CGLSetCurrentContext(NULL);
00991         if (!_bCopyContext)
00992             CGLDestroyContext(_hGLContext);
00993         CGLDestroyPBuffer(_hPBuffer);
00994         _hPBuffer = NULL;
00995         return true;
00996     }
00997 #else
00998     if ( _hPBuffer )
00999     {
01000         if(glXGetCurrentContext() == _hGLContext)
01001             // XXX I don't know if this is right at all
01002             glXMakeCurrent(_pDisplay, _hPBuffer, 0);
01003         glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
01004         _hPBuffer = 0;
01005     }
01006 #endif
01007     else {
01008         SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): failed to resize.");
01009         return false;
01010     }
01011     _bInitialized = false;
01012     return Initialize(iWidth, iHeight, _bShareObjects, _bCopyContext);
01013 }
01014 
01015 //---------------------------------------------------------------------------
01016 // Function             : RenderTexture::BeginCapture
01017 // Description      : 
01018 //---------------------------------------------------------------------------
01023 bool RenderTexture::BeginCapture()
01024 {
01025     if (!_bInitialized)
01026     {
01027         SG_LOG(SG_GL, SG_ALERT, 
01028                 "RenderTexture::BeginCapture(): Texture is not initialized!");
01029         return false;
01030     }
01031 #ifdef _WIN32
01032     // cache the current context so we can reset it when EndCapture() is called.
01033     _hPreviousDC      = wglGetCurrentDC();
01034     if (NULL == _hPreviousDC)
01035         _wglGetLastError();
01036     _hPreviousContext = wglGetCurrentContext();
01037     if (NULL == _hPreviousContext)
01038         _wglGetLastError();
01039 #elif defined( __MACH__ )
01040     _hPreviousContext = CGLGetCurrentContext();
01041 #else
01042     _hPreviousContext = glXGetCurrentContext();
01043     _hPreviousDrawable = glXGetCurrentDrawable();
01044 #endif
01045 
01046     _ReleaseBoundBuffers();
01047 
01048     return _MakeCurrent();
01049 }
01050 
01051 
01052 //---------------------------------------------------------------------------
01053 // Function             : RenderTexture::EndCapture
01054 // Description      : 
01055 //---------------------------------------------------------------------------
01060 bool RenderTexture::EndCapture()
01061 {    
01062     if (!_bInitialized)
01063     {
01064         SG_LOG(SG_GL, SG_ALERT, 
01065                 "RenderTexture::EndCapture() : Texture is not initialized!");
01066         return false;
01067     }
01068 
01069     glFlush();  // Added by a-lex
01070 
01071     _MaybeCopyBuffer();
01072 
01073 #ifdef _WIN32
01074     // make the previous rendering context current 
01075     if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
01076     {
01077         _wglGetLastError();
01078         return false;
01079     }
01080 #elif defined( __MACH__ )
01081     CGLError err;
01082     if (err = CGLSetCurrentContext(_hPreviousContext))
01083     {
01084             _cglCheckError(err);
01085             return false;
01086     }
01087 #else
01088     if (False == glXMakeCurrent(_pDisplay, _hPreviousDrawable, 
01089                                 _hPreviousContext))
01090     {
01091         return false;
01092     }
01093 #endif
01094 
01095     // rebind the textures to a buffers for RTT
01096     BindBuffer(_iCurrentBoundBuffer);
01097     _BindDepthBuffer();
01098 
01099     return true;
01100 }
01101 
01102 //---------------------------------------------------------------------------
01103 // Function               : RenderTexture::BeginCapture(RenderTexture*)
01104 // Description      : 
01105 //---------------------------------------------------------------------------
01120 bool RenderTexture::BeginCapture(RenderTexture* current)
01121 {
01122     // bool bContextReset = false;
01123     
01124     if (current == this) {
01125         return true; // no switch necessary
01126     }
01127     if (!current) {
01128         // treat as normal Begin if current is 0.
01129         return BeginCapture();
01130     }
01131     if (!_bInitialized)
01132     {
01133         SG_LOG(SG_GL, SG_ALERT, 
01134             "RenderTexture::BeginCapture(RenderTexture*): Texture is not initialized!");
01135         return false;
01136     }
01137     if (!current->_bInitialized)
01138     {
01139         SG_LOG(SG_GL, SG_ALERT, 
01140             "RenderTexture::BeginCapture(RenderTexture): 'current' texture is not initialized!");
01141         return false;
01142     }
01143     
01144     // Sync current pbuffer with its CTT texture if necessary
01145     current->_MaybeCopyBuffer();
01146 
01147     // pass along the previous context so we can reset it when 
01148     // EndCapture() is called.
01149 #ifdef _WIN32
01150     _hPreviousDC      = current->_hPreviousDC;
01151     if (NULL == _hPreviousDC)
01152         _wglGetLastError();
01153     _hPreviousContext = current->_hPreviousContext;
01154     if (NULL == _hPreviousContext)
01155         _wglGetLastError();
01156 #elif defined( __MACH__ )
01157     _hPreviousContext = current->_hPreviousContext;
01158 #else
01159     _hPreviousContext = current->_hPreviousContext;
01160     _hPreviousDrawable = current->_hPreviousDrawable;
01161 #endif    
01162 
01163     // Unbind textures before making context current
01164     if (!_ReleaseBoundBuffers()) 
01165       return false;
01166 
01167     // Make the pbuffer context current
01168     if (!_MakeCurrent())
01169         return false;
01170 
01171     // Rebind buffers of initial RenderTexture
01172     current->BindBuffer(_iCurrentBoundBuffer);
01173     current->_BindDepthBuffer();
01174     
01175     return true;
01176 }
01177 
01178 
01179 
01180 //---------------------------------------------------------------------------
01181 // Function             : RenderTexture::Bind
01182 // Description      : 
01183 //---------------------------------------------------------------------------
01188 void RenderTexture::Bind() const 
01189 { 
01190     if (_bInitialized && _bIsTexture) 
01191     {
01192         glBindTexture(_iTextureTarget, _iTextureID);
01193     }    
01194 }
01195 
01196 
01197 //---------------------------------------------------------------------------
01198 // Function             : RenderTexture::BindDepth
01199 // Description      : 
01200 //---------------------------------------------------------------------------
01205 void RenderTexture::BindDepth() const 
01206 { 
01207     if (_bInitialized && _bIsDepthTexture) 
01208     {
01209         glBindTexture(_iTextureTarget, _iDepthTextureID); 
01210     }
01211 }
01212 
01213 
01214 //---------------------------------------------------------------------------
01215 // Function             : RenderTexture::BindBuffer
01216 // Description      : 
01217 //---------------------------------------------------------------------------
01222 bool RenderTexture::BindBuffer( int iBuffer )
01223 { 
01224     // Must bind the texture too
01225     if (_bInitialized && _bIsTexture) 
01226     {
01227         glBindTexture(_iTextureTarget, _iTextureID);
01228         
01229 #ifdef _WIN32
01230         if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
01231             (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
01232         {
01233             if (FALSE == wglBindTexImageARBPtr(_hPBuffer, iBuffer))
01234             {
01235                 //  WVB: WGL API considers binding twice to the same buffer
01236                 //  to be an error.  But we don't want to 
01237                 //_wglGetLastError();
01238                 //return false;
01239                 SetLastError(0);
01240             }
01241             _bIsBufferBound = true;
01242             _iCurrentBoundBuffer = iBuffer;
01243         }
01244 #elif defined(__MACH__)
01245     if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
01246          (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
01247     {
01248         CGLError err;
01249         if (err=CGLTexImagePBuffer(CGLGetCurrentContext(), _hPBuffer, iBuffer))
01250         {
01251             _cglCheckError(err);
01252         }
01253         _bIsBufferBound = true;
01254         _iCurrentBoundBuffer = iBuffer;
01255      }
01256 #endif
01257     }    
01258     return true;
01259 }
01260 
01261 
01262 //---------------------------------------------------------------------------
01263 // Function             : RenderTexture::BindDepthBuffer
01264 // Description      : 
01265 //---------------------------------------------------------------------------
01270 bool RenderTexture::_BindDepthBuffer() const
01271 {
01272 #ifdef WIN32
01273     if (_bInitialized && _bIsDepthTexture && 
01274         RT_RENDER_TO_TEXTURE == _eUpdateMode)
01275     {
01276         glBindTexture(_iTextureTarget, _iDepthTextureID);
01277         if (FALSE == wglBindTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
01278         {
01279             _wglGetLastError();
01280             return false;
01281         }
01282     }
01283 #elif defined(__MACH__)
01284     if (_bInitialized && _bIsDepthTexture &&
01285         RT_RENDER_TO_TEXTURE == _eUpdateMode)
01286     {
01287         glBindTexture(_iTextureTarget, _iDepthTextureID);
01288         //if (FALSE == CGLTexImagePBuffer(<#CGLContextObj ctx#>,<#CGLPBufferObj pbuffer#>,<#unsigned long source#>)(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
01289         //{
01290         //    _wglGetLastError();
01291         //    return false;
01292         //}
01293     }
01294 #endif
01295     return true;
01296 }
01297 
01298 //---------------------------------------------------------------------------
01299 // Function             : RenderTexture::_ParseModeString
01300 // Description      : 
01301 //---------------------------------------------------------------------------
01306 void RenderTexture::_ParseModeString(const char *modeString, 
01307                                      vector<int> &pfAttribs, 
01308                                      vector<int> &pbAttribs)
01309 {
01310     if (!modeString || strcmp(modeString, "") == 0)
01311         return;
01312 
01313         _iNumComponents = 0;
01314 #if defined(_WIN32) || defined(__MACH__)
01315     _eUpdateMode = RT_RENDER_TO_TEXTURE;
01316 #else
01317     _eUpdateMode = RT_COPY_TO_TEXTURE;
01318 #endif
01319     
01320     int  iDepthBits = 0;
01321     bool bHasStencil = false;
01322     bool bBind2D   = false;
01323     bool bBindRECT = false;
01324     bool bBindCUBE = false;
01325     
01326     char *mode = strdup(modeString);
01327     
01328 
01329     vector<string> tokens;
01330     char *buf = strtok(mode, " ");
01331     while (buf != NULL)
01332     {
01333         tokens.push_back(buf);
01334         buf = strtok(NULL, " ");
01335     }
01336     free(mode);
01337     for (unsigned int i = 0; i < tokens.size(); i++)
01338     {
01339         string token = tokens[i];
01340 
01341         KeyVal kv = _GetKeyValuePair(token);
01342         
01343         
01344         if (kv.first == "rgb" && (_iNumComponents <= 1))
01345         {           
01346             if (kv.second.find("f") != kv.second.npos)
01347                 _bFloat = true;
01348 
01349             vector<int> bitVec = _ParseBitVector(kv.second);
01350 
01351             if (bitVec.size() < 3) // expand the scalar to a vector
01352             {
01353                 bitVec.push_back(bitVec[0]);
01354                 bitVec.push_back(bitVec[0]);
01355             }
01356 
01357 #ifdef _WIN32
01358             pfAttribs.push_back(WGL_RED_BITS_ARB);
01359             pfAttribs.push_back(bitVec[0]);
01360             pfAttribs.push_back(WGL_GREEN_BITS_ARB);
01361             pfAttribs.push_back(bitVec[1]);
01362             pfAttribs.push_back(WGL_BLUE_BITS_ARB);
01363             pfAttribs.push_back(bitVec[2]);
01364 #elif defined( __MACH__ )
01365 # if 0
01366             pfAttribs.push_back(AGL_RED_SIZE);
01367             pfAttribs.push_back(bitVec[0]);
01368             pfAttribs.push_back(AGL_GREEN_SIZE);
01369             pfAttribs.push_back(bitVec[1]);
01370             pfAttribs.push_back(AGL_BLUE_SIZE);
01371             pfAttribs.push_back(bitVec[2]);
01372 # else
01373             pfAttribs.push_back(kCGLPFAColorSize);
01374             pfAttribs.push_back(bitVec[0] + bitVec[1] + bitVec[2]);
01375 # endif
01376 #else
01377             pfAttribs.push_back(GLX_RED_SIZE);
01378             pfAttribs.push_back(bitVec[0]);
01379             pfAttribs.push_back(GLX_GREEN_SIZE);
01380             pfAttribs.push_back(bitVec[1]);
01381             pfAttribs.push_back(GLX_BLUE_SIZE);
01382             pfAttribs.push_back(bitVec[2]);
01383 #endif
01384             _iNumComponents += 3;
01385             continue;
01386         }
01387                 else if (kv.first == "rgb") 
01388             SG_LOG(SG_GL, SG_ALERT, 
01389                     "RenderTexture Warning: mistake in components definition "
01390                     "(rgb + " << _iNumComponents << ").");
01391         
01392         if (kv.first == "rgba" && (_iNumComponents == 0))
01393         {
01394             if (kv.second.find("f") != kv.second.npos)
01395                 _bFloat = true;
01396 
01397             vector<int> bitVec = _ParseBitVector(kv.second);
01398 
01399             if (bitVec.size() < 4) // expand the scalar to a vector
01400             {
01401                 bitVec.push_back(bitVec[0]);
01402                 bitVec.push_back(bitVec[0]);
01403                 bitVec.push_back(bitVec[0]);
01404             }
01405 
01406 #ifdef _WIN32
01407             pfAttribs.push_back(WGL_RED_BITS_ARB);
01408             pfAttribs.push_back(bitVec[0]);
01409             pfAttribs.push_back(WGL_GREEN_BITS_ARB);
01410             pfAttribs.push_back(bitVec[1]);
01411             pfAttribs.push_back(WGL_BLUE_BITS_ARB);
01412             pfAttribs.push_back(bitVec[2]);
01413             pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
01414             pfAttribs.push_back(bitVec[3]);
01415 #elif defined( __MACH__ )
01416 # if 0 
01417             pfAttribs.push_back(AGL_RED_SIZE);
01418             pfAttribs.push_back(bitVec[0]);
01419             pfAttribs.push_back(AGL_GREEN_SIZE);
01420             pfAttribs.push_back(bitVec[1]);
01421             pfAttribs.push_back(AGL_BLUE_SIZE);
01422             pfAttribs.push_back(bitVec[2]);
01423             pfAttribs.push_back(AGL_ALPHA_SIZE);
01424             pfAttribs.push_back(bitVec[3]);
01425 # else
01426             pfAttribs.push_back(kCGLPFAColorSize);
01427             pfAttribs.push_back(bitVec[0] + bitVec[1] + bitVec[2] + bitVec[3]);
01428             //pfAttribs.push_back(kCGLPFAAlphaSize);
01429             //pfAttribs.push_back(bitVec[3]);
01430             // printf("Color size: %d\n", bitVec[0] + bitVec[1] + bitVec[2] + bitVec[3]);
01431 
01432 # endif
01433 #else
01434             pfAttribs.push_back(GLX_RED_SIZE);
01435             pfAttribs.push_back(bitVec[0]);
01436             pfAttribs.push_back(GLX_GREEN_SIZE);
01437             pfAttribs.push_back(bitVec[1]);
01438             pfAttribs.push_back(GLX_BLUE_SIZE);
01439             pfAttribs.push_back(bitVec[2]);
01440             pfAttribs.push_back(GLX_ALPHA_SIZE);
01441             pfAttribs.push_back(bitVec[3]);
01442 #endif
01443             _iNumComponents = 4;
01444             continue;
01445         }
01446                 else if (kv.first == "rgba") 
01447             SG_LOG(SG_GL, SG_ALERT, 
01448                     "RenderTexture Warning: mistake in components definition "
01449                     "(rgba + " << _iNumComponents << ").");
01450         
01451         if (kv.first == "r" && (_iNumComponents <= 1))
01452         {
01453             if (kv.second.find("f") != kv.second.npos)
01454                 _bFloat = true;
01455 
01456             vector<int> bitVec = _ParseBitVector(kv.second);
01457 
01458 #ifdef _WIN32
01459             pfAttribs.push_back(WGL_RED_BITS_ARB);
01460             pfAttribs.push_back(bitVec[0]);
01461 #elif defined( __MACH__ )
01462 # if 0
01463             pfAttribs.push_back(AGL_RED_SIZE);
01464             pfAttribs.push_back(bitVec[0]);
01465 # else
01466             pfAttribs.push_back(kCGLPFAColorSize);
01467             pfAttribs.push_back(bitVec[0]);
01468 # endif
01469 #else
01470             pfAttribs.push_back(GLX_RED_SIZE);
01471             pfAttribs.push_back(bitVec[0]);
01472 #endif
01473                         _iNumComponents++;
01474             continue;
01475         }
01476         else if (kv.first == "r") 
01477             SG_LOG(SG_GL, SG_ALERT, 
01478                     "RenderTexture Warning: mistake in components definition "
01479                     "(r + " << _iNumComponents << ").");
01480 
01481         if (kv.first == "rg" && (_iNumComponents <= 1))
01482         {
01483             if (kv.second.find("f") != kv.second.npos)
01484                 _bFloat = true;
01485 
01486             vector<int> bitVec = _ParseBitVector(kv.second);
01487 
01488             if (bitVec.size() < 2) // expand the scalar to a vector
01489             {
01490                 bitVec.push_back(bitVec[0]);
01491             }
01492 
01493 #ifdef _WIN32
01494             pfAttribs.push_back(WGL_RED_BITS_ARB);
01495             pfAttribs.push_back(bitVec[0]);
01496             pfAttribs.push_back(WGL_GREEN_BITS_ARB);
01497             pfAttribs.push_back(bitVec[1]);
01498 #elif defined( __MACH__ )
01499 # if 0
01500             pfAttribs.push_back(AGL_RED_SIZE);
01501             pfAttribs.push_back(bitVec[0]);
01502             pfAttribs.push_back(AGL_GREEN_SIZE);
01503             pfAttribs.push_back(bitVec[1]);
01504 # else
01505             pfAttribs.push_back(kCGLPFAColorSize);
01506             pfAttribs.push_back(bitVec[0] + bitVec[1]);
01507 # endif
01508 #else
01509             pfAttribs.push_back(GLX_RED_SIZE);
01510             pfAttribs.push_back(bitVec[0]);
01511             pfAttribs.push_back(GLX_GREEN_SIZE);
01512             pfAttribs.push_back(bitVec[1]);
01513 #endif
01514                         _iNumComponents += 2;
01515             continue;
01516         }
01517                 else if (kv.first == "rg") 
01518             SG_LOG(SG_GL, SG_ALERT, 
01519                     "RenderTexture Warning: mistake in components definition "
01520                     "(rg + " << _iNumComponents << ").");
01521 
01522         if (kv.first == "depth")
01523         {
01524             if (kv.second == "")
01525                 iDepthBits = 24;
01526             else
01527                 iDepthBits = strtol(kv.second.c_str(), 0, 10);
01528             continue;
01529         }
01530 
01531         if (kv.first == "stencil")
01532         {
01533             bHasStencil = true;
01534 #ifdef _WIN32
01535             pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
01536 #elif defined( __MACH__ )
01537 # if 0
01538             pfAttribs.push_back(AGL_STENCIL_SIZE);
01539 # else
01540             pfAttribs.push_back(kCGLPFAStencilSize);
01541 # endif
01542 #else
01543             pfAttribs.push_back(GLX_STENCIL_SIZE);
01544 #endif
01545             if (kv.second == "")
01546                 pfAttribs.push_back(8);
01547             else
01548                 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
01549             continue;
01550         }
01551 
01552         if (kv.first == "samples")
01553         {
01554 #ifdef _WIN32
01555             pfAttribs.push_back(WGL_SAMPLE_BUFFERS_ARB);
01556             pfAttribs.push_back(1);
01557             pfAttribs.push_back(WGL_SAMPLES_ARB);
01558             pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
01559 #elif defined( __MACH__ )
01560 # if 0
01561             pfAttribs.push_back(AGL_SAMPLE_BUFFERS_ARB);
01562             pfAttribs.push_back(1);
01563             pfAttribs.push_back(AGL_SAMPLES_ARB);
01564 # else
01565             pfAttribs.push_back(kCGLPFAMultisample);
01566             pfAttribs.push_back(kCGLPFASamples);
01567 # endif
01568             pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
01569 #else
01570             pfAttribs.push_back(GLX_SAMPLE_BUFFERS_ARB);
01571             pfAttribs.push_back(1);
01572             pfAttribs.push_back(GLX_SAMPLES_ARB);
01573             pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
01574 #endif
01575             continue;
01576 
01577         }
01578 
01579         if (kv.first == "doublebuffer" || kv.first == "double")
01580         {
01581 #ifdef _WIN32
01582             pfAttribs.push_back(WGL_DOUBLE_BUFFER_ARB);
01583             pfAttribs.push_back(true);
01584 #elif defined( __MACH__ )
01585 # if 0
01586             pfAttribs.push_back(AGL_DOUBLEBUFFER);
01587             pfAttribs.push_back(True);
01588 # else
01589             pfAttribs.push_back(kCGLPFADoubleBuffer);
01590 # endif
01591 #else
01592             pfAttribs.push_back(GLX_DOUBLEBUFFER);
01593             pfAttribs.push_back(True);
01594 #endif
01595             continue;
01596         }  
01597         
01598         if (kv.first == "aux")
01599         {
01600 #ifdef _WIN32
01601             pfAttribs.push_back(WGL_AUX_BUFFERS_ARB);
01602 #elif defined( __MACH__ )
01603 # if 0
01604             pfAttribs.push_back(AGL_AUX_BUFFERS);
01605 # else
01606             pfAttribs.push_back(kCGLPFAAuxBuffers);
01607 # endif
01608 #else
01609             pfAttribs.push_back(GLX_AUX_BUFFERS);
01610 #endif
01611             if (kv.second == "")
01612                 pfAttribs.push_back(0);
01613             else
01614                 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
01615             continue;
01616         }
01617         
01618         if (token.find("tex") == 0)
01619         {            
01620             _bIsTexture = true;
01621             
01622             if ((kv.first == "texRECT") && (GL_NV_texture_rectangle ||
01623                                             GL_EXT_texture_rectangle))
01624             {
01625                 _bRectangle = true;
01626                 bBindRECT = true;
01627             }
01628             else if (kv.first == "texCUBE")
01629             {
01630                 bBindCUBE = true;
01631             }
01632             else
01633             {
01634                 bBind2D = true;
01635             }
01636 
01637             continue;
01638         }
01639 
01640         if (token.find("depthTex") == 0)
01641         {
01642             _bIsDepthTexture = true;
01643             
01644             if ((kv.first == "depthTexRECT") && (GL_NV_texture_rectangle ||
01645                                                  GL_EXT_texture_rectangle))
01646             {
01647                 _bRectangle = true;
01648                 bBindRECT = true;
01649             }
01650             else if (kv.first == "depthTexCUBE")
01651             {
01652                 bBindCUBE = true;
01653             }
01654             else