本文介绍了 - [EAGLContext renderbufferStorage:fromDrawable:]第二次失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm developing an iOS openGL ES application.

我正在做通常的EAGLView / ES2Render。

I'm doing the usual EAGLView / ES2Render stuff.

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

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

不久之后, UIView -layoutSubviews 然后执行 -resizeFromLayer:

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.

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

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.

或者,我跳过上面的 resizeFromLayer:并将其替换为:

Alternatively, I skipped the above resizeFromLayer: and replaced it with this:

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

    return [self createFramebuffers];
}

...但同样的错误仍然存​​在( - renderStorage:fromDrawable:失败;这次在 -createFramebuffers 中。

...but the same error persists (-renderStorage:fromDrawable: fails; this time inside -createFramebuffers).

目前,我只返回 YES (我的应用只支持肖像,所以实际上没有发生屏幕尺寸变化),但我真的想修复它因为有一天我需要支持格局等...

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...

推荐答案

一个可能的原因 renderbufferStorage :fromDrawable:失败的是 _mainContext 不是当时的当前上下文。即使看起来似乎没有其他上下文可以窃取当前状态,我建议在任何 gl之前调用 [EAGLContext setCurrentContext:_mainContext] / code>或 EAGL 对与该上下文关联的对象进行操作的代码(例如,在 resizeFromLayer的开头:方法)。

One possible reason that renderbufferStorage:fromDrawable: is failing is that the _mainContext is not the current context at that time. Even though it may seem that no other context could have stolen the 'current' status, I recommend calling [EAGLContext setCurrentContext:_mainContext] before any gl or EAGL code that operates on objects associated with that context (e.g. at the beginning of the resizeFromLayer: method).

这篇关于 - [EAGLContext renderbufferStorage:fromDrawable:]第二次失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-27 20:11