private void _detectFBOFormats()
{
// Try all formats, and report which ones work as target
int fb, tid;
int old_drawbuffer, old_readbuffer;
int target = Gl.GL_TEXTURE_2D;
Gl.glGetIntegerv( Gl.GL_DRAW_BUFFER, out old_drawbuffer );
Gl.glGetIntegerv( Gl.GL_READ_BUFFER, out old_readbuffer );
for ( int x = 0; x < (int)PixelFormat.Count; ++x )
{
_props[ x ].Valid = false;
// Fetch GL format token
int fmt = GLPixelUtil.GetGLInternalFormat( (PixelFormat)x );
if ( fmt == Gl.GL_NONE && x != 0 )
continue;
// No test for compressed formats
if ( PixelUtil.IsCompressed( (PixelFormat)x ) )
continue;
// Buggy ATI cards *crash* on non-RGB(A) formats
int[] depths = PixelUtil.GetBitDepths( (PixelFormat)x );
if ( fmt != Gl.GL_NONE && _atiMode && ( depths[ 0 ] == 0 || depths[ 1 ] == 0 || depths[ 2 ] == 0 ) )
continue;
// Buggy NVidia Drivers fail on 32Bit FP formats on Windows.
if ( PixelUtil.IsFloatingPoint( (PixelFormat)x ) && PlatformManager.IsWindowsOS && !_atiMode )
continue;
// Create and attach framebuffer
Gl.glGenFramebuffersEXT( 1, out fb );
Gl.glBindFramebufferEXT( Gl.GL_FRAMEBUFFER_EXT, fb );
if ( fmt != Gl.GL_NONE )
{
// Create and attach texture
Gl.glGenTextures( 1, out tid );
Gl.glBindTexture( target, tid );
// Set some default parameters so it won't fail on NVidia cards
Gl.glTexParameteri( target, Gl.GL_TEXTURE_MAX_LEVEL, 0 );
Gl.glTexParameteri( target, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_NEAREST );
Gl.glTexParameteri( target, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_NEAREST );
Gl.glTexParameteri( target, Gl.GL_TEXTURE_WRAP_S, Gl.GL_CLAMP_TO_EDGE );
Gl.glTexParameteri( target, Gl.GL_TEXTURE_WRAP_T, Gl.GL_CLAMP_TO_EDGE );
Gl.glTexImage2D( target, 0, fmt, PROBE_SIZE, PROBE_SIZE, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, IntPtr.Zero );
Gl.glFramebufferTexture2DEXT( Gl.GL_FRAMEBUFFER_EXT, Gl.GL_COLOR_ATTACHMENT0_EXT, target, tid, 0 );
}
else
{
// Draw to nowhere -- stencil/depth only
tid = 0;
Gl.glDrawBuffer( Gl.GL_NONE );
Gl.glReadBuffer( Gl.GL_NONE );
}
// Check status
int status = Gl.glCheckFramebufferStatusEXT( Gl.GL_FRAMEBUFFER_EXT );
// Ignore status in case of fmt==GL_NONE, because no implementation will accept
// a buffer without *any* attachment. Buffers with only stencil and depth attachment
// might still be supported, so we must continue probing.
if ( fmt == Gl.GL_NONE || status == Gl.GL_FRAMEBUFFER_COMPLETE_EXT )
{
_props[ x ].Valid = true;
StringBuilder str = new StringBuilder();
str.AppendFormat( "\tFBO {0} depth/stencil support: ", PixelUtil.GetFormatName( (PixelFormat)x ) );
// For each depth/stencil formats
for ( int depth = 0; depth < _depthFormats.GetLength( 0 ); ++depth )
{
if ( _depthFormats[ depth ] != GL_DEPTH24_STENCIL8_EXT )
{
// General depth/stencil combination
for ( int stencil = 0; stencil < _stencilFormats.GetLength( 0 ); ++stencil )
{
//LogManager.Instance.Write( "Trying {0} D{1}S{2} ", PixelUtil.GetFormatName( (PixelFormat)x ), _depthBits[ depth ], _stencilBits[ stencil ] );
if ( _tryFormat( _depthFormats[ depth ], _stencilFormats[ stencil ] ) )
{
/// Add mode to allowed modes
str.AppendFormat( "D{0}S{1} ", _depthBits[ depth ], _stencilBits[ stencil ] );
FormatProperties.Mode mode;
mode.Depth = depth;
mode.Stencil = stencil;
_props[ x ].Modes.Add( mode );
}
}
}
else
{
// Packed depth/stencil format
#if false
// Only query packed depth/stencil formats for 32-bit
// non-floating point formats (ie not R32!)
// Linux nVidia driver segfaults if you query others
if ( !PlatformManager.IsWindowsOS &&
( PixelUtil.GetNumElemBits( (PixelFormat)x ) != 32 ||
PixelUtil.IsFloatingPoint( (PixelFormat)x ) ) )
{
continue;
}
#endif
if ( _tryPackedFormat( _depthFormats[ depth ] ) )
{
/// Add mode to allowed modes
str.AppendFormat( "Packed-D{0}S8 ", _depthBits[ depth ] );
FormatProperties.Mode mode;
mode.Depth = depth;
mode.Stencil = 0; // unuse
_props[ x ].Modes.Add( mode );
}
}
}
LogManager.Instance.Write( str.ToString() );
}
// Delete texture and framebuffer
Gl.glBindFramebufferEXT( Gl.GL_FRAMEBUFFER_EXT, 0 );
Gl.glDeleteFramebuffersEXT( 1, ref fb );
// Workaround for NVIDIA / Linux 169.21 driver problem
// see http://www.ogre3d.org/phpBB2/viewtopic.php?t=38037&start=25
Gl.glFinish();
Gl.glDeleteTextures( 1, ref tid );
}
// It seems a bug in nVidia driver: glBindFramebufferEXT should restore
// draw and read buffers, but in some unclear circumstances it won't.
Gl.glDrawBuffer( old_drawbuffer );
Gl.glReadBuffer( old_readbuffer );
string fmtstring = "";
for ( int x = 0; x < (int)PixelFormat.Count; ++x )
{
if ( _props[ x ].Valid )
fmtstring += PixelUtil.GetFormatName( (PixelFormat)x ) + " ";
}
LogManager.Instance.Write( "[GL] : Valid FBO targets " + fmtstring );
}