123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- #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
|