I was surprised to find that I was able to make a self-contained example without too much effort.
First, here’s the setup for the main OpenGL context:
static int ChooseWindowPixelFormat()
{
PIXELFORMATDESCRIPTOR pixelFormatDesc;
std::memset( &pixelFormatDesc, 0, sizeof(pixelFormatDesc) );
pixelFormatDesc.nSize = sizeof(pixelFormatDesc);
pixelFormatDesc.nVersion = 1;
pixelFormatDesc.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;
pixelFormatDesc.cColorBits = 0;
pixelFormatDesc.cDepthBits = 24;
pixelFormatDesc.cStencilBits = 8;
pixelFormatDesc.iPixelType = PFD_TYPE_RGBA;
int pixelFormat = ChoosePixelFormat( gDC, &pixelFormatDesc );
SetPixelFormat( gDC, pixelFormat, &pixelFormatDesc );
return pixelFormat;
}
void InitOpenGLWindowContext()
{
RECT windowRect;
GetClientRect( gWindow, &windowRect );
gWindowWidth = windowRect.right - windowRect.left;
gWindowHeight = windowRect.bottom - windowRect.top;
int pixelFormat = ChooseWindowPixelFormat();
if (pixelFormat == 0)
{
OutputDebugString("Failed to get pixel format");
throw std::exception();
}
PIXELFORMATDESCRIPTOR pixelFormatDesc;
DescribePixelFormat( gDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pixelFormatDesc );
glContext = wglCreateContext( gDC );
wglMakeCurrent( gDC, glContext );
glBindFrameBuffer = (glBindFramebufferEXTProcPtr) wglGetProcAddress( "glBindFramebufferEXT" );
if (glBindFrameBuffer == NULL)
{
OutputDebugString("No FBO support here");
}
else
{
OutputDebugString("FBO supported here");
InitFBO();
}
glViewport( 0, 0, gWindowWidth, gWindowHeight );
}
Next, we have the initialization of the FBO, which is called from within the main initialization function above. I have lots of glGetError tests here, none of which detected any error.
static void CheckOpenGLError()
{
GLenum theError = glGetError();
if (theError != GL_NO_ERROR)
{
char msg[300];
std::sprintf( msg, "OpenGL error %d", theError );
OutputDebugString(msg);
}
}
template <typename T>
inline void GLGetProcAddress( T& outFuncPtr, const char* inName1 )
{
outFuncPtr = (T) wglGetProcAddress( inName1 );
}
void InitFBO()
{
// Get FBO function pointers
GLGetProcAddress( glGenFramebuffersEXT, "glGenFramebuffersEXT" );
GLGetProcAddress( glDeleteFramebuffersEXT, "glDeleteFramebuffersEXT" );
GLGetProcAddress( glGenRenderbuffersEXT, "glGenRenderbuffersEXT" );
GLGetProcAddress( glDeleteRenderbuffersEXT, "glDeleteRenderbuffersEXT" );
GLGetProcAddress( glBindRenderbufferEXT, "glBindRenderbufferEXT" );
GLGetProcAddress( glRenderbufferStorageEXT, "glRenderbufferStorageEXT" );
GLGetProcAddress( glFramebufferRenderbufferEXT, "glFramebufferRenderbufferEXT" );
GLGetProcAddress( glCheckFramebufferStatusEXT, "glCheckFramebufferStatusEXT" );
GLGetProcAddress( glFramebufferTexture2DEXT, "glFramebufferTexture2DEXT" );
// Create and bind a framebuffer object
glGenFramebuffersEXT( 1, &glFrameBufferID );
CheckOpenGLError();
glBindFrameBuffer( GL_FRAMEBUFFER_EXT, glFrameBufferID );
CheckOpenGLError();
// Create color renderbuffer
glGenRenderbuffersEXT( 1, &glColorRenderBufferID );
CheckOpenGLError();
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT,
glColorRenderBufferID );
CheckOpenGLError();
glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_RGB,
kFBO_width, kFBO_height );
CheckOpenGLError();
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT,
glColorRenderBufferID );
CheckOpenGLError();
// Create a depth buffer...
glGenRenderbuffersEXT( 1, &glDepthRenderBufferID );
CheckOpenGLError();
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT,
glDepthRenderBufferID );
CheckOpenGLError();
// Make a packed depth-stencil buffer
glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT,
GL_DEPTH24_STENCIL8_EXT, kFBO_width, kFBO_height );
CheckOpenGLError();
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT,
glDepthRenderBufferID );
CheckOpenGLError();
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT,
GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT,
glDepthRenderBufferID );
CheckOpenGLError();
// Check whether FBO is OK
GLenum result = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );
if (result == GL_FRAMEBUFFER_COMPLETE_EXT)
{
// Set the viewport
glViewport( 0, 0, kFBO_width, kFBO_height );
}
else
{
OutputDebugString("FBO failed status check");
glBindFrameBuffer( GL_FRAMEBUFFER_EXT, 0 );
glBindFrameBuffer = NULL;
}
}
Finally, the FBO rendering function. There is an access violation in the video driver after 9000000 calls to glIsEnabled.
void RenderFBO()
{
OutputDebugString("RenderFBO 1");
// Make the FBO the current context
wglMakeCurrent( gDC, glContext );
glBindFrameBuffer( GL_FRAMEBUFFER_EXT, glFrameBufferID );
CheckOpenGLError();
OutputDebugString("RenderFBO 2");
int count = 1;
while (count)
{
glIsEnabled( GL_LIGHT6 );
++count;
if ((count % 100000) == 0)
{
char msg[300];
std::sprintf( msg, "RenderFBO %d iterations", count );
OutputDebugString(msg);
}
}
OutputDebugString("RenderFBO end");
}