Invalid Operation - glDrawBuffer/glPopAttrib

Hi,

I’m interfacing my glsl shader library with a 3rd party scenegraph in an app at work. I have source for the 3rd party app but want to keep code changes as minimal as possible.

This scenegraph makes available routines which I can use to set up my shader stuff (select which program to run, set up uniform variables, bind textures etc) before the geometry is actually rendered.

This works great for simple shaders (in general - I’ve had to find a few workarounds) but now I’m rendering to fbo in a multipass shader.
This means I need to be able to call glDrawBuffers in my shader setup code (works fine), render the geometry into my fbo (works fine) and then set the drawbuffer back to whatever it was set to before I started doing my thing.

However, whether I use glPushAttrib(GL_COLOR_BUFFER_BIT) + glPopAttrib or manually query the current drawbuffer and reset it, I’m getting an Invalid Operation error when I try to Pop or call glDrawBufferss
As far as I know, this should only happen if I’m trying to do either inside a glBegin/End pair. Which as far as I can see, I’m not.

I’d appreciate you guys taking a look at the output of a trace and letting me know if I’ve missed anything.
There’s a load of stuff going on before this output but I think this is a reasonable place to start:

glGetIntegerv(GL_CURRENT_PROGRAM, 0x15E9680)
glUseProgram(1) [Context 2 - program 1: shader 2, shader 3]
glUniform1f(4, 0.15000001)
glGetError()
glGetIntegerv(GL_CURRENT_PROGRAM, 0x15E9680)
glUniform4f(0, 160, 165, 170, 175)
glGetError()
glGetIntegerv(GL_CURRENT_PROGRAM, 0x15E9680)
glGetError()
glGetIntegerv(GL_CURRENT_PROGRAM, 0x15E9680)
glGetError()
glGetError()
glActiveTexture(GL_TEXTURE0)
glGetError()
glBindTexture(GL_TEXTURE_2D, 1) [Context 2 - Texture 1: Context 2 - Texture 1]
glGetError()
glGetUniformLocation(1, rendertarget) [Context 2 - program 1: shader 2, shader 3]
glGetError()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 957, 965, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0x0) [Context 2 - Texture 1: Context 2 - Texture 1]
glGetError()
glGetIntegerv(GL_CURRENT_PROGRAM, 0x15E9680)
glUniformMatrix4fv(3, 1, FALSE, {-0.99601507, 0, -0, 0} {0, 0.992046, -0.089185514, 0} {-0, 0.088830113, 0.99601507, 0} {0, -5.1806593, -170.21442, 1})
glGetError()
glGetIntegerv(GL_CURRENT_PROGRAM, 0x15E9680)
glUniformMatrix4fv(1, 1, FALSE, {-0.083333336, 0, 0, 0} {0, 0.082638882, 0, 0} {0, 0, -0.016003657, -0.016003657} {0, 0, -1.8999817, 0})
glGetError()
glGetIntegerv(GL_CURRENT_PROGRAM, 0x15E9680)
glUniform3f(2, 0, -10, 170)
glGetError()
[b]glPushAttrib(0x4000)[/b]
glUseProgram(1) [Context 2 - program 1: shader 2, shader 3]
glGetIntegerv(GL_CURRENT_PROGRAM, 0x15E9684)
glUniformMatrix4fv(1, 1, FALSE, {-0.083333336, 0, 0, 0} {0, 0.082638882, 0, 0} {0, 0, -0.016003657, -0.016003657} {0, 0, -1.8999817, 0})
glGetError()
glGetIntegerv(GL_CURRENT_PROGRAM, 0x15E9684)
glUniformMatrix4fv(3, 1, FALSE, {-0.99601507, 0, -0, 0} {0, 0.992046, -0.089185514, 0} {-0, 0.088830113, 0.99601507, 0} {0, -5.1806593, -170.21442, 1})
glGetError()
glGetIntegerv(GL_CURRENT_PROGRAM, 0x15E9684)
glUniform3f(2, 0, -10, 170)
glGetError()
glGetIntegerv(GL_CURRENT_PROGRAM, 0x15E9684)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 1)
glGetError()
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 1, 0)
glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
glGetError()
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT)
glGetError()
glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
glUniform1i(-1, 0)
glGetError()
glGetIntegerv(GL_CURRENT_PROGRAM, 0x15E9684)
glUniform4f(0, 160, 165, 170, 175)
glGetError()
glGetIntegerv(GL_CURRENT_PROGRAM, 0x15E9684)
glUniform1f(4, 0.15000001)
glGetError()
glEnable(GL_BLEND)
glBlendFunc(1, 1)
glUseProgramObjectARB(1) [Context 2 - program 1: shader 2, shader 3]
glMatrixMode(GL_PROJECTION)
glLoadMatrixf({-0.083333336, 0, 0, 0} {0, 0.082638882, 0, 0} {0, 0, -0.016003657, -0.016003657} {0, 0, -1.8999817, 0})
glMatrixMode(GL_MODELVIEW)
glLoadMatrixf({-1, 0, -0, 0} {0, 1, -0, 0} {0, 0, 1, 0} {-0, -4.9983401, -64.985718, 1})
glViewport(2, 2, 953, 961)
glEnable(GL_MULTISAMPLE)
glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glTranslatef(0, 0, -0.049988572)
glMatrixMode(GL_MODELVIEW)
glDepthRange(0, 1)
glDisable(GL_LIGHTING)
glDisable(GL_LIGHT0)
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, {0, 0, -1})
glLightfv(GL_LIGHT0, GL_POSITION, {0, 0, 1, 0})
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 0)
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 180)
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, {0})
glLightfv(GL_LIGHT0, GL_AMBIENT, {0, 0, 0, 1})
glLightfv(GL_LIGHT0, GL_DIFFUSE, {1, 1, 1, 1})
glLightfv(GL_LIGHT0, GL_SPECULAR, {1, 1, 1, 1})
glLightfv(GL_LIGHT0, GL_POSITION, {0, 4.9983401, 64.985718, 1})
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 100)
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 180)
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, {0, 0, -1})
glEnable(GL_LIGHT0)
glEnable(GL_LIGHTING)
glEnable(GL_COLOR_MATERIAL)
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, {1, 1, 1, 1})
glColor3f(1, 1, 1)
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, {0, 0, 0, 1})
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, {0, 0, 0, 1})
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 4)
glNormalPointer(GL_FLOAT, 0, 0x3975624)
glVertexPointer(3, GL_FLOAT, 0, 0x396C610)
glDrawElements(GL_TRIANGLE_STRIP, 3, GL_UNSIGNED_INT, 0x39B6228)
glDrawElements(GL_TRIANGLE_STRIP, 3, GL_UNSIGNED_INT, 0x39B6240)
<SNIP>
glDrawElements(GL_TRIANGLE_STRIP, 13, GL_UNSIGNED_INT, 0x39B7ABC)
[b]glPopAttrib() [/b] < causes Invalid Operation

