1 // File : RenderTexture.cpp
2 //---------------------------------------------------------------------------
3 // Copyright (c) 2002-2004 Mark J. Harris
4 //---------------------------------------------------------------------------
5 // This software is provided 'as-is', without any express or implied
6 // warranty. In no event will the authors be held liable for any
7 // damages arising from the use of this software.
9 // Permission is granted to anyone to use this software for any
10 // purpose, including commercial applications, and to alter it and
11 // redistribute it freely, subject to the following restrictions:
13 // 1. The origin of this software must not be misrepresented; you
14 // must not claim that you wrote the original software. If you use
15 // this software in a product, an acknowledgment in the product
16 // documentation would be appreciated but is not required.
18 // 2. Altered source versions must be plainly marked as such, and
19 // must not be misrepresented as being the original software.
21 // 3. This notice may not be removed or altered from any source
24 // --------------------------------------------------------------------------
26 // Original RenderTexture class: Mark J. Harris
27 // Original Render to Depth Texture support: Thorsten Scheuermann
28 // Linux Copy-to-texture: Eric Werness
29 // OS X: Alexander Powell (someone please help)
30 // Various Bug Fixes: Daniel (Redge) Sperl
33 // --------------------------------------------------------------------------
35 * @file RenderTexture.cpp
37 * Implementation of class RenderTexture. A multi-format render to
40 #pragma warning(disable:4786)
45 * Jan. 2005, Removed GLEW dependencies, Erik Hofman, Fred Bouvier
46 * Nov. 2005, Use the simgear logging facility, Erik Hofman
47 * Mar. 2006, Add MAC OS X support, Alexander Powell
51 # include <simgear_config.h>
58 #include <simgear/compiler.h>
59 #include <simgear/debug/logstream.hxx>
60 #include <simgear/screen/extensions.hxx>
61 #include <simgear/screen/RenderTexture.h>
69 #pragma comment(lib, "gdi32.lib") // required for GetPixelFormat()
75 static bool fctPtrInited = false;
76 /* WGL_ARB_pixel_format */
77 static wglChoosePixelFormatARBProc wglChoosePixelFormatARBPtr = 0;
78 static wglGetPixelFormatAttribivARBProc wglGetPixelFormatAttribivARBPtr = 0;
80 static wglCreatePbufferARBProc wglCreatePbufferARBPtr = 0;
81 static wglGetPbufferDCARBProc wglGetPbufferDCARBPtr = 0;
82 static wglQueryPbufferARBProc wglQueryPbufferARBPtr = 0;
83 static wglReleasePbufferDCARBProc wglReleasePbufferDCARBPtr = 0;
84 static wglDestroyPbufferARBProc wglDestroyPbufferARBPtr = 0;
85 /* WGL_ARB_render_texture */
86 static wglBindTexImageARBProc wglBindTexImageARBPtr = 0;
87 static wglReleaseTexImageARBProc wglReleaseTexImageARBPtr = 0;
89 #elif defined( __MACH__ )
91 static bool glXVersion1_3Present = false;
92 static glXChooseFBConfigProc glXChooseFBConfigPtr = 0;
93 static glXCreatePbufferProc glXCreatePbufferPtr = 0;
94 static glXCreateGLXPbufferProc glXCreateGLXPbufferPtr = 0;
95 static glXGetVisualFromFBConfigProc glXGetVisualFromFBConfigPtr = 0;
96 static glXCreateContextProc glXCreateContextPtr = 0;
97 static glXCreateContextWithConfigProc glXCreateContextWithConfigPtr = 0;
98 static glXDestroyPbufferProc glXDestroyPbufferPtr = 0;
99 static glXQueryDrawableProc glXQueryDrawablePtr = 0;
100 static glXQueryGLXPbufferSGIXProc glXQueryGLXPbufferSGIXPtr = 0;
103 //---------------------------------------------------------------------------
104 // Function : RenderTexture::RenderTexture
106 //---------------------------------------------------------------------------
108 * @fn RenderTexture::RenderTexture()
109 * @brief Mode-string-based Constructor.
111 RenderTexture::RenderTexture(const char *strMode)
115 _bIsDepthTexture(false),
116 _bHasARBDepthTexture(true), // [Redge]
117 #if defined(_WIN32) || defined(__MACH__)
118 _eUpdateMode(RT_RENDER_TO_TEXTURE),
120 _eUpdateMode(RT_COPY_TO_TEXTURE),
122 _bInitialized(false),
124 _bIsBufferBound(false),
125 _iCurrentBoundBuffer(0),
129 _bDoubleBuffered(false),
133 _bShareObjects(false),
134 _bCopyContext(false),
140 _hPreviousContext(0),
141 #elif defined( __MACH__ )
144 _hPreviousContext(NULL),
149 _hPreviousContext(0),
150 _hPreviousDrawable(0),
152 _iTextureTarget(GL_NONE),
155 _pPoorDepthTexture(0) // [Redge]
157 _iNumColorBits[0] = _iNumColorBits[1] =
158 _iNumColorBits[2] = _iNumColorBits[3] = 0;
161 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
162 _pixelFormatAttribs.push_back(true);
163 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
164 _pixelFormatAttribs.push_back(true);
166 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
167 _pbufferAttribs.push_back(true);
168 #elif defined( __MACH__ )
169 //_pixelFormatAttribs.push_back(kCGLPFANoRecovery);
170 _pixelFormatAttribs.push_back(kCGLPFAAccelerated);
171 _pixelFormatAttribs.push_back(kCGLPFAWindow);
172 _pixelFormatAttribs.push_back(kCGLPFAPBuffer);
174 _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
175 _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
176 _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
177 _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
180 _ParseModeString(strMode, _pixelFormatAttribs, _pbufferAttribs);
183 _pixelFormatAttribs.push_back(0);
184 _pbufferAttribs.push_back(0);
185 #elif defined(__MACH__)
186 _pixelFormatAttribs.push_back((CGLPixelFormatAttribute)0);
187 _pbufferAttribs.push_back((CGLPixelFormatAttribute)0);
189 _pixelFormatAttribs.push_back(None);
194 //---------------------------------------------------------------------------
195 // Function : RenderTexture::~RenderTexture
197 //---------------------------------------------------------------------------
199 * @fn RenderTexture::~RenderTexture()
202 RenderTexture::~RenderTexture()
207 //---------------------------------------------------------------------------
208 // Function : _cglcheckError
210 //---------------------------------------------------------------------------
212 * @fn _cglCheckError()
213 * @brief Prints to stderr a description when an OS X error is found.
216 static void _cglCheckErrorHelper(CGLError err, char *sourceFile, int sourceLine)
221 fprintf(stderr, "RenderTexture CGL Error: %s at (%s,%d)",
222 CGLErrorString(err), sourceFile, sourceLine);
227 # define _cglCheckError(err) _cglCheckErrorHelper(err,__FILE__,__LINE__)
232 //---------------------------------------------------------------------------
233 // Function : _wglGetLastError
235 //---------------------------------------------------------------------------
237 * @fn wglGetLastError()
238 * @brief Returns the last windows error generated.
241 void _wglGetLastError()
245 DWORD err = GetLastError();
248 case ERROR_INVALID_PIXEL_FORMAT:
249 SG_LOG(SG_GL, SG_ALERT,
250 "RenderTexture Win32 Error: ERROR_INVALID_PIXEL_FORMAT");
252 case ERROR_NO_SYSTEM_RESOURCES:
253 SG_LOG(SG_GL, SG_ALERT,
254 "RenderTexture Win32 Error: ERROR_NO_SYSTEM_RESOURCES");
256 case ERROR_INVALID_DATA:
257 SG_LOG(SG_GL, SG_ALERT,
258 "RenderTexture Win32 Error: ERROR_INVALID_DATA");
260 case ERROR_INVALID_WINDOW_HANDLE:
261 SG_LOG(SG_GL, SG_ALERT,
262 "RenderTexture Win32 Error: ERROR_INVALID_WINDOW_HANDLE");
264 case ERROR_RESOURCE_TYPE_NOT_FOUND:
265 SG_LOG(SG_GL, SG_ALERT,
266 "RenderTexture Win32 Error: ERROR_RESOURCE_TYPE_NOT_FOUND");
273 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
274 FORMAT_MESSAGE_FROM_SYSTEM |
275 FORMAT_MESSAGE_IGNORE_INSERTS,
278 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
283 SG_LOG(SG_GL, SG_ALERT, "RenderTexture Win32 Error " << err << ":" << lpMsgBuf);
284 LocalFree( lpMsgBuf );
293 //---------------------------------------------------------------------------
294 // Function : PrintExtensionError
296 //---------------------------------------------------------------------------
298 * @fn PrintExtensionError( char* strMsg, ... )
299 * @brief Prints an error about missing OpenGL extensions.
301 void PrintExtensionError( char* strMsg, ... )
303 SG_LOG(SG_GL, SG_ALERT,
304 "Error: RenderTexture requires the following unsupported "
305 "OpenGL extensions: ");
308 va_start(args, strMsg);
309 #if defined _WIN32 && !defined __CYGWIN__
310 _vsnprintf( strBuffer, 512, strMsg, args );
312 vsnprintf( strBuffer, 512, strMsg, args );
316 SG_LOG(SG_GL, SG_ALERT, strMsg);
320 //---------------------------------------------------------------------------
321 // Function : RenderTexture::Initialize
323 //---------------------------------------------------------------------------
325 * @fn RenderTexture::Initialize(int width, int height, bool shareObjects, bool copyContext);
326 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
328 * This function creates of the p-buffer. It can only be called once a GL
329 * context has already been created.
331 bool RenderTexture::Initialize(int width, int height,
332 bool shareObjects /* = true */,
333 bool copyContext /* = false */)
335 assert(width > 0 && height > 0);
337 _iWidth = width; _iHeight = height;
338 _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
340 _bShareObjects = shareObjects;
341 _bCopyContext = copyContext;
343 // Check if this is an NVXX GPU and verify necessary extensions.
344 if (!_VerifyExtensions())
351 // Get the current context.
352 HDC hdc = wglGetCurrentDC();
355 HGLRC hglrc = wglGetCurrentContext();
360 unsigned int iNumFormats;
364 // Get the pixel format for the on-screen window.
365 iFormat = GetPixelFormat(hdc);
368 SG_LOG(SG_GL, SG_ALERT,
369 "RenderTexture Error: GetPixelFormat() failed.");
375 if (!wglChoosePixelFormatARBPtr(hdc, &_pixelFormatAttribs[0], NULL,
376 1, &iFormat, &iNumFormats))
378 SG_LOG(SG_GL, SG_ALERT,
379 "RenderTexture Error: wglChoosePixelFormatARB() failed.");
383 if ( iNumFormats <= 0 )
385 SG_LOG(SG_GL, SG_ALERT,
386 "RenderTexture Error: Couldn't find a suitable "
393 // Create the p-buffer.
394 _hPBuffer = wglCreatePbufferARBPtr(hdc, iFormat, _iWidth, _iHeight,
395 &_pbufferAttribs[0]);
398 SG_LOG(SG_GL, SG_ALERT,
399 "RenderTexture Error: wglCreatePbufferARB() failed.");
404 // Get the device context.
405 _hDC = wglGetPbufferDCARBPtr( _hPBuffer);
408 SG_LOG(SG_GL, SG_ALERT,
409 "RenderTexture Error: wglGetGetPbufferDCARB() failed.");
414 // Create a gl context for the p-buffer.
417 // Let's use the same gl context..
418 // Since the device contexts are compatible (i.e. same pixelformat),
419 // we should be able to use the same gl rendering context.
424 _hGLContext = wglCreateContext( _hDC );
427 SG_LOG(SG_GL, SG_ALERT,
428 "RenderTexture Error: wglCreateContext() failed.");
434 // Share lists, texture objects, and program objects.
437 if( !wglShareLists(hglrc, _hGLContext) )
439 SG_LOG(SG_GL, SG_ALERT,
440 "RenderTexture Error: wglShareLists() failed.");
446 // Determine the actual width and height we were able to create.
447 wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
448 wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
450 _bInitialized = true;
452 // get the actual number of bits allocated:
453 int attrib = WGL_RED_BITS_ARB;
457 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
459 attrib = WGL_GREEN_BITS_ARB;
461 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
463 attrib = WGL_BLUE_BITS_ARB;
465 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
467 attrib = WGL_ALPHA_BITS_ARB;
469 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
471 attrib = WGL_DEPTH_BITS_ARB;
473 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
475 attrib = WGL_STENCIL_BITS_ARB;
477 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
479 attrib = WGL_DOUBLE_BUFFER_ARB;
481 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
482 ? (value?true:false) : false;
484 #if defined(_DEBUG) | defined(DEBUG)
485 SG_LOG(SG_GL, SG_ALERT, "Created a " << _iWidth << "x" << _iHeight <<
486 " RenderTexture with BPP(" <<
487 _iNumColorBits[0] << "," << _iNumColorBits[1] << "," <<
488 _iNumColorBits[2] << "," << _iNumColorBits[3] << ")");
489 if (_iNumDepthBits) SG_LOG(SG_GL, SG_ALERT, " depth=" << _iNumDepthBits);
490 if (_iNumStencilBits) SG_LOG(SG_GL, SG_ALERT, " stencil=" << _iNumStencilBits);
491 if (_bDoubleBuffered) SG_LOG(SG_GL, SG_ALERT, " double buffered");
494 #elif defined( __MACH__ )
495 // Get the current context.
496 CGLContextObj hglrc = CGLGetCurrentContext();
498 fprintf(stderr, "Couldn't get current context!");
500 CGLPixelFormatObj pixFormat = NULL;
501 long int iNumFormats;
504 // Copy the _pixelFormatAttribs into another array to fix
506 CGLPixelFormatAttribute *pixFormatAttribs =
507 (CGLPixelFormatAttribute *)malloc(sizeof(CGLPixelFormatAttribute)
508 * _pixelFormatAttribs.size());
510 for (unsigned int ii = 0; ii < _pixelFormatAttribs.size(); ii++)
512 pixFormatAttribs[ii] =
513 (CGLPixelFormatAttribute)_pixelFormatAttribs[ii];
517 CGLChoosePixelFormat(&pixFormatAttribs[0], &pixFormat, &iNumFormats))
520 "RenderTexture Error: CGLChoosePixelFormat() failed.\n");
521 _cglCheckError(error);
524 if ( iNumFormats <= 0 )
527 "RenderTexture Error: Couldn't find a suitable "+
532 // Free the copy of the _pixelFormatAttribs array
533 free(pixFormatAttribs);
535 // Create the context.
536 error = CGLCreateContext(pixFormat, (_bShareObjects)
537 ? CGLGetCurrentContext() : NULL, &_hGLContext);
541 "RenderTexture Error: CGLCreateContext() failed.\n");
542 _cglCheckError(error);
545 CGLDestroyPixelFormat(pixFormat);
547 // Create the p-buffer.
548 error = CGLCreatePBuffer(_iWidth, _iHeight, (_bRectangle)
549 ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D, GL_RGBA, 0, &_hPBuffer);
553 "RenderTexture Error: CGLCreatePBuffer() failed.\n");
554 _cglCheckError(error);
559 if (error = CGLGetVirtualScreen(CGLGetCurrentContext(), &screen))
561 _cglCheckError(error);
564 if (error = CGLSetPBuffer(_hGLContext, _hPBuffer, 0, 0, screen))
566 _cglCheckError(error);
570 // Determine the actual width and height we were able to create.
571 //wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
572 //wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
574 _bInitialized = true;
577 // get the actual number of bits allocated:
578 int attrib = WGL_RED_BITS_ARB;
582 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
584 attrib = WGL_GREEN_BITS_ARB;
586 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
588 attrib = WGL_BLUE_BITS_ARB;
590 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
592 attrib = WGL_ALPHA_BITS_ARB;
594 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
596 attrib = WGL_DEPTH_BITS_ARB;
598 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
600 attrib = WGL_STENCIL_BITS_ARB;
602 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
604 attrib = WGL_DOUBLE_BUFFER_ARB;
606 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
607 ? (value?true:false) : false;
610 #if defined(_DEBUG) | defined(DEBUG)
611 fprintf(stderr, "Created a %dx%d RenderTexture with BPP(%d, %d, %d, %d)",
613 _iNumColorBits[0], _iNumColorBits[1],
614 _iNumColorBits[2], _iNumColorBits[3]);
615 if (_iNumDepthBits) fprintf(stderr, " depth=%d", _iNumDepthBits);
616 if (_iNumStencilBits) fprintf(stderr, " stencil=%d", _iNumStencilBits);
617 if (_bDoubleBuffered) fprintf(stderr, " double buffered");
618 fprintf(stderr, "\n");
621 #else // !_WIN32, !__MACH_
622 _pDisplay = glXGetCurrentDisplay();
623 GLXContext context = glXGetCurrentContext();
624 int screen = DefaultScreen(_pDisplay);
625 XVisualInfo *visInfo;
627 GLXFBConfig *fbConfigs;
630 fbConfigs = glXChooseFBConfigPtr(_pDisplay, screen,
631 &_pixelFormatAttribs[0], &nConfigs);
633 if (nConfigs == 0 || !fbConfigs)
635 SG_LOG(SG_GL, SG_ALERT,
636 "RenderTexture Error: Couldn't find a suitable pixel format.");
640 // Pick the first returned format that will return a pbuffer
641 if (glXVersion1_3Present)
644 GLX_PBUFFER_WIDTH, _iWidth,
645 GLX_PBUFFER_HEIGHT, _iHeight,
646 GLX_LARGEST_PBUFFER, False,
649 for (int i=0;i<nConfigs;i++)
651 _hPBuffer = glXCreatePbufferPtr(_pDisplay, fbConfigs[i], pbufAttrib);
654 XVisualInfo *visInfo = glXGetVisualFromFBConfigPtr(_pDisplay, fbConfigs[i]);
656 _hGLContext = glXCreateContextPtr(_pDisplay, visInfo,
657 _bShareObjects ? context : NULL,
673 for (int i=0;i<nConfigs;i++)
675 _hPBuffer = glXCreateGLXPbufferPtr(_pDisplay, fbConfigs[i],
676 _iWidth, _iHeight, NULL);
679 _hGLContext = glXCreateContextWithConfigPtr(_pDisplay,
682 _bShareObjects ? context : NULL,
692 SG_LOG(SG_GL, SG_ALERT,
693 "RenderTexture Error: glXCreateGLXPbufferPtr() failed.");
700 _hGLContext = glXCreateContext(_pDisplay, visInfo,
701 _bShareObjects ? context : NULL, False);
704 SG_LOG(SG_GL, SG_ALERT,
705 "RenderTexture Error: glXCreateContext() failed.");
710 if (!glXVersion1_3Present)
712 glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_WIDTH_SGIX,
714 glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_HEIGHT_SGIX,
718 _bInitialized = true;
720 // XXX Query the color format
725 // Now that the pbuffer is created, allocate any texture objects needed,
726 // and initialize them (for CTT updates only). These must be allocated
727 // in the context of the pbuffer, though, or the RT won't work without
730 if (false == wglMakeCurrent( _hDC, _hGLContext))
735 #elif defined( __MACH__ )
737 if (err = CGLSetCurrentContext(_hGLContext))
743 _hPreviousContext = glXGetCurrentContext();
744 _hPreviousDrawable = glXGetCurrentDrawable();
746 if (False == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
752 bool result = _InitializeTextures();
754 BindBuffer(WGL_FRONT_LEFT_ARB);
760 // make the previous rendering context current
761 if (false == wglMakeCurrent( hdc, hglrc))
766 #elif defined( __MACH__ )
767 if (err = CGLSetCurrentContext(_hPreviousContext))
773 if (False == glXMakeCurrent(_pDisplay,
774 _hPreviousDrawable, _hPreviousContext))
778 if (glXVersion1_3Present)
780 GLXDrawable draw = glXGetCurrentDrawable();
781 glXQueryDrawablePtr(_pDisplay, draw, GLX_WIDTH, (unsigned int*)&_iWidth);
782 glXQueryDrawablePtr(_pDisplay, draw, GLX_HEIGHT, (unsigned int*)&_iHeight);
790 //---------------------------------------------------------------------------
791 // Function : RenderTexture::_Invalidate
793 //---------------------------------------------------------------------------
795 * @fn RenderTexture::_Invalidate()
796 * @brief Returns the pbuffer memory to the graphics device.
799 bool RenderTexture::_Invalidate()
801 _iNumColorBits[0] = _iNumColorBits[1] =
802 _iNumColorBits[2] = _iNumColorBits[3] = 0;
804 _iNumStencilBits = 0;
807 glDeleteTextures(1, &_iTextureID);
808 if (_bIsDepthTexture)
811 if (!_bHasARBDepthTexture) delete[] _pPoorDepthTexture;
813 glDeleteTextures(1, &_iDepthTextureID);
819 // Check if we are currently rendering in the pbuffer
820 if (wglGetCurrentContext() == _hGLContext)
823 wglDeleteContext( _hGLContext);
824 wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
825 wglDestroyPbufferARBPtr( _hPBuffer );
829 #elif defined( __MACH__ )
832 if (CGLGetCurrentContext() == _hGLContext)
833 CGLSetCurrentContext(NULL);
835 CGLDestroyContext(_hGLContext);
836 CGLDestroyPBuffer(_hPBuffer);
843 if(glXGetCurrentContext() == _hGLContext)
844 // XXX I don't know if this is right at all
845 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
846 glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
852 // [WVB] do we need to call _ReleaseBoundBuffers() too?
857 //---------------------------------------------------------------------------
858 // Function : RenderTexture::Reset
860 //---------------------------------------------------------------------------
862 * @fn RenderTexture::Reset()
863 * @brief Resets the resolution of the offscreen buffer.
865 * Causes the buffer to delete itself. User must call Initialize() again
868 bool RenderTexture::Reset(const char *strMode, ...)
870 _iWidth = 0; _iHeight = 0;
871 _bIsTexture = false; _bIsDepthTexture = false,
872 _bHasARBDepthTexture = true;
873 #if defined(_WIN32) || defined(__MACH__)
874 _eUpdateMode = RT_RENDER_TO_TEXTURE;
876 _eUpdateMode = RT_COPY_TO_TEXTURE;
878 _bInitialized = false;
880 _bIsBufferBound = false;
881 _iCurrentBoundBuffer = 0;
882 _iNumDepthBits = 0; _iNumStencilBits = 0;
883 _bDoubleBuffered = false;
884 _bFloat = false; _bPowerOf2 = true;
885 _bRectangle = false; _bMipmap = false;
886 _bShareObjects = false; _bCopyContext = false;
887 _iTextureTarget = GL_NONE; _iTextureID = 0;
888 _iDepthTextureID = 0;
889 _pPoorDepthTexture = 0;
890 _pixelFormatAttribs.clear();
891 _pbufferAttribs.clear();
893 if (IsInitialized() && !_Invalidate())
895 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Reset(): failed to invalidate.");
899 _iNumColorBits[0] = _iNumColorBits[1] =
900 _iNumColorBits[2] = _iNumColorBits[3] = 0;
903 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
904 _pixelFormatAttribs.push_back(true);
905 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
906 _pixelFormatAttribs.push_back(true);
908 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
909 _pbufferAttribs.push_back(true);
910 #elif defined( __MACH__ )
911 //_pixelFormatAttribs.push_back(kCGLPFANoRecovery);
912 _pixelFormatAttribs.push_back(kCGLPFAAccelerated);
913 _pixelFormatAttribs.push_back(kCGLPFAWindow);
914 _pixelFormatAttribs.push_back(kCGLPFAPBuffer);
916 _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
917 _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
918 _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
919 _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
924 va_start(args,strMode);
925 #if defined _WIN32 && !defined __CYGWIN__
926 _vsnprintf( strBuffer, 256, strMode, args );
928 vsnprintf( strBuffer, 256, strMode, args );
932 _ParseModeString(strBuffer, _pixelFormatAttribs, _pbufferAttribs);
935 _pixelFormatAttribs.push_back(0);
936 _pbufferAttribs.push_back(0);
937 #elif defined(__MACH__)
938 _pixelFormatAttribs.push_back((CGLPixelFormatAttribute)0);
940 _pixelFormatAttribs.push_back(None);
945 //------------------------------------------------------------------------------
946 // Function : RenderTexture::Resize
948 //------------------------------------------------------------------------------
950 * @fn RenderTexture::Resize(int iWidth, int iHeight)
951 * @brief Changes the size of the offscreen buffer.
953 * Like Reset() this causes the buffer to delete itself.
954 * But unlike Reset(), this call re-initializes the RenderTexture.
955 * Note that Resize() will not work after calling Reset(), or before
956 * calling Initialize() the first time.
958 bool RenderTexture::Resize(int iWidth, int iHeight)
960 if (!_bInitialized) {
961 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): must Initialize() first.");
964 if (iWidth == _iWidth && iHeight == _iHeight) {
968 // Do same basic work as _Invalidate, but don't reset all our flags
970 glDeleteTextures(1, &_iTextureID);
971 if (_bIsDepthTexture)
972 glDeleteTextures(1, &_iDepthTextureID);
976 // Check if we are currently rendering in the pbuffer
977 if (wglGetCurrentContext() == _hGLContext)
980 wglDeleteContext( _hGLContext);
981 wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
982 wglDestroyPbufferARBPtr( _hPBuffer );
986 #elif defined( __MACH__ )
989 if (CGLGetCurrentContext() == _hGLContext)
990 CGLSetCurrentContext(NULL);
992 CGLDestroyContext(_hGLContext);
993 CGLDestroyPBuffer(_hPBuffer);
1000 if(glXGetCurrentContext() == _hGLContext)
1001 // XXX I don't know if this is right at all
1002 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
1003 glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
1008 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): failed to resize.");
1011 _bInitialized = false;
1012 return Initialize(iWidth, iHeight, _bShareObjects, _bCopyContext);
1015 //---------------------------------------------------------------------------
1016 // Function : RenderTexture::BeginCapture
1018 //---------------------------------------------------------------------------
1020 * @fn RenderTexture::BeginCapture()
1021 * @brief Activates rendering to the RenderTexture.
1023 bool RenderTexture::BeginCapture()
1027 SG_LOG(SG_GL, SG_ALERT,
1028 "RenderTexture::BeginCapture(): Texture is not initialized!");
1032 // cache the current context so we can reset it when EndCapture() is called.
1033 _hPreviousDC = wglGetCurrentDC();
1034 if (NULL == _hPreviousDC)
1036 _hPreviousContext = wglGetCurrentContext();
1037 if (NULL == _hPreviousContext)
1039 #elif defined( __MACH__ )
1040 _hPreviousContext = CGLGetCurrentContext();
1042 _hPreviousContext = glXGetCurrentContext();
1043 _hPreviousDrawable = glXGetCurrentDrawable();
1046 _ReleaseBoundBuffers();
1048 return _MakeCurrent();
1052 //---------------------------------------------------------------------------
1053 // Function : RenderTexture::EndCapture
1055 //---------------------------------------------------------------------------
1057 * @fn RenderTexture::EndCapture()
1058 * @brief Ends rendering to the RenderTexture.
1060 bool RenderTexture::EndCapture()
1064 SG_LOG(SG_GL, SG_ALERT,
1065 "RenderTexture::EndCapture() : Texture is not initialized!");
1069 glFlush(); // Added by a-lex
1074 // make the previous rendering context current
1075 if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
1080 #elif defined( __MACH__ )
1082 if (err = CGLSetCurrentContext(_hPreviousContext))
1084 _cglCheckError(err);
1088 if (False == glXMakeCurrent(_pDisplay, _hPreviousDrawable,
1095 // rebind the textures to a buffers for RTT
1096 BindBuffer(_iCurrentBoundBuffer);
1102 //---------------------------------------------------------------------------
1103 // Function : RenderTexture::BeginCapture(RenderTexture*)
1105 //---------------------------------------------------------------------------
1107 * @fn RenderTexture::BeginCapture(RenderTexture* other)
1108 * @brief Ends capture of 'other', begins capture on 'this'
1110 * When performing a series of operations where you modify one texture after
1111 * another, it is more efficient to use this method instead of the equivalent
1112 * 'EndCapture'/'BeginCapture' pair. This method switches directly to the
1113 * new context rather than changing to the default context, and then to the
1116 * RenderTexture doesn't have any mechanism for determining if
1117 * 'current' really is currently active, so no error will be thrown
1120 bool RenderTexture::BeginCapture(RenderTexture* current)
1122 bool bContextReset = false;
1124 if (current == this) {
1125 return true; // no switch necessary
1128 // treat as normal Begin if current is 0.
1129 return BeginCapture();
1133 SG_LOG(SG_GL, SG_ALERT,
1134 "RenderTexture::BeginCapture(RenderTexture*): Texture is not initialized!");
1137 if (!current->_bInitialized)
1139 SG_LOG(SG_GL, SG_ALERT,
1140 "RenderTexture::BeginCapture(RenderTexture): 'current' texture is not initialized!");
1144 // Sync current pbuffer with its CTT texture if necessary
1145 current->_MaybeCopyBuffer();
1147 // pass along the previous context so we can reset it when
1148 // EndCapture() is called.
1150 _hPreviousDC = current->_hPreviousDC;
1151 if (NULL == _hPreviousDC)
1153 _hPreviousContext = current->_hPreviousContext;
1154 if (NULL == _hPreviousContext)
1156 #elif defined( __MACH__ )
1157 _hPreviousContext = current->_hPreviousContext;
1159 _hPreviousContext = current->_hPreviousContext;
1160 _hPreviousDrawable = current->_hPreviousDrawable;
1163 // Unbind textures before making context current
1164 if (!_ReleaseBoundBuffers())
1167 // Make the pbuffer context current
1168 if (!_MakeCurrent())
1171 // Rebind buffers of initial RenderTexture
1172 current->BindBuffer(_iCurrentBoundBuffer);
1173 current->_BindDepthBuffer();
1180 //---------------------------------------------------------------------------
1181 // Function : RenderTexture::Bind
1183 //---------------------------------------------------------------------------
1185 * @fn RenderTexture::Bind()
1186 * @brief Binds RGB texture.
1188 void RenderTexture::Bind() const
1190 if (_bInitialized && _bIsTexture)
1192 glBindTexture(_iTextureTarget, _iTextureID);
1197 //---------------------------------------------------------------------------
1198 // Function : RenderTexture::BindDepth
1200 //---------------------------------------------------------------------------
1202 * @fn RenderTexture::BindDepth()
1203 * @brief Binds depth texture.
1205 void RenderTexture::BindDepth() const
1207 if (_bInitialized && _bIsDepthTexture)
1209 glBindTexture(_iTextureTarget, _iDepthTextureID);
1214 //---------------------------------------------------------------------------
1215 // Function : RenderTexture::BindBuffer
1217 //---------------------------------------------------------------------------
1219 * @fn RenderTexture::BindBuffer()
1220 * @brief Associate the RTT texture id with 'iBuffer' (e.g. WGL_FRONT_LEFT_ARB)
1222 bool RenderTexture::BindBuffer( int iBuffer )
1224 // Must bind the texture too
1225 if (_bInitialized && _bIsTexture)
1227 glBindTexture(_iTextureTarget, _iTextureID);
1230 if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
1231 (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
1233 if (FALSE == wglBindTexImageARBPtr(_hPBuffer, iBuffer))
1235 // WVB: WGL API considers binding twice to the same buffer
1236 // to be an error. But we don't want to
1237 //_wglGetLastError();
1241 _bIsBufferBound = true;
1242 _iCurrentBoundBuffer = iBuffer;
1244 #elif defined(__MACH__)
1245 if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
1246 (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
1249 if (err=CGLTexImagePBuffer(CGLGetCurrentContext(), _hPBuffer, iBuffer))
1251 _cglCheckError(err);
1253 _bIsBufferBound = true;
1254 _iCurrentBoundBuffer = iBuffer;
1262 //---------------------------------------------------------------------------
1263 // Function : RenderTexture::BindDepthBuffer
1265 //---------------------------------------------------------------------------
1267 * @fn RenderTexture::_BindDepthBuffer()
1268 * @brief Associate the RTT depth texture id with the depth buffer
1270 bool RenderTexture::_BindDepthBuffer() const
1273 if (_bInitialized && _bIsDepthTexture &&
1274 RT_RENDER_TO_TEXTURE == _eUpdateMode)
1276 glBindTexture(_iTextureTarget, _iDepthTextureID);
1277 if (FALSE == wglBindTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1283 #elif defined(__MACH__)
1284 if (_bInitialized && _bIsDepthTexture &&
1285 RT_RENDER_TO_TEXTURE == _eUpdateMode)
1287 glBindTexture(_iTextureTarget, _iDepthTextureID);
1288 //if (FALSE == CGLTexImagePBuffer(<#CGLContextObj ctx#>,<#CGLPBufferObj pbuffer#>,<#unsigned long source#>)(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1290 // _wglGetLastError();
1298 //---------------------------------------------------------------------------
1299 // Function : RenderTexture::_ParseModeString
1301 //---------------------------------------------------------------------------
1303 * @fn RenderTexture::_ParseModeString()
1304 * @brief Parses the user-specified mode string for RenderTexture parameters.
1306 void RenderTexture::_ParseModeString(const char *modeString,
1307 vector<int> &pfAttribs,
1308 vector<int> &pbAttribs)
1310 if (!modeString || strcmp(modeString, "") == 0)
1313 _iNumComponents = 0;
1314 #if defined(_WIN32) || defined(__MACH__)
1315 _eUpdateMode = RT_RENDER_TO_TEXTURE;
1317 _eUpdateMode = RT_COPY_TO_TEXTURE;
1321 bool bHasStencil = false;
1322 bool bBind2D = false;
1323 bool bBindRECT = false;
1324 bool bBindCUBE = false;
1326 char *mode = strdup(modeString);
1329 vector<string> tokens;
1330 char *buf = strtok(mode, " ");
1333 tokens.push_back(buf);
1334 buf = strtok(NULL, " ");
1337 for (unsigned int i = 0; i < tokens.size(); i++)
1339 string token = tokens[i];
1341 KeyVal kv = _GetKeyValuePair(token);
1344 if (kv.first == "rgb" && (_iNumComponents <= 1))
1346 if (kv.second.find("f") != kv.second.npos)
1349 vector<int> bitVec = _ParseBitVector(kv.second);
1351 if (bitVec.size() < 3) // expand the scalar to a vector
1353 bitVec.push_back(bitVec[0]);
1354 bitVec.push_back(bitVec[0]);
1358 pfAttribs.push_back(WGL_RED_BITS_ARB);
1359 pfAttribs.push_back(bitVec[0]);
1360 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1361 pfAttribs.push_back(bitVec[1]);
1362 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1363 pfAttribs.push_back(bitVec[2]);
1364 #elif defined( __MACH__ )
1366 pfAttribs.push_back(AGL_RED_SIZE);
1367 pfAttribs.push_back(bitVec[0]);
1368 pfAttribs.push_back(AGL_GREEN_SIZE);
1369 pfAttribs.push_back(bitVec[1]);
1370 pfAttribs.push_back(AGL_BLUE_SIZE);
1371 pfAttribs.push_back(bitVec[2]);
1373 pfAttribs.push_back(kCGLPFAColorSize);
1374 pfAttribs.push_back(bitVec[0] + bitVec[1] + bitVec[2]);
1377 pfAttribs.push_back(GLX_RED_SIZE);
1378 pfAttribs.push_back(bitVec[0]);
1379 pfAttribs.push_back(GLX_GREEN_SIZE);
1380 pfAttribs.push_back(bitVec[1]);
1381 pfAttribs.push_back(GLX_BLUE_SIZE);
1382 pfAttribs.push_back(bitVec[2]);
1384 _iNumComponents += 3;
1387 else if (kv.first == "rgb")
1388 SG_LOG(SG_GL, SG_ALERT,
1389 "RenderTexture Warning: mistake in components definition "
1390 "(rgb + " << _iNumComponents << ").");
1392 if (kv.first == "rgba" && (_iNumComponents == 0))
1394 if (kv.second.find("f") != kv.second.npos)
1397 vector<int> bitVec = _ParseBitVector(kv.second);
1399 if (bitVec.size() < 4) // expand the scalar to a vector
1401 bitVec.push_back(bitVec[0]);
1402 bitVec.push_back(bitVec[0]);
1403 bitVec.push_back(bitVec[0]);
1407 pfAttribs.push_back(WGL_RED_BITS_ARB);
1408 pfAttribs.push_back(bitVec[0]);
1409 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1410 pfAttribs.push_back(bitVec[1]);
1411 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1412 pfAttribs.push_back(bitVec[2]);
1413 pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1414 pfAttribs.push_back(bitVec[3]);
1415 #elif defined( __MACH__ )
1417 pfAttribs.push_back(AGL_RED_SIZE);
1418 pfAttribs.push_back(bitVec[0]);
1419 pfAttribs.push_back(AGL_GREEN_SIZE);
1420 pfAttribs.push_back(bitVec[1]);
1421 pfAttribs.push_back(AGL_BLUE_SIZE);
1422 pfAttribs.push_back(bitVec[2]);
1423 pfAttribs.push_back(AGL_ALPHA_SIZE);
1424 pfAttribs.push_back(bitVec[3]);
1426 pfAttribs.push_back(kCGLPFAColorSize);
1427 pfAttribs.push_back(bitVec[0] + bitVec[1] + bitVec[2] + bitVec[3]);
1428 //pfAttribs.push_back(kCGLPFAAlphaSize);
1429 //pfAttribs.push_back(bitVec[3]);
1430 // printf("Color size: %d\n", bitVec[0] + bitVec[1] + bitVec[2] + bitVec[3]);
1434 pfAttribs.push_back(GLX_RED_SIZE);
1435 pfAttribs.push_back(bitVec[0]);
1436 pfAttribs.push_back(GLX_GREEN_SIZE);
1437 pfAttribs.push_back(bitVec[1]);
1438 pfAttribs.push_back(GLX_BLUE_SIZE);
1439 pfAttribs.push_back(bitVec[2]);
1440 pfAttribs.push_back(GLX_ALPHA_SIZE);
1441 pfAttribs.push_back(bitVec[3]);
1443 _iNumComponents = 4;
1446 else if (kv.first == "rgba")
1447 SG_LOG(SG_GL, SG_ALERT,
1448 "RenderTexture Warning: mistake in components definition "
1449 "(rgba + " << _iNumComponents << ").");
1451 if (kv.first == "r" && (_iNumComponents <= 1))
1453 if (kv.second.find("f") != kv.second.npos)
1456 vector<int> bitVec = _ParseBitVector(kv.second);
1459 pfAttribs.push_back(WGL_RED_BITS_ARB);
1460 pfAttribs.push_back(bitVec[0]);
1461 #elif defined( __MACH__ )
1463 pfAttribs.push_back(AGL_RED_SIZE);
1464 pfAttribs.push_back(bitVec[0]);
1466 pfAttribs.push_back(kCGLPFAColorSize);
1467 pfAttribs.push_back(bitVec[0]);
1470 pfAttribs.push_back(GLX_RED_SIZE);
1471 pfAttribs.push_back(bitVec[0]);
1476 else if (kv.first == "r")
1477 SG_LOG(SG_GL, SG_ALERT,
1478 "RenderTexture Warning: mistake in components definition "
1479 "(r + " << _iNumComponents << ").");
1481 if (kv.first == "rg" && (_iNumComponents <= 1))
1483 if (kv.second.find("f") != kv.second.npos)
1486 vector<int> bitVec = _ParseBitVector(kv.second);
1488 if (bitVec.size() < 2) // expand the scalar to a vector
1490 bitVec.push_back(bitVec[0]);
1494 pfAttribs.push_back(WGL_RED_BITS_ARB);
1495 pfAttribs.push_back(bitVec[0]);
1496 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1497 pfAttribs.push_back(bitVec[1]);
1498 #elif defined( __MACH__ )
1500 pfAttribs.push_back(AGL_RED_SIZE);
1501 pfAttribs.push_back(bitVec[0]);
1502 pfAttribs.push_back(AGL_GREEN_SIZE);
1503 pfAttribs.push_back(bitVec[1]);
1505 pfAttribs.push_back(kCGLPFAColorSize);
1506 pfAttribs.push_back(bitVec[0] + bitVec[1]);
1509 pfAttribs.push_back(GLX_RED_SIZE);
1510 pfAttribs.push_back(bitVec[0]);
1511 pfAttribs.push_back(GLX_GREEN_SIZE);
1512 pfAttribs.push_back(bitVec[1]);
1514 _iNumComponents += 2;
1517 else if (kv.first == "rg")
1518 SG_LOG(SG_GL, SG_ALERT,
1519 "RenderTexture Warning: mistake in components definition "
1520 "(rg + " << _iNumComponents << ").");
1522 if (kv.first == "depth")
1524 if (kv.second == "")
1527 iDepthBits = strtol(kv.second.c_str(), 0, 10);
1531 if (kv.first == "stencil")
1535 pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1536 #elif defined( __MACH__ )
1538 pfAttribs.push_back(AGL_STENCIL_SIZE);
1540 pfAttribs.push_back(kCGLPFAStencilSize);
1543 pfAttribs.push_back(GLX_STENCIL_SIZE);
1545 if (kv.second == "")
1546 pfAttribs.push_back(8);
1548 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1552 if (kv.first == "samples")
1555 pfAttribs.push_back(WGL_SAMPLE_BUFFERS_ARB);
1556 pfAttribs.push_back(1);
1557 pfAttribs.push_back(WGL_SAMPLES_ARB);
1558 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1559 #elif defined( __MACH__ )
1561 pfAttribs.push_back(AGL_SAMPLE_BUFFERS_ARB);
1562 pfAttribs.push_back(1);
1563 pfAttribs.push_back(AGL_SAMPLES_ARB);
1565 pfAttribs.push_back(kCGLPFAMultisample);
1566 pfAttribs.push_back(kCGLPFASamples);
1568 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1570 pfAttribs.push_back(GLX_SAMPLE_BUFFERS_ARB);
1571 pfAttribs.push_back(1);
1572 pfAttribs.push_back(GLX_SAMPLES_ARB);
1573 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1579 if (kv.first == "doublebuffer" || kv.first == "double")
1582 pfAttribs.push_back(WGL_DOUBLE_BUFFER_ARB);
1583 pfAttribs.push_back(true);
1584 #elif defined( __MACH__ )
1586 pfAttribs.push_back(AGL_DOUBLEBUFFER);
1587 pfAttribs.push_back(True);
1589 pfAttribs.push_back(kCGLPFADoubleBuffer);
1592 pfAttribs.push_back(GLX_DOUBLEBUFFER);
1593 pfAttribs.push_back(True);
1598 if (kv.first == "aux")
1601 pfAttribs.push_back(WGL_AUX_BUFFERS_ARB);
1602 #elif defined( __MACH__ )
1604 pfAttribs.push_back(AGL_AUX_BUFFERS);
1606 pfAttribs.push_back(kCGLPFAAuxBuffers);
1609 pfAttribs.push_back(GLX_AUX_BUFFERS);
1611 if (kv.second == "")
1612 pfAttribs.push_back(0);
1614 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1618 if (token.find("tex") == 0)
1622 if ((kv.first == "texRECT") && (GL_NV_texture_rectangle ||
1623 GL_EXT_texture_rectangle))
1628 else if (kv.first == "texCUBE")
1640 if (token.find("depthTex") == 0)
1642 _bIsDepthTexture = true;
1644 if ((kv.first == "depthTexRECT") && (GL_NV_texture_rectangle ||
1645 GL_EXT_texture_rectangle))
1650 else if (kv.first == "depthTexCUBE")
1662 if (kv.first == "mipmap")
1668 if (kv.first == "rtt")
1670 _eUpdateMode = RT_RENDER_TO_TEXTURE;
1674 if (kv.first == "ctt")
1676 _eUpdateMode = RT_COPY_TO_TEXTURE;
1680 SG_LOG(SG_GL, SG_ALERT,
1681 "RenderTexture Error: Unknown pbuffer attribute: " <<
1685 // Processing of some options must be last because of interactions.
1687 // Check for inconsistent texture targets
1688 if (_bIsTexture && _bIsDepthTexture && !(bBind2D ^ bBindRECT ^ bBindCUBE))
1690 SG_LOG(SG_GL, SG_ALERT,
1691 "RenderTexture Warning: Depth and Color texture targets "
1695 // Apply default bit format if none specified
1697 if (0 == _iNumComponents)
1699 pfAttribs.push_back(WGL_RED_BITS_ARB);
1700 pfAttribs.push_back(8);
1701 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1702 pfAttribs.push_back(8);
1703 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1704 pfAttribs.push_back(8);
1705 pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1706 pfAttribs.push_back(8);
1707 _iNumComponents = 4;
1712 if (_bIsDepthTexture && !iDepthBits)
1716 pfAttribs.push_back(WGL_DEPTH_BITS_ARB);
1717 #elif defined( __MACH__ )
1719 pfAttribs.push_back(AGL_DEPTH_SIZE);
1721 pfAttribs.push_back(kCGLPFADepthSize);
1724 pfAttribs.push_back(GLX_DEPTH_SIZE);
1726 pfAttribs.push_back(iDepthBits); // default
1731 pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1732 pfAttribs.push_back(0);
1733 #elif defined( __MACH__ )
1735 pfAttribs.push_back(AGL_STENCIL_SIZE);
1737 pfAttribs.push_back(kCGLPFAStencilSize);
1739 pfAttribs.push_back(0);
1741 pfAttribs.push_back(GLX_STENCIL_SIZE);
1742 pfAttribs.push_back(0);
1746 if (_iNumComponents < 4)
1748 // Can't do this right now -- on NVIDIA drivers, currently get
1749 // a non-functioning pbuffer if ALPHA_BITS=0 and
1750 // WGL_BIND_TO_TEXTURE_RGB_ARB=true
1752 //pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1753 //pfAttribs.push_back(0);
1757 if (!WGL_NV_render_depth_texture && _bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1759 #if defined(DEBUG) || defined(_DEBUG)
1760 SG_LOG(SG_GL, SG_ALERT, "RenderTexture Warning: No support found for "
1761 "render to depth texture.");
1763 _bIsDepthTexture = false;
1767 if ((_bIsTexture || _bIsDepthTexture) &&
1768 (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1773 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1774 pbAttribs.push_back(WGL_TEXTURE_RECTANGLE_NV);
1778 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1779 pbAttribs.push_back(WGL_TEXTURE_CUBE_MAP_ARB);
1783 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1784 pbAttribs.push_back(WGL_TEXTURE_2D_ARB);
1789 pbAttribs.push_back(WGL_MIPMAP_TEXTURE_ARB);
1790 pbAttribs.push_back(true);
1792 #elif defined(__MACH__)
1793 #elif defined(DEBUG) || defined(_DEBUG)
1794 SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: Render to Texture not "
1795 "supported in Linux or MacOS");
1799 // Set the pixel type
1803 if (WGL_NV_float_buffer)
1805 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1806 pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1808 pfAttribs.push_back(WGL_FLOAT_COMPONENTS_NV);
1809 pfAttribs.push_back(true);
1813 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1814 pfAttribs.push_back(WGL_TYPE_RGBA_FLOAT_ATI);
1816 #elif defined( __MACH__ )
1817 // if (GL_MACH_float_pixels) // FIXME
1819 pfAttribs.push_back(kCGLPFAColorFloat);
1822 if (GLX_NV_float_buffer)
1824 pfAttribs.push_back(GLX_FLOAT_COMPONENTS_NV);
1825 pfAttribs.push_back(1);
1832 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1833 pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1837 // Set up texture binding for render to texture
1838 if (_bIsTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1844 if (WGL_NV_float_buffer)
1846 switch(_iNumComponents)
1849 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
1850 pfAttribs.push_back(true);
1852 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1853 pbAttribs.push_back(WGL_TEXTURE_FLOAT_R_NV);
1856 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
1857 pfAttribs.push_back(true);
1859 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1860 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RG_NV);
1863 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
1864 pfAttribs.push_back(true);
1866 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1867 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGB_NV);
1870 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
1871 pfAttribs.push_back(true);
1873 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1874 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGBA_NV);
1877 SG_LOG(SG_GL, SG_ALERT,
1878 "RenderTexture Warning: Bad number of components "
1879 "(r=1,rg=2,rgb=3,rgba=4): " <<
1886 if (4 == _iNumComponents)
1888 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1889 pfAttribs.push_back(true);
1891 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1892 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1896 // standard ARB_render_texture only supports 3 or 4 channels
1897 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1898 pfAttribs.push_back(true);
1900 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1901 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1908 switch(_iNumComponents)
1911 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1912 pfAttribs.push_back(true);
1914 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1915 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1918 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1919 pfAttribs.push_back(true);
1921 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1922 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1925 SG_LOG(SG_GL, SG_ALERT,
1926 "RenderTexture Warning: Bad number of components "
1927 "(r=1,rg=2,rgb=3,rgba=4): " << _iNumComponents);
1931 #elif defined(__MACH__)
1935 //if (WGLEW_NV_float_buffer) // FIXME
1937 switch(_iNumComponents)
1940 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
1941 pfAttribs.push_back(true);
1943 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1944 pbAttribs.push_back(WGL_TEXTURE_FLOAT_R_NV);
1947 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
1948 pfAttribs.push_back(true);
1950 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1951 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RG_NV);
1954 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
1955 pfAttribs.push_back(true);
1957 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1958 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGB_NV);
1961 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
1962 pfAttribs.push_back(true);
1964 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1965 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGBA_NV);
1969 "RenderTexture Warning: Bad number of components "
1970 "(r=1,rg=2,rgb=3,rgba=4): %d.\n",
1977 if (4 == _iNumComponents)
1979 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1980 pfAttribs.push_back(true);
1982 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1983 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1987 // standard ARB_render_texture only supports 3 or 4 channels
1988 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1989 pfAttribs.push_back(true);
1991 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1992 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
2000 switch(_iNumComponents)
2003 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
2004 pfAttribs.push_back(true);
2006 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2007 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
2010 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
2011 pfAttribs.push_back(true);
2013 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2014 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
2018 "RenderTexture Warning: Bad number of components "
2019 "(r=1,rg=2,rgb=3,rgba=4): %d.\n", _iNumComponents);
2024 #elif defined(DEBUG) || defined(_DEBUG)
2025 SG_LOG(SG_GL, SG_ALERT,
2026 "RenderTexture Error: Render to Texture not supported in "
2027 "Linux or MacOS\ n");
2031 if (_bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
2036 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV);
2037 pfAttribs.push_back(true);
2039 pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
2040 pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
2044 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_DEPTH_NV);
2045 pfAttribs.push_back(true);
2047 pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
2048 pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
2050 #elif defined(__MACH__)
2051 #elif defined(DEBUG) || defined(_DEBUG)
2052 SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: Render to Texture not supported in "
2058 //---------------------------------------------------------------------------
2059 // Function : RenderTexture::_GetKeyValuePair
2061 //---------------------------------------------------------------------------
2063 * @fn RenderTexture::_GetKeyValuePair()
2064 * @brief Parses expressions of the form "X=Y" into a pair (X,Y).
2066 RenderTexture::KeyVal RenderTexture::_GetKeyValuePair(string token)
2068 string::size_type pos = 0;
2069 if ((pos = token.find("=")) != token.npos)
2071 string key = token.substr(0, pos);
2072 string value = token.substr(pos+1, token.length()-pos+1);
2073 return KeyVal(key, value);
2076 return KeyVal(token, "");
2079 //---------------------------------------------------------------------------
2080 // Function : RenderTexture::_ParseBitVector
2082 //---------------------------------------------------------------------------
2084 * @fn RenderTexture::_ParseBitVector()
2085 * @brief Parses expressions of the form "=r,g,b,a" into a vector: (r,g,b,a)
2087 vector<int> RenderTexture::_ParseBitVector(string bitVector)
2089 vector<string> pieces;
2092 if (bitVector == "")
2094 bits.push_back(8); // if a depth isn't specified, use default 8 bits
2098 string::size_type pos = 0;
2099 string::size_type nextpos = 0;
2102 nextpos = bitVector.find_first_of(", ", pos);
2103 pieces.push_back(string(bitVector, pos, nextpos - pos));
2105 } while (nextpos != bitVector.npos );
2107 for ( vector<string>::iterator it = pieces.begin(); it != pieces.end(); it++)
2109 bits.push_back(strtol(it->c_str(), 0, 10));
2115 //---------------------------------------------------------------------------
2116 // Function : RenderTexture::_VerifyExtensions
2118 //---------------------------------------------------------------------------
2120 * @fn RenderTexture::_VerifyExtensions()
2121 * @brief Checks that the necessary extensions are available based on RT mode.
2123 bool RenderTexture::_VerifyExtensions()
2126 // a second call to _VerifyExtensions will allways return true, causing a crash
2127 // if the extension is not supported
2128 if ( true || !fctPtrInited )
2130 fctPtrInited = true;
2131 wglGetExtensionsStringARBProc wglGetExtensionsStringARBPtr = (wglGetExtensionsStringARBProc)wglGetProcAddress( "wglGetExtensionsStringARB" );
2132 if ( wglGetExtensionsStringARBPtr == 0 )
2134 PrintExtensionError("WGL_ARB_extensions_string");
2137 string wglExtensionsString = wglGetExtensionsStringARBPtr( wglGetCurrentDC() );
2138 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pixel_format" ) )
2140 wglChoosePixelFormatARBPtr = (wglChoosePixelFormatARBProc)SGLookupFunction("wglChoosePixelFormatARB");
2141 wglGetPixelFormatAttribivARBPtr = (wglGetPixelFormatAttribivARBProc)SGLookupFunction("wglGetPixelFormatAttribivARB");
2145 PrintExtensionError("WGL_ARB_pixel_format");
2148 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pbuffer" ) )
2150 wglCreatePbufferARBPtr = (wglCreatePbufferARBProc)SGLookupFunction("wglCreatePbufferARB");
2151 wglGetPbufferDCARBPtr = (wglGetPbufferDCARBProc)SGLookupFunction("wglGetPbufferDCARB");
2152 wglQueryPbufferARBPtr = (wglQueryPbufferARBProc)SGLookupFunction("wglQueryPbufferARB");
2153 wglReleasePbufferDCARBPtr = (wglReleasePbufferDCARBProc)SGLookupFunction("wglReleasePbufferDCARB");
2154 wglDestroyPbufferARBPtr = (wglDestroyPbufferARBProc)SGLookupFunction("wglDestroyPbufferARB");
2158 PrintExtensionError("WGL_ARB_pbuffer");
2161 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_render_texture" ) )
2163 wglBindTexImageARBPtr = (wglBindTexImageARBProc)SGLookupFunction("wglBindTexImageARB");
2164 wglReleaseTexImageARBPtr = (wglReleaseTexImageARBProc)SGLookupFunction("wglReleaseTexImageARB");
2166 else if ( _bIsTexture )
2168 PrintExtensionError("WGL_ARB_render_texture");
2171 if (_bRectangle && !SGIsOpenGLExtensionSupported( "GL_NV_texture_rectangle" ))
2173 PrintExtensionError("GL_NV_texture_rectangle");
2176 if (_bFloat && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) ||
2177 SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ATI_pixel_format_float" )))
2179 PrintExtensionError("GL_NV_float_buffer or GL_ATI_pixel_format_float");
2183 if (_bFloat && _bIsTexture && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) || SGIsOpenGLExtensionSupported( "GL_ATI_texture_float" )))
2185 PrintExtensionError("NV_float_buffer or ATI_texture_float");
2187 if (_bIsDepthTexture && !SGIsOpenGLExtensionSupported( "GL_ARB_depth_texture" ))
2190 #if defined(_DEBUG) | defined(DEBUG)
2191 SG_LOG(SG_GL, SG_ALERT,
2192 "RenderTexture Warning: "
2193 "OpenGL extension GL_ARB_depth_texture not available."
2194 " Using glReadPixels() to emulate behavior.");
2196 _bHasARBDepthTexture = false;
2197 //PrintExtensionError("GL_ARB_depth_texture");
2203 #elif defined( __MACH__ )
2204 // FIXME! Check extensions!
2206 Display* dpy = glXGetCurrentDisplay();
2207 int minor = 0, major = 0;
2208 if (!glXQueryVersion(dpy, &major, &minor))
2211 int screen = DefaultScreen(dpy);
2212 const char* extString = glXQueryExtensionsString(dpy, screen);
2213 if (!SGSearchExtensionsString(extString, "GLX_SGIX_fbconfig") ||
2214 !SGSearchExtensionsString(extString, "GLX_SGIX_pbuffer"))
2217 // First try the glX version 1.3 functions.
2218 glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfig");
2219 glXCreatePbufferPtr = (glXCreatePbufferProc)SGLookupFunction("glXCreatePbuffer");
2220 glXGetVisualFromFBConfigPtr = (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfig");
2221 glXCreateContextPtr = (glXCreateContextProc)SGLookupFunction("glXCreateContext");
2222 glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyPbuffer");
2223 glXQueryDrawablePtr = (glXQueryDrawableProc)SGLookupFunction("glXQueryDrawable");
2225 if (((1 <= major && 3 <= minor) || 2 <= major) &&
2226 glXChooseFBConfigPtr &&
2227 glXCreatePbufferPtr &&
2228 glXGetVisualFromFBConfigPtr &&
2229 glXCreateContextPtr &&
2230 glXDestroyPbufferPtr &&
2231 glXQueryDrawablePtr)
2232 glXVersion1_3Present = true;
2235 glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfigSGIX");
2236 glXCreateGLXPbufferPtr = (glXCreateGLXPbufferProc)SGLookupFunction("glXCreateGLXPbufferSGIX");
2237 glXGetVisualFromFBConfigPtr = (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfigSGIX");
2238 glXCreateContextWithConfigPtr = (glXCreateContextWithConfigProc)SGLookupFunction("glXCreateContextWithConfigSGIX");
2239 glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyGLXPbufferSGIX");
2240 glXQueryGLXPbufferSGIXPtr = (glXQueryGLXPbufferSGIXProc)SGLookupFunction("glXQueryGLXPbufferSGIX");
2243 if (!glXChooseFBConfigPtr ||
2244 !glXCreateGLXPbufferPtr ||
2245 !glXGetVisualFromFBConfigPtr ||
2246 !glXCreateContextWithConfigPtr ||
2247 !glXDestroyPbufferPtr ||
2248 !glXQueryGLXPbufferSGIXPtr)
2252 if (_bIsDepthTexture && !GL_ARB_depth_texture)
2254 PrintExtensionError("GL_ARB_depth_texture");
2257 if (_bFloat && _bIsTexture && !GLX_NV_float_buffer)
2259 PrintExtensionError("GLX_NV_float_buffer");
2262 if (_eUpdateMode == RT_RENDER_TO_TEXTURE)
2264 PrintExtensionError("Some GLX render texture extension: Please implement me!");
2272 //---------------------------------------------------------------------------
2273 // Function : RenderTexture::_InitializeTextures
2275 //---------------------------------------------------------------------------
2277 * @fn RenderTexture::_InitializeTextures()
2278 * @brief Initializes the state of textures used by the RenderTexture.
2280 bool RenderTexture::_InitializeTextures()
2282 // Determine the appropriate texture formats and filtering modes.
2283 if (_bIsTexture || _bIsDepthTexture)
2285 if (_bRectangle && GL_NV_texture_rectangle)
2286 _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
2287 else if (_bRectangle && GL_EXT_texture_rectangle)
2288 _iTextureTarget = GL_TEXTURE_RECTANGLE_EXT;
2290 _iTextureTarget = GL_TEXTURE_2D;
2295 glGenTextures(1, (GLuint*)&_iTextureID);
2296 glBindTexture(_iTextureTarget, _iTextureID);
2298 // Use clamp to edge as the default texture wrap mode for all tex
2299 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2300 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2301 // Use NEAREST as the default texture filtering mode.
2302 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2303 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2306 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2308 GLuint iInternalFormat;
2315 SG_LOG(SG_GL, SG_ALERT,
2316 "RenderTexture Error: mipmapped float textures not "
2321 switch(_iNumComponents)
2324 if (GL_NV_float_buffer)
2326 iInternalFormat = (_iNumColorBits[0] > 16) ?
2327 GL_FLOAT_R32_NV : GL_FLOAT_R16_NV;
2329 else if (GL_ATI_texture_float)
2331 iInternalFormat = (_iNumColorBits[0] > 16) ?
2332 GL_LUMINANCE_FLOAT32_ATI :
2333 GL_LUMINANCE_FLOAT16_ATI;
2335 iFormat = GL_LUMINANCE;
2338 if (GL_NV_float_buffer)
2340 iInternalFormat = (_iNumColorBits[0] > 16) ?
2341 GL_FLOAT_RG32_NV : GL_FLOAT_RG16_NV;
2343 else if (GL_ATI_texture_float)
2345 iInternalFormat = (_iNumColorBits[0] > 16) ?
2346 GL_LUMINANCE_ALPHA_FLOAT32_ATI :
2347 GL_LUMINANCE_ALPHA_FLOAT16_ATI;
2349 iFormat = GL_LUMINANCE_ALPHA;
2352 if (GL_NV_float_buffer)
2354 iInternalFormat = (_iNumColorBits[0] > 16) ?
2355 GL_FLOAT_RGB32_NV : GL_FLOAT_RGB16_NV;
2357 else if (GL_ATI_texture_float)
2359 iInternalFormat = (_iNumColorBits[0] > 16) ?
2360 GL_RGB_FLOAT32_ATI : GL_RGB_FLOAT16_ATI;
2365 if (GL_NV_float_buffer)
2367 iInternalFormat = (_iNumColorBits[0] > 16) ?
2368 GL_FLOAT_RGBA32_NV : GL_FLOAT_RGBA16_NV;
2370 else if (GL_ATI_texture_float)
2372 iInternalFormat = (_iNumColorBits[0] > 16) ?
2373 GL_RGBA_FLOAT32_ATI : GL_RGBA_FLOAT16_ATI;
2378 SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: "
2379 "Invalid number of components: " <<
2386 if (4 == _iNumComponents)
2388 iInternalFormat = GL_RGBA8;
2393 iInternalFormat = GL_RGB8;
2398 // Allocate the texture image (but pass it no data for now).
2399 glTexImage2D(_iTextureTarget, 0, iInternalFormat,
2400 _iWidth, _iHeight, 0, iFormat, GL_FLOAT, NULL);
2404 if (_bIsDepthTexture)
2406 glGenTextures(1, (GLuint*)&_iDepthTextureID);
2407 glBindTexture(_iTextureTarget, _iDepthTextureID);
2409 // Use clamp to edge as the default texture wrap mode for all tex
2410 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2411 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2412 // Use NEAREST as the default texture filtering mode.
2413 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2414 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2416 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2419 if (_bHasARBDepthTexture)
2421 // Allocate the texture image (but pass it no data for now).
2422 glTexImage2D(_iTextureTarget, 0, GL_DEPTH_COMPONENT,
2423 _iWidth, _iHeight, 0, GL_DEPTH_COMPONENT,
2428 // allocate memory for depth texture
2429 // Since this is slow, we warn the user in debug mode. (above)
2430 _pPoorDepthTexture = new unsigned short[_iWidth * _iHeight];
2431 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
2432 _iWidth, _iHeight, 0, GL_LUMINANCE,
2433 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2443 //---------------------------------------------------------------------------
2444 // Function : RenderTexture::_MaybeCopyBuffer
2446 //---------------------------------------------------------------------------
2448 * @fn RenderTexture::_MaybeCopyBuffer()
2449 * @brief Does the actual copying for RenderTextures with RT_COPY_TO_TEXTURE
2451 void RenderTexture::_MaybeCopyBuffer()
2454 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2458 glBindTexture(_iTextureTarget, _iTextureID);
2459 glCopyTexSubImage2D(_iTextureTarget,
2460 0, 0, 0, 0, 0, _iWidth, _iHeight);
2462 if (_bIsDepthTexture)
2464 glBindTexture(_iTextureTarget, _iDepthTextureID);
2465 // HOW TO COPY DEPTH TEXTURE??? Supposedly this just magically works...
2467 if (_bHasARBDepthTexture)
2469 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0,
2474 // no 'real' depth texture available, so behavior has to be emulated
2475 // using glReadPixels (beware, this is (naturally) slow ...)
2476 glReadPixels(0, 0, _iWidth, _iHeight, GL_DEPTH_COMPONENT,
2477 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2478 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
2479 _iWidth, _iHeight, 0, GL_LUMINANCE,
2480 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2486 #elif defined(__MACH__)
2487 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2491 glBindTexture(_iTextureTarget, _iTextureID);
2492 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2494 if (_bIsDepthTexture)
2496 glBindTexture(_iTextureTarget, _iDepthTextureID);
2497 assert(_bHasARBDepthTexture);
2498 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2504 glBindTexture(_iTextureTarget, _iTextureID);
2505 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2507 if (_bIsDepthTexture)
2509 glBindTexture(_iTextureTarget, _iDepthTextureID);
2510 assert(_bHasARBDepthTexture);
2511 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2517 //---------------------------------------------------------------------------
2518 // Function : RenderTexture::_ReleaseBoundBuffers
2520 //---------------------------------------------------------------------------
2522 * @fn RenderTexture::_ReleaseBoundBuffers()
2523 * @brief Releases buffer bindings on RenderTextures with RT_RENDER_TO_TEXTURE
2525 bool RenderTexture::_ReleaseBoundBuffers()
2528 if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2530 glBindTexture(_iTextureTarget, _iTextureID);
2532 // release the pbuffer from the render texture object
2533 if (0 != _iCurrentBoundBuffer && _bIsBufferBound)
2535 if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, _iCurrentBoundBuffer))
2540 _bIsBufferBound = false;
2544 if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2546 glBindTexture(_iTextureTarget, _iDepthTextureID);
2548 // release the pbuffer from the render texture object
2549 if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
2557 // textures can't be bound in Linux
2562 //---------------------------------------------------------------------------
2563 // Function : RenderTexture::_MakeCurrent
2565 //---------------------------------------------------------------------------
2567 * @fn RenderTexture::_MakeCurrent()
2568 * @brief Makes the RenderTexture's context current
2571 bool RenderTexture::_MakeCurrent()
2574 // make the pbuffer's rendering context current.
2575 if (FALSE == wglMakeCurrent( _hDC, _hGLContext))
2580 #elif defined( __MACH__ )
2583 if (err = CGLSetCurrentContext(_hGLContext))
2585 _cglCheckError(err);
2589 if (false == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
2598 /////////////////////////////////////////////////////////////////////////////
2600 // Begin Deprecated Interface
2602 /////////////////////////////////////////////////////////////////////////////
2604 //---------------------------------------------------------------------------
2605 // Function : RenderTexture::RenderTexture
2607 //---------------------------------------------------------------------------
2609 * @fn RenderTexture::RenderTexture()
2610 * @brief Constructor.
2612 RenderTexture::RenderTexture(int width, int height,
2613 bool bIsTexture /* = true */,
2614 bool bIsDepthTexture /* = false */)
2617 _bIsTexture(bIsTexture),
2618 _bIsDepthTexture(bIsDepthTexture),
2619 _bHasARBDepthTexture(true), // [Redge]
2620 _eUpdateMode(RT_RENDER_TO_TEXTURE),
2621 _bInitialized(false),
2623 _iCurrentBoundBuffer(0),
2625 _iNumStencilBits(0),
2626 _bDoubleBuffered(false),
2631 _bShareObjects(false),
2632 _bCopyContext(false),
2638 _hPreviousContext(0),
2639 #elif defined( __MACH__ )
2642 _hPreviousContext(NULL),
2647 _hPreviousContext(0),
2648 _hPreviousDrawable(0),
2650 _iTextureTarget(GL_NONE),
2652 _iDepthTextureID(0),
2653 _pPoorDepthTexture(0) // [Redge]
2655 assert(width > 0 && height > 0);
2656 #if defined DEBUG || defined _DEBUG
2657 SG_LOG(SG_GL, SG_ALERT,
2658 "RenderTexture Warning: Deprecated Contructor interface used.");
2661 _iNumColorBits[0] = _iNumColorBits[1] =
2662 _iNumColorBits[2] = _iNumColorBits[3] = 0;
2663 _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
2666 //------------------------------------------------------------------------------
2667 // Function : RenderTexture::Initialize
2669 //------------------------------------------------------------------------------
2671 * @fn RenderTexture::Initialize(bool bShare, bool bDepth, bool bStencil, bool bMipmap, unsigned int iRBits, unsigned int iGBits, unsigned int iBBits, unsigned int iABits);
2672 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
2674 * This function actually does the creation of the p-buffer. It can only be called
2675 * once a GL context has already been created. Note that if the texture is not
2676 * power of two dimensioned, or has more than 8 bits per channel, enabling mipmapping
2677 * will cause an error.
2679 bool RenderTexture::Initialize(bool bShare /* = true */,
2680 bool bDepth /* = false */,
2681 bool bStencil /* = false */,
2682 bool bMipmap /* = false */,
2683 bool bAnisoFilter /* = false */,
2684 unsigned int iRBits /* = 8 */,
2685 unsigned int iGBits /* = 8 */,
2686 unsigned int iBBits /* = 8 */,
2687 unsigned int iABits /* = 8 */,
2688 UpdateMode updateMode /* = RT_RENDER_TO_TEXTURE */)
2690 if (0 == _iWidth || 0 == _iHeight)
2693 #if defined DEBUG || defined _DEBUG
2694 SG_LOG(SG_GL, SG_ALERT,
2695 "RenderTexture Warning: Deprecated Initialize() interface used.");
2698 // create a mode string.
2701 mode.append("depth ");
2703 mode.append("stencil ");
2705 mode.append("mipmap ");
2706 if (iRBits + iGBits + iBBits + iABits > 0)
2717 char bitVector[100];
2718 snprintf( bitVector, 100,
2719 "%d%s,%d%s,%d%s,%d%s",
2720 iRBits, (iRBits >= 16) ? "f" : "",
2721 iGBits, (iGBits >= 16) ? "f" : "",
2722 iBBits, (iBBits >= 16) ? "f" : "",
2723 iABits, (iABits >= 16) ? "f" : "");
2724 mode.append(bitVector);
2729 if ((GL_NV_texture_rectangle || GL_EXT_texture_rectangle) &&
2730 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2731 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2732 mode.append("texRECT ");
2734 mode.append("tex2D ");
2736 if (_bIsDepthTexture)
2738 if ((GL_NV_texture_rectangle || GL_EXT_texture_rectangle) &&
2739 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2740 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2741 mode.append("texRECT ");
2743 mode.append("tex2D ");
2745 if (RT_COPY_TO_TEXTURE == updateMode)
2748 _pixelFormatAttribs.clear();
2749 _pbufferAttribs.clear();
2752 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
2753 _pixelFormatAttribs.push_back(true);
2754 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
2755 _pixelFormatAttribs.push_back(true);
2757 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
2758 _pbufferAttribs.push_back(true);
2759 #elif defined( __MACH__ )
2760 //_pixelFormatAttribs.push_back(kCGLPFANoRecovery);
2761 _pixelFormatAttribs.push_back(kCGLPFAAccelerated);
2762 _pixelFormatAttribs.push_back(kCGLPFAWindow);
2763 _pixelFormatAttribs.push_back(kCGLPFAPBuffer);
2765 _pixelFormatAttribs.push_back(GLX_RENDER_TYPE_SGIX);
2766 _pixelFormatAttribs.push_back(GLX_RGBA_BIT_SGIX);
2767 _pixelFormatAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
2768 _pixelFormatAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
2771 _ParseModeString(mode.c_str(), _pixelFormatAttribs, _pbufferAttribs);
2774 _pixelFormatAttribs.push_back(0);
2775 _pbufferAttribs.push_back(0);
2776 #elif defined(__MACH__)
2777 _pixelFormatAttribs.push_back(0);
2779 _pixelFormatAttribs.push_back(None);
2782 Initialize(_iWidth, _iHeight, bShare);
2788 //---------------------------------------------------------------------------
2789 // Function : RenderTexture::Reset
2791 //---------------------------------------------------------------------------
2793 * @fn RenderTexture::Reset(int iWidth, int iHeight, unsigned int iMode, bool bIsTexture, bool bIsDepthTexture)
2794 * @brief Resets the resolution of the offscreen buffer.
2796 * Causes the buffer to delete itself. User must call Initialize() again
2799 bool RenderTexture::Reset(int iWidth, int iHeight)
2801 SG_LOG(SG_GL, SG_ALERT,
2802 "RenderTexture Warning: Deprecated Reset() interface used.");
2806 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Reset(): failed to invalidate.");