– 第二次失败?

我正在开发一个iOS的OpenGL ES应用程序。

我正在做通常的EAGLView / ES2Render的东西。

启动时,frambuffer创build成功,使用以下代码:

- (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; } 

不久之后, UIView-layoutSubviews被调用,我依次执行-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; } 

没有什么我做的是特别的。 我有一个单独的framebuffer渲染场景转换,两个纹理附加到颜色和深度。

第二次-renderbufferStorage:fromDrawable:被调用( -layoutSubviews – > resizeFromLayer: ,它总是失败(返回NO )。 在glGetError()之前调用glGetError()会导致没有错误,但在返回GL_INVALID_OPERATION之后立即调用它。 如果我忽略这个并继续, glGetRenderbufferParameteriv()仍然得到我正确的宽度和高度(分别为640和1136,在iPhone 5),但glCheckFramebufferStatus()将返回GL_FRAMEBUFFER_UNSUPPORTED

或者,我跳过上面的resizeFromLayer:并用下面的resizeFromLayer:replace它:

 - (BOOL) resizeFromLayer:(CAEAGLLayer *)layer { [self destroyFramebuffers]; return [self createFramebuffers]; } 

…但同样的错误仍然存​​在( -renderStorage:fromDrawable:失败;这一次内部-createFramebuffers )。

现在,我只是返回YES (我的应用程序只支持肖像,所以没有发生实际的屏幕大小变化),但我真的想解决它,因为有一天,我需要支持景观等…

renderbufferStorage:fromDrawable:失败的一个可能原因是_mainContext不是当前的上下文。 尽pipe似乎没有其他上下文可能会被盗取“当前”状态,但我build议在对与该上下文相关联的对象操作的任何glEAGL代码之前调用[EAGLContext setCurrentContext:_mainContext] (例如,在resizeFromLayer:方法)。