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
49 # include <simgear_config.h>
56 #include <simgear/compiler.h>
57 #include <simgear/screen/extensions.hxx>
58 #include <simgear/screen/RenderTexture.h>
66 #pragma comment(lib, "gdi32.lib") // required for GetPixelFormat()
72 static bool fctPtrInited = false;
73 /* WGL_ARB_pixel_format */
74 static wglChoosePixelFormatARBProc wglChoosePixelFormatARBPtr = 0;
75 static wglGetPixelFormatAttribivARBProc wglGetPixelFormatAttribivARBPtr = 0;
77 static wglCreatePbufferARBProc wglCreatePbufferARBPtr = 0;
78 static wglGetPbufferDCARBProc wglGetPbufferDCARBPtr = 0;
79 static wglQueryPbufferARBProc wglQueryPbufferARBPtr = 0;
80 static wglReleasePbufferDCARBProc wglReleasePbufferDCARBPtr = 0;
81 static wglDestroyPbufferARBProc wglDestroyPbufferARBPtr = 0;
82 /* WGL_ARB_render_texture */
83 static wglBindTexImageARBProc wglBindTexImageARBPtr = 0;
84 static wglReleaseTexImageARBProc wglReleaseTexImageARBPtr = 0;
86 #elif defined( __APPLE__ )
88 static bool glXVersion1_3Present = false;
89 static glXChooseFBConfigProc glXChooseFBConfigPtr = 0;
90 static glXCreateGLXPbufferProc glXCreateGLXPbufferPtr = 0;
91 static glXGetVisualFromFBConfigProc glXGetVisualFromFBConfigPtr = 0;
92 static glXCreateContextWithConfigProc glXCreateContextWithConfigPtr = 0;
93 static glXCreateContextProc glXCreateContextPtr = 0;
94 static glXDestroyPbufferProc glXDestroyPbufferPtr = 0;
95 static glXQueryDrawableProc glXQueryDrawablePtr = 0;
96 static glXQueryGLXPbufferSGIXProc glXQueryGLXPbufferSGIXPtr = 0;
99 //---------------------------------------------------------------------------
100 // Function : RenderTexture::RenderTexture
102 //---------------------------------------------------------------------------
104 * @fn RenderTexture::RenderTexture()
105 * @brief Mode-string-based Constructor.
107 RenderTexture::RenderTexture(const char *strMode)
111 _bIsDepthTexture(false),
112 _bHasARBDepthTexture(true), // [Redge]
114 _eUpdateMode(RT_RENDER_TO_TEXTURE),
116 _eUpdateMode(RT_COPY_TO_TEXTURE),
118 _bInitialized(false),
120 _bIsBufferBound(false),
121 _iCurrentBoundBuffer(0),
125 _bDoubleBuffered(false),
129 _bShareObjects(false),
130 _bCopyContext(false),
136 _hPreviousContext(0),
137 #elif defined( __APPLE__ )
142 _hPreviousContext(0),
143 _hPreviousDrawable(0),
145 _iTextureTarget(GL_NONE),
148 _pPoorDepthTexture(0) // [Redge]
150 _iNumColorBits[0] = _iNumColorBits[1] =
151 _iNumColorBits[2] = _iNumColorBits[3] = 0;
154 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
155 _pixelFormatAttribs.push_back(true);
156 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
157 _pixelFormatAttribs.push_back(true);
159 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
160 _pbufferAttribs.push_back(true);
161 #elif defined( __APPLE__ )
163 _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
164 _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
165 _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
166 _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
169 _ParseModeString(strMode, _pixelFormatAttribs, _pbufferAttribs);
172 _pixelFormatAttribs.push_back(0);
173 _pbufferAttribs.push_back(0);
175 _pixelFormatAttribs.push_back(None);
180 //---------------------------------------------------------------------------
181 // Function : RenderTexture::~RenderTexture
183 //---------------------------------------------------------------------------
185 * @fn RenderTexture::~RenderTexture()
188 RenderTexture::~RenderTexture()
194 //---------------------------------------------------------------------------
195 // Function : _wglGetLastError
197 //---------------------------------------------------------------------------
199 * @fn wglGetLastError()
200 * @brief Returns the last windows error generated.
203 void _wglGetLastError()
207 DWORD err = GetLastError();
210 case ERROR_INVALID_PIXEL_FORMAT:
212 "RenderTexture Win32 Error: ERROR_INVALID_PIXEL_FORMAT\n");
214 case ERROR_NO_SYSTEM_RESOURCES:
216 "RenderTexture Win32 Error: ERROR_NO_SYSTEM_RESOURCES\n");
218 case ERROR_INVALID_DATA:
220 "RenderTexture Win32 Error: ERROR_INVALID_DATA\n");
222 case ERROR_INVALID_WINDOW_HANDLE:
224 "RenderTexture Win32 Error: ERROR_INVALID_WINDOW_HANDLE\n");
226 case ERROR_RESOURCE_TYPE_NOT_FOUND:
228 "RenderTexture Win32 Error: ERROR_RESOURCE_TYPE_NOT_FOUND\n");
235 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
236 FORMAT_MESSAGE_FROM_SYSTEM |
237 FORMAT_MESSAGE_IGNORE_INSERTS,
240 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
245 fprintf(stderr, "RenderTexture Win32 Error %d: %s\n", err, lpMsgBuf);
246 LocalFree( lpMsgBuf );
255 //---------------------------------------------------------------------------
256 // Function : PrintExtensionError
258 //---------------------------------------------------------------------------
260 * @fn PrintExtensionError( char* strMsg, ... )
261 * @brief Prints an error about missing OpenGL extensions.
263 void PrintExtensionError( char* strMsg, ... )
266 "Error: RenderTexture requires the following unsupported "
267 "OpenGL extensions: \n");
270 va_start(args, strMsg);
271 #if defined _WIN32 && !defined __CYGWIN__
272 _vsnprintf( strBuffer, 512, strMsg, args );
274 vsnprintf( strBuffer, 512, strMsg, args );
278 fprintf(stderr, strMsg);
282 //---------------------------------------------------------------------------
283 // Function : RenderTexture::Initialize
285 //---------------------------------------------------------------------------
287 * @fn RenderTexture::Initialize(int width, int height, bool shareObjects, bool copyContext);
288 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
290 * This function creates of the p-buffer. It can only be called once a GL
291 * context has already been created.
293 bool RenderTexture::Initialize(int width, int height,
294 bool shareObjects /* = true */,
295 bool copyContext /* = false */)
297 assert(width > 0 && height > 0);
299 _iWidth = width; _iHeight = height;
300 _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
302 _bShareObjects = shareObjects;
303 _bCopyContext = copyContext;
305 // Check if this is an NVXX GPU and verify necessary extensions.
306 if (!_VerifyExtensions())
313 // Get the current context.
314 HDC hdc = wglGetCurrentDC();
317 HGLRC hglrc = wglGetCurrentContext();
322 unsigned int iNumFormats;
326 // Get the pixel format for the on-screen window.
327 iFormat = GetPixelFormat(hdc);
331 "RenderTexture Error: GetPixelFormat() failed.\n");
337 if (!wglChoosePixelFormatARBPtr(hdc, &_pixelFormatAttribs[0], NULL,
338 1, &iFormat, &iNumFormats))
341 "RenderTexture Error: wglChoosePixelFormatARB() failed.\n");
345 if ( iNumFormats <= 0 )
348 "RenderTexture Error: Couldn't find a suitable "
355 // Create the p-buffer.
356 _hPBuffer = wglCreatePbufferARBPtr(hdc, iFormat, _iWidth, _iHeight,
357 &_pbufferAttribs[0]);
361 "RenderTexture Error: wglCreatePbufferARB() failed.\n");
366 // Get the device context.
367 _hDC = wglGetPbufferDCARBPtr( _hPBuffer);
371 "RenderTexture Error: wglGetGetPbufferDCARB() failed.\n");
376 // Create a gl context for the p-buffer.
379 // Let's use the same gl context..
380 // Since the device contexts are compatible (i.e. same pixelformat),
381 // we should be able to use the same gl rendering context.
386 _hGLContext = wglCreateContext( _hDC );
390 "RenderTexture Error: wglCreateContext() failed.\n");
396 // Share lists, texture objects, and program objects.
399 if( !wglShareLists(hglrc, _hGLContext) )
402 "RenderTexture Error: wglShareLists() failed.\n");
408 // Determine the actual width and height we were able to create.
409 wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
410 wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
412 _bInitialized = true;
414 // get the actual number of bits allocated:
415 int attrib = WGL_RED_BITS_ARB;
419 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
421 attrib = WGL_GREEN_BITS_ARB;
423 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
425 attrib = WGL_BLUE_BITS_ARB;
427 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
429 attrib = WGL_ALPHA_BITS_ARB;
431 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
433 attrib = WGL_DEPTH_BITS_ARB;
435 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
437 attrib = WGL_STENCIL_BITS_ARB;
439 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
441 attrib = WGL_DOUBLE_BUFFER_ARB;
443 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
444 ? (value?true:false) : false;
446 #if defined(_DEBUG) | defined(DEBUG)
447 fprintf(stderr, "Created a %dx%d RenderTexture with BPP(%d, %d, %d, %d)",
449 _iNumColorBits[0], _iNumColorBits[1],
450 _iNumColorBits[2], _iNumColorBits[3]);
451 if (_iNumDepthBits) fprintf(stderr, " depth=%d", _iNumDepthBits);
452 if (_iNumStencilBits) fprintf(stderr, " stencil=%d", _iNumStencilBits);
453 if (_bDoubleBuffered) fprintf(stderr, " double buffered");
454 fprintf(stderr, "\n");
457 #elif defined( __APPLE__ )
459 _pDisplay = glXGetCurrentDisplay();
460 GLXContext context = glXGetCurrentContext();
461 int screen = DefaultScreen(_pDisplay);
462 XVisualInfo *visInfo;
464 GLXFBConfig *fbConfigs;
467 fbConfigs = glXChooseFBConfigPtr(_pDisplay, screen,
468 &_pixelFormatAttribs[0], &nConfigs);
470 if (nConfigs == 0 || !fbConfigs)
473 "RenderTexture Error: Couldn't find a suitable pixel format.\n");
477 // Pick the first returned format that will return a pbuffer
478 if (glXVersion1_3Present)
481 GLX_PBUFFER_WIDTH, _iWidth,
482 GLX_PBUFFER_HEIGHT, _iHeight,
483 GLX_LARGEST_PBUFFER, False,
486 for (int i=0;i<nConfigs;i++)
488 _hPBuffer = glXCreatePbuffer(_pDisplay, fbConfigs[i], pbufAttrib);
491 XVisualInfo *visInfo = glXGetVisualFromFBConfig(_pDisplay, fbConfigs[i]);
493 _hGLContext = glXCreateContext(_pDisplay, visInfo,
494 _bShareObjects ? context : NULL,
506 for (int i=0;i<nConfigs;i++)
508 _hPBuffer = glXCreateGLXPbufferPtr(_pDisplay, fbConfigs[i],
509 _iWidth, _iHeight, NULL);
512 _hGLContext = glXCreateContextWithConfigPtr(_pDisplay,
515 _bShareObjects ? context : NULL,
526 "RenderTexture Error: glXCreateGLXPbufferPtr() failed.\n");
533 _hGLContext = glXCreateContext(_pDisplay, visInfo,
534 _bShareObjects ? context : NULL, False);
538 "RenderTexture Error: glXCreateContext() failed.\n");
543 if (!glXVersion1_3Present)
545 glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_WIDTH_SGIX,
547 glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_HEIGHT_SGIX,
551 _bInitialized = true;
553 // XXX Query the color format
558 // Now that the pbuffer is created, allocate any texture objects needed,
559 // and initialize them (for CTT updates only). These must be allocated
560 // in the context of the pbuffer, though, or the RT won't work without
563 if (false == wglMakeCurrent( _hDC, _hGLContext))
568 #elif defined( __APPLE__ )
570 _hPreviousContext = glXGetCurrentContext();
571 _hPreviousDrawable = glXGetCurrentDrawable();
573 if (False == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
579 bool result = _InitializeTextures();
581 BindBuffer(WGL_FRONT_LEFT_ARB);
587 // make the previous rendering context current
588 if (false == wglMakeCurrent( hdc, hglrc))
593 #elif defined( __APPLE__ )
595 if (False == glXMakeCurrent(_pDisplay,
596 _hPreviousDrawable, _hPreviousContext))
600 if (glXVersion1_3Present)
602 GLXDrawable draw = glXGetCurrentDrawable();
603 glXQueryDrawablePtr(_pDisplay, draw, GLX_WIDTH, (unsigned int*)&_iWidth);
604 glXQueryDrawablePtr(_pDisplay, draw, GLX_HEIGHT, (unsigned int*)&_iHeight);
612 //---------------------------------------------------------------------------
613 // Function : RenderTexture::_Invalidate
615 //---------------------------------------------------------------------------
617 * @fn RenderTexture::_Invalidate()
618 * @brief Returns the pbuffer memory to the graphics device.
621 bool RenderTexture::_Invalidate()
623 _iNumColorBits[0] = _iNumColorBits[1] =
624 _iNumColorBits[2] = _iNumColorBits[3] = 0;
626 _iNumStencilBits = 0;
629 glDeleteTextures(1, &_iTextureID);
630 if (_bIsDepthTexture)
633 if (!_bHasARBDepthTexture) delete[] _pPoorDepthTexture;
635 glDeleteTextures(1, &_iDepthTextureID);
641 // Check if we are currently rendering in the pbuffer
642 if (wglGetCurrentContext() == _hGLContext)
645 wglDeleteContext( _hGLContext);
646 wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
647 wglDestroyPbufferARBPtr( _hPBuffer );
651 #elif defined( __APPLE__ )
655 if(glXGetCurrentContext() == _hGLContext)
656 // XXX I don't know if this is right at all
657 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
658 glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
664 // [WVB] do we need to call _ReleaseBoundBuffers() too?
669 //---------------------------------------------------------------------------
670 // Function : RenderTexture::Reset
672 //---------------------------------------------------------------------------
674 * @fn RenderTexture::Reset()
675 * @brief Resets the resolution of the offscreen buffer.
677 * Causes the buffer to delete itself. User must call Initialize() again
680 bool RenderTexture::Reset(const char *strMode, ...)
682 _iWidth = 0; _iHeight = 0;
683 _bIsTexture = false; _bIsDepthTexture = false,
684 _bHasARBDepthTexture = true;
686 _eUpdateMode = RT_RENDER_TO_TEXTURE;
688 _eUpdateMode = RT_COPY_TO_TEXTURE;
690 _bInitialized = false;
692 _bIsBufferBound = false;
693 _iCurrentBoundBuffer = 0;
694 _iNumDepthBits = 0; _iNumStencilBits = 0;
695 _bDoubleBuffered = false;
696 _bFloat = false; _bPowerOf2 = true;
697 _bRectangle = false; _bMipmap = false;
698 _bShareObjects = false; _bCopyContext = false;
699 _iTextureTarget = GL_NONE; _iTextureID = 0;
700 _iDepthTextureID = 0;
701 _pPoorDepthTexture = 0;
702 _pixelFormatAttribs.clear();
703 _pbufferAttribs.clear();
705 if (IsInitialized() && !_Invalidate())
707 fprintf(stderr, "RenderTexture::Reset(): failed to invalidate.\n");
711 _iNumColorBits[0] = _iNumColorBits[1] =
712 _iNumColorBits[2] = _iNumColorBits[3] = 0;
715 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
716 _pixelFormatAttribs.push_back(true);
717 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
718 _pixelFormatAttribs.push_back(true);
720 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
721 _pbufferAttribs.push_back(true);
722 #elif defined( __APPLE__ )
724 _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
725 _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
726 _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
727 _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
732 va_start(args,strMode);
733 #if defined _WIN32 && !defined __CYGWIN__
734 _vsnprintf( strBuffer, 256, strMode, args );
736 vsnprintf( strBuffer, 256, strMode, args );
740 _ParseModeString(strBuffer, _pixelFormatAttribs, _pbufferAttribs);
743 _pixelFormatAttribs.push_back(0);
744 _pbufferAttribs.push_back(0);
746 _pixelFormatAttribs.push_back(None);
751 //------------------------------------------------------------------------------
752 // Function : RenderTexture::Resize
754 //------------------------------------------------------------------------------
756 * @fn RenderTexture::Resize(int iWidth, int iHeight)
757 * @brief Changes the size of the offscreen buffer.
759 * Like Reset() this causes the buffer to delete itself.
760 * But unlike Reset(), this call re-initializes the RenderTexture.
761 * Note that Resize() will not work after calling Reset(), or before
762 * calling Initialize() the first time.
764 bool RenderTexture::Resize(int iWidth, int iHeight)
766 if (!_bInitialized) {
767 fprintf(stderr, "RenderTexture::Resize(): must Initialize() first.\n");
770 if (iWidth == _iWidth && iHeight == _iHeight) {
774 // Do same basic work as _Invalidate, but don't reset all our flags
776 glDeleteTextures(1, &_iTextureID);
777 if (_bIsDepthTexture)
778 glDeleteTextures(1, &_iDepthTextureID);
782 // Check if we are currently rendering in the pbuffer
783 if (wglGetCurrentContext() == _hGLContext)
786 wglDeleteContext( _hGLContext);
787 wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
788 wglDestroyPbufferARBPtr( _hPBuffer );
792 #elif defined( __APPLE__ )
796 if(glXGetCurrentContext() == _hGLContext)
797 // XXX I don't know if this is right at all
798 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
799 glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
804 fprintf(stderr, "RenderTexture::Resize(): failed to resize.\n");
807 _bInitialized = false;
808 return Initialize(iWidth, iHeight, _bShareObjects, _bCopyContext);
811 //---------------------------------------------------------------------------
812 // Function : RenderTexture::BeginCapture
814 //---------------------------------------------------------------------------
816 * @fn RenderTexture::BeginCapture()
817 * @brief Activates rendering to the RenderTexture.
819 bool RenderTexture::BeginCapture()
824 "RenderTexture::BeginCapture(): Texture is not initialized!\n");
828 // cache the current context so we can reset it when EndCapture() is called.
829 _hPreviousDC = wglGetCurrentDC();
830 if (NULL == _hPreviousDC)
832 _hPreviousContext = wglGetCurrentContext();
833 if (NULL == _hPreviousContext)
835 #elif defined( __APPLE__ )
837 _hPreviousContext = glXGetCurrentContext();
838 _hPreviousDrawable = glXGetCurrentDrawable();
841 _ReleaseBoundBuffers();
843 return _MakeCurrent();
847 //---------------------------------------------------------------------------
848 // Function : RenderTexture::EndCapture
850 //---------------------------------------------------------------------------
852 * @fn RenderTexture::EndCapture()
853 * @brief Ends rendering to the RenderTexture.
855 bool RenderTexture::EndCapture()
860 "RenderTexture::EndCapture() : Texture is not initialized!\n");
867 // make the previous rendering context current
868 if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
873 #elif defined( __APPLE__ )
875 if (False == glXMakeCurrent(_pDisplay, _hPreviousDrawable,
882 // rebind the textures to a buffers for RTT
883 BindBuffer(_iCurrentBoundBuffer);
889 //---------------------------------------------------------------------------
890 // Function : RenderTexture::BeginCapture(RenderTexture*)
892 //---------------------------------------------------------------------------
894 * @fn RenderTexture::BeginCapture(RenderTexture* other)
895 * @brief Ends capture of 'other', begins capture on 'this'
897 * When performing a series of operations where you modify one texture after
898 * another, it is more efficient to use this method instead of the equivalent
899 * 'EndCapture'/'BeginCapture' pair. This method switches directly to the
900 * new context rather than changing to the default context, and then to the
903 * RenderTexture doesn't have any mechanism for determining if
904 * 'current' really is currently active, so no error will be thrown
907 bool RenderTexture::BeginCapture(RenderTexture* current)
909 bool bContextReset = false;
911 if (current == this) {
912 return true; // no switch necessary
915 // treat as normal Begin if current is 0.
916 return BeginCapture();
921 "RenderTexture::BeginCapture(RenderTexture*): Texture is not initialized!\n");
924 if (!current->_bInitialized)
927 "RenderTexture::BeginCapture(RenderTexture): 'current' texture is not initialized!\n");
931 // Sync current pbuffer with its CTT texture if necessary
932 current->_MaybeCopyBuffer();
934 // pass along the previous context so we can reset it when
935 // EndCapture() is called.
937 _hPreviousDC = current->_hPreviousDC;
938 if (NULL == _hPreviousDC)
940 _hPreviousContext = current->_hPreviousContext;
941 if (NULL == _hPreviousContext)
943 #elif defined( __APPLE__ )
945 _hPreviousContext = current->_hPreviousContext;
946 _hPreviousDrawable = current->_hPreviousDrawable;
949 // Unbind textures before making context current
950 if (!_ReleaseBoundBuffers())
953 // Make the pbuffer context current
957 // Rebind buffers of initial RenderTexture
958 current->BindBuffer(_iCurrentBoundBuffer);
959 current->_BindDepthBuffer();
966 //---------------------------------------------------------------------------
967 // Function : RenderTexture::Bind
969 //---------------------------------------------------------------------------
971 * @fn RenderTexture::Bind()
972 * @brief Binds RGB texture.
974 void RenderTexture::Bind() const
976 if (_bInitialized && _bIsTexture)
978 glBindTexture(_iTextureTarget, _iTextureID);
983 //---------------------------------------------------------------------------
984 // Function : RenderTexture::BindDepth
986 //---------------------------------------------------------------------------
988 * @fn RenderTexture::BindDepth()
989 * @brief Binds depth texture.
991 void RenderTexture::BindDepth() const
993 if (_bInitialized && _bIsDepthTexture)
995 glBindTexture(_iTextureTarget, _iDepthTextureID);
1000 //---------------------------------------------------------------------------
1001 // Function : RenderTexture::BindBuffer
1003 //---------------------------------------------------------------------------
1005 * @fn RenderTexture::BindBuffer()
1006 * @brief Associate the RTT texture id with 'iBuffer' (e.g. WGL_FRONT_LEFT_ARB)
1008 bool RenderTexture::BindBuffer( int iBuffer )
1010 // Must bind the texture too
1011 if (_bInitialized && _bIsTexture)
1013 glBindTexture(_iTextureTarget, _iTextureID);
1016 if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
1017 (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
1019 if (FALSE == wglBindTexImageARBPtr(_hPBuffer, iBuffer))
1021 // WVB: WGL API considers binding twice to the same buffer
1022 // to be an error. But we don't want to
1023 //_wglGetLastError();
1027 _bIsBufferBound = true;
1028 _iCurrentBoundBuffer = iBuffer;
1036 //---------------------------------------------------------------------------
1037 // Function : RenderTexture::BindBuffer
1039 //---------------------------------------------------------------------------
1041 * @fn RenderTexture::_BindDepthBuffer()
1042 * @brief Associate the RTT depth texture id with the depth buffer
1044 bool RenderTexture::_BindDepthBuffer() const
1047 if (_bInitialized && _bIsDepthTexture &&
1048 RT_RENDER_TO_TEXTURE == _eUpdateMode)
1050 glBindTexture(_iTextureTarget, _iDepthTextureID);
1051 if (FALSE == wglBindTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1061 //---------------------------------------------------------------------------
1062 // Function : RenderTexture::_ParseModeString
1064 //---------------------------------------------------------------------------
1066 * @fn RenderTexture::_ParseModeString()
1067 * @brief Parses the user-specified mode string for RenderTexture parameters.
1069 void RenderTexture::_ParseModeString(const char *modeString,
1070 vector<int> &pfAttribs,
1071 vector<int> &pbAttribs)
1073 if (!modeString || strcmp(modeString, "") == 0)
1076 _iNumComponents = 0;
1078 _eUpdateMode = RT_RENDER_TO_TEXTURE;
1080 _eUpdateMode = RT_COPY_TO_TEXTURE;
1084 bool bHasStencil = false;
1085 bool bBind2D = false;
1086 bool bBindRECT = false;
1087 bool bBindCUBE = false;
1089 char *mode = strdup(modeString);
1092 vector<string> tokens;
1093 char *buf = strtok(mode, " ");
1096 tokens.push_back(buf);
1097 buf = strtok(NULL, " ");
1100 for (unsigned int i = 0; i < tokens.size(); i++)
1102 string token = tokens[i];
1104 KeyVal kv = _GetKeyValuePair(token);
1107 if (kv.first == "rgb" && (_iNumComponents <= 1))
1109 if (kv.second.find("f") != kv.second.npos)
1112 vector<int> bitVec = _ParseBitVector(kv.second);
1114 if (bitVec.size() < 3) // expand the scalar to a vector
1116 bitVec.push_back(bitVec[0]);
1117 bitVec.push_back(bitVec[0]);
1121 pfAttribs.push_back(WGL_RED_BITS_ARB);
1122 pfAttribs.push_back(bitVec[0]);
1123 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1124 pfAttribs.push_back(bitVec[1]);
1125 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1126 pfAttribs.push_back(bitVec[2]);
1127 #elif defined( __APPLE__ )
1128 pfAttribs.push_back(AGL_RED_SIZE);
1129 pfAttribs.push_back(bitVec[0]);
1130 pfAttribs.push_back(AGL_GREEN_SIZE);
1131 pfAttribs.push_back(bitVec[1]);
1132 pfAttribs.push_back(AGL_BLUE_SIZE);
1133 pfAttribs.push_back(bitVec[2]);
1135 pfAttribs.push_back(GLX_RED_SIZE);
1136 pfAttribs.push_back(bitVec[0]);
1137 pfAttribs.push_back(GLX_GREEN_SIZE);
1138 pfAttribs.push_back(bitVec[1]);
1139 pfAttribs.push_back(GLX_BLUE_SIZE);
1140 pfAttribs.push_back(bitVec[2]);
1142 _iNumComponents += 3;
1145 else if (kv.first == "rgb")
1147 "RenderTexture Warning: mistake in components definition "
1152 if (kv.first == "rgba" && (_iNumComponents == 0))
1154 if (kv.second.find("f") != kv.second.npos)
1157 vector<int> bitVec = _ParseBitVector(kv.second);
1159 if (bitVec.size() < 4) // expand the scalar to a vector
1161 bitVec.push_back(bitVec[0]);
1162 bitVec.push_back(bitVec[0]);
1163 bitVec.push_back(bitVec[0]);
1167 pfAttribs.push_back(WGL_RED_BITS_ARB);
1168 pfAttribs.push_back(bitVec[0]);
1169 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1170 pfAttribs.push_back(bitVec[1]);
1171 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1172 pfAttribs.push_back(bitVec[2]);
1173 pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1174 pfAttribs.push_back(bitVec[3]);
1175 #elif defined( __APPLE__ )
1176 pfAttribs.push_back(AGL_RED_SIZE);
1177 pfAttribs.push_back(bitVec[0]);
1178 pfAttribs.push_back(AGL_GREEN_SIZE);
1179 pfAttribs.push_back(bitVec[1]);
1180 pfAttribs.push_back(AGL_BLUE_SIZE);
1181 pfAttribs.push_back(bitVec[2]);
1182 pfAttribs.push_back(AGL_ALPHA_SIZE);
1183 pfAttribs.push_back(bitVec[3]);
1185 pfAttribs.push_back(GLX_RED_SIZE);
1186 pfAttribs.push_back(bitVec[0]);
1187 pfAttribs.push_back(GLX_GREEN_SIZE);
1188 pfAttribs.push_back(bitVec[1]);
1189 pfAttribs.push_back(GLX_BLUE_SIZE);
1190 pfAttribs.push_back(bitVec[2]);
1191 pfAttribs.push_back(GLX_ALPHA_SIZE);
1192 pfAttribs.push_back(bitVec[3]);
1194 _iNumComponents = 4;
1197 else if (kv.first == "rgba")
1199 "RenderTexture Warning: mistake in components definition "
1203 if (kv.first == "r" && (_iNumComponents <= 1))
1205 if (kv.second.find("f") != kv.second.npos)
1208 vector<int> bitVec = _ParseBitVector(kv.second);
1211 pfAttribs.push_back(WGL_RED_BITS_ARB);
1212 pfAttribs.push_back(bitVec[0]);
1213 #elif defined( __APPLE__ )
1214 pfAttribs.push_back(AGL_RED_SIZE);
1215 pfAttribs.push_back(bitVec[0]);
1217 pfAttribs.push_back(GLX_RED_SIZE);
1218 pfAttribs.push_back(bitVec[0]);
1223 else if (kv.first == "r")
1225 "RenderTexture Warning: mistake in components definition "
1229 if (kv.first == "rg" && (_iNumComponents <= 1))
1231 if (kv.second.find("f") != kv.second.npos)
1234 vector<int> bitVec = _ParseBitVector(kv.second);
1236 if (bitVec.size() < 2) // expand the scalar to a vector
1238 bitVec.push_back(bitVec[0]);
1242 pfAttribs.push_back(WGL_RED_BITS_ARB);
1243 pfAttribs.push_back(bitVec[0]);
1244 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1245 pfAttribs.push_back(bitVec[1]);
1246 #elif defined( __APPLE__ )
1247 pfAttribs.push_back(AGL_RED_SIZE);
1248 pfAttribs.push_back(bitVec[0]);
1249 pfAttribs.push_back(AGL_GREEN_SIZE);
1250 pfAttribs.push_back(bitVec[1]);
1252 pfAttribs.push_back(GLX_RED_SIZE);
1253 pfAttribs.push_back(bitVec[0]);
1254 pfAttribs.push_back(GLX_GREEN_SIZE);
1255 pfAttribs.push_back(bitVec[1]);
1257 _iNumComponents += 2;
1260 else if (kv.first == "rg")
1262 "RenderTexture Warning: mistake in components definition "
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;
1406 "RenderTexture Error: Unknown pbuffer attribute: %s\n",
1410 // Processing of some options must be last because of interactions.
1412 // Check for inconsistent texture targets
1413 if (_bIsTexture && _bIsDepthTexture && !(bBind2D ^ bBindRECT ^ bBindCUBE))
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 fprintf(stderr, "RenderTexture Warning: No support found for "
1478 "render to depth texture.\n");
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 printf("RenderTexture Error: Render to Texture not "
1512 "supported in Linux or MacOS\n");
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);
1591 "RenderTexture Warning: Bad number of components "
1592 "(r=1,rg=2,rgb=3,rgba=4): %d.\n",
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);
1639 "RenderTexture Warning: Bad number of components "
1640 "(r=1,rg=2,rgb=3,rgba=4): %d.\n", _iNumComponents);
1644 #elif defined(DEBUG) || defined(_DEBUG)
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 printf("RenderTexture Error: Render to Texture not supported in "
1672 "Linux or MacOS\n");
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(", \n", 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" ) || SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ATI_pixel_format_float" )))
1797 PrintExtensionError("GL_NV_float_buffer or GL_ATI_pixel_format_float");
1801 if (_bFloat && _bIsTexture && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) || SGIsOpenGLExtensionSupported( "GL_ATI_texture_float" )))
1803 PrintExtensionError("NV_float_buffer or ATI_texture_float");
1805 if (_bIsDepthTexture && !SGIsOpenGLExtensionSupported( "GL_ARB_depth_texture" ))
1808 #if defined(_DEBUG) | defined(DEBUG)
1810 "RenderTexture Warning: "
1811 "OpenGL extension GL_ARB_depth_texture not available.\n"
1812 " Using glReadPixels() to emulate behavior.\n");
1814 _bHasARBDepthTexture = false;
1815 //PrintExtensionError("GL_ARB_depth_texture");
1821 #elif defined( __APPLE__ )
1824 // First try the glX version 1.3 functions.
1825 glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfig");
1826 glXCreateGLXPbufferPtr = (glXCreateGLXPbufferProc)SGLookupFunction("glXCreatePbuffer");
1827 glXGetVisualFromFBConfigPtr = (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfig");
1828 glXCreateContextPtr = (glXCreateContextProc)SGLookupFunction("glXCreateContext");
1829 glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyPbuffer");
1830 glXQueryDrawablePtr = (glXQueryDrawableProc)SGLookupFunction("glXQueryDrawable");
1832 if (glXChooseFBConfigPtr &&
1833 glXCreateGLXPbufferPtr &&
1834 glXGetVisualFromFBConfigPtr &&
1835 glXCreateContextPtr &&
1836 glXDestroyPbufferPtr &&
1837 glXQueryDrawablePtr)
1838 glXVersion1_3Present = true;
1841 glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfigSGIX");
1842 glXCreateGLXPbufferPtr = (glXCreateGLXPbufferProc)SGLookupFunction("glXCreateGLXPbufferSGIX");
1843 glXGetVisualFromFBConfigPtr = (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfigSGIX");
1844 glXCreateContextWithConfigPtr = (glXCreateContextWithConfigProc)SGLookupFunction("glXCreateContextWithConfigSGIX");
1845 glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyGLXPbufferSGIX");
1846 glXQueryGLXPbufferSGIXPtr = (glXQueryGLXPbufferSGIXProc)SGLookupFunction("glXQueryGLXPbufferSGIX");
1849 if (!glXChooseFBConfigPtr ||
1850 !glXCreateGLXPbufferPtr ||
1851 !glXGetVisualFromFBConfigPtr ||
1852 !glXCreateContextWithConfigPtr ||
1853 !glXDestroyPbufferPtr ||
1854 !glXQueryGLXPbufferSGIXPtr)
1858 if (_bIsDepthTexture && !GL_ARB_depth_texture)
1860 PrintExtensionError("GL_ARB_depth_texture");
1863 if (_bFloat && _bIsTexture && !GLX_NV_float_buffer)
1865 PrintExtensionError("GLX_NV_float_buffer");
1868 if (_eUpdateMode == RT_RENDER_TO_TEXTURE)
1870 PrintExtensionError("Some GLX render texture extension: Please implement me!");
1878 //---------------------------------------------------------------------------
1879 // Function : RenderTexture::_InitializeTextures
1881 //---------------------------------------------------------------------------
1883 * @fn RenderTexture::_InitializeTextures()
1884 * @brief Initializes the state of textures used by the RenderTexture.
1886 bool RenderTexture::_InitializeTextures()
1888 // Determine the appropriate texture formats and filtering modes.
1889 if (_bIsTexture || _bIsDepthTexture)
1891 if (_bRectangle && GL_NV_texture_rectangle)
1892 _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
1894 _iTextureTarget = GL_TEXTURE_2D;
1899 glGenTextures(1, (GLuint*)&_iTextureID);
1900 glBindTexture(_iTextureTarget, _iTextureID);
1902 // Use clamp to edge as the default texture wrap mode for all tex
1903 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1904 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1905 // Use NEAREST as the default texture filtering mode.
1906 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1907 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1910 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
1912 GLuint iInternalFormat;
1920 "RenderTexture Error: mipmapped float textures not "
1925 switch(_iNumComponents)
1928 if (GL_NV_float_buffer)
1930 iInternalFormat = (_iNumColorBits[0] > 16) ?
1931 GL_FLOAT_R32_NV : GL_FLOAT_R16_NV;
1933 else if (GL_ATI_texture_float)
1935 iInternalFormat = (_iNumColorBits[0] > 16) ?
1936 GL_LUMINANCE_FLOAT32_ATI :
1937 GL_LUMINANCE_FLOAT16_ATI;
1939 iFormat = GL_LUMINANCE;
1942 if (GL_NV_float_buffer)
1944 iInternalFormat = (_iNumColorBits[0] > 16) ?
1945 GL_FLOAT_RG32_NV : GL_FLOAT_RG16_NV;
1947 else if (GL_ATI_texture_float)
1949 iInternalFormat = (_iNumColorBits[0] > 16) ?
1950 GL_LUMINANCE_ALPHA_FLOAT32_ATI :
1951 GL_LUMINANCE_ALPHA_FLOAT16_ATI;
1953 iFormat = GL_LUMINANCE_ALPHA;
1956 if (GL_NV_float_buffer)
1958 iInternalFormat = (_iNumColorBits[0] > 16) ?
1959 GL_FLOAT_RGB32_NV : GL_FLOAT_RGB16_NV;
1961 else if (GL_ATI_texture_float)
1963 iInternalFormat = (_iNumColorBits[0] > 16) ?
1964 GL_RGB_FLOAT32_ATI : GL_RGB_FLOAT16_ATI;
1969 if (GL_NV_float_buffer)
1971 iInternalFormat = (_iNumColorBits[0] > 16) ?
1972 GL_FLOAT_RGBA32_NV : GL_FLOAT_RGBA16_NV;
1974 else if (GL_ATI_texture_float)
1976 iInternalFormat = (_iNumColorBits[0] > 16) ?
1977 GL_RGBA_FLOAT32_ATI : GL_RGBA_FLOAT16_ATI;
1982 printf("RenderTexture Error: "
1983 "Invalid number of components: %d\n",
1990 if (4 == _iNumComponents)
1992 iInternalFormat = GL_RGBA8;
1997 iInternalFormat = GL_RGB8;
2002 // Allocate the texture image (but pass it no data for now).
2003 glTexImage2D(_iTextureTarget, 0, iInternalFormat,
2004 _iWidth, _iHeight, 0, iFormat, GL_FLOAT, NULL);
2008 if (_bIsDepthTexture)
2010 glGenTextures(1, (GLuint*)&_iDepthTextureID);
2011 glBindTexture(_iTextureTarget, _iDepthTextureID);
2013 // Use clamp to edge as the default texture wrap mode for all tex
2014 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2015 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2016 // Use NEAREST as the default texture filtering mode.
2017 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2018 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2020 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2023 if (_bHasARBDepthTexture)
2025 // Allocate the texture image (but pass it no data for now).
2026 glTexImage2D(_iTextureTarget, 0, GL_DEPTH_COMPONENT,
2027 _iWidth, _iHeight, 0, GL_DEPTH_COMPONENT,
2032 // allocate memory for depth texture
2033 // Since this is slow, we warn the user in debug mode. (above)
2034 _pPoorDepthTexture = new unsigned short[_iWidth * _iHeight];
2035 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
2036 _iWidth, _iHeight, 0, GL_LUMINANCE,
2037 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2047 //---------------------------------------------------------------------------
2048 // Function : RenderTexture::_MaybeCopyBuffer
2050 //---------------------------------------------------------------------------
2052 * @fn RenderTexture::_MaybeCopyBuffer()
2053 * @brief Does the actual copying for RenderTextures with RT_COPY_TO_TEXTURE
2055 void RenderTexture::_MaybeCopyBuffer()
2058 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2062 glBindTexture(_iTextureTarget, _iTextureID);
2063 glCopyTexSubImage2D(_iTextureTarget,
2064 0, 0, 0, 0, 0, _iWidth, _iHeight);
2066 if (_bIsDepthTexture)
2068 glBindTexture(_iTextureTarget, _iDepthTextureID);
2069 // HOW TO COPY DEPTH TEXTURE??? Supposedly this just magically works...
2071 if (_bHasARBDepthTexture)
2073 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0,
2078 // no 'real' depth texture available, so behavior has to be emulated
2079 // using glReadPixels (beware, this is (naturally) slow ...)
2080 glReadPixels(0, 0, _iWidth, _iHeight, GL_DEPTH_COMPONENT,
2081 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2082 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
2083 _iWidth, _iHeight, 0, GL_LUMINANCE,
2084 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2093 glBindTexture(_iTextureTarget, _iTextureID);
2094 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2096 if (_bIsDepthTexture)
2098 glBindTexture(_iTextureTarget, _iDepthTextureID);
2099 assert(_bHasARBDepthTexture);
2100 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2106 //---------------------------------------------------------------------------
2107 // Function : RenderTexture::_ReleaseBoundBuffers
2109 //---------------------------------------------------------------------------
2111 * @fn RenderTexture::_ReleaseBoundBuffers()
2112 * @brief Releases buffer bindings on RenderTextures with RT_RENDER_TO_TEXTURE
2114 bool RenderTexture::_ReleaseBoundBuffers()
2117 if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2119 glBindTexture(_iTextureTarget, _iTextureID);
2121 // release the pbuffer from the render texture object
2122 if (0 != _iCurrentBoundBuffer && _bIsBufferBound)
2124 if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, _iCurrentBoundBuffer))
2129 _bIsBufferBound = false;
2133 if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2135 glBindTexture(_iTextureTarget, _iDepthTextureID);
2137 // release the pbuffer from the render texture object
2138 if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
2146 // textures can't be bound in Linux
2151 //---------------------------------------------------------------------------
2152 // Function : RenderTexture::_MakeCurrent
2154 //---------------------------------------------------------------------------
2156 * @fn RenderTexture::_MakeCurrent()
2157 * @brief Makes the RenderTexture's context current
2160 bool RenderTexture::_MakeCurrent()
2163 // make the pbuffer's rendering context current.
2164 if (FALSE == wglMakeCurrent( _hDC, _hGLContext))
2169 #elif defined( __APPLE__ )
2171 if (false == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
2180 /////////////////////////////////////////////////////////////////////////////
2182 // Begin Deprecated Interface
2184 /////////////////////////////////////////////////////////////////////////////
2186 //---------------------------------------------------------------------------
2187 // Function : RenderTexture::RenderTexture
2189 //---------------------------------------------------------------------------
2191 * @fn RenderTexture::RenderTexture()
2192 * @brief Constructor.
2194 RenderTexture::RenderTexture(int width, int height,
2195 bool bIsTexture /* = true */,
2196 bool bIsDepthTexture /* = false */)
2199 _bIsTexture(bIsTexture),
2200 _bIsDepthTexture(bIsDepthTexture),
2201 _bHasARBDepthTexture(true), // [Redge]
2202 _eUpdateMode(RT_RENDER_TO_TEXTURE),
2203 _bInitialized(false),
2205 _iCurrentBoundBuffer(0),
2207 _iNumStencilBits(0),
2208 _bDoubleBuffered(false),
2213 _bShareObjects(false),
2214 _bCopyContext(false),
2220 _hPreviousContext(0),
2221 #elif defined( __APPLE__ )
2226 _hPreviousContext(0),
2227 _hPreviousDrawable(0),
2229 _iTextureTarget(GL_NONE),
2231 _iDepthTextureID(0),
2232 _pPoorDepthTexture(0) // [Redge]
2234 assert(width > 0 && height > 0);
2235 #if defined DEBUG || defined _DEBUG
2237 "RenderTexture Warning: Deprecated Contructor interface used.\n");
2240 _iNumColorBits[0] = _iNumColorBits[1] =
2241 _iNumColorBits[2] = _iNumColorBits[3] = 0;
2242 _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
2245 //------------------------------------------------------------------------------
2246 // Function : RenderTexture::Initialize
2248 //------------------------------------------------------------------------------
2250 * @fn RenderTexture::Initialize(bool bShare, bool bDepth, bool bStencil, bool bMipmap, unsigned int iRBits, unsigned int iGBits, unsigned int iBBits, unsigned int iABits);
2251 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
2253 * This function actually does the creation of the p-buffer. It can only be called
2254 * once a GL context has already been created. Note that if the texture is not
2255 * power of two dimensioned, or has more than 8 bits per channel, enabling mipmapping
2256 * will cause an error.
2258 bool RenderTexture::Initialize(bool bShare /* = true */,
2259 bool bDepth /* = false */,
2260 bool bStencil /* = false */,
2261 bool bMipmap /* = false */,
2262 bool bAnisoFilter /* = false */,
2263 unsigned int iRBits /* = 8 */,
2264 unsigned int iGBits /* = 8 */,
2265 unsigned int iBBits /* = 8 */,
2266 unsigned int iABits /* = 8 */,
2267 UpdateMode updateMode /* = RT_RENDER_TO_TEXTURE */)
2269 if (0 == _iWidth || 0 == _iHeight)
2272 #if defined DEBUG || defined _DEBUG
2274 "RenderTexture Warning: Deprecated Initialize() interface used.\n");
2277 // create a mode string.
2280 mode.append("depth ");
2282 mode.append("stencil ");
2284 mode.append("mipmap ");
2285 if (iRBits + iGBits + iBBits + iABits > 0)
2296 char bitVector[100];
2298 "%d%s,%d%s,%d%s,%d%s",
2299 iRBits, (iRBits >= 16) ? "f" : "",
2300 iGBits, (iGBits >= 16) ? "f" : "",
2301 iBBits, (iBBits >= 16) ? "f" : "",
2302 iABits, (iABits >= 16) ? "f" : "");
2303 mode.append(bitVector);
2308 if (GL_NV_texture_rectangle &&
2309 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2310 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2311 mode.append("texRECT ");
2313 mode.append("tex2D ");
2315 if (_bIsDepthTexture)
2317 if (GL_NV_texture_rectangle &&
2318 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2319 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2320 mode.append("texRECT ");
2322 mode.append("tex2D ");
2324 if (RT_COPY_TO_TEXTURE == updateMode)
2327 _pixelFormatAttribs.clear();
2328 _pbufferAttribs.clear();
2331 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
2332 _pixelFormatAttribs.push_back(true);
2333 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
2334 _pixelFormatAttribs.push_back(true);
2336 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
2337 _pbufferAttribs.push_back(true);
2338 #elif defined( __APPLE__ )
2340 _pixelFormatAttribs.push_back(GLX_RENDER_TYPE_SGIX);
2341 _pixelFormatAttribs.push_back(GLX_RGBA_BIT_SGIX);
2342 _pixelFormatAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
2343 _pixelFormatAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
2346 _ParseModeString(mode.c_str(), _pixelFormatAttribs, _pbufferAttribs);
2349 _pixelFormatAttribs.push_back(0);
2350 _pbufferAttribs.push_back(0);
2352 _pixelFormatAttribs.push_back(None);
2355 Initialize(_iWidth, _iHeight, bShare);
2361 //---------------------------------------------------------------------------
2362 // Function : RenderTexture::Reset
2364 //---------------------------------------------------------------------------
2366 * @fn RenderTexture::Reset(int iWidth, int iHeight, unsigned int iMode, bool bIsTexture, bool bIsDepthTexture)
2367 * @brief Resets the resolution of the offscreen buffer.
2369 * Causes the buffer to delete itself. User must call Initialize() again
2372 bool RenderTexture::Reset(int iWidth, int iHeight)
2375 "RenderTexture Warning: Deprecated Reset() interface used.\n");
2379 fprintf(stderr, "RenderTexture::Reset(): failed to invalidate.\n");