glReadPixels and glGetTexImage inconsistency

I have a FBO with a texture which is per default grey. I bind the FBO, do glClear() and now I expect the texture to be red. I do glReadPixels() and I get the correct image data (red imge), but when I do glGetTexImage() I get the grey (default) image data.

Only glCopyTexImage2D() and glTexSubImage2D() seem to change the texture data, all rendering to the FBO doesn’t change the texture as seen by glGetTexImage().

Here’s my test app (works only under linux):
http://dbservice.com/tom/gltest.c

Please make sure your screen resolution isn’t bigger than 1280x1024 when you run this app.

At the bottom of the file there’s __glCapture() which is called in an endless loop… press CTRL+C to abort the app.

You see there that I activate the FBO, glClear(), glReadPixels() to a local buffer, activate the texture, glGetTexImage() to another local buffer and compare the two buffers.

the app prints the first pixel of each buffer, I get this:

textureBuffer 85:85:85:85
frameBuffer 0:0:255:255

which means glReadPixels() returns the correct image data (BGRA), but glGetTexImage() returns BGRA 85:85:85:85 which is in ASCII ‘U’ (like Undefined ?)
glGetTexImage() does not generate any error.

What am I doing wrong?

You can’t bind texture if currently active FBO use this texure as render target. So… you must call glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0 or other FBO id); before glBindTexture(GL_TEXTURE_2D, textureBuffer);.
This is reason why glGetTexImage returns bad data.

Also, please read FBO spec again. There is a paragraph regarding glReadBuffer. In short… If you use standard backbuffer then params for glReadBuffer is usual (GL_FRONT_LEFT, GL_FRONT_RIGHT, GL_BACK_LEFT, GL_BACK_RIGHT, GL_FRONT, GL_BACK, GL_LEFT, GL_RIGHT, and GL_AUX0 through GL_AUXn), but if app do readback while some FBO is active then params for glReadBuffer is GL_NONE or COLOR_ATTACHMENT0_EXT … COLOR_ATTACHMENTn_EXT. So, set correct readbuffer than call glReadPixels.
This is a reason why glReadPixels returns bad data.

Please give us more details regarding your hw spec (graphics card, OS, diver version).

yooyo

Even if I unbind the FBO before I bind the texture, glGetTexImage() still returns wrong data.

and there is no problem with glReadPixels(), this function retrurns the correct data even if I don’t call glReadBuffer() explicitly. So I guess the driver automatically switches to a FBO color attachment when I activate the FBO.

system is linux gentoo, kernel 2.6.13, opengl:
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: GeForce 6800 GT/AGP/SSE2
OpenGL version string: 2.0.0 NVIDIA 76.76

The following code still does abort:

 
void __glCaptureGet()
{	
	glBindTexture(GL_TEXTURE_2D, 0);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBuffer);

	glClearColor(1.0, 0.0, 0.0, 1.0);
	glClear(GL_COLOR_BUFFER_BIT);
	glFinish();
	
	glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
	glReadPixels(0, 0, __glCaptureWidth, __glCaptureHeight, GL_BGRA, GL_UNSIGNED_BYTE, (char *) __frameBuffer);
	
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
	glBindTexture(GL_TEXTURE_2D, textureBuffer);

	glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, (char *) __textureBuffer);
	
	int cmp = memcmp(__textureBuffer, __frameBuffer, imageDataSize);
	if (cmp) {
		fprintf( stderr, "data different
" );
		fprintf( stderr, "textureBuffer %d:%d:%d:%d
", __textureBuffer[0], __textureBuffer[1], __textureBuffer[2], __textureBuffer[3] );
		fprintf( stderr, "frameBuffer %d:%d:%d:%d
", __frameBuffer[0], __frameBuffer[1], __frameBuffer[2], __frameBuffer[3] );
		exit( 1 );
	}
}

I get the following output (the texture memory has been initialized with 0x0f which happens to be 15)

textureBuffer 15:15:15:15
frameBuffer 0:0:255:255

I can give you an updated version of my gltest application which uses glut and doesn’t create a fullscreen window…

Maybe I should add that when I map the texture onto a quad and display the quad, it appears red. That means the texture unit reads the correct colored (red) texture.

I think the driver somehow has two versions of the texture in VRAM, one original which is changed only by glCopyTex[Sub]Image2D and glTex[Sub]Image2D and a second which it renders to.
And glGetTexImage() reads only from the original texture which is never changed by rendering and the texture unit uses whatever texture is more up-to-date.