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 // Various Bug Fixes: Daniel (Redge) Sperl
32 // --------------------------------------------------------------------------
34 * @file RenderTexture.cpp
36 * Implementation of class RenderTexture. A multi-format render to
39 #pragma warning(disable:4786)
44 * Jan. 2005, Removed GLEW dependencies, Erik Hofman, Fred Bouvier
45 * Nov. 2005, Use the simgear logging facility, Erik Hofman
49 # include <simgear_config.h>
56 #include <simgear/compiler.h>
57 #include <simgear/debug/logstream.hxx>
58 #include <simgear/screen/extensions.hxx>
59 #include <simgear/screen/RenderTexture.h>
67 #pragma comment(lib, "gdi32.lib") // required for GetPixelFormat()
73 static bool fctPtrInited = false;
74 /* WGL_ARB_pixel_format */
75 static wglChoosePixelFormatARBProc wglChoosePixelFormatARBPtr = 0;
76 static wglGetPixelFormatAttribivARBProc wglGetPixelFormatAttribivARBPtr = 0;
78 static wglCreatePbufferARBProc wglCreatePbufferARBPtr = 0;
79 static wglGetPbufferDCARBProc wglGetPbufferDCARBPtr = 0;
80 static wglQueryPbufferARBProc wglQueryPbufferARBPtr = 0;
81 static wglReleasePbufferDCARBProc wglReleasePbufferDCARBPtr = 0;
82 static wglDestroyPbufferARBProc wglDestroyPbufferARBPtr = 0;
83 /* WGL_ARB_render_texture */
84 static wglBindTexImageARBProc wglBindTexImageARBPtr = 0;
85 static wglReleaseTexImageARBProc wglReleaseTexImageARBPtr = 0;
87 #elif defined( __APPLE__ )
89 static bool glXVersion1_3Present = false;
90 static glXChooseFBConfigProc glXChooseFBConfigPtr = 0;
91 static glXCreatePbufferProc glXCreatePbufferPtr = 0;
92 static glXCreateGLXPbufferProc glXCreateGLXPbufferPtr = 0;
93 static glXGetVisualFromFBConfigProc glXGetVisualFromFBConfigPtr = 0;
94 static glXCreateContextProc glXCreateContextPtr = 0;
95 static glXCreateContextWithConfigProc glXCreateContextWithConfigPtr = 0;
96 static glXDestroyPbufferProc glXDestroyPbufferPtr = 0;
97 static glXQueryDrawableProc glXQueryDrawablePtr = 0;
98 static glXQueryGLXPbufferSGIXProc glXQueryGLXPbufferSGIXPtr = 0;
101 //---------------------------------------------------------------------------
102 // Function : RenderTexture::RenderTexture
104 //---------------------------------------------------------------------------
106 * @fn RenderTexture::RenderTexture()
107 * @brief Mode-string-based Constructor.
109 RenderTexture::RenderTexture(const char *strMode)
113 _bIsDepthTexture(false),
114 _bHasARBDepthTexture(true), // [Redge]
116 _eUpdateMode(RT_RENDER_TO_TEXTURE),
118 _eUpdateMode(RT_COPY_TO_TEXTURE),
120 _bInitialized(false),
122 _bIsBufferBound(false),
123 _iCurrentBoundBuffer(0),
127 _bDoubleBuffered(false),
131 _bShareObjects(false),
132 _bCopyContext(false),
138 _hPreviousContext(0),
139 #elif defined( __APPLE__ )
144 _hPreviousContext(0),
145 _hPreviousDrawable(0),
147 _iTextureTarget(GL_NONE),
150 _pPoorDepthTexture(0) // [Redge]
152 _iNumColorBits[0] = _iNumColorBits[1] =
153 _iNumColorBits[2] = _iNumColorBits[3] = 0;
156 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
157 _pixelFormatAttribs.push_back(true);
158 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
159 _pixelFormatAttribs.push_back(true);
161 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
162 _pbufferAttribs.push_back(true);
163 #elif defined( __APPLE__ )
165 _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
166 _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
167 _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
168 _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
171 _ParseModeString(strMode, _pixelFormatAttribs, _pbufferAttribs);
174 _pixelFormatAttribs.push_back(0);
175 _pbufferAttribs.push_back(0);
177 _pixelFormatAttribs.push_back(None);
182 //---------------------------------------------------------------------------
183 // Function : RenderTexture::~RenderTexture
185 //---------------------------------------------------------------------------
187 * @fn RenderTexture::~RenderTexture()
190 RenderTexture::~RenderTexture()
196 //---------------------------------------------------------------------------
197 // Function : _wglGetLastError
199 //---------------------------------------------------------------------------
201 * @fn wglGetLastError()
202 * @brief Returns the last windows error generated.
205 void _wglGetLastError()
209 DWORD err = GetLastError();
212 case ERROR_INVALID_PIXEL_FORMAT:
213 SG_LOG(SG_GL, SG_ALERT,
214 "RenderTexture Win32 Error: ERROR_INVALID_PIXEL_FORMAT");
216 case ERROR_NO_SYSTEM_RESOURCES:
217 SG_LOG(SG_GL, SG_ALERT,
218 "RenderTexture Win32 Error: ERROR_NO_SYSTEM_RESOURCES");
220 case ERROR_INVALID_DATA:
221 SG_LOG(SG_GL, SG_ALERT,
222 "RenderTexture Win32 Error: ERROR_INVALID_DATA");
224 case ERROR_INVALID_WINDOW_HANDLE:
225 SG_LOG(SG_GL, SG_ALERT,
226 "RenderTexture Win32 Error: ERROR_INVALID_WINDOW_HANDLE");
228 case ERROR_RESOURCE_TYPE_NOT_FOUND:
229 SG_LOG(SG_GL, SG_ALERT,
230 "RenderTexture Win32 Error: ERROR_RESOURCE_TYPE_NOT_FOUND");
237 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
238 FORMAT_MESSAGE_FROM_SYSTEM |
239 FORMAT_MESSAGE_IGNORE_INSERTS,
242 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
247 SG_LOG(SG_GL, SG_ALERT, "RenderTexture Win32 Error " << err << ":" << lpMsgBuf);
248 LocalFree( lpMsgBuf );
257 //---------------------------------------------------------------------------
258 // Function : PrintExtensionError
260 //---------------------------------------------------------------------------
262 * @fn PrintExtensionError( char* strMsg, ... )
263 * @brief Prints an error about missing OpenGL extensions.
265 void PrintExtensionError( char* strMsg, ... )
267 SG_LOG(SG_GL, SG_ALERT,
268 "Error: RenderTexture requires the following unsupported "
269 "OpenGL extensions: ");
272 va_start(args, strMsg);
273 #if defined _WIN32 && !defined __CYGWIN__
274 _vsnprintf( strBuffer, 512, strMsg, args );
276 vsnprintf( strBuffer, 512, strMsg, args );
280 SG_LOG(SG_GL, SG_ALERT, strMsg);
284 //---------------------------------------------------------------------------
285 // Function : RenderTexture::Initialize
287 //---------------------------------------------------------------------------
289 * @fn RenderTexture::Initialize(int width, int height, bool shareObjects, bool copyContext);
290 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
292 * This function creates of the p-buffer. It can only be called once a GL
293 * context has already been created.
295 bool RenderTexture::Initialize(int width, int height,
296 bool shareObjects /* = true */,
297 bool copyContext /* = false */)
299 assert(width > 0 && height > 0);
301 _iWidth = width; _iHeight = height;
302 _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
304 _bShareObjects = shareObjects;
305 _bCopyContext = copyContext;
307 // Check if this is an NVXX GPU and verify necessary extensions.
308 if (!_VerifyExtensions())
315 // Get the current context.
316 HDC hdc = wglGetCurrentDC();
319 HGLRC hglrc = wglGetCurrentContext();
324 unsigned int iNumFormats;
328 // Get the pixel format for the on-screen window.
329 iFormat = GetPixelFormat(hdc);
332 SG_LOG(SG_GL, SG_ALERT,
333 "RenderTexture Error: GetPixelFormat() failed.");
339 if (!wglChoosePixelFormatARBPtr(hdc, &_pixelFormatAttribs[0], NULL,
340 1, &iFormat, &iNumFormats))
342 SG_LOG(SG_GL, SG_ALERT,
343 "RenderTexture Error: wglChoosePixelFormatARB() failed.");
347 if ( iNumFormats <= 0 )
349 SG_LOG(SG_GL, SG_ALERT,
350 "RenderTexture Error: Couldn't find a suitable "
357 // Create the p-buffer.
358 _hPBuffer = wglCreatePbufferARBPtr(hdc, iFormat, _iWidth, _iHeight,
359 &_pbufferAttribs[0]);
362 SG_LOG(SG_GL, SG_ALERT,
363 "RenderTexture Error: wglCreatePbufferARB() failed.");
368 // Get the device context.
369 _hDC = wglGetPbufferDCARBPtr( _hPBuffer);
372 SG_LOG(SG_GL, SG_ALERT,
373 "RenderTexture Error: wglGetGetPbufferDCARB() failed.");
378 // Create a gl context for the p-buffer.
381 // Let's use the same gl context..
382 // Since the device contexts are compatible (i.e. same pixelformat),
383 // we should be able to use the same gl rendering context.
388 _hGLContext = wglCreateContext( _hDC );
391 SG_LOG(SG_GL, SG_ALERT,
392 "RenderTexture Error: wglCreateContext() failed.");
398 // Share lists, texture objects, and program objects.
401 if( !wglShareLists(hglrc, _hGLContext) )
403 SG_LOG(SG_GL, SG_ALERT,
404 "RenderTexture Error: wglShareLists() failed.");
410 // Determine the actual width and height we were able to create.
411 wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
412 wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
414 _bInitialized = true;
416 // get the actual number of bits allocated:
417 int attrib = WGL_RED_BITS_ARB;
421 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
423 attrib = WGL_GREEN_BITS_ARB;
425 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
427 attrib = WGL_BLUE_BITS_ARB;
429 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
431 attrib = WGL_ALPHA_BITS_ARB;
433 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
435 attrib = WGL_DEPTH_BITS_ARB;
437 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
439 attrib = WGL_STENCIL_BITS_ARB;
441 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
443 attrib = WGL_DOUBLE_BUFFER_ARB;
445 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
446 ? (value?true:false) : false;
448 #if defined(_DEBUG) | defined(DEBUG)
449 SG_LOG(SG_GL, SG_ALERT, "Created a " << _iWidth << "x" << _iHeight <<
450 " RenderTexture with BPP(" <<
451 _iNumColorBits[0] << "," << _iNumColorBits[1] << "," <<
452 _iNumColorBits[2] << "," << _iNumColorBits[3] << ")");
453 if (_iNumDepthBits) SG_LOG(SG_GL, SG_ALERT, " depth=" << _iNumDepthBits);
454 if (_iNumStencilBits) SG_LOG(SG_GL, SG_ALERT, " stencil=" << _iNumStencilBits);
455 if (_bDoubleBuffered) SG_LOG(SG_GL, SG_ALERT, " double buffered");
458 #elif defined( __APPLE__ )
460 _pDisplay = glXGetCurrentDisplay();
461 GLXContext context = glXGetCurrentContext();
462 int screen = DefaultScreen(_pDisplay);
463 XVisualInfo *visInfo;
465 GLXFBConfig *fbConfigs;
468 fbConfigs = glXChooseFBConfigPtr(_pDisplay, screen,
469 &_pixelFormatAttribs[0], &nConfigs);
471 if (nConfigs == 0 || !fbConfigs)
473 SG_LOG(SG_GL, SG_ALERT,
474 "RenderTexture Error: Couldn't find a suitable pixel format.");
478 // Pick the first returned format that will return a pbuffer
479 if (glXVersion1_3Present)
482 GLX_PBUFFER_WIDTH, _iWidth,
483 GLX_PBUFFER_HEIGHT, _iHeight,
484 GLX_LARGEST_PBUFFER, False,
487 for (int i=0;i<nConfigs;i++)
489 _hPBuffer = glXCreatePbufferPtr(_pDisplay, fbConfigs[i], pbufAttrib);
492 XVisualInfo *visInfo = glXGetVisualFromFBConfigPtr(_pDisplay, fbConfigs[i]);
494 _hGLContext = glXCreateContextPtr(_pDisplay, visInfo,
495 _bShareObjects ? context : NULL,
511 for (int i=0;i<nConfigs;i++)
513 _hPBuffer = glXCreateGLXPbufferPtr(_pDisplay, fbConfigs[i],
514 _iWidth, _iHeight, NULL);
517 _hGLContext = glXCreateContextWithConfigPtr(_pDisplay,
520 _bShareObjects ? context : NULL,
530 SG_LOG(SG_GL, SG_ALERT,
531 "RenderTexture Error: glXCreateGLXPbufferPtr() failed.");
538 _hGLContext = glXCreateContext(_pDisplay, visInfo,
539 _bShareObjects ? context : NULL, False);
542 SG_LOG(SG_GL, SG_ALERT,
543 "RenderTexture Error: glXCreateContext() failed.");
548 if (!glXVersion1_3Present)
550 glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_WIDTH_SGIX,
552 glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_HEIGHT_SGIX,
556 _bInitialized = true;
558 // XXX Query the color format
563 // Now that the pbuffer is created, allocate any texture objects needed,
564 // and initialize them (for CTT updates only). These must be allocated
565 // in the context of the pbuffer, though, or the RT won't work without
568 if (false == wglMakeCurrent( _hDC, _hGLContext))
573 #elif defined( __APPLE__ )
575 _hPreviousContext = glXGetCurrentContext();
576 _hPreviousDrawable = glXGetCurrentDrawable();
578 if (False == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
584 bool result = _InitializeTextures();
586 BindBuffer(WGL_FRONT_LEFT_ARB);
592 // make the previous rendering context current
593 if (false == wglMakeCurrent( hdc, hglrc))
598 #elif defined( __APPLE__ )
600 if (False == glXMakeCurrent(_pDisplay,
601 _hPreviousDrawable, _hPreviousContext))
605 if (glXVersion1_3Present)
607 GLXDrawable draw = glXGetCurrentDrawable();
608 glXQueryDrawablePtr(_pDisplay, draw, GLX_WIDTH, (unsigned int*)&_iWidth);
609 glXQueryDrawablePtr(_pDisplay, draw, GLX_HEIGHT, (unsigned int*)&_iHeight);
617 //---------------------------------------------------------------------------
618 // Function : RenderTexture::_Invalidate
620 //---------------------------------------------------------------------------
622 * @fn RenderTexture::_Invalidate()
623 * @brief Returns the pbuffer memory to the graphics device.
626 bool RenderTexture::_Invalidate()
628 _iNumColorBits[0] = _iNumColorBits[1] =
629 _iNumColorBits[2] = _iNumColorBits[3] = 0;
631 _iNumStencilBits = 0;
634 glDeleteTextures(1, &_iTextureID);
635 if (_bIsDepthTexture)
638 if (!_bHasARBDepthTexture) delete[] _pPoorDepthTexture;
640 glDeleteTextures(1, &_iDepthTextureID);
646 // Check if we are currently rendering in the pbuffer
647 if (wglGetCurrentContext() == _hGLContext)
650 wglDeleteContext( _hGLContext);
651 wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
652 wglDestroyPbufferARBPtr( _hPBuffer );
656 #elif defined( __APPLE__ )
660 if(glXGetCurrentContext() == _hGLContext)
661 // XXX I don't know if this is right at all
662 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
663 glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
669 // [WVB] do we need to call _ReleaseBoundBuffers() too?
674 //---------------------------------------------------------------------------
675 // Function : RenderTexture::Reset
677 //---------------------------------------------------------------------------
679 * @fn RenderTexture::Reset()
680 * @brief Resets the resolution of the offscreen buffer.
682 * Causes the buffer to delete itself. User must call Initialize() again
685 bool RenderTexture::Reset(const char *strMode, ...)
687 _iWidth = 0; _iHeight = 0;
688 _bIsTexture = false; _bIsDepthTexture = false,
689 _bHasARBDepthTexture = true;
691 _eUpdateMode = RT_RENDER_TO_TEXTURE;
693 _eUpdateMode = RT_COPY_TO_TEXTURE;
695 _bInitialized = false;
697 _bIsBufferBound = false;
698 _iCurrentBoundBuffer = 0;
699 _iNumDepthBits = 0; _iNumStencilBits = 0;
700 _bDoubleBuffered = false;
701 _bFloat = false; _bPowerOf2 = true;
702 _bRectangle = false; _bMipmap = false;
703 _bShareObjects = false; _bCopyContext = false;
704 _iTextureTarget = GL_NONE; _iTextureID = 0;
705 _iDepthTextureID = 0;
706 _pPoorDepthTexture = 0;
707 _pixelFormatAttribs.clear();
708 _pbufferAttribs.clear();
710 if (IsInitialized() && !_Invalidate())
712 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Reset(): failed to invalidate.");
716 _iNumColorBits[0] = _iNumColorBits[1] =
717 _iNumColorBits[2] = _iNumColorBits[3] = 0;
720 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
721 _pixelFormatAttribs.push_back(true);
722 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
723 _pixelFormatAttribs.push_back(true);
725 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
726 _pbufferAttribs.push_back(true);
727 #elif defined( __APPLE__ )
729 _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
730 _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
731 _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
732 _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
737 va_start(args,strMode);
738 #if defined _WIN32 && !defined __CYGWIN__
739 _vsnprintf( strBuffer, 256, strMode, args );
741 vsnprintf( strBuffer, 256, strMode, args );
745 _ParseModeString(strBuffer, _pixelFormatAttribs, _pbufferAttribs);
748 _pixelFormatAttribs.push_back(0);
749 _pbufferAttribs.push_back(0);
751 _pixelFormatAttribs.push_back(None);
756 //------------------------------------------------------------------------------
757 // Function : RenderTexture::Resize
759 //------------------------------------------------------------------------------
761 * @fn RenderTexture::Resize(int iWidth, int iHeight)
762 * @brief Changes the size of the offscreen buffer.
764 * Like Reset() this causes the buffer to delete itself.
765 * But unlike Reset(), this call re-initializes the RenderTexture.
766 * Note that Resize() will not work after calling Reset(), or before
767 * calling Initialize() the first time.
769 bool RenderTexture::Resize(int iWidth, int iHeight)
771 if (!_bInitialized) {
772 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): must Initialize() first.");
775 if (iWidth == _iWidth && iHeight == _iHeight) {
779 // Do same basic work as _Invalidate, but don't reset all our flags
781 glDeleteTextures(1, &_iTextureID);
782 if (_bIsDepthTexture)
783 glDeleteTextures(1, &_iDepthTextureID);
787 // Check if we are currently rendering in the pbuffer
788 if (wglGetCurrentContext() == _hGLContext)
791 wglDeleteContext( _hGLContext);
792 wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
793 wglDestroyPbufferARBPtr( _hPBuffer );
797 #elif defined( __APPLE__ )
801 if(glXGetCurrentContext() == _hGLContext)
802 // XXX I don't know if this is right at all
803 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
804 glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
809 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): failed to resize.");
812 _bInitialized = false;
813 return Initialize(iWidth, iHeight, _bShareObjects, _bCopyContext);
816 //---------------------------------------------------------------------------
817 // Function : RenderTexture::BeginCapture
819 //---------------------------------------------------------------------------
821 * @fn RenderTexture::BeginCapture()
822 * @brief Activates rendering to the RenderTexture.
824 bool RenderTexture::BeginCapture()
828 SG_LOG(SG_GL, SG_ALERT,
829 "RenderTexture::BeginCapture(): Texture is not initialized!");
833 // cache the current context so we can reset it when EndCapture() is called.
834 _hPreviousDC = wglGetCurrentDC();
835 if (NULL == _hPreviousDC)
837 _hPreviousContext = wglGetCurrentContext();
838 if (NULL == _hPreviousContext)
840 #elif defined( __APPLE__ )
842 _hPreviousContext = glXGetCurrentContext();
843 _hPreviousDrawable = glXGetCurrentDrawable();
846 _ReleaseBoundBuffers();
848 return _MakeCurrent();
852 //---------------------------------------------------------------------------
853 // Function : RenderTexture::EndCapture
855 //---------------------------------------------------------------------------
857 * @fn RenderTexture::EndCapture()
858 * @brief Ends rendering to the RenderTexture.
860 bool RenderTexture::EndCapture()
864 SG_LOG(SG_GL, SG_ALERT,
865 "RenderTexture::EndCapture() : Texture is not initialized!");
872 // make the previous rendering context current
873 if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
878 #elif defined( __APPLE__ )
880 if (False == glXMakeCurrent(_pDisplay, _hPreviousDrawable,
887 // rebind the textures to a buffers for RTT
888 BindBuffer(_iCurrentBoundBuffer);
894 //---------------------------------------------------------------------------
895 // Function : RenderTexture::BeginCapture(RenderTexture*)
897 //---------------------------------------------------------------------------
899 * @fn RenderTexture::BeginCapture(RenderTexture* other)
900 * @brief Ends capture of 'other', begins capture on 'this'
902 * When performing a series of operations where you modify one texture after
903 * another, it is more efficient to use this method instead of the equivalent
904 * 'EndCapture'/'BeginCapture' pair. This method switches directly to the
905 * new context rather than changing to the default context, and then to the
908 * RenderTexture doesn't have any mechanism for determining if
909 * 'current' really is currently active, so no error will be thrown
912 bool RenderTexture::BeginCapture(RenderTexture* current)
914 bool bContextReset = false;
916 if (current == this) {
917 return true; // no switch necessary
920 // treat as normal Begin if current is 0.
921 return BeginCapture();
925 SG_LOG(SG_GL, SG_ALERT,
926 "RenderTexture::BeginCapture(RenderTexture*): Texture is not initialized!");
929 if (!current->_bInitialized)
931 SG_LOG(SG_GL, SG_ALERT,
932 "RenderTexture::BeginCapture(RenderTexture): 'current' texture is not initialized!");
936 // Sync current pbuffer with its CTT texture if necessary
937 current->_MaybeCopyBuffer();
939 // pass along the previous context so we can reset it when
940 // EndCapture() is called.
942 _hPreviousDC = current->_hPreviousDC;
943 if (NULL == _hPreviousDC)
945 _hPreviousContext = current->_hPreviousContext;
946 if (NULL == _hPreviousContext)
948 #elif defined( __APPLE__ )
950 _hPreviousContext = current->_hPreviousContext;
951 _hPreviousDrawable = current->_hPreviousDrawable;
954 // Unbind textures before making context current
955 if (!_ReleaseBoundBuffers())
958 // Make the pbuffer context current
962 // Rebind buffers of initial RenderTexture
963 current->BindBuffer(_iCurrentBoundBuffer);
964 current->_BindDepthBuffer();
971 //---------------------------------------------------------------------------
972 // Function : RenderTexture::Bind
974 //---------------------------------------------------------------------------
976 * @fn RenderTexture::Bind()
977 * @brief Binds RGB texture.
979 void RenderTexture::Bind() const
981 if (_bInitialized && _bIsTexture)
983 glBindTexture(_iTextureTarget, _iTextureID);
988 //---------------------------------------------------------------------------
989 // Function : RenderTexture::BindDepth
991 //---------------------------------------------------------------------------
993 * @fn RenderTexture::BindDepth()
994 * @brief Binds depth texture.
996 void RenderTexture::BindDepth() const
998 if (_bInitialized && _bIsDepthTexture)
1000 glBindTexture(_iTextureTarget, _iDepthTextureID);
1005 //---------------------------------------------------------------------------
1006 // Function : RenderTexture::BindBuffer
1008 //---------------------------------------------------------------------------
1010 * @fn RenderTexture::BindBuffer()
1011 * @brief Associate the RTT texture id with 'iBuffer' (e.g. WGL_FRONT_LEFT_ARB)
1013 bool RenderTexture::BindBuffer( int iBuffer )
1015 // Must bind the texture too
1016 if (_bInitialized && _bIsTexture)
1018 glBindTexture(_iTextureTarget, _iTextureID);
1021 if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
1022 (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
1024 if (FALSE == wglBindTexImageARBPtr(_hPBuffer, iBuffer))
1026 // WVB: WGL API considers binding twice to the same buffer
1027 // to be an error. But we don't want to
1028 //_wglGetLastError();
1032 _bIsBufferBound = true;
1033 _iCurrentBoundBuffer = iBuffer;
1041 //---------------------------------------------------------------------------
1042 // Function : RenderTexture::BindBuffer
1044 //---------------------------------------------------------------------------
1046 * @fn RenderTexture::_BindDepthBuffer()
1047 * @brief Associate the RTT depth texture id with the depth buffer
1049 bool RenderTexture::_BindDepthBuffer() const
1052 if (_bInitialized && _bIsDepthTexture &&
1053 RT_RENDER_TO_TEXTURE == _eUpdateMode)
1055 glBindTexture(_iTextureTarget, _iDepthTextureID);
1056 if (FALSE == wglBindTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1066 //---------------------------------------------------------------------------
1067 // Function : RenderTexture::_ParseModeString
1069 //---------------------------------------------------------------------------
1071 * @fn RenderTexture::_ParseModeString()
1072 * @brief Parses the user-specified mode string for RenderTexture parameters.
1074 void RenderTexture::_ParseModeString(const char *modeString,
1075 vector<int> &pfAttribs,
1076 vector<int> &pbAttribs)
1078 if (!modeString || strcmp(modeString, "") == 0)
1081 _iNumComponents = 0;
1083 _eUpdateMode = RT_RENDER_TO_TEXTURE;
1085 _eUpdateMode = RT_COPY_TO_TEXTURE;
1089 bool bHasStencil = false;
1090 bool bBind2D = false;
1091 bool bBindRECT = false;
1092 bool bBindCUBE = false;
1094 char *mode = strdup(modeString);
1097 vector<string> tokens;
1098 char *buf = strtok(mode, " ");
1101 tokens.push_back(buf);
1102 buf = strtok(NULL, " ");
1105 for (unsigned int i = 0; i < tokens.size(); i++)
1107 string token = tokens[i];
1109 KeyVal kv = _GetKeyValuePair(token);
1112 if (kv.first == "rgb" && (_iNumComponents <= 1))
1114 if (kv.second.find("f") != kv.second.npos)
1117 vector<int> bitVec = _ParseBitVector(kv.second);
1119 if (bitVec.size() < 3) // expand the scalar to a vector
1121 bitVec.push_back(bitVec[0]);
1122 bitVec.push_back(bitVec[0]);
1126 pfAttribs.push_back(WGL_RED_BITS_ARB);
1127 pfAttribs.push_back(bitVec[0]);
1128 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1129 pfAttribs.push_back(bitVec[1]);
1130 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1131 pfAttribs.push_back(bitVec[2]);
1132 #elif defined( __APPLE__ )
1133 pfAttribs.push_back(AGL_RED_SIZE);
1134 pfAttribs.push_back(bitVec[0]);
1135 pfAttribs.push_back(AGL_GREEN_SIZE);
1136 pfAttribs.push_back(bitVec[1]);
1137 pfAttribs.push_back(AGL_BLUE_SIZE);
1138 pfAttribs.push_back(bitVec[2]);
1140 pfAttribs.push_back(GLX_RED_SIZE);
1141 pfAttribs.push_back(bitVec[0]);
1142 pfAttribs.push_back(GLX_GREEN_SIZE);
1143 pfAttribs.push_back(bitVec[1]);
1144 pfAttribs.push_back(GLX_BLUE_SIZE);
1145 pfAttribs.push_back(bitVec[2]);
1147 _iNumComponents += 3;
1150 else if (kv.first == "rgb")
1151 SG_LOG(SG_GL, SG_ALERT,
1152 "RenderTexture Warning: mistake in components definition "
1153 "(rgb + " << _iNumComponents << ").");
1155 if (kv.first == "rgba" && (_iNumComponents == 0))
1157 if (kv.second.find("f") != kv.second.npos)
1160 vector<int> bitVec = _ParseBitVector(kv.second);
1162 if (bitVec.size() < 4) // expand the scalar to a vector
1164 bitVec.push_back(bitVec[0]);
1165 bitVec.push_back(bitVec[0]);
1166 bitVec.push_back(bitVec[0]);
1170 pfAttribs.push_back(WGL_RED_BITS_ARB);
1171 pfAttribs.push_back(bitVec[0]);
1172 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1173 pfAttribs.push_back(bitVec[1]);
1174 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1175 pfAttribs.push_back(bitVec[2]);
1176 pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1177 pfAttribs.push_back(bitVec[3]);
1178 #elif defined( __APPLE__ )
1179 pfAttribs.push_back(AGL_RED_SIZE);
1180 pfAttribs.push_back(bitVec[0]);
1181 pfAttribs.push_back(AGL_GREEN_SIZE);
1182 pfAttribs.push_back(bitVec[1]);
1183 pfAttribs.push_back(AGL_BLUE_SIZE);
1184 pfAttribs.push_back(bitVec[2]);
1185 pfAttribs.push_back(AGL_ALPHA_SIZE);
1186 pfAttribs.push_back(bitVec[3]);
1188 pfAttribs.push_back(GLX_RED_SIZE);
1189 pfAttribs.push_back(bitVec[0]);
1190 pfAttribs.push_back(GLX_GREEN_SIZE);
1191 pfAttribs.push_back(bitVec[1]);
1192 pfAttribs.push_back(GLX_BLUE_SIZE);
1193 pfAttribs.push_back(bitVec[2]);
1194 pfAttribs.push_back(GLX_ALPHA_SIZE);
1195 pfAttribs.push_back(bitVec[3]);
1197 _iNumComponents = 4;
1200 else if (kv.first == "rgba")
1201 SG_LOG(SG_GL, SG_ALERT,
1202 "RenderTexture Warning: mistake in components definition "
1203 "(rgba + " << _iNumComponents << ").");
1205 if (kv.first == "r" && (_iNumComponents <= 1))
1207 if (kv.second.find("f") != kv.second.npos)
1210 vector<int> bitVec = _ParseBitVector(kv.second);
1213 pfAttribs.push_back(WGL_RED_BITS_ARB);
1214 pfAttribs.push_back(bitVec[0]);
1215 #elif defined( __APPLE__ )
1216 pfAttribs.push_back(AGL_RED_SIZE);
1217 pfAttribs.push_back(bitVec[0]);
1219 pfAttribs.push_back(GLX_RED_SIZE);
1220 pfAttribs.push_back(bitVec[0]);
1225 else if (kv.first == "r")
1226 SG_LOG(SG_GL, SG_ALERT,
1227 "RenderTexture Warning: mistake in components definition "
1228 "(r + " << _iNumComponents << ").");
1230 if (kv.first == "rg" && (_iNumComponents <= 1))
1232 if (kv.second.find("f") != kv.second.npos)
1235 vector<int> bitVec = _ParseBitVector(kv.second);
1237 if (bitVec.size() < 2) // expand the scalar to a vector
1239 bitVec.push_back(bitVec[0]);
1243 pfAttribs.push_back(WGL_RED_BITS_ARB);
1244 pfAttribs.push_back(bitVec[0]);
1245 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1246 pfAttribs.push_back(bitVec[1]);
1247 #elif defined( __APPLE__ )
1248 pfAttribs.push_back(AGL_RED_SIZE);
1249 pfAttribs.push_back(bitVec[0]);
1250 pfAttribs.push_back(AGL_GREEN_SIZE);
1251 pfAttribs.push_back(bitVec[1]);
1253 pfAttribs.push_back(GLX_RED_SIZE);
1254 pfAttribs.push_back(bitVec[0]);
1255 pfAttribs.push_back(GLX_GREEN_SIZE);
1256 pfAttribs.push_back(bitVec[1]);
1258 _iNumComponents += 2;
1261 else if (kv.first == "rg")
1262 SG_LOG(SG_GL, SG_ALERT,
1263 "RenderTexture Warning: mistake in components definition "
1264 "(rg + " << _iNumComponents << ").");
1266 if (kv.first == "depth")
1268 if (kv.second == "")
1271 iDepthBits = strtol(kv.second.c_str(), 0, 10);
1275 if (kv.first == "stencil")
1279 pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1280 #elif defined( __APPLE__ )
1281 pfAttribs.push_back(AGL_STENCIL_SIZE);
1283 pfAttribs.push_back(GLX_STENCIL_SIZE);
1285 if (kv.second == "")
1286 pfAttribs.push_back(8);
1288 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1292 if (kv.first == "samples")
1295 pfAttribs.push_back(WGL_SAMPLE_BUFFERS_ARB);
1296 pfAttribs.push_back(1);
1297 pfAttribs.push_back(WGL_SAMPLES_ARB);
1298 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1299 #elif defined( __APPLE__ )
1300 pfAttribs.push_back(AGL_SAMPLE_BUFFERS_ARB);
1301 pfAttribs.push_back(1);
1302 pfAttribs.push_back(AGL_SAMPLES_ARB);
1303 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1305 pfAttribs.push_back(GLX_SAMPLE_BUFFERS_ARB);
1306 pfAttribs.push_back(1);
1307 pfAttribs.push_back(GLX_SAMPLES_ARB);
1308 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1314 if (kv.first == "doublebuffer" || kv.first == "double")
1317 pfAttribs.push_back(WGL_DOUBLE_BUFFER_ARB);
1318 pfAttribs.push_back(true);
1319 #elif defined( __APPLE__ )
1320 pfAttribs.push_back(AGL_DOUBLEBUFFER);
1321 pfAttribs.push_back(True);
1323 pfAttribs.push_back(GLX_DOUBLEBUFFER);
1324 pfAttribs.push_back(True);
1329 if (kv.first == "aux")
1332 pfAttribs.push_back(WGL_AUX_BUFFERS_ARB);
1333 #elif defined( __APPLE__ )
1334 pfAttribs.push_back(AGL_AUX_BUFFERS);
1336 pfAttribs.push_back(GLX_AUX_BUFFERS);
1338 if (kv.second == "")
1339 pfAttribs.push_back(0);
1341 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1345 if (token.find("tex") == 0)
1349 if ((kv.first == "texRECT") && GL_NV_texture_rectangle)
1354 else if (kv.first == "texCUBE")
1366 if (token.find("depthTex") == 0)
1368 _bIsDepthTexture = true;
1370 if ((kv.first == "depthTexRECT") && GL_NV_texture_rectangle)
1375 else if (kv.first == "depthTexCUBE")
1387 if (kv.first == "mipmap")
1393 if (kv.first == "rtt")
1395 _eUpdateMode = RT_RENDER_TO_TEXTURE;
1399 if (kv.first == "ctt")
1401 _eUpdateMode = RT_COPY_TO_TEXTURE;
1405 SG_LOG(SG_GL, SG_ALERT,
1406 "RenderTexture Error: Unknown pbuffer attribute: " <<
1410 // Processing of some options must be last because of interactions.
1412 // Check for inconsistent texture targets
1413 if (_bIsTexture && _bIsDepthTexture && !(bBind2D ^ bBindRECT ^ bBindCUBE))
1415 SG_LOG(SG_GL, SG_ALERT,
1416 "RenderTexture Warning: Depth and Color texture targets "
1420 // Apply default bit format if none specified
1422 if (0 == _iNumComponents)
1424 pfAttribs.push_back(WGL_RED_BITS_ARB);
1425 pfAttribs.push_back(8);
1426 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1427 pfAttribs.push_back(8);
1428 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1429 pfAttribs.push_back(8);
1430 pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1431 pfAttribs.push_back(8);
1432 _iNumComponents = 4;
1437 if (_bIsDepthTexture && !iDepthBits)
1441 pfAttribs.push_back(WGL_DEPTH_BITS_ARB);
1442 #elif defined( __APPLE__ )
1443 pfAttribs.push_back(AGL_DEPTH_SIZE);
1445 pfAttribs.push_back(GLX_DEPTH_SIZE);
1447 pfAttribs.push_back(iDepthBits); // default
1452 pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1453 pfAttribs.push_back(0);
1454 #elif defined( __APPLE__ )
1455 pfAttribs.push_back(AGL_STENCIL_SIZE);
1456 pfAttribs.push_back(0);
1458 pfAttribs.push_back(GLX_STENCIL_SIZE);
1459 pfAttribs.push_back(0);
1463 if (_iNumComponents < 4)
1465 // Can't do this right now -- on NVIDIA drivers, currently get
1466 // a non-functioning pbuffer if ALPHA_BITS=0 and
1467 // WGL_BIND_TO_TEXTURE_RGB_ARB=true
1469 //pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1470 //pfAttribs.push_back(0);
1474 if (!WGL_NV_render_depth_texture && _bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1476 #if defined(DEBUG) || defined(_DEBUG)
1477 SG_LOG(SG_GL, SG_ALERT, "RenderTexture Warning: No support found for "
1478 "render to depth texture.");
1480 _bIsDepthTexture = false;
1484 if ((_bIsTexture || _bIsDepthTexture) &&
1485 (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1490 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1491 pbAttribs.push_back(WGL_TEXTURE_RECTANGLE_NV);
1495 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1496 pbAttribs.push_back(WGL_TEXTURE_CUBE_MAP_ARB);
1500 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1501 pbAttribs.push_back(WGL_TEXTURE_2D_ARB);
1506 pbAttribs.push_back(WGL_MIPMAP_TEXTURE_ARB);
1507 pbAttribs.push_back(true);
1510 #elif defined(DEBUG) || defined(_DEBUG)
1511 SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: Render to Texture not "
1512 "supported in Linux or MacOS");
1516 // Set the pixel type
1520 if (WGL_NV_float_buffer)
1522 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1523 pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1525 pfAttribs.push_back(WGL_FLOAT_COMPONENTS_NV);
1526 pfAttribs.push_back(true);
1530 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1531 pfAttribs.push_back(WGL_TYPE_RGBA_FLOAT_ATI);
1533 #elif defined( __APPLE__ )
1535 if (GLX_NV_float_buffer)
1537 pfAttribs.push_back(GLX_FLOAT_COMPONENTS_NV);
1538 pfAttribs.push_back(1);
1545 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1546 pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1550 // Set up texture binding for render to texture
1551 if (_bIsTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1557 if (WGL_NV_float_buffer)
1559 switch(_iNumComponents)
1562 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
1563 pfAttribs.push_back(true);
1565 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1566 pbAttribs.push_back(WGL_TEXTURE_FLOAT_R_NV);
1569 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
1570 pfAttribs.push_back(true);
1572 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1573 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RG_NV);
1576 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
1577 pfAttribs.push_back(true);
1579 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1580 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGB_NV);
1583 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
1584 pfAttribs.push_back(true);
1586 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1587 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGBA_NV);
1590 SG_LOG(SG_GL, SG_ALERT,
1591 "RenderTexture Warning: Bad number of components "
1592 "(r=1,rg=2,rgb=3,rgba=4): " <<
1599 if (4 == _iNumComponents)
1601 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1602 pfAttribs.push_back(true);
1604 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1605 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1609 // standard ARB_render_texture only supports 3 or 4 channels
1610 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1611 pfAttribs.push_back(true);
1613 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1614 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1621 switch(_iNumComponents)
1624 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1625 pfAttribs.push_back(true);
1627 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1628 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1631 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1632 pfAttribs.push_back(true);
1634 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1635 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1638 SG_LOG(SG_GL, SG_ALERT,
1639 "RenderTexture Warning: Bad number of components "
1640 "(r=1,rg=2,rgb=3,rgba=4): " << _iNumComponents);
1644 #elif defined(DEBUG) || defined(_DEBUG)
1645 SG_LOG(SG_GL, SG_ALERT,
1646 "RenderTexture Error: Render to Texture not supported in "
1647 "Linux or MacOS\ n");
1651 if (_bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1656 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV);
1657 pfAttribs.push_back(true);
1659 pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
1660 pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
1664 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_DEPTH_NV);
1665 pfAttribs.push_back(true);
1667 pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
1668 pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
1670 #elif defined(DEBUG) || defined(_DEBUG)
1671 SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: Render to Texture not supported in "
1677 //---------------------------------------------------------------------------
1678 // Function : RenderTexture::_GetKeyValuePair
1680 //---------------------------------------------------------------------------
1682 * @fn RenderTexture::_GetKeyValuePair()
1683 * @brief Parses expressions of the form "X=Y" into a pair (X,Y).
1685 RenderTexture::KeyVal RenderTexture::_GetKeyValuePair(string token)
1687 string::size_type pos = 0;
1688 if ((pos = token.find("=")) != token.npos)
1690 string key = token.substr(0, pos);
1691 string value = token.substr(pos+1, token.length()-pos+1);
1692 return KeyVal(key, value);
1695 return KeyVal(token, "");
1698 //---------------------------------------------------------------------------
1699 // Function : RenderTexture::_ParseBitVector
1701 //---------------------------------------------------------------------------
1703 * @fn RenderTexture::_ParseBitVector()
1704 * @brief Parses expressions of the form "=r,g,b,a" into a vector: (r,g,b,a)
1706 vector<int> RenderTexture::_ParseBitVector(string bitVector)
1708 vector<string> pieces;
1711 if (bitVector == "")
1713 bits.push_back(8); // if a depth isn't specified, use default 8 bits
1717 string::size_type pos = 0;
1718 string::size_type nextpos = 0;
1721 nextpos = bitVector.find_first_of(", ", pos);
1722 pieces.push_back(string(bitVector, pos, nextpos - pos));
1724 } while (nextpos != bitVector.npos );
1726 for ( vector<string>::iterator it = pieces.begin(); it != pieces.end(); it++)
1728 bits.push_back(strtol(it->c_str(), 0, 10));
1734 //---------------------------------------------------------------------------
1735 // Function : RenderTexture::_VerifyExtensions
1737 //---------------------------------------------------------------------------
1739 * @fn RenderTexture::_VerifyExtensions()
1740 * @brief Checks that the necessary extensions are available based on RT mode.
1742 bool RenderTexture::_VerifyExtensions()
1745 // a second call to _VerifyExtensions will allways return true, causing a crash
1746 // if the extension is not supported
1747 if ( true || !fctPtrInited )
1749 fctPtrInited = true;
1750 wglGetExtensionsStringARBProc wglGetExtensionsStringARBPtr = (wglGetExtensionsStringARBProc)wglGetProcAddress( "wglGetExtensionsStringARB" );
1751 if ( wglGetExtensionsStringARBPtr == 0 )
1753 PrintExtensionError("WGL_ARB_extensions_string");
1756 string wglExtensionsString = wglGetExtensionsStringARBPtr( wglGetCurrentDC() );
1757 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pixel_format" ) )
1759 wglChoosePixelFormatARBPtr = (wglChoosePixelFormatARBProc)SGLookupFunction("wglChoosePixelFormatARB");
1760 wglGetPixelFormatAttribivARBPtr = (wglGetPixelFormatAttribivARBProc)SGLookupFunction("wglGetPixelFormatAttribivARB");
1764 PrintExtensionError("WGL_ARB_pixel_format");
1767 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pbuffer" ) )
1769 wglCreatePbufferARBPtr = (wglCreatePbufferARBProc)SGLookupFunction("wglCreatePbufferARB");
1770 wglGetPbufferDCARBPtr = (wglGetPbufferDCARBProc)SGLookupFunction("wglGetPbufferDCARB");
1771 wglQueryPbufferARBPtr = (wglQueryPbufferARBProc)SGLookupFunction("wglQueryPbufferARB");
1772 wglReleasePbufferDCARBPtr = (wglReleasePbufferDCARBProc)SGLookupFunction("wglReleasePbufferDCARB");
1773 wglDestroyPbufferARBPtr = (wglDestroyPbufferARBProc)SGLookupFunction("wglDestroyPbufferARB");
1777 PrintExtensionError("WGL_ARB_pbuffer");
1780 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_render_texture" ) )
1782 wglBindTexImageARBPtr = (wglBindTexImageARBProc)SGLookupFunction("wglBindTexImageARB");
1783 wglReleaseTexImageARBPtr = (wglReleaseTexImageARBProc)SGLookupFunction("wglReleaseTexImageARB");
1785 else if ( _bIsTexture )
1787 PrintExtensionError("WGL_ARB_render_texture");
1790 if (_bRectangle && !SGIsOpenGLExtensionSupported( "GL_NV_texture_rectangle" ))
1792 PrintExtensionError("GL_NV_texture_rectangle");
1795 if (_bFloat && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) ||
1796 SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ATI_pixel_format_float" )))
1798 PrintExtensionError("GL_NV_float_buffer or GL_ATI_pixel_format_float");
1802 if (_bFloat && _bIsTexture && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) || SGIsOpenGLExtensionSupported( "GL_ATI_texture_float" )))
1804 PrintExtensionError("NV_float_buffer or ATI_texture_float");
1806 if (_bIsDepthTexture && !SGIsOpenGLExtensionSupported( "GL_ARB_depth_texture" ))
1809 #if defined(_DEBUG) | defined(DEBUG)
1810 SG_LOG(SG_GL, SG_ALERT,
1811 "RenderTexture Warning: "
1812 "OpenGL extension GL_ARB_depth_texture not available."
1813 " Using glReadPixels() to emulate behavior.");
1815 _bHasARBDepthTexture = false;
1816 //PrintExtensionError("GL_ARB_depth_texture");
1822 #elif defined( __APPLE__ )
1824 Display* dpy = glXGetCurrentDisplay();
1825 int minor = 0, major = 0;
1826 if (!glXQueryVersion(dpy, &major, &minor))
1829 int screen = DefaultScreen(dpy);
1830 const char* extString = glXQueryExtensionsString(dpy, screen);
1831 if (!SGSearchExtensionsString(extString, "GLX_SGIX_fbconfig") ||
1832 !SGSearchExtensionsString(extString, "GLX_SGIX_pbuffer"))
1835 // First try the glX version 1.3 functions.
1836 glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfig");
1837 glXCreatePbufferPtr = (glXCreatePbufferProc)SGLookupFunction("glXCreatePbuffer");
1838 glXGetVisualFromFBConfigPtr = (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfig");
1839 glXCreateContextPtr = (glXCreateContextProc)SGLookupFunction("glXCreateContext");
1840 glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyPbuffer");
1841 glXQueryDrawablePtr = (glXQueryDrawableProc)SGLookupFunction("glXQueryDrawable");
1843 if (((1 <= major && 3 <= minor) || 2 <= major) &&
1844 glXChooseFBConfigPtr &&
1845 glXCreatePbufferPtr &&
1846 glXGetVisualFromFBConfigPtr &&
1847 glXCreateContextPtr &&
1848 glXDestroyPbufferPtr &&
1849 glXQueryDrawablePtr)
1850 glXVersion1_3Present = true;
1853 glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfigSGIX");
1854 glXCreateGLXPbufferPtr = (glXCreateGLXPbufferProc)SGLookupFunction("glXCreateGLXPbufferSGIX");
1855 glXGetVisualFromFBConfigPtr = (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfigSGIX");
1856 glXCreateContextWithConfigPtr = (glXCreateContextWithConfigProc)SGLookupFunction("glXCreateContextWithConfigSGIX");
1857 glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyGLXPbufferSGIX");
1858 glXQueryGLXPbufferSGIXPtr = (glXQueryGLXPbufferSGIXProc)SGLookupFunction("glXQueryGLXPbufferSGIX");
1861 if (!glXChooseFBConfigPtr ||
1862 !glXCreateGLXPbufferPtr ||
1863 !glXGetVisualFromFBConfigPtr ||
1864 !glXCreateContextWithConfigPtr ||
1865 !glXDestroyPbufferPtr ||
1866 !glXQueryGLXPbufferSGIXPtr)
1870 if (_bIsDepthTexture && !GL_ARB_depth_texture)
1872 PrintExtensionError("GL_ARB_depth_texture");
1875 if (_bFloat && _bIsTexture && !GLX_NV_float_buffer)
1877 PrintExtensionError("GLX_NV_float_buffer");
1880 if (_eUpdateMode == RT_RENDER_TO_TEXTURE)
1882 PrintExtensionError("Some GLX render texture extension: Please implement me!");
1890 //---------------------------------------------------------------------------
1891 // Function : RenderTexture::_InitializeTextures
1893 //---------------------------------------------------------------------------
1895 * @fn RenderTexture::_InitializeTextures()
1896 * @brief Initializes the state of textures used by the RenderTexture.
1898 bool RenderTexture::_InitializeTextures()
1900 // Determine the appropriate texture formats and filtering modes.
1901 if (_bIsTexture || _bIsDepthTexture)
1903 if (_bRectangle && GL_NV_texture_rectangle)
1904 _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
1906 _iTextureTarget = GL_TEXTURE_2D;
1911 glGenTextures(1, (GLuint*)&_iTextureID);
1912 glBindTexture(_iTextureTarget, _iTextureID);
1914 // Use clamp to edge as the default texture wrap mode for all tex
1915 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1916 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1917 // Use NEAREST as the default texture filtering mode.
1918 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1919 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1922 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
1924 GLuint iInternalFormat;
1931 SG_LOG(SG_GL, SG_ALERT,
1932 "RenderTexture Error: mipmapped float textures not "
1937 switch(_iNumComponents)
1940 if (GL_NV_float_buffer)
1942 iInternalFormat = (_iNumColorBits[0] > 16) ?
1943 GL_FLOAT_R32_NV : GL_FLOAT_R16_NV;
1945 else if (GL_ATI_texture_float)
1947 iInternalFormat = (_iNumColorBits[0] > 16) ?
1948 GL_LUMINANCE_FLOAT32_ATI :
1949 GL_LUMINANCE_FLOAT16_ATI;
1951 iFormat = GL_LUMINANCE;
1954 if (GL_NV_float_buffer)
1956 iInternalFormat = (_iNumColorBits[0] > 16) ?
1957 GL_FLOAT_RG32_NV : GL_FLOAT_RG16_NV;
1959 else if (GL_ATI_texture_float)
1961 iInternalFormat = (_iNumColorBits[0] > 16) ?
1962 GL_LUMINANCE_ALPHA_FLOAT32_ATI :
1963 GL_LUMINANCE_ALPHA_FLOAT16_ATI;
1965 iFormat = GL_LUMINANCE_ALPHA;
1968 if (GL_NV_float_buffer)
1970 iInternalFormat = (_iNumColorBits[0] > 16) ?
1971 GL_FLOAT_RGB32_NV : GL_FLOAT_RGB16_NV;
1973 else if (GL_ATI_texture_float)
1975 iInternalFormat = (_iNumColorBits[0] > 16) ?
1976 GL_RGB_FLOAT32_ATI : GL_RGB_FLOAT16_ATI;
1981 if (GL_NV_float_buffer)
1983 iInternalFormat = (_iNumColorBits[0] > 16) ?
1984 GL_FLOAT_RGBA32_NV : GL_FLOAT_RGBA16_NV;
1986 else if (GL_ATI_texture_float)
1988 iInternalFormat = (_iNumColorBits[0] > 16) ?
1989 GL_RGBA_FLOAT32_ATI : GL_RGBA_FLOAT16_ATI;
1994 SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: "
1995 "Invalid number of components: " <<
2002 if (4 == _iNumComponents)
2004 iInternalFormat = GL_RGBA8;
2009 iInternalFormat = GL_RGB8;
2014 // Allocate the texture image (but pass it no data for now).
2015 glTexImage2D(_iTextureTarget, 0, iInternalFormat,
2016 _iWidth, _iHeight, 0, iFormat, GL_FLOAT, NULL);
2020 if (_bIsDepthTexture)
2022 glGenTextures(1, (GLuint*)&_iDepthTextureID);
2023 glBindTexture(_iTextureTarget, _iDepthTextureID);
2025 // Use clamp to edge as the default texture wrap mode for all tex
2026 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2027 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2028 // Use NEAREST as the default texture filtering mode.
2029 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2030 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2032 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2035 if (_bHasARBDepthTexture)
2037 // Allocate the texture image (but pass it no data for now).
2038 glTexImage2D(_iTextureTarget, 0, GL_DEPTH_COMPONENT,
2039 _iWidth, _iHeight, 0, GL_DEPTH_COMPONENT,
2044 // allocate memory for depth texture
2045 // Since this is slow, we warn the user in debug mode. (above)
2046 _pPoorDepthTexture = new unsigned short[_iWidth * _iHeight];
2047 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
2048 _iWidth, _iHeight, 0, GL_LUMINANCE,
2049 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2059 //---------------------------------------------------------------------------
2060 // Function : RenderTexture::_MaybeCopyBuffer
2062 //---------------------------------------------------------------------------
2064 * @fn RenderTexture::_MaybeCopyBuffer()
2065 * @brief Does the actual copying for RenderTextures with RT_COPY_TO_TEXTURE
2067 void RenderTexture::_MaybeCopyBuffer()
2070 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2074 glBindTexture(_iTextureTarget, _iTextureID);
2075 glCopyTexSubImage2D(_iTextureTarget,
2076 0, 0, 0, 0, 0, _iWidth, _iHeight);
2078 if (_bIsDepthTexture)
2080 glBindTexture(_iTextureTarget, _iDepthTextureID);
2081 // HOW TO COPY DEPTH TEXTURE??? Supposedly this just magically works...
2083 if (_bHasARBDepthTexture)
2085 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0,
2090 // no 'real' depth texture available, so behavior has to be emulated
2091 // using glReadPixels (beware, this is (naturally) slow ...)
2092 glReadPixels(0, 0, _iWidth, _iHeight, GL_DEPTH_COMPONENT,
2093 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2094 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
2095 _iWidth, _iHeight, 0, GL_LUMINANCE,
2096 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2105 glBindTexture(_iTextureTarget, _iTextureID);
2106 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2108 if (_bIsDepthTexture)
2110 glBindTexture(_iTextureTarget, _iDepthTextureID);
2111 assert(_bHasARBDepthTexture);
2112 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2118 //---------------------------------------------------------------------------
2119 // Function : RenderTexture::_ReleaseBoundBuffers
2121 //---------------------------------------------------------------------------
2123 * @fn RenderTexture::_ReleaseBoundBuffers()
2124 * @brief Releases buffer bindings on RenderTextures with RT_RENDER_TO_TEXTURE
2126 bool RenderTexture::_ReleaseBoundBuffers()
2129 if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2131 glBindTexture(_iTextureTarget, _iTextureID);
2133 // release the pbuffer from the render texture object
2134 if (0 != _iCurrentBoundBuffer && _bIsBufferBound)
2136 if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, _iCurrentBoundBuffer))
2141 _bIsBufferBound = false;
2145 if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2147 glBindTexture(_iTextureTarget, _iDepthTextureID);
2149 // release the pbuffer from the render texture object
2150 if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
2158 // textures can't be bound in Linux
2163 //---------------------------------------------------------------------------
2164 // Function : RenderTexture::_MakeCurrent
2166 //---------------------------------------------------------------------------
2168 * @fn RenderTexture::_MakeCurrent()
2169 * @brief Makes the RenderTexture's context current
2172 bool RenderTexture::_MakeCurrent()
2175 // make the pbuffer's rendering context current.
2176 if (FALSE == wglMakeCurrent( _hDC, _hGLContext))
2181 #elif defined( __APPLE__ )
2183 if (false == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
2192 /////////////////////////////////////////////////////////////////////////////
2194 // Begin Deprecated Interface
2196 /////////////////////////////////////////////////////////////////////////////
2198 //---------------------------------------------------------------------------
2199 // Function : RenderTexture::RenderTexture
2201 //---------------------------------------------------------------------------
2203 * @fn RenderTexture::RenderTexture()
2204 * @brief Constructor.
2206 RenderTexture::RenderTexture(int width, int height,
2207 bool bIsTexture /* = true */,
2208 bool bIsDepthTexture /* = false */)
2211 _bIsTexture(bIsTexture),
2212 _bIsDepthTexture(bIsDepthTexture),
2213 _bHasARBDepthTexture(true), // [Redge]
2214 _eUpdateMode(RT_RENDER_TO_TEXTURE),
2215 _bInitialized(false),
2217 _iCurrentBoundBuffer(0),
2219 _iNumStencilBits(0),
2220 _bDoubleBuffered(false),
2225 _bShareObjects(false),
2226 _bCopyContext(false),
2232 _hPreviousContext(0),
2233 #elif defined( __APPLE__ )
2238 _hPreviousContext(0),
2239 _hPreviousDrawable(0),
2241 _iTextureTarget(GL_NONE),
2243 _iDepthTextureID(0),
2244 _pPoorDepthTexture(0) // [Redge]
2246 assert(width > 0 && height > 0);
2247 #if defined DEBUG || defined _DEBUG
2248 SG_LOG(SG_GL, SG_ALERT,
2249 "RenderTexture Warning: Deprecated Contructor interface used.");
2252 _iNumColorBits[0] = _iNumColorBits[1] =
2253 _iNumColorBits[2] = _iNumColorBits[3] = 0;
2254 _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
2257 //------------------------------------------------------------------------------
2258 // Function : RenderTexture::Initialize
2260 //------------------------------------------------------------------------------
2262 * @fn RenderTexture::Initialize(bool bShare, bool bDepth, bool bStencil, bool bMipmap, unsigned int iRBits, unsigned int iGBits, unsigned int iBBits, unsigned int iABits);
2263 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
2265 * This function actually does the creation of the p-buffer. It can only be called
2266 * once a GL context has already been created. Note that if the texture is not
2267 * power of two dimensioned, or has more than 8 bits per channel, enabling mipmapping
2268 * will cause an error.
2270 bool RenderTexture::Initialize(bool bShare /* = true */,
2271 bool bDepth /* = false */,
2272 bool bStencil /* = false */,
2273 bool bMipmap /* = false */,
2274 bool bAnisoFilter /* = false */,
2275 unsigned int iRBits /* = 8 */,
2276 unsigned int iGBits /* = 8 */,
2277 unsigned int iBBits /* = 8 */,
2278 unsigned int iABits /* = 8 */,
2279 UpdateMode updateMode /* = RT_RENDER_TO_TEXTURE */)
2281 if (0 == _iWidth || 0 == _iHeight)
2284 #if defined DEBUG || defined _DEBUG
2285 SG_LOG(SG_GL, SG_ALERT,
2286 "RenderTexture Warning: Deprecated Initialize() interface used.");
2289 // create a mode string.
2292 mode.append("depth ");
2294 mode.append("stencil ");
2296 mode.append("mipmap ");
2297 if (iRBits + iGBits + iBBits + iABits > 0)
2308 char bitVector[100];
2309 snprintf( bitVector, 100,
2310 "%d%s,%d%s,%d%s,%d%s",
2311 iRBits, (iRBits >= 16) ? "f" : "",
2312 iGBits, (iGBits >= 16) ? "f" : "",
2313 iBBits, (iBBits >= 16) ? "f" : "",
2314 iABits, (iABits >= 16) ? "f" : "");
2315 mode.append(bitVector);
2320 if (GL_NV_texture_rectangle &&
2321 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2322 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2323 mode.append("texRECT ");
2325 mode.append("tex2D ");
2327 if (_bIsDepthTexture)
2329 if (GL_NV_texture_rectangle &&
2330 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2331 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2332 mode.append("texRECT ");
2334 mode.append("tex2D ");
2336 if (RT_COPY_TO_TEXTURE == updateMode)
2339 _pixelFormatAttribs.clear();
2340 _pbufferAttribs.clear();
2343 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
2344 _pixelFormatAttribs.push_back(true);
2345 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
2346 _pixelFormatAttribs.push_back(true);
2348 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
2349 _pbufferAttribs.push_back(true);
2350 #elif defined( __APPLE__ )
2352 _pixelFormatAttribs.push_back(GLX_RENDER_TYPE_SGIX);
2353 _pixelFormatAttribs.push_back(GLX_RGBA_BIT_SGIX);
2354 _pixelFormatAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
2355 _pixelFormatAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
2358 _ParseModeString(mode.c_str(), _pixelFormatAttribs, _pbufferAttribs);
2361 _pixelFormatAttribs.push_back(0);
2362 _pbufferAttribs.push_back(0);
2364 _pixelFormatAttribs.push_back(None);
2367 Initialize(_iWidth, _iHeight, bShare);
2373 //---------------------------------------------------------------------------
2374 // Function : RenderTexture::Reset
2376 //---------------------------------------------------------------------------
2378 * @fn RenderTexture::Reset(int iWidth, int iHeight, unsigned int iMode, bool bIsTexture, bool bIsDepthTexture)
2379 * @brief Resets the resolution of the offscreen buffer.
2381 * Causes the buffer to delete itself. User must call Initialize() again
2384 bool RenderTexture::Reset(int iWidth, int iHeight)
2386 SG_LOG(SG_GL, SG_ALERT,
2387 "RenderTexture Warning: Deprecated Reset() interface used.");
2391 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Reset(): failed to invalidate.");