Question

In an OpenGL ES app I'm working on, I noticed that the glReadPixels() function fails to work across all devices/simulators. To test this, I created a bare-bones sample OpenGL app. I set the background color on an EAGLContext context and tried to read the pixels using glReadPixels() as follows:

int bytesPerPixel = 4;
int bufferSize = _backingWidth * _backingHeight * bytesPerPixel;

void* pixelBuffer = malloc(bufferSize);
glReadPixels(0, 0, _backingWidth, _backingHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixelBuffer);

// pixelBuffer should now have meaningful color/pixel data, but it's null for iOS 7 devices

free(pixelBuffer);

This works as expected on the simulator for iOS 6 and 7 and a physical iOS 6 device, but it fails on a physical iOS 7 device. The scenarios tested are shown in the table below (YES/NO = works/doesn't):

Test

I'm using OpenGL ES v1.1 (though v2 also fails to work after a quick test).

Has anyone encountered this problem? Am I missing something? The strangest part of this is that it only fails on iOS 7 physical devices.

Here is a gist with all the relevant code and the bare-bones GitHub project for reference. I've made it very easy to build and demonstrate the issue.

UPDATE:

Here is the updated gist, and the GitHub project has been updated too. I've updated the sample project so that you can easily view the memory output from glReadPixels.

Also, I have a new observation: When the EAGLContext is layer-backed ([self.context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer]), glReadPixels can successfully read data on all devices/simulators (iOS 6 and 7). However, when you toggle the flag in GLView.m so that the context is not layer-backed ([self.context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:nil]), glReadPixels exhibits the condition expressed in the initial post (works on iOS 6 sim/device, iOS 7 sim, but fails on iOS 7 device).

Was it helpful?

Solution

As posted in the comments I managed to use your code and it worked. However, I defined your BACKING_TYPE_LAYERBACKED which generates the render buffer from the view.

The other pipeline that creates the FBO did not work though. The issue in your FBO pipeline is calling [self.context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:nil]. Remove this line and you should be fine.

OTHER TIPS

To continue from Matic Oblak's answer, for those who might encounter this issue when using a second back buffer( data backed - storage not from layer ) for tasks like object picking, on device, you will need to rebind frameBuffer, renderBuffer and then re-attach renderBuffer to frameBuffer. For e.g the bindBuffers function in gist would be as below

- (void)bindBuffers
{
  glBindFramebufferOES(GL_FRAMEBUFFER_OES, _framebuffer);
  glBindRenderbufferOES(GL_RENDERBUFFER_OES, _renderbuffer);
  glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _renderbuffer);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top