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),
129 _hPreviousContext(0),
130 _hPreviousDrawable(0),
132 _iTextureTarget(GL_NONE),
135 _pPoorDepthTexture(0) // [Redge]
137 _iNumColorBits[0] = _iNumColorBits[1] =
138 _iNumColorBits[2] = _iNumColorBits[3] = 0;
141 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
142 _pixelFormatAttribs.push_back(true);
143 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
144 _pixelFormatAttribs.push_back(true);
146 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
147 _pbufferAttribs.push_back(true);
149 _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
150 _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
151 _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
152 _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
155 _ParseModeString(strMode, _pixelFormatAttribs, _pbufferAttribs);
158 _pixelFormatAttribs.push_back(0);
159 _pbufferAttribs.push_back(0);
161 _pixelFormatAttribs.push_back(None);
166 //---------------------------------------------------------------------------
167 // Function : RenderTexture::~RenderTexture
169 //---------------------------------------------------------------------------
171 * @fn RenderTexture::~RenderTexture()
174 RenderTexture::~RenderTexture()
180 //---------------------------------------------------------------------------
181 // Function : _wglGetLastError
183 //---------------------------------------------------------------------------
185 * @fn wglGetLastError()
186 * @brief Returns the last windows error generated.
189 void _wglGetLastError()
193 DWORD err = GetLastError();
196 case ERROR_INVALID_PIXEL_FORMAT:
198 "RenderTexture Win32 Error: ERROR_INVALID_PIXEL_FORMAT\n");
200 case ERROR_NO_SYSTEM_RESOURCES:
202 "RenderTexture Win32 Error: ERROR_NO_SYSTEM_RESOURCES\n");
204 case ERROR_INVALID_DATA:
206 "RenderTexture Win32 Error: ERROR_INVALID_DATA\n");
208 case ERROR_INVALID_WINDOW_HANDLE:
210 "RenderTexture Win32 Error: ERROR_INVALID_WINDOW_HANDLE\n");
212 case ERROR_RESOURCE_TYPE_NOT_FOUND:
214 "RenderTexture Win32 Error: ERROR_RESOURCE_TYPE_NOT_FOUND\n");
221 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
222 FORMAT_MESSAGE_FROM_SYSTEM |
223 FORMAT_MESSAGE_IGNORE_INSERTS,
226 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
231 fprintf(stderr, "RenderTexture Win32 Error %d: %s\n", err, lpMsgBuf);
232 LocalFree( lpMsgBuf );
241 //---------------------------------------------------------------------------
242 // Function : PrintExtensionError
244 //---------------------------------------------------------------------------
246 * @fn PrintExtensionError( char* strMsg, ... )
247 * @brief Prints an error about missing OpenGL extensions.
249 void PrintExtensionError( char* strMsg, ... )
252 "Error: RenderTexture requires the following unsupported "
253 "OpenGL extensions: \n");
256 va_start(args, strMsg);
257 #if defined _WIN32 && !defined __CYGWIN__
258 _vsnprintf( strBuffer, 512, strMsg, args );
260 vsnprintf( strBuffer, 512, strMsg, args );
264 fprintf(stderr, strMsg);
268 //---------------------------------------------------------------------------
269 // Function : RenderTexture::Initialize
271 //---------------------------------------------------------------------------
273 * @fn RenderTexture::Initialize(int width, int height, bool shareObjects, bool copyContext);
274 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
276 * This function creates of the p-buffer. It can only be called once a GL
277 * context has already been created.
279 bool RenderTexture::Initialize(int width, int height,
280 bool shareObjects /* = true */,
281 bool copyContext /* = false */)
283 assert(width > 0 && height > 0);
285 _iWidth = width; _iHeight = height;
286 _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
288 _bShareObjects = shareObjects;
289 _bCopyContext = copyContext;
291 // Check if this is an NVXX GPU and verify necessary extensions.
292 if (!_VerifyExtensions())
299 // Get the current context.
300 HDC hdc = wglGetCurrentDC();
303 HGLRC hglrc = wglGetCurrentContext();
308 unsigned int iNumFormats;
312 // Get the pixel format for the on-screen window.
313 iFormat = GetPixelFormat(hdc);
317 "RenderTexture Error: GetPixelFormat() failed.\n");
323 if (!wglChoosePixelFormatARBPtr(hdc, &_pixelFormatAttribs[0], NULL,
324 1, &iFormat, &iNumFormats))
327 "RenderTexture Error: wglChoosePixelFormatARB() failed.\n");
331 if ( iNumFormats <= 0 )
334 "RenderTexture Error: Couldn't find a suitable "
341 // Create the p-buffer.
342 _hPBuffer = wglCreatePbufferARBPtr(hdc, iFormat, _iWidth, _iHeight,
343 &_pbufferAttribs[0]);
347 "RenderTexture Error: wglCreatePbufferARB() failed.\n");
352 // Get the device context.
353 _hDC = wglGetPbufferDCARBPtr( _hPBuffer);
357 "RenderTexture Error: wglGetGetPbufferDCARB() failed.\n");
362 // Create a gl context for the p-buffer.
365 // Let's use the same gl context..
366 // Since the device contexts are compatible (i.e. same pixelformat),
367 // we should be able to use the same gl rendering context.
372 _hGLContext = wglCreateContext( _hDC );
376 "RenderTexture Error: wglCreateContext() failed.\n");
382 // Share lists, texture objects, and program objects.
385 if( !wglShareLists(hglrc, _hGLContext) )
388 "RenderTexture Error: wglShareLists() failed.\n");
394 // Determine the actual width and height we were able to create.
395 wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
396 wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
398 _bInitialized = true;
400 // get the actual number of bits allocated:
401 int attrib = WGL_RED_BITS_ARB;
405 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
407 attrib = WGL_GREEN_BITS_ARB;
409 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
411 attrib = WGL_BLUE_BITS_ARB;
413 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
415 attrib = WGL_ALPHA_BITS_ARB;
417 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
419 attrib = WGL_DEPTH_BITS_ARB;
421 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
423 attrib = WGL_STENCIL_BITS_ARB;
425 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
427 attrib = WGL_DOUBLE_BUFFER_ARB;
429 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
430 ? (value?true:false) : false;
432 #if defined(_DEBUG) | defined(DEBUG)
433 fprintf(stderr, "Created a %dx%d RenderTexture with BPP(%d, %d, %d, %d)",
435 _iNumColorBits[0], _iNumColorBits[1],
436 _iNumColorBits[2], _iNumColorBits[3]);
437 if (_iNumDepthBits) fprintf(stderr, " depth=%d", _iNumDepthBits);
438 if (_iNumStencilBits) fprintf(stderr, " stencil=%d", _iNumStencilBits);
439 if (_bDoubleBuffered) fprintf(stderr, " double buffered");
440 fprintf(stderr, "\n");
444 _pDisplay = glXGetCurrentDisplay();
445 GLXContext context = glXGetCurrentContext();
446 int screen = DefaultScreen(_pDisplay);
447 XVisualInfo *visInfo;
453 GLXFBConfigSGIX *fbConfigs;
456 fbConfigs = glXChooseFBConfigSGIX(_pDisplay, screen,
457 &_pixelFormatAttribs[0], &nConfigs);
459 if (nConfigs == 0 || !fbConfigs)
462 "RenderTexture Error: Couldn't find a suitable pixel format.\n");
466 // Pick the first returned format that will return a pbuffer
467 for (int i=0;i<nConfigs;i++)
469 _hPBuffer = glXCreateGLXPbufferSGIX(_pDisplay, fbConfigs[i],
470 _iWidth, _iHeight, NULL);
473 _hGLContext = glXCreateContextWithConfigSGIX(_pDisplay,
476 _bShareObjects ? context : NULL,
485 "RenderTexture Error: glXCreateGLXPbufferSGIX() failed.\n");
492 _hGLContext = glXCreateContext(_pDisplay, visInfo,
493 _bShareObjects ? context : NULL, False);
497 "RenderTexture Error: glXCreateContext() failed.\n");
502 glXQueryGLXPbufferSGIX(_pDisplay, _hPBuffer, GLX_WIDTH_SGIX,
504 glXQueryGLXPbufferSGIX(_pDisplay, _hPBuffer, GLX_HEIGHT_SGIX,
507 _bInitialized = true;
509 // XXX Query the color format
514 // Now that the pbuffer is created, allocate any texture objects needed,
515 // and initialize them (for CTT updates only). These must be allocated
516 // in the context of the pbuffer, though, or the RT won't work without
519 if (false == wglMakeCurrent( _hDC, _hGLContext))
525 _hPreviousContext = glXGetCurrentContext();
526 _hPreviousDrawable = glXGetCurrentDrawable();
528 if (False == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
534 bool result = _InitializeTextures();
536 BindBuffer(WGL_FRONT_LEFT_ARB);
542 // make the previous rendering context current
543 if (false == wglMakeCurrent( hdc, hglrc))
549 if (False == glXMakeCurrent(_pDisplay,
550 _hPreviousDrawable, _hPreviousContext))
560 //---------------------------------------------------------------------------
561 // Function : RenderTexture::_Invalidate
563 //---------------------------------------------------------------------------
565 * @fn RenderTexture::_Invalidate()
566 * @brief Returns the pbuffer memory to the graphics device.
569 bool RenderTexture::_Invalidate()
571 _iNumColorBits[0] = _iNumColorBits[1] =
572 _iNumColorBits[2] = _iNumColorBits[3] = 0;
574 _iNumStencilBits = 0;
577 glDeleteTextures(1, &_iTextureID);
578 if (_bIsDepthTexture)
581 if (!_bHasARBDepthTexture) delete[] _pPoorDepthTexture;
583 glDeleteTextures(1, &_iDepthTextureID);
589 // Check if we are currently rendering in the pbuffer
590 if (wglGetCurrentContext() == _hGLContext)
593 wglDeleteContext( _hGLContext);
594 wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
595 wglDestroyPbufferARBPtr( _hPBuffer );
602 if(glXGetCurrentContext() == _hGLContext)
603 // XXX I don't know if this is right at all
604 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
605 glXDestroyGLXPbufferSGIX(_pDisplay, _hPBuffer);
611 // [WVB] do we need to call _ReleaseBoundBuffers() too?
616 //---------------------------------------------------------------------------
617 // Function : RenderTexture::Reset
619 //---------------------------------------------------------------------------
621 * @fn RenderTexture::Reset()
622 * @brief Resets the resolution of the offscreen buffer.
624 * Causes the buffer to delete itself. User must call Initialize() again
627 bool RenderTexture::Reset(const char *strMode, ...)
629 _iWidth = 0; _iHeight = 0;
630 _bIsTexture = false; _bIsDepthTexture = false,
631 _bHasARBDepthTexture = true;
633 _eUpdateMode = RT_RENDER_TO_TEXTURE;
635 _eUpdateMode = RT_COPY_TO_TEXTURE;
637 _bInitialized = false;
639 _bIsBufferBound = false;
640 _iCurrentBoundBuffer = 0;
641 _iNumDepthBits = 0; _iNumStencilBits = 0;
642 _bDoubleBuffered = false;
643 _bFloat = false; _bPowerOf2 = true;
644 _bRectangle = false; _bMipmap = false;
645 _bShareObjects = false; _bCopyContext = false;
646 _iTextureTarget = GL_NONE; _iTextureID = 0;
647 _iDepthTextureID = 0;
648 _pPoorDepthTexture = 0;
649 _pixelFormatAttribs.clear();
650 _pbufferAttribs.clear();
652 if (IsInitialized() && !_Invalidate())
654 fprintf(stderr, "RenderTexture::Reset(): failed to invalidate.\n");
658 _iNumColorBits[0] = _iNumColorBits[1] =
659 _iNumColorBits[2] = _iNumColorBits[3] = 0;
662 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
663 _pixelFormatAttribs.push_back(true);
664 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
665 _pixelFormatAttribs.push_back(true);
667 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
668 _pbufferAttribs.push_back(true);
670 _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
671 _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
672 _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
673 _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
678 va_start(args,strMode);
679 #if defined _WIN32 && !defined __CYGWIN__
680 _vsnprintf( strBuffer, 256, strMode, args );
682 vsnprintf( strBuffer, 256, strMode, args );
686 _ParseModeString(strBuffer, _pixelFormatAttribs, _pbufferAttribs);
689 _pixelFormatAttribs.push_back(0);
690 _pbufferAttribs.push_back(0);
692 _pixelFormatAttribs.push_back(None);
697 //------------------------------------------------------------------------------
698 // Function : RenderTexture::Resize
700 //------------------------------------------------------------------------------
702 * @fn RenderTexture::Resize(int iWidth, int iHeight)
703 * @brief Changes the size of the offscreen buffer.
705 * Like Reset() this causes the buffer to delete itself.
706 * But unlike Reset(), this call re-initializes the RenderTexture.
707 * Note that Resize() will not work after calling Reset(), or before
708 * calling Initialize() the first time.
710 bool RenderTexture::Resize(int iWidth, int iHeight)
712 if (!_bInitialized) {
713 fprintf(stderr, "RenderTexture::Resize(): must Initialize() first.\n");
716 if (iWidth == _iWidth && iHeight == _iHeight) {
720 // Do same basic work as _Invalidate, but don't reset all our flags
722 glDeleteTextures(1, &_iTextureID);
723 if (_bIsDepthTexture)
724 glDeleteTextures(1, &_iDepthTextureID);
728 // Check if we are currently rendering in the pbuffer
729 if (wglGetCurrentContext() == _hGLContext)
732 wglDeleteContext( _hGLContext);
733 wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
734 wglDestroyPbufferARBPtr( _hPBuffer );
741 if(glXGetCurrentContext() == _hGLContext)
742 // XXX I don't know if this is right at all
743 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
744 glXDestroyGLXPbufferSGIX(_pDisplay, _hPBuffer);
749 fprintf(stderr, "RenderTexture::Resize(): failed to resize.\n");
752 _bInitialized = false;
753 return Initialize(iWidth, iHeight, _bShareObjects, _bCopyContext);
756 //---------------------------------------------------------------------------
757 // Function : RenderTexture::BeginCapture
759 //---------------------------------------------------------------------------
761 * @fn RenderTexture::BeginCapture()
762 * @brief Activates rendering to the RenderTexture.
764 bool RenderTexture::BeginCapture()
769 "RenderTexture::BeginCapture(): Texture is not initialized!\n");
773 // cache the current context so we can reset it when EndCapture() is called.
774 _hPreviousDC = wglGetCurrentDC();
775 if (NULL == _hPreviousDC)
777 _hPreviousContext = wglGetCurrentContext();
778 if (NULL == _hPreviousContext)
781 _hPreviousContext = glXGetCurrentContext();
782 _hPreviousDrawable = glXGetCurrentDrawable();
785 _ReleaseBoundBuffers();
787 return _MakeCurrent();
791 //---------------------------------------------------------------------------
792 // Function : RenderTexture::EndCapture
794 //---------------------------------------------------------------------------
796 * @fn RenderTexture::EndCapture()
797 * @brief Ends rendering to the RenderTexture.
799 bool RenderTexture::EndCapture()
804 "RenderTexture::EndCapture() : Texture is not initialized!\n");
811 // make the previous rendering context current
812 if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
818 if (False == glXMakeCurrent(_pDisplay, _hPreviousDrawable,
825 // rebind the textures to a buffers for RTT
826 BindBuffer(_iCurrentBoundBuffer);
832 //---------------------------------------------------------------------------
833 // Function : RenderTexture::BeginCapture(RenderTexture*)
835 //---------------------------------------------------------------------------
837 * @fn RenderTexture::BeginCapture(RenderTexture* other)
838 * @brief Ends capture of 'other', begins capture on 'this'
840 * When performing a series of operations where you modify one texture after
841 * another, it is more efficient to use this method instead of the equivalent
842 * 'EndCapture'/'BeginCapture' pair. This method switches directly to the
843 * new context rather than changing to the default context, and then to the
846 * RenderTexture doesn't have any mechanism for determining if
847 * 'current' really is currently active, so no error will be thrown
850 bool RenderTexture::BeginCapture(RenderTexture* current)
852 bool bContextReset = false;
854 if (current == this) {
855 return true; // no switch necessary
858 // treat as normal Begin if current is 0.
859 return BeginCapture();
864 "RenderTexture::BeginCapture(RenderTexture*): Texture is not initialized!\n");
867 if (!current->_bInitialized)
870 "RenderTexture::BeginCapture(RenderTexture): 'current' texture is not initialized!\n");
874 // Sync current pbuffer with its CTT texture if necessary
875 current->_MaybeCopyBuffer();
877 // pass along the previous context so we can reset it when
878 // EndCapture() is called.
880 _hPreviousDC = current->_hPreviousDC;
881 if (NULL == _hPreviousDC)
883 _hPreviousContext = current->_hPreviousContext;
884 if (NULL == _hPreviousContext)
887 _hPreviousContext = current->_hPreviousContext;
888 _hPreviousDrawable = current->_hPreviousDrawable;
891 // Unbind textures before making context current
892 if (!_ReleaseBoundBuffers())
895 // Make the pbuffer context current
899 // Rebind buffers of initial RenderTexture
900 current->BindBuffer(_iCurrentBoundBuffer);
901 current->_BindDepthBuffer();
908 //---------------------------------------------------------------------------
909 // Function : RenderTexture::Bind
911 //---------------------------------------------------------------------------
913 * @fn RenderTexture::Bind()
914 * @brief Binds RGB texture.
916 void RenderTexture::Bind() const
918 if (_bInitialized && _bIsTexture)
920 glBindTexture(_iTextureTarget, _iTextureID);
925 //---------------------------------------------------------------------------
926 // Function : RenderTexture::BindDepth
928 //---------------------------------------------------------------------------
930 * @fn RenderTexture::BindDepth()
931 * @brief Binds depth texture.
933 void RenderTexture::BindDepth() const
935 if (_bInitialized && _bIsDepthTexture)
937 glBindTexture(_iTextureTarget, _iDepthTextureID);
942 //---------------------------------------------------------------------------
943 // Function : RenderTexture::BindBuffer
945 //---------------------------------------------------------------------------
947 * @fn RenderTexture::BindBuffer()
948 * @brief Associate the RTT texture id with 'iBuffer' (e.g. WGL_FRONT_LEFT_ARB)
950 bool RenderTexture::BindBuffer( int iBuffer )
952 // Must bind the texture too
953 if (_bInitialized && _bIsTexture)
955 glBindTexture(_iTextureTarget, _iTextureID);
958 if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
959 (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
961 if (FALSE == wglBindTexImageARBPtr(_hPBuffer, iBuffer))
963 // WVB: WGL API considers binding twice to the same buffer
964 // to be an error. But we don't want to
965 //_wglGetLastError();
969 _bIsBufferBound = true;
970 _iCurrentBoundBuffer = iBuffer;
978 //---------------------------------------------------------------------------
979 // Function : RenderTexture::BindBuffer
981 //---------------------------------------------------------------------------
983 * @fn RenderTexture::_BindDepthBuffer()
984 * @brief Associate the RTT depth texture id with the depth buffer
986 bool RenderTexture::_BindDepthBuffer() const
989 if (_bInitialized && _bIsDepthTexture &&
990 RT_RENDER_TO_TEXTURE == _eUpdateMode)
992 glBindTexture(_iTextureTarget, _iDepthTextureID);
993 if (FALSE == wglBindTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1003 //---------------------------------------------------------------------------
1004 // Function : RenderTexture::_ParseModeString
1006 //---------------------------------------------------------------------------
1008 * @fn RenderTexture::_ParseModeString()
1009 * @brief Parses the user-specified mode string for RenderTexture parameters.
1011 void RenderTexture::_ParseModeString(const char *modeString,
1012 vector<int> &pfAttribs,
1013 vector<int> &pbAttribs)
1015 if (!modeString || strcmp(modeString, "") == 0)
1018 _iNumComponents = 0;
1020 _eUpdateMode = RT_RENDER_TO_TEXTURE;
1022 _eUpdateMode = RT_COPY_TO_TEXTURE;
1026 bool bHasStencil = false;
1027 bool bBind2D = false;
1028 bool bBindRECT = false;
1029 bool bBindCUBE = false;
1031 char *mode = strdup(modeString);
1034 vector<string> tokens;
1035 char *buf = strtok(mode, " ");
1038 tokens.push_back(buf);
1039 buf = strtok(NULL, " ");
1042 for (unsigned int i = 0; i < tokens.size(); i++)
1044 string token = tokens[i];
1046 KeyVal kv = _GetKeyValuePair(token);
1049 if (kv.first == "rgb" && (_iNumComponents <= 1))
1051 if (kv.second.find("f") != kv.second.npos)
1054 vector<int> bitVec = _ParseBitVector(kv.second);
1056 if (bitVec.size() < 3) // expand the scalar to a vector
1058 bitVec.push_back(bitVec[0]);
1059 bitVec.push_back(bitVec[0]);
1063 pfAttribs.push_back(WGL_RED_BITS_ARB);
1064 pfAttribs.push_back(bitVec[0]);
1065 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1066 pfAttribs.push_back(bitVec[1]);
1067 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1068 pfAttribs.push_back(bitVec[2]);
1071 pfAttribs.push_back(GLX_RED_SIZE);
1072 pfAttribs.push_back(bitVec[0]);
1073 pfAttribs.push_back(GLX_GREEN_SIZE);
1074 pfAttribs.push_back(bitVec[1]);
1075 pfAttribs.push_back(GLX_BLUE_SIZE);
1076 pfAttribs.push_back(bitVec[2]);
1079 _iNumComponents += 3;
1082 else if (kv.first == "rgb")
1084 "RenderTexture Warning: mistake in components definition "
1089 if (kv.first == "rgba" && (_iNumComponents == 0))
1091 if (kv.second.find("f") != kv.second.npos)
1094 vector<int> bitVec = _ParseBitVector(kv.second);
1096 if (bitVec.size() < 4) // expand the scalar to a vector
1098 bitVec.push_back(bitVec[0]);
1099 bitVec.push_back(bitVec[0]);
1100 bitVec.push_back(bitVec[0]);
1104 pfAttribs.push_back(WGL_RED_BITS_ARB);
1105 pfAttribs.push_back(bitVec[0]);
1106 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1107 pfAttribs.push_back(bitVec[1]);
1108 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1109 pfAttribs.push_back(bitVec[2]);
1110 pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1111 pfAttribs.push_back(bitVec[3]);
1114 pfAttribs.push_back(GLX_RED_SIZE);
1115 pfAttribs.push_back(bitVec[0]);
1116 pfAttribs.push_back(GLX_GREEN_SIZE);
1117 pfAttribs.push_back(bitVec[1]);
1118 pfAttribs.push_back(GLX_BLUE_SIZE);
1119 pfAttribs.push_back(bitVec[2]);
1120 pfAttribs.push_back(GLX_ALPHA_SIZE);
1121 pfAttribs.push_back(bitVec[3]);
1124 _iNumComponents = 4;
1127 else if (kv.first == "rgba")
1129 "RenderTexture Warning: mistake in components definition "
1133 if (kv.first == "r" && (_iNumComponents <= 1))
1135 if (kv.second.find("f") != kv.second.npos)
1138 vector<int> bitVec = _ParseBitVector(kv.second);
1141 pfAttribs.push_back(WGL_RED_BITS_ARB);
1142 pfAttribs.push_back(bitVec[0]);
1144 pfAttribs.push_back(GLX_RED_SIZE);
1145 pfAttribs.push_back(bitVec[0]);
1150 else if (kv.first == "r")
1152 "RenderTexture Warning: mistake in components definition "
1156 if (kv.first == "rg" && (_iNumComponents <= 1))
1158 if (kv.second.find("f") != kv.second.npos)
1161 vector<int> bitVec = _ParseBitVector(kv.second);
1163 if (bitVec.size() < 2) // expand the scalar to a vector
1165 bitVec.push_back(bitVec[0]);
1169 pfAttribs.push_back(WGL_RED_BITS_ARB);
1170 pfAttribs.push_back(bitVec[0]);
1171 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1172 pfAttribs.push_back(bitVec[1]);
1174 pfAttribs.push_back(GLX_RED_SIZE);
1175 pfAttribs.push_back(bitVec[0]);
1176 pfAttribs.push_back(GLX_GREEN_SIZE);
1177 pfAttribs.push_back(bitVec[1]);
1179 _iNumComponents += 2;
1182 else if (kv.first == "rg")
1184 "RenderTexture Warning: mistake in components definition "
1188 if (kv.first == "depth")
1190 if (kv.second == "")
1193 iDepthBits = strtol(kv.second.c_str(), 0, 10);
1197 if (kv.first == "stencil")
1201 pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1203 pfAttribs.push_back(GLX_STENCIL_SIZE);
1205 if (kv.second == "")
1206 pfAttribs.push_back(8);
1208 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1212 if (kv.first == "samples")
1215 pfAttribs.push_back(WGL_SAMPLE_BUFFERS_ARB);
1216 pfAttribs.push_back(1);
1217 pfAttribs.push_back(WGL_SAMPLES_ARB);
1218 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1220 pfAttribs.push_back(GL_SAMPLE_BUFFERS_ARB);
1221 pfAttribs.push_back(1);
1222 pfAttribs.push_back(GL_SAMPLES_ARB);
1223 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1229 if (kv.first == "doublebuffer" || kv.first == "double")
1232 pfAttribs.push_back(WGL_DOUBLE_BUFFER_ARB);
1233 pfAttribs.push_back(true);
1235 pfAttribs.push_back(GL_DOUBLEBUFFER);
1236 pfAttribs.push_back(True);
1241 if (kv.first == "aux")
1244 pfAttribs.push_back(WGL_AUX_BUFFERS_ARB);
1246 pfAttribs.push_back(GL_AUX_BUFFERS);
1248 if (kv.second == "")
1249 pfAttribs.push_back(0);
1251 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1255 if (token.find("tex") == 0)
1259 if ((kv.first == "texRECT") && GL_NV_texture_rectangle)
1264 else if (kv.first == "texCUBE")
1276 if (token.find("depthTex") == 0)
1278 _bIsDepthTexture = true;
1280 if ((kv.first == "depthTexRECT") && GL_NV_texture_rectangle)
1285 else if (kv.first == "depthTexCUBE")
1297 if (kv.first == "mipmap")
1303 if (kv.first == "rtt")
1305 _eUpdateMode = RT_RENDER_TO_TEXTURE;
1309 if (kv.first == "ctt")
1311 _eUpdateMode = RT_COPY_TO_TEXTURE;
1316 "RenderTexture Error: Unknown pbuffer attribute: %s\n",
1320 // Processing of some options must be last because of interactions.
1322 // Check for inconsistent texture targets
1323 if (_bIsTexture && _bIsDepthTexture && !(bBind2D ^ bBindRECT ^ bBindCUBE))
1326 "RenderTexture Warning: Depth and Color texture targets "
1330 // Apply default bit format if none specified
1332 if (0 == _iNumComponents)
1334 pfAttribs.push_back(WGL_RED_BITS_ARB);
1335 pfAttribs.push_back(8);
1336 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1337 pfAttribs.push_back(8);
1338 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1339 pfAttribs.push_back(8);
1340 pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1341 pfAttribs.push_back(8);
1342 _iNumComponents = 4;
1347 if (_bIsDepthTexture && !iDepthBits)
1351 pfAttribs.push_back(WGL_DEPTH_BITS_ARB);
1353 pfAttribs.push_back(GLX_DEPTH_SIZE);
1355 pfAttribs.push_back(iDepthBits); // default
1360 pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1361 pfAttribs.push_back(0);
1363 pfAttribs.push_back(GLX_STENCIL_SIZE);
1364 pfAttribs.push_back(0);
1368 if (_iNumComponents < 4)
1370 // Can't do this right now -- on NVIDIA drivers, currently get
1371 // a non-functioning pbuffer if ALPHA_BITS=0 and
1372 // WGL_BIND_TO_TEXTURE_RGB_ARB=true
1374 //pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1375 //pfAttribs.push_back(0);
1379 if (!WGL_NV_render_depth_texture && _bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1381 #if defined(DEBUG) || defined(_DEBUG)
1382 fprintf(stderr, "RenderTexture Warning: No support found for "
1383 "render to depth texture.\n");
1385 _bIsDepthTexture = false;
1389 if ((_bIsTexture || _bIsDepthTexture) &&
1390 (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1395 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1396 pbAttribs.push_back(WGL_TEXTURE_RECTANGLE_NV);
1400 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1401 pbAttribs.push_back(WGL_TEXTURE_CUBE_MAP_ARB);
1405 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1406 pbAttribs.push_back(WGL_TEXTURE_2D_ARB);
1411 pbAttribs.push_back(WGL_MIPMAP_TEXTURE_ARB);
1412 pbAttribs.push_back(true);
1415 #elif defined(DEBUG) || defined(_DEBUG)
1416 printf("RenderTexture Error: Render to Texture not "
1417 "supported in Linux\n");
1421 // Set the pixel type
1425 if (WGL_NV_float_buffer)
1427 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1428 pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1430 pfAttribs.push_back(WGL_FLOAT_COMPONENTS_NV);
1431 pfAttribs.push_back(true);
1435 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1436 pfAttribs.push_back(WGL_TYPE_RGBA_FLOAT_ATI);
1439 if (GL_NV_float_buffer)
1441 pfAttribs.push_back(GLX_FLOAT_COMPONENTS_NV);
1442 pfAttribs.push_back(1);
1449 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1450 pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1454 // Set up texture binding for render to texture
1455 if (_bIsTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1461 if (WGL_NV_float_buffer)
1463 switch(_iNumComponents)
1466 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
1467 pfAttribs.push_back(true);
1469 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1470 pbAttribs.push_back(WGL_TEXTURE_FLOAT_R_NV);
1473 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
1474 pfAttribs.push_back(true);
1476 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1477 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RG_NV);
1480 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
1481 pfAttribs.push_back(true);
1483 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1484 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGB_NV);
1487 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
1488 pfAttribs.push_back(true);
1490 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1491 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGBA_NV);
1495 "RenderTexture Warning: Bad number of components "
1496 "(r=1,rg=2,rgb=3,rgba=4): %d.\n",
1503 if (4 == _iNumComponents)
1505 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1506 pfAttribs.push_back(true);
1508 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1509 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1513 // standard ARB_render_texture only supports 3 or 4 channels
1514 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1515 pfAttribs.push_back(true);
1517 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1518 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1525 switch(_iNumComponents)
1528 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1529 pfAttribs.push_back(true);
1531 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1532 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1535 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1536 pfAttribs.push_back(true);
1538 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1539 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1543 "RenderTexture Warning: Bad number of components "
1544 "(r=1,rg=2,rgb=3,rgba=4): %d.\n", _iNumComponents);
1548 #elif defined(DEBUG) || defined(_DEBUG)
1550 "RenderTexture Error: Render to Texture not supported in "
1555 if (_bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1560 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV);
1561 pfAttribs.push_back(true);
1563 pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
1564 pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
1568 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_DEPTH_NV);
1569 pfAttribs.push_back(true);
1571 pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
1572 pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
1574 #elif defined(DEBUG) || defined(_DEBUG)
1575 printf("RenderTexture Error: Render to Texture not supported in "
1581 //---------------------------------------------------------------------------
1582 // Function : RenderTexture::_GetKeyValuePair
1584 //---------------------------------------------------------------------------
1586 * @fn RenderTexture::_GetKeyValuePair()
1587 * @brief Parses expressions of the form "X=Y" into a pair (X,Y).
1589 RenderTexture::KeyVal RenderTexture::_GetKeyValuePair(string token)
1591 string::size_type pos = 0;
1592 if ((pos = token.find("=")) != token.npos)
1594 string key = token.substr(0, pos);
1595 string value = token.substr(pos+1, token.length()-pos+1);
1596 return KeyVal(key, value);
1599 return KeyVal(token, "");
1602 //---------------------------------------------------------------------------
1603 // Function : RenderTexture::_ParseBitVector
1605 //---------------------------------------------------------------------------
1607 * @fn RenderTexture::_ParseBitVector()
1608 * @brief Parses expressions of the form "=r,g,b,a" into a vector: (r,g,b,a)
1610 vector<int> RenderTexture::_ParseBitVector(string bitVector)
1612 vector<string> pieces;
1615 if (bitVector == "")
1617 bits.push_back(8); // if a depth isn't specified, use default 8 bits
1621 string::size_type pos = 0;
1622 string::size_type nextpos = 0;
1625 nextpos = bitVector.find_first_of(", \n", pos);
1626 pieces.push_back(string(bitVector, pos, nextpos - pos));
1628 } while (nextpos != bitVector.npos );
1630 for ( vector<string>::iterator it = pieces.begin(); it != pieces.end(); it++)
1632 bits.push_back(strtol(it->c_str(), 0, 10));
1638 //---------------------------------------------------------------------------
1639 // Function : RenderTexture::_VerifyExtensions
1641 //---------------------------------------------------------------------------
1643 * @fn RenderTexture::_VerifyExtensions()
1644 * @brief Checks that the necessary extensions are available based on RT mode.
1646 bool RenderTexture::_VerifyExtensions()
1649 if ( !fctPtrInited )
1651 fctPtrInited = true;
1652 wglGetExtensionsStringARBProc wglGetExtensionsStringARBPtr = (wglGetExtensionsStringARBProc)wglGetProcAddress( "wglGetExtensionsStringARB" );
1653 if ( wglGetExtensionsStringARBPtr == 0 )
1655 PrintExtensionError("WGL_ARB_extensions_string");
1658 string wglExtensionsString = wglGetExtensionsStringARBPtr( wglGetCurrentDC() );
1659 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pixel_format" ) )
1661 wglChoosePixelFormatARBPtr = (wglChoosePixelFormatARBProc)SGLookupFunction("wglChoosePixelFormatARB");
1662 wglGetPixelFormatAttribivARBPtr = (wglGetPixelFormatAttribivARBProc)SGLookupFunction("wglGetPixelFormatAttribivARB");
1666 PrintExtensionError("WGL_ARB_pixel_format");
1669 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pbuffer" ) )
1671 wglCreatePbufferARBPtr = (wglCreatePbufferARBProc)SGLookupFunction("wglCreatePbufferARB");
1672 wglGetPbufferDCARBPtr = (wglGetPbufferDCARBProc)SGLookupFunction("wglGetPbufferDCARB");
1673 wglQueryPbufferARBPtr = (wglQueryPbufferARBProc)SGLookupFunction("wglQueryPbufferARB");
1674 wglReleasePbufferDCARBPtr = (wglReleasePbufferDCARBProc)SGLookupFunction("wglReleasePbufferDCARB");
1675 wglDestroyPbufferARBPtr = (wglDestroyPbufferARBProc)SGLookupFunction("wglDestroyPbufferARB");
1679 PrintExtensionError("WGL_ARB_pbuffer");
1682 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_render_texture" ) )
1684 wglBindTexImageARBPtr = (wglBindTexImageARBProc)SGLookupFunction("wglBindTexImageARB");
1685 wglReleaseTexImageARBPtr = (wglReleaseTexImageARBProc)SGLookupFunction("wglReleaseTexImageARB");
1687 else if ( _bIsTexture )
1689 PrintExtensionError("WGL_ARB_render_texture");
1692 if (_bRectangle && !SGIsOpenGLExtensionSupported( "GL_NV_texture_rectangle" ))
1694 PrintExtensionError("GL_NV_texture_rectangle");
1697 if (_bFloat && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) || SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ATI_pixel_format_float" )))
1699 PrintExtensionError("GL_NV_float_buffer or GL_ATI_pixel_format_float");
1703 if (_bFloat && _bIsTexture && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) || SGIsOpenGLExtensionSupported( "GL_ATI_texture_float" )))
1705 PrintExtensionError("NV_float_buffer or ATI_texture_float");
1707 if (_bIsDepthTexture && !SGIsOpenGLExtensionSupported( "GL_ARB_depth_texture" ))
1710 #if defined(_DEBUG) | defined(DEBUG)
1712 "RenderTexture Warning: "
1713 "OpenGL extension GL_ARB_depth_texture not available.\n"
1714 " Using glReadPixels() to emulate behavior.\n");
1716 _bHasARBDepthTexture = false;
1717 //PrintExtensionError("GL_ARB_depth_texture");
1724 if (!GLX_SGIX_pbuffer)
1726 PrintExtensionError("GL_SGIX_pbuffer");
1729 if (!GLX_SGIX_fbconfig)
1731 PrintExtensionError("GL_SGIX_fbconfig");
1734 if (_bIsDepthTexture && !GL_ARB_depth_texture)
1736 PrintExtensionError("GL_ARB_depth_texture");
1739 if (_bFloat && _bIsTexture && !GL_NV_float_buffer)
1741 PrintExtensionError("GL_NV_float_buffer");
1744 if (_eUpdateMode == RT_RENDER_TO_TEXTURE)
1746 PrintExtensionError("Some GLX render texture extension: FIXME!");
1754 //---------------------------------------------------------------------------
1755 // Function : RenderTexture::_InitializeTextures
1757 //---------------------------------------------------------------------------
1759 * @fn RenderTexture::_InitializeTextures()
1760 * @brief Initializes the state of textures used by the RenderTexture.
1762 bool RenderTexture::_InitializeTextures()
1764 // Determine the appropriate texture formats and filtering modes.
1765 if (_bIsTexture || _bIsDepthTexture)
1767 if (_bRectangle && GL_NV_texture_rectangle)
1768 _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
1770 _iTextureTarget = GL_TEXTURE_2D;
1775 glGenTextures(1, &_iTextureID);
1776 glBindTexture(_iTextureTarget, _iTextureID);
1778 // Use clamp to edge as the default texture wrap mode for all tex
1779 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1780 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1781 // Use NEAREST as the default texture filtering mode.
1782 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1783 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1786 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
1788 GLuint iInternalFormat;
1796 "RenderTexture Error: mipmapped float textures not "
1801 switch(_iNumComponents)
1804 if (GL_NV_float_buffer)
1806 iInternalFormat = (_iNumColorBits[0] > 16) ?
1807 GL_FLOAT_R32_NV : GL_FLOAT_R16_NV;
1809 else if (GL_ATI_texture_float)
1811 iInternalFormat = (_iNumColorBits[0] > 16) ?
1812 GL_LUMINANCE_FLOAT32_ATI :
1813 GL_LUMINANCE_FLOAT16_ATI;
1815 iFormat = GL_LUMINANCE;
1818 if (GL_NV_float_buffer)
1820 iInternalFormat = (_iNumColorBits[0] > 16) ?
1821 GL_FLOAT_RG32_NV : GL_FLOAT_RG16_NV;
1823 else if (GL_ATI_texture_float)
1825 iInternalFormat = (_iNumColorBits[0] > 16) ?
1826 GL_LUMINANCE_ALPHA_FLOAT32_ATI :
1827 GL_LUMINANCE_ALPHA_FLOAT16_ATI;
1829 iFormat = GL_LUMINANCE_ALPHA;
1832 if (GL_NV_float_buffer)
1834 iInternalFormat = (_iNumColorBits[0] > 16) ?
1835 GL_FLOAT_RGB32_NV : GL_FLOAT_RGB16_NV;
1837 else if (GL_ATI_texture_float)
1839 iInternalFormat = (_iNumColorBits[0] > 16) ?
1840 GL_RGB_FLOAT32_ATI : GL_RGB_FLOAT16_ATI;
1845 if (GL_NV_float_buffer)
1847 iInternalFormat = (_iNumColorBits[0] > 16) ?
1848 GL_FLOAT_RGBA32_NV : GL_FLOAT_RGBA16_NV;
1850 else if (GL_ATI_texture_float)
1852 iInternalFormat = (_iNumColorBits[0] > 16) ?
1853 GL_RGBA_FLOAT32_ATI : GL_RGBA_FLOAT16_ATI;
1858 printf("RenderTexture Error: "
1859 "Invalid number of components: %d\n",
1866 if (4 == _iNumComponents)
1868 iInternalFormat = GL_RGBA8;
1873 iInternalFormat = GL_RGB8;
1878 // Allocate the texture image (but pass it no data for now).
1879 glTexImage2D(_iTextureTarget, 0, iInternalFormat,
1880 _iWidth, _iHeight, 0, iFormat, GL_FLOAT, NULL);
1884 if (_bIsDepthTexture)
1886 glGenTextures(1, &_iDepthTextureID);
1887 glBindTexture(_iTextureTarget, _iDepthTextureID);
1889 // Use clamp to edge as the default texture wrap mode for all tex
1890 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1891 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1892 // Use NEAREST as the default texture filtering mode.
1893 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1894 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1896 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
1899 if (_bHasARBDepthTexture)
1901 // Allocate the texture image (but pass it no data for now).
1902 glTexImage2D(_iTextureTarget, 0, GL_DEPTH_COMPONENT,
1903 _iWidth, _iHeight, 0, GL_DEPTH_COMPONENT,
1908 // allocate memory for depth texture
1909 // Since this is slow, we warn the user in debug mode. (above)
1910 _pPoorDepthTexture = new unsigned short[_iWidth * _iHeight];
1911 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
1912 _iWidth, _iHeight, 0, GL_LUMINANCE,
1913 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
1923 //---------------------------------------------------------------------------
1924 // Function : RenderTexture::_MaybeCopyBuffer
1926 //---------------------------------------------------------------------------
1928 * @fn RenderTexture::_MaybeCopyBuffer()
1929 * @brief Does the actual copying for RenderTextures with RT_COPY_TO_TEXTURE
1931 void RenderTexture::_MaybeCopyBuffer()
1934 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
1938 glBindTexture(_iTextureTarget, _iTextureID);
1939 glCopyTexSubImage2D(_iTextureTarget,
1940 0, 0, 0, 0, 0, _iWidth, _iHeight);
1942 if (_bIsDepthTexture)
1944 glBindTexture(_iTextureTarget, _iDepthTextureID);
1945 // HOW TO COPY DEPTH TEXTURE??? Supposedly this just magically works...
1947 if (_bHasARBDepthTexture)
1949 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0,
1954 // no 'real' depth texture available, so behavior has to be emulated
1955 // using glReadPixels (beware, this is (naturally) slow ...)
1956 glReadPixels(0, 0, _iWidth, _iHeight, GL_DEPTH_COMPONENT,
1957 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
1958 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
1959 _iWidth, _iHeight, 0, GL_LUMINANCE,
1960 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
1969 glBindTexture(_iTextureTarget, _iTextureID);
1970 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
1972 if (_bIsDepthTexture)
1974 glBindTexture(_iTextureTarget, _iDepthTextureID);
1975 assert(_bHasARBDepthTexture);
1976 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
1982 //---------------------------------------------------------------------------
1983 // Function : RenderTexture::_ReleaseBoundBuffers
1985 //---------------------------------------------------------------------------
1987 * @fn RenderTexture::_ReleaseBoundBuffers()
1988 * @brief Releases buffer bindings on RenderTextures with RT_RENDER_TO_TEXTURE
1990 bool RenderTexture::_ReleaseBoundBuffers()
1993 if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
1995 glBindTexture(_iTextureTarget, _iTextureID);
1997 // release the pbuffer from the render texture object
1998 if (0 != _iCurrentBoundBuffer && _bIsBufferBound)
2000 if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, _iCurrentBoundBuffer))
2005 _bIsBufferBound = false;
2009 if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2011 glBindTexture(_iTextureTarget, _iDepthTextureID);
2013 // release the pbuffer from the render texture object
2014 if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
2022 // textures can't be bound in Linux
2027 //---------------------------------------------------------------------------
2028 // Function : RenderTexture::_MakeCurrent
2030 //---------------------------------------------------------------------------
2032 * @fn RenderTexture::_MakeCurrent()
2033 * @brief Makes the RenderTexture's context current
2036 bool RenderTexture::_MakeCurrent()
2039 // make the pbuffer's rendering context current.
2040 if (FALSE == wglMakeCurrent( _hDC, _hGLContext))
2046 if (false == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
2055 /////////////////////////////////////////////////////////////////////////////
2057 // Begin Deprecated Interface
2059 /////////////////////////////////////////////////////////////////////////////
2061 //---------------------------------------------------------------------------
2062 // Function : RenderTexture::RenderTexture
2064 //---------------------------------------------------------------------------
2066 * @fn RenderTexture::RenderTexture()
2067 * @brief Constructor.
2069 RenderTexture::RenderTexture(int width, int height,
2070 bool bIsTexture /* = true */,
2071 bool bIsDepthTexture /* = false */)
2074 _bIsTexture(bIsTexture),
2075 _bIsDepthTexture(bIsDepthTexture),
2076 _bHasARBDepthTexture(true), // [Redge]
2077 _eUpdateMode(RT_RENDER_TO_TEXTURE),
2078 _bInitialized(false),
2080 _iCurrentBoundBuffer(0),
2082 _iNumStencilBits(0),
2083 _bDoubleBuffered(false),
2088 _bShareObjects(false),
2089 _bCopyContext(false),
2095 _hPreviousContext(0),
2100 _hPreviousContext(0),
2101 _hPreviousDrawable(0),
2103 _iTextureTarget(GL_NONE),
2105 _iDepthTextureID(0),
2106 _pPoorDepthTexture(0) // [Redge]
2108 assert(width > 0 && height > 0);
2109 #if defined DEBUG || defined _DEBUG
2111 "RenderTexture Warning: Deprecated Contructor interface used.\n");
2114 _iNumColorBits[0] = _iNumColorBits[1] =
2115 _iNumColorBits[2] = _iNumColorBits[3] = 0;
2116 _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
2119 //------------------------------------------------------------------------------
2120 // Function : RenderTexture::Initialize
2122 //------------------------------------------------------------------------------
2124 * @fn RenderTexture::Initialize(bool bShare, bool bDepth, bool bStencil, bool bMipmap, unsigned int iRBits, unsigned int iGBits, unsigned int iBBits, unsigned int iABits);
2125 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
2127 * This function actually does the creation of the p-buffer. It can only be called
2128 * once a GL context has already been created. Note that if the texture is not
2129 * power of two dimensioned, or has more than 8 bits per channel, enabling mipmapping
2130 * will cause an error.
2132 bool RenderTexture::Initialize(bool bShare /* = true */,
2133 bool bDepth /* = false */,
2134 bool bStencil /* = false */,
2135 bool bMipmap /* = false */,
2136 bool bAnisoFilter /* = false */,
2137 unsigned int iRBits /* = 8 */,
2138 unsigned int iGBits /* = 8 */,
2139 unsigned int iBBits /* = 8 */,
2140 unsigned int iABits /* = 8 */,
2141 UpdateMode updateMode /* = RT_RENDER_TO_TEXTURE */)
2143 if (0 == _iWidth || 0 == _iHeight)
2146 #if defined DEBUG || defined _DEBUG
2148 "RenderTexture Warning: Deprecated Initialize() interface used.\n");
2151 // create a mode string.
2154 mode.append("depth ");
2156 mode.append("stencil ");
2158 mode.append("mipmap ");
2159 if (iRBits + iGBits + iBBits + iABits > 0)
2170 char bitVector[100];
2172 "%d%s,%d%s,%d%s,%d%s",
2173 iRBits, (iRBits >= 16) ? "f" : "",
2174 iGBits, (iGBits >= 16) ? "f" : "",
2175 iBBits, (iBBits >= 16) ? "f" : "",
2176 iABits, (iABits >= 16) ? "f" : "");
2177 mode.append(bitVector);
2182 if (GL_NV_texture_rectangle &&
2183 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2184 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2185 mode.append("texRECT ");
2187 mode.append("tex2D ");
2189 if (_bIsDepthTexture)
2191 if (GL_NV_texture_rectangle &&
2192 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2193 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2194 mode.append("texRECT ");
2196 mode.append("tex2D ");
2198 if (RT_COPY_TO_TEXTURE == updateMode)
2201 _pixelFormatAttribs.clear();
2202 _pbufferAttribs.clear();
2205 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
2206 _pixelFormatAttribs.push_back(true);
2207 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
2208 _pixelFormatAttribs.push_back(true);
2210 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
2211 _pbufferAttribs.push_back(true);
2213 _pixelFormatAttribs.push_back(GLX_RENDER_TYPE_SGIX);
2214 _pixelFormatAttribs.push_back(GLX_RGBA_BIT_SGIX);
2215 _pixelFormatAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
2216 _pixelFormatAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
2219 _ParseModeString(mode.c_str(), _pixelFormatAttribs, _pbufferAttribs);
2222 _pixelFormatAttribs.push_back(0);
2223 _pbufferAttribs.push_back(0);
2225 _pixelFormatAttribs.push_back(None);
2228 Initialize(_iWidth, _iHeight, bShare);
2234 //---------------------------------------------------------------------------
2235 // Function : RenderTexture::Reset
2237 //---------------------------------------------------------------------------
2239 * @fn RenderTexture::Reset(int iWidth, int iHeight, unsigned int iMode, bool bIsTexture, bool bIsDepthTexture)
2240 * @brief Resets the resolution of the offscreen buffer.
2242 * Causes the buffer to delete itself. User must call Initialize() again
2245 bool RenderTexture::Reset(int iWidth, int iHeight)
2248 "RenderTexture Warning: Deprecated Reset() interface used.\n");
2252 fprintf(stderr, "RenderTexture::Reset(): failed to invalidate.\n");