OpenGL ES - glReadPixels

Bill Kotsias picture Bill Kotsias · Nov 21, 2011 · Viewed 7.1k times · Source

I am taking a screenshot with glReadPixels to perform a "cross-over" effect between two images.

On the Marmalade SDK simulator, the screenshot is taken just fine and the "cross-over" effect works a treat: enter image description here

However, this is how it looks on iOS and Android devices - corrupted: enter image description here
(source: eikona.info)

I always read the screen as RGBA 1 byte/channel, as the documentation says it's ALWAYS accepted.

Here is the code used to take the screenshot:

uint8* Gfx::ScreenshotBuffer(int& deviceWidth, int& deviceHeight, int& dataLength) {

    /// width/height
    deviceWidth = IwGxGetDeviceWidth();
    deviceHeight = IwGxGetDeviceHeight();
    int rowLength = deviceWidth * 4; /// data always returned by GL as RGBA, 1 byte/each

    dataLength = rowLength * deviceHeight;

    // set the target framebuffer to read
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glPixelStorei(GL_PACK_ALIGNMENT, 1);
    uint8* buffer = new uint8[dataLength];
    glReadPixels(0, 0, deviceWidth, deviceHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer);

    return buffer;
}

void Gfx::ScreenshotImage(CIwImage* img, uint8*& pbuffer) {

    int deviceWidth, deviceHeight, dataLength;

    pbuffer = ScreenshotBuffer(deviceWidth, deviceHeight, dataLength);
    img->SetFormat(CIwImage::ABGR_8888);
    img->SetWidth(deviceWidth);
    img->SetHeight(deviceHeight);
    img->SetBuffers(pbuffer, dataLength, 0, 0);
}

Answer

Nils Pipenbrinck picture Nils Pipenbrinck · Nov 27, 2011

That is a driver bug. Simple as that.

The driver got the pitch of the surface in the video memory wrong. You can clearly see this in the upper lines. Also the garbage you see at the lower part of the image is the memory where the driver thinks the image is stored but there is different data there. Textures / Vertex data maybe.

And sorry, I know of no way to fix that. You may have better luck with a different surface-format or by enabling/disabling multisampling.