Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL ES - glReadPixels

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);
}
like image 264
Bill Kotsias Avatar asked Nov 21 '11 08:11

Bill Kotsias


2 Answers

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.

like image 98
Nils Pipenbrinck Avatar answered Oct 09 '22 01:10

Nils Pipenbrinck


In the end, it was lack of memory. The "new uint8[dataLength];" never returned an existent pointer, thus the whole process went corrupted.

TomA, your idea of clearing the buffer actually helped me to solve the problem. Thanks.

like image 24
Bill Kotsias Avatar answered Oct 09 '22 00:10

Bill Kotsias