Monday, 19 August 2013

-[EAGLContext renderbufferStorage:fromDrawable:] Failing the second time on?

-[EAGLContext renderbufferStorage:fromDrawable:] Failing the second time on?

I'm developing an iOS openGL ES application.
I'm doing the usual EAGLView / ES2Render stuff.
On startup, frambuffer creation succeeds, using the following code:
- (BOOL) createFramebuffers
{
[EAGLContext setCurrentContext:_mainContext];
// [ A ] On-screen
// 1. Framebuffer
glGenFramebuffers(1, &_mainFramebuffer);
bindFramebuffer(_mainFramebuffer);
// 2. Color buffer
glGenRenderbuffers(1, &_mainColorbuffer);
bindRenderbuffer(_mainColorbuffer);
// Adjust size to view's layer:
CAEAGLLayer* layer = (CAEAGLLayer*)[_view layer];
if (![_mainContext renderbufferStorage:GL_RENDERBUFFER
fromDrawable:layer]) {
// something went horribly wrong
NSLog(@"-[ES2Renderer createFramebuffers]: Failed to obtain
renderbuffer storage from layer!");
return NO;
}
// Query new size:
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH,
&_backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT,
&_backingHeight);
// Attach to color:
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, _mainColorbuffer);
// 3. Depth buffer
glGenRenderbuffers(1, &_depthBuffer);
bindRenderbuffer(_depthBuffer);
if (_useStencilBuffer) {
// Depth + Stencil
// Allocate storage:
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES,
_backingWidth, _backingHeight);
// Attach to depth:
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, _depthBuffer);
// Attach to stencil:
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, _depthBuffer);
}
else{
// Depth only
// Allocate storage:
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES,
_backingWidth, _backingHeight);
// Attachto depth:
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, _depthBuffer);
}
// 4. Validate the set:
GLenum framebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (framebufferStatus != GL_FRAMEBUFFER_COMPLETE) {
// Something went wrong!
NSLog(@"-[ES2Renderer createFramebuffers]: Failed to make complete
framebuffer object: %@",
[self stringFromFramebufferStauts:framebufferStatus]);
return NO;
}
// [ B ] Off-screen (Render-to-texture)
// 1. Framebuffer
glGenFramebuffers(1, &_transFramebuffer);
bindFramebuffer(_transFramebuffer);
// 2. Depth buffer
glGenRenderbuffers(1, &_transDepthBuffer);
bindRenderbuffer(_transDepthBuffer);
if (_useStencilBuffer) {
// Allocate storage:
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES,
_backingWidth, _backingHeight);
// Attach to depth:
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, _transDepthBuffer);
// Attach to stencil:
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, _transDepthBuffer);
}
else{
// Allocate storage
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES,
_backingWidth, _backingHeight);
// Attach to depth:
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, _transDepthBuffer);
}
// 3. Textures (color buffers)
GLuint* texPtrs[2] = {&_transTexture1, &_transTexture2};
for (NSUInteger i=0; i < 2; i++) {
GLuint* texPtr = texPtrs[i];
// Create:
glGenTextures(1, texPtr);
// Bind:
bindTexture2D(*texPtr);
// Configure for pixel-aligned use:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Allocate storage:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _backingWidth,
_backingHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
// Attach:
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, *texPtr, 0);
framebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
// Validate:
if ( framebufferStatus != GL_FRAMEBUFFER_COMPLETE) {
// Something went wrong!
NSLog(@"-[ES2Renderer createFramebuffers]: Failed to make
complete framebuffer object: %@",
[self stringFromFramebufferStauts:framebufferStatus]);
return NO;
}
}
// Final State:
bindFramebuffer(_mainFramebuffer);
bindRenderbuffer(_mainColorbuffer);
bindTexture2D(0);
NSLog(@"-[ES2Renderer createFramebuffers] Succeeded.");
return YES;
}
Soon after, UIView's -layoutSubviews is called and I in turn execute
-resizeFromLayer::
- (BOOL) resizeFromLayer:(CAEAGLLayer *)layer
{
// [ A ] On screen framebuffer
bindFramebuffer(_mainFramebuffer);
// 1. Resize color buffer
bindRenderbuffer(_mainColorbuffer);
if (![_mainContext renderbufferStorage:GL_RENDERBUFFER
fromDrawable:layer]) {
// Something went wrong
return NO; // <-- SECOND TIME ON, THIS HAPPENS
}
// Query new size:
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH,
&_backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT,
&_backingHeight);
// 2. Resize depth buffer
bindRenderbuffer(_depthBuffer);
if (_useStencilBuffer) {
// (Depth & Stencil)
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES,
_backingWidth, _backingHeight);
}
else{
// (Depth only)
glRenderbufferStorage(GL_FRAMEBUFFER, GL_DEPTH_COMPONENT24_OES,
_backingWidth, _backingHeight);
}
// ...Validate:
GLenum framebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (framebufferStatus != GL_FRAMEBUFFER_COMPLETE) {
// Something went wrong!
NSLog(@"-[ES2Renderer resizeFromLayer:]: Failed to make complete
framebuffer object: %@",
[self
stringFromFramebufferStauts:glCheckFramebufferStatus(GL_FRAMEBUFFER)]);
return NO;
}
// [ B ] Off screen (render-to-terxture) framebuffer
bindFramebuffer(_transFramebuffer);
// 1. Resize depth buffer
bindRenderbuffer(_transDepthBuffer);
if (_useStencilBuffer) {
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES,
_backingWidth, _backingHeight);
}
else{
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES,
_backingWidth, _backingHeight);
}
// 2. Resize textures
GLuint* texPtrs[2] = {&_transTexture1, &_transTexture2};
for (NSUInteger i=0; i < 2; i++) {
GLuint* texPtr = texPtrs[i];
// Bind:
bindTexture2D(*texPtr);
// Configure for pixel-aligned use:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Allocate storage:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _backingWidth,
_backingHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
// Attach:
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, *texPtr, 0);
// Validate:
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) !=
GL_FRAMEBUFFER_COMPLETE) {
// Something went wrong!
NSString* statusString = [self
stringFromFramebufferStauts:glCheckFramebufferStatus(GL_FRAMEBUFFER)];
NSLog(@"-[ES2Renderer resizeFromLayer:]: Failed to make
complete framebuffer object: %@", statusString);
return NO;
}
}
bindFramebuffer(_mainFramebuffer);
bindRenderbuffer(_mainColorbuffer);
// Pass new ortho projection to shaders
[self initializeModelViewMatrix];
[self initializeSpriteProgram];
// Set new viewport
glViewport(0, 0, _backingWidth, _backingHeight);
NSLog(@"-[ES2Renderer resizeFromLayer:]: Succeeded.");
return YES;
}
Nothing of what I'm doing is special. I have a separate framebuffer to
render scene transitions, with two textures to attach to color, and depth.
The second time -renderbufferStorage:fromDrawable: is called
(-layoutSubviews -> resizeFromLayer:), it invariably fails (returns NO);
Calling glGetError() right before that results in no error, but calling it
right after returns GL_INVALID_OPERATION. If I ignore this and proceed,
glGetRenderbufferParameteriv() still gets me the right width and height
(640 and 1136, respectively, on an iPhone 5), but
glCheckFramebufferStatus() will return GL_FRAMEBUFFER_UNSUPPORTED.
Alternatively, I skipped the above resizeFromLayer: and replaced it with
this:
- (BOOL) resizeFromLayer:(CAEAGLLayer *)layer
{
[self destroyFramebuffers];
return [self createFramebuffers];
}
...but the same error persists (-renderStorage:fromDrawable: fails; this
time inside -createFramebuffers).
For now, I just return YES (my app only supports portrait, so no screen
size change actually ever happens), but I really want to fix it because
one day I'll need to support landscape, etc...

No comments:

Post a Comment