/// <summary>
/// Detect allowed FBO formats
/// </summary>
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)
{
this._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 && this._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 && !this._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)
{
this._props[x].Valid = true;
var str = new StringBuilder();
str.AppendFormat("\tFBO {0} depth/stencil support: ", PixelUtil.GetFormatName((PixelFormat)x));
// For each depth/stencil formats
for (int depth = 0; depth < this._depthFormats.GetLength(0); ++depth)
{
if (this._depthFormats[depth] != GL_DEPTH24_STENCIL8_EXT)
{
// General depth/stencil combination
for (int stencil = 0; stencil < this._stencilFormats.GetLength(0); ++stencil)
{
//LogManager.Instance.Write( "Trying {0} D{1}S{2} ", PixelUtil.GetFormatName( (PixelFormat)x ), _depthBits[ depth ], _stencilBits[ stencil ] );
if (_tryFormat(this._depthFormats[depth], this._stencilFormats[stencil]))
{
/// Add mode to allowed modes
str.AppendFormat("D{0}S{1} ", this._depthBits[depth], this._stencilBits[stencil]);
FormatProperties.Mode mode;
mode.Depth = depth;
mode.Stencil = stencil;
this._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(this._depthFormats[depth]))
{
/// Add mode to allowed modes
str.AppendFormat("Packed-D{0}S8 ", this._depthBits[depth]);
FormatProperties.Mode mode;
mode.Depth = depth;
mode.Stencil = 0; // unuse
this._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 (this._props[x].Valid)
{
fmtstring += PixelUtil.GetFormatName((PixelFormat)x) + " ";
}
}
LogManager.Instance.Write("[GL] : Valid FBO targets " + fmtstring);
}