Problem with glReadPixels on a part of a view on ATI cards


I can’t find what is wrong on ATI cards. On nvidia I have no problem.
Maybe you will have an idea…

I have 3 views :

  • a 2D (ortho) view on the left
  • two 3D (pers) view on the right, one above the other.
    The model is drawn on the 3 views and the 2D view shares the display lists.

When I close one 3D view, the remaining view takes all the place on the right of the 2D view.

Problem : glReadPixels returns 0 where the closed 3D view was. So on the half of the view it returns 0 and on the other half it is correct.
I saw with gDebugger that the depth buffer is wrong on the half of the view.
I have not this problem on nvidia.
I debugged on 2 pc, one nvidia and one ati : they use the same handles on opengl contexts.
The only difference in visual studio debugger is the “unused” member in the HGLRC structure : it is always 0 on nvidia, and never 0 on ati. But I don’t know the meaning of this variable :
on nvidia : HGLRC__* hGLContext { unused=0 }
on ati : HGLRC__* hGLContext { unused=973096704 } // and other values

I do a wglMakeCurrent before using glReadPixels to be sure.
There is no error with glGetError() and glCheckFramebufferStatus(GL_FRAMEBUFFER).

It seems that something is not well initialized or updated for ATI but I don’t know what…
If you have an idea…

Thanks in advance.

glCheckFramebufferStatus is for FBO, not for the main surface.

Are you refreshing the window before using glReadPixels?
The usual pattern of calls is

or better yet, render to an actual FBO since that is what it is for. It is more reliable then rendering to a window and reading back.

Thanks for your answer.
For the fun, here are the depth buffers… ImageShack - Best place for all of your image hosting and image sharing needs

To answer, the view is refreshed because I added geometry. And the glReadPixels is called on a mouse event over the view.

I did some tests :

  • I can obtain the same problem by resizing the views : with the two 3D views, one above the other ; I reduce the size of one view so that the other take the place. And I have the problem.
    So it is not a mistake in my code when deleting an opengl context ; I do not create a zombie context.
  • If I undock the 2 views I have the problem on the 2 views
  • If I close the 2 views with problem and I create a new 3D view this one has no problem.
    Maybe this will give an idea to someone…

On two cards I upgraded the drivers and I have no more the problem.
On an old card it is not possible to upgrade and I have the problem…
Maybe it is a bug in the driver but I don’t know what generates the problem…

So, you are using glReadPixels to read the depth buffer?
It looks like the depth buffer is stretched started from the middle. Is it causing a problem with the output to your window or is it just a problem for glReadPixels?
If it is glReadPixels, then I would just go with rendering to an FBO (attach a render buffer and render your scene to it). You can even choose to render to depth only for your FBO.

Yes. To then use gluUnProject to show world coordinates in the status bar or to move in the scene on some mouse events.

Is it causing a problem with the output to your window or is it just a problem for glReadPixels?

It is incredible (for me…) but there is no drawing problem. Maybe a chance with our drawing order ?
Only the world coordinates in the status bar are false and the scene do not move correctly in the half of the view…

If it is glReadPixels, then I would just go with rendering to an FBO (attach a render buffer and render your scene to it). You can even choose to render to depth only for your FBO.
Framebuffer Object Extension Examples - OpenGL Wiki

I will read your link.
If I understand this means to draw the scene several times more (on mouse events for me) to the depth buffer.

I will try to test your advice. To see if the depth buffer is correctly updated.


Maybe glReadPixels works well. The question is maybe why is the depth buffer invalid after drawing correctly ?

You would already need to re-render the scene on mouse move even if you are using the main window.
Usually, SwapBuffer invalidates the backbuffer.
On Windows, for the pixelformat descriptor, you can try setting PFD_SWAP_COPY and in this case, you don’t need to re-render. However, the MSDN documentation says this is a hint only, and it might not be provided by the driver.

Hello V-man,

Thanks for following my post.
And you have found something !

As I am discovering FBO it was easier to quickly test the pixel format.
And with our classical pixelformat, which contains PFD_SWAP_COPY, I have not the problem.

I use MSAA antialiasing when it is possible. In this case I have the problem. And the pixel format is different. So I will look tomorrow if there is something to change in the pixel format or if the problem comes from the MSAA.

Thanks for your help : i have two things to test now !

I join the pixelformats.
For MSAA :

int iAttributes[] =
        WGL_RED_BITS_ARB, 8,
        WGL_GREEN_BITS_ARB, 8,
        WGL_BLUE_BITS_ARB, 8,
        WGL_ACCUM_BITS_ARB, 0,
    valid = wglChoosePixelFormatARB(hDC,iAttributes,fAttributes,1,&M_PixelFormat,&numFormats);

Classical pixelformat :


    pixelDescriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pixelDescriptor.nVersion = 1;

        | PFD_SWAP_COPY
#if WINVER>=0x0600    // Vista
        | 0x00008000

    pixelDescriptor.iPixelType = PFD_TYPE_RGBA;
    pixelDescriptor.cColorBits = 32;
    pixelDescriptor.cRedBits = 8;
    pixelDescriptor.cRedShift = 24;
    pixelDescriptor.cGreenBits = 8;
    pixelDescriptor.cGreenShift = 16;
    pixelDescriptor.cBlueBits = 8;
    pixelDescriptor.cBlueShift = 8;
    pixelDescriptor.cAlphaBits = 8;
    pixelDescriptor.cAlphaShift = 0;
    pixelDescriptor.cAccumBits = 0;
    pixelDescriptor.cAccumRedBits = 0;
    pixelDescriptor.cAccumGreenBits = 0;
    pixelDescriptor.cAccumBlueBits = 0;
    pixelDescriptor.cAccumAlphaBits = 0;
    pixelDescriptor.cDepthBits = 24;
    pixelDescriptor.cStencilBits = 1;
    pixelDescriptor.cAuxBuffers = 0;
    pixelDescriptor.iLayerType = PFD_MAIN_PLANE;
    pixelDescriptor.bReserved = 0;
    pixelDescriptor.dwLayerMask = 0;
    pixelDescriptor.dwVisibleMask = 0;
    pixelDescriptor.dwDamageMask = 0;

    int pixelIndex = ChoosePixelFormat(hDC, &pixelDescriptor);