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 _hPreviousDrawable(0),
150 _hPreviousContext(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 )
526 SG_LOG(SG_GL, SG_ALERT,
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 = NULL;
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,
675 for (int i=0;i<nConfigs;i++)
677 _hPBuffer = glXCreateGLXPbufferPtr(_pDisplay, fbConfigs[i],
678 _iWidth, _iHeight, NULL);
681 _hGLContext = glXCreateContextWithConfigPtr(_pDisplay,
684 _bShareObjects ? context : NULL,
694 SG_LOG(SG_GL, SG_ALERT,
695 "RenderTexture Error: glXCreateGLXPbufferPtr() failed.");
702 _hGLContext = glXCreateContext(_pDisplay, visInfo,
703 _bShareObjects ? context : NULL, False);
706 SG_LOG(SG_GL, SG_ALERT,
707 "RenderTexture Error: glXCreateContext() failed.");
712 if (!glXVersion1_3Present)
714 glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_WIDTH_SGIX,
716 glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_HEIGHT_SGIX,
720 _bInitialized = true;
722 // XXX Query the color format
727 // Now that the pbuffer is created, allocate any texture objects needed,
728 // and initialize them (for CTT updates only). These must be allocated
729 // in the context of the pbuffer, though, or the RT won't work without
732 if (false == wglMakeCurrent( _hDC, _hGLContext))
737 #elif defined( __MACH__ )
739 if (err = CGLSetCurrentContext(_hGLContext))
745 _hPreviousContext = glXGetCurrentContext();
746 _hPreviousDrawable = glXGetCurrentDrawable();
748 if (False == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
754 bool result = _InitializeTextures();
756 BindBuffer(WGL_FRONT_LEFT_ARB);
762 // make the previous rendering context current
763 if (false == wglMakeCurrent( hdc, hglrc))
768 #elif defined( __MACH__ )
769 if (err = CGLSetCurrentContext(_hPreviousContext))
775 if (False == glXMakeCurrent(_pDisplay,
776 _hPreviousDrawable, _hPreviousContext))
780 if (glXVersion1_3Present)
782 GLXDrawable draw = glXGetCurrentDrawable();
783 glXQueryDrawablePtr(_pDisplay, draw, GLX_WIDTH, (unsigned int*)&_iWidth);
784 glXQueryDrawablePtr(_pDisplay, draw, GLX_HEIGHT, (unsigned int*)&_iHeight);
792 //---------------------------------------------------------------------------
793 // Function : RenderTexture::_Invalidate
795 //---------------------------------------------------------------------------
797 * @fn RenderTexture::_Invalidate()
798 * @brief Returns the pbuffer memory to the graphics device.
801 bool RenderTexture::_Invalidate()
803 _iNumColorBits[0] = _iNumColorBits[1] =
804 _iNumColorBits[2] = _iNumColorBits[3] = 0;
806 _iNumStencilBits = 0;
809 glDeleteTextures(1, &_iTextureID);
810 if (_bIsDepthTexture)
813 if (!_bHasARBDepthTexture) delete[] _pPoorDepthTexture;
815 glDeleteTextures(1, &_iDepthTextureID);
821 // Check if we are currently rendering in the pbuffer
822 if (wglGetCurrentContext() == _hGLContext)
825 wglDeleteContext( _hGLContext);
826 wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
827 wglDestroyPbufferARBPtr( _hPBuffer );
831 #elif defined( __MACH__ )
834 if (CGLGetCurrentContext() == _hGLContext)
835 CGLSetCurrentContext(NULL);
837 CGLDestroyContext(_hGLContext);
838 CGLDestroyPBuffer(_hPBuffer);
845 if(glXGetCurrentContext() == _hGLContext)
846 // XXX I don't know if this is right at all
847 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
848 glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
854 // [WVB] do we need to call _ReleaseBoundBuffers() too?
859 //---------------------------------------------------------------------------
860 // Function : RenderTexture::Reset
862 //---------------------------------------------------------------------------
864 * @fn RenderTexture::Reset()
865 * @brief Resets the resolution of the offscreen buffer.
867 * Causes the buffer to delete itself. User must call Initialize() again
870 bool RenderTexture::Reset(const char *strMode, ...)
872 _iWidth = 0; _iHeight = 0;
873 _bIsTexture = false; _bIsDepthTexture = false,
874 _bHasARBDepthTexture = true;
875 #if defined(_WIN32) || defined(__MACH__)
876 _eUpdateMode = RT_RENDER_TO_TEXTURE;
878 _eUpdateMode = RT_COPY_TO_TEXTURE;
880 _bInitialized = false;
882 _bIsBufferBound = false;
883 _iCurrentBoundBuffer = 0;
884 _iNumDepthBits = 0; _iNumStencilBits = 0;
885 _bDoubleBuffered = false;
886 _bFloat = false; _bPowerOf2 = true;
887 _bRectangle = false; _bMipmap = false;
888 _bShareObjects = false; _bCopyContext = false;
889 _iTextureTarget = GL_NONE; _iTextureID = 0;
890 _iDepthTextureID = 0;
891 _pPoorDepthTexture = 0;
892 _pixelFormatAttribs.clear();
893 _pbufferAttribs.clear();
895 if (IsInitialized() && !_Invalidate())
897 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Reset(): failed to invalidate.");
901 _iNumColorBits[0] = _iNumColorBits[1] =
902 _iNumColorBits[2] = _iNumColorBits[3] = 0;
905 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
906 _pixelFormatAttribs.push_back(true);
907 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
908 _pixelFormatAttribs.push_back(true);
910 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
911 _pbufferAttribs.push_back(true);
912 #elif defined( __MACH__ )
913 //_pixelFormatAttribs.push_back(kCGLPFANoRecovery);
914 _pixelFormatAttribs.push_back(kCGLPFAAccelerated);
915 _pixelFormatAttribs.push_back(kCGLPFAWindow);
916 _pixelFormatAttribs.push_back(kCGLPFAPBuffer);
918 _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
919 _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
920 _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
921 _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
926 va_start(args,strMode);
927 #if defined _WIN32 && !defined __CYGWIN__
928 _vsnprintf( strBuffer, 256, strMode, args );
930 vsnprintf( strBuffer, 256, strMode, args );
934 _ParseModeString(strBuffer, _pixelFormatAttribs, _pbufferAttribs);
937 _pixelFormatAttribs.push_back(0);
938 _pbufferAttribs.push_back(0);
939 #elif defined(__MACH__)
940 _pixelFormatAttribs.push_back((CGLPixelFormatAttribute)0);
942 _pixelFormatAttribs.push_back(None);
947 //------------------------------------------------------------------------------
948 // Function : RenderTexture::Resize
950 //------------------------------------------------------------------------------
952 * @fn RenderTexture::Resize(int iWidth, int iHeight)
953 * @brief Changes the size of the offscreen buffer.
955 * Like Reset() this causes the buffer to delete itself.
956 * But unlike Reset(), this call re-initializes the RenderTexture.
957 * Note that Resize() will not work after calling Reset(), or before
958 * calling Initialize() the first time.
960 bool RenderTexture::Resize(int iWidth, int iHeight)
962 if (!_bInitialized) {
963 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): must Initialize() first.");
966 if (iWidth == _iWidth && iHeight == _iHeight) {
970 // Do same basic work as _Invalidate, but don't reset all our flags
972 glDeleteTextures(1, &_iTextureID);
973 if (_bIsDepthTexture)
974 glDeleteTextures(1, &_iDepthTextureID);
978 // Check if we are currently rendering in the pbuffer
979 if (wglGetCurrentContext() == _hGLContext)
982 wglDeleteContext( _hGLContext);
983 wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
984 wglDestroyPbufferARBPtr( _hPBuffer );
988 #elif defined( __MACH__ )
991 if (CGLGetCurrentContext() == _hGLContext)
992 CGLSetCurrentContext(NULL);
994 CGLDestroyContext(_hGLContext);
995 CGLDestroyPBuffer(_hPBuffer);
1002 if(glXGetCurrentContext() == _hGLContext)
1003 // XXX I don't know if this is right at all
1004 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
1005 glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
1010 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): failed to resize.");
1013 _bInitialized = false;
1014 return Initialize(iWidth, iHeight, _bShareObjects, _bCopyContext);
1017 //---------------------------------------------------------------------------
1018 // Function : RenderTexture::BeginCapture
1020 //---------------------------------------------------------------------------
1022 * @fn RenderTexture::BeginCapture()
1023 * @brief Activates rendering to the RenderTexture.
1025 bool RenderTexture::BeginCapture()
1029 SG_LOG(SG_GL, SG_ALERT,
1030 "RenderTexture::BeginCapture(): Texture is not initialized!");
1034 // cache the current context so we can reset it when EndCapture() is called.
1035 _hPreviousDC = wglGetCurrentDC();
1036 if (NULL == _hPreviousDC)
1038 _hPreviousContext = wglGetCurrentContext();
1039 if (NULL == _hPreviousContext)
1041 #elif defined( __MACH__ )
1042 _hPreviousContext = CGLGetCurrentContext();
1044 _hPreviousContext = glXGetCurrentContext();
1045 _hPreviousDrawable = glXGetCurrentDrawable();
1048 _ReleaseBoundBuffers();
1050 return _MakeCurrent();
1054 //---------------------------------------------------------------------------
1055 // Function : RenderTexture::EndCapture
1057 //---------------------------------------------------------------------------
1059 * @fn RenderTexture::EndCapture()
1060 * @brief Ends rendering to the RenderTexture.
1062 bool RenderTexture::EndCapture()
1066 SG_LOG(SG_GL, SG_ALERT,
1067 "RenderTexture::EndCapture() : Texture is not initialized!");
1071 glFlush(); // Added by a-lex
1076 // make the previous rendering context current
1077 if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
1082 #elif defined( __MACH__ )
1084 if (err = CGLSetCurrentContext(_hPreviousContext))
1086 _cglCheckError(err);
1090 if (False == glXMakeCurrent(_pDisplay, _hPreviousDrawable,
1097 // rebind the textures to a buffers for RTT
1098 BindBuffer(_iCurrentBoundBuffer);
1104 //---------------------------------------------------------------------------
1105 // Function : RenderTexture::BeginCapture(RenderTexture*)
1107 //---------------------------------------------------------------------------
1109 * @fn RenderTexture::BeginCapture(RenderTexture* other)
1110 * @brief Ends capture of 'other', begins capture on 'this'
1112 * When performing a series of operations where you modify one texture after
1113 * another, it is more efficient to use this method instead of the equivalent
1114 * 'EndCapture'/'BeginCapture' pair. This method switches directly to the
1115 * new context rather than changing to the default context, and then to the
1118 * RenderTexture doesn't have any mechanism for determining if
1119 * 'current' really is currently active, so no error will be thrown
1122 bool RenderTexture::BeginCapture(RenderTexture* current)
1124 // bool bContextReset = false;
1126 if (current == this) {
1127 return true; // no switch necessary
1130 // treat as normal Begin if current is 0.
1131 return BeginCapture();
1135 SG_LOG(SG_GL, SG_ALERT,
1136 "RenderTexture::BeginCapture(RenderTexture*): Texture is not initialized!");
1139 if (!current->_bInitialized)
1141 SG_LOG(SG_GL, SG_ALERT,
1142 "RenderTexture::BeginCapture(RenderTexture): 'current' texture is not initialized!");
1146 // Sync current pbuffer with its CTT texture if necessary
1147 current->_MaybeCopyBuffer();
1149 // pass along the previous context so we can reset it when
1150 // EndCapture() is called.
1152 _hPreviousDC = current->_hPreviousDC;
1153 if (NULL == _hPreviousDC)
1155 _hPreviousContext = current->_hPreviousContext;
1156 if (NULL == _hPreviousContext)
1158 #elif defined( __MACH__ )
1159 _hPreviousContext = current->_hPreviousContext;
1161 _hPreviousContext = current->_hPreviousContext;
1162 _hPreviousDrawable = current->_hPreviousDrawable;
1165 // Unbind textures before making context current
1166 if (!_ReleaseBoundBuffers())
1169 // Make the pbuffer context current
1170 if (!_MakeCurrent())
1173 // Rebind buffers of initial RenderTexture
1174 current->BindBuffer(_iCurrentBoundBuffer);
1175 current->_BindDepthBuffer();
1182 //---------------------------------------------------------------------------
1183 // Function : RenderTexture::Bind
1185 //---------------------------------------------------------------------------
1187 * @fn RenderTexture::Bind()
1188 * @brief Binds RGB texture.
1190 void RenderTexture::Bind() const
1192 if (_bInitialized && _bIsTexture)
1194 glBindTexture(_iTextureTarget, _iTextureID);
1199 //---------------------------------------------------------------------------
1200 // Function : RenderTexture::BindDepth
1202 //---------------------------------------------------------------------------
1204 * @fn RenderTexture::BindDepth()
1205 * @brief Binds depth texture.
1207 void RenderTexture::BindDepth() const
1209 if (_bInitialized && _bIsDepthTexture)
1211 glBindTexture(_iTextureTarget, _iDepthTextureID);
1216 //---------------------------------------------------------------------------
1217 // Function : RenderTexture::BindBuffer
1219 //---------------------------------------------------------------------------
1221 * @fn RenderTexture::BindBuffer()
1222 * @brief Associate the RTT texture id with 'iBuffer' (e.g. WGL_FRONT_LEFT_ARB)
1224 bool RenderTexture::BindBuffer( int iBuffer )
1226 // Must bind the texture too
1227 if (_bInitialized && _bIsTexture)
1229 glBindTexture(_iTextureTarget, _iTextureID);
1232 if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
1233 (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
1235 if (FALSE == wglBindTexImageARBPtr(_hPBuffer, iBuffer))
1237 // WVB: WGL API considers binding twice to the same buffer
1238 // to be an error. But we don't want to
1239 //_wglGetLastError();
1243 _bIsBufferBound = true;
1244 _iCurrentBoundBuffer = iBuffer;
1246 #elif defined(__MACH__)
1247 if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
1248 (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
1251 if (err=CGLTexImagePBuffer(CGLGetCurrentContext(), _hPBuffer, iBuffer))
1253 _cglCheckError(err);
1255 _bIsBufferBound = true;
1256 _iCurrentBoundBuffer = iBuffer;
1264 //---------------------------------------------------------------------------
1265 // Function : RenderTexture::BindDepthBuffer
1267 //---------------------------------------------------------------------------
1269 * @fn RenderTexture::_BindDepthBuffer()
1270 * @brief Associate the RTT depth texture id with the depth buffer
1272 bool RenderTexture::_BindDepthBuffer() const
1275 if (_bInitialized && _bIsDepthTexture &&
1276 RT_RENDER_TO_TEXTURE == _eUpdateMode)
1278 glBindTexture(_iTextureTarget, _iDepthTextureID);
1279 if (FALSE == wglBindTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1285 #elif defined(__MACH__)
1286 if (_bInitialized && _bIsDepthTexture &&
1287 RT_RENDER_TO_TEXTURE == _eUpdateMode)
1289 glBindTexture(_iTextureTarget, _iDepthTextureID);
1290 //if (FALSE == CGLTexImagePBuffer(<#CGLContextObj ctx#>,<#CGLPBufferObj pbuffer#>,<#unsigned long source#>)(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1292 // _wglGetLastError();
1300 //---------------------------------------------------------------------------
1301 // Function : RenderTexture::_ParseModeString
1303 //---------------------------------------------------------------------------
1305 * @fn RenderTexture::_ParseModeString()
1306 * @brief Parses the user-specified mode string for RenderTexture parameters.
1308 void RenderTexture::_ParseModeString(const char *modeString,
1309 vector<int> &pfAttribs,
1310 vector<int> &pbAttribs)
1312 if (!modeString || strcmp(modeString, "") == 0)
1315 _iNumComponents = 0;
1316 #if defined(_WIN32) || defined(__MACH__)
1317 _eUpdateMode = RT_RENDER_TO_TEXTURE;
1319 _eUpdateMode = RT_COPY_TO_TEXTURE;
1323 bool bHasStencil = false;
1324 bool bBind2D = false;
1325 bool bBindRECT = false;
1326 bool bBindCUBE = false;
1328 char *mode = strdup(modeString);
1331 vector<string> tokens;
1332 char *buf = strtok(mode, " ");
1335 tokens.push_back(buf);
1336 buf = strtok(NULL, " ");
1339 for (unsigned int i = 0; i < tokens.size(); i++)
1341 string token = tokens[i];
1343 KeyVal kv = _GetKeyValuePair(token);
1346 if (kv.first == "rgb" && (_iNumComponents <= 1))
1348 if (kv.second.find("f") != kv.second.npos)
1351 vector<int> bitVec = _ParseBitVector(kv.second);
1353 if (bitVec.size() < 3) // expand the scalar to a vector
1355 bitVec.push_back(bitVec[0]);
1356 bitVec.push_back(bitVec[0]);
1360 pfAttribs.push_back(WGL_RED_BITS_ARB);
1361 pfAttribs.push_back(bitVec[0]);
1362 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1363 pfAttribs.push_back(bitVec[1]);
1364 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1365 pfAttribs.push_back(bitVec[2]);
1366 #elif defined( __MACH__ )
1368 pfAttribs.push_back(AGL_RED_SIZE);
1369 pfAttribs.push_back(bitVec[0]);
1370 pfAttribs.push_back(AGL_GREEN_SIZE);
1371 pfAttribs.push_back(bitVec[1]);
1372 pfAttribs.push_back(AGL_BLUE_SIZE);
1373 pfAttribs.push_back(bitVec[2]);
1375 pfAttribs.push_back(kCGLPFAColorSize);
1376 pfAttribs.push_back(bitVec[0] + bitVec[1] + bitVec[2]);
1379 pfAttribs.push_back(GLX_RED_SIZE);
1380 pfAttribs.push_back(bitVec[0]);
1381 pfAttribs.push_back(GLX_GREEN_SIZE);
1382 pfAttribs.push_back(bitVec[1]);
1383 pfAttribs.push_back(GLX_BLUE_SIZE);
1384 pfAttribs.push_back(bitVec[2]);
1386 _iNumComponents += 3;
1389 else if (kv.first == "rgb")
1390 SG_LOG(SG_GL, SG_ALERT,
1391 "RenderTexture Warning: mistake in components definition "
1392 "(rgb + " << _iNumComponents << ").");
1394 if (kv.first == "rgba" && (_iNumComponents == 0))
1396 if (kv.second.find("f") != kv.second.npos)
1399 vector<int> bitVec = _ParseBitVector(kv.second);
1401 if (bitVec.size() < 4) // expand the scalar to a vector
1403 bitVec.push_back(bitVec[0]);
1404 bitVec.push_back(bitVec[0]);
1405 bitVec.push_back(bitVec[0]);
1409 pfAttribs.push_back(WGL_RED_BITS_ARB);
1410 pfAttribs.push_back(bitVec[0]);
1411 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1412 pfAttribs.push_back(bitVec[1]);
1413 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1414 pfAttribs.push_back(bitVec[2]);
1415 pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1416 pfAttribs.push_back(bitVec[3]);
1417 #elif defined( __MACH__ )
1419 pfAttribs.push_back(AGL_RED_SIZE);
1420 pfAttribs.push_back(bitVec[0]);
1421 pfAttribs.push_back(AGL_GREEN_SIZE);
1422 pfAttribs.push_back(bitVec[1]);
1423 pfAttribs.push_back(AGL_BLUE_SIZE);
1424 pfAttribs.push_back(bitVec[2]);
1425 pfAttribs.push_back(AGL_ALPHA_SIZE);
1426 pfAttribs.push_back(bitVec[3]);
1428 pfAttribs.push_back(kCGLPFAColorSize);
1429 pfAttribs.push_back(bitVec[0] + bitVec[1] + bitVec[2] + bitVec[3]);
1430 //pfAttribs.push_back(kCGLPFAAlphaSize);
1431 //pfAttribs.push_back(bitVec[3]);
1432 // printf("Color size: %d\n", bitVec[0] + bitVec[1] + bitVec[2] + bitVec[3]);
1436 pfAttribs.push_back(GLX_RED_SIZE);
1437 pfAttribs.push_back(bitVec[0]);
1438 pfAttribs.push_back(GLX_GREEN_SIZE);
1439 pfAttribs.push_back(bitVec[1]);
1440 pfAttribs.push_back(GLX_BLUE_SIZE);
1441 pfAttribs.push_back(bitVec[2]);
1442 pfAttribs.push_back(GLX_ALPHA_SIZE);
1443 pfAttribs.push_back(bitVec[3]);
1445 _iNumComponents = 4;
1448 else if (kv.first == "rgba")
1449 SG_LOG(SG_GL, SG_ALERT,
1450 "RenderTexture Warning: mistake in components definition "
1451 "(rgba + " << _iNumComponents << ").");
1453 if (kv.first == "r" && (_iNumComponents <= 1))
1455 if (kv.second.find("f") != kv.second.npos)
1458 vector<int> bitVec = _ParseBitVector(kv.second);
1461 pfAttribs.push_back(WGL_RED_BITS_ARB);
1462 pfAttribs.push_back(bitVec[0]);
1463 #elif defined( __MACH__ )
1465 pfAttribs.push_back(AGL_RED_SIZE);
1466 pfAttribs.push_back(bitVec[0]);
1468 pfAttribs.push_back(kCGLPFAColorSize);
1469 pfAttribs.push_back(bitVec[0]);
1472 pfAttribs.push_back(GLX_RED_SIZE);
1473 pfAttribs.push_back(bitVec[0]);
1478 else if (kv.first == "r")
1479 SG_LOG(SG_GL, SG_ALERT,
1480 "RenderTexture Warning: mistake in components definition "
1481 "(r + " << _iNumComponents << ").");
1483 if (kv.first == "rg" && (_iNumComponents <= 1))
1485 if (kv.second.find("f") != kv.second.npos)
1488 vector<int> bitVec = _ParseBitVector(kv.second);
1490 if (bitVec.size() < 2) // expand the scalar to a vector
1492 bitVec.push_back(bitVec[0]);
1496 pfAttribs.push_back(WGL_RED_BITS_ARB);
1497 pfAttribs.push_back(bitVec[0]);
1498 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1499 pfAttribs.push_back(bitVec[1]);
1500 #elif defined( __MACH__ )
1502 pfAttribs.push_back(AGL_RED_SIZE);
1503 pfAttribs.push_back(bitVec[0]);
1504 pfAttribs.push_back(AGL_GREEN_SIZE);
1505 pfAttribs.push_back(bitVec[1]);
1507 pfAttribs.push_back(kCGLPFAColorSize);
1508 pfAttribs.push_back(bitVec[0] + bitVec[1]);
1511 pfAttribs.push_back(GLX_RED_SIZE);
1512 pfAttribs.push_back(bitVec[0]);
1513 pfAttribs.push_back(GLX_GREEN_SIZE);
1514 pfAttribs.push_back(bitVec[1]);
1516 _iNumComponents += 2;
1519 else if (kv.first == "rg")
1520 SG_LOG(SG_GL, SG_ALERT,
1521 "RenderTexture Warning: mistake in components definition "
1522 "(rg + " << _iNumComponents << ").");
1524 if (kv.first == "depth")
1526 if (kv.second == "")
1529 iDepthBits = strtol(kv.second.c_str(), 0, 10);
1533 if (kv.first == "stencil")
1537 pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1538 #elif defined( __MACH__ )
1540 pfAttribs.push_back(AGL_STENCIL_SIZE);
1542 pfAttribs.push_back(kCGLPFAStencilSize);
1545 pfAttribs.push_back(GLX_STENCIL_SIZE);
1547 if (kv.second == "")
1548 pfAttribs.push_back(8);
1550 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1554 if (kv.first == "samples")
1557 pfAttribs.push_back(WGL_SAMPLE_BUFFERS_ARB);
1558 pfAttribs.push_back(1);
1559 pfAttribs.push_back(WGL_SAMPLES_ARB);
1560 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1561 #elif defined( __MACH__ )
1563 pfAttribs.push_back(AGL_SAMPLE_BUFFERS_ARB);
1564 pfAttribs.push_back(1);
1565 pfAttribs.push_back(AGL_SAMPLES_ARB);
1567 pfAttribs.push_back(kCGLPFAMultisample);
1568 pfAttribs.push_back(kCGLPFASamples);
1570 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1572 pfAttribs.push_back(GLX_SAMPLE_BUFFERS_ARB);
1573 pfAttribs.push_back(1);
1574 pfAttribs.push_back(GLX_SAMPLES_ARB);
1575 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1581 if (kv.first == "doublebuffer" || kv.first == "double")
1584 pfAttribs.push_back(WGL_DOUBLE_BUFFER_ARB);
1585 pfAttribs.push_back(true);
1586 #elif defined( __MACH__ )
1588 pfAttribs.push_back(AGL_DOUBLEBUFFER);
1589 pfAttribs.push_back(True);
1591 pfAttribs.push_back(kCGLPFADoubleBuffer);
1594 pfAttribs.push_back(GLX_DOUBLEBUFFER);
1595 pfAttribs.push_back(True);
1600 if (kv.first == "aux")
1603 pfAttribs.push_back(WGL_AUX_BUFFERS_ARB);
1604 #elif defined( __MACH__ )
1606 pfAttribs.push_back(AGL_AUX_BUFFERS);
1608 pfAttribs.push_back(kCGLPFAAuxBuffers);
1611 pfAttribs.push_back(GLX_AUX_BUFFERS);
1613 if (kv.second == "")
1614 pfAttribs.push_back(0);
1616 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1620 if (token.find("tex") == 0)
1624 if ((kv.first == "texRECT") && (GL_NV_texture_rectangle ||
1625 GL_EXT_texture_rectangle))
1630 else if (kv.first == "texCUBE")
1642 if (token.find("depthTex") == 0)
1644 _bIsDepthTexture = true;
1646 if ((kv.first == "depthTexRECT") && (GL_NV_texture_rectangle ||
1647 GL_EXT_texture_rectangle))
1652 else if (kv.first == "depthTexCUBE")
1664 if (kv.first == "mipmap")
1670 if (kv.first == "rtt")
1672 _eUpdateMode = RT_RENDER_TO_TEXTURE;
1676 if (kv.first == "ctt")
1678 _eUpdateMode = RT_COPY_TO_TEXTURE;
1682 SG_LOG(SG_GL, SG_ALERT,
1683 "RenderTexture Error: Unknown pbuffer attribute: " <<
1687 // Processing of some options must be last because of interactions.
1689 // Check for inconsistent texture targets
1690 if (_bIsTexture && _bIsDepthTexture && !(bBind2D ^ bBindRECT ^ bBindCUBE))
1692 SG_LOG(SG_GL, SG_ALERT,
1693 "RenderTexture Warning: Depth and Color texture targets "
1697 // Apply default bit format if none specified
1699 if (0 == _iNumComponents)
1701 pfAttribs.push_back(WGL_RED_BITS_ARB);
1702 pfAttribs.push_back(8);
1703 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1704 pfAttribs.push_back(8);
1705 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1706 pfAttribs.push_back(8);
1707 pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1708 pfAttribs.push_back(8);
1709 _iNumComponents = 4;
1714 if (_bIsDepthTexture && !iDepthBits)
1718 pfAttribs.push_back(WGL_DEPTH_BITS_ARB);
1719 #elif defined( __MACH__ )
1721 pfAttribs.push_back(AGL_DEPTH_SIZE);
1723 pfAttribs.push_back(kCGLPFADepthSize);
1726 pfAttribs.push_back(GLX_DEPTH_SIZE);
1728 pfAttribs.push_back(iDepthBits); // default
1733 pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1734 pfAttribs.push_back(0);
1735 #elif defined( __MACH__ )
1737 pfAttribs.push_back(AGL_STENCIL_SIZE);
1739 pfAttribs.push_back(kCGLPFAStencilSize);
1741 pfAttribs.push_back(0);
1743 pfAttribs.push_back(GLX_STENCIL_SIZE);
1744 pfAttribs.push_back(0);
1748 if (_iNumComponents < 4)
1750 // Can't do this right now -- on NVIDIA drivers, currently get
1751 // a non-functioning pbuffer if ALPHA_BITS=0 and
1752 // WGL_BIND_TO_TEXTURE_RGB_ARB=true
1754 //pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1755 //pfAttribs.push_back(0);
1759 if (!WGL_NV_render_depth_texture && _bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1761 #if defined(DEBUG) || defined(_DEBUG)
1762 SG_LOG(SG_GL, SG_ALERT, "RenderTexture Warning: No support found for "
1763 "render to depth texture.");
1765 _bIsDepthTexture = false;
1769 if ((_bIsTexture || _bIsDepthTexture) &&
1770 (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1775 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1776 pbAttribs.push_back(WGL_TEXTURE_RECTANGLE_NV);
1780 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1781 pbAttribs.push_back(WGL_TEXTURE_CUBE_MAP_ARB);
1785 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1786 pbAttribs.push_back(WGL_TEXTURE_2D_ARB);
1791 pbAttribs.push_back(WGL_MIPMAP_TEXTURE_ARB);
1792 pbAttribs.push_back(true);
1794 #elif defined(__MACH__)
1795 #elif defined(DEBUG) || defined(_DEBUG)
1796 SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: Render to Texture not "
1797 "supported in Linux or MacOS");
1801 // Set the pixel type
1805 if (WGL_NV_float_buffer)
1807 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1808 pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1810 pfAttribs.push_back(WGL_FLOAT_COMPONENTS_NV);
1811 pfAttribs.push_back(true);
1815 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1816 pfAttribs.push_back(WGL_TYPE_RGBA_FLOAT_ATI);
1818 #elif defined( __MACH__ )
1819 // if (GL_MACH_float_pixels) // FIXME
1821 pfAttribs.push_back(kCGLPFAColorFloat);
1824 if (GLX_NV_float_buffer)
1826 pfAttribs.push_back(GLX_FLOAT_COMPONENTS_NV);
1827 pfAttribs.push_back(1);
1834 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1835 pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1839 // Set up texture binding for render to texture
1840 if (_bIsTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1846 if (WGL_NV_float_buffer)
1848 switch(_iNumComponents)
1851 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
1852 pfAttribs.push_back(true);
1854 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1855 pbAttribs.push_back(WGL_TEXTURE_FLOAT_R_NV);
1858 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
1859 pfAttribs.push_back(true);
1861 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1862 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RG_NV);
1865 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
1866 pfAttribs.push_back(true);
1868 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1869 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGB_NV);
1872 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
1873 pfAttribs.push_back(true);
1875 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1876 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGBA_NV);
1879 SG_LOG(SG_GL, SG_ALERT,
1880 "RenderTexture Warning: Bad number of components "
1881 "(r=1,rg=2,rgb=3,rgba=4): " <<
1888 if (4 == _iNumComponents)
1890 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1891 pfAttribs.push_back(true);
1893 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1894 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1898 // standard ARB_render_texture only supports 3 or 4 channels
1899 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1900 pfAttribs.push_back(true);
1902 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1903 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1910 switch(_iNumComponents)
1913 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1914 pfAttribs.push_back(true);
1916 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1917 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1920 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1921 pfAttribs.push_back(true);
1923 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1924 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1927 SG_LOG(SG_GL, SG_ALERT,
1928 "RenderTexture Warning: Bad number of components "
1929 "(r=1,rg=2,rgb=3,rgba=4): " << _iNumComponents);
1933 #elif defined(__MACH__)
1937 //if (WGLEW_NV_float_buffer) // FIXME
1939 switch(_iNumComponents)
1942 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
1943 pfAttribs.push_back(true);
1945 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1946 pbAttribs.push_back(WGL_TEXTURE_FLOAT_R_NV);
1949 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
1950 pfAttribs.push_back(true);
1952 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1953 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RG_NV);
1956 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
1957 pfAttribs.push_back(true);
1959 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1960 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGB_NV);
1963 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
1964 pfAttribs.push_back(true);
1966 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1967 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGBA_NV);
1971 "RenderTexture Warning: Bad number of components "
1972 "(r=1,rg=2,rgb=3,rgba=4): %d.\n",
1979 if (4 == _iNumComponents)
1981 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1982 pfAttribs.push_back(true);
1984 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1985 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1989 // standard ARB_render_texture only supports 3 or 4 channels
1990 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1991 pfAttribs.push_back(true);
1993 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1994 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
2002 switch(_iNumComponents)
2005 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
2006 pfAttribs.push_back(true);
2008 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2009 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
2012 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
2013 pfAttribs.push_back(true);
2015 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2016 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
2020 "RenderTexture Warning: Bad number of components "
2021 "(r=1,rg=2,rgb=3,rgba=4): %d.\n", _iNumComponents);
2026 #elif defined(DEBUG) || defined(_DEBUG)
2027 SG_LOG(SG_GL, SG_ALERT,
2028 "RenderTexture Error: Render to Texture not supported in "
2029 "Linux or MacOS\ n");
2033 if (_bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
2038 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV);
2039 pfAttribs.push_back(true);
2041 pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
2042 pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
2046 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_DEPTH_NV);
2047 pfAttribs.push_back(true);
2049 pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
2050 pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
2052 #elif defined(__MACH__)
2053 #elif defined(DEBUG) || defined(_DEBUG)
2054 SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: Render to Texture not supported in "
2060 //---------------------------------------------------------------------------
2061 // Function : RenderTexture::_GetKeyValuePair
2063 //---------------------------------------------------------------------------
2065 * @fn RenderTexture::_GetKeyValuePair()
2066 * @brief Parses expressions of the form "X=Y" into a pair (X,Y).
2068 RenderTexture::KeyVal RenderTexture::_GetKeyValuePair(string token)
2070 string::size_type pos = 0;
2071 if ((pos = token.find("=")) != token.npos)
2073 string key = token.substr(0, pos);
2074 string value = token.substr(pos+1, token.length()-pos+1);
2075 return KeyVal(key, value);
2078 return KeyVal(token, "");
2081 //---------------------------------------------------------------------------
2082 // Function : RenderTexture::_ParseBitVector
2084 //---------------------------------------------------------------------------
2086 * @fn RenderTexture::_ParseBitVector()
2087 * @brief Parses expressions of the form "=r,g,b,a" into a vector: (r,g,b,a)
2089 vector<int> RenderTexture::_ParseBitVector(string bitVector)
2091 vector<string> pieces;
2094 if (bitVector == "")
2096 bits.push_back(8); // if a depth isn't specified, use default 8 bits
2100 string::size_type pos = 0;
2101 string::size_type nextpos = 0;
2104 nextpos = bitVector.find_first_of(", ", pos);
2105 pieces.push_back(string(bitVector, pos, nextpos - pos));
2107 } while (nextpos != bitVector.npos );
2109 for ( vector<string>::iterator it = pieces.begin(); it != pieces.end(); it++)
2111 bits.push_back(strtol(it->c_str(), 0, 10));
2117 //---------------------------------------------------------------------------
2118 // Function : RenderTexture::_VerifyExtensions
2120 //---------------------------------------------------------------------------
2122 * @fn RenderTexture::_VerifyExtensions()
2123 * @brief Checks that the necessary extensions are available based on RT mode.
2125 bool RenderTexture::_VerifyExtensions()
2128 // a second call to _VerifyExtensions will allways return true, causing a crash
2129 // if the extension is not supported
2130 if ( true || !fctPtrInited )
2132 fctPtrInited = true;
2133 wglGetExtensionsStringARBProc wglGetExtensionsStringARBPtr = (wglGetExtensionsStringARBProc)wglGetProcAddress( "wglGetExtensionsStringARB" );
2134 if ( wglGetExtensionsStringARBPtr == 0 )
2136 PrintExtensionError("WGL_ARB_extensions_string");
2139 string wglExtensionsString = wglGetExtensionsStringARBPtr( wglGetCurrentDC() );
2140 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pixel_format" ) )
2142 wglChoosePixelFormatARBPtr = (wglChoosePixelFormatARBProc)SGLookupFunction("wglChoosePixelFormatARB");
2143 wglGetPixelFormatAttribivARBPtr = (wglGetPixelFormatAttribivARBProc)SGLookupFunction("wglGetPixelFormatAttribivARB");
2147 PrintExtensionError("WGL_ARB_pixel_format");
2150 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pbuffer" ) )
2152 wglCreatePbufferARBPtr = (wglCreatePbufferARBProc)SGLookupFunction("wglCreatePbufferARB");
2153 wglGetPbufferDCARBPtr = (wglGetPbufferDCARBProc)SGLookupFunction("wglGetPbufferDCARB");
2154 wglQueryPbufferARBPtr = (wglQueryPbufferARBProc)SGLookupFunction("wglQueryPbufferARB");
2155 wglReleasePbufferDCARBPtr = (wglReleasePbufferDCARBProc)SGLookupFunction("wglReleasePbufferDCARB");
2156 wglDestroyPbufferARBPtr = (wglDestroyPbufferARBProc)SGLookupFunction("wglDestroyPbufferARB");
2160 PrintExtensionError("WGL_ARB_pbuffer");
2163 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_render_texture" ) )
2165 wglBindTexImageARBPtr = (wglBindTexImageARBProc)SGLookupFunction("wglBindTexImageARB");
2166 wglReleaseTexImageARBPtr = (wglReleaseTexImageARBProc)SGLookupFunction("wglReleaseTexImageARB");
2168 else if ( _bIsTexture )
2170 PrintExtensionError("WGL_ARB_render_texture");
2173 if (_bRectangle && !SGIsOpenGLExtensionSupported( "GL_NV_texture_rectangle" ))
2175 PrintExtensionError("GL_NV_texture_rectangle");
2178 if (_bFloat && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) ||
2179 SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ATI_pixel_format_float" )))
2181 PrintExtensionError("GL_NV_float_buffer or GL_ATI_pixel_format_float");
2185 if (_bFloat && _bIsTexture && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) || SGIsOpenGLExtensionSupported( "GL_ATI_texture_float" )))
2187 PrintExtensionError("NV_float_buffer or ATI_texture_float");
2189 if (_bIsDepthTexture && !SGIsOpenGLExtensionSupported( "GL_ARB_depth_texture" ))
2192 #if defined(_DEBUG) | defined(DEBUG)
2193 SG_LOG(SG_GL, SG_ALERT,
2194 "RenderTexture Warning: "
2195 "OpenGL extension GL_ARB_depth_texture not available."
2196 " Using glReadPixels() to emulate behavior.");
2198 _bHasARBDepthTexture = false;
2199 //PrintExtensionError("GL_ARB_depth_texture");
2205 #elif defined( __MACH__ )
2206 // FIXME! Check extensions!
2208 Display* dpy = glXGetCurrentDisplay();
2209 int minor = 0, major = 0;
2210 if (!glXQueryVersion(dpy, &major, &minor))
2213 int screen = DefaultScreen(dpy);
2214 const char* extString = glXQueryExtensionsString(dpy, screen);
2215 if (!SGSearchExtensionsString(extString, "GLX_SGIX_fbconfig") ||
2216 !SGSearchExtensionsString(extString, "GLX_SGIX_pbuffer"))
2219 // First try the glX version 1.3 functions.
2220 glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfig");
2221 glXCreatePbufferPtr = (glXCreatePbufferProc)SGLookupFunction("glXCreatePbuffer");
2222 glXGetVisualFromFBConfigPtr = (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfig");
2223 glXCreateContextPtr = (glXCreateContextProc)SGLookupFunction("glXCreateContext");
2224 glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyPbuffer");
2225 glXQueryDrawablePtr = (glXQueryDrawableProc)SGLookupFunction("glXQueryDrawable");
2227 if (((1 <= major && 3 <= minor) || 2 <= major) &&
2228 glXChooseFBConfigPtr &&
2229 glXCreatePbufferPtr &&
2230 glXGetVisualFromFBConfigPtr &&
2231 glXCreateContextPtr &&
2232 glXDestroyPbufferPtr &&
2233 glXQueryDrawablePtr)
2234 glXVersion1_3Present = true;
2237 glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfigSGIX");
2238 glXCreateGLXPbufferPtr = (glXCreateGLXPbufferProc)SGLookupFunction("glXCreateGLXPbufferSGIX");
2239 glXGetVisualFromFBConfigPtr = (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfigSGIX");
2240 glXCreateContextWithConfigPtr = (glXCreateContextWithConfigProc)SGLookupFunction("glXCreateContextWithConfigSGIX");
2241 glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyGLXPbufferSGIX");
2242 glXQueryGLXPbufferSGIXPtr = (glXQueryGLXPbufferSGIXProc)SGLookupFunction("glXQueryGLXPbufferSGIX");
2245 if (!glXChooseFBConfigPtr ||
2246 !glXCreateGLXPbufferPtr ||
2247 !glXGetVisualFromFBConfigPtr ||
2248 !glXCreateContextWithConfigPtr ||
2249 !glXDestroyPbufferPtr ||
2250 !glXQueryGLXPbufferSGIXPtr)
2254 if (_bIsDepthTexture && !GL_ARB_depth_texture)
2256 PrintExtensionError("GL_ARB_depth_texture");
2259 if (_bFloat && _bIsTexture && !GLX_NV_float_buffer)
2261 PrintExtensionError("GLX_NV_float_buffer");
2264 if (_eUpdateMode == RT_RENDER_TO_TEXTURE)
2266 PrintExtensionError("Some GLX render texture extension: Please implement me!");
2274 //---------------------------------------------------------------------------
2275 // Function : RenderTexture::_InitializeTextures
2277 //---------------------------------------------------------------------------
2279 * @fn RenderTexture::_InitializeTextures()
2280 * @brief Initializes the state of textures used by the RenderTexture.
2282 bool RenderTexture::_InitializeTextures()
2284 // Determine the appropriate texture formats and filtering modes.
2285 if (_bIsTexture || _bIsDepthTexture)
2287 if (_bRectangle && GL_NV_texture_rectangle)
2288 _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
2289 else if (_bRectangle && GL_EXT_texture_rectangle)
2290 _iTextureTarget = GL_TEXTURE_RECTANGLE_EXT;
2292 _iTextureTarget = GL_TEXTURE_2D;
2297 glGenTextures(1, (GLuint*)&_iTextureID);
2298 glBindTexture(_iTextureTarget, _iTextureID);
2300 // Use clamp to edge as the default texture wrap mode for all tex
2301 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2302 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2303 // Use NEAREST as the default texture filtering mode.
2304 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2305 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2308 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2310 GLuint iInternalFormat;
2317 SG_LOG(SG_GL, SG_ALERT,
2318 "RenderTexture Error: mipmapped float textures not "
2323 switch(_iNumComponents)
2326 if (GL_NV_float_buffer)
2328 iInternalFormat = (_iNumColorBits[0] > 16) ?
2329 GL_FLOAT_R32_NV : GL_FLOAT_R16_NV;
2331 else if (GL_ATI_texture_float)
2333 iInternalFormat = (_iNumColorBits[0] > 16) ?
2334 GL_LUMINANCE_FLOAT32_ATI :
2335 GL_LUMINANCE_FLOAT16_ATI;
2337 iFormat = GL_LUMINANCE;
2340 if (GL_NV_float_buffer)
2342 iInternalFormat = (_iNumColorBits[0] > 16) ?
2343 GL_FLOAT_RG32_NV : GL_FLOAT_RG16_NV;
2345 else if (GL_ATI_texture_float)
2347 iInternalFormat = (_iNumColorBits[0] > 16) ?
2348 GL_LUMINANCE_ALPHA_FLOAT32_ATI :
2349 GL_LUMINANCE_ALPHA_FLOAT16_ATI;
2351 iFormat = GL_LUMINANCE_ALPHA;
2354 if (GL_NV_float_buffer)
2356 iInternalFormat = (_iNumColorBits[0] > 16) ?
2357 GL_FLOAT_RGB32_NV : GL_FLOAT_RGB16_NV;
2359 else if (GL_ATI_texture_float)
2361 iInternalFormat = (_iNumColorBits[0] > 16) ?
2362 GL_RGB_FLOAT32_ATI : GL_RGB_FLOAT16_ATI;
2367 if (GL_NV_float_buffer)
2369 iInternalFormat = (_iNumColorBits[0] > 16) ?
2370 GL_FLOAT_RGBA32_NV : GL_FLOAT_RGBA16_NV;
2372 else if (GL_ATI_texture_float)
2374 iInternalFormat = (_iNumColorBits[0] > 16) ?
2375 GL_RGBA_FLOAT32_ATI : GL_RGBA_FLOAT16_ATI;
2380 SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: "
2381 "Invalid number of components: " <<
2388 if (4 == _iNumComponents)
2390 iInternalFormat = GL_RGBA8;
2395 iInternalFormat = GL_RGB8;
2400 // Allocate the texture image (but pass it no data for now).
2401 glTexImage2D(_iTextureTarget, 0, iInternalFormat,
2402 _iWidth, _iHeight, 0, iFormat, GL_FLOAT, NULL);
2406 if (_bIsDepthTexture)
2408 glGenTextures(1, (GLuint*)&_iDepthTextureID);
2409 glBindTexture(_iTextureTarget, _iDepthTextureID);
2411 // Use clamp to edge as the default texture wrap mode for all tex
2412 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2413 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2414 // Use NEAREST as the default texture filtering mode.
2415 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2416 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2418 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2421 if (_bHasARBDepthTexture)
2423 // Allocate the texture image (but pass it no data for now).
2424 glTexImage2D(_iTextureTarget, 0, GL_DEPTH_COMPONENT,
2425 _iWidth, _iHeight, 0, GL_DEPTH_COMPONENT,
2430 // allocate memory for depth texture
2431 // Since this is slow, we warn the user in debug mode. (above)
2432 _pPoorDepthTexture = new unsigned short[_iWidth * _iHeight];
2433 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
2434 _iWidth, _iHeight, 0, GL_LUMINANCE,
2435 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2445 //---------------------------------------------------------------------------
2446 // Function : RenderTexture::_MaybeCopyBuffer
2448 //---------------------------------------------------------------------------
2450 * @fn RenderTexture::_MaybeCopyBuffer()
2451 * @brief Does the actual copying for RenderTextures with RT_COPY_TO_TEXTURE
2453 void RenderTexture::_MaybeCopyBuffer()
2456 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2460 glBindTexture(_iTextureTarget, _iTextureID);
2461 glCopyTexSubImage2D(_iTextureTarget,
2462 0, 0, 0, 0, 0, _iWidth, _iHeight);
2464 if (_bIsDepthTexture)
2466 glBindTexture(_iTextureTarget, _iDepthTextureID);
2467 // HOW TO COPY DEPTH TEXTURE??? Supposedly this just magically works...
2469 if (_bHasARBDepthTexture)
2471 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0,
2476 // no 'real' depth texture available, so behavior has to be emulated
2477 // using glReadPixels (beware, this is (naturally) slow ...)
2478 glReadPixels(0, 0, _iWidth, _iHeight, GL_DEPTH_COMPONENT,
2479 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2480 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
2481 _iWidth, _iHeight, 0, GL_LUMINANCE,
2482 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2488 #elif defined(__MACH__)
2489 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2493 glBindTexture(_iTextureTarget, _iTextureID);
2494 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2496 if (_bIsDepthTexture)
2498 glBindTexture(_iTextureTarget, _iDepthTextureID);
2499 assert(_bHasARBDepthTexture);
2500 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2506 glBindTexture(_iTextureTarget, _iTextureID);
2507 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2509 if (_bIsDepthTexture)
2511 glBindTexture(_iTextureTarget, _iDepthTextureID);
2512 assert(_bHasARBDepthTexture);
2513 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2519 //---------------------------------------------------------------------------
2520 // Function : RenderTexture::_ReleaseBoundBuffers
2522 //---------------------------------------------------------------------------
2524 * @fn RenderTexture::_ReleaseBoundBuffers()
2525 * @brief Releases buffer bindings on RenderTextures with RT_RENDER_TO_TEXTURE
2527 bool RenderTexture::_ReleaseBoundBuffers()
2530 if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2532 glBindTexture(_iTextureTarget, _iTextureID);
2534 // release the pbuffer from the render texture object
2535 if (0 != _iCurrentBoundBuffer && _bIsBufferBound)
2537 if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, _iCurrentBoundBuffer))
2542 _bIsBufferBound = false;
2546 if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2548 glBindTexture(_iTextureTarget, _iDepthTextureID);
2550 // release the pbuffer from the render texture object
2551 if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
2559 // textures can't be bound in Linux
2564 //---------------------------------------------------------------------------
2565 // Function : RenderTexture::_MakeCurrent
2567 //---------------------------------------------------------------------------
2569 * @fn RenderTexture::_MakeCurrent()
2570 * @brief Makes the RenderTexture's context current
2573 bool RenderTexture::_MakeCurrent()
2576 // make the pbuffer's rendering context current.
2577 if (FALSE == wglMakeCurrent( _hDC, _hGLContext))
2582 #elif defined( __MACH__ )
2585 if (err = CGLSetCurrentContext(_hGLContext))
2587 _cglCheckError(err);
2591 if (false == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
2600 /////////////////////////////////////////////////////////////////////////////
2602 // Begin Deprecated Interface
2604 /////////////////////////////////////////////////////////////////////////////
2606 //---------------------------------------------------------------------------
2607 // Function : RenderTexture::RenderTexture
2609 //---------------------------------------------------------------------------
2611 * @fn RenderTexture::RenderTexture()
2612 * @brief Constructor.
2614 RenderTexture::RenderTexture(int width, int height,
2615 bool bIsTexture /* = true */,
2616 bool bIsDepthTexture /* = false */)
2619 _bIsTexture(bIsTexture),
2620 _bIsDepthTexture(bIsDepthTexture),
2621 _bHasARBDepthTexture(true), // [Redge]
2622 _eUpdateMode(RT_RENDER_TO_TEXTURE),
2623 _bInitialized(false),
2625 _iCurrentBoundBuffer(0),
2627 _iNumStencilBits(0),
2629 _bDoubleBuffered(false),
2633 _bShareObjects(false),
2634 _bCopyContext(false),
2640 _hPreviousContext(0),
2641 #elif defined( __MACH__ )
2644 _hPreviousContext(NULL),
2649 _hPreviousDrawable(0),
2650 _hPreviousContext(0),
2652 _iTextureTarget(GL_NONE),
2654 _iDepthTextureID(0),
2655 _pPoorDepthTexture(0) // [Redge]
2657 assert(width > 0 && height > 0);
2658 #if defined DEBUG || defined _DEBUG
2659 SG_LOG(SG_GL, SG_ALERT,
2660 "RenderTexture Warning: Deprecated Contructor interface used.");
2663 _iNumColorBits[0] = _iNumColorBits[1] =
2664 _iNumColorBits[2] = _iNumColorBits[3] = 0;
2665 _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
2668 //------------------------------------------------------------------------------
2669 // Function : RenderTexture::Initialize
2671 //------------------------------------------------------------------------------
2673 * @fn RenderTexture::Initialize(bool bShare, bool bDepth, bool bStencil, bool bMipmap, unsigned int iRBits, unsigned int iGBits, unsigned int iBBits, unsigned int iABits);
2674 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
2676 * This function actually does the creation of the p-buffer. It can only be called
2677 * once a GL context has already been created. Note that if the texture is not
2678 * power of two dimensioned, or has more than 8 bits per channel, enabling mipmapping
2679 * will cause an error.
2681 bool RenderTexture::Initialize(bool bShare /* = true */,
2682 bool bDepth /* = false */,
2683 bool bStencil /* = false */,
2684 bool bMipmap /* = false */,
2685 bool bAnisoFilter /* = false */,
2686 unsigned int iRBits /* = 8 */,
2687 unsigned int iGBits /* = 8 */,
2688 unsigned int iBBits /* = 8 */,
2689 unsigned int iABits /* = 8 */,
2690 UpdateMode updateMode /* = RT_RENDER_TO_TEXTURE */)
2692 if (0 == _iWidth || 0 == _iHeight)
2695 #if defined DEBUG || defined _DEBUG
2696 SG_LOG(SG_GL, SG_ALERT,
2697 "RenderTexture Warning: Deprecated Initialize() interface used.");
2700 // create a mode string.
2703 mode.append("depth ");
2705 mode.append("stencil ");
2707 mode.append("mipmap ");
2708 if (iRBits + iGBits + iBBits + iABits > 0)
2719 char bitVector[100];
2720 snprintf( bitVector, 100,
2721 "%d%s,%d%s,%d%s,%d%s",
2722 iRBits, (iRBits >= 16) ? "f" : "",
2723 iGBits, (iGBits >= 16) ? "f" : "",
2724 iBBits, (iBBits >= 16) ? "f" : "",
2725 iABits, (iABits >= 16) ? "f" : "");
2726 mode.append(bitVector);
2731 if ((GL_NV_texture_rectangle || GL_EXT_texture_rectangle) &&
2732 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2733 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2734 mode.append("texRECT ");
2736 mode.append("tex2D ");
2738 if (_bIsDepthTexture)
2740 if ((GL_NV_texture_rectangle || GL_EXT_texture_rectangle) &&
2741 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2742 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2743 mode.append("texRECT ");
2745 mode.append("tex2D ");
2747 if (RT_COPY_TO_TEXTURE == updateMode)
2750 _pixelFormatAttribs.clear();
2751 _pbufferAttribs.clear();
2754 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
2755 _pixelFormatAttribs.push_back(true);
2756 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
2757 _pixelFormatAttribs.push_back(true);
2759 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
2760 _pbufferAttribs.push_back(true);
2761 #elif defined( __MACH__ )
2762 //_pixelFormatAttribs.push_back(kCGLPFANoRecovery);
2763 _pixelFormatAttribs.push_back(kCGLPFAAccelerated);
2764 _pixelFormatAttribs.push_back(kCGLPFAWindow);
2765 _pixelFormatAttribs.push_back(kCGLPFAPBuffer);
2767 _pixelFormatAttribs.push_back(GLX_RENDER_TYPE_SGIX);
2768 _pixelFormatAttribs.push_back(GLX_RGBA_BIT_SGIX);
2769 _pixelFormatAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
2770 _pixelFormatAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
2773 _ParseModeString(mode.c_str(), _pixelFormatAttribs, _pbufferAttribs);
2776 _pixelFormatAttribs.push_back(0);
2777 _pbufferAttribs.push_back(0);
2778 #elif defined(__MACH__)
2779 _pixelFormatAttribs.push_back(0);
2781 _pixelFormatAttribs.push_back(None);
2784 Initialize(_iWidth, _iHeight, bShare);
2790 //---------------------------------------------------------------------------
2791 // Function : RenderTexture::Reset
2793 //---------------------------------------------------------------------------
2795 * @fn RenderTexture::Reset(int iWidth, int iHeight, unsigned int iMode, bool bIsTexture, bool bIsDepthTexture)
2796 * @brief Resets the resolution of the offscreen buffer.
2798 * Causes the buffer to delete itself. User must call Initialize() again
2801 bool RenderTexture::Reset(int iWidth, int iHeight)
2803 SG_LOG(SG_GL, SG_ALERT,
2804 "RenderTexture Warning: Deprecated Reset() interface used.");
2808 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Reset(): failed to invalidate.");