1 //---------------------------------------------------------------------------
2 // File : RenderTexture.cpp
3 //---------------------------------------------------------------------------
4 // Copyright (c) 2002-2004 Mark J. Harris
5 //---------------------------------------------------------------------------
6 // This software is provided 'as-is', without any express or implied
7 // warranty. In no event will the authors be held liable for any
8 // damages arising from the use of this software.
10 // Permission is granted to anyone to use this software for any
11 // purpose, including commercial applications, and to alter it and
12 // redistribute it freely, subject to the following restrictions:
14 // 1. The origin of this software must not be misrepresented; you
15 // must not claim that you wrote the original software. If you use
16 // this software in a product, an acknowledgment in the product
17 // documentation would be appreciated but is not required.
19 // 2. Altered source versions must be plainly marked as such, and
20 // must not be misrepresented as being the original software.
22 // 3. This notice may not be removed or altered from any source
25 // --------------------------------------------------------------------------
27 // Original RenderTexture class: Mark J. Harris
28 // Original Render to Depth Texture support: Thorsten Scheuermann
29 // Linux Copy-to-texture: Eric Werness
30 // Various Bug Fixes: Daniel (Redge) Sperl
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
50 # include <simgear_config.h>
57 #include <simgear/compiler.h>
58 #include <simgear/debug/logstream.hxx>
59 #include <simgear/screen/extensions.hxx>
60 #include <simgear/screen/RenderTexture.h>
68 #pragma comment(lib, "gdi32.lib") // required for GetPixelFormat()
74 static bool fctPtrInited = false;
75 /* WGL_ARB_pixel_format */
76 static wglChoosePixelFormatARBProc wglChoosePixelFormatARBPtr = 0;
77 static wglGetPixelFormatAttribivARBProc wglGetPixelFormatAttribivARBPtr = 0;
79 static wglCreatePbufferARBProc wglCreatePbufferARBPtr = 0;
80 static wglGetPbufferDCARBProc wglGetPbufferDCARBPtr = 0;
81 static wglQueryPbufferARBProc wglQueryPbufferARBPtr = 0;
82 static wglReleasePbufferDCARBProc wglReleasePbufferDCARBPtr = 0;
83 static wglDestroyPbufferARBProc wglDestroyPbufferARBPtr = 0;
84 /* WGL_ARB_render_texture */
85 static wglBindTexImageARBProc wglBindTexImageARBPtr = 0;
86 static wglReleaseTexImageARBProc wglReleaseTexImageARBPtr = 0;
88 #elif defined( __APPLE__ )
90 static bool glXVersion1_3Present = false;
91 static glXChooseFBConfigProc glXChooseFBConfigPtr = 0;
92 static glXCreatePbufferProc glXCreatePbufferPtr = 0;
93 static glXCreateGLXPbufferProc glXCreateGLXPbufferPtr = 0;
94 static glXGetVisualFromFBConfigProc glXGetVisualFromFBConfigPtr = 0;
95 static glXCreateContextProc glXCreateContextPtr = 0;
96 static glXCreateContextWithConfigProc glXCreateContextWithConfigPtr = 0;
97 static glXDestroyPbufferProc glXDestroyPbufferPtr = 0;
98 static glXQueryDrawableProc glXQueryDrawablePtr = 0;
99 static glXQueryGLXPbufferSGIXProc glXQueryGLXPbufferSGIXPtr = 0;
102 //---------------------------------------------------------------------------
103 // Function : RenderTexture::RenderTexture
105 //---------------------------------------------------------------------------
107 * @fn RenderTexture::RenderTexture()
108 * @brief Mode-string-based Constructor.
110 RenderTexture::RenderTexture(const char *strMode)
114 _bIsDepthTexture(false),
115 _bHasARBDepthTexture(true), // [Redge]
117 _eUpdateMode(RT_RENDER_TO_TEXTURE),
119 _eUpdateMode(RT_COPY_TO_TEXTURE),
121 _bInitialized(false),
123 _bIsBufferBound(false),
124 _iCurrentBoundBuffer(0),
128 _bDoubleBuffered(false),
132 _bShareObjects(false),
133 _bCopyContext(false),
139 _hPreviousContext(0),
140 #elif defined( __APPLE__ )
145 _hPreviousContext(0),
146 _hPreviousDrawable(0),
148 _iTextureTarget(GL_NONE),
151 _pPoorDepthTexture(0) // [Redge]
153 _iNumColorBits[0] = _iNumColorBits[1] =
154 _iNumColorBits[2] = _iNumColorBits[3] = 0;
157 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
158 _pixelFormatAttribs.push_back(true);
159 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
160 _pixelFormatAttribs.push_back(true);
162 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
163 _pbufferAttribs.push_back(true);
164 #elif defined( __APPLE__ )
166 _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
167 _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
168 _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
169 _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
172 _ParseModeString(strMode, _pixelFormatAttribs, _pbufferAttribs);
175 _pixelFormatAttribs.push_back(0);
176 _pbufferAttribs.push_back(0);
178 _pixelFormatAttribs.push_back(None);
183 //---------------------------------------------------------------------------
184 // Function : RenderTexture::~RenderTexture
186 //---------------------------------------------------------------------------
188 * @fn RenderTexture::~RenderTexture()
191 RenderTexture::~RenderTexture()
197 //---------------------------------------------------------------------------
198 // Function : _wglGetLastError
200 //---------------------------------------------------------------------------
202 * @fn wglGetLastError()
203 * @brief Returns the last windows error generated.
206 void _wglGetLastError()
210 DWORD err = GetLastError();
213 case ERROR_INVALID_PIXEL_FORMAT:
214 SG_LOG(SG_GL, SG_ALERT,
215 "RenderTexture Win32 Error: ERROR_INVALID_PIXEL_FORMAT");
217 case ERROR_NO_SYSTEM_RESOURCES:
218 SG_LOG(SG_GL, SG_ALERT,
219 "RenderTexture Win32 Error: ERROR_NO_SYSTEM_RESOURCES");
221 case ERROR_INVALID_DATA:
222 SG_LOG(SG_GL, SG_ALERT,
223 "RenderTexture Win32 Error: ERROR_INVALID_DATA");
225 case ERROR_INVALID_WINDOW_HANDLE:
226 SG_LOG(SG_GL, SG_ALERT,
227 "RenderTexture Win32 Error: ERROR_INVALID_WINDOW_HANDLE");
229 case ERROR_RESOURCE_TYPE_NOT_FOUND:
230 SG_LOG(SG_GL, SG_ALERT,
231 "RenderTexture Win32 Error: ERROR_RESOURCE_TYPE_NOT_FOUND");
238 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
239 FORMAT_MESSAGE_FROM_SYSTEM |
240 FORMAT_MESSAGE_IGNORE_INSERTS,
243 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
248 SG_LOG(SG_GL, SG_ALERT, "RenderTexture Win32 Error %d: %s", err, lpMsgBuf);
249 LocalFree( lpMsgBuf );
258 //---------------------------------------------------------------------------
259 // Function : PrintExtensionError
261 //---------------------------------------------------------------------------
263 * @fn PrintExtensionError( char* strMsg, ... )
264 * @brief Prints an error about missing OpenGL extensions.
266 void PrintExtensionError( char* strMsg, ... )
268 SG_LOG(SG_GL, SG_ALERT,
269 "Error: RenderTexture requires the following unsupported "
270 "OpenGL extensions: ");
273 va_start(args, strMsg);
274 #if defined _WIN32 && !defined __CYGWIN__
275 _vsnprintf( strBuffer, 512, strMsg, args );
277 vsnprintf( strBuffer, 512, strMsg, args );
281 SG_LOG(SG_GL, SG_ALERT, strMsg);
285 //---------------------------------------------------------------------------
286 // Function : RenderTexture::Initialize
288 //---------------------------------------------------------------------------
290 * @fn RenderTexture::Initialize(int width, int height, bool shareObjects, bool copyContext);
291 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
293 * This function creates of the p-buffer. It can only be called once a GL
294 * context has already been created.
296 bool RenderTexture::Initialize(int width, int height,
297 bool shareObjects /* = true */,
298 bool copyContext /* = false */)
300 assert(width > 0 && height > 0);
302 _iWidth = width; _iHeight = height;
303 _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
305 _bShareObjects = shareObjects;
306 _bCopyContext = copyContext;
308 // Check if this is an NVXX GPU and verify necessary extensions.
309 if (!_VerifyExtensions())
316 // Get the current context.
317 HDC hdc = wglGetCurrentDC();
320 HGLRC hglrc = wglGetCurrentContext();
325 unsigned int iNumFormats;
329 // Get the pixel format for the on-screen window.
330 iFormat = GetPixelFormat(hdc);
333 SG_LOG(SG_GL, SG_ALERT,
334 "RenderTexture Error: GetPixelFormat() failed.");
340 if (!wglChoosePixelFormatARBPtr(hdc, &_pixelFormatAttribs[0], NULL,
341 1, &iFormat, &iNumFormats))
343 SG_LOG(SG_GL, SG_ALERT,
344 "RenderTexture Error: wglChoosePixelFormatARB() failed.");
348 if ( iNumFormats <= 0 )
350 SG_LOG(SG_GL, SG_ALERT,
351 "RenderTexture Error: Couldn't find a suitable "
358 // Create the p-buffer.
359 _hPBuffer = wglCreatePbufferARBPtr(hdc, iFormat, _iWidth, _iHeight,
360 &_pbufferAttribs[0]);
363 SG_LOG(SG_GL, SG_ALERT,
364 "RenderTexture Error: wglCreatePbufferARB() failed.");
369 // Get the device context.
370 _hDC = wglGetPbufferDCARBPtr( _hPBuffer);
373 SG_LOG(SG_GL, SG_ALERT,
374 "RenderTexture Error: wglGetGetPbufferDCARB() failed.");
379 // Create a gl context for the p-buffer.
382 // Let's use the same gl context..
383 // Since the device contexts are compatible (i.e. same pixelformat),
384 // we should be able to use the same gl rendering context.
389 _hGLContext = wglCreateContext( _hDC );
392 SG_LOG(SG_GL, SG_ALERT,
393 "RenderTexture Error: wglCreateContext() failed.");
399 // Share lists, texture objects, and program objects.
402 if( !wglShareLists(hglrc, _hGLContext) )
404 SG_LOG(SG_GL, SG_ALERT,
405 "RenderTexture Error: wglShareLists() failed.");
411 // Determine the actual width and height we were able to create.
412 wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
413 wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
415 _bInitialized = true;
417 // get the actual number of bits allocated:
418 int attrib = WGL_RED_BITS_ARB;
422 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
424 attrib = WGL_GREEN_BITS_ARB;
426 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
428 attrib = WGL_BLUE_BITS_ARB;
430 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
432 attrib = WGL_ALPHA_BITS_ARB;
434 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
436 attrib = WGL_DEPTH_BITS_ARB;
438 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
440 attrib = WGL_STENCIL_BITS_ARB;
442 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
444 attrib = WGL_DOUBLE_BUFFER_ARB;
446 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
447 ? (value?true:false) : false;
449 #if defined(_DEBUG) | defined(DEBUG)
450 SG_LOG(SG_GL, SG_ALERT, "Created a %dx%d RenderTexture with BPP(%d, %d, %d, %d)",
452 _iNumColorBits[0], _iNumColorBits[1],
453 _iNumColorBits[2], _iNumColorBits[3]);
454 if (_iNumDepthBits) SG_LOG(SG_GL, SG_ALERT, " depth=%d", _iNumDepthBits);
455 if (_iNumStencilBits) SG_LOG(SG_GL, SG_ALERT, " stencil=%d", _iNumStencilBits);
456 if (_bDoubleBuffered) SG_LOG(SG_GL, SG_ALERT, " double buffered");
457 SG_LOG(SG_GL, SG_ALERT, "");
460 #elif defined( __APPLE__ )
462 _pDisplay = glXGetCurrentDisplay();
463 GLXContext context = glXGetCurrentContext();
464 int screen = DefaultScreen(_pDisplay);
465 XVisualInfo *visInfo;
467 GLXFBConfig *fbConfigs;
470 fbConfigs = glXChooseFBConfigPtr(_pDisplay, screen,
471 &_pixelFormatAttribs[0], &nConfigs);
473 if (nConfigs == 0 || !fbConfigs)
475 SG_LOG(SG_GL, SG_ALERT,
476 "RenderTexture Error: Couldn't find a suitable pixel format.");
480 // Pick the first returned format that will return a pbuffer
481 if (glXVersion1_3Present)
484 GLX_PBUFFER_WIDTH, _iWidth,
485 GLX_PBUFFER_HEIGHT, _iHeight,
486 GLX_LARGEST_PBUFFER, False,
489 for (int i=0;i<nConfigs;i++)
491 _hPBuffer = glXCreatePbufferPtr(_pDisplay, fbConfigs[i], pbufAttrib);
494 XVisualInfo *visInfo = glXGetVisualFromFBConfigPtr(_pDisplay, fbConfigs[i]);
496 _hGLContext = glXCreateContextPtr(_pDisplay, visInfo,
497 _bShareObjects ? context : NULL,
513 for (int i=0;i<nConfigs;i++)
515 _hPBuffer = glXCreateGLXPbufferPtr(_pDisplay, fbConfigs[i],
516 _iWidth, _iHeight, NULL);
519 _hGLContext = glXCreateContextWithConfigPtr(_pDisplay,
522 _bShareObjects ? context : NULL,
532 SG_LOG(SG_GL, SG_ALERT,
533 "RenderTexture Error: glXCreateGLXPbufferPtr() failed.");
540 _hGLContext = glXCreateContext(_pDisplay, visInfo,
541 _bShareObjects ? context : NULL, False);
544 SG_LOG(SG_GL, SG_ALERT,
545 "RenderTexture Error: glXCreateContext() failed.");
550 if (!glXVersion1_3Present)
552 glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_WIDTH_SGIX,
554 glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_HEIGHT_SGIX,
558 _bInitialized = true;
560 // XXX Query the color format
565 // Now that the pbuffer is created, allocate any texture objects needed,
566 // and initialize them (for CTT updates only). These must be allocated
567 // in the context of the pbuffer, though, or the RT won't work without
570 if (false == wglMakeCurrent( _hDC, _hGLContext))
575 #elif defined( __APPLE__ )
577 _hPreviousContext = glXGetCurrentContext();
578 _hPreviousDrawable = glXGetCurrentDrawable();
580 if (False == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
586 bool result = _InitializeTextures();
588 BindBuffer(WGL_FRONT_LEFT_ARB);
594 // make the previous rendering context current
595 if (false == wglMakeCurrent( hdc, hglrc))
600 #elif defined( __APPLE__ )
602 if (False == glXMakeCurrent(_pDisplay,
603 _hPreviousDrawable, _hPreviousContext))
607 if (glXVersion1_3Present)
609 GLXDrawable draw = glXGetCurrentDrawable();
610 glXQueryDrawablePtr(_pDisplay, draw, GLX_WIDTH, (unsigned int*)&_iWidth);
611 glXQueryDrawablePtr(_pDisplay, draw, GLX_HEIGHT, (unsigned int*)&_iHeight);
619 //---------------------------------------------------------------------------
620 // Function : RenderTexture::_Invalidate
622 //---------------------------------------------------------------------------
624 * @fn RenderTexture::_Invalidate()
625 * @brief Returns the pbuffer memory to the graphics device.
628 bool RenderTexture::_Invalidate()
630 _iNumColorBits[0] = _iNumColorBits[1] =
631 _iNumColorBits[2] = _iNumColorBits[3] = 0;
633 _iNumStencilBits = 0;
636 glDeleteTextures(1, &_iTextureID);
637 if (_bIsDepthTexture)
640 if (!_bHasARBDepthTexture) delete[] _pPoorDepthTexture;
642 glDeleteTextures(1, &_iDepthTextureID);
648 // Check if we are currently rendering in the pbuffer
649 if (wglGetCurrentContext() == _hGLContext)
652 wglDeleteContext( _hGLContext);
653 wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
654 wglDestroyPbufferARBPtr( _hPBuffer );
658 #elif defined( __APPLE__ )
662 if(glXGetCurrentContext() == _hGLContext)
663 // XXX I don't know if this is right at all
664 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
665 glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
671 // [WVB] do we need to call _ReleaseBoundBuffers() too?
676 //---------------------------------------------------------------------------
677 // Function : RenderTexture::Reset
679 //---------------------------------------------------------------------------
681 * @fn RenderTexture::Reset()
682 * @brief Resets the resolution of the offscreen buffer.
684 * Causes the buffer to delete itself. User must call Initialize() again
687 bool RenderTexture::Reset(const char *strMode, ...)
689 _iWidth = 0; _iHeight = 0;
690 _bIsTexture = false; _bIsDepthTexture = false,
691 _bHasARBDepthTexture = true;
693 _eUpdateMode = RT_RENDER_TO_TEXTURE;
695 _eUpdateMode = RT_COPY_TO_TEXTURE;
697 _bInitialized = false;
699 _bIsBufferBound = false;
700 _iCurrentBoundBuffer = 0;
701 _iNumDepthBits = 0; _iNumStencilBits = 0;
702 _bDoubleBuffered = false;
703 _bFloat = false; _bPowerOf2 = true;
704 _bRectangle = false; _bMipmap = false;
705 _bShareObjects = false; _bCopyContext = false;
706 _iTextureTarget = GL_NONE; _iTextureID = 0;
707 _iDepthTextureID = 0;
708 _pPoorDepthTexture = 0;
709 _pixelFormatAttribs.clear();
710 _pbufferAttribs.clear();
712 if (IsInitialized() && !_Invalidate())
714 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Reset(): failed to invalidate.");
718 _iNumColorBits[0] = _iNumColorBits[1] =
719 _iNumColorBits[2] = _iNumColorBits[3] = 0;
722 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
723 _pixelFormatAttribs.push_back(true);
724 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
725 _pixelFormatAttribs.push_back(true);
727 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
728 _pbufferAttribs.push_back(true);
729 #elif defined( __APPLE__ )
731 _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
732 _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
733 _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
734 _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
739 va_start(args,strMode);
740 #if defined _WIN32 && !defined __CYGWIN__
741 _vsnprintf( strBuffer, 256, strMode, args );
743 vsnprintf( strBuffer, 256, strMode, args );
747 _ParseModeString(strBuffer, _pixelFormatAttribs, _pbufferAttribs);
750 _pixelFormatAttribs.push_back(0);
751 _pbufferAttribs.push_back(0);
753 _pixelFormatAttribs.push_back(None);
758 //------------------------------------------------------------------------------
759 // Function : RenderTexture::Resize
761 //------------------------------------------------------------------------------
763 * @fn RenderTexture::Resize(int iWidth, int iHeight)
764 * @brief Changes the size of the offscreen buffer.
766 * Like Reset() this causes the buffer to delete itself.
767 * But unlike Reset(), this call re-initializes the RenderTexture.
768 * Note that Resize() will not work after calling Reset(), or before
769 * calling Initialize() the first time.
771 bool RenderTexture::Resize(int iWidth, int iHeight)
773 if (!_bInitialized) {
774 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): must Initialize() first.");
777 if (iWidth == _iWidth && iHeight == _iHeight) {
781 // Do same basic work as _Invalidate, but don't reset all our flags
783 glDeleteTextures(1, &_iTextureID);
784 if (_bIsDepthTexture)
785 glDeleteTextures(1, &_iDepthTextureID);
789 // Check if we are currently rendering in the pbuffer
790 if (wglGetCurrentContext() == _hGLContext)
793 wglDeleteContext( _hGLContext);
794 wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
795 wglDestroyPbufferARBPtr( _hPBuffer );
799 #elif defined( __APPLE__ )
803 if(glXGetCurrentContext() == _hGLContext)
804 // XXX I don't know if this is right at all
805 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
806 glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
811 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): failed to resize.");
814 _bInitialized = false;
815 return Initialize(iWidth, iHeight, _bShareObjects, _bCopyContext);
818 //---------------------------------------------------------------------------
819 // Function : RenderTexture::BeginCapture
821 //---------------------------------------------------------------------------
823 * @fn RenderTexture::BeginCapture()
824 * @brief Activates rendering to the RenderTexture.
826 bool RenderTexture::BeginCapture()
830 SG_LOG(SG_GL, SG_ALERT,
831 "RenderTexture::BeginCapture(): Texture is not initialized!");
835 // cache the current context so we can reset it when EndCapture() is called.
836 _hPreviousDC = wglGetCurrentDC();
837 if (NULL == _hPreviousDC)
839 _hPreviousContext = wglGetCurrentContext();
840 if (NULL == _hPreviousContext)
842 #elif defined( __APPLE__ )
844 _hPreviousContext = glXGetCurrentContext();
845 _hPreviousDrawable = glXGetCurrentDrawable();
848 _ReleaseBoundBuffers();
850 return _MakeCurrent();
854 //---------------------------------------------------------------------------
855 // Function : RenderTexture::EndCapture
857 //---------------------------------------------------------------------------
859 * @fn RenderTexture::EndCapture()
860 * @brief Ends rendering to the RenderTexture.
862 bool RenderTexture::EndCapture()
866 SG_LOG(SG_GL, SG_ALERT,
867 "RenderTexture::EndCapture() : Texture is not initialized!");
874 // make the previous rendering context current
875 if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
880 #elif defined( __APPLE__ )
882 if (False == glXMakeCurrent(_pDisplay, _hPreviousDrawable,
889 // rebind the textures to a buffers for RTT
890 BindBuffer(_iCurrentBoundBuffer);
896 //---------------------------------------------------------------------------
897 // Function : RenderTexture::BeginCapture(RenderTexture*)
899 //---------------------------------------------------------------------------
901 * @fn RenderTexture::BeginCapture(RenderTexture* other)
902 * @brief Ends capture of 'other', begins capture on 'this'
904 * When performing a series of operations where you modify one texture after
905 * another, it is more efficient to use this method instead of the equivalent
906 * 'EndCapture'/'BeginCapture' pair. This method switches directly to the
907 * new context rather than changing to the default context, and then to the
910 * RenderTexture doesn't have any mechanism for determining if
911 * 'current' really is currently active, so no error will be thrown
914 bool RenderTexture::BeginCapture(RenderTexture* current)
916 bool bContextReset = false;
918 if (current == this) {
919 return true; // no switch necessary
922 // treat as normal Begin if current is 0.
923 return BeginCapture();
927 SG_LOG(SG_GL, SG_ALERT,
928 "RenderTexture::BeginCapture(RenderTexture*): Texture is not initialized!");
931 if (!current->_bInitialized)
933 SG_LOG(SG_GL, SG_ALERT,
934 "RenderTexture::BeginCapture(RenderTexture): 'current' texture is not initialized!");
938 // Sync current pbuffer with its CTT texture if necessary
939 current->_MaybeCopyBuffer();
941 // pass along the previous context so we can reset it when
942 // EndCapture() is called.
944 _hPreviousDC = current->_hPreviousDC;
945 if (NULL == _hPreviousDC)
947 _hPreviousContext = current->_hPreviousContext;
948 if (NULL == _hPreviousContext)
950 #elif defined( __APPLE__ )
952 _hPreviousContext = current->_hPreviousContext;
953 _hPreviousDrawable = current->_hPreviousDrawable;
956 // Unbind textures before making context current
957 if (!_ReleaseBoundBuffers())
960 // Make the pbuffer context current
964 // Rebind buffers of initial RenderTexture
965 current->BindBuffer(_iCurrentBoundBuffer);
966 current->_BindDepthBuffer();
973 //---------------------------------------------------------------------------
974 // Function : RenderTexture::Bind
976 //---------------------------------------------------------------------------
978 * @fn RenderTexture::Bind()
979 * @brief Binds RGB texture.
981 void RenderTexture::Bind() const
983 if (_bInitialized && _bIsTexture)
985 glBindTexture(_iTextureTarget, _iTextureID);
990 //---------------------------------------------------------------------------
991 // Function : RenderTexture::BindDepth
993 //---------------------------------------------------------------------------
995 * @fn RenderTexture::BindDepth()
996 * @brief Binds depth texture.
998 void RenderTexture::BindDepth() const
1000 if (_bInitialized && _bIsDepthTexture)
1002 glBindTexture(_iTextureTarget, _iDepthTextureID);
1007 //---------------------------------------------------------------------------
1008 // Function : RenderTexture::BindBuffer
1010 //---------------------------------------------------------------------------
1012 * @fn RenderTexture::BindBuffer()
1013 * @brief Associate the RTT texture id with 'iBuffer' (e.g. WGL_FRONT_LEFT_ARB)
1015 bool RenderTexture::BindBuffer( int iBuffer )
1017 // Must bind the texture too
1018 if (_bInitialized && _bIsTexture)
1020 glBindTexture(_iTextureTarget, _iTextureID);
1023 if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
1024 (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
1026 if (FALSE == wglBindTexImageARBPtr(_hPBuffer, iBuffer))
1028 // WVB: WGL API considers binding twice to the same buffer
1029 // to be an error. But we don't want to
1030 //_wglGetLastError();
1034 _bIsBufferBound = true;
1035 _iCurrentBoundBuffer = iBuffer;
1043 //---------------------------------------------------------------------------
1044 // Function : RenderTexture::BindBuffer
1046 //---------------------------------------------------------------------------
1048 * @fn RenderTexture::_BindDepthBuffer()
1049 * @brief Associate the RTT depth texture id with the depth buffer
1051 bool RenderTexture::_BindDepthBuffer() const
1054 if (_bInitialized && _bIsDepthTexture &&
1055 RT_RENDER_TO_TEXTURE == _eUpdateMode)
1057 glBindTexture(_iTextureTarget, _iDepthTextureID);
1058 if (FALSE == wglBindTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1068 //---------------------------------------------------------------------------
1069 // Function : RenderTexture::_ParseModeString
1071 //---------------------------------------------------------------------------
1073 * @fn RenderTexture::_ParseModeString()
1074 * @brief Parses the user-specified mode string for RenderTexture parameters.
1076 void RenderTexture::_ParseModeString(const char *modeString,
1077 vector<int> &pfAttribs,
1078 vector<int> &pbAttribs)
1080 if (!modeString || strcmp(modeString, "") == 0)
1083 _iNumComponents = 0;
1085 _eUpdateMode = RT_RENDER_TO_TEXTURE;
1087 _eUpdateMode = RT_COPY_TO_TEXTURE;
1091 bool bHasStencil = false;
1092 bool bBind2D = false;
1093 bool bBindRECT = false;
1094 bool bBindCUBE = false;
1096 char *mode = strdup(modeString);
1099 vector<string> tokens;
1100 char *buf = strtok(mode, " ");
1103 tokens.push_back(buf);
1104 buf = strtok(NULL, " ");
1107 for (unsigned int i = 0; i < tokens.size(); i++)
1109 string token = tokens[i];
1111 KeyVal kv = _GetKeyValuePair(token);
1114 if (kv.first == "rgb" && (_iNumComponents <= 1))
1116 if (kv.second.find("f") != kv.second.npos)
1119 vector<int> bitVec = _ParseBitVector(kv.second);
1121 if (bitVec.size() < 3) // expand the scalar to a vector
1123 bitVec.push_back(bitVec[0]);
1124 bitVec.push_back(bitVec[0]);
1128 pfAttribs.push_back(WGL_RED_BITS_ARB);
1129 pfAttribs.push_back(bitVec[0]);
1130 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1131 pfAttribs.push_back(bitVec[1]);
1132 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1133 pfAttribs.push_back(bitVec[2]);
1134 #elif defined( __APPLE__ )
1135 pfAttribs.push_back(AGL_RED_SIZE);
1136 pfAttribs.push_back(bitVec[0]);
1137 pfAttribs.push_back(AGL_GREEN_SIZE);
1138 pfAttribs.push_back(bitVec[1]);
1139 pfAttribs.push_back(AGL_BLUE_SIZE);
1140 pfAttribs.push_back(bitVec[2]);
1142 pfAttribs.push_back(GLX_RED_SIZE);
1143 pfAttribs.push_back(bitVec[0]);
1144 pfAttribs.push_back(GLX_GREEN_SIZE);
1145 pfAttribs.push_back(bitVec[1]);
1146 pfAttribs.push_back(GLX_BLUE_SIZE);
1147 pfAttribs.push_back(bitVec[2]);
1149 _iNumComponents += 3;
1152 else if (kv.first == "rgb")
1153 SG_LOG(SG_GL, SG_ALERT,
1154 "RenderTexture Warning: mistake in components definition "
1155 "(rgb + " << _iNumComponents << ").");
1157 if (kv.first == "rgba" && (_iNumComponents == 0))
1159 if (kv.second.find("f") != kv.second.npos)
1162 vector<int> bitVec = _ParseBitVector(kv.second);
1164 if (bitVec.size() < 4) // expand the scalar to a vector
1166 bitVec.push_back(bitVec[0]);
1167 bitVec.push_back(bitVec[0]);
1168 bitVec.push_back(bitVec[0]);
1172 pfAttribs.push_back(WGL_RED_BITS_ARB);
1173 pfAttribs.push_back(bitVec[0]);
1174 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1175 pfAttribs.push_back(bitVec[1]);
1176 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1177 pfAttribs.push_back(bitVec[2]);
1178 pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1179 pfAttribs.push_back(bitVec[3]);
1180 #elif defined( __APPLE__ )
1181 pfAttribs.push_back(AGL_RED_SIZE);
1182 pfAttribs.push_back(bitVec[0]);
1183 pfAttribs.push_back(AGL_GREEN_SIZE);
1184 pfAttribs.push_back(bitVec[1]);
1185 pfAttribs.push_back(AGL_BLUE_SIZE);
1186 pfAttribs.push_back(bitVec[2]);
1187 pfAttribs.push_back(AGL_ALPHA_SIZE);
1188 pfAttribs.push_back(bitVec[3]);
1190 pfAttribs.push_back(GLX_RED_SIZE);
1191 pfAttribs.push_back(bitVec[0]);
1192 pfAttribs.push_back(GLX_GREEN_SIZE);
1193 pfAttribs.push_back(bitVec[1]);
1194 pfAttribs.push_back(GLX_BLUE_SIZE);
1195 pfAttribs.push_back(bitVec[2]);
1196 pfAttribs.push_back(GLX_ALPHA_SIZE);
1197 pfAttribs.push_back(bitVec[3]);
1199 _iNumComponents = 4;
1202 else if (kv.first == "rgba")
1203 SG_LOG(SG_GL, SG_ALERT,
1204 "RenderTexture Warning: mistake in components definition "
1205 "(rgba + " << _iNumComponents << ").");
1207 if (kv.first == "r" && (_iNumComponents <= 1))
1209 if (kv.second.find("f") != kv.second.npos)
1212 vector<int> bitVec = _ParseBitVector(kv.second);
1215 pfAttribs.push_back(WGL_RED_BITS_ARB);
1216 pfAttribs.push_back(bitVec[0]);
1217 #elif defined( __APPLE__ )
1218 pfAttribs.push_back(AGL_RED_SIZE);
1219 pfAttribs.push_back(bitVec[0]);
1221 pfAttribs.push_back(GLX_RED_SIZE);
1222 pfAttribs.push_back(bitVec[0]);
1227 else if (kv.first == "r")
1228 SG_LOG(SG_GL, SG_ALERT,
1229 "RenderTexture Warning: mistake in components definition "
1230 "(r + " << _iNumComponents << ").");
1232 if (kv.first == "rg" && (_iNumComponents <= 1))
1234 if (kv.second.find("f") != kv.second.npos)
1237 vector<int> bitVec = _ParseBitVector(kv.second);
1239 if (bitVec.size() < 2) // expand the scalar to a vector
1241 bitVec.push_back(bitVec[0]);
1245 pfAttribs.push_back(WGL_RED_BITS_ARB);
1246 pfAttribs.push_back(bitVec[0]);
1247 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1248 pfAttribs.push_back(bitVec[1]);
1249 #elif defined( __APPLE__ )
1250 pfAttribs.push_back(AGL_RED_SIZE);
1251 pfAttribs.push_back(bitVec[0]);
1252 pfAttribs.push_back(AGL_GREEN_SIZE);
1253 pfAttribs.push_back(bitVec[1]);
1255 pfAttribs.push_back(GLX_RED_SIZE);
1256 pfAttribs.push_back(bitVec[0]);
1257 pfAttribs.push_back(GLX_GREEN_SIZE);
1258 pfAttribs.push_back(bitVec[1]);
1260 _iNumComponents += 2;
1263 else if (kv.first == "rg")
1264 SG_LOG(SG_GL, SG_ALERT,
1265 "RenderTexture Warning: mistake in components definition "
1266 "(rg + " << _iNumComponents << ").");
1268 if (kv.first == "depth")
1270 if (kv.second == "")
1273 iDepthBits = strtol(kv.second.c_str(), 0, 10);
1277 if (kv.first == "stencil")
1281 pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1282 #elif defined( __APPLE__ )
1283 pfAttribs.push_back(AGL_STENCIL_SIZE);
1285 pfAttribs.push_back(GLX_STENCIL_SIZE);
1287 if (kv.second == "")
1288 pfAttribs.push_back(8);
1290 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1294 if (kv.first == "samples")
1297 pfAttribs.push_back(WGL_SAMPLE_BUFFERS_ARB);
1298 pfAttribs.push_back(1);
1299 pfAttribs.push_back(WGL_SAMPLES_ARB);
1300 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1301 #elif defined( __APPLE__ )
1302 pfAttribs.push_back(AGL_SAMPLE_BUFFERS_ARB);
1303 pfAttribs.push_back(1);
1304 pfAttribs.push_back(AGL_SAMPLES_ARB);
1305 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1307 pfAttribs.push_back(GLX_SAMPLE_BUFFERS_ARB);
1308 pfAttribs.push_back(1);
1309 pfAttribs.push_back(GLX_SAMPLES_ARB);
1310 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1316 if (kv.first == "doublebuffer" || kv.first == "double")
1319 pfAttribs.push_back(WGL_DOUBLE_BUFFER_ARB);
1320 pfAttribs.push_back(true);
1321 #elif defined( __APPLE__ )
1322 pfAttribs.push_back(AGL_DOUBLEBUFFER);
1323 pfAttribs.push_back(True);
1325 pfAttribs.push_back(GLX_DOUBLEBUFFER);
1326 pfAttribs.push_back(True);
1331 if (kv.first == "aux")
1334 pfAttribs.push_back(WGL_AUX_BUFFERS_ARB);
1335 #elif defined( __APPLE__ )
1336 pfAttribs.push_back(AGL_AUX_BUFFERS);
1338 pfAttribs.push_back(GLX_AUX_BUFFERS);
1340 if (kv.second == "")
1341 pfAttribs.push_back(0);
1343 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1347 if (token.find("tex") == 0)
1351 if ((kv.first == "texRECT") && GL_NV_texture_rectangle)
1356 else if (kv.first == "texCUBE")
1368 if (token.find("depthTex") == 0)
1370 _bIsDepthTexture = true;
1372 if ((kv.first == "depthTexRECT") && GL_NV_texture_rectangle)
1377 else if (kv.first == "depthTexCUBE")
1389 if (kv.first == "mipmap")
1395 if (kv.first == "rtt")
1397 _eUpdateMode = RT_RENDER_TO_TEXTURE;
1401 if (kv.first == "ctt")
1403 _eUpdateMode = RT_COPY_TO_TEXTURE;
1407 SG_LOG(SG_GL, SG_ALERT,
1408 "RenderTexture Error: Unknown pbuffer attribute: " <<
1412 // Processing of some options must be last because of interactions.
1414 // Check for inconsistent texture targets
1415 if (_bIsTexture && _bIsDepthTexture && !(bBind2D ^ bBindRECT ^ bBindCUBE))
1417 SG_LOG(SG_GL, SG_ALERT,
1418 "RenderTexture Warning: Depth and Color texture targets "
1422 // Apply default bit format if none specified
1424 if (0 == _iNumComponents)
1426 pfAttribs.push_back(WGL_RED_BITS_ARB);
1427 pfAttribs.push_back(8);
1428 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1429 pfAttribs.push_back(8);
1430 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1431 pfAttribs.push_back(8);
1432 pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1433 pfAttribs.push_back(8);
1434 _iNumComponents = 4;
1439 if (_bIsDepthTexture && !iDepthBits)
1443 pfAttribs.push_back(WGL_DEPTH_BITS_ARB);
1444 #elif defined( __APPLE__ )
1445 pfAttribs.push_back(AGL_DEPTH_SIZE);
1447 pfAttribs.push_back(GLX_DEPTH_SIZE);
1449 pfAttribs.push_back(iDepthBits); // default
1454 pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1455 pfAttribs.push_back(0);
1456 #elif defined( __APPLE__ )
1457 pfAttribs.push_back(AGL_STENCIL_SIZE);
1458 pfAttribs.push_back(0);
1460 pfAttribs.push_back(GLX_STENCIL_SIZE);
1461 pfAttribs.push_back(0);
1465 if (_iNumComponents < 4)
1467 // Can't do this right now -- on NVIDIA drivers, currently get
1468 // a non-functioning pbuffer if ALPHA_BITS=0 and
1469 // WGL_BIND_TO_TEXTURE_RGB_ARB=true
1471 //pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1472 //pfAttribs.push_back(0);
1476 if (!WGL_NV_render_depth_texture && _bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1478 #if defined(DEBUG) || defined(_DEBUG)
1479 SG_LOG(SG_GL, SG_ALERT, "RenderTexture Warning: No support found for "
1480 "render to depth texture.");
1482 _bIsDepthTexture = false;
1486 if ((_bIsTexture || _bIsDepthTexture) &&
1487 (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1492 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1493 pbAttribs.push_back(WGL_TEXTURE_RECTANGLE_NV);
1497 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1498 pbAttribs.push_back(WGL_TEXTURE_CUBE_MAP_ARB);
1502 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1503 pbAttribs.push_back(WGL_TEXTURE_2D_ARB);
1508 pbAttribs.push_back(WGL_MIPMAP_TEXTURE_ARB);
1509 pbAttribs.push_back(true);
1512 #elif defined(DEBUG) || defined(_DEBUG)
1513 SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: Render to Texture not "
1514 "supported in Linux or MacOS");
1518 // Set the pixel type
1522 if (WGL_NV_float_buffer)
1524 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1525 pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1527 pfAttribs.push_back(WGL_FLOAT_COMPONENTS_NV);
1528 pfAttribs.push_back(true);
1532 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1533 pfAttribs.push_back(WGL_TYPE_RGBA_FLOAT_ATI);
1535 #elif defined( __APPLE__ )
1537 if (GLX_NV_float_buffer)
1539 pfAttribs.push_back(GLX_FLOAT_COMPONENTS_NV);
1540 pfAttribs.push_back(1);
1547 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1548 pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1552 // Set up texture binding for render to texture
1553 if (_bIsTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1559 if (WGL_NV_float_buffer)
1561 switch(_iNumComponents)
1564 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
1565 pfAttribs.push_back(true);
1567 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1568 pbAttribs.push_back(WGL_TEXTURE_FLOAT_R_NV);
1571 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
1572 pfAttribs.push_back(true);
1574 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1575 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RG_NV);
1578 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
1579 pfAttribs.push_back(true);
1581 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1582 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGB_NV);
1585 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
1586 pfAttribs.push_back(true);
1588 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1589 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGBA_NV);
1592 SG_LOG(SG_GL, SG_ALERT,
1593 "RenderTexture Warning: Bad number of components "
1594 "(r=1,rg=2,rgb=3,rgba=4): %d.",
1601 if (4 == _iNumComponents)
1603 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1604 pfAttribs.push_back(true);
1606 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1607 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1611 // standard ARB_render_texture only supports 3 or 4 channels
1612 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1613 pfAttribs.push_back(true);
1615 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1616 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1623 switch(_iNumComponents)
1626 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1627 pfAttribs.push_back(true);
1629 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1630 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1633 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1634 pfAttribs.push_back(true);
1636 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1637 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1640 SG_LOG(SG_GL, SG_ALERT,
1641 "RenderTexture Warning: Bad number of components "
1642 "(r=1,rg=2,rgb=3,rgba=4): %d.", _iNumComponents);
1646 #elif defined(DEBUG) || defined(_DEBUG)
1647 SG_LOG(SG_GL, SG_ALERT,
1648 "RenderTexture Error: Render to Texture not supported in "
1649 "Linux or MacOS\ n");
1653 if (_bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1658 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV);
1659 pfAttribs.push_back(true);
1661 pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
1662 pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
1666 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_DEPTH_NV);
1667 pfAttribs.push_back(true);
1669 pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
1670 pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
1672 #elif defined(DEBUG) || defined(_DEBUG)
1673 SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: Render to Texture not supported in "
1679 //---------------------------------------------------------------------------
1680 // Function : RenderTexture::_GetKeyValuePair
1682 //---------------------------------------------------------------------------
1684 * @fn RenderTexture::_GetKeyValuePair()
1685 * @brief Parses expressions of the form "X=Y" into a pair (X,Y).
1687 RenderTexture::KeyVal RenderTexture::_GetKeyValuePair(string token)
1689 string::size_type pos = 0;
1690 if ((pos = token.find("=")) != token.npos)
1692 string key = token.substr(0, pos);
1693 string value = token.substr(pos+1, token.length()-pos+1);
1694 return KeyVal(key, value);
1697 return KeyVal(token, "");
1700 //---------------------------------------------------------------------------
1701 // Function : RenderTexture::_ParseBitVector
1703 //---------------------------------------------------------------------------
1705 * @fn RenderTexture::_ParseBitVector()
1706 * @brief Parses expressions of the form "=r,g,b,a" into a vector: (r,g,b,a)
1708 vector<int> RenderTexture::_ParseBitVector(string bitVector)
1710 vector<string> pieces;
1713 if (bitVector == "")
1715 bits.push_back(8); // if a depth isn't specified, use default 8 bits
1719 string::size_type pos = 0;
1720 string::size_type nextpos = 0;
1723 nextpos = bitVector.find_first_of(", ", pos);
1724 pieces.push_back(string(bitVector, pos, nextpos - pos));
1726 } while (nextpos != bitVector.npos );
1728 for ( vector<string>::iterator it = pieces.begin(); it != pieces.end(); it++)
1730 bits.push_back(strtol(it->c_str(), 0, 10));
1736 //---------------------------------------------------------------------------
1737 // Function : RenderTexture::_VerifyExtensions
1739 //---------------------------------------------------------------------------
1741 * @fn RenderTexture::_VerifyExtensions()
1742 * @brief Checks that the necessary extensions are available based on RT mode.
1744 bool RenderTexture::_VerifyExtensions()
1747 // a second call to _VerifyExtensions will allways return true, causing a crash
1748 // if the extension is not supported
1749 if ( true || !fctPtrInited )
1751 fctPtrInited = true;
1752 wglGetExtensionsStringARBProc wglGetExtensionsStringARBPtr = (wglGetExtensionsStringARBProc)wglGetProcAddress( "wglGetExtensionsStringARB" );
1753 if ( wglGetExtensionsStringARBPtr == 0 )
1755 PrintExtensionError("WGL_ARB_extensions_string");
1758 string wglExtensionsString = wglGetExtensionsStringARBPtr( wglGetCurrentDC() );
1759 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pixel_format" ) )
1761 wglChoosePixelFormatARBPtr = (wglChoosePixelFormatARBProc)SGLookupFunction("wglChoosePixelFormatARB");
1762 wglGetPixelFormatAttribivARBPtr = (wglGetPixelFormatAttribivARBProc)SGLookupFunction("wglGetPixelFormatAttribivARB");
1766 PrintExtensionError("WGL_ARB_pixel_format");
1769 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pbuffer" ) )
1771 wglCreatePbufferARBPtr = (wglCreatePbufferARBProc)SGLookupFunction("wglCreatePbufferARB");
1772 wglGetPbufferDCARBPtr = (wglGetPbufferDCARBProc)SGLookupFunction("wglGetPbufferDCARB");
1773 wglQueryPbufferARBPtr = (wglQueryPbufferARBProc)SGLookupFunction("wglQueryPbufferARB");
1774 wglReleasePbufferDCARBPtr = (wglReleasePbufferDCARBProc)SGLookupFunction("wglReleasePbufferDCARB");
1775 wglDestroyPbufferARBPtr = (wglDestroyPbufferARBProc)SGLookupFunction("wglDestroyPbufferARB");
1779 PrintExtensionError("WGL_ARB_pbuffer");
1782 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_render_texture" ) )
1784 wglBindTexImageARBPtr = (wglBindTexImageARBProc)SGLookupFunction("wglBindTexImageARB");
1785 wglReleaseTexImageARBPtr = (wglReleaseTexImageARBProc)SGLookupFunction("wglReleaseTexImageARB");
1787 else if ( _bIsTexture )
1789 PrintExtensionError("WGL_ARB_render_texture");
1792 if (_bRectangle && !SGIsOpenGLExtensionSupported( "GL_NV_texture_rectangle" ))
1794 PrintExtensionError("GL_NV_texture_rectangle");
1797 if (_bFloat && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) || SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ATI_pixel_format_float" )))
1799 PrintExtensionError("GL_NV_float_buffer or GL_ATI_pixel_format_float");
1803 if (_bFloat && _bIsTexture && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) || SGIsOpenGLExtensionSupported( "GL_ATI_texture_float" )))
1805 PrintExtensionError("NV_float_buffer or ATI_texture_float");
1807 if (_bIsDepthTexture && !SGIsOpenGLExtensionSupported( "GL_ARB_depth_texture" ))
1810 #if defined(_DEBUG) | defined(DEBUG)
1811 SG_LOG(SG_GL, SG_ALERT,
1812 "RenderTexture Warning: "
1813 "OpenGL extension GL_ARB_depth_texture not available."
1814 " Using glReadPixels() to emulate behavior.");
1816 _bHasARBDepthTexture = false;
1817 //PrintExtensionError("GL_ARB_depth_texture");
1823 #elif defined( __APPLE__ )
1826 // First try the glX version 1.3 functions.
1827 glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfig");
1828 glXCreatePbufferPtr = (glXCreatePbufferProc)SGLookupFunction("glXCreatePbuffer");
1829 glXGetVisualFromFBConfigPtr = (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfig");
1830 glXCreateContextPtr = (glXCreateContextProc)SGLookupFunction("glXCreateContext");
1831 glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyPbuffer");
1832 glXQueryDrawablePtr = (glXQueryDrawableProc)SGLookupFunction("glXQueryDrawable");
1834 if (glXChooseFBConfigPtr &&
1835 glXCreatePbufferPtr &&
1836 glXGetVisualFromFBConfigPtr &&
1837 glXCreateContextPtr &&
1838 glXDestroyPbufferPtr &&
1839 glXQueryDrawablePtr)
1840 glXVersion1_3Present = true;
1843 glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfigSGIX");
1844 glXCreateGLXPbufferPtr = (glXCreateGLXPbufferProc)SGLookupFunction("glXCreateGLXPbufferSGIX");
1845 glXGetVisualFromFBConfigPtr = (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfigSGIX");
1846 glXCreateContextWithConfigPtr = (glXCreateContextWithConfigProc)SGLookupFunction("glXCreateContextWithConfigSGIX");
1847 glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyGLXPbufferSGIX");
1848 glXQueryGLXPbufferSGIXPtr = (glXQueryGLXPbufferSGIXProc)SGLookupFunction("glXQueryGLXPbufferSGIX");
1851 if (!glXChooseFBConfigPtr ||
1852 !glXCreateGLXPbufferPtr ||
1853 !glXGetVisualFromFBConfigPtr ||
1854 !glXCreateContextWithConfigPtr ||
1855 !glXDestroyPbufferPtr ||
1856 !glXQueryGLXPbufferSGIXPtr)
1860 if (_bIsDepthTexture && !GL_ARB_depth_texture)
1862 PrintExtensionError("GL_ARB_depth_texture");
1865 if (_bFloat && _bIsTexture && !GLX_NV_float_buffer)
1867 PrintExtensionError("GLX_NV_float_buffer");
1870 if (_eUpdateMode == RT_RENDER_TO_TEXTURE)
1872 PrintExtensionError("Some GLX render texture extension: Please implement me!");
1880 //---------------------------------------------------------------------------
1881 // Function : RenderTexture::_InitializeTextures
1883 //---------------------------------------------------------------------------
1885 * @fn RenderTexture::_InitializeTextures()
1886 * @brief Initializes the state of textures used by the RenderTexture.
1888 bool RenderTexture::_InitializeTextures()
1890 // Determine the appropriate texture formats and filtering modes.
1891 if (_bIsTexture || _bIsDepthTexture)
1893 if (_bRectangle && GL_NV_texture_rectangle)
1894 _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
1896 _iTextureTarget = GL_TEXTURE_2D;
1901 glGenTextures(1, (GLuint*)&_iTextureID);
1902 glBindTexture(_iTextureTarget, _iTextureID);
1904 // Use clamp to edge as the default texture wrap mode for all tex
1905 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1906 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1907 // Use NEAREST as the default texture filtering mode.
1908 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1909 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1912 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
1914 GLuint iInternalFormat;
1921 SG_LOG(SG_GL, SG_ALERT,
1922 "RenderTexture Error: mipmapped float textures not "
1927 switch(_iNumComponents)
1930 if (GL_NV_float_buffer)
1932 iInternalFormat = (_iNumColorBits[0] > 16) ?
1933 GL_FLOAT_R32_NV : GL_FLOAT_R16_NV;
1935 else if (GL_ATI_texture_float)
1937 iInternalFormat = (_iNumColorBits[0] > 16) ?
1938 GL_LUMINANCE_FLOAT32_ATI :
1939 GL_LUMINANCE_FLOAT16_ATI;
1941 iFormat = GL_LUMINANCE;
1944 if (GL_NV_float_buffer)
1946 iInternalFormat = (_iNumColorBits[0] > 16) ?
1947 GL_FLOAT_RG32_NV : GL_FLOAT_RG16_NV;
1949 else if (GL_ATI_texture_float)
1951 iInternalFormat = (_iNumColorBits[0] > 16) ?
1952 GL_LUMINANCE_ALPHA_FLOAT32_ATI :
1953 GL_LUMINANCE_ALPHA_FLOAT16_ATI;
1955 iFormat = GL_LUMINANCE_ALPHA;
1958 if (GL_NV_float_buffer)
1960 iInternalFormat = (_iNumColorBits[0] > 16) ?
1961 GL_FLOAT_RGB32_NV : GL_FLOAT_RGB16_NV;
1963 else if (GL_ATI_texture_float)
1965 iInternalFormat = (_iNumColorBits[0] > 16) ?
1966 GL_RGB_FLOAT32_ATI : GL_RGB_FLOAT16_ATI;
1971 if (GL_NV_float_buffer)
1973 iInternalFormat = (_iNumColorBits[0] > 16) ?
1974 GL_FLOAT_RGBA32_NV : GL_FLOAT_RGBA16_NV;
1976 else if (GL_ATI_texture_float)
1978 iInternalFormat = (_iNumColorBits[0] > 16) ?
1979 GL_RGBA_FLOAT32_ATI : GL_RGBA_FLOAT16_ATI;
1984 SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: "
1985 "Invalid number of components: " <<
1992 if (4 == _iNumComponents)
1994 iInternalFormat = GL_RGBA8;
1999 iInternalFormat = GL_RGB8;
2004 // Allocate the texture image (but pass it no data for now).
2005 glTexImage2D(_iTextureTarget, 0, iInternalFormat,
2006 _iWidth, _iHeight, 0, iFormat, GL_FLOAT, NULL);
2010 if (_bIsDepthTexture)
2012 glGenTextures(1, (GLuint*)&_iDepthTextureID);
2013 glBindTexture(_iTextureTarget, _iDepthTextureID);
2015 // Use clamp to edge as the default texture wrap mode for all tex
2016 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2017 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2018 // Use NEAREST as the default texture filtering mode.
2019 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2020 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2022 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2025 if (_bHasARBDepthTexture)
2027 // Allocate the texture image (but pass it no data for now).
2028 glTexImage2D(_iTextureTarget, 0, GL_DEPTH_COMPONENT,
2029 _iWidth, _iHeight, 0, GL_DEPTH_COMPONENT,
2034 // allocate memory for depth texture
2035 // Since this is slow, we warn the user in debug mode. (above)
2036 _pPoorDepthTexture = new unsigned short[_iWidth * _iHeight];
2037 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
2038 _iWidth, _iHeight, 0, GL_LUMINANCE,
2039 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2049 //---------------------------------------------------------------------------
2050 // Function : RenderTexture::_MaybeCopyBuffer
2052 //---------------------------------------------------------------------------
2054 * @fn RenderTexture::_MaybeCopyBuffer()
2055 * @brief Does the actual copying for RenderTextures with RT_COPY_TO_TEXTURE
2057 void RenderTexture::_MaybeCopyBuffer()
2060 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2064 glBindTexture(_iTextureTarget, _iTextureID);
2065 glCopyTexSubImage2D(_iTextureTarget,
2066 0, 0, 0, 0, 0, _iWidth, _iHeight);
2068 if (_bIsDepthTexture)
2070 glBindTexture(_iTextureTarget, _iDepthTextureID);
2071 // HOW TO COPY DEPTH TEXTURE??? Supposedly this just magically works...
2073 if (_bHasARBDepthTexture)
2075 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0,
2080 // no 'real' depth texture available, so behavior has to be emulated
2081 // using glReadPixels (beware, this is (naturally) slow ...)
2082 glReadPixels(0, 0, _iWidth, _iHeight, GL_DEPTH_COMPONENT,
2083 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2084 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
2085 _iWidth, _iHeight, 0, GL_LUMINANCE,
2086 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2095 glBindTexture(_iTextureTarget, _iTextureID);
2096 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2098 if (_bIsDepthTexture)
2100 glBindTexture(_iTextureTarget, _iDepthTextureID);
2101 assert(_bHasARBDepthTexture);
2102 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2108 //---------------------------------------------------------------------------
2109 // Function : RenderTexture::_ReleaseBoundBuffers
2111 //---------------------------------------------------------------------------
2113 * @fn RenderTexture::_ReleaseBoundBuffers()
2114 * @brief Releases buffer bindings on RenderTextures with RT_RENDER_TO_TEXTURE
2116 bool RenderTexture::_ReleaseBoundBuffers()
2119 if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2121 glBindTexture(_iTextureTarget, _iTextureID);
2123 // release the pbuffer from the render texture object
2124 if (0 != _iCurrentBoundBuffer && _bIsBufferBound)
2126 if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, _iCurrentBoundBuffer))
2131 _bIsBufferBound = false;
2135 if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2137 glBindTexture(_iTextureTarget, _iDepthTextureID);
2139 // release the pbuffer from the render texture object
2140 if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
2148 // textures can't be bound in Linux
2153 //---------------------------------------------------------------------------
2154 // Function : RenderTexture::_MakeCurrent
2156 //---------------------------------------------------------------------------
2158 * @fn RenderTexture::_MakeCurrent()
2159 * @brief Makes the RenderTexture's context current
2162 bool RenderTexture::_MakeCurrent()
2165 // make the pbuffer's rendering context current.
2166 if (FALSE == wglMakeCurrent( _hDC, _hGLContext))
2171 #elif defined( __APPLE__ )
2173 if (false == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
2182 /////////////////////////////////////////////////////////////////////////////
2184 // Begin Deprecated Interface
2186 /////////////////////////////////////////////////////////////////////////////
2188 //---------------------------------------------------------------------------
2189 // Function : RenderTexture::RenderTexture
2191 //---------------------------------------------------------------------------
2193 * @fn RenderTexture::RenderTexture()
2194 * @brief Constructor.
2196 RenderTexture::RenderTexture(int width, int height,
2197 bool bIsTexture /* = true */,
2198 bool bIsDepthTexture /* = false */)
2201 _bIsTexture(bIsTexture),
2202 _bIsDepthTexture(bIsDepthTexture),
2203 _bHasARBDepthTexture(true), // [Redge]
2204 _eUpdateMode(RT_RENDER_TO_TEXTURE),
2205 _bInitialized(false),
2207 _iCurrentBoundBuffer(0),
2209 _iNumStencilBits(0),
2210 _bDoubleBuffered(false),
2215 _bShareObjects(false),
2216 _bCopyContext(false),
2222 _hPreviousContext(0),
2223 #elif defined( __APPLE__ )
2228 _hPreviousContext(0),
2229 _hPreviousDrawable(0),
2231 _iTextureTarget(GL_NONE),
2233 _iDepthTextureID(0),
2234 _pPoorDepthTexture(0) // [Redge]
2236 assert(width > 0 && height > 0);
2237 #if defined DEBUG || defined _DEBUG
2238 SG_LOG(SG_GL, SG_ALERT,
2239 "RenderTexture Warning: Deprecated Contructor interface used.");
2242 _iNumColorBits[0] = _iNumColorBits[1] =
2243 _iNumColorBits[2] = _iNumColorBits[3] = 0;
2244 _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
2247 //------------------------------------------------------------------------------
2248 // Function : RenderTexture::Initialize
2250 //------------------------------------------------------------------------------
2252 * @fn RenderTexture::Initialize(bool bShare, bool bDepth, bool bStencil, bool bMipmap, unsigned int iRBits, unsigned int iGBits, unsigned int iBBits, unsigned int iABits);
2253 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
2255 * This function actually does the creation of the p-buffer. It can only be called
2256 * once a GL context has already been created. Note that if the texture is not
2257 * power of two dimensioned, or has more than 8 bits per channel, enabling mipmapping
2258 * will cause an error.
2260 bool RenderTexture::Initialize(bool bShare /* = true */,
2261 bool bDepth /* = false */,
2262 bool bStencil /* = false */,
2263 bool bMipmap /* = false */,
2264 bool bAnisoFilter /* = false */,
2265 unsigned int iRBits /* = 8 */,
2266 unsigned int iGBits /* = 8 */,
2267 unsigned int iBBits /* = 8 */,
2268 unsigned int iABits /* = 8 */,
2269 UpdateMode updateMode /* = RT_RENDER_TO_TEXTURE */)
2271 if (0 == _iWidth || 0 == _iHeight)
2274 #if defined DEBUG || defined _DEBUG
2275 SG_LOG(SG_GL, SG_ALERT,
2276 "RenderTexture Warning: Deprecated Initialize() interface used.");
2279 // create a mode string.
2282 mode.append("depth ");
2284 mode.append("stencil ");
2286 mode.append("mipmap ");
2287 if (iRBits + iGBits + iBBits + iABits > 0)
2298 char bitVector[100];
2299 snprintf( bitVector, 100,
2300 "%d%s,%d%s,%d%s,%d%s",
2301 iRBits, (iRBits >= 16) ? "f" : "",
2302 iGBits, (iGBits >= 16) ? "f" : "",
2303 iBBits, (iBBits >= 16) ? "f" : "",
2304 iABits, (iABits >= 16) ? "f" : "");
2305 mode.append(bitVector);
2310 if (GL_NV_texture_rectangle &&
2311 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2312 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2313 mode.append("texRECT ");
2315 mode.append("tex2D ");
2317 if (_bIsDepthTexture)
2319 if (GL_NV_texture_rectangle &&
2320 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2321 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2322 mode.append("texRECT ");
2324 mode.append("tex2D ");
2326 if (RT_COPY_TO_TEXTURE == updateMode)
2329 _pixelFormatAttribs.clear();
2330 _pbufferAttribs.clear();
2333 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
2334 _pixelFormatAttribs.push_back(true);
2335 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
2336 _pixelFormatAttribs.push_back(true);
2338 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
2339 _pbufferAttribs.push_back(true);
2340 #elif defined( __APPLE__ )
2342 _pixelFormatAttribs.push_back(GLX_RENDER_TYPE_SGIX);
2343 _pixelFormatAttribs.push_back(GLX_RGBA_BIT_SGIX);
2344 _pixelFormatAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
2345 _pixelFormatAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
2348 _ParseModeString(mode.c_str(), _pixelFormatAttribs, _pbufferAttribs);
2351 _pixelFormatAttribs.push_back(0);
2352 _pbufferAttribs.push_back(0);
2354 _pixelFormatAttribs.push_back(None);
2357 Initialize(_iWidth, _iHeight, bShare);
2363 //---------------------------------------------------------------------------
2364 // Function : RenderTexture::Reset
2366 //---------------------------------------------------------------------------
2368 * @fn RenderTexture::Reset(int iWidth, int iHeight, unsigned int iMode, bool bIsTexture, bool bIsDepthTexture)
2369 * @brief Resets the resolution of the offscreen buffer.
2371 * Causes the buffer to delete itself. User must call Initialize() again
2374 bool RenderTexture::Reset(int iWidth, int iHeight)
2376 SG_LOG(SG_GL, SG_ALERT,
2377 "RenderTexture Warning: Deprecated Reset() interface used.");
2381 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Reset(): failed to invalidate.");