Many thanks for any help!

I’m getting a similarly unexpected “invalid operation” when calling glPopAttrib. I didn’t see any responses to kreyszig’s post; did anyone ever figure out what was wrong there? I am getting very similar symptoms, though I’m not pushing the same thing: I push

GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT

and as far as I can tell I don’t use glBegin at all (the drawing is done by glDrawArrays, which may be calling glBegin internally).

This only happens on a couple of Linux machines with glX; the same code works on Mac OSX with glX, and on Windows with wgl.

Thanks for any help…

In that case its prolly a driver bug, submit an error report to the driver makers of the card youre seeing it on.

personally though Ild ditch the Push/Pop Attrib stuff
u can easily either
A/ store the current relevant states yourself before hand
B/ keep track of what states youve changes and change back at the end

My tip would be: try to call glPopAttrib when exactly the same FBO is bound (again) as when the corresponding glPushAttrib has been called.

Once I stumbled across a driver bug where the glDrawBuffer setting which would get restored through glPopAttrib would try to restore a draw buffer which is not valid for the window provided framebuffer.

Yep, w.r.t DrawBuffer(s) the 2 causes for nastiness seem to be

Except for NONE, a buffer may not appear more then once in the array pointed to by bufs. Specifying a buffer more then once will result in the error INVALID OPERATION.

P.S. I’m inclined to agree with zed - ditch the attrib stack if possible (deprecated anyway).