PDA

View Full Version : FBOs and GL_COLOR_BUFFER_BIT



skynet
02-02-2010, 04:44 AM
Hi,
I need some confirmation on this code:


glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

glPushAttrib(GL_COLOR_BUFFER_BIT);
glClearColor(0.0f,0.0f,0.0f,0.0f);

glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo);
glClear(GL_COLOR_BUFFER_BIT);

glPopAttrib();

GLenum err=glGetError();
if (err!=GL_NO_ERROR)
{
cout<<"a GL Error occurred in glPopAttrib()"<<endl;
}

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);


When doing it this way, I get GL_INVALID_OPERATION after glPopAttrib(). It seems as if the driver wants to 'call' glDrawBuffer(GL_BACK)on my own FBO. In 2007 I stumbled across the very same problem, but back then it resulted in a driver crash :-) By reordering the operations one can circumvent it.
I get GL_INVALID_OPERATION on both, nVidia and ATI.

My question is now, where in the specs is this behaviour covered? EXT_fbo is very vague about it, neither ARB_fbo nor GL3.0 specs seem to mention it explicitly.

Alfonse Reinheart
02-02-2010, 10:57 AM
neither ARB_fbo nor GL3.0 specs seem to mention it explicitly.

That's what "deprecated" means. It may not interact well with non-deprecated functionality.

You should not put an FBO bind in a push/pop like that. Not unless you manually restore the object's state yourself. Do this instead:



glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo);

glPushAttrib(GL_COLOR_BUFFER_BIT);
glClearColor(0.0f,0.0f,0.0f,0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glPopAttrib();

skynet
02-02-2010, 02:52 PM
Deprecated means to me "it may go away in future", not "it is still present but doesn't work anymore". In a standard, non-forward-compatible context glPushAttrib/glPopAttrib are still supposed to work.

Anyway, I'm using a 2.1 context and EXT_fbo. Deprecation should not affect this scenario.

But you are right, GL3.1 and 3.2 already created some "holes" in many extensions. Like, what can I expect when requesting a core 3.2 context and ARB_vertex_program is still in the extension list? I can guess that I should/can not use any built in state variables anymore, but there are no official specs that tell me for sure.

Alfonse Reinheart
02-02-2010, 02:59 PM
Anyway, I'm using a 2.1 context and EXT_fbo. Deprecation should not affect this scenario.

glPushAttrib, until now, has never pushed state that was actually part of an object before. Remember: objects are defined in terms of the state they encapsulate. And glPush/PopAttrib are likewise defined in terms of the state that they save/restore.

So performing a glPopAttrib means making the equivalent OpenGL calls that would set the state to the values saved by the corresponding glPushAttrib.

However, by binding an FBO, you have changed what are the allowable state values that a certain state can hold. This is fairly unprecedented for OpenGL (nothing else in GL causes state to hold different values like this).

Therefore, when you pushed the state, it acted like you called glDrawBuffer with a value that was acceptable for having the default framebuffer active. When you pushed an FBO, that changed the allowable state. But since glDrawBuffer(s) state is part of the FBO, that's fine. The problem comes when you pop the state. The pop function will set the state exactly as it was when you pushed.

Bottom line: don't push/pop state that is part of OpenGL Objects.

skynet
02-02-2010, 03:19 PM
Yes, I realized what went wrong... Its just, I was kind of unprepared and tried to find out where this behaviour is described in the specs. EXT_fbo discussed this problem in Issue 81; the solution has been deferred. But ARB_fbo seems to give no definite answer, too.

don't push/pop state that is part of OpenGL Objects
I absolutely avoided GL_TEXTURE_BIT for the very reason :-) But until now I really liked GL_COLOR_BUFFER_BIT because it stores writemasks, blend settings and the like.