GPUImageFramebufferCache类负责管理GPUImageFramebuffer对象,是一个GPUImageFramebuffer对象的缓存。
方法
- (GPUImageFramebuffer *)fetchFramebufferForSize:(CGSize)framebufferSize textureOptions:(GPUTextureOptions)textureOptions onlyTexture:(BOOL)onlyTexture
说明:从cache中获取一个GPUImageFramebuffer对象,如果获取失败,那么创建一个新的GPUImageFramebuffer对象。
参数:framebufferSize是对象的大小,textureOptions是纹理的配置信息,onlyTexture指示是否只为纹理,是否包含framebuffer对象。
返回:一个GPUImageFramebuffer对象
实现
- (GPUImageFramebuffer *)fetchFramebufferForSize:(CGSize)framebufferSize textureOptions:(GPUTextureOptions)textureOptions onlyTexture:(BOOL)onlyTexture;{ __block GPUImageFramebuffer *framebufferFromCache = nil;// dispatch_sync(framebufferCacheQueue, ^{ runSynchronouslyOnVideoPRocessingQueue(^{ NSString *lookupHash = [self hashForSize:framebufferSize textureOptions:textureOptions onlyTexture:onlyTexture]; NSNumber *numberOfMatchingTexturesInCache = [framebufferTypeCounts objectForKey:lookupHash]; NSInteger numberOfMatchingTextures = [numberOfMatchingTexturesInCache integerValue]; if ([numberOfMatchingTexturesInCache integerValue] < 1) { // Nothing in the cache, create a new framebuffer to use framebufferFromCache = [[GPUImageFramebuffer alloc] initWithSize:framebufferSize textureOptions:textureOptions onlyTexture:onlyTexture]; } else { // Something found, pull the old framebuffer and decrement the count NSInteger currentTextureID = (numberOfMatchingTextures - 1); while ((framebufferFromCache == nil) && (currentTextureID >= 0)) { NSString *textureHash = [NSString stringWithFormat:@"%@-%ld", lookupHash, (long)currentTextureID]; framebufferFromCache = [framebufferCache objectForKey:textureHash]; // Test the values in the cache first, to see if they got invalidated behind our back if (framebufferFromCache != nil) { // Withdraw this from the cache while it's in use [framebufferCache removeObjectForKey:textureHash]; } currentTextureID--; } currentTextureID++; [framebufferTypeCounts setObject:[NSNumber numberWithInteger:currentTextureID] forKey:lookupHash]; if (framebufferFromCache == nil) { framebufferFromCache = [[GPUImageFramebuffer alloc] initWithSize:framebufferSize textureOptions:textureOptions onlyTexture:onlyTexture]; } } }); [framebufferFromCache lock]; return framebufferFromCache;}
- (GPUImageFramebuffer *)fetchFramebufferForSize:(CGSize)framebufferSize onlyTexture:(BOOL)onlyTexture
说明:同上
实现
- (GPUImageFramebuffer *)fetchFramebufferForSize:(CGSize)framebufferSize onlyTexture:(BOOL)onlyTexture;{ GPUTextureOptions defaultTextureOptions; defaultTextureOptions.minFilter = GL_LINEAR; defaultTextureOptions.magFilter = GL_LINEAR; defaultTextureOptions.wrapS = GL_CLAMP_TO_EDGE; defaultTextureOptions.wrapT = GL_CLAMP_TO_EDGE; defaultTextureOptions.internalFormat = GL_RGBA; defaultTextureOptions.format = GL_BGRA; defaultTextureOptions.type = GL_UNSIGNED_BYTE; return [self fetchFramebufferForSize:framebufferSize textureOptions:defaultTextureOptions onlyTexture:onlyTexture];}
- (void)returnFramebufferToCache:(GPUImageFramebuffer *)framebuffer
说明:向GPUImageFramebuffer缓存加添加GPUImageFramebuffer对象
参数:需要添加的GPUImageFramebuffer对象
实现
- (void)returnFramebufferToCache:(GPUImageFramebuffer *)framebuffer;{ [framebuffer clearAllLocks]; // dispatch_async(framebufferCacheQueue, ^{ runAsynchronouslyOnVideoProcessingQueue(^{ CGSize framebufferSize = framebuffer.size; GPUTextureOptions framebufferTextureOptions = framebuffer.textureOptions; NSString *lookupHash = [self hashForSize:framebufferSize textureOptions:framebufferTextureOptions onlyTexture:framebuffer.missingFramebuffer]; NSNumber *numberOfMatchingTexturesInCache = [framebufferTypeCounts objectForKey:lookupHash]; NSInteger numberOfMatchingTextures = [numberOfMatchingTexturesInCache integerValue]; NSString *textureHash = [NSString stringWithFormat:@"%@-%ld", lookupHash, (long)numberOfMatchingTextures]; // [framebufferCache setObject:framebuffer forKey:textureHash cost:round(framebufferSize.width * framebufferSize.height * 4.0)]; [framebufferCache setObject:framebuffer forKey:textureHash]; [framebufferTypeCounts setObject:[NSNumber numberWithInteger:(numberOfMatchingTextures + 1)] forKey:lookupHash]; });}
- (void)purgeAllUnassignedFramebuffers
说明:清理缓存中的纹理缓存,清理framebufferCache中的所有对象
实现
- (void)purgeAllUnassignedFramebuffers;{ runAsynchronouslyOnVideoProcessingQueue(^{// dispatch_async(framebufferCacheQueue, ^{ [framebufferCache removeAllObjects]; [framebufferTypeCounts removeAllObjects];#if TARGET_ipHONE_SIMULATOR || TARGET_OS_IPHONE CVOpenGLESTextureCacheFlush([[GPUImageContext sharedImageProcessingContext] coreVideoTextureCache], 0);#else#endif });}
- (void)addFramebufferToActiveImageCaptureList:(GPUImageFramebuffer *)framebuffer
说明:
实现
- (void)addFramebufferToActiveImageCaptureList:(GPUImageFramebuffer *)framebuffer;{ runAsynchronouslyOnVideoProcessingQueue(^{// dispatch_async(framebufferCacheQueue, ^{ [activeImageCaptureList addObject:framebuffer]; });}
- (void)removeFramebufferFromActiveImageCaptureList:(GPUImageFramebuffer *)framebuffer
说明:
实现
- (void)removeFramebufferFromActiveImageCaptureList:(GPUImageFramebuffer *)framebuffer;{ runAsynchronouslyOnVideoProcessingQueue(^{// dispatch_async(framebufferCacheQueue, ^{ [activeImageCaptureList removeObject:framebuffer]; });}
完整代码
#import <Foundation/Foundation.h>#import <QuartzCore/QuartzCore.h>#import "GPUImageFramebuffer.h"@interface GPUImageFramebufferCache : NSObject// Framebuffer management- (GPUImageFramebuffer *)fetchFramebufferForSize:(CGSize)framebufferSize textureOptions:(GPUTextureOptions)textureOptions onlyTexture:(BOOL)onlyTexture;- (GPUImageFramebuffer *)fetchFramebufferForSize:(CGSize)framebufferSize onlyTexture:(BOOL)onlyTexture;- (void)returnFramebufferToCache:(GPUImageFramebuffer *)framebuffer;- (void)purgeAllUnassignedFramebuffers;- (void)addFramebufferToActiveImageCaptureList:(GPUImageFramebuffer *)framebuffer;- (void)removeFramebufferFromActiveImageCaptureList:(GPUImageFramebuffer *)framebuffer;@end
#import "GPUImageFramebufferCache.h"#import "GPUImageContext.h"#import "GPUImageOutput.h"#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE#import <UIKit/UIKit.h>#else#endif@interface GPUImageFramebufferCache(){// NSCache *framebufferCache; NSMutableDictionary *framebufferCache; NSMutableDictionary *framebufferTypeCounts; NSMutableArray *activeImageCaptureList; // Where framebuffers that may be lost by a filter, but which are still needed for a UIImage, etc., are stored id memoryWarningObserver; dispatch_queue_t framebufferCacheQueue;}- (NSString *)hashForSize:(CGSize)size textureOptions:(GPUTextureOptions)textureOptions onlyTexture:(BOOL)onlyTexture;@end@implementation GPUImageFramebufferCache#pragma mark -#pragma mark Initialization and teardown- (id)init;{ if (!(self = [super init])) { return nil; } #if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE memoryWarningObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIapplicationDidReceiveMemoryWarningNotification object:nil queue:nil usingBlock:^(NSNotification *note) { [self purgeAllUnassignedFramebuffers]; }];#else#endif// framebufferCache = [[NSCache alloc] init]; framebufferCache = [[NSMutableDictionary alloc] init]; framebufferTypeCounts = [[NSMutableDictionary alloc] init]; activeImageCaptureList = [[NSMutableArray alloc] init]; framebufferCacheQueue = dispatch_queue_create("com.sunsetlakesoftware.GPUImage.framebufferCacheQueue", NULL); return self;}#pragma mark -#pragma mark Framebuffer management- (NSString *)hashForSize:(CGSize)size textureOptions:(GPUTextureOptions)textureOptions onlyTexture:(BOOL)onlyTexture;{ if (onlyTexture) { return [NSString stringWithFormat:@"%.1fx%.1f-%d:%d:%d:%d:%d:%d:%d-NOFB", size.width, size.height, textureOptions.minFilter, textureOptions.magFilter, textureOptions.wrapS, textureOptions.wrapT, textureOptions.internalFormat, textureOptions.format, textureOptions.type]; } else { return [NSString stringWithFormat:@"%.1fx%.1f-%d:%d:%d:%d:%d:%d:%d", size.width, size.height, textureOptions.minFilter, textureOptions.magFilter, textureOptions.wrapS, textureOptions.wrapT, textureOptions.internalFormat, textureOptions.format, textureOptions.type]; }}- (GPUImageFramebuffer *)fetchFramebufferForSize:(CGSize)framebufferSize textureOptions:(GPUTextureOptions)textureOptions onlyTexture:(BOOL)onlyTexture;{ __block GPUImageFramebuffer *framebufferFromCache = nil;// dispatch_sync(framebufferCacheQueue, ^{ runSynchronouslyOnVideoProcessingQueue(^{ NSString *lookupHash = [self hashForSize:framebufferSize textureOptions:textureOptions onlyTexture:onlyTexture]; NSNumber *numberOfMatchingTexturesInCache = [framebufferTypeCounts objectForKey:lookupHash]; NSInteger numberOfMatchingTextures = [numberOfMatchingTexturesInCache integerValue]; if ([numberOfMatchingTexturesInCache integerValue] < 1) { // Nothing in the cache, create a new framebuffer to use framebufferFromCache = [[GPUImageFramebuffer alloc] initWithSize:framebufferSize textureOptions:textureOptions onlyTexture:onlyTexture]; } else { // Something found, pull the old framebuffer and decrement the count NSInteger currentTextureID = (numberOfMatchingTextures - 1); while ((framebufferFromCache == nil) && (currentTextureID >= 0)) { NSString *textureHash = [NSString stringWithFormat:@"%@-%ld", lookupHash, (long)currentTextureID]; framebufferFromCache = [framebufferCache objectForKey:textureHash]; // Test the values in the cache first, to see if they got invalidated behind our back if (framebufferFromCache != nil) { // Withdraw this from the cache while it's in use [framebufferCache removeObjectForKey:textureHash]; } currentTextureID--; } currentTextureID++; [framebufferTypeCounts setObject:[NSNumber numberWithInteger:currentTextureID] forKey:lookupHash]; if (framebufferFromCache == nil) { framebufferFromCache = [[GPUImageFramebuffer alloc] initWithSize:framebufferSize textureOptions:textureOptions onlyTexture:onlyTexture]; } } }); [framebufferFromCache lock]; return framebufferFromCache;}- (GPUImageFramebuffer *)fetchFramebufferForSize:(CGSize)framebufferSize onlyTexture:(BOOL)onlyTexture;{ GPUTextureOptions defaultTextureOptions; defaultTextureOptions.minFilter = GL_LINEAR; defaultTextureOptions.magFilter = GL_LINEAR; defaultTextureOptions.wrapS = GL_CLAMP_TO_EDGE; defaultTextureOptions.wrapT = GL_CLAMP_TO_EDGE; defaultTextureOptions.internalFormat = GL_RGBA; defaultTextureOptions.format = GL_BGRA; defaultTextureOptions.type = GL_UNSIGNED_BYTE; return [self fetchFramebufferForSize:framebufferSize textureOptions:defaultTextureOptions onlyTexture:onlyTexture];}- (void)returnFramebufferToCache:(GPUImageFramebuffer *)framebuffer;{ [framebuffer clearAllLocks]; // dispatch_async(framebufferCacheQueue, ^{ runAsynchronouslyOnVideoProcessingQueue(^{ CGSize framebufferSize = framebuffer.size; GPUTextureOptions framebufferTextureOptions = framebuffer.textureOptions; NSString *lookupHash = [self hashForSize:framebufferSize textureOptions:framebufferTextureOptions onlyTexture:framebuffer.missingFramebuffer]; NSNumber *numberOfMatchingTexturesInCache = [framebufferTypeCounts objectForKey:lookupHash]; NSInteger numberOfMatchingTextures = [numberOfMatchingTexturesInCache integerValue]; NSString *textureHash = [NSString stringWithFormat:@"%@-%ld", lookupHash, (long)numberOfMatchingTextures]; // [framebufferCache setObject:framebuffer forKey:textureHash cost:round(framebufferSize.width * framebufferSize.height * 4.0)]; [framebufferCache setObject:framebuffer forKey:textureHash]; [framebufferTypeCounts setObject:[NSNumber numberWithInteger:(numberOfMatchingTextures + 1)] forKey:lookupHash]; });}- (void)purgeAllUnassignedFramebuffers;{ runAsynchronouslyOnVideoProcessingQueue(^{// dispatch_async(framebufferCacheQueue, ^{ [framebufferCache removeAllObjects]; [framebufferTypeCounts removeAllObjects];#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE CVOpenGLESTextureCacheFlush([[GPUImageContext sharedImageProcessingContext] coreVideoTextureCache], 0);#else#endif });}- (void)addFramebufferToActiveImageCaptureList:(GPUImageFramebuffer *)framebuffer;{ runAsynchronouslyOnVideoProcessingQueue(^{// dispatch_async(framebufferCacheQueue, ^{ [activeImageCaptureList addObject:framebuffer]; });}- (void)removeFramebufferFromActiveImageCaptureList:(GPUImageFramebuffer *)framebuffer;{ runAsynchronouslyOnVideoProcessingQueue(^{// dispatch_async(framebufferCacheQueue, ^{ [activeImageCaptureList removeObject:framebuffer]; });}@end
新闻热点
疑难解答