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
49 #include <simgear/compiler.h>
50 #include <simgear/screen/RenderTexture.h>
51 #include <simgear/screen/extensions.hxx>
59 #pragma comment(lib, "gdi32.lib") // required for GetPixelFormat()
64 //---------------------------------------------------------------------------
65 // Function : RenderTexture::RenderTexture
67 //---------------------------------------------------------------------------
69 * @fn RenderTexture::RenderTexture()
70 * @brief Mode-string-based Constructor.
72 RenderTexture::RenderTexture(const char *strMode)
76 _bIsDepthTexture(false),
77 _bHasARBDepthTexture(true), // [Redge]
79 _eUpdateMode(RT_RENDER_TO_TEXTURE),
81 _eUpdateMode(RT_COPY_TO_TEXTURE),
85 _bIsBufferBound(false),
86 _iCurrentBoundBuffer(0),
90 _bDoubleBuffered(false),
94 _bShareObjects(false),
101 _hPreviousContext(0),
106 _hPreviousContext(0),
107 _hPreviousDrawable(0),
109 _iTextureTarget(GL_NONE),
112 _pPoorDepthTexture(0) // [Redge]
114 _iNumColorBits[0] = _iNumColorBits[1] =
115 _iNumColorBits[2] = _iNumColorBits[3] = 0;
118 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
119 _pixelFormatAttribs.push_back(true);
120 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
121 _pixelFormatAttribs.push_back(true);
123 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
124 _pbufferAttribs.push_back(true);
126 _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
127 _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
128 _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
129 _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
132 _ParseModeString(strMode, _pixelFormatAttribs, _pbufferAttribs);
135 _pixelFormatAttribs.push_back(0);
136 _pbufferAttribs.push_back(0);
138 _pixelFormatAttribs.push_back(None);
143 //---------------------------------------------------------------------------
144 // Function : RenderTexture::~RenderTexture
146 //---------------------------------------------------------------------------
148 * @fn RenderTexture::~RenderTexture()
151 RenderTexture::~RenderTexture()
157 //---------------------------------------------------------------------------
158 // Function : _wglGetLastError
160 //---------------------------------------------------------------------------
162 * @fn wglGetLastError()
163 * @brief Returns the last windows error generated.
166 void _wglGetLastError()
170 DWORD err = GetLastError();
173 case ERROR_INVALID_PIXEL_FORMAT:
175 "RenderTexture Win32 Error: ERROR_INVALID_PIXEL_FORMAT\n");
177 case ERROR_NO_SYSTEM_RESOURCES:
179 "RenderTexture Win32 Error: ERROR_NO_SYSTEM_RESOURCES\n");
181 case ERROR_INVALID_DATA:
183 "RenderTexture Win32 Error: ERROR_INVALID_DATA\n");
185 case ERROR_INVALID_WINDOW_HANDLE:
187 "RenderTexture Win32 Error: ERROR_INVALID_WINDOW_HANDLE\n");
189 case ERROR_RESOURCE_TYPE_NOT_FOUND:
191 "RenderTexture Win32 Error: ERROR_RESOURCE_TYPE_NOT_FOUND\n");
198 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
199 FORMAT_MESSAGE_FROM_SYSTEM |
200 FORMAT_MESSAGE_IGNORE_INSERTS,
203 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
208 fprintf(stderr, "RenderTexture Win32 Error %d: %s\n", err, lpMsgBuf);
209 LocalFree( lpMsgBuf );
218 //---------------------------------------------------------------------------
219 // Function : PrintExtensionError
221 //---------------------------------------------------------------------------
223 * @fn PrintExtensionError( char* strMsg, ... )
224 * @brief Prints an error about missing OpenGL extensions.
226 void PrintExtensionError( char* strMsg, ... )
229 "Error: RenderTexture requires the following unsupported "
230 "OpenGL extensions: \n");
233 va_start(args, strMsg);
235 _vsnprintf( strBuffer, 512, strMsg, args );
237 vsnprintf( strBuffer, 512, strMsg, args );
241 fprintf(stderr, strMsg);
244 //---------------------------------------------------------------------------
245 // Function : RenderTexture::Initialize
247 //---------------------------------------------------------------------------
249 * @fn RenderTexture::Initialize(int width, int height, bool shareObjects, bool copyContext);
250 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
252 * This function creates of the p-buffer. It can only be called once a GL
253 * context has already been created.
255 bool RenderTexture::Initialize(int width, int height,
256 bool shareObjects /* = true */,
257 bool copyContext /* = false */)
259 assert(width > 0 && height > 0);
261 _iWidth = width; _iHeight = height;
262 _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
264 _bShareObjects = shareObjects;
265 _bCopyContext = copyContext;
267 // Check if this is an NVXX GPU and verify necessary extensions.
268 if (!_VerifyExtensions())
275 // Get the current context.
276 HDC hdc = wglGetCurrentDC();
279 HGLRC hglrc = wglGetCurrentContext();
284 unsigned int iNumFormats;
288 // Get the pixel format for the on-screen window.
289 iFormat = GetPixelFormat(hdc);
293 "RenderTexture Error: GetPixelFormat() failed.\n");
299 if (!wglChoosePixelFormatARB(hdc, &_pixelFormatAttribs[0], NULL,
300 1, &iFormat, &iNumFormats))
303 "RenderTexture Error: wglChoosePixelFormatARB() failed.\n");
307 if ( iNumFormats <= 0 )
310 "RenderTexture Error: Couldn't find a suitable "
317 // Create the p-buffer.
318 _hPBuffer = wglCreatePbufferARB(hdc, iFormat, _iWidth, _iHeight,
319 &_pbufferAttribs[0]);
323 "RenderTexture Error: wglCreatePbufferARB() failed.\n");
328 // Get the device context.
329 _hDC = wglGetPbufferDCARB( _hPBuffer);
333 "RenderTexture Error: wglGetGetPbufferDCARB() failed.\n");
338 // Create a gl context for the p-buffer.
341 // Let's use the same gl context..
342 // Since the device contexts are compatible (i.e. same pixelformat),
343 // we should be able to use the same gl rendering context.
348 _hGLContext = wglCreateContext( _hDC );
352 "RenderTexture Error: wglCreateContext() failed.\n");
358 // Share lists, texture objects, and program objects.
361 if( !wglShareLists(hglrc, _hGLContext) )
364 "RenderTexture Error: wglShareLists() failed.\n");
370 // Determine the actual width and height we were able to create.
371 wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
372 wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
374 _bInitialized = true;
376 // get the actual number of bits allocated:
377 int attrib = WGL_RED_BITS_ARB;
381 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
383 attrib = WGL_GREEN_BITS_ARB;
385 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
387 attrib = WGL_BLUE_BITS_ARB;
389 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
391 attrib = WGL_ALPHA_BITS_ARB;
393 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
395 attrib = WGL_DEPTH_BITS_ARB;
397 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
399 attrib = WGL_STENCIL_BITS_ARB;
401 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
403 attrib = WGL_DOUBLE_BUFFER_ARB;
405 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
406 ? (value?true:false) : false;
408 #if defined(_DEBUG) | defined(DEBUG)
409 fprintf(stderr, "Created a %dx%d RenderTexture with BPP(%d, %d, %d, %d)",
411 _iNumColorBits[0], _iNumColorBits[1],
412 _iNumColorBits[2], _iNumColorBits[3]);
413 if (_iNumDepthBits) fprintf(stderr, " depth=%d", _iNumDepthBits);
414 if (_iNumStencilBits) fprintf(stderr, " stencil=%d", _iNumStencilBits);
415 if (_bDoubleBuffered) fprintf(stderr, " double buffered");
416 fprintf(stderr, "\n");
420 _pDisplay = glXGetCurrentDisplay();
421 GLXContext context = glXGetCurrentContext();
422 int screen = DefaultScreen(_pDisplay);
423 XVisualInfo *visInfo;
429 GLXFBConfigSGIX *fbConfigs;
432 fbConfigs = glXChooseFBConfigSGIX(_pDisplay, screen,
433 &_pixelFormatAttribs[0], &nConfigs);
435 if (nConfigs == 0 || !fbConfigs)
438 "RenderTexture Error: Couldn't find a suitable pixel format.\n");
442 // Pick the first returned format that will return a pbuffer
443 for (int i=0;i<nConfigs;i++)
445 _hPBuffer = glXCreateGLXPbufferSGIX(_pDisplay, fbConfigs[i],
446 _iWidth, _iHeight, NULL);
449 _hGLContext = glXCreateContextWithConfigSGIX(_pDisplay,
452 _bShareObjects ? context : NULL,
461 "RenderTexture Error: glXCreateGLXPbufferSGIX() failed.\n");
468 _hGLContext = glXCreateContext(_pDisplay, visInfo,
469 _bShareObjects ? context : NULL, False);
473 "RenderTexture Error: glXCreateContext() failed.\n");
478 glXQueryGLXPbufferSGIX(_pDisplay, _hPBuffer, GLX_WIDTH_SGIX,
480 glXQueryGLXPbufferSGIX(_pDisplay, _hPBuffer, GLX_HEIGHT_SGIX,
483 _bInitialized = true;
485 // XXX Query the color format
490 // Now that the pbuffer is created, allocate any texture objects needed,
491 // and initialize them (for CTT updates only). These must be allocated
492 // in the context of the pbuffer, though, or the RT won't work without
495 if (false == wglMakeCurrent( _hDC, _hGLContext))
501 _hPreviousContext = glXGetCurrentContext();
502 _hPreviousDrawable = glXGetCurrentDrawable();
504 if (False == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
510 bool result = _InitializeTextures();
512 BindBuffer(WGL_FRONT_LEFT_ARB);
518 // make the previous rendering context current
519 if (false == wglMakeCurrent( hdc, hglrc))
525 if (False == glXMakeCurrent(_pDisplay,
526 _hPreviousDrawable, _hPreviousContext))
536 //---------------------------------------------------------------------------
537 // Function : RenderTexture::_Invalidate
539 //---------------------------------------------------------------------------
541 * @fn RenderTexture::_Invalidate()
542 * @brief Returns the pbuffer memory to the graphics device.
545 bool RenderTexture::_Invalidate()
547 _iNumColorBits[0] = _iNumColorBits[1] =
548 _iNumColorBits[2] = _iNumColorBits[3] = 0;
550 _iNumStencilBits = 0;
553 glDeleteTextures(1, &_iTextureID);
554 if (_bIsDepthTexture)
557 if (!_bHasARBDepthTexture) delete[] _pPoorDepthTexture;
559 glDeleteTextures(1, &_iDepthTextureID);
565 // Check if we are currently rendering in the pbuffer
566 if (wglGetCurrentContext() == _hGLContext)
569 wglDeleteContext( _hGLContext);
570 wglReleasePbufferDCARB( _hPBuffer, _hDC);
571 wglDestroyPbufferARB( _hPBuffer );
578 if(glXGetCurrentContext() == _hGLContext)
579 // XXX I don't know if this is right at all
580 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
581 glXDestroyGLXPbufferSGIX(_pDisplay, _hPBuffer);
587 // [WVB] do we need to call _ReleaseBoundBuffers() too?
592 //---------------------------------------------------------------------------
593 // Function : RenderTexture::Reset
595 //---------------------------------------------------------------------------
597 * @fn RenderTexture::Reset()
598 * @brief Resets the resolution of the offscreen buffer.
600 * Causes the buffer to delete itself. User must call Initialize() again
603 bool RenderTexture::Reset(const char *strMode, ...)
605 _iWidth = 0; _iHeight = 0;
606 _bIsTexture = false; _bIsDepthTexture = false,
607 _bHasARBDepthTexture = true;
609 _eUpdateMode = RT_RENDER_TO_TEXTURE;
611 _eUpdateMode = RT_COPY_TO_TEXTURE;
613 _bInitialized = false;
615 _bIsBufferBound = false;
616 _iCurrentBoundBuffer = 0;
617 _iNumDepthBits = 0; _iNumStencilBits = 0;
618 _bDoubleBuffered = false;
619 _bFloat = false; _bPowerOf2 = true;
620 _bRectangle = false; _bMipmap = false;
621 _bShareObjects = false; _bCopyContext = false;
622 _iTextureTarget = GL_NONE; _iTextureID = 0;
623 _iDepthTextureID = 0;
624 _pPoorDepthTexture = 0;
625 _pixelFormatAttribs.clear();
626 _pbufferAttribs.clear();
628 if (IsInitialized() && !_Invalidate())
630 fprintf(stderr, "RenderTexture::Reset(): failed to invalidate.\n");
634 _iNumColorBits[0] = _iNumColorBits[1] =
635 _iNumColorBits[2] = _iNumColorBits[3] = 0;
638 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
639 _pixelFormatAttribs.push_back(true);
640 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
641 _pixelFormatAttribs.push_back(true);
643 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
644 _pbufferAttribs.push_back(true);
646 _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
647 _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
648 _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
649 _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
654 va_start(args,strMode);
656 _vsnprintf( strBuffer, 256, strMode, args );
658 vsnprintf( strBuffer, 256, strMode, args );
662 _ParseModeString(strBuffer, _pixelFormatAttribs, _pbufferAttribs);
665 _pixelFormatAttribs.push_back(0);
666 _pbufferAttribs.push_back(0);
668 _pixelFormatAttribs.push_back(None);
673 //------------------------------------------------------------------------------
674 // Function : RenderTexture::Resize
676 //------------------------------------------------------------------------------
678 * @fn RenderTexture::Resize(int iWidth, int iHeight)
679 * @brief Changes the size of the offscreen buffer.
681 * Like Reset() this causes the buffer to delete itself.
682 * But unlike Reset(), this call re-initializes the RenderTexture.
683 * Note that Resize() will not work after calling Reset(), or before
684 * calling Initialize() the first time.
686 bool RenderTexture::Resize(int iWidth, int iHeight)
688 if (!_bInitialized) {
689 fprintf(stderr, "RenderTexture::Resize(): must Initialize() first.\n");
692 if (iWidth == _iWidth && iHeight == _iHeight) {
696 // Do same basic work as _Invalidate, but don't reset all our flags
698 glDeleteTextures(1, &_iTextureID);
699 if (_bIsDepthTexture)
700 glDeleteTextures(1, &_iDepthTextureID);
704 // Check if we are currently rendering in the pbuffer
705 if (wglGetCurrentContext() == _hGLContext)
708 wglDeleteContext( _hGLContext);
709 wglReleasePbufferDCARB( _hPBuffer, _hDC);
710 wglDestroyPbufferARB( _hPBuffer );
717 if(glXGetCurrentContext() == _hGLContext)
718 // XXX I don't know if this is right at all
719 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
720 glXDestroyGLXPbufferSGIX(_pDisplay, _hPBuffer);
725 fprintf(stderr, "RenderTexture::Resize(): failed to resize.\n");
728 _bInitialized = false;
729 return Initialize(iWidth, iHeight, _bShareObjects, _bCopyContext);
732 //---------------------------------------------------------------------------
733 // Function : RenderTexture::BeginCapture
735 //---------------------------------------------------------------------------
737 * @fn RenderTexture::BeginCapture()
738 * @brief Activates rendering to the RenderTexture.
740 bool RenderTexture::BeginCapture()
745 "RenderTexture::BeginCapture(): Texture is not initialized!\n");
749 // cache the current context so we can reset it when EndCapture() is called.
750 _hPreviousDC = wglGetCurrentDC();
751 if (NULL == _hPreviousDC)
753 _hPreviousContext = wglGetCurrentContext();
754 if (NULL == _hPreviousContext)
757 _hPreviousContext = glXGetCurrentContext();
758 _hPreviousDrawable = glXGetCurrentDrawable();
761 _ReleaseBoundBuffers();
763 return _MakeCurrent();
767 //---------------------------------------------------------------------------
768 // Function : RenderTexture::EndCapture
770 //---------------------------------------------------------------------------
772 * @fn RenderTexture::EndCapture()
773 * @brief Ends rendering to the RenderTexture.
775 bool RenderTexture::EndCapture()
780 "RenderTexture::EndCapture() : Texture is not initialized!\n");
787 // make the previous rendering context current
788 if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
794 if (False == glXMakeCurrent(_pDisplay, _hPreviousDrawable,
801 // rebind the textures to a buffers for RTT
802 BindBuffer(_iCurrentBoundBuffer);
808 //---------------------------------------------------------------------------
809 // Function : RenderTexture::BeginCapture(RenderTexture*)
811 //---------------------------------------------------------------------------
813 * @fn RenderTexture::BeginCapture(RenderTexture* other)
814 * @brief Ends capture of 'other', begins capture on 'this'
816 * When performing a series of operations where you modify one texture after
817 * another, it is more efficient to use this method instead of the equivalent
818 * 'EndCapture'/'BeginCapture' pair. This method switches directly to the
819 * new context rather than changing to the default context, and then to the
822 * RenderTexture doesn't have any mechanism for determining if
823 * 'current' really is currently active, so no error will be thrown
826 bool RenderTexture::BeginCapture(RenderTexture* current)
828 bool bContextReset = false;
830 if (current == this) {
831 return true; // no switch necessary
834 // treat as normal Begin if current is 0.
835 return BeginCapture();
840 "RenderTexture::BeginCapture(RenderTexture*): Texture is not initialized!\n");
843 if (!current->_bInitialized)
846 "RenderTexture::BeginCapture(RenderTexture): 'current' texture is not initialized!\n");
850 // Sync current pbuffer with its CTT texture if necessary
851 current->_MaybeCopyBuffer();
853 // pass along the previous context so we can reset it when
854 // EndCapture() is called.
856 _hPreviousDC = current->_hPreviousDC;
857 if (NULL == _hPreviousDC)
859 _hPreviousContext = current->_hPreviousContext;
860 if (NULL == _hPreviousContext)
863 _hPreviousContext = current->_hPreviousContext;
864 _hPreviousDrawable = current->_hPreviousDrawable;
867 // Unbind textures before making context current
868 if (!_ReleaseBoundBuffers())
871 // Make the pbuffer context current
875 // Rebind buffers of initial RenderTexture
876 current->BindBuffer(_iCurrentBoundBuffer);
877 current->_BindDepthBuffer();
884 //---------------------------------------------------------------------------
885 // Function : RenderTexture::Bind
887 //---------------------------------------------------------------------------
889 * @fn RenderTexture::Bind()
890 * @brief Binds RGB texture.
892 void RenderTexture::Bind() const
894 if (_bInitialized && _bIsTexture)
896 glBindTexture(_iTextureTarget, _iTextureID);
901 //---------------------------------------------------------------------------
902 // Function : RenderTexture::BindDepth
904 //---------------------------------------------------------------------------
906 * @fn RenderTexture::BindDepth()
907 * @brief Binds depth texture.
909 void RenderTexture::BindDepth() const
911 if (_bInitialized && _bIsDepthTexture)
913 glBindTexture(_iTextureTarget, _iDepthTextureID);
918 //---------------------------------------------------------------------------
919 // Function : RenderTexture::BindBuffer
921 //---------------------------------------------------------------------------
923 * @fn RenderTexture::BindBuffer()
924 * @brief Associate the RTT texture id with 'iBuffer' (e.g. WGL_FRONT_LEFT_ARB)
926 bool RenderTexture::BindBuffer( int iBuffer )
928 // Must bind the texture too
929 if (_bInitialized && _bIsTexture)
931 glBindTexture(_iTextureTarget, _iTextureID);
934 if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
935 (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
937 if (FALSE == wglBindTexImageARB(_hPBuffer, iBuffer))
939 // WVB: WGL API considers binding twice to the same buffer
940 // to be an error. But we don't want to
941 //_wglGetLastError();
945 _bIsBufferBound = true;
946 _iCurrentBoundBuffer = iBuffer;
954 //---------------------------------------------------------------------------
955 // Function : RenderTexture::BindBuffer
957 //---------------------------------------------------------------------------
959 * @fn RenderTexture::_BindDepthBuffer()
960 * @brief Associate the RTT depth texture id with the depth buffer
962 bool RenderTexture::_BindDepthBuffer() const
965 if (_bInitialized && _bIsDepthTexture &&
966 RT_RENDER_TO_TEXTURE == _eUpdateMode)
968 glBindTexture(_iTextureTarget, _iDepthTextureID);
969 if (FALSE == wglBindTexImageARB(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
979 //---------------------------------------------------------------------------
980 // Function : RenderTexture::_ParseModeString
982 //---------------------------------------------------------------------------
984 * @fn RenderTexture::_ParseModeString()
985 * @brief Parses the user-specified mode string for RenderTexture parameters.
987 void RenderTexture::_ParseModeString(const char *modeString,
988 vector<int> &pfAttribs,
989 vector<int> &pbAttribs)
991 if (!modeString || strcmp(modeString, "") == 0)
996 _eUpdateMode = RT_RENDER_TO_TEXTURE;
998 _eUpdateMode = RT_COPY_TO_TEXTURE;
1002 bool bHasStencil = false;
1003 bool bBind2D = false;
1004 bool bBindRECT = false;
1005 bool bBindCUBE = false;
1007 char *mode = strdup(modeString);
1010 vector<string> tokens;
1011 char *buf = strtok(mode, " ");
1014 tokens.push_back(buf);
1015 buf = strtok(NULL, " ");
1018 for (unsigned int i = 0; i < tokens.size(); i++)
1020 string token = tokens[i];
1022 KeyVal kv = _GetKeyValuePair(token);
1025 if (kv.first == "rgb" && (_iNumComponents <= 1))
1027 if (kv.second.find("f") != kv.second.npos)
1030 vector<int> bitVec = _ParseBitVector(kv.second);
1032 if (bitVec.size() < 3) // expand the scalar to a vector
1034 bitVec.push_back(bitVec[0]);
1035 bitVec.push_back(bitVec[0]);
1039 pfAttribs.push_back(WGL_RED_BITS_ARB);
1040 pfAttribs.push_back(bitVec[0]);
1041 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1042 pfAttribs.push_back(bitVec[1]);
1043 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1044 pfAttribs.push_back(bitVec[2]);
1047 pfAttribs.push_back(GLX_RED_SIZE);
1048 pfAttribs.push_back(bitVec[0]);
1049 pfAttribs.push_back(GLX_GREEN_SIZE);
1050 pfAttribs.push_back(bitVec[1]);
1051 pfAttribs.push_back(GLX_BLUE_SIZE);
1052 pfAttribs.push_back(bitVec[2]);
1055 _iNumComponents += 3;
1058 else if (kv.first == "rgb")
1060 "RenderTexture Warning: mistake in components definition "
1065 if (kv.first == "rgba" && (_iNumComponents == 0))
1067 if (kv.second.find("f") != kv.second.npos)
1070 vector<int> bitVec = _ParseBitVector(kv.second);
1072 if (bitVec.size() < 4) // expand the scalar to a vector
1074 bitVec.push_back(bitVec[0]);
1075 bitVec.push_back(bitVec[0]);
1076 bitVec.push_back(bitVec[0]);
1080 pfAttribs.push_back(WGL_RED_BITS_ARB);
1081 pfAttribs.push_back(bitVec[0]);
1082 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1083 pfAttribs.push_back(bitVec[1]);
1084 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1085 pfAttribs.push_back(bitVec[2]);
1086 pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1087 pfAttribs.push_back(bitVec[3]);
1090 pfAttribs.push_back(GLX_RED_SIZE);
1091 pfAttribs.push_back(bitVec[0]);
1092 pfAttribs.push_back(GLX_GREEN_SIZE);
1093 pfAttribs.push_back(bitVec[1]);
1094 pfAttribs.push_back(GLX_BLUE_SIZE);
1095 pfAttribs.push_back(bitVec[2]);
1096 pfAttribs.push_back(GLX_ALPHA_SIZE);
1097 pfAttribs.push_back(bitVec[3]);
1100 _iNumComponents = 4;
1103 else if (kv.first == "rgba")
1105 "RenderTexture Warning: mistake in components definition "
1109 if (kv.first == "r" && (_iNumComponents <= 1))
1111 if (kv.second.find("f") != kv.second.npos)
1114 vector<int> bitVec = _ParseBitVector(kv.second);
1117 pfAttribs.push_back(WGL_RED_BITS_ARB);
1118 pfAttribs.push_back(bitVec[0]);
1120 pfAttribs.push_back(GLX_RED_SIZE);
1121 pfAttribs.push_back(bitVec[0]);
1126 else if (kv.first == "r")
1128 "RenderTexture Warning: mistake in components definition "
1132 if (kv.first == "rg" && (_iNumComponents <= 1))
1134 if (kv.second.find("f") != kv.second.npos)
1137 vector<int> bitVec = _ParseBitVector(kv.second);
1139 if (bitVec.size() < 2) // expand the scalar to a vector
1141 bitVec.push_back(bitVec[0]);
1145 pfAttribs.push_back(WGL_RED_BITS_ARB);
1146 pfAttribs.push_back(bitVec[0]);
1147 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1148 pfAttribs.push_back(bitVec[1]);
1150 pfAttribs.push_back(GLX_RED_SIZE);
1151 pfAttribs.push_back(bitVec[0]);
1152 pfAttribs.push_back(GLX_GREEN_SIZE);
1153 pfAttribs.push_back(bitVec[1]);
1155 _iNumComponents += 2;
1158 else if (kv.first == "rg")
1160 "RenderTexture Warning: mistake in components definition "
1164 if (kv.first == "depth")
1166 if (kv.second == "")
1169 iDepthBits = strtol(kv.second.c_str(), 0, 10);
1173 if (kv.first == "stencil")
1177 pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1179 pfAttribs.push_back(GLX_STENCIL_SIZE);
1181 if (kv.second == "")
1182 pfAttribs.push_back(8);
1184 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1188 if (kv.first == "samples")
1191 pfAttribs.push_back(WGL_SAMPLE_BUFFERS_ARB);
1192 pfAttribs.push_back(1);
1193 pfAttribs.push_back(WGL_SAMPLES_ARB);
1194 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1196 pfAttribs.push_back(GL_SAMPLE_BUFFERS_ARB);
1197 pfAttribs.push_back(1);
1198 pfAttribs.push_back(GL_SAMPLES_ARB);
1199 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1205 if (kv.first == "doublebuffer" || kv.first == "double")
1208 pfAttribs.push_back(WGL_DOUBLE_BUFFER_ARB);
1209 pfAttribs.push_back(true);
1211 pfAttribs.push_back(GL_DOUBLEBUFFER);
1212 pfAttribs.push_back(True);
1217 if (kv.first == "aux")
1220 pfAttribs.push_back(WGL_AUX_BUFFERS_ARB);
1222 pfAttribs.push_back(GL_AUX_BUFFERS);
1224 if (kv.second == "")
1225 pfAttribs.push_back(0);
1227 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1231 if (token.find("tex") == 0)
1235 if ((kv.first == "texRECT") && GL_NV_texture_rectangle)
1240 else if (kv.first == "texCUBE")
1252 if (token.find("depthTex") == 0)
1254 _bIsDepthTexture = true;
1256 if ((kv.first == "depthTexRECT") && GL_NV_texture_rectangle)
1261 else if (kv.first == "depthTexCUBE")
1273 if (kv.first == "mipmap")
1279 if (kv.first == "rtt")
1281 _eUpdateMode = RT_RENDER_TO_TEXTURE;
1285 if (kv.first == "ctt")
1287 _eUpdateMode = RT_COPY_TO_TEXTURE;
1292 "RenderTexture Error: Unknown pbuffer attribute: %s\n",
1296 // Processing of some options must be last because of interactions.
1298 // Check for inconsistent texture targets
1299 if (_bIsTexture && _bIsDepthTexture && !(bBind2D ^ bBindRECT ^ bBindCUBE))
1302 "RenderTexture Warning: Depth and Color texture targets "
1306 // Apply default bit format if none specified
1308 if (0 == _iNumComponents)
1310 pfAttribs.push_back(WGL_RED_BITS_ARB);
1311 pfAttribs.push_back(8);
1312 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1313 pfAttribs.push_back(8);
1314 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1315 pfAttribs.push_back(8);
1316 pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1317 pfAttribs.push_back(8);
1318 _iNumComponents = 4;
1323 if (_bIsDepthTexture && !iDepthBits)
1327 pfAttribs.push_back(WGL_DEPTH_BITS_ARB);
1329 pfAttribs.push_back(GLX_DEPTH_SIZE);
1331 pfAttribs.push_back(iDepthBits); // default
1336 pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1337 pfAttribs.push_back(0);
1339 pfAttribs.push_back(GLX_STENCIL_SIZE);
1340 pfAttribs.push_back(0);
1344 if (_iNumComponents < 4)
1346 // Can't do this right now -- on NVIDIA drivers, currently get
1347 // a non-functioning pbuffer if ALPHA_BITS=0 and
1348 // WGL_BIND_TO_TEXTURE_RGB_ARB=true
1350 //pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1351 //pfAttribs.push_back(0);
1355 if (!WGL_NV_render_depth_texture && _bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1357 #if defined(DEBUG) || defined(_DEBUG)
1358 fprintf(stderr, "RenderTexture Warning: No support found for "
1359 "render to depth texture.\n");
1361 _bIsDepthTexture = false;
1365 if ((_bIsTexture || _bIsDepthTexture) &&
1366 (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1371 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1372 pbAttribs.push_back(WGL_TEXTURE_RECTANGLE_NV);
1376 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1377 pbAttribs.push_back(WGL_TEXTURE_CUBE_MAP_ARB);
1381 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1382 pbAttribs.push_back(WGL_TEXTURE_2D_ARB);
1387 pbAttribs.push_back(WGL_MIPMAP_TEXTURE_ARB);
1388 pbAttribs.push_back(true);
1391 #elif defined(DEBUG) || defined(_DEBUG)
1392 printf("RenderTexture Error: Render to Texture not "
1393 "supported in Linux\n");
1397 // Set the pixel type
1401 if (WGL_NV_float_buffer)
1403 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1404 pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1406 pfAttribs.push_back(WGL_FLOAT_COMPONENTS_NV);
1407 pfAttribs.push_back(true);
1411 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1412 pfAttribs.push_back(WGL_TYPE_RGBA_FLOAT_ATI);
1415 if (GL_NV_float_buffer)
1417 pfAttribs.push_back(GLX_FLOAT_COMPONENTS_NV);
1418 pfAttribs.push_back(1);
1425 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1426 pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1430 // Set up texture binding for render to texture
1431 if (_bIsTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1437 if (WGL_NV_float_buffer)
1439 switch(_iNumComponents)
1442 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
1443 pfAttribs.push_back(true);
1445 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1446 pbAttribs.push_back(WGL_TEXTURE_FLOAT_R_NV);
1449 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
1450 pfAttribs.push_back(true);
1452 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1453 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RG_NV);
1456 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
1457 pfAttribs.push_back(true);
1459 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1460 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGB_NV);
1463 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
1464 pfAttribs.push_back(true);
1466 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1467 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGBA_NV);
1471 "RenderTexture Warning: Bad number of components "
1472 "(r=1,rg=2,rgb=3,rgba=4): %d.\n",
1479 if (4 == _iNumComponents)
1481 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1482 pfAttribs.push_back(true);
1484 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1485 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1489 // standard ARB_render_texture only supports 3 or 4 channels
1490 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1491 pfAttribs.push_back(true);
1493 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1494 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1501 switch(_iNumComponents)
1504 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1505 pfAttribs.push_back(true);
1507 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1508 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1511 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1512 pfAttribs.push_back(true);
1514 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1515 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1519 "RenderTexture Warning: Bad number of components "
1520 "(r=1,rg=2,rgb=3,rgba=4): %d.\n", _iNumComponents);
1524 #elif defined(DEBUG) || defined(_DEBUG)
1526 "RenderTexture Error: Render to Texture not supported in "
1531 if (_bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1536 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV);
1537 pfAttribs.push_back(true);
1539 pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
1540 pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
1544 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_DEPTH_NV);
1545 pfAttribs.push_back(true);
1547 pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
1548 pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
1550 #elif defined(DEBUG) || defined(_DEBUG)
1551 printf("RenderTexture Error: Render to Texture not supported in "
1557 //---------------------------------------------------------------------------
1558 // Function : RenderTexture::_GetKeyValuePair
1560 //---------------------------------------------------------------------------
1562 * @fn RenderTexture::_GetKeyValuePair()
1563 * @brief Parses expressions of the form "X=Y" into a pair (X,Y).
1565 RenderTexture::KeyVal RenderTexture::_GetKeyValuePair(string token)
1567 string::size_type pos = 0;
1568 if ((pos = token.find("=")) != token.npos)
1570 string key = token.substr(0, pos);
1571 string value = token.substr(pos+1, token.length()-pos+1);
1572 return KeyVal(key, value);
1575 return KeyVal(token, "");
1578 //---------------------------------------------------------------------------
1579 // Function : RenderTexture::_ParseBitVector
1581 //---------------------------------------------------------------------------
1583 * @fn RenderTexture::_ParseBitVector()
1584 * @brief Parses expressions of the form "=r,g,b,a" into a vector: (r,g,b,a)
1586 vector<int> RenderTexture::_ParseBitVector(string bitVector)
1588 vector<string> pieces;
1591 if (bitVector == "")
1593 bits.push_back(8); // if a depth isn't specified, use default 8 bits
1597 string::size_type pos = 0;
1598 string::size_type nextpos = 0;
1601 nextpos = bitVector.find_first_of(", \n", pos);
1602 pieces.push_back(string(bitVector, pos, nextpos - pos));
1604 } while (nextpos != bitVector.npos );
1606 for ( vector<string>::iterator it = pieces.begin(); it != pieces.end(); it++)
1608 bits.push_back(strtol(it->c_str(), 0, 10));
1614 //---------------------------------------------------------------------------
1615 // Function : RenderTexture::_VerifyExtensions
1617 //---------------------------------------------------------------------------
1619 * @fn RenderTexture::_VerifyExtensions()
1620 * @brief Checks that the necessary extensions are available based on RT mode.
1622 bool RenderTexture::_VerifyExtensions()
1625 if (!WGL_ARB_pbuffer)
1627 PrintExtensionError("WGL_ARB_pbuffer");
1630 if (!WGL_ARB_pixel_format)
1632 PrintExtensionError("WGL_ARB_pixel_format");
1635 if (_bIsTexture && !WGL_ARB_render_texture)
1637 PrintExtensionError("WGL_ARB_render_texture");
1640 if (_bRectangle && !GL_NV_texture_rectangle)
1642 PrintExtensionError("GL_NV_texture_rectangle");
1645 if (_bFloat && !(GL_NV_float_buffer || WGL_ATI_pixel_format_float))
1647 PrintExtensionError("GL_NV_float_buffer or GL_ATI_pixel_format_float");
1651 if (_bFloat && _bIsTexture && !(GL_NV_float_buffer || GL_ATI_texture_float))
1653 PrintExtensionError("NV_float_buffer or ATI_texture_float");
1655 if (_bIsDepthTexture && !GL_ARB_depth_texture)
1658 #if defined(_DEBUG) | defined(DEBUG)
1660 "RenderTexture Warning: "
1661 "OpenGL extension GL_ARB_depth_texture not available.\n"
1662 " Using glReadPixels() to emulate behavior.\n");
1664 _bHasARBDepthTexture = false;
1665 //PrintExtensionError("GL_ARB_depth_texture");
1671 if (!GLX_SGIX_pbuffer)
1673 PrintExtensionError("GL_SGIX_pbuffer");
1676 if (!GLX_SGIX_fbconfig)
1678 PrintExtensionError("GL_SGIX_fbconfig");
1681 if (_bIsDepthTexture && !GL_ARB_depth_texture)
1683 PrintExtensionError("GL_ARB_depth_texture");
1686 if (_bFloat && _bIsTexture && !GL_NV_float_buffer)
1688 PrintExtensionError("GL_NV_float_buffer");
1691 if (_eUpdateMode == RT_RENDER_TO_TEXTURE)
1693 PrintExtensionError("Some GLX render texture extension: FIXME!");
1701 //---------------------------------------------------------------------------
1702 // Function : RenderTexture::_InitializeTextures
1704 //---------------------------------------------------------------------------
1706 * @fn RenderTexture::_InitializeTextures()
1707 * @brief Initializes the state of textures used by the RenderTexture.
1709 bool RenderTexture::_InitializeTextures()
1711 // Determine the appropriate texture formats and filtering modes.
1712 if (_bIsTexture || _bIsDepthTexture)
1714 if (_bRectangle && GL_NV_texture_rectangle)
1715 _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
1717 _iTextureTarget = GL_TEXTURE_2D;
1722 glGenTextures(1, &_iTextureID);
1723 glBindTexture(_iTextureTarget, _iTextureID);
1725 // Use clamp to edge as the default texture wrap mode for all tex
1726 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1727 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1728 // Use NEAREST as the default texture filtering mode.
1729 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1730 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1733 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
1735 GLuint iInternalFormat;
1743 "RenderTexture Error: mipmapped float textures not "
1748 switch(_iNumComponents)
1751 if (GL_NV_float_buffer)
1753 iInternalFormat = (_iNumColorBits[0] > 16) ?
1754 GL_FLOAT_R32_NV : GL_FLOAT_R16_NV;
1756 else if (GL_ATI_texture_float)
1758 iInternalFormat = (_iNumColorBits[0] > 16) ?
1759 GL_LUMINANCE_FLOAT32_ATI :
1760 GL_LUMINANCE_FLOAT16_ATI;
1762 iFormat = GL_LUMINANCE;
1765 if (GL_NV_float_buffer)
1767 iInternalFormat = (_iNumColorBits[0] > 16) ?
1768 GL_FLOAT_RG32_NV : GL_FLOAT_RG16_NV;
1770 else if (GL_ATI_texture_float)
1772 iInternalFormat = (_iNumColorBits[0] > 16) ?
1773 GL_LUMINANCE_ALPHA_FLOAT32_ATI :
1774 GL_LUMINANCE_ALPHA_FLOAT16_ATI;
1776 iFormat = GL_LUMINANCE_ALPHA;
1779 if (GL_NV_float_buffer)
1781 iInternalFormat = (_iNumColorBits[0] > 16) ?
1782 GL_FLOAT_RGB32_NV : GL_FLOAT_RGB16_NV;
1784 else if (GL_ATI_texture_float)
1786 iInternalFormat = (_iNumColorBits[0] > 16) ?
1787 GL_RGB_FLOAT32_ATI : GL_RGB_FLOAT16_ATI;
1792 if (GL_NV_float_buffer)
1794 iInternalFormat = (_iNumColorBits[0] > 16) ?
1795 GL_FLOAT_RGBA32_NV : GL_FLOAT_RGBA16_NV;
1797 else if (GL_ATI_texture_float)
1799 iInternalFormat = (_iNumColorBits[0] > 16) ?
1800 GL_RGBA_FLOAT32_ATI : GL_RGBA_FLOAT16_ATI;
1805 printf("RenderTexture Error: "
1806 "Invalid number of components: %d\n",
1813 if (4 == _iNumComponents)
1815 iInternalFormat = GL_RGBA8;
1820 iInternalFormat = GL_RGB8;
1825 // Allocate the texture image (but pass it no data for now).
1826 glTexImage2D(_iTextureTarget, 0, iInternalFormat,
1827 _iWidth, _iHeight, 0, iFormat, GL_FLOAT, NULL);
1831 if (_bIsDepthTexture)
1833 glGenTextures(1, &_iDepthTextureID);
1834 glBindTexture(_iTextureTarget, _iDepthTextureID);
1836 // Use clamp to edge as the default texture wrap mode for all tex
1837 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1838 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1839 // Use NEAREST as the default texture filtering mode.
1840 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1841 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1843 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
1846 if (_bHasARBDepthTexture)
1848 // Allocate the texture image (but pass it no data for now).
1849 glTexImage2D(_iTextureTarget, 0, GL_DEPTH_COMPONENT,
1850 _iWidth, _iHeight, 0, GL_DEPTH_COMPONENT,
1855 // allocate memory for depth texture
1856 // Since this is slow, we warn the user in debug mode. (above)
1857 _pPoorDepthTexture = new unsigned short[_iWidth * _iHeight];
1858 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
1859 _iWidth, _iHeight, 0, GL_LUMINANCE,
1860 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
1870 //---------------------------------------------------------------------------
1871 // Function : RenderTexture::_MaybeCopyBuffer
1873 //---------------------------------------------------------------------------
1875 * @fn RenderTexture::_MaybeCopyBuffer()
1876 * @brief Does the actual copying for RenderTextures with RT_COPY_TO_TEXTURE
1878 void RenderTexture::_MaybeCopyBuffer()
1881 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
1885 glBindTexture(_iTextureTarget, _iTextureID);
1886 glCopyTexSubImage2D(_iTextureTarget,
1887 0, 0, 0, 0, 0, _iWidth, _iHeight);
1889 if (_bIsDepthTexture)
1891 glBindTexture(_iTextureTarget, _iDepthTextureID);
1892 // HOW TO COPY DEPTH TEXTURE??? Supposedly this just magically works...
1894 if (_bHasARBDepthTexture)
1896 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0,
1901 // no 'real' depth texture available, so behavior has to be emulated
1902 // using glReadPixels (beware, this is (naturally) slow ...)
1903 glReadPixels(0, 0, _iWidth, _iHeight, GL_DEPTH_COMPONENT,
1904 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
1905 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
1906 _iWidth, _iHeight, 0, GL_LUMINANCE,
1907 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
1916 glBindTexture(_iTextureTarget, _iTextureID);
1917 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
1919 if (_bIsDepthTexture)
1921 glBindTexture(_iTextureTarget, _iDepthTextureID);
1922 assert(_bHasARBDepthTexture);
1923 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
1929 //---------------------------------------------------------------------------
1930 // Function : RenderTexture::_ReleaseBoundBuffers
1932 //---------------------------------------------------------------------------
1934 * @fn RenderTexture::_ReleaseBoundBuffers()
1935 * @brief Releases buffer bindings on RenderTextures with RT_RENDER_TO_TEXTURE
1937 bool RenderTexture::_ReleaseBoundBuffers()
1940 if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
1942 glBindTexture(_iTextureTarget, _iTextureID);
1944 // release the pbuffer from the render texture object
1945 if (0 != _iCurrentBoundBuffer && _bIsBufferBound)
1947 if (FALSE == wglReleaseTexImageARB(_hPBuffer, _iCurrentBoundBuffer))
1952 _bIsBufferBound = false;
1956 if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
1958 glBindTexture(_iTextureTarget, _iDepthTextureID);
1960 // release the pbuffer from the render texture object
1961 if (FALSE == wglReleaseTexImageARB(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1969 // textures can't be bound in Linux
1974 //---------------------------------------------------------------------------
1975 // Function : RenderTexture::_MakeCurrent
1977 //---------------------------------------------------------------------------
1979 * @fn RenderTexture::_MakeCurrent()
1980 * @brief Makes the RenderTexture's context current
1983 bool RenderTexture::_MakeCurrent()
1986 // make the pbuffer's rendering context current.
1987 if (FALSE == wglMakeCurrent( _hDC, _hGLContext))
1993 if (false == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
2002 /////////////////////////////////////////////////////////////////////////////
2004 // Begin Deprecated Interface
2006 /////////////////////////////////////////////////////////////////////////////
2008 //---------------------------------------------------------------------------
2009 // Function : RenderTexture::RenderTexture
2011 //---------------------------------------------------------------------------
2013 * @fn RenderTexture::RenderTexture()
2014 * @brief Constructor.
2016 RenderTexture::RenderTexture(int width, int height,
2017 bool bIsTexture /* = true */,
2018 bool bIsDepthTexture /* = false */)
2021 _bIsTexture(bIsTexture),
2022 _bIsDepthTexture(bIsDepthTexture),
2023 _bHasARBDepthTexture(true), // [Redge]
2024 _eUpdateMode(RT_RENDER_TO_TEXTURE),
2025 _bInitialized(false),
2027 _iCurrentBoundBuffer(0),
2029 _iNumStencilBits(0),
2030 _bDoubleBuffered(false),
2035 _bShareObjects(false),
2036 _bCopyContext(false),
2042 _hPreviousContext(0),
2047 _hPreviousContext(0),
2048 _hPreviousDrawable(0),
2050 _iTextureTarget(GL_NONE),
2052 _iDepthTextureID(0),
2053 _pPoorDepthTexture(0) // [Redge]
2055 assert(width > 0 && height > 0);
2056 #if defined DEBUG || defined _DEBUG
2058 "RenderTexture Warning: Deprecated Contructor interface used.\n");
2061 _iNumColorBits[0] = _iNumColorBits[1] =
2062 _iNumColorBits[2] = _iNumColorBits[3] = 0;
2063 _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
2066 //------------------------------------------------------------------------------
2067 // Function : RenderTexture::Initialize
2069 //------------------------------------------------------------------------------
2071 * @fn RenderTexture::Initialize(bool bShare, bool bDepth, bool bStencil, bool bMipmap, unsigned int iRBits, unsigned int iGBits, unsigned int iBBits, unsigned int iABits);
2072 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
2074 * This function actually does the creation of the p-buffer. It can only be called
2075 * once a GL context has already been created. Note that if the texture is not
2076 * power of two dimensioned, or has more than 8 bits per channel, enabling mipmapping
2077 * will cause an error.
2079 bool RenderTexture::Initialize(bool bShare /* = true */,
2080 bool bDepth /* = false */,
2081 bool bStencil /* = false */,
2082 bool bMipmap /* = false */,
2083 bool bAnisoFilter /* = false */,
2084 unsigned int iRBits /* = 8 */,
2085 unsigned int iGBits /* = 8 */,
2086 unsigned int iBBits /* = 8 */,
2087 unsigned int iABits /* = 8 */,
2088 UpdateMode updateMode /* = RT_RENDER_TO_TEXTURE */)
2090 if (0 == _iWidth || 0 == _iHeight)
2093 #if defined DEBUG || defined _DEBUG
2095 "RenderTexture Warning: Deprecated Initialize() interface used.\n");
2098 // create a mode string.
2101 mode.append("depth ");
2103 mode.append("stencil ");
2105 mode.append("mipmap ");
2106 if (iRBits + iGBits + iBBits + iABits > 0)
2117 char bitVector[100];
2119 "%d%s,%d%s,%d%s,%d%s",
2120 iRBits, (iRBits >= 16) ? "f" : "",
2121 iGBits, (iGBits >= 16) ? "f" : "",
2122 iBBits, (iBBits >= 16) ? "f" : "",
2123 iABits, (iABits >= 16) ? "f" : "");
2124 mode.append(bitVector);
2129 if (GL_NV_texture_rectangle &&
2130 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2131 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2132 mode.append("texRECT ");
2134 mode.append("tex2D ");
2136 if (_bIsDepthTexture)
2138 if (GL_NV_texture_rectangle &&
2139 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2140 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2141 mode.append("texRECT ");
2143 mode.append("tex2D ");
2145 if (RT_COPY_TO_TEXTURE == updateMode)
2148 _pixelFormatAttribs.clear();
2149 _pbufferAttribs.clear();
2152 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
2153 _pixelFormatAttribs.push_back(true);
2154 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
2155 _pixelFormatAttribs.push_back(true);
2157 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
2158 _pbufferAttribs.push_back(true);
2160 _pixelFormatAttribs.push_back(GLX_RENDER_TYPE_SGIX);
2161 _pixelFormatAttribs.push_back(GLX_RGBA_BIT_SGIX);
2162 _pixelFormatAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
2163 _pixelFormatAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
2166 _ParseModeString(mode.c_str(), _pixelFormatAttribs, _pbufferAttribs);
2169 _pixelFormatAttribs.push_back(0);
2170 _pbufferAttribs.push_back(0);
2172 _pixelFormatAttribs.push_back(None);
2175 Initialize(_iWidth, _iHeight, bShare);
2181 //---------------------------------------------------------------------------
2182 // Function : RenderTexture::Reset
2184 //---------------------------------------------------------------------------
2186 * @fn RenderTexture::Reset(int iWidth, int iHeight, unsigned int iMode, bool bIsTexture, bool bIsDepthTexture)
2187 * @brief Resets the resolution of the offscreen buffer.
2189 * Causes the buffer to delete itself. User must call Initialize() again
2192 bool RenderTexture::Reset(int iWidth, int iHeight)
2195 "RenderTexture Warning: Deprecated Reset() interface used.\n");
2199 fprintf(stderr, "RenderTexture::Reset(): failed to invalidate.\n");