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;
87 //---------------------------------------------------------------------------
88 // Function : RenderTexture::RenderTexture
90 //---------------------------------------------------------------------------
92 * @fn RenderTexture::RenderTexture()
93 * @brief Mode-string-based Constructor.
95 RenderTexture::RenderTexture(const char *strMode)
99 _bIsDepthTexture(false),
100 _bHasARBDepthTexture(true), // [Redge]
102 _eUpdateMode(RT_RENDER_TO_TEXTURE),
104 _eUpdateMode(RT_COPY_TO_TEXTURE),
106 _bInitialized(false),
108 _bIsBufferBound(false),
109 _iCurrentBoundBuffer(0),
113 _bDoubleBuffered(false),
117 _bShareObjects(false),
118 _bCopyContext(false),
124 _hPreviousContext(0),
125 #elif defined( __APPLE__ )
130 _hPreviousContext(0),
131 _hPreviousDrawable(0),
133 _iTextureTarget(GL_NONE),
136 _pPoorDepthTexture(0) // [Redge]
138 _iNumColorBits[0] = _iNumColorBits[1] =
139 _iNumColorBits[2] = _iNumColorBits[3] = 0;
142 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
143 _pixelFormatAttribs.push_back(true);
144 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
145 _pixelFormatAttribs.push_back(true);
147 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
148 _pbufferAttribs.push_back(true);
149 #elif defined( __APPLE__ )
151 _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
152 _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
153 _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
154 _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
157 _ParseModeString(strMode, _pixelFormatAttribs, _pbufferAttribs);
160 _pixelFormatAttribs.push_back(0);
161 _pbufferAttribs.push_back(0);
163 _pixelFormatAttribs.push_back(None);
168 //---------------------------------------------------------------------------
169 // Function : RenderTexture::~RenderTexture
171 //---------------------------------------------------------------------------
173 * @fn RenderTexture::~RenderTexture()
176 RenderTexture::~RenderTexture()
182 //---------------------------------------------------------------------------
183 // Function : _wglGetLastError
185 //---------------------------------------------------------------------------
187 * @fn wglGetLastError()
188 * @brief Returns the last windows error generated.
191 void _wglGetLastError()
195 DWORD err = GetLastError();
198 case ERROR_INVALID_PIXEL_FORMAT:
200 "RenderTexture Win32 Error: ERROR_INVALID_PIXEL_FORMAT\n");
202 case ERROR_NO_SYSTEM_RESOURCES:
204 "RenderTexture Win32 Error: ERROR_NO_SYSTEM_RESOURCES\n");
206 case ERROR_INVALID_DATA:
208 "RenderTexture Win32 Error: ERROR_INVALID_DATA\n");
210 case ERROR_INVALID_WINDOW_HANDLE:
212 "RenderTexture Win32 Error: ERROR_INVALID_WINDOW_HANDLE\n");
214 case ERROR_RESOURCE_TYPE_NOT_FOUND:
216 "RenderTexture Win32 Error: ERROR_RESOURCE_TYPE_NOT_FOUND\n");
223 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
224 FORMAT_MESSAGE_FROM_SYSTEM |
225 FORMAT_MESSAGE_IGNORE_INSERTS,
228 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
233 fprintf(stderr, "RenderTexture Win32 Error %d: %s\n", err, lpMsgBuf);
234 LocalFree( lpMsgBuf );
243 //---------------------------------------------------------------------------
244 // Function : PrintExtensionError
246 //---------------------------------------------------------------------------
248 * @fn PrintExtensionError( char* strMsg, ... )
249 * @brief Prints an error about missing OpenGL extensions.
251 void PrintExtensionError( char* strMsg, ... )
254 "Error: RenderTexture requires the following unsupported "
255 "OpenGL extensions: \n");
258 va_start(args, strMsg);
259 #if defined _WIN32 && !defined __CYGWIN__
260 _vsnprintf( strBuffer, 512, strMsg, args );
262 vsnprintf( strBuffer, 512, strMsg, args );
266 fprintf(stderr, strMsg);
270 //---------------------------------------------------------------------------
271 // Function : RenderTexture::Initialize
273 //---------------------------------------------------------------------------
275 * @fn RenderTexture::Initialize(int width, int height, bool shareObjects, bool copyContext);
276 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
278 * This function creates of the p-buffer. It can only be called once a GL
279 * context has already been created.
281 bool RenderTexture::Initialize(int width, int height,
282 bool shareObjects /* = true */,
283 bool copyContext /* = false */)
285 assert(width > 0 && height > 0);
287 _iWidth = width; _iHeight = height;
288 _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
290 _bShareObjects = shareObjects;
291 _bCopyContext = copyContext;
293 // Check if this is an NVXX GPU and verify necessary extensions.
294 if (!_VerifyExtensions())
301 // Get the current context.
302 HDC hdc = wglGetCurrentDC();
305 HGLRC hglrc = wglGetCurrentContext();
310 unsigned int iNumFormats;
314 // Get the pixel format for the on-screen window.
315 iFormat = GetPixelFormat(hdc);
319 "RenderTexture Error: GetPixelFormat() failed.\n");
325 if (!wglChoosePixelFormatARBPtr(hdc, &_pixelFormatAttribs[0], NULL,
326 1, &iFormat, &iNumFormats))
329 "RenderTexture Error: wglChoosePixelFormatARB() failed.\n");
333 if ( iNumFormats <= 0 )
336 "RenderTexture Error: Couldn't find a suitable "
343 // Create the p-buffer.
344 _hPBuffer = wglCreatePbufferARBPtr(hdc, iFormat, _iWidth, _iHeight,
345 &_pbufferAttribs[0]);
349 "RenderTexture Error: wglCreatePbufferARB() failed.\n");
354 // Get the device context.
355 _hDC = wglGetPbufferDCARBPtr( _hPBuffer);
359 "RenderTexture Error: wglGetGetPbufferDCARB() failed.\n");
364 // Create a gl context for the p-buffer.
367 // Let's use the same gl context..
368 // Since the device contexts are compatible (i.e. same pixelformat),
369 // we should be able to use the same gl rendering context.
374 _hGLContext = wglCreateContext( _hDC );
378 "RenderTexture Error: wglCreateContext() failed.\n");
384 // Share lists, texture objects, and program objects.
387 if( !wglShareLists(hglrc, _hGLContext) )
390 "RenderTexture Error: wglShareLists() failed.\n");
396 // Determine the actual width and height we were able to create.
397 wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
398 wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
400 _bInitialized = true;
402 // get the actual number of bits allocated:
403 int attrib = WGL_RED_BITS_ARB;
407 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
409 attrib = WGL_GREEN_BITS_ARB;
411 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
413 attrib = WGL_BLUE_BITS_ARB;
415 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
417 attrib = WGL_ALPHA_BITS_ARB;
419 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
421 attrib = WGL_DEPTH_BITS_ARB;
423 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
425 attrib = WGL_STENCIL_BITS_ARB;
427 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
429 attrib = WGL_DOUBLE_BUFFER_ARB;
431 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
432 ? (value?true:false) : false;
434 #if defined(_DEBUG) | defined(DEBUG)
435 fprintf(stderr, "Created a %dx%d RenderTexture with BPP(%d, %d, %d, %d)",
437 _iNumColorBits[0], _iNumColorBits[1],
438 _iNumColorBits[2], _iNumColorBits[3]);
439 if (_iNumDepthBits) fprintf(stderr, " depth=%d", _iNumDepthBits);
440 if (_iNumStencilBits) fprintf(stderr, " stencil=%d", _iNumStencilBits);
441 if (_bDoubleBuffered) fprintf(stderr, " double buffered");
442 fprintf(stderr, "\n");
445 #elif defined( __APPLE__ )
447 _pDisplay = glXGetCurrentDisplay();
448 GLXContext context = glXGetCurrentContext();
449 int screen = DefaultScreen(_pDisplay);
450 XVisualInfo *visInfo;
456 GLXFBConfigSGIX *fbConfigs;
459 fbConfigs = glXChooseFBConfigSGIX(_pDisplay, screen,
460 &_pixelFormatAttribs[0], &nConfigs);
462 if (nConfigs == 0 || !fbConfigs)
465 "RenderTexture Error: Couldn't find a suitable pixel format.\n");
469 // Pick the first returned format that will return a pbuffer
470 for (int i=0;i<nConfigs;i++)
472 _hPBuffer = glXCreateGLXPbufferSGIX(_pDisplay, fbConfigs[i],
473 _iWidth, _iHeight, NULL);
476 _hGLContext = glXCreateContextWithConfigSGIX(_pDisplay,
479 _bShareObjects ? context : NULL,
488 "RenderTexture Error: glXCreateGLXPbufferSGIX() failed.\n");
495 _hGLContext = glXCreateContext(_pDisplay, visInfo,
496 _bShareObjects ? context : NULL, False);
500 "RenderTexture Error: glXCreateContext() failed.\n");
505 glXQueryGLXPbufferSGIX(_pDisplay, _hPBuffer, GLX_WIDTH_SGIX,
507 glXQueryGLXPbufferSGIX(_pDisplay, _hPBuffer, GLX_HEIGHT_SGIX,
510 _bInitialized = true;
512 // XXX Query the color format
517 // Now that the pbuffer is created, allocate any texture objects needed,
518 // and initialize them (for CTT updates only). These must be allocated
519 // in the context of the pbuffer, though, or the RT won't work without
522 if (false == wglMakeCurrent( _hDC, _hGLContext))
527 #elif defined( __APPLE__ )
529 _hPreviousContext = glXGetCurrentContext();
530 _hPreviousDrawable = glXGetCurrentDrawable();
532 if (False == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
538 bool result = _InitializeTextures();
540 BindBuffer(WGL_FRONT_LEFT_ARB);
546 // make the previous rendering context current
547 if (false == wglMakeCurrent( hdc, hglrc))
552 #elif defined( __APPLE__ )
554 if (False == glXMakeCurrent(_pDisplay,
555 _hPreviousDrawable, _hPreviousContext))
565 //---------------------------------------------------------------------------
566 // Function : RenderTexture::_Invalidate
568 //---------------------------------------------------------------------------
570 * @fn RenderTexture::_Invalidate()
571 * @brief Returns the pbuffer memory to the graphics device.
574 bool RenderTexture::_Invalidate()
576 _iNumColorBits[0] = _iNumColorBits[1] =
577 _iNumColorBits[2] = _iNumColorBits[3] = 0;
579 _iNumStencilBits = 0;
582 glDeleteTextures(1, (const GLuint*)&_iTextureID);
583 if (_bIsDepthTexture)
586 if (!_bHasARBDepthTexture) delete[] _pPoorDepthTexture;
588 glDeleteTextures(1, (const GLuint*)&_iDepthTextureID);
594 // Check if we are currently rendering in the pbuffer
595 if (wglGetCurrentContext() == _hGLContext)
598 wglDeleteContext( _hGLContext);
599 wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
600 wglDestroyPbufferARBPtr( _hPBuffer );
604 #elif defined( __APPLE__ )
608 if(glXGetCurrentContext() == _hGLContext)
609 // XXX I don't know if this is right at all
610 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
611 glXDestroyGLXPbufferSGIX(_pDisplay, _hPBuffer);
617 // [WVB] do we need to call _ReleaseBoundBuffers() too?
622 //---------------------------------------------------------------------------
623 // Function : RenderTexture::Reset
625 //---------------------------------------------------------------------------
627 * @fn RenderTexture::Reset()
628 * @brief Resets the resolution of the offscreen buffer.
630 * Causes the buffer to delete itself. User must call Initialize() again
633 bool RenderTexture::Reset(const char *strMode, ...)
635 _iWidth = 0; _iHeight = 0;
636 _bIsTexture = false; _bIsDepthTexture = false,
637 _bHasARBDepthTexture = true;
639 _eUpdateMode = RT_RENDER_TO_TEXTURE;
641 _eUpdateMode = RT_COPY_TO_TEXTURE;
643 _bInitialized = false;
645 _bIsBufferBound = false;
646 _iCurrentBoundBuffer = 0;
647 _iNumDepthBits = 0; _iNumStencilBits = 0;
648 _bDoubleBuffered = false;
649 _bFloat = false; _bPowerOf2 = true;
650 _bRectangle = false; _bMipmap = false;
651 _bShareObjects = false; _bCopyContext = false;
652 _iTextureTarget = GL_NONE; _iTextureID = 0;
653 _iDepthTextureID = 0;
654 _pPoorDepthTexture = 0;
655 _pixelFormatAttribs.clear();
656 _pbufferAttribs.clear();
658 if (IsInitialized() && !_Invalidate())
660 fprintf(stderr, "RenderTexture::Reset(): failed to invalidate.\n");
664 _iNumColorBits[0] = _iNumColorBits[1] =
665 _iNumColorBits[2] = _iNumColorBits[3] = 0;
668 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
669 _pixelFormatAttribs.push_back(true);
670 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
671 _pixelFormatAttribs.push_back(true);
673 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
674 _pbufferAttribs.push_back(true);
675 #elif defined( __APPLE__ )
677 _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
678 _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
679 _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
680 _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
685 va_start(args,strMode);
686 #if defined _WIN32 && !defined __CYGWIN__
687 _vsnprintf( strBuffer, 256, strMode, args );
689 vsnprintf( strBuffer, 256, strMode, args );
693 _ParseModeString(strBuffer, _pixelFormatAttribs, _pbufferAttribs);
696 _pixelFormatAttribs.push_back(0);
697 _pbufferAttribs.push_back(0);
699 _pixelFormatAttribs.push_back(None);
704 //------------------------------------------------------------------------------
705 // Function : RenderTexture::Resize
707 //------------------------------------------------------------------------------
709 * @fn RenderTexture::Resize(int iWidth, int iHeight)
710 * @brief Changes the size of the offscreen buffer.
712 * Like Reset() this causes the buffer to delete itself.
713 * But unlike Reset(), this call re-initializes the RenderTexture.
714 * Note that Resize() will not work after calling Reset(), or before
715 * calling Initialize() the first time.
717 bool RenderTexture::Resize(int iWidth, int iHeight)
719 if (!_bInitialized) {
720 fprintf(stderr, "RenderTexture::Resize(): must Initialize() first.\n");
723 if (iWidth == _iWidth && iHeight == _iHeight) {
727 // Do same basic work as _Invalidate, but don't reset all our flags
729 glDeleteTextures(1, (const GLuint*)&_iTextureID);
730 if (_bIsDepthTexture)
731 glDeleteTextures(1, (const GLuint*)&_iDepthTextureID);
735 // Check if we are currently rendering in the pbuffer
736 if (wglGetCurrentContext() == _hGLContext)
739 wglDeleteContext( _hGLContext);
740 wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
741 wglDestroyPbufferARBPtr( _hPBuffer );
745 #elif defined( __APPLE__ )
749 if(glXGetCurrentContext() == _hGLContext)
750 // XXX I don't know if this is right at all
751 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
752 glXDestroyGLXPbufferSGIX(_pDisplay, _hPBuffer);
757 fprintf(stderr, "RenderTexture::Resize(): failed to resize.\n");
760 _bInitialized = false;
761 return Initialize(iWidth, iHeight, _bShareObjects, _bCopyContext);
764 //---------------------------------------------------------------------------
765 // Function : RenderTexture::BeginCapture
767 //---------------------------------------------------------------------------
769 * @fn RenderTexture::BeginCapture()
770 * @brief Activates rendering to the RenderTexture.
772 bool RenderTexture::BeginCapture()
777 "RenderTexture::BeginCapture(): Texture is not initialized!\n");
781 // cache the current context so we can reset it when EndCapture() is called.
782 _hPreviousDC = wglGetCurrentDC();
783 if (NULL == _hPreviousDC)
785 _hPreviousContext = wglGetCurrentContext();
786 if (NULL == _hPreviousContext)
788 #elif defined( __APPLE__ )
790 _hPreviousContext = glXGetCurrentContext();
791 _hPreviousDrawable = glXGetCurrentDrawable();
794 _ReleaseBoundBuffers();
796 return _MakeCurrent();
800 //---------------------------------------------------------------------------
801 // Function : RenderTexture::EndCapture
803 //---------------------------------------------------------------------------
805 * @fn RenderTexture::EndCapture()
806 * @brief Ends rendering to the RenderTexture.
808 bool RenderTexture::EndCapture()
813 "RenderTexture::EndCapture() : Texture is not initialized!\n");
820 // make the previous rendering context current
821 if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
826 #elif defined( __APPLE__ )
828 if (False == glXMakeCurrent(_pDisplay, _hPreviousDrawable,
835 // rebind the textures to a buffers for RTT
836 BindBuffer(_iCurrentBoundBuffer);
842 //---------------------------------------------------------------------------
843 // Function : RenderTexture::BeginCapture(RenderTexture*)
845 //---------------------------------------------------------------------------
847 * @fn RenderTexture::BeginCapture(RenderTexture* other)
848 * @brief Ends capture of 'other', begins capture on 'this'
850 * When performing a series of operations where you modify one texture after
851 * another, it is more efficient to use this method instead of the equivalent
852 * 'EndCapture'/'BeginCapture' pair. This method switches directly to the
853 * new context rather than changing to the default context, and then to the
856 * RenderTexture doesn't have any mechanism for determining if
857 * 'current' really is currently active, so no error will be thrown
860 bool RenderTexture::BeginCapture(RenderTexture* current)
862 bool bContextReset = false;
864 if (current == this) {
865 return true; // no switch necessary
868 // treat as normal Begin if current is 0.
869 return BeginCapture();
874 "RenderTexture::BeginCapture(RenderTexture*): Texture is not initialized!\n");
877 if (!current->_bInitialized)
880 "RenderTexture::BeginCapture(RenderTexture): 'current' texture is not initialized!\n");
884 // Sync current pbuffer with its CTT texture if necessary
885 current->_MaybeCopyBuffer();
887 // pass along the previous context so we can reset it when
888 // EndCapture() is called.
890 _hPreviousDC = current->_hPreviousDC;
891 if (NULL == _hPreviousDC)
893 _hPreviousContext = current->_hPreviousContext;
894 if (NULL == _hPreviousContext)
896 #elif defined( __APPLE__ )
898 _hPreviousContext = current->_hPreviousContext;
899 _hPreviousDrawable = current->_hPreviousDrawable;
902 // Unbind textures before making context current
903 if (!_ReleaseBoundBuffers())
906 // Make the pbuffer context current
910 // Rebind buffers of initial RenderTexture
911 current->BindBuffer(_iCurrentBoundBuffer);
912 current->_BindDepthBuffer();
919 //---------------------------------------------------------------------------
920 // Function : RenderTexture::Bind
922 //---------------------------------------------------------------------------
924 * @fn RenderTexture::Bind()
925 * @brief Binds RGB texture.
927 void RenderTexture::Bind() const
929 if (_bInitialized && _bIsTexture)
931 glBindTexture(_iTextureTarget, _iTextureID);
936 //---------------------------------------------------------------------------
937 // Function : RenderTexture::BindDepth
939 //---------------------------------------------------------------------------
941 * @fn RenderTexture::BindDepth()
942 * @brief Binds depth texture.
944 void RenderTexture::BindDepth() const
946 if (_bInitialized && _bIsDepthTexture)
948 glBindTexture(_iTextureTarget, _iDepthTextureID);
953 //---------------------------------------------------------------------------
954 // Function : RenderTexture::BindBuffer
956 //---------------------------------------------------------------------------
958 * @fn RenderTexture::BindBuffer()
959 * @brief Associate the RTT texture id with 'iBuffer' (e.g. WGL_FRONT_LEFT_ARB)
961 bool RenderTexture::BindBuffer( int iBuffer )
963 // Must bind the texture too
964 if (_bInitialized && _bIsTexture)
966 glBindTexture(_iTextureTarget, _iTextureID);
969 if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
970 (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
972 if (FALSE == wglBindTexImageARBPtr(_hPBuffer, iBuffer))
974 // WVB: WGL API considers binding twice to the same buffer
975 // to be an error. But we don't want to
976 //_wglGetLastError();
980 _bIsBufferBound = true;
981 _iCurrentBoundBuffer = iBuffer;
989 //---------------------------------------------------------------------------
990 // Function : RenderTexture::BindBuffer
992 //---------------------------------------------------------------------------
994 * @fn RenderTexture::_BindDepthBuffer()
995 * @brief Associate the RTT depth texture id with the depth buffer
997 bool RenderTexture::_BindDepthBuffer() const
1000 if (_bInitialized && _bIsDepthTexture &&
1001 RT_RENDER_TO_TEXTURE == _eUpdateMode)
1003 glBindTexture(_iTextureTarget, _iDepthTextureID);
1004 if (FALSE == wglBindTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1014 //---------------------------------------------------------------------------
1015 // Function : RenderTexture::_ParseModeString
1017 //---------------------------------------------------------------------------
1019 * @fn RenderTexture::_ParseModeString()
1020 * @brief Parses the user-specified mode string for RenderTexture parameters.
1022 void RenderTexture::_ParseModeString(const char *modeString,
1023 vector<int> &pfAttribs,
1024 vector<int> &pbAttribs)
1026 if (!modeString || strcmp(modeString, "") == 0)
1029 _iNumComponents = 0;
1031 _eUpdateMode = RT_RENDER_TO_TEXTURE;
1033 _eUpdateMode = RT_COPY_TO_TEXTURE;
1037 bool bHasStencil = false;
1038 bool bBind2D = false;
1039 bool bBindRECT = false;
1040 bool bBindCUBE = false;
1042 char *mode = strdup(modeString);
1045 vector<string> tokens;
1046 char *buf = strtok(mode, " ");
1049 tokens.push_back(buf);
1050 buf = strtok(NULL, " ");
1053 for (unsigned int i = 0; i < tokens.size(); i++)
1055 string token = tokens[i];
1057 KeyVal kv = _GetKeyValuePair(token);
1060 if (kv.first == "rgb" && (_iNumComponents <= 1))
1062 if (kv.second.find("f") != kv.second.npos)
1065 vector<int> bitVec = _ParseBitVector(kv.second);
1067 if (bitVec.size() < 3) // expand the scalar to a vector
1069 bitVec.push_back(bitVec[0]);
1070 bitVec.push_back(bitVec[0]);
1074 pfAttribs.push_back(WGL_RED_BITS_ARB);
1075 pfAttribs.push_back(bitVec[0]);
1076 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1077 pfAttribs.push_back(bitVec[1]);
1078 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1079 pfAttribs.push_back(bitVec[2]);
1080 #elif defined( __APPLE__ )
1081 pfAttribs.push_back(AGL_RED_SIZE);
1082 pfAttribs.push_back(bitVec[0]);
1083 pfAttribs.push_back(AGL_GREEN_SIZE);
1084 pfAttribs.push_back(bitVec[1]);
1085 pfAttribs.push_back(AGL_BLUE_SIZE);
1086 pfAttribs.push_back(bitVec[2]);
1088 pfAttribs.push_back(GLX_RED_SIZE);
1089 pfAttribs.push_back(bitVec[0]);
1090 pfAttribs.push_back(GLX_GREEN_SIZE);
1091 pfAttribs.push_back(bitVec[1]);
1092 pfAttribs.push_back(GLX_BLUE_SIZE);
1093 pfAttribs.push_back(bitVec[2]);
1095 _iNumComponents += 3;
1098 else if (kv.first == "rgb")
1100 "RenderTexture Warning: mistake in components definition "
1105 if (kv.first == "rgba" && (_iNumComponents == 0))
1107 if (kv.second.find("f") != kv.second.npos)
1110 vector<int> bitVec = _ParseBitVector(kv.second);
1112 if (bitVec.size() < 4) // expand the scalar to a vector
1114 bitVec.push_back(bitVec[0]);
1115 bitVec.push_back(bitVec[0]);
1116 bitVec.push_back(bitVec[0]);
1120 pfAttribs.push_back(WGL_RED_BITS_ARB);
1121 pfAttribs.push_back(bitVec[0]);
1122 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1123 pfAttribs.push_back(bitVec[1]);
1124 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1125 pfAttribs.push_back(bitVec[2]);
1126 pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1127 pfAttribs.push_back(bitVec[3]);
1128 #elif defined( __APPLE__ )
1129 pfAttribs.push_back(AGL_RED_SIZE);
1130 pfAttribs.push_back(bitVec[0]);
1131 pfAttribs.push_back(AGL_GREEN_SIZE);
1132 pfAttribs.push_back(bitVec[1]);
1133 pfAttribs.push_back(AGL_BLUE_SIZE);
1134 pfAttribs.push_back(bitVec[2]);
1135 pfAttribs.push_back(AGL_ALPHA_SIZE);
1136 pfAttribs.push_back(bitVec[3]);
1138 pfAttribs.push_back(GLX_RED_SIZE);
1139 pfAttribs.push_back(bitVec[0]);
1140 pfAttribs.push_back(GLX_GREEN_SIZE);
1141 pfAttribs.push_back(bitVec[1]);
1142 pfAttribs.push_back(GLX_BLUE_SIZE);
1143 pfAttribs.push_back(bitVec[2]);
1144 pfAttribs.push_back(GLX_ALPHA_SIZE);
1145 pfAttribs.push_back(bitVec[3]);
1147 _iNumComponents = 4;
1150 else if (kv.first == "rgba")
1152 "RenderTexture Warning: mistake in components definition "
1156 if (kv.first == "r" && (_iNumComponents <= 1))
1158 if (kv.second.find("f") != kv.second.npos)
1161 vector<int> bitVec = _ParseBitVector(kv.second);
1164 pfAttribs.push_back(WGL_RED_BITS_ARB);
1165 pfAttribs.push_back(bitVec[0]);
1166 #elif defined( __APPLE__ )
1167 pfAttribs.push_back(AGL_RED_SIZE);
1168 pfAttribs.push_back(bitVec[0]);
1170 pfAttribs.push_back(GLX_RED_SIZE);
1171 pfAttribs.push_back(bitVec[0]);
1176 else if (kv.first == "r")
1178 "RenderTexture Warning: mistake in components definition "
1182 if (kv.first == "rg" && (_iNumComponents <= 1))
1184 if (kv.second.find("f") != kv.second.npos)
1187 vector<int> bitVec = _ParseBitVector(kv.second);
1189 if (bitVec.size() < 2) // expand the scalar to a vector
1191 bitVec.push_back(bitVec[0]);
1195 pfAttribs.push_back(WGL_RED_BITS_ARB);
1196 pfAttribs.push_back(bitVec[0]);
1197 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1198 pfAttribs.push_back(bitVec[1]);
1199 #elif defined( __APPLE__ )
1200 pfAttribs.push_back(AGL_RED_SIZE);
1201 pfAttribs.push_back(bitVec[0]);
1202 pfAttribs.push_back(AGL_GREEN_SIZE);
1203 pfAttribs.push_back(bitVec[1]);
1205 pfAttribs.push_back(GLX_RED_SIZE);
1206 pfAttribs.push_back(bitVec[0]);
1207 pfAttribs.push_back(GLX_GREEN_SIZE);
1208 pfAttribs.push_back(bitVec[1]);
1210 _iNumComponents += 2;
1213 else if (kv.first == "rg")
1215 "RenderTexture Warning: mistake in components definition "
1219 if (kv.first == "depth")
1221 if (kv.second == "")
1224 iDepthBits = strtol(kv.second.c_str(), 0, 10);
1228 if (kv.first == "stencil")
1232 pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1233 #elif defined( __APPLE__ )
1234 pfAttribs.push_back(AGL_STENCIL_SIZE);
1236 pfAttribs.push_back(GLX_STENCIL_SIZE);
1238 if (kv.second == "")
1239 pfAttribs.push_back(8);
1241 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1245 if (kv.first == "samples")
1248 pfAttribs.push_back(WGL_SAMPLE_BUFFERS_ARB);
1249 pfAttribs.push_back(1);
1250 pfAttribs.push_back(WGL_SAMPLES_ARB);
1251 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1252 #elif defined( __APPLE__ )
1253 pfAttribs.push_back(AGL_SAMPLE_BUFFERS_ARB);
1254 pfAttribs.push_back(1);
1255 pfAttribs.push_back(AGL_SAMPLES_ARB);
1256 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1258 pfAttribs.push_back(GL_SAMPLE_BUFFERS_ARB);
1259 pfAttribs.push_back(1);
1260 pfAttribs.push_back(GL_SAMPLES_ARB);
1261 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1267 if (kv.first == "doublebuffer" || kv.first == "double")
1270 pfAttribs.push_back(WGL_DOUBLE_BUFFER_ARB);
1271 pfAttribs.push_back(true);
1272 #elif defined( __APPLE__ )
1273 pfAttribs.push_back(AGL_DOUBLEBUFFER);
1274 pfAttribs.push_back(True);
1276 pfAttribs.push_back(GL_DOUBLEBUFFER);
1277 pfAttribs.push_back(True);
1282 if (kv.first == "aux")
1285 pfAttribs.push_back(WGL_AUX_BUFFERS_ARB);
1286 #elif defined( __APPLE__ )
1287 pfAttribs.push_back(AGL_AUX_BUFFERS);
1289 pfAttribs.push_back(GL_AUX_BUFFERS);
1291 if (kv.second == "")
1292 pfAttribs.push_back(0);
1294 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1298 if (token.find("tex") == 0)
1302 if ((kv.first == "texRECT") && GL_NV_texture_rectangle)
1307 else if (kv.first == "texCUBE")
1319 if (token.find("depthTex") == 0)
1321 _bIsDepthTexture = true;
1323 if ((kv.first == "depthTexRECT") && GL_NV_texture_rectangle)
1328 else if (kv.first == "depthTexCUBE")
1340 if (kv.first == "mipmap")
1346 if (kv.first == "rtt")
1348 _eUpdateMode = RT_RENDER_TO_TEXTURE;
1352 if (kv.first == "ctt")
1354 _eUpdateMode = RT_COPY_TO_TEXTURE;
1359 "RenderTexture Error: Unknown pbuffer attribute: %s\n",
1363 // Processing of some options must be last because of interactions.
1365 // Check for inconsistent texture targets
1366 if (_bIsTexture && _bIsDepthTexture && !(bBind2D ^ bBindRECT ^ bBindCUBE))
1369 "RenderTexture Warning: Depth and Color texture targets "
1373 // Apply default bit format if none specified
1375 if (0 == _iNumComponents)
1377 pfAttribs.push_back(WGL_RED_BITS_ARB);
1378 pfAttribs.push_back(8);
1379 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1380 pfAttribs.push_back(8);
1381 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1382 pfAttribs.push_back(8);
1383 pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1384 pfAttribs.push_back(8);
1385 _iNumComponents = 4;
1390 if (_bIsDepthTexture && !iDepthBits)
1394 pfAttribs.push_back(WGL_DEPTH_BITS_ARB);
1395 #elif defined( __APPLE__ )
1396 pfAttribs.push_back(AGL_DEPTH_SIZE);
1398 pfAttribs.push_back(GLX_DEPTH_SIZE);
1400 pfAttribs.push_back(iDepthBits); // default
1405 pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1406 pfAttribs.push_back(0);
1407 #elif defined( __APPLE__ )
1408 pfAttribs.push_back(AGL_STENCIL_SIZE);
1409 pfAttribs.push_back(0);
1411 pfAttribs.push_back(GLX_STENCIL_SIZE);
1412 pfAttribs.push_back(0);
1416 if (_iNumComponents < 4)
1418 // Can't do this right now -- on NVIDIA drivers, currently get
1419 // a non-functioning pbuffer if ALPHA_BITS=0 and
1420 // WGL_BIND_TO_TEXTURE_RGB_ARB=true
1422 //pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1423 //pfAttribs.push_back(0);
1427 if (!WGL_NV_render_depth_texture && _bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1429 #if defined(DEBUG) || defined(_DEBUG)
1430 fprintf(stderr, "RenderTexture Warning: No support found for "
1431 "render to depth texture.\n");
1433 _bIsDepthTexture = false;
1437 if ((_bIsTexture || _bIsDepthTexture) &&
1438 (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1443 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1444 pbAttribs.push_back(WGL_TEXTURE_RECTANGLE_NV);
1448 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1449 pbAttribs.push_back(WGL_TEXTURE_CUBE_MAP_ARB);
1453 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1454 pbAttribs.push_back(WGL_TEXTURE_2D_ARB);
1459 pbAttribs.push_back(WGL_MIPMAP_TEXTURE_ARB);
1460 pbAttribs.push_back(true);
1463 #elif defined(DEBUG) || defined(_DEBUG)
1464 printf("RenderTexture Error: Render to Texture not "
1465 "supported in Linux or MacOS\n");
1469 // Set the pixel type
1473 if (WGL_NV_float_buffer)
1475 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1476 pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1478 pfAttribs.push_back(WGL_FLOAT_COMPONENTS_NV);
1479 pfAttribs.push_back(true);
1483 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1484 pfAttribs.push_back(WGL_TYPE_RGBA_FLOAT_ATI);
1486 #elif defined( __APPLE__ )
1488 if (GL_NV_float_buffer)
1490 pfAttribs.push_back(GLX_FLOAT_COMPONENTS_NV);
1491 pfAttribs.push_back(1);
1498 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1499 pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1503 // Set up texture binding for render to texture
1504 if (_bIsTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1510 if (WGL_NV_float_buffer)
1512 switch(_iNumComponents)
1515 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
1516 pfAttribs.push_back(true);
1518 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1519 pbAttribs.push_back(WGL_TEXTURE_FLOAT_R_NV);
1522 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
1523 pfAttribs.push_back(true);
1525 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1526 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RG_NV);
1529 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
1530 pfAttribs.push_back(true);
1532 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1533 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGB_NV);
1536 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
1537 pfAttribs.push_back(true);
1539 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1540 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGBA_NV);
1544 "RenderTexture Warning: Bad number of components "
1545 "(r=1,rg=2,rgb=3,rgba=4): %d.\n",
1552 if (4 == _iNumComponents)
1554 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1555 pfAttribs.push_back(true);
1557 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1558 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1562 // standard ARB_render_texture only supports 3 or 4 channels
1563 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1564 pfAttribs.push_back(true);
1566 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1567 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1574 switch(_iNumComponents)
1577 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1578 pfAttribs.push_back(true);
1580 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1581 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1584 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1585 pfAttribs.push_back(true);
1587 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1588 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1592 "RenderTexture Warning: Bad number of components "
1593 "(r=1,rg=2,rgb=3,rgba=4): %d.\n", _iNumComponents);
1597 #elif defined(DEBUG) || defined(_DEBUG)
1599 "RenderTexture Error: Render to Texture not supported in "
1600 "Linux or MacOS\ n");
1604 if (_bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1609 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV);
1610 pfAttribs.push_back(true);
1612 pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
1613 pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
1617 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_DEPTH_NV);
1618 pfAttribs.push_back(true);
1620 pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
1621 pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
1623 #elif defined(DEBUG) || defined(_DEBUG)
1624 printf("RenderTexture Error: Render to Texture not supported in "
1625 "Linux or MacOS\n");
1630 //---------------------------------------------------------------------------
1631 // Function : RenderTexture::_GetKeyValuePair
1633 //---------------------------------------------------------------------------
1635 * @fn RenderTexture::_GetKeyValuePair()
1636 * @brief Parses expressions of the form "X=Y" into a pair (X,Y).
1638 RenderTexture::KeyVal RenderTexture::_GetKeyValuePair(string token)
1640 string::size_type pos = 0;
1641 if ((pos = token.find("=")) != token.npos)
1643 string key = token.substr(0, pos);
1644 string value = token.substr(pos+1, token.length()-pos+1);
1645 return KeyVal(key, value);
1648 return KeyVal(token, "");
1651 //---------------------------------------------------------------------------
1652 // Function : RenderTexture::_ParseBitVector
1654 //---------------------------------------------------------------------------
1656 * @fn RenderTexture::_ParseBitVector()
1657 * @brief Parses expressions of the form "=r,g,b,a" into a vector: (r,g,b,a)
1659 vector<int> RenderTexture::_ParseBitVector(string bitVector)
1661 vector<string> pieces;
1664 if (bitVector == "")
1666 bits.push_back(8); // if a depth isn't specified, use default 8 bits
1670 string::size_type pos = 0;
1671 string::size_type nextpos = 0;
1674 nextpos = bitVector.find_first_of(", \n", pos);
1675 pieces.push_back(string(bitVector, pos, nextpos - pos));
1677 } while (nextpos != bitVector.npos );
1679 for ( vector<string>::iterator it = pieces.begin(); it != pieces.end(); it++)
1681 bits.push_back(strtol(it->c_str(), 0, 10));
1687 //---------------------------------------------------------------------------
1688 // Function : RenderTexture::_VerifyExtensions
1690 //---------------------------------------------------------------------------
1692 * @fn RenderTexture::_VerifyExtensions()
1693 * @brief Checks that the necessary extensions are available based on RT mode.
1695 bool RenderTexture::_VerifyExtensions()
1698 if ( !fctPtrInited )
1700 fctPtrInited = true;
1701 wglGetExtensionsStringARBProc wglGetExtensionsStringARBPtr = (wglGetExtensionsStringARBProc)wglGetProcAddress( "wglGetExtensionsStringARB" );
1702 if ( wglGetExtensionsStringARBPtr == 0 )
1704 PrintExtensionError("WGL_ARB_extensions_string");
1707 string wglExtensionsString = wglGetExtensionsStringARBPtr( wglGetCurrentDC() );
1708 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pixel_format" ) )
1710 wglChoosePixelFormatARBPtr = (wglChoosePixelFormatARBProc)SGLookupFunction("wglChoosePixelFormatARB");
1711 wglGetPixelFormatAttribivARBPtr = (wglGetPixelFormatAttribivARBProc)SGLookupFunction("wglGetPixelFormatAttribivARB");
1715 PrintExtensionError("WGL_ARB_pixel_format");
1718 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pbuffer" ) )
1720 wglCreatePbufferARBPtr = (wglCreatePbufferARBProc)SGLookupFunction("wglCreatePbufferARB");
1721 wglGetPbufferDCARBPtr = (wglGetPbufferDCARBProc)SGLookupFunction("wglGetPbufferDCARB");
1722 wglQueryPbufferARBPtr = (wglQueryPbufferARBProc)SGLookupFunction("wglQueryPbufferARB");
1723 wglReleasePbufferDCARBPtr = (wglReleasePbufferDCARBProc)SGLookupFunction("wglReleasePbufferDCARB");
1724 wglDestroyPbufferARBPtr = (wglDestroyPbufferARBProc)SGLookupFunction("wglDestroyPbufferARB");
1728 PrintExtensionError("WGL_ARB_pbuffer");
1731 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_render_texture" ) )
1733 wglBindTexImageARBPtr = (wglBindTexImageARBProc)SGLookupFunction("wglBindTexImageARB");
1734 wglReleaseTexImageARBPtr = (wglReleaseTexImageARBProc)SGLookupFunction("wglReleaseTexImageARB");
1736 else if ( _bIsTexture )
1738 PrintExtensionError("WGL_ARB_render_texture");
1741 if (_bRectangle && !SGIsOpenGLExtensionSupported( "GL_NV_texture_rectangle" ))
1743 PrintExtensionError("GL_NV_texture_rectangle");
1746 if (_bFloat && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) || SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ATI_pixel_format_float" )))
1748 PrintExtensionError("GL_NV_float_buffer or GL_ATI_pixel_format_float");
1752 if (_bFloat && _bIsTexture && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) || SGIsOpenGLExtensionSupported( "GL_ATI_texture_float" )))
1754 PrintExtensionError("NV_float_buffer or ATI_texture_float");
1756 if (_bIsDepthTexture && !SGIsOpenGLExtensionSupported( "GL_ARB_depth_texture" ))
1759 #if defined(_DEBUG) | defined(DEBUG)
1761 "RenderTexture Warning: "
1762 "OpenGL extension GL_ARB_depth_texture not available.\n"
1763 " Using glReadPixels() to emulate behavior.\n");
1765 _bHasARBDepthTexture = false;
1766 //PrintExtensionError("GL_ARB_depth_texture");
1772 #elif defined( __APPLE__ )
1774 if (!GLX_SGIX_pbuffer)
1776 PrintExtensionError("GL_SGIX_pbuffer");
1779 if (!GLX_SGIX_fbconfig)
1781 PrintExtensionError("GL_SGIX_fbconfig");
1784 if (_bIsDepthTexture && !GL_ARB_depth_texture)
1786 PrintExtensionError("GL_ARB_depth_texture");
1789 if (_bFloat && _bIsTexture && !GL_NV_float_buffer)
1791 PrintExtensionError("GL_NV_float_buffer");
1794 if (_eUpdateMode == RT_RENDER_TO_TEXTURE)
1796 PrintExtensionError("Some GLX render texture extension: FIXME!");
1804 //---------------------------------------------------------------------------
1805 // Function : RenderTexture::_InitializeTextures
1807 //---------------------------------------------------------------------------
1809 * @fn RenderTexture::_InitializeTextures()
1810 * @brief Initializes the state of textures used by the RenderTexture.
1812 bool RenderTexture::_InitializeTextures()
1814 // Determine the appropriate texture formats and filtering modes.
1815 if (_bIsTexture || _bIsDepthTexture)
1817 if (_bRectangle && GL_NV_texture_rectangle)
1818 _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
1820 _iTextureTarget = GL_TEXTURE_2D;
1825 glGenTextures(1, (GLuint*)&_iTextureID);
1826 glBindTexture(_iTextureTarget, _iTextureID);
1828 // Use clamp to edge as the default texture wrap mode for all tex
1829 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1830 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1831 // Use NEAREST as the default texture filtering mode.
1832 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1833 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1836 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
1838 GLuint iInternalFormat;
1846 "RenderTexture Error: mipmapped float textures not "
1851 switch(_iNumComponents)
1854 if (GL_NV_float_buffer)
1856 iInternalFormat = (_iNumColorBits[0] > 16) ?
1857 GL_FLOAT_R32_NV : GL_FLOAT_R16_NV;
1859 else if (GL_ATI_texture_float)
1861 iInternalFormat = (_iNumColorBits[0] > 16) ?
1862 GL_LUMINANCE_FLOAT32_ATI :
1863 GL_LUMINANCE_FLOAT16_ATI;
1865 iFormat = GL_LUMINANCE;
1868 if (GL_NV_float_buffer)
1870 iInternalFormat = (_iNumColorBits[0] > 16) ?
1871 GL_FLOAT_RG32_NV : GL_FLOAT_RG16_NV;
1873 else if (GL_ATI_texture_float)
1875 iInternalFormat = (_iNumColorBits[0] > 16) ?
1876 GL_LUMINANCE_ALPHA_FLOAT32_ATI :
1877 GL_LUMINANCE_ALPHA_FLOAT16_ATI;
1879 iFormat = GL_LUMINANCE_ALPHA;
1882 if (GL_NV_float_buffer)
1884 iInternalFormat = (_iNumColorBits[0] > 16) ?
1885 GL_FLOAT_RGB32_NV : GL_FLOAT_RGB16_NV;
1887 else if (GL_ATI_texture_float)
1889 iInternalFormat = (_iNumColorBits[0] > 16) ?
1890 GL_RGB_FLOAT32_ATI : GL_RGB_FLOAT16_ATI;
1895 if (GL_NV_float_buffer)
1897 iInternalFormat = (_iNumColorBits[0] > 16) ?
1898 GL_FLOAT_RGBA32_NV : GL_FLOAT_RGBA16_NV;
1900 else if (GL_ATI_texture_float)
1902 iInternalFormat = (_iNumColorBits[0] > 16) ?
1903 GL_RGBA_FLOAT32_ATI : GL_RGBA_FLOAT16_ATI;
1908 printf("RenderTexture Error: "
1909 "Invalid number of components: %d\n",
1916 if (4 == _iNumComponents)
1918 iInternalFormat = GL_RGBA8;
1923 iInternalFormat = GL_RGB8;
1928 // Allocate the texture image (but pass it no data for now).
1929 glTexImage2D(_iTextureTarget, 0, iInternalFormat,
1930 _iWidth, _iHeight, 0, iFormat, GL_FLOAT, NULL);
1934 if (_bIsDepthTexture)
1936 glGenTextures(1, (GLuint*)&_iDepthTextureID);
1937 glBindTexture(_iTextureTarget, _iDepthTextureID);
1939 // Use clamp to edge as the default texture wrap mode for all tex
1940 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1941 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1942 // Use NEAREST as the default texture filtering mode.
1943 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1944 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1946 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
1949 if (_bHasARBDepthTexture)
1951 // Allocate the texture image (but pass it no data for now).
1952 glTexImage2D(_iTextureTarget, 0, GL_DEPTH_COMPONENT,
1953 _iWidth, _iHeight, 0, GL_DEPTH_COMPONENT,
1958 // allocate memory for depth texture
1959 // Since this is slow, we warn the user in debug mode. (above)
1960 _pPoorDepthTexture = new unsigned short[_iWidth * _iHeight];
1961 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
1962 _iWidth, _iHeight, 0, GL_LUMINANCE,
1963 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
1973 //---------------------------------------------------------------------------
1974 // Function : RenderTexture::_MaybeCopyBuffer
1976 //---------------------------------------------------------------------------
1978 * @fn RenderTexture::_MaybeCopyBuffer()
1979 * @brief Does the actual copying for RenderTextures with RT_COPY_TO_TEXTURE
1981 void RenderTexture::_MaybeCopyBuffer()
1984 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
1988 glBindTexture(_iTextureTarget, _iTextureID);
1989 glCopyTexSubImage2D(_iTextureTarget,
1990 0, 0, 0, 0, 0, _iWidth, _iHeight);
1992 if (_bIsDepthTexture)
1994 glBindTexture(_iTextureTarget, _iDepthTextureID);
1995 // HOW TO COPY DEPTH TEXTURE??? Supposedly this just magically works...
1997 if (_bHasARBDepthTexture)
1999 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0,
2004 // no 'real' depth texture available, so behavior has to be emulated
2005 // using glReadPixels (beware, this is (naturally) slow ...)
2006 glReadPixels(0, 0, _iWidth, _iHeight, GL_DEPTH_COMPONENT,
2007 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2008 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
2009 _iWidth, _iHeight, 0, GL_LUMINANCE,
2010 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2019 glBindTexture(_iTextureTarget, _iTextureID);
2020 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2022 if (_bIsDepthTexture)
2024 glBindTexture(_iTextureTarget, _iDepthTextureID);
2025 assert(_bHasARBDepthTexture);
2026 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2032 //---------------------------------------------------------------------------
2033 // Function : RenderTexture::_ReleaseBoundBuffers
2035 //---------------------------------------------------------------------------
2037 * @fn RenderTexture::_ReleaseBoundBuffers()
2038 * @brief Releases buffer bindings on RenderTextures with RT_RENDER_TO_TEXTURE
2040 bool RenderTexture::_ReleaseBoundBuffers()
2043 if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2045 glBindTexture(_iTextureTarget, _iTextureID);
2047 // release the pbuffer from the render texture object
2048 if (0 != _iCurrentBoundBuffer && _bIsBufferBound)
2050 if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, _iCurrentBoundBuffer))
2055 _bIsBufferBound = false;
2059 if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2061 glBindTexture(_iTextureTarget, _iDepthTextureID);
2063 // release the pbuffer from the render texture object
2064 if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
2072 // textures can't be bound in Linux
2077 //---------------------------------------------------------------------------
2078 // Function : RenderTexture::_MakeCurrent
2080 //---------------------------------------------------------------------------
2082 * @fn RenderTexture::_MakeCurrent()
2083 * @brief Makes the RenderTexture's context current
2086 bool RenderTexture::_MakeCurrent()
2089 // make the pbuffer's rendering context current.
2090 if (FALSE == wglMakeCurrent( _hDC, _hGLContext))
2095 #elif defined( __APPLE__ )
2097 if (false == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
2106 /////////////////////////////////////////////////////////////////////////////
2108 // Begin Deprecated Interface
2110 /////////////////////////////////////////////////////////////////////////////
2112 //---------------------------------------------------------------------------
2113 // Function : RenderTexture::RenderTexture
2115 //---------------------------------------------------------------------------
2117 * @fn RenderTexture::RenderTexture()
2118 * @brief Constructor.
2120 RenderTexture::RenderTexture(int width, int height,
2121 bool bIsTexture /* = true */,
2122 bool bIsDepthTexture /* = false */)
2125 _bIsTexture(bIsTexture),
2126 _bIsDepthTexture(bIsDepthTexture),
2127 _bHasARBDepthTexture(true), // [Redge]
2128 _eUpdateMode(RT_RENDER_TO_TEXTURE),
2129 _bInitialized(false),
2131 _iCurrentBoundBuffer(0),
2133 _iNumStencilBits(0),
2134 _bDoubleBuffered(false),
2139 _bShareObjects(false),
2140 _bCopyContext(false),
2146 _hPreviousContext(0),
2147 #elif defined( __APPLE__ )
2152 _hPreviousContext(0),
2153 _hPreviousDrawable(0),
2155 _iTextureTarget(GL_NONE),
2157 _iDepthTextureID(0),
2158 _pPoorDepthTexture(0) // [Redge]
2160 assert(width > 0 && height > 0);
2161 #if defined DEBUG || defined _DEBUG
2163 "RenderTexture Warning: Deprecated Contructor interface used.\n");
2166 _iNumColorBits[0] = _iNumColorBits[1] =
2167 _iNumColorBits[2] = _iNumColorBits[3] = 0;
2168 _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
2171 //------------------------------------------------------------------------------
2172 // Function : RenderTexture::Initialize
2174 //------------------------------------------------------------------------------
2176 * @fn RenderTexture::Initialize(bool bShare, bool bDepth, bool bStencil, bool bMipmap, unsigned int iRBits, unsigned int iGBits, unsigned int iBBits, unsigned int iABits);
2177 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
2179 * This function actually does the creation of the p-buffer. It can only be called
2180 * once a GL context has already been created. Note that if the texture is not
2181 * power of two dimensioned, or has more than 8 bits per channel, enabling mipmapping
2182 * will cause an error.
2184 bool RenderTexture::Initialize(bool bShare /* = true */,
2185 bool bDepth /* = false */,
2186 bool bStencil /* = false */,
2187 bool bMipmap /* = false */,
2188 bool bAnisoFilter /* = false */,
2189 unsigned int iRBits /* = 8 */,
2190 unsigned int iGBits /* = 8 */,
2191 unsigned int iBBits /* = 8 */,
2192 unsigned int iABits /* = 8 */,
2193 UpdateMode updateMode /* = RT_RENDER_TO_TEXTURE */)
2195 if (0 == _iWidth || 0 == _iHeight)
2198 #if defined DEBUG || defined _DEBUG
2200 "RenderTexture Warning: Deprecated Initialize() interface used.\n");
2203 // create a mode string.
2206 mode.append("depth ");
2208 mode.append("stencil ");
2210 mode.append("mipmap ");
2211 if (iRBits + iGBits + iBBits + iABits > 0)
2222 char bitVector[100];
2224 "%d%s,%d%s,%d%s,%d%s",
2225 iRBits, (iRBits >= 16) ? "f" : "",
2226 iGBits, (iGBits >= 16) ? "f" : "",
2227 iBBits, (iBBits >= 16) ? "f" : "",
2228 iABits, (iABits >= 16) ? "f" : "");
2229 mode.append(bitVector);
2234 if (GL_NV_texture_rectangle &&
2235 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2236 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2237 mode.append("texRECT ");
2239 mode.append("tex2D ");
2241 if (_bIsDepthTexture)
2243 if (GL_NV_texture_rectangle &&
2244 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2245 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2246 mode.append("texRECT ");
2248 mode.append("tex2D ");
2250 if (RT_COPY_TO_TEXTURE == updateMode)
2253 _pixelFormatAttribs.clear();
2254 _pbufferAttribs.clear();
2257 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
2258 _pixelFormatAttribs.push_back(true);
2259 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
2260 _pixelFormatAttribs.push_back(true);
2262 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
2263 _pbufferAttribs.push_back(true);
2264 #elif defined( __APPLE__ )
2266 _pixelFormatAttribs.push_back(GLX_RENDER_TYPE_SGIX);
2267 _pixelFormatAttribs.push_back(GLX_RGBA_BIT_SGIX);
2268 _pixelFormatAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
2269 _pixelFormatAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
2272 _ParseModeString(mode.c_str(), _pixelFormatAttribs, _pbufferAttribs);
2275 _pixelFormatAttribs.push_back(0);
2276 _pbufferAttribs.push_back(0);
2278 _pixelFormatAttribs.push_back(None);
2281 Initialize(_iWidth, _iHeight, bShare);
2287 //---------------------------------------------------------------------------
2288 // Function : RenderTexture::Reset
2290 //---------------------------------------------------------------------------
2292 * @fn RenderTexture::Reset(int iWidth, int iHeight, unsigned int iMode, bool bIsTexture, bool bIsDepthTexture)
2293 * @brief Resets the resolution of the offscreen buffer.
2295 * Causes the buffer to delete itself. User must call Initialize() again
2298 bool RenderTexture::Reset(int iWidth, int iHeight)
2301 "RenderTexture Warning: Deprecated Reset() interface used.\n");
2305 fprintf(stderr, "RenderTexture::Reset(): failed to invalidate.\n");