在iOS上开发新功能,特别是iOS 5上新的OpenGL相关功能,所以如果我的任何问题都是如此基本,我会道歉。
我正在处理的应用程序旨在接收相机帧并通过OpenGL ES在屏幕上显示它们(图形人员将接管这个并添加我知道的实际OpenGL绘图)。该应用程序是开发XCode4,目标是运行iOS 5的iPhone4。目前,我使用ARC和GLKit功能,除了在将图像加载为纹理时的内存泄漏,所有工作都正常。该应用程序很快会收到“内存警告”。
具体来说,我想问一下如何释放由
分配的纹理@property(retain) GLKTextureInfo *texture;
-(void)setTextureCGImage:(CGImageRef)image
{
NSError *error;
self.texture = [GLKTextureLoader textureWithCGImage:image options:nil error:&error];
if (error)
{
NSLog(@"Error loading texture from image: %@",error);
}
}
image
是从相机框架构建的石英图像(来自苹果的示例代码)。我知道问题不在代码的那一部分,因为如果我禁用分配,应用程序就不会收到警告。
答案 0 :(得分:22)
我相信超级hacky解决方案,但似乎有效:
在作业之前添加以下内容:
GLuint name = self.texture.name;
glDeleteTextures(1, &name);
如果有更正式的方式(或者这是官方方式),如果有人能让我知道,我将不胜感激。
答案 1 :(得分:5)
不是一个直接的答案,而是我注意到的一些东西,它并不适合评论。
如果您使用GLKTextureLoader
在后台加载纹理来替换现有纹理,则必须删除主线程上的现有纹理。删除完成处理程序中的纹理将不起作用。
AFAIK这是因为:
也就是说,会泄漏内存。
NSDictionary *options = @{GLKTextureLoaderOriginBottomLeft:@YES};
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
[self.asyncTextureLoader textureWithContentsOfFile:@"my_texture_path.png"
options:options
queue:queue
completionHandler:^(GLKTextureInfo *texture, NSError *e){
GLuint name = self.myTexture.name;
//
// This delete textures call has no effect!!!
//
glDeleteTextures(1, &name);
self.myTexture = texture;
}];
要解决此问题,您可以:
因此,要解决泄漏问题,您需要这样做:
//
// Method #1, delete before upload happens.
// Executed on the main thread so it works as expected.
// Potentially leaves some GL content untextured if you're still drawing it
// while the texture is being loaded in.
//
// Done on the main thread so it works as expected
GLuint name = self.myTexture.name;
glDeleteTextures(1, &name)
NSDictionary *options = @{GLKTextureLoaderOriginBottomLeft:@YES};
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
[self.asyncTextureLoader textureWithContentsOfFile:@"my_texture_path.png"
options:options
queue:queue
completionHandler:^(GLKTextureInfo *texture, NSError *e){
// no delete required, done previously.
self.myTexture = texture;
}];
或
//
// Method #2, delete in completion handler but do it on the main thread.
//
NSDictionary *options = @{GLKTextureLoaderOriginBottomLeft:@YES};
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
[self.asyncTextureLoader textureWithContentsOfFile:@"my_texture_path.png"
options:options
queue:queue
completionHandler:^(GLKTextureInfo *texture, NSError *e){
// you could potentially do non-gl related work here, still in the background
// ...
// Force the actual texture delete and re-assignment to happen on the main thread.
dispatch_sync(dispatch_get_main_queue(), ^{
GLuint name = self.myTexture.name;
glDeleteTextures(1, &name);
self.myTexture = texture;
});
}];
答案 2 :(得分:0)
有没有办法简单地将纹理内容替换为相同的GLKTextureInfo.name句柄?使用glgentextures时,您可以使用返回的纹理句柄使用glteximage2d加载新的texuture数据。但是使用GLKTextureLoader似乎每次加载新的纹理数据时都会调用glgentextures ...