GPUImageAPI文档之GPUImageContext类
GPUImageContext类,提供OpenGL ES基本环境,我们一般不会用到,所以讲的很简单。
属性
@PRoperty(readonly, nonatomic) dispatch_queue_t contextQueue
说明:创建一个context线程
描述:_contextQueue = dispatch_queue_create("com.sunsetlakesoftware.GPUImage.openGLESContextQueue", NULL);
@property(readwrite, retain, nonatomic) GLProgram *currentShaderProgram
说明:当前着色器program
@property(readonly, retain, nonatomic) EAGLContext *context
说明:opengl es绘制环境,管理上下文
方法
+ (void *)contextKey
说明:设置当前context的线程标识符,全局静态变量。
+ (GPUImageContext *)sharedImageProcessingContext
说明:创建一个全局的GPUImageContext对象的单例。
+ (dispatch_queue_t)sharedContextQueue
说明:创建一个context queue单例
+ (GPUImageFramebufferCache *)sharedFramebufferCache
说明:创建一个GPUFramebufferCache单例
- (void)useAsCurrentContext
说明:使用当前context
+ (void)setActiveShaderProgram:(GLProgram *)shaderProgram;
- (void)setContextShaderProgram:(GLProgram *)shaderProgram;
+ (GLint)maximumTextureSizeForThisDevice;
+ (GLint)maximumTextureUnitsForThisDevice;
+ (GLint)maximumVaryingVectorsForThisDevice;
+ (BOOL)deviceSupportsOpenGLESExtension:(NSString *)extension;
+ (BOOL)deviceSupportsRedTextures;
+ (BOOL)deviceSupportsFramebufferReads;
+ (CGSize)sizeThatFitsWithinATextureForSize:(CGSize)inputSize;
- (void)presentBufferForDisplay;
- (GLProgram *)programForVertexShaderString:(NSString *)vertexShaderString fragmentShaderString:(NSString *)fragmentShaderString;
- (void)useSharegroup:(EAGLSharegroup *)sharegroup;
+ (BOOL)supportsFastTextureUpload;
完整代码
#import"GLProgram.h"#import"GPUImageFramebuffer.h"#import"GPUImageFramebufferCache.h"#defineGPUImageRotationSwapsWidthAndHeight(rotation) ((rotation) == kGPUImageRotateLeft || (rotation) == kGPUImageRotateRight || (rotation) == kGPUImageRotateRightFlipVertical || (rotation) == kGPUImageRotateRightFlipHorizontal)typedefenum{ kGPUImageNoRotation, kGPUImageRotateLeft, kGPUImageRotateRight, kGPUImageFlipVertical, kGPUImageFlipHorizonal, kGPUImageRotateRightFlipVertical, kGPUImageRotateRightFlipHorizontal, kGPUImageRotate180 } GPUImageRotationMode;
@interface GPUImageContext : NSObject
@property(readonly, nonatomic) dispatch_queue_t contextQueue;
@property(readwrite, retain, nonatomic) GLProgram*currentShaderProgram;
@property(readonly, retain, nonatomic) EAGLContext *context;
@property(readonly) CVOpenGLESTextureCacheRef coreVideoTextureCache;
@property(readonly) GPUImageFramebufferCache *framebufferCache;+ (void*)contextKey;+ (GPUImageContext *)sharedImageProcessingContext;+(dispatch_queue_t)sharedContextQueue;+ (GPUImageFramebufferCache *)sharedFramebufferCache;+ (void)useImageProcessingContext;- (void)useAsCurrentContext;+ (void)setActiveShaderProgram:(GLProgram *)shaderProgram;- (void)setContextShaderProgram:(GLProgram *)shaderProgram;+(GLint)maximumTextureSizeForThisDevice;+(GLint)maximumTextureUnitsForThisDevice;+(GLint)maximumVaryingVectorsForThisDevice;+ (BOOL)deviceSupportsOpenGLESExtension:(NSString *)extension;+(BOOL)deviceSupportsRedTextures;+(BOOL)deviceSupportsFramebufferReads;+(CGSize)sizeThatFitsWithinATextureForSize:(CGSize)inputSize;- (void)presentBufferForDisplay;- (GLProgram *)programForVertexShaderString:(NSString *)vertexShaderString fragmentShaderString:(NSString *)fragmentShaderString;- (void)useSharegroup:(EAGLSharegroup *)sharegroup;//Manage fast texture upload+(BOOL)supportsFastTextureUpload;
@end
@protocol GPUImageInput<NSObject>
- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex;-(NSInteger)nextAvailableTextureIndex;- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex;- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex;-(CGSize)maximumOutputSize;- (void)endProcessing;-(BOOL)shouldIgnoreUpdatesToThisTarget;-(BOOL)enabled;-(BOOL)wantsMonoChromeInput;- (void)setCurrentlyReceivingMonochromeInput:(BOOL)newValue;
@end
View Code
#import"GPUImageContext.h"#import<OpenGLES/EAGLDrawable.h>#import<AVFoundation/AVFoundation.h>#defineMAXSHADERPROGRAMSALLOWEDINCACHE 40@interface GPUImageContext()
{
NSMutableDictionary*shaderProgramCache;
NSMutableArray*shaderProgramUsageHistory;
EAGLSharegroup*_sharegroup;
}
@end
@implementation GPUImageContext
@synthesize context=_context;
@synthesize currentShaderProgram=_currentShaderProgram;
@synthesize contextQueue=_contextQueue;
@synthesize coreVideoTextureCache=_coreVideoTextureCache;
@synthesize framebufferCache=_framebufferCache;staticvoid*openGLESContextQueueKey;-(id)init;
{if(!(self =[super init]))
{returnnil;
}
openGLESContextQueueKey= &openGLESContextQueueKey;
_contextQueue= dispatch_queue_create("com.sunsetlakesoftware.GPUImage.openGLESContextQueue", NULL);#ifOS_OBJECT_USE_OBJCdispatch_queue_set_specific(_contextQueue, openGLESContextQueueKey, (__bridgevoid*)self, NULL);#endifshaderProgramCache=[[NSMutableDictionary alloc] init];
shaderProgramUsageHistory=[[NSMutableArray alloc] init];returnself;
}+ (void*)contextKey {returnopenGLESContextQueueKey;
}//Based on Colin Wheeler's example here:http://cocoasamurai.blogspot.com/2011/04/singletons-your-doing-them-wrong.html+ (GPUImageContext *)sharedImageProcessingContext;
{staticdispatch_once_t pred;staticGPUImageContext *sharedImageProcessingContext =nil;
dispatch_once(&pred, ^{
sharedImageProcessingContext= [[[selfclass] alloc] init];
});returnsharedImageProcessingContext;
}+(dispatch_queue_t)sharedContextQueue;
{return[[self sharedImageProcessingContext] contextQueue];
}+ (GPUImageFramebufferCache *)sharedFramebufferCache;
{return[[self sharedImageProcessingContext] framebufferCache];
}+ (void)useImageProcessingContext;
{
[[GPUImageContext sharedImageProcessingContext] useAsCurrentContext];
}- (void)useAsCurrentContext;
{
EAGLContext*imageProcessingContext =[self context];if([EAGLContext currentContext] !=imageProcessingContext)
{
[EAGLContext setCurrentContext:imageProcessingContext];
}
}+ (void)setActiveShaderProgram:(GLProgram *)shaderProgram;
{
GPUImageContext*sharedContext =[GPUImageContext sharedImageProcessingContext];
[sharedContext setContextShaderProgram:shaderProgram];
}- (void)setContextShaderProgram:(GLProgram *)shaderProgram;
{
EAGLContext*imageProcessingContext =[self context];if([EAGLContext currentContext] !=imageProcessingContext)
{
[EAGLContext setCurrentContext:imageProcessingContext];
}if(self.currentShaderProgram !=shaderProgram)
{
self.currentShaderProgram=shaderProgram;
[shaderProgram use];
}
}+(GLint)maximumTextureSizeForThisDevice;
{staticdispatch_once_t pred;staticGLint maxTextureSize =0;
dispatch_once(&pred, ^{
[self useImageProcessingContext];
glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxTextureSize);
});returnmaxTextureSize;
}+(GLint)maximumTextureUnitsForThisDevice;
{staticdispatch_once_t pred;staticGLint maxTextureUnits =0;
dispatch_once(&pred, ^{
[self useImageProcessingContext];
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&maxTextureUnits);
});returnmaxTextureUnits;
}+(GLint)maximumVaryingVectorsForThisDevice;
{staticdispatch_once_t pred;staticGLint maxVaryingVectors =0;
dispatch_once(&pred, ^{
[self useImageProcessingContext];
glGetIntegerv(GL_MAX_VARYING_VECTORS,&maxVaryingVectors);
});returnmaxVaryingVectors;
}+ (BOOL)deviceSupportsOpenGLESExtension:(NSString *)extension;
{staticdispatch_once_t pred;staticNSArray *extensionNames =nil;//Cache extensions for later quick reference, since this won't change for a given devicedispatch_once(&pred, ^{
[GPUImageContext useImageProcessingContext];
NSString*extensionsString = [NSString stringWithCString:(constchar*)glGetString(GL_EXTENSIONS) encoding:NSASCIIStringEncoding];
extensionNames= [extensionsString componentsSeparatedByString:@""];
});return[extensionNames containsObject:extension];
}//http://www.khronos.org/registry/gles/extensions/EXT/EXT_texture_rg.txt+(BOOL)deviceSupportsRedTextures;
{staticdispatch_once_t pred;staticBOOL supportsRedTextures =NO;
dispatch_once(&pred, ^{
supportsRedTextures= [GPUImageContext deviceSupportsOpenGLESExtension:@"GL_EXT_texture_rg"];
});returnsupportsRedTextures;
}+(BOOL)deviceSupportsFramebufferReads;
{staticdispatch_once_t pred;staticBOOL supportsFramebufferReads =NO;
dispatch_once(&pred, ^{
supportsFramebufferReads= [GPUImageContext deviceSupportsOpenGLESExtension:@"GL_EXT_shader_framebuffer_fetch"];
});returnsupportsFramebufferReads;
}+(CGSize)sizeThatFitsWithinATextureForSize:(CGSize)inputSize;
{
GLint maxTextureSize=[self maximumTextureSizeForThisDevice];if( (inputSize.width < maxTextureSize) && (inputSize.height <maxTextureSize) )
{returninputSize;
}
CGSize adjustedSize;if(inputSize.width >inputSize.height)
{
adjustedSize.width=(CGFloat)maxTextureSize;
adjustedSize.height= ((CGFloat)maxTextureSize / inputSize.width) *inputSize.height;
}else{
adjustedSize.height=(CGFloat)maxTextureSize;
adjustedSize.width= ((CGFloat)maxTextureSize / inputSize.height) *inputSize.width;
}returnadjustedSize;
}- (void)presentBufferForDisplay;
{
[self.context presentRenderbuffer:GL_RENDERBUFFER];
}- (GLProgram *)programForVertexShaderString:(NSString *)vertexShaderString fragmentShaderString:(NSString *)fragmentShaderString;
{
NSString*lookupKeyForShaderProgram = [NSString stringWithFormat:@"V: %@ - F: %@", vertexShaderString, fragmentShaderString];
GLProgram*programFromCache =[shaderProgramCache objectForKey:lookupKeyForShaderProgram];if(programFromCache ==nil)
{
programFromCache=[[GLProgram alloc] initWithVertexShaderString:vertexShaderString fragmentShaderString:fragmentShaderString];
[shaderProgramCache setObject:programFromCache forKey:lookupKeyForShaderProgram];//[shaderProgramUsageHistory addObject:lookupKeyForShaderProgram];//if ([shaderProgramUsageHistory count] >= MAXSHADERPROGRAMSALLOWEDINCACHE)//{//for (NSUInteger currentShaderProgramRemovedFromCache = 0; currentShaderProgramRemovedFromCache < 10; currentShaderProgramRemovedFromCache++)//{//NSString *shaderProgramToRemoveFromCache = [shaderProgramUsageHistory objectAtIndex:0];//[shaderProgramUsageHistory removeObjectAtIndex:0];//[shaderProgramCache removeObjectForKey:shaderProgramToRemoveFromCache];//}//}}returnprogramFromCache;
}- (void)useSharegroup:(EAGLSharegroup *)sharegroup;
{
NSAssert(_context== nil,@"Unable to use a share group when the context has already been created. Call this method before you use the context for the first time.");
_sharegroup=sharegroup;
}- (EAGLContext *)createContext;
{
EAGLContext*context =[[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:_sharegroup];
NSAssert(context!= nil,@"Unable to create an OpenGL ES 2.0 context. The GPUImage framework requires OpenGL ES 2.0 support to work.");returncontext;
}#pragmamark -#pragmamark Manage fast texture upload
+(BOOL)supportsFastTextureUpload;
{#ifTARGET_IPHONE_SIMULATORreturnNO;#else#pragmaclang diagnostic push#pragmaclang diagnostic ignored "-Wtautological-pointer-compare"return(CVOpenGLESTextureCacheCreate !=NULL);#pragmaclang diagnostic pop#endif}#pragmamark -#pragmamarkaccessors
- (EAGLContext *)context;
{if(_context ==nil)
{
_context=[self createContext];
[EAGLContext setCurrentContext:_context];//Set up a few global settings for the image processing pipelineglDisable(GL_DEPTH_TEST);
}return_context;
}-(CVOpenGLESTextureCacheRef)coreVideoTextureCache;
{if(_coreVideoTextureCache ==NULL)
{#ifdefined(__IPHONE_6_0)CVReturn err= CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, [self context], NULL, &_coreVideoTextureCache);#elseCVReturn err= CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, (__bridgevoid*)[self context], NULL, &_coreVideoTextureCache);#endifif(err)
{
NSAssert(NO,@"Error at CVOpenGLESTextureCacheCreate %d", err);
}
}return_coreVideoTextureCache;
}- (GPUImageFramebufferCache *)framebufferCache;
{if(_framebufferCache ==nil)
{
_framebufferCache=[[GPUImageFramebufferCache alloc] init];
}return_framebufferCache;
}
@end
View Code