2010-07-08 174 views
3

我正在写一个iPhone应用程序使用UIView与CAEAGLayer作为其图层。一切都很好,并从1个小题工作分开:有时它与EXC_BAD_ACCESS崩溃和下面的堆栈跟踪:glDrawArrays崩溃与EXC_BAD_ACCESS

[EAGLView draw] 
    glDrawArrays_Exec 
    PrepareToDraw 
    DrawFramebufferMakeResident 
    AttachmentMakeResident 
    TextureMakeResident 
    memmove 

崩溃就行了:

glVertexPointer(3, GL_FLOAT, 0, vertexCoordinates); 
    glTexCoordPointer(2, GL_FLOAT, 0, textureCoordinates); 
    glBindTexture(GL_TEXTURE_2D, textures[kActiveSideLeft]); 
    glDrawArrays(GL_TRIANGLE_STRIP, 0, totalPoints); //<--Crash here 

应用将接口旋转变化期间仅崩溃(这也恰好是视图框架改变时的唯一情况)。它不会经常崩溃;大部分时间需要3-5分钟的旋转装置来重现此问题。
我相信我犯了一个与CAEAGLLayer初始化/帧更改有关的错误,因为这是它崩溃的地方(我相信)。
因此,这里有init和布局子视图的方法:
初始化:

... 
    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;  
    eaglLayer.opaque = TRUE; 

    context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; 
    if (!context || ![EAGLContext setCurrentContext:context]) 
    { 
     [self release]; 
     return nil; 
    } 

    glGenFramebuffersOES(1, &defaultFramebuffer); 
    glGenRenderbuffersOES(1, &colorRenderbuffer); 
    glGenRenderbuffersOES(1, &depthRenderbuffer); 
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer); 
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer); 
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer); 
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer); 
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer); 
    ... 

在组帧我只设置GL_MODELVIEW和GL_POJECTION矩阵,所以我想没有什么不好的可以在那里发生。
LayoutSubviews:

- (void)layoutSubviews 
    { 
     [EAGLContext setCurrentContext:context]; 

     glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer); 
     [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer]; 
     glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth); 
     glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight); 
     glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer); 
     glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight); 

     NSAssert1(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) == GL_FRAMEBUFFER_COMPLETE_OES, @"Failed to make complete framebuffer object: %X", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); 
    } 

Draw方法本身看起来像:

 if ([EAGLContext currentContext] != context) { 
      [EAGLContext setCurrentContext:context]; 
     } 

     glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer); 
     glViewport(0, 0, backingWidth, backingHeight); 

     ...//drawing different triangle strips here 

     glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer); 
     [context presentRenderbuffer:GL_RENDERBUFFER_OES]; 

我会很感激的上市代码或建议,我怎么能找到这个错误的原因的任何意见。

回答

3

我会怀疑totalPoints变量传递给drawArrays,或者可能是vertexCorrdinates或textureCoordinates的值,如果这些数组不是静态的。你的崩溃意味着你在绘制数组的同时走出内存的尽头。我对您的GL设置不太怀疑,并且更关心您的内存管理,以及您在轮换期间绘制的内容。 (另外,FWIW,我认为你不应该在每次绑定渲染缓冲区时调用RenderBufferStorage,你创建它们时只需要做一次,也就是说,我并不是这样做的。当你改变它们的大小并且从头开始重新创建它们时,肯定不应该破坏缓冲区。)

+0

那么,所有的数组都是静态的(至少它的大小永远不会改变),totalPoints只是一个#define常量。无论如何,我最终从头开始重新创建opengl视图,每次设备旋转时,都会有所帮助。 我不确定它是否是解决问题的好方法,但至少可以工作=) – Alexey 2010-07-29 06:49:27