【问题标题】:Memory leak in drawing OpenGL framebuffer to UIImage将 OpenGL 帧缓冲区绘制到 UIImage 时的内存泄漏
【发布时间】:2014-03-18 04:41:41
【问题描述】:

我正在使用 OpenGL 在屏幕上进行绘图,并希望将屏幕的一部分绘制到 UIImage。这是我在查看示例时拼凑起来的代码,它有效,但每次调用时都会产生内存泄漏。我已经在设备上对此进行了测试,泄漏仍然存在并最终导致崩溃。返回的 UIImage 被保存到一个实例变量中,稍后肯定会再次设置为 nil。是什么导致了这里的内存泄漏?

- (UIImage *)renderToImageWithContentFrame:(CGRect)contentFrame
                               exportFrame:(CGRect)exportFrame
                                     scale:(float)scale {

    float screenWidth = contentFrame.size.width * scale;
    float screenHeight = contentFrame.size.height * scale;

    GLuint framebuffer;
    glGenFramebuffers(1, &framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

    GLuint renderTex;
    glGenTextures(1, &renderTex);
    glBindTexture(GL_TEXTURE_2D, renderTex);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screenWidth, screenHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTex, 0);

    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
    glViewport(0, 0, screenWidth, screenHeight);

    [self _renderImageGL];

    // grabbing image from FBO

    NSInteger dataLength = screenWidth * screenHeight * 4;
    GLubyte *data = (GLubyte*)malloc(dataLength * sizeof(GLubyte));

    glPixelStorei(GL_PACK_ALIGNMENT, 4);
    glReadPixels(0, 0, screenWidth, screenHeight, GL_RGBA, GL_UNSIGNED_BYTE, data);

    glDeleteFramebuffers(1, &framebuffer);

    CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, data, dataLength, NULL);
    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
    CGImageRef iref = CGImageCreate(screenWidth, screenHeight, 8, 32, screenWidth * 4, colorspace,
                                    kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast,
                                    ref, NULL, true, kCGRenderingIntentDefault);

    float x = (exportFrame.origin.x - contentFrame.origin.x) * scale;
    float y = (exportFrame.origin.y - contentFrame.origin.y) * scale;
    float width = exportFrame.size.width * scale;
    float height = exportFrame.size.height * scale;
    CGImageRef cropped = CGImageCreateWithImageInRect(iref, (CGRect){x, y, width, height});

    UIGraphicsBeginImageContext((CGSize){width, height});
    CGContextRef cgcontext = UIGraphicsGetCurrentContext();
    CGContextSetBlendMode(cgcontext, kCGBlendModeCopy);
    CGContextDrawImage(cgcontext, (CGRect){0, 0, width, height}, cropped);
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    free(data);
    CFRelease(ref);
    CFRelease(colorspace);
    CGImageRelease(iref);
    CGImageRelease(cropped);

    return image;

}

【问题讨论】:

  • 泄漏仪器说泄漏在哪里?另外,你在哪里免费datarenderTex
  • @user1118321 内存泄漏是因为我没有释放renderTex。感谢您指出。泄漏没有出现在仪器中。所有的OpenGL泄漏都是这样吗?随意做一个答案写

标签: ios memory-management opengl-es opengl-es-2.0


【解决方案1】:

变量renderTex 未被释放(通过调用glDeleteTextures(1, &renderTex);)。我的猜测是 Instruments 可能不知道 OpenGL 分配的内存,因为该内存可能驻留在显卡上并且可能更难(或不可能)跟踪。 (虽然这主要是猜测。)

【讨论】:

  • 纹理记忆对乐器不透明是我的经验,大约是 iOS5。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多