1 // File : RenderTexture.cpp
2 //---------------------------------------------------------------------------
3 // Copyright (c) 2002-2004 Mark J. Harris
4 //---------------------------------------------------------------------------
5 // This software is provided 'as-is', without any express or implied
6 // warranty. In no event will the authors be held liable for any
7 // damages arising from the use of this software.
9 // Permission is granted to anyone to use this software for any
10 // purpose, including commercial applications, and to alter it and
11 // redistribute it freely, subject to the following restrictions:
13 // 1. The origin of this software must not be misrepresented; you
14 // must not claim that you wrote the original software. If you use
15 // this software in a product, an acknowledgment in the product
16 // documentation would be appreciated but is not required.
18 // 2. Altered source versions must be plainly marked as such, and
19 // must not be misrepresented as being the original software.
21 // 3. This notice may not be removed or altered from any source
24 // --------------------------------------------------------------------------
26 // Original RenderTexture class: Mark J. Harris
27 // Original Render to Depth Texture support: Thorsten Scheuermann
28 // Linux Copy-to-texture: Eric Werness
29 // OS X: Alexander Powell (someone please help)
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
46 * Nov. 2005, Use the simgear logging facility, Erik Hofman
47 * Mar. 2006, Add MAC OS X support, Alexander Powell
51 # include <simgear_config.h>
58 #include <simgear/compiler.h>
59 #include <simgear/debug/logstream.hxx>
60 #include <simgear/screen/extensions.hxx>
61 #include <simgear/screen/RenderTexture.h>
71 #pragma comment(lib, "gdi32.lib") // required for GetPixelFormat()
77 static bool fctPtrInited = false;
78 /* WGL_ARB_pixel_format */
79 static wglChoosePixelFormatARBProc wglChoosePixelFormatARBPtr = 0;
80 static wglGetPixelFormatAttribivARBProc wglGetPixelFormatAttribivARBPtr = 0;
82 static wglCreatePbufferARBProc wglCreatePbufferARBPtr = 0;
83 static wglGetPbufferDCARBProc wglGetPbufferDCARBPtr = 0;
84 static wglQueryPbufferARBProc wglQueryPbufferARBPtr = 0;
85 static wglReleasePbufferDCARBProc wglReleasePbufferDCARBPtr = 0;
86 static wglDestroyPbufferARBProc wglDestroyPbufferARBPtr = 0;
87 /* WGL_ARB_render_texture */
88 static wglBindTexImageARBProc wglBindTexImageARBPtr = 0;
89 static wglReleaseTexImageARBProc wglReleaseTexImageARBPtr = 0;
91 #elif defined( __MACH__ )
93 static bool glXVersion1_3Present = false;
94 static glXChooseFBConfigProc glXChooseFBConfigPtr = 0;
95 static glXCreatePbufferProc glXCreatePbufferPtr = 0;
96 static glXCreateGLXPbufferProc glXCreateGLXPbufferPtr = 0;
97 static glXGetVisualFromFBConfigProc glXGetVisualFromFBConfigPtr = 0;
98 static glXCreateContextProc glXCreateContextPtr = 0;
99 static glXCreateContextWithConfigProc glXCreateContextWithConfigPtr = 0;
100 static glXDestroyPbufferProc glXDestroyPbufferPtr = 0;
101 static glXQueryDrawableProc glXQueryDrawablePtr = 0;
102 static glXQueryGLXPbufferSGIXProc glXQueryGLXPbufferSGIXPtr = 0;
105 //---------------------------------------------------------------------------
106 // Function : RenderTexture::RenderTexture
108 //---------------------------------------------------------------------------
110 * @fn RenderTexture::RenderTexture()
111 * @brief Mode-string-based Constructor.
113 RenderTexture::RenderTexture(const char *strMode)
117 _bIsDepthTexture(false),
118 _bHasARBDepthTexture(true), // [Redge]
119 #if defined(_WIN32) || defined(__MACH__)
120 _eUpdateMode(RT_RENDER_TO_TEXTURE),
122 _eUpdateMode(RT_COPY_TO_TEXTURE),
124 _bInitialized(false),
126 _bIsBufferBound(false),
127 _iCurrentBoundBuffer(0),
131 _bDoubleBuffered(false),
135 _bShareObjects(false),
136 _bCopyContext(false),
142 _hPreviousContext(0),
143 #elif defined( __MACH__ )
146 _hPreviousContext(NULL),
151 _hPreviousDrawable(0),
152 _hPreviousContext(0),
154 _iTextureTarget(GL_NONE),
157 _pPoorDepthTexture(0) // [Redge]
159 _iNumColorBits[0] = _iNumColorBits[1] =
160 _iNumColorBits[2] = _iNumColorBits[3] = 0;
163 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
164 _pixelFormatAttribs.push_back(true);
165 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
166 _pixelFormatAttribs.push_back(true);
168 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
169 _pbufferAttribs.push_back(true);
170 #elif defined( __MACH__ )
171 //_pixelFormatAttribs.push_back(kCGLPFANoRecovery);
172 _pixelFormatAttribs.push_back(kCGLPFAAccelerated);
173 _pixelFormatAttribs.push_back(kCGLPFAWindow);
174 _pixelFormatAttribs.push_back(kCGLPFAPBuffer);
176 _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
177 _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
178 _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
179 _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
182 _ParseModeString(strMode, _pixelFormatAttribs, _pbufferAttribs);
185 _pixelFormatAttribs.push_back(0);
186 _pbufferAttribs.push_back(0);
187 #elif defined(__MACH__)
188 _pixelFormatAttribs.push_back((CGLPixelFormatAttribute)0);
189 _pbufferAttribs.push_back((CGLPixelFormatAttribute)0);
191 _pixelFormatAttribs.push_back(None);
196 //---------------------------------------------------------------------------
197 // Function : RenderTexture::~RenderTexture
199 //---------------------------------------------------------------------------
201 * @fn RenderTexture::~RenderTexture()
204 RenderTexture::~RenderTexture()
209 //---------------------------------------------------------------------------
210 // Function : _cglcheckError
212 //---------------------------------------------------------------------------
214 * @fn _cglCheckError()
215 * @brief Prints to stderr a description when an OS X error is found.
218 static void _cglCheckErrorHelper(CGLError err, char *sourceFile, int sourceLine)
223 fprintf(stderr, "RenderTexture CGL Error: %s at (%s,%d)",
224 CGLErrorString(err), sourceFile, sourceLine);
229 # define _cglCheckError(err) _cglCheckErrorHelper(err,__FILE__,__LINE__)
234 //---------------------------------------------------------------------------
235 // Function : _wglGetLastError
237 //---------------------------------------------------------------------------
239 * @fn wglGetLastError()
240 * @brief Returns the last windows error generated.
243 void _wglGetLastError()
247 DWORD err = GetLastError();
250 case ERROR_INVALID_PIXEL_FORMAT:
251 SG_LOG(SG_GL, SG_ALERT,
252 "RenderTexture Win32 Error: ERROR_INVALID_PIXEL_FORMAT");
254 case ERROR_NO_SYSTEM_RESOURCES:
255 SG_LOG(SG_GL, SG_ALERT,
256 "RenderTexture Win32 Error: ERROR_NO_SYSTEM_RESOURCES");
258 case ERROR_INVALID_DATA:
259 SG_LOG(SG_GL, SG_ALERT,
260 "RenderTexture Win32 Error: ERROR_INVALID_DATA");
262 case ERROR_INVALID_WINDOW_HANDLE:
263 SG_LOG(SG_GL, SG_ALERT,
264 "RenderTexture Win32 Error: ERROR_INVALID_WINDOW_HANDLE");
266 case ERROR_RESOURCE_TYPE_NOT_FOUND:
267 SG_LOG(SG_GL, SG_ALERT,
268 "RenderTexture Win32 Error: ERROR_RESOURCE_TYPE_NOT_FOUND");
275 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
276 FORMAT_MESSAGE_FROM_SYSTEM |
277 FORMAT_MESSAGE_IGNORE_INSERTS,
280 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
285 SG_LOG(SG_GL, SG_ALERT, "RenderTexture Win32 Error " << err << ":" << lpMsgBuf);
286 LocalFree( lpMsgBuf );
295 //---------------------------------------------------------------------------
296 // Function : PrintExtensionError
298 //---------------------------------------------------------------------------
300 * @fn PrintExtensionError( char* strMsg, ... )
301 * @brief Prints an error about missing OpenGL extensions.
303 void PrintExtensionError( const char* strMsg, ... )
305 SG_LOG(SG_GL, SG_ALERT,
306 "Error: RenderTexture requires the following unsupported "
307 "OpenGL extensions: ");
310 va_start(args, strMsg);
311 #if defined _WIN32 && !defined __CYGWIN__
312 _vsnprintf( strBuffer, 512, strMsg, args );
314 vsnprintf( strBuffer, 512, strMsg, args );
318 SG_LOG(SG_GL, SG_ALERT, strMsg);
322 //---------------------------------------------------------------------------
323 // Function : RenderTexture::Initialize
325 //---------------------------------------------------------------------------
327 * @fn RenderTexture::Initialize(int width, int height, bool shareObjects, bool copyContext);
328 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
330 * This function creates of the p-buffer. It can only be called once a GL
331 * context has already been created.
333 bool RenderTexture::Initialize(int width, int height,
334 bool shareObjects /* = true */,
335 bool copyContext /* = false */)
337 assert(width > 0 && height > 0);
339 _iWidth = width; _iHeight = height;
340 _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
342 _bShareObjects = shareObjects;
343 _bCopyContext = copyContext;
345 // Check if this is an NVXX GPU and verify necessary extensions.
346 if (!_VerifyExtensions())
353 // Get the current context.
354 HDC hdc = wglGetCurrentDC();
357 HGLRC hglrc = wglGetCurrentContext();
362 unsigned int iNumFormats;
366 // Get the pixel format for the on-screen window.
367 iFormat = GetPixelFormat(hdc);
370 SG_LOG(SG_GL, SG_ALERT,
371 "RenderTexture Error: GetPixelFormat() failed.");
377 if (!wglChoosePixelFormatARBPtr(hdc, &_pixelFormatAttribs[0], NULL,
378 1, &iFormat, &iNumFormats))
380 SG_LOG(SG_GL, SG_ALERT,
381 "RenderTexture Error: wglChoosePixelFormatARB() failed.");
385 if ( iNumFormats <= 0 )
387 SG_LOG(SG_GL, SG_ALERT,
388 "RenderTexture Error: Couldn't find a suitable "
395 // Create the p-buffer.
396 _hPBuffer = wglCreatePbufferARBPtr(hdc, iFormat, _iWidth, _iHeight,
397 &_pbufferAttribs[0]);
400 SG_LOG(SG_GL, SG_ALERT,
401 "RenderTexture Error: wglCreatePbufferARB() failed.");
406 // Get the device context.
407 _hDC = wglGetPbufferDCARBPtr( _hPBuffer);
410 SG_LOG(SG_GL, SG_ALERT,
411 "RenderTexture Error: wglGetGetPbufferDCARB() failed.");
416 // Create a gl context for the p-buffer.
419 // Let's use the same gl context..
420 // Since the device contexts are compatible (i.e. same pixelformat),
421 // we should be able to use the same gl rendering context.
426 _hGLContext = wglCreateContext( _hDC );
429 SG_LOG(SG_GL, SG_ALERT,
430 "RenderTexture Error: wglCreateContext() failed.");
436 // Share lists, texture objects, and program objects.
439 if( !wglShareLists(hglrc, _hGLContext) )
441 SG_LOG(SG_GL, SG_ALERT,
442 "RenderTexture Error: wglShareLists() failed.");
448 // Determine the actual width and height we were able to create.
449 wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
450 wglQueryPbufferARBPtr( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
452 _bInitialized = true;
454 // get the actual number of bits allocated:
455 int attrib = WGL_RED_BITS_ARB;
459 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
461 attrib = WGL_GREEN_BITS_ARB;
463 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
465 attrib = WGL_BLUE_BITS_ARB;
467 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
469 attrib = WGL_ALPHA_BITS_ARB;
471 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
473 attrib = WGL_DEPTH_BITS_ARB;
475 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
477 attrib = WGL_STENCIL_BITS_ARB;
479 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
481 attrib = WGL_DOUBLE_BUFFER_ARB;
483 (wglGetPixelFormatAttribivARBPtr(_hDC, iFormat, 0, 1, &attrib, &value))
484 ? (value?true:false) : false;
486 #if defined(_DEBUG) | defined(DEBUG)
487 SG_LOG(SG_GL, SG_ALERT, "Created a " << _iWidth << "x" << _iHeight <<
488 " RenderTexture with BPP(" <<
489 _iNumColorBits[0] << "," << _iNumColorBits[1] << "," <<
490 _iNumColorBits[2] << "," << _iNumColorBits[3] << ")");
491 if (_iNumDepthBits) SG_LOG(SG_GL, SG_ALERT, " depth=" << _iNumDepthBits);
492 if (_iNumStencilBits) SG_LOG(SG_GL, SG_ALERT, " stencil=" << _iNumStencilBits);
493 if (_bDoubleBuffered) SG_LOG(SG_GL, SG_ALERT, " double buffered");
496 #elif defined( __MACH__ )
497 // Get the current context.
498 CGLContextObj hglrc = CGLGetCurrentContext();
500 fprintf(stderr, "Couldn't get current context!");
502 CGLPixelFormatObj pixFormat = NULL;
503 long int iNumFormats;
506 // Copy the _pixelFormatAttribs into another array to fix
508 CGLPixelFormatAttribute *pixFormatAttribs =
509 (CGLPixelFormatAttribute *)malloc(sizeof(CGLPixelFormatAttribute)
510 * _pixelFormatAttribs.size());
512 for (unsigned int ii = 0; ii < _pixelFormatAttribs.size(); ii++)
514 pixFormatAttribs[ii] =
515 (CGLPixelFormatAttribute)_pixelFormatAttribs[ii];
519 CGLChoosePixelFormat(&pixFormatAttribs[0], &pixFormat, &iNumFormats))
522 "RenderTexture Error: CGLChoosePixelFormat() failed.\n");
523 _cglCheckError(error);
526 if ( iNumFormats <= 0 )
528 SG_LOG(SG_GL, SG_ALERT,
529 "RenderTexture Error: Couldn't find a suitable "
534 // Free the copy of the _pixelFormatAttribs array
535 free(pixFormatAttribs);
537 // Create the context.
538 error = CGLCreateContext(pixFormat, (_bShareObjects)
539 ? CGLGetCurrentContext() : NULL, &_hGLContext);
543 "RenderTexture Error: CGLCreateContext() failed.\n");
544 _cglCheckError(error);
547 CGLDestroyPixelFormat(pixFormat);
549 // Create the p-buffer.
550 error = CGLCreatePBuffer(_iWidth, _iHeight, (_bRectangle)
551 ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D, GL_RGBA, 0, &_hPBuffer);
555 "RenderTexture Error: CGLCreatePBuffer() failed.\n");
556 _cglCheckError(error);
561 if (error = CGLGetVirtualScreen(CGLGetCurrentContext(), &screen))
563 _cglCheckError(error);
566 if (error = CGLSetPBuffer(_hGLContext, _hPBuffer, 0, 0, screen))
568 _cglCheckError(error);
572 // Determine the actual width and height we were able to create.
573 //wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
574 //wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
576 _bInitialized = true;
579 // get the actual number of bits allocated:
580 int attrib = WGL_RED_BITS_ARB;
584 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
586 attrib = WGL_GREEN_BITS_ARB;
588 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
590 attrib = WGL_BLUE_BITS_ARB;
592 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
594 attrib = WGL_ALPHA_BITS_ARB;
596 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
598 attrib = WGL_DEPTH_BITS_ARB;
600 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
602 attrib = WGL_STENCIL_BITS_ARB;
604 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
606 attrib = WGL_DOUBLE_BUFFER_ARB;
608 (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
609 ? (value?true:false) : false;
612 #if defined(_DEBUG) | defined(DEBUG)
613 fprintf(stderr, "Created a %dx%d RenderTexture with BPP(%d, %d, %d, %d)",
615 _iNumColorBits[0], _iNumColorBits[1],
616 _iNumColorBits[2], _iNumColorBits[3]);
617 if (_iNumDepthBits) fprintf(stderr, " depth=%d", _iNumDepthBits);
618 if (_iNumStencilBits) fprintf(stderr, " stencil=%d", _iNumStencilBits);
619 if (_bDoubleBuffered) fprintf(stderr, " double buffered");
620 fprintf(stderr, "\n");
623 #else // !_WIN32, !__MACH_
624 _pDisplay = glXGetCurrentDisplay();
625 GLXContext context = glXGetCurrentContext();
626 int screen = DefaultScreen(_pDisplay);
627 XVisualInfo *visInfo = NULL;
629 GLXFBConfig *fbConfigs;
632 fbConfigs = glXChooseFBConfigPtr(_pDisplay, screen,
633 &_pixelFormatAttribs[0], &nConfigs);
635 if (nConfigs == 0 || !fbConfigs)
637 SG_LOG(SG_GL, SG_ALERT,
638 "RenderTexture Error: Couldn't find a suitable pixel format.");
642 // Pick the first returned format that will return a pbuffer
643 if (glXVersion1_3Present)
646 GLX_PBUFFER_WIDTH, _iWidth,
647 GLX_PBUFFER_HEIGHT, _iHeight,
648 GLX_LARGEST_PBUFFER, False,
651 for (int i=0;i<nConfigs;i++)
653 _hPBuffer = glXCreatePbufferPtr(_pDisplay, fbConfigs[i], pbufAttrib);
656 XVisualInfo *visInfo = glXGetVisualFromFBConfigPtr(_pDisplay, fbConfigs[i]);
658 _hGLContext = glXCreateContextPtr(_pDisplay, visInfo,
659 _bShareObjects ? context : NULL,
677 for (int i=0;i<nConfigs;i++)
679 _hPBuffer = glXCreateGLXPbufferPtr(_pDisplay, fbConfigs[i],
680 _iWidth, _iHeight, NULL);
683 _hGLContext = glXCreateContextWithConfigPtr(_pDisplay,
686 _bShareObjects ? context : NULL,
696 SG_LOG(SG_GL, SG_ALERT,
697 "RenderTexture Error: glXCreateGLXPbufferPtr() failed.");
704 _hGLContext = glXCreateContext(_pDisplay, visInfo,
705 _bShareObjects ? context : NULL, False);
708 SG_LOG(SG_GL, SG_ALERT,
709 "RenderTexture Error: glXCreateContext() failed.");
714 if (!glXVersion1_3Present)
716 glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_WIDTH_SGIX,
718 glXQueryGLXPbufferSGIXPtr(_pDisplay, _hPBuffer, GLX_HEIGHT_SGIX,
722 _bInitialized = true;
724 // XXX Query the color format
729 // Now that the pbuffer is created, allocate any texture objects needed,
730 // and initialize them (for CTT updates only). These must be allocated
731 // in the context of the pbuffer, though, or the RT won't work without
734 if (false == wglMakeCurrent( _hDC, _hGLContext))
739 #elif defined( __MACH__ )
741 if (err = CGLSetCurrentContext(_hGLContext))
747 _hPreviousContext = glXGetCurrentContext();
748 _hPreviousDrawable = glXGetCurrentDrawable();
750 if (False == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
756 bool result = _InitializeTextures();
758 BindBuffer(WGL_FRONT_LEFT_ARB);
764 // make the previous rendering context current
765 if (false == wglMakeCurrent( hdc, hglrc))
770 #elif defined( __MACH__ )
771 if (err = CGLSetCurrentContext(_hPreviousContext))
777 if (False == glXMakeCurrent(_pDisplay,
778 _hPreviousDrawable, _hPreviousContext))
782 if (glXVersion1_3Present)
784 GLXDrawable draw = glXGetCurrentDrawable();
785 glXQueryDrawablePtr(_pDisplay, draw, GLX_WIDTH, (unsigned int*)&_iWidth);
786 glXQueryDrawablePtr(_pDisplay, draw, GLX_HEIGHT, (unsigned int*)&_iHeight);
794 //---------------------------------------------------------------------------
795 // Function : RenderTexture::_Invalidate
797 //---------------------------------------------------------------------------
799 * @fn RenderTexture::_Invalidate()
800 * @brief Returns the pbuffer memory to the graphics device.
803 bool RenderTexture::_Invalidate()
805 _iNumColorBits[0] = _iNumColorBits[1] =
806 _iNumColorBits[2] = _iNumColorBits[3] = 0;
808 _iNumStencilBits = 0;
811 glDeleteTextures(1, &_iTextureID);
812 if (_bIsDepthTexture)
815 if (!_bHasARBDepthTexture) delete[] _pPoorDepthTexture;
817 glDeleteTextures(1, &_iDepthTextureID);
823 // Check if we are currently rendering in the pbuffer
824 if (wglGetCurrentContext() == _hGLContext)
827 wglDeleteContext( _hGLContext);
828 wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
829 wglDestroyPbufferARBPtr( _hPBuffer );
833 #elif defined( __MACH__ )
836 if (CGLGetCurrentContext() == _hGLContext)
837 CGLSetCurrentContext(NULL);
839 CGLDestroyContext(_hGLContext);
840 CGLDestroyPBuffer(_hPBuffer);
847 if(glXGetCurrentContext() == _hGLContext)
848 // XXX I don't know if this is right at all
849 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
850 glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
856 // [WVB] do we need to call _ReleaseBoundBuffers() too?
861 //---------------------------------------------------------------------------
862 // Function : RenderTexture::Reset
864 //---------------------------------------------------------------------------
866 * @fn RenderTexture::Reset()
867 * @brief Resets the resolution of the offscreen buffer.
869 * Causes the buffer to delete itself. User must call Initialize() again
872 bool RenderTexture::Reset(const char *strMode, ...)
874 _iWidth = 0; _iHeight = 0;
875 _bIsTexture = false; _bIsDepthTexture = false,
876 _bHasARBDepthTexture = true;
877 #if defined(_WIN32) || defined(__MACH__)
878 _eUpdateMode = RT_RENDER_TO_TEXTURE;
880 _eUpdateMode = RT_COPY_TO_TEXTURE;
882 _bInitialized = false;
884 _bIsBufferBound = false;
885 _iCurrentBoundBuffer = 0;
886 _iNumDepthBits = 0; _iNumStencilBits = 0;
887 _bDoubleBuffered = false;
888 _bFloat = false; _bPowerOf2 = true;
889 _bRectangle = false; _bMipmap = false;
890 _bShareObjects = false; _bCopyContext = false;
891 _iTextureTarget = GL_NONE; _iTextureID = 0;
892 _iDepthTextureID = 0;
893 _pPoorDepthTexture = 0;
894 _pixelFormatAttribs.clear();
895 _pbufferAttribs.clear();
897 if (IsInitialized() && !_Invalidate())
899 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Reset(): failed to invalidate.");
903 _iNumColorBits[0] = _iNumColorBits[1] =
904 _iNumColorBits[2] = _iNumColorBits[3] = 0;
907 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
908 _pixelFormatAttribs.push_back(true);
909 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
910 _pixelFormatAttribs.push_back(true);
912 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
913 _pbufferAttribs.push_back(true);
914 #elif defined( __MACH__ )
915 //_pixelFormatAttribs.push_back(kCGLPFANoRecovery);
916 _pixelFormatAttribs.push_back(kCGLPFAAccelerated);
917 _pixelFormatAttribs.push_back(kCGLPFAWindow);
918 _pixelFormatAttribs.push_back(kCGLPFAPBuffer);
920 _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
921 _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
922 _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
923 _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
928 va_start(args,strMode);
929 #if defined _WIN32 && !defined __CYGWIN__
930 _vsnprintf( strBuffer, 256, strMode, args );
932 vsnprintf( strBuffer, 256, strMode, args );
936 _ParseModeString(strBuffer, _pixelFormatAttribs, _pbufferAttribs);
939 _pixelFormatAttribs.push_back(0);
940 _pbufferAttribs.push_back(0);
941 #elif defined(__MACH__)
942 _pixelFormatAttribs.push_back((CGLPixelFormatAttribute)0);
944 _pixelFormatAttribs.push_back(None);
949 //------------------------------------------------------------------------------
950 // Function : RenderTexture::Resize
952 //------------------------------------------------------------------------------
954 * @fn RenderTexture::Resize(int iWidth, int iHeight)
955 * @brief Changes the size of the offscreen buffer.
957 * Like Reset() this causes the buffer to delete itself.
958 * But unlike Reset(), this call re-initializes the RenderTexture.
959 * Note that Resize() will not work after calling Reset(), or before
960 * calling Initialize() the first time.
962 bool RenderTexture::Resize(int iWidth, int iHeight)
964 if (!_bInitialized) {
965 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): must Initialize() first.");
968 if (iWidth == _iWidth && iHeight == _iHeight) {
972 // Do same basic work as _Invalidate, but don't reset all our flags
974 glDeleteTextures(1, &_iTextureID);
975 if (_bIsDepthTexture)
976 glDeleteTextures(1, &_iDepthTextureID);
980 // Check if we are currently rendering in the pbuffer
981 if (wglGetCurrentContext() == _hGLContext)
984 wglDeleteContext( _hGLContext);
985 wglReleasePbufferDCARBPtr( _hPBuffer, _hDC);
986 wglDestroyPbufferARBPtr( _hPBuffer );
990 #elif defined( __MACH__ )
993 if (CGLGetCurrentContext() == _hGLContext)
994 CGLSetCurrentContext(NULL);
996 CGLDestroyContext(_hGLContext);
997 CGLDestroyPBuffer(_hPBuffer);
1004 if(glXGetCurrentContext() == _hGLContext)
1005 // XXX I don't know if this is right at all
1006 glXMakeCurrent(_pDisplay, _hPBuffer, 0);
1007 glXDestroyPbufferPtr(_pDisplay, _hPBuffer);
1012 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Resize(): failed to resize.");
1015 _bInitialized = false;
1016 return Initialize(iWidth, iHeight, _bShareObjects, _bCopyContext);
1019 //---------------------------------------------------------------------------
1020 // Function : RenderTexture::BeginCapture
1022 //---------------------------------------------------------------------------
1024 * @fn RenderTexture::BeginCapture()
1025 * @brief Activates rendering to the RenderTexture.
1027 bool RenderTexture::BeginCapture()
1031 SG_LOG(SG_GL, SG_ALERT,
1032 "RenderTexture::BeginCapture(): Texture is not initialized!");
1036 // cache the current context so we can reset it when EndCapture() is called.
1037 _hPreviousDC = wglGetCurrentDC();
1038 if (NULL == _hPreviousDC)
1040 _hPreviousContext = wglGetCurrentContext();
1041 if (NULL == _hPreviousContext)
1043 #elif defined( __MACH__ )
1044 _hPreviousContext = CGLGetCurrentContext();
1046 _hPreviousContext = glXGetCurrentContext();
1047 _hPreviousDrawable = glXGetCurrentDrawable();
1050 _ReleaseBoundBuffers();
1052 return _MakeCurrent();
1056 //---------------------------------------------------------------------------
1057 // Function : RenderTexture::EndCapture
1059 //---------------------------------------------------------------------------
1061 * @fn RenderTexture::EndCapture()
1062 * @brief Ends rendering to the RenderTexture.
1064 bool RenderTexture::EndCapture()
1068 SG_LOG(SG_GL, SG_ALERT,
1069 "RenderTexture::EndCapture() : Texture is not initialized!");
1073 glFlush(); // Added by a-lex
1078 // make the previous rendering context current
1079 if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
1084 #elif defined( __MACH__ )
1086 if (err = CGLSetCurrentContext(_hPreviousContext))
1088 _cglCheckError(err);
1092 if (False == glXMakeCurrent(_pDisplay, _hPreviousDrawable,
1099 // rebind the textures to a buffers for RTT
1100 BindBuffer(_iCurrentBoundBuffer);
1106 //---------------------------------------------------------------------------
1107 // Function : RenderTexture::BeginCapture(RenderTexture*)
1109 //---------------------------------------------------------------------------
1111 * @fn RenderTexture::BeginCapture(RenderTexture* other)
1112 * @brief Ends capture of 'other', begins capture on 'this'
1114 * When performing a series of operations where you modify one texture after
1115 * another, it is more efficient to use this method instead of the equivalent
1116 * 'EndCapture'/'BeginCapture' pair. This method switches directly to the
1117 * new context rather than changing to the default context, and then to the
1120 * RenderTexture doesn't have any mechanism for determining if
1121 * 'current' really is currently active, so no error will be thrown
1124 bool RenderTexture::BeginCapture(RenderTexture* current)
1126 // bool bContextReset = false;
1128 if (current == this) {
1129 return true; // no switch necessary
1132 // treat as normal Begin if current is 0.
1133 return BeginCapture();
1137 SG_LOG(SG_GL, SG_ALERT,
1138 "RenderTexture::BeginCapture(RenderTexture*): Texture is not initialized!");
1141 if (!current->_bInitialized)
1143 SG_LOG(SG_GL, SG_ALERT,
1144 "RenderTexture::BeginCapture(RenderTexture): 'current' texture is not initialized!");
1148 // Sync current pbuffer with its CTT texture if necessary
1149 current->_MaybeCopyBuffer();
1151 // pass along the previous context so we can reset it when
1152 // EndCapture() is called.
1154 _hPreviousDC = current->_hPreviousDC;
1155 if (NULL == _hPreviousDC)
1157 _hPreviousContext = current->_hPreviousContext;
1158 if (NULL == _hPreviousContext)
1160 #elif defined( __MACH__ )
1161 _hPreviousContext = current->_hPreviousContext;
1163 _hPreviousContext = current->_hPreviousContext;
1164 _hPreviousDrawable = current->_hPreviousDrawable;
1167 // Unbind textures before making context current
1168 if (!_ReleaseBoundBuffers())
1171 // Make the pbuffer context current
1172 if (!_MakeCurrent())
1175 // Rebind buffers of initial RenderTexture
1176 current->BindBuffer(_iCurrentBoundBuffer);
1177 current->_BindDepthBuffer();
1184 //---------------------------------------------------------------------------
1185 // Function : RenderTexture::Bind
1187 //---------------------------------------------------------------------------
1189 * @fn RenderTexture::Bind()
1190 * @brief Binds RGB texture.
1192 void RenderTexture::Bind() const
1194 if (_bInitialized && _bIsTexture)
1196 glBindTexture(_iTextureTarget, _iTextureID);
1201 //---------------------------------------------------------------------------
1202 // Function : RenderTexture::BindDepth
1204 //---------------------------------------------------------------------------
1206 * @fn RenderTexture::BindDepth()
1207 * @brief Binds depth texture.
1209 void RenderTexture::BindDepth() const
1211 if (_bInitialized && _bIsDepthTexture)
1213 glBindTexture(_iTextureTarget, _iDepthTextureID);
1218 //---------------------------------------------------------------------------
1219 // Function : RenderTexture::BindBuffer
1221 //---------------------------------------------------------------------------
1223 * @fn RenderTexture::BindBuffer()
1224 * @brief Associate the RTT texture id with 'iBuffer' (e.g. WGL_FRONT_LEFT_ARB)
1226 bool RenderTexture::BindBuffer( int iBuffer )
1228 // Must bind the texture too
1229 if (_bInitialized && _bIsTexture)
1231 glBindTexture(_iTextureTarget, _iTextureID);
1234 if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
1235 (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
1237 if (FALSE == wglBindTexImageARBPtr(_hPBuffer, iBuffer))
1239 // WVB: WGL API considers binding twice to the same buffer
1240 // to be an error. But we don't want to
1241 //_wglGetLastError();
1245 _bIsBufferBound = true;
1246 _iCurrentBoundBuffer = iBuffer;
1248 #elif defined(__MACH__)
1249 if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
1250 (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
1253 if (err=CGLTexImagePBuffer(CGLGetCurrentContext(), _hPBuffer, iBuffer))
1255 _cglCheckError(err);
1257 _bIsBufferBound = true;
1258 _iCurrentBoundBuffer = iBuffer;
1266 //---------------------------------------------------------------------------
1267 // Function : RenderTexture::BindDepthBuffer
1269 //---------------------------------------------------------------------------
1271 * @fn RenderTexture::_BindDepthBuffer()
1272 * @brief Associate the RTT depth texture id with the depth buffer
1274 bool RenderTexture::_BindDepthBuffer() const
1277 if (_bInitialized && _bIsDepthTexture &&
1278 RT_RENDER_TO_TEXTURE == _eUpdateMode)
1280 glBindTexture(_iTextureTarget, _iDepthTextureID);
1281 if (FALSE == wglBindTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1287 #elif defined(__MACH__)
1288 if (_bInitialized && _bIsDepthTexture &&
1289 RT_RENDER_TO_TEXTURE == _eUpdateMode)
1291 glBindTexture(_iTextureTarget, _iDepthTextureID);
1292 //if (FALSE == CGLTexImagePBuffer(<#CGLContextObj ctx#>,<#CGLPBufferObj pbuffer#>,<#unsigned long source#>)(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1294 // _wglGetLastError();
1302 //---------------------------------------------------------------------------
1303 // Function : RenderTexture::_ParseModeString
1305 //---------------------------------------------------------------------------
1307 * @fn RenderTexture::_ParseModeString()
1308 * @brief Parses the user-specified mode string for RenderTexture parameters.
1310 void RenderTexture::_ParseModeString(const char *modeString,
1311 vector<int> &pfAttribs,
1312 vector<int> &pbAttribs)
1314 if (!modeString || strcmp(modeString, "") == 0)
1317 _iNumComponents = 0;
1318 #if defined(_WIN32) || defined(__MACH__)
1319 _eUpdateMode = RT_RENDER_TO_TEXTURE;
1321 _eUpdateMode = RT_COPY_TO_TEXTURE;
1325 bool bHasStencil = false;
1326 bool bBind2D = false;
1327 bool bBindRECT = false;
1328 bool bBindCUBE = false;
1330 char *mode = strdup(modeString);
1333 vector<string> tokens;
1334 char *buf = strtok(mode, " ");
1337 tokens.push_back(buf);
1338 buf = strtok(NULL, " ");
1341 for (unsigned int i = 0; i < tokens.size(); i++)
1343 string token = tokens[i];
1345 KeyVal kv = _GetKeyValuePair(token);
1348 if (kv.first == "rgb" && (_iNumComponents <= 1))
1350 if (kv.second.find("f") != kv.second.npos)
1353 vector<int> bitVec = _ParseBitVector(kv.second);
1355 if (bitVec.size() < 3) // expand the scalar to a vector
1357 bitVec.push_back(bitVec[0]);
1358 bitVec.push_back(bitVec[0]);
1362 pfAttribs.push_back(WGL_RED_BITS_ARB);
1363 pfAttribs.push_back(bitVec[0]);
1364 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1365 pfAttribs.push_back(bitVec[1]);
1366 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1367 pfAttribs.push_back(bitVec[2]);
1368 #elif defined( __MACH__ )
1370 pfAttribs.push_back(AGL_RED_SIZE);
1371 pfAttribs.push_back(bitVec[0]);
1372 pfAttribs.push_back(AGL_GREEN_SIZE);
1373 pfAttribs.push_back(bitVec[1]);
1374 pfAttribs.push_back(AGL_BLUE_SIZE);
1375 pfAttribs.push_back(bitVec[2]);
1377 pfAttribs.push_back(kCGLPFAColorSize);
1378 pfAttribs.push_back(bitVec[0] + bitVec[1] + bitVec[2]);
1381 pfAttribs.push_back(GLX_RED_SIZE);
1382 pfAttribs.push_back(bitVec[0]);
1383 pfAttribs.push_back(GLX_GREEN_SIZE);
1384 pfAttribs.push_back(bitVec[1]);
1385 pfAttribs.push_back(GLX_BLUE_SIZE);
1386 pfAttribs.push_back(bitVec[2]);
1388 _iNumComponents += 3;
1391 else if (kv.first == "rgb")
1392 SG_LOG(SG_GL, SG_ALERT,
1393 "RenderTexture Warning: mistake in components definition "
1394 "(rgb + " << _iNumComponents << ").");
1396 if (kv.first == "rgba" && (_iNumComponents == 0))
1398 if (kv.second.find("f") != kv.second.npos)
1401 vector<int> bitVec = _ParseBitVector(kv.second);
1403 if (bitVec.size() < 4) // expand the scalar to a vector
1405 bitVec.push_back(bitVec[0]);
1406 bitVec.push_back(bitVec[0]);
1407 bitVec.push_back(bitVec[0]);
1411 pfAttribs.push_back(WGL_RED_BITS_ARB);
1412 pfAttribs.push_back(bitVec[0]);
1413 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1414 pfAttribs.push_back(bitVec[1]);
1415 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1416 pfAttribs.push_back(bitVec[2]);
1417 pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1418 pfAttribs.push_back(bitVec[3]);
1419 #elif defined( __MACH__ )
1421 pfAttribs.push_back(AGL_RED_SIZE);
1422 pfAttribs.push_back(bitVec[0]);
1423 pfAttribs.push_back(AGL_GREEN_SIZE);
1424 pfAttribs.push_back(bitVec[1]);
1425 pfAttribs.push_back(AGL_BLUE_SIZE);
1426 pfAttribs.push_back(bitVec[2]);
1427 pfAttribs.push_back(AGL_ALPHA_SIZE);
1428 pfAttribs.push_back(bitVec[3]);
1430 pfAttribs.push_back(kCGLPFAColorSize);
1431 pfAttribs.push_back(bitVec[0] + bitVec[1] + bitVec[2] + bitVec[3]);
1432 //pfAttribs.push_back(kCGLPFAAlphaSize);
1433 //pfAttribs.push_back(bitVec[3]);
1434 // printf("Color size: %d\n", bitVec[0] + bitVec[1] + bitVec[2] + bitVec[3]);
1438 pfAttribs.push_back(GLX_RED_SIZE);
1439 pfAttribs.push_back(bitVec[0]);
1440 pfAttribs.push_back(GLX_GREEN_SIZE);
1441 pfAttribs.push_back(bitVec[1]);
1442 pfAttribs.push_back(GLX_BLUE_SIZE);
1443 pfAttribs.push_back(bitVec[2]);
1444 pfAttribs.push_back(GLX_ALPHA_SIZE);
1445 pfAttribs.push_back(bitVec[3]);
1447 _iNumComponents = 4;
1450 else if (kv.first == "rgba")
1451 SG_LOG(SG_GL, SG_ALERT,
1452 "RenderTexture Warning: mistake in components definition "
1453 "(rgba + " << _iNumComponents << ").");
1455 if (kv.first == "r" && (_iNumComponents <= 1))
1457 if (kv.second.find("f") != kv.second.npos)
1460 vector<int> bitVec = _ParseBitVector(kv.second);
1463 pfAttribs.push_back(WGL_RED_BITS_ARB);
1464 pfAttribs.push_back(bitVec[0]);
1465 #elif defined( __MACH__ )
1467 pfAttribs.push_back(AGL_RED_SIZE);
1468 pfAttribs.push_back(bitVec[0]);
1470 pfAttribs.push_back(kCGLPFAColorSize);
1471 pfAttribs.push_back(bitVec[0]);
1474 pfAttribs.push_back(GLX_RED_SIZE);
1475 pfAttribs.push_back(bitVec[0]);
1480 else if (kv.first == "r")
1481 SG_LOG(SG_GL, SG_ALERT,
1482 "RenderTexture Warning: mistake in components definition "
1483 "(r + " << _iNumComponents << ").");
1485 if (kv.first == "rg" && (_iNumComponents <= 1))
1487 if (kv.second.find("f") != kv.second.npos)
1490 vector<int> bitVec = _ParseBitVector(kv.second);
1492 if (bitVec.size() < 2) // expand the scalar to a vector
1494 bitVec.push_back(bitVec[0]);
1498 pfAttribs.push_back(WGL_RED_BITS_ARB);
1499 pfAttribs.push_back(bitVec[0]);
1500 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1501 pfAttribs.push_back(bitVec[1]);
1502 #elif defined( __MACH__ )
1504 pfAttribs.push_back(AGL_RED_SIZE);
1505 pfAttribs.push_back(bitVec[0]);
1506 pfAttribs.push_back(AGL_GREEN_SIZE);
1507 pfAttribs.push_back(bitVec[1]);
1509 pfAttribs.push_back(kCGLPFAColorSize);
1510 pfAttribs.push_back(bitVec[0] + bitVec[1]);
1513 pfAttribs.push_back(GLX_RED_SIZE);
1514 pfAttribs.push_back(bitVec[0]);
1515 pfAttribs.push_back(GLX_GREEN_SIZE);
1516 pfAttribs.push_back(bitVec[1]);
1518 _iNumComponents += 2;
1521 else if (kv.first == "rg")
1522 SG_LOG(SG_GL, SG_ALERT,
1523 "RenderTexture Warning: mistake in components definition "
1524 "(rg + " << _iNumComponents << ").");
1526 if (kv.first == "depth")
1528 if (kv.second == "")
1531 iDepthBits = strtol(kv.second.c_str(), 0, 10);
1535 if (kv.first == "stencil")
1539 pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1540 #elif defined( __MACH__ )
1542 pfAttribs.push_back(AGL_STENCIL_SIZE);
1544 pfAttribs.push_back(kCGLPFAStencilSize);
1547 pfAttribs.push_back(GLX_STENCIL_SIZE);
1549 if (kv.second == "")
1550 pfAttribs.push_back(8);
1552 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1556 if (kv.first == "samples")
1559 pfAttribs.push_back(WGL_SAMPLE_BUFFERS_ARB);
1560 pfAttribs.push_back(1);
1561 pfAttribs.push_back(WGL_SAMPLES_ARB);
1562 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1563 #elif defined( __MACH__ )
1565 pfAttribs.push_back(AGL_SAMPLE_BUFFERS_ARB);
1566 pfAttribs.push_back(1);
1567 pfAttribs.push_back(AGL_SAMPLES_ARB);
1569 pfAttribs.push_back(kCGLPFAMultisample);
1570 pfAttribs.push_back(kCGLPFASamples);
1572 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1574 pfAttribs.push_back(GLX_SAMPLE_BUFFERS_ARB);
1575 pfAttribs.push_back(1);
1576 pfAttribs.push_back(GLX_SAMPLES_ARB);
1577 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1583 if (kv.first == "doublebuffer" || kv.first == "double")
1586 pfAttribs.push_back(WGL_DOUBLE_BUFFER_ARB);
1587 pfAttribs.push_back(true);
1588 #elif defined( __MACH__ )
1590 pfAttribs.push_back(AGL_DOUBLEBUFFER);
1591 pfAttribs.push_back(True);
1593 pfAttribs.push_back(kCGLPFADoubleBuffer);
1596 pfAttribs.push_back(GLX_DOUBLEBUFFER);
1597 pfAttribs.push_back(True);
1602 if (kv.first == "aux")
1605 pfAttribs.push_back(WGL_AUX_BUFFERS_ARB);
1606 #elif defined( __MACH__ )
1608 pfAttribs.push_back(AGL_AUX_BUFFERS);
1610 pfAttribs.push_back(kCGLPFAAuxBuffers);
1613 pfAttribs.push_back(GLX_AUX_BUFFERS);
1615 if (kv.second == "")
1616 pfAttribs.push_back(0);
1618 pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
1622 if (token.find("tex") == 0)
1626 if ((kv.first == "texRECT") && (GL_NV_texture_rectangle ||
1627 GL_EXT_texture_rectangle))
1632 else if (kv.first == "texCUBE")
1644 if (token.find("depthTex") == 0)
1646 _bIsDepthTexture = true;
1648 if ((kv.first == "depthTexRECT") && (GL_NV_texture_rectangle ||
1649 GL_EXT_texture_rectangle))
1654 else if (kv.first == "depthTexCUBE")
1666 if (kv.first == "mipmap")
1672 if (kv.first == "rtt")
1674 _eUpdateMode = RT_RENDER_TO_TEXTURE;
1678 if (kv.first == "ctt")
1680 _eUpdateMode = RT_COPY_TO_TEXTURE;
1684 SG_LOG(SG_GL, SG_ALERT,
1685 "RenderTexture Error: Unknown pbuffer attribute: " <<
1689 // Processing of some options must be last because of interactions.
1691 // Check for inconsistent texture targets
1692 if (_bIsTexture && _bIsDepthTexture && !(bBind2D ^ bBindRECT ^ bBindCUBE))
1694 SG_LOG(SG_GL, SG_ALERT,
1695 "RenderTexture Warning: Depth and Color texture targets "
1699 // Apply default bit format if none specified
1701 if (0 == _iNumComponents)
1703 pfAttribs.push_back(WGL_RED_BITS_ARB);
1704 pfAttribs.push_back(8);
1705 pfAttribs.push_back(WGL_GREEN_BITS_ARB);
1706 pfAttribs.push_back(8);
1707 pfAttribs.push_back(WGL_BLUE_BITS_ARB);
1708 pfAttribs.push_back(8);
1709 pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1710 pfAttribs.push_back(8);
1711 _iNumComponents = 4;
1716 if (_bIsDepthTexture && !iDepthBits)
1720 pfAttribs.push_back(WGL_DEPTH_BITS_ARB);
1721 #elif defined( __MACH__ )
1723 pfAttribs.push_back(AGL_DEPTH_SIZE);
1725 pfAttribs.push_back(kCGLPFADepthSize);
1728 pfAttribs.push_back(GLX_DEPTH_SIZE);
1730 pfAttribs.push_back(iDepthBits); // default
1735 pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
1736 pfAttribs.push_back(0);
1737 #elif defined( __MACH__ )
1739 pfAttribs.push_back(AGL_STENCIL_SIZE);
1741 pfAttribs.push_back(kCGLPFAStencilSize);
1743 pfAttribs.push_back(0);
1745 pfAttribs.push_back(GLX_STENCIL_SIZE);
1746 pfAttribs.push_back(0);
1750 if (_iNumComponents < 4)
1752 // Can't do this right now -- on NVIDIA drivers, currently get
1753 // a non-functioning pbuffer if ALPHA_BITS=0 and
1754 // WGL_BIND_TO_TEXTURE_RGB_ARB=true
1756 //pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
1757 //pfAttribs.push_back(0);
1761 if (!WGL_NV_render_depth_texture && _bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1763 #if defined(DEBUG) || defined(_DEBUG)
1764 SG_LOG(SG_GL, SG_ALERT, "RenderTexture Warning: No support found for "
1765 "render to depth texture.");
1767 _bIsDepthTexture = false;
1771 if ((_bIsTexture || _bIsDepthTexture) &&
1772 (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1777 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1778 pbAttribs.push_back(WGL_TEXTURE_RECTANGLE_NV);
1782 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1783 pbAttribs.push_back(WGL_TEXTURE_CUBE_MAP_ARB);
1787 pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
1788 pbAttribs.push_back(WGL_TEXTURE_2D_ARB);
1793 pbAttribs.push_back(WGL_MIPMAP_TEXTURE_ARB);
1794 pbAttribs.push_back(true);
1796 #elif defined(__MACH__)
1797 #elif defined(DEBUG) || defined(_DEBUG)
1798 SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: Render to Texture not "
1799 "supported in Linux or MacOS");
1803 // Set the pixel type
1807 if (WGL_NV_float_buffer)
1809 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1810 pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1812 pfAttribs.push_back(WGL_FLOAT_COMPONENTS_NV);
1813 pfAttribs.push_back(true);
1817 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1818 pfAttribs.push_back(WGL_TYPE_RGBA_FLOAT_ATI);
1820 #elif defined( __MACH__ )
1821 // if (GL_MACH_float_pixels) // FIXME
1823 pfAttribs.push_back(kCGLPFAColorFloat);
1826 if (GLX_NV_float_buffer)
1828 pfAttribs.push_back(GLX_FLOAT_COMPONENTS_NV);
1829 pfAttribs.push_back(1);
1836 pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
1837 pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
1841 // Set up texture binding for render to texture
1842 if (_bIsTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
1848 if (WGL_NV_float_buffer)
1850 switch(_iNumComponents)
1853 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
1854 pfAttribs.push_back(true);
1856 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1857 pbAttribs.push_back(WGL_TEXTURE_FLOAT_R_NV);
1860 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
1861 pfAttribs.push_back(true);
1863 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1864 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RG_NV);
1867 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
1868 pfAttribs.push_back(true);
1870 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1871 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGB_NV);
1874 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
1875 pfAttribs.push_back(true);
1877 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1878 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGBA_NV);
1881 SG_LOG(SG_GL, SG_ALERT,
1882 "RenderTexture Warning: Bad number of components "
1883 "(r=1,rg=2,rgb=3,rgba=4): " <<
1890 if (4 == _iNumComponents)
1892 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1893 pfAttribs.push_back(true);
1895 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1896 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1900 // standard ARB_render_texture only supports 3 or 4 channels
1901 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1902 pfAttribs.push_back(true);
1904 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1905 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1912 switch(_iNumComponents)
1915 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1916 pfAttribs.push_back(true);
1918 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1919 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
1922 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1923 pfAttribs.push_back(true);
1925 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1926 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1929 SG_LOG(SG_GL, SG_ALERT,
1930 "RenderTexture Warning: Bad number of components "
1931 "(r=1,rg=2,rgb=3,rgba=4): " << _iNumComponents);
1935 #elif defined(__MACH__)
1939 //if (WGLEW_NV_float_buffer) // FIXME
1941 switch(_iNumComponents)
1944 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
1945 pfAttribs.push_back(true);
1947 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1948 pbAttribs.push_back(WGL_TEXTURE_FLOAT_R_NV);
1951 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
1952 pfAttribs.push_back(true);
1954 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1955 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RG_NV);
1958 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
1959 pfAttribs.push_back(true);
1961 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1962 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGB_NV);
1965 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
1966 pfAttribs.push_back(true);
1968 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1969 pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGBA_NV);
1973 "RenderTexture Warning: Bad number of components "
1974 "(r=1,rg=2,rgb=3,rgba=4): %d.\n",
1981 if (4 == _iNumComponents)
1983 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
1984 pfAttribs.push_back(true);
1986 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1987 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
1991 // standard ARB_render_texture only supports 3 or 4 channels
1992 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
1993 pfAttribs.push_back(true);
1995 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
1996 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
2004 switch(_iNumComponents)
2007 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
2008 pfAttribs.push_back(true);
2010 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2011 pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
2014 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
2015 pfAttribs.push_back(true);
2017 pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
2018 pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
2022 "RenderTexture Warning: Bad number of components "
2023 "(r=1,rg=2,rgb=3,rgba=4): %d.\n", _iNumComponents);
2028 #elif defined(DEBUG) || defined(_DEBUG)
2029 SG_LOG(SG_GL, SG_ALERT,
2030 "RenderTexture Error: Render to Texture not supported in "
2031 "Linux or MacOS\ n");
2035 if (_bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
2040 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV);
2041 pfAttribs.push_back(true);
2043 pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
2044 pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
2048 pfAttribs.push_back(WGL_BIND_TO_TEXTURE_DEPTH_NV);
2049 pfAttribs.push_back(true);
2051 pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
2052 pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
2054 #elif defined(__MACH__)
2055 #elif defined(DEBUG) || defined(_DEBUG)
2056 SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: Render to Texture not supported in "
2062 //---------------------------------------------------------------------------
2063 // Function : RenderTexture::_GetKeyValuePair
2065 //---------------------------------------------------------------------------
2067 * @fn RenderTexture::_GetKeyValuePair()
2068 * @brief Parses expressions of the form "X=Y" into a pair (X,Y).
2070 RenderTexture::KeyVal RenderTexture::_GetKeyValuePair(string token)
2072 string::size_type pos = 0;
2073 if ((pos = token.find("=")) != token.npos)
2075 string key = token.substr(0, pos);
2076 string value = token.substr(pos+1, token.length()-pos+1);
2077 return KeyVal(key, value);
2080 return KeyVal(token, "");
2083 //---------------------------------------------------------------------------
2084 // Function : RenderTexture::_ParseBitVector
2086 //---------------------------------------------------------------------------
2088 * @fn RenderTexture::_ParseBitVector()
2089 * @brief Parses expressions of the form "=r,g,b,a" into a vector: (r,g,b,a)
2091 vector<int> RenderTexture::_ParseBitVector(string bitVector)
2093 vector<string> pieces;
2096 if (bitVector == "")
2098 bits.push_back(8); // if a depth isn't specified, use default 8 bits
2102 string::size_type pos = 0;
2103 string::size_type nextpos = 0;
2106 nextpos = bitVector.find_first_of(", ", pos);
2107 pieces.push_back(string(bitVector, pos, nextpos - pos));
2109 } while (nextpos != bitVector.npos );
2111 for ( vector<string>::iterator it = pieces.begin(); it != pieces.end(); it++)
2113 bits.push_back(strtol(it->c_str(), 0, 10));
2119 //---------------------------------------------------------------------------
2120 // Function : RenderTexture::_VerifyExtensions
2122 //---------------------------------------------------------------------------
2124 * @fn RenderTexture::_VerifyExtensions()
2125 * @brief Checks that the necessary extensions are available based on RT mode.
2127 bool RenderTexture::_VerifyExtensions()
2130 // a second call to _VerifyExtensions will allways return true, causing a crash
2131 // if the extension is not supported
2132 if ( true || !fctPtrInited )
2134 fctPtrInited = true;
2135 wglGetExtensionsStringARBProc wglGetExtensionsStringARBPtr = (wglGetExtensionsStringARBProc)wglGetProcAddress( "wglGetExtensionsStringARB" );
2136 if ( wglGetExtensionsStringARBPtr == 0 )
2138 PrintExtensionError("WGL_ARB_extensions_string");
2141 string wglExtensionsString = wglGetExtensionsStringARBPtr( wglGetCurrentDC() );
2142 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pixel_format" ) )
2144 wglChoosePixelFormatARBPtr = (wglChoosePixelFormatARBProc)SGLookupFunction("wglChoosePixelFormatARB");
2145 wglGetPixelFormatAttribivARBPtr = (wglGetPixelFormatAttribivARBProc)SGLookupFunction("wglGetPixelFormatAttribivARB");
2149 PrintExtensionError("WGL_ARB_pixel_format");
2152 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_pbuffer" ) )
2154 wglCreatePbufferARBPtr = (wglCreatePbufferARBProc)SGLookupFunction("wglCreatePbufferARB");
2155 wglGetPbufferDCARBPtr = (wglGetPbufferDCARBProc)SGLookupFunction("wglGetPbufferDCARB");
2156 wglQueryPbufferARBPtr = (wglQueryPbufferARBProc)SGLookupFunction("wglQueryPbufferARB");
2157 wglReleasePbufferDCARBPtr = (wglReleasePbufferDCARBProc)SGLookupFunction("wglReleasePbufferDCARB");
2158 wglDestroyPbufferARBPtr = (wglDestroyPbufferARBProc)SGLookupFunction("wglDestroyPbufferARB");
2162 PrintExtensionError("WGL_ARB_pbuffer");
2165 if ( SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ARB_render_texture" ) )
2167 wglBindTexImageARBPtr = (wglBindTexImageARBProc)SGLookupFunction("wglBindTexImageARB");
2168 wglReleaseTexImageARBPtr = (wglReleaseTexImageARBProc)SGLookupFunction("wglReleaseTexImageARB");
2170 else if ( _bIsTexture )
2172 PrintExtensionError("WGL_ARB_render_texture");
2175 if (_bRectangle && !SGIsOpenGLExtensionSupported( "GL_NV_texture_rectangle" ))
2177 PrintExtensionError("GL_NV_texture_rectangle");
2180 if (_bFloat && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) ||
2181 SGSearchExtensionsString( wglExtensionsString.c_str(), "WGL_ATI_pixel_format_float" )))
2183 PrintExtensionError("GL_NV_float_buffer or GL_ATI_pixel_format_float");
2187 if (_bFloat && _bIsTexture && !(SGIsOpenGLExtensionSupported( "GL_NV_float_buffer" ) || SGIsOpenGLExtensionSupported( "GL_ATI_texture_float" )))
2189 PrintExtensionError("NV_float_buffer or ATI_texture_float");
2191 if (_bIsDepthTexture && !SGIsOpenGLExtensionSupported( "GL_ARB_depth_texture" ))
2194 #if defined(_DEBUG) | defined(DEBUG)
2195 SG_LOG(SG_GL, SG_ALERT,
2196 "RenderTexture Warning: "
2197 "OpenGL extension GL_ARB_depth_texture not available."
2198 " Using glReadPixels() to emulate behavior.");
2200 _bHasARBDepthTexture = false;
2201 //PrintExtensionError("GL_ARB_depth_texture");
2207 #elif defined( __MACH__ )
2208 // FIXME! Check extensions!
2210 Display* dpy = glXGetCurrentDisplay();
2211 int minor = 0, major = 0;
2212 if (!glXQueryVersion(dpy, &major, &minor))
2215 int screen = DefaultScreen(dpy);
2216 const char* extString = glXQueryExtensionsString(dpy, screen);
2217 if (!SGSearchExtensionsString(extString, "GLX_SGIX_fbconfig") ||
2218 !SGSearchExtensionsString(extString, "GLX_SGIX_pbuffer"))
2221 // First try the glX version 1.3 functions.
2222 glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfig");
2223 glXCreatePbufferPtr = (glXCreatePbufferProc)SGLookupFunction("glXCreatePbuffer");
2224 glXGetVisualFromFBConfigPtr = (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfig");
2225 glXCreateContextPtr = (glXCreateContextProc)SGLookupFunction("glXCreateContext");
2226 glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyPbuffer");
2227 glXQueryDrawablePtr = (glXQueryDrawableProc)SGLookupFunction("glXQueryDrawable");
2229 if (((1 <= major && 3 <= minor) || 2 <= major) &&
2230 glXChooseFBConfigPtr &&
2231 glXCreatePbufferPtr &&
2232 glXGetVisualFromFBConfigPtr &&
2233 glXCreateContextPtr &&
2234 glXDestroyPbufferPtr &&
2235 glXQueryDrawablePtr)
2236 glXVersion1_3Present = true;
2239 glXChooseFBConfigPtr = (glXChooseFBConfigProc)SGLookupFunction("glXChooseFBConfigSGIX");
2240 glXCreateGLXPbufferPtr = (glXCreateGLXPbufferProc)SGLookupFunction("glXCreateGLXPbufferSGIX");
2241 glXGetVisualFromFBConfigPtr = (glXGetVisualFromFBConfigProc)SGLookupFunction("glXGetVisualFromFBConfigSGIX");
2242 glXCreateContextWithConfigPtr = (glXCreateContextWithConfigProc)SGLookupFunction("glXCreateContextWithConfigSGIX");
2243 glXDestroyPbufferPtr = (glXDestroyPbufferProc)SGLookupFunction("glXDestroyGLXPbufferSGIX");
2244 glXQueryGLXPbufferSGIXPtr = (glXQueryGLXPbufferSGIXProc)SGLookupFunction("glXQueryGLXPbufferSGIX");
2247 if (!glXChooseFBConfigPtr ||
2248 !glXCreateGLXPbufferPtr ||
2249 !glXGetVisualFromFBConfigPtr ||
2250 !glXCreateContextWithConfigPtr ||
2251 !glXDestroyPbufferPtr ||
2252 !glXQueryGLXPbufferSGIXPtr)
2256 if (_bIsDepthTexture && !GL_ARB_depth_texture)
2258 PrintExtensionError("GL_ARB_depth_texture");
2261 if (_bFloat && _bIsTexture && !GLX_NV_float_buffer)
2263 PrintExtensionError("GLX_NV_float_buffer");
2266 if (_eUpdateMode == RT_RENDER_TO_TEXTURE)
2268 PrintExtensionError("Some GLX render texture extension: Please implement me!");
2276 //---------------------------------------------------------------------------
2277 // Function : RenderTexture::_InitializeTextures
2279 //---------------------------------------------------------------------------
2281 * @fn RenderTexture::_InitializeTextures()
2282 * @brief Initializes the state of textures used by the RenderTexture.
2284 bool RenderTexture::_InitializeTextures()
2286 // Determine the appropriate texture formats and filtering modes.
2287 if (_bIsTexture || _bIsDepthTexture)
2289 if (_bRectangle && GL_NV_texture_rectangle)
2290 _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
2291 else if (_bRectangle && GL_EXT_texture_rectangle)
2292 _iTextureTarget = GL_TEXTURE_RECTANGLE_EXT;
2294 _iTextureTarget = GL_TEXTURE_2D;
2299 glGenTextures(1, (GLuint*)&_iTextureID);
2300 glBindTexture(_iTextureTarget, _iTextureID);
2302 // Use clamp to edge as the default texture wrap mode for all tex
2303 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2304 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2305 // Use NEAREST as the default texture filtering mode.
2306 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2307 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2310 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2312 GLuint iInternalFormat;
2319 SG_LOG(SG_GL, SG_ALERT,
2320 "RenderTexture Error: mipmapped float textures not "
2325 switch(_iNumComponents)
2328 if (GL_NV_float_buffer)
2330 iInternalFormat = (_iNumColorBits[0] > 16) ?
2331 GL_FLOAT_R32_NV : GL_FLOAT_R16_NV;
2333 else if (GL_ATI_texture_float)
2335 iInternalFormat = (_iNumColorBits[0] > 16) ?
2336 GL_LUMINANCE_FLOAT32_ATI :
2337 GL_LUMINANCE_FLOAT16_ATI;
2339 iFormat = GL_LUMINANCE;
2342 if (GL_NV_float_buffer)
2344 iInternalFormat = (_iNumColorBits[0] > 16) ?
2345 GL_FLOAT_RG32_NV : GL_FLOAT_RG16_NV;
2347 else if (GL_ATI_texture_float)
2349 iInternalFormat = (_iNumColorBits[0] > 16) ?
2350 GL_LUMINANCE_ALPHA_FLOAT32_ATI :
2351 GL_LUMINANCE_ALPHA_FLOAT16_ATI;
2353 iFormat = GL_LUMINANCE_ALPHA;
2356 if (GL_NV_float_buffer)
2358 iInternalFormat = (_iNumColorBits[0] > 16) ?
2359 GL_FLOAT_RGB32_NV : GL_FLOAT_RGB16_NV;
2361 else if (GL_ATI_texture_float)
2363 iInternalFormat = (_iNumColorBits[0] > 16) ?
2364 GL_RGB_FLOAT32_ATI : GL_RGB_FLOAT16_ATI;
2369 if (GL_NV_float_buffer)
2371 iInternalFormat = (_iNumColorBits[0] > 16) ?
2372 GL_FLOAT_RGBA32_NV : GL_FLOAT_RGBA16_NV;
2374 else if (GL_ATI_texture_float)
2376 iInternalFormat = (_iNumColorBits[0] > 16) ?
2377 GL_RGBA_FLOAT32_ATI : GL_RGBA_FLOAT16_ATI;
2382 SG_LOG(SG_GL, SG_INFO, "RenderTexture Error: "
2383 "Invalid number of components: " <<
2390 if (4 == _iNumComponents)
2392 iInternalFormat = GL_RGBA8;
2397 iInternalFormat = GL_RGB8;
2402 // Allocate the texture image (but pass it no data for now).
2403 glTexImage2D(_iTextureTarget, 0, iInternalFormat,
2404 _iWidth, _iHeight, 0, iFormat, GL_FLOAT, NULL);
2408 if (_bIsDepthTexture)
2410 glGenTextures(1, (GLuint*)&_iDepthTextureID);
2411 glBindTexture(_iTextureTarget, _iDepthTextureID);
2413 // Use clamp to edge as the default texture wrap mode for all tex
2414 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2415 glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2416 // Use NEAREST as the default texture filtering mode.
2417 glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2418 glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2420 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2423 if (_bHasARBDepthTexture)
2425 // Allocate the texture image (but pass it no data for now).
2426 glTexImage2D(_iTextureTarget, 0, GL_DEPTH_COMPONENT,
2427 _iWidth, _iHeight, 0, GL_DEPTH_COMPONENT,
2432 // allocate memory for depth texture
2433 // Since this is slow, we warn the user in debug mode. (above)
2434 _pPoorDepthTexture = new unsigned short[_iWidth * _iHeight];
2435 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
2436 _iWidth, _iHeight, 0, GL_LUMINANCE,
2437 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2447 //---------------------------------------------------------------------------
2448 // Function : RenderTexture::_MaybeCopyBuffer
2450 //---------------------------------------------------------------------------
2452 * @fn RenderTexture::_MaybeCopyBuffer()
2453 * @brief Does the actual copying for RenderTextures with RT_COPY_TO_TEXTURE
2455 void RenderTexture::_MaybeCopyBuffer()
2458 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2462 glBindTexture(_iTextureTarget, _iTextureID);
2463 glCopyTexSubImage2D(_iTextureTarget,
2464 0, 0, 0, 0, 0, _iWidth, _iHeight);
2466 if (_bIsDepthTexture)
2468 glBindTexture(_iTextureTarget, _iDepthTextureID);
2469 // HOW TO COPY DEPTH TEXTURE??? Supposedly this just magically works...
2471 if (_bHasARBDepthTexture)
2473 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0,
2478 // no 'real' depth texture available, so behavior has to be emulated
2479 // using glReadPixels (beware, this is (naturally) slow ...)
2480 glReadPixels(0, 0, _iWidth, _iHeight, GL_DEPTH_COMPONENT,
2481 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2482 glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
2483 _iWidth, _iHeight, 0, GL_LUMINANCE,
2484 GL_UNSIGNED_SHORT, _pPoorDepthTexture);
2490 #elif defined(__MACH__)
2491 if (RT_COPY_TO_TEXTURE == _eUpdateMode)
2495 glBindTexture(_iTextureTarget, _iTextureID);
2496 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2498 if (_bIsDepthTexture)
2500 glBindTexture(_iTextureTarget, _iDepthTextureID);
2501 assert(_bHasARBDepthTexture);
2502 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2508 glBindTexture(_iTextureTarget, _iTextureID);
2509 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2511 if (_bIsDepthTexture)
2513 glBindTexture(_iTextureTarget, _iDepthTextureID);
2514 assert(_bHasARBDepthTexture);
2515 glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
2521 //---------------------------------------------------------------------------
2522 // Function : RenderTexture::_ReleaseBoundBuffers
2524 //---------------------------------------------------------------------------
2526 * @fn RenderTexture::_ReleaseBoundBuffers()
2527 * @brief Releases buffer bindings on RenderTextures with RT_RENDER_TO_TEXTURE
2529 bool RenderTexture::_ReleaseBoundBuffers()
2532 if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2534 glBindTexture(_iTextureTarget, _iTextureID);
2536 // release the pbuffer from the render texture object
2537 if (0 != _iCurrentBoundBuffer && _bIsBufferBound)
2539 if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, _iCurrentBoundBuffer))
2544 _bIsBufferBound = false;
2548 if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
2550 glBindTexture(_iTextureTarget, _iDepthTextureID);
2552 // release the pbuffer from the render texture object
2553 if (FALSE == wglReleaseTexImageARBPtr(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
2561 // textures can't be bound in Linux
2566 //---------------------------------------------------------------------------
2567 // Function : RenderTexture::_MakeCurrent
2569 //---------------------------------------------------------------------------
2571 * @fn RenderTexture::_MakeCurrent()
2572 * @brief Makes the RenderTexture's context current
2575 bool RenderTexture::_MakeCurrent()
2578 // make the pbuffer's rendering context current.
2579 if (FALSE == wglMakeCurrent( _hDC, _hGLContext))
2584 #elif defined( __MACH__ )
2587 if (err = CGLSetCurrentContext(_hGLContext))
2589 _cglCheckError(err);
2593 if (false == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
2602 /////////////////////////////////////////////////////////////////////////////
2604 // Begin Deprecated Interface
2606 /////////////////////////////////////////////////////////////////////////////
2608 //---------------------------------------------------------------------------
2609 // Function : RenderTexture::RenderTexture
2611 //---------------------------------------------------------------------------
2613 * @fn RenderTexture::RenderTexture()
2614 * @brief Constructor.
2616 RenderTexture::RenderTexture(int width, int height,
2617 bool bIsTexture /* = true */,
2618 bool bIsDepthTexture /* = false */)
2621 _bIsTexture(bIsTexture),
2622 _bIsDepthTexture(bIsDepthTexture),
2623 _bHasARBDepthTexture(true), // [Redge]
2624 _eUpdateMode(RT_RENDER_TO_TEXTURE),
2625 _bInitialized(false),
2627 _iCurrentBoundBuffer(0),
2629 _iNumStencilBits(0),
2631 _bDoubleBuffered(false),
2635 _bShareObjects(false),
2636 _bCopyContext(false),
2642 _hPreviousContext(0),
2643 #elif defined( __MACH__ )
2646 _hPreviousContext(NULL),
2651 _hPreviousDrawable(0),
2652 _hPreviousContext(0),
2654 _iTextureTarget(GL_NONE),
2656 _iDepthTextureID(0),
2657 _pPoorDepthTexture(0) // [Redge]
2659 assert(width > 0 && height > 0);
2660 #if defined DEBUG || defined _DEBUG
2661 SG_LOG(SG_GL, SG_ALERT,
2662 "RenderTexture Warning: Deprecated Contructor interface used.");
2665 _iNumColorBits[0] = _iNumColorBits[1] =
2666 _iNumColorBits[2] = _iNumColorBits[3] = 0;
2667 _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
2670 //------------------------------------------------------------------------------
2671 // Function : RenderTexture::Initialize
2673 //------------------------------------------------------------------------------
2675 * @fn RenderTexture::Initialize(bool bShare, bool bDepth, bool bStencil, bool bMipmap, unsigned int iRBits, unsigned int iGBits, unsigned int iBBits, unsigned int iABits);
2676 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
2678 * This function actually does the creation of the p-buffer. It can only be called
2679 * once a GL context has already been created. Note that if the texture is not
2680 * power of two dimensioned, or has more than 8 bits per channel, enabling mipmapping
2681 * will cause an error.
2683 bool RenderTexture::Initialize(bool bShare /* = true */,
2684 bool bDepth /* = false */,
2685 bool bStencil /* = false */,
2686 bool bMipmap /* = false */,
2687 bool bAnisoFilter /* = false */,
2688 unsigned int iRBits /* = 8 */,
2689 unsigned int iGBits /* = 8 */,
2690 unsigned int iBBits /* = 8 */,
2691 unsigned int iABits /* = 8 */,
2692 UpdateMode updateMode /* = RT_RENDER_TO_TEXTURE */)
2694 if (0 == _iWidth || 0 == _iHeight)
2697 #if defined DEBUG || defined _DEBUG
2698 SG_LOG(SG_GL, SG_ALERT,
2699 "RenderTexture Warning: Deprecated Initialize() interface used.");
2702 // create a mode string.
2705 mode.append("depth ");
2707 mode.append("stencil ");
2709 mode.append("mipmap ");
2710 if (iRBits + iGBits + iBBits + iABits > 0)
2721 char bitVector[100];
2722 snprintf( bitVector, 100,
2723 "%d%s,%d%s,%d%s,%d%s",
2724 iRBits, (iRBits >= 16) ? "f" : "",
2725 iGBits, (iGBits >= 16) ? "f" : "",
2726 iBBits, (iBBits >= 16) ? "f" : "",
2727 iABits, (iABits >= 16) ? "f" : "");
2728 mode.append(bitVector);
2733 if ((GL_NV_texture_rectangle || GL_EXT_texture_rectangle) &&
2734 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2735 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2736 mode.append("texRECT ");
2738 mode.append("tex2D ");
2740 if (_bIsDepthTexture)
2742 if ((GL_NV_texture_rectangle || GL_EXT_texture_rectangle) &&
2743 ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
2744 || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
2745 mode.append("texRECT ");
2747 mode.append("tex2D ");
2749 if (RT_COPY_TO_TEXTURE == updateMode)
2752 _pixelFormatAttribs.clear();
2753 _pbufferAttribs.clear();
2756 _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
2757 _pixelFormatAttribs.push_back(true);
2758 _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
2759 _pixelFormatAttribs.push_back(true);
2761 _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
2762 _pbufferAttribs.push_back(true);
2763 #elif defined( __MACH__ )
2764 //_pixelFormatAttribs.push_back(kCGLPFANoRecovery);
2765 _pixelFormatAttribs.push_back(kCGLPFAAccelerated);
2766 _pixelFormatAttribs.push_back(kCGLPFAWindow);
2767 _pixelFormatAttribs.push_back(kCGLPFAPBuffer);
2769 _pixelFormatAttribs.push_back(GLX_RENDER_TYPE_SGIX);
2770 _pixelFormatAttribs.push_back(GLX_RGBA_BIT_SGIX);
2771 _pixelFormatAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
2772 _pixelFormatAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
2775 _ParseModeString(mode.c_str(), _pixelFormatAttribs, _pbufferAttribs);
2778 _pixelFormatAttribs.push_back(0);
2779 _pbufferAttribs.push_back(0);
2780 #elif defined(__MACH__)
2781 _pixelFormatAttribs.push_back(0);
2783 _pixelFormatAttribs.push_back(None);
2786 Initialize(_iWidth, _iHeight, bShare);
2792 //---------------------------------------------------------------------------
2793 // Function : RenderTexture::Reset
2795 //---------------------------------------------------------------------------
2797 * @fn RenderTexture::Reset(int iWidth, int iHeight, unsigned int iMode, bool bIsTexture, bool bIsDepthTexture)
2798 * @brief Resets the resolution of the offscreen buffer.
2800 * Causes the buffer to delete itself. User must call Initialize() again
2803 bool RenderTexture::Reset(int iWidth, int iHeight)
2805 SG_LOG(SG_GL, SG_ALERT,
2806 "RenderTexture Warning: Deprecated Reset() interface used.");
2810 SG_LOG(SG_GL, SG_ALERT, "RenderTexture::Reset(): failed to invalidate.");