[关闭]
@qidiandasheng 2020-07-13T14:47:49.000000Z 字数 4220 阅读 1513

GPUImage解析(三):GPUImageContext

音视频


介绍

GPUImageContext类,提供OpenGL ES基本上下文,GPUImage相关处理线程,GLProgram缓存、帧缓存。由于是上下文对象,因此该模块提供的更多是存取、设置相关的方法。

GLProgram与着色器程序创建息息相关,其中包括创建、编译、链接、使用等过程。

属性列表

  1. // GPUImage处理OpenGL绘制的相关队列,串行队列
  2. @property(readonly, nonatomic) dispatch_queue_t contextQueue;
  3. // 当前使用的着色器程序
  4. @property(readwrite, retain, nonatomic) GLProgram *currentShaderProgram;
  5. // OpenGLES上下文对象
  6. @property(readonly, retain, nonatomic) EAGLContext *context;
  7. // CoreVideo中的纹理缓存
  8. @property(readonly) CVOpenGLESTextureCacheRef coreVideoTextureCache;
  9. // 帧缓存
  10. @property(readonly) GPUImageFramebufferCache *framebufferCache;

方法列表

  1. // 获取队列标识
  2. + (void *)contextKey;
  3. // 单例对象
  4. + (GPUImageContext *)sharedImageProcessingContext;
  5. // 获取处理队列
  6. + (dispatch_queue_t)sharedContextQueue;
  7. // 帧缓存
  8. + (GPUImageFramebufferCache *)sharedFramebufferCache;
  9. // 设置当前上下文
  10. + (void)useImageProcessingContext;
  11. - (void)useAsCurrentContext;
  12. // 设置当前的GL程序
  13. + (void)setActiveShaderProgram:(GLProgram *)shaderProgram;
  14. - (void)setContextShaderProgram:(GLProgram *)shaderProgram;
  15. // 获取设备OpenGLES相关特性的支持情况
  16. + (GLint)maximumTextureSizeForThisDevice;
  17. + (GLint)maximumTextureUnitsForThisDevice;
  18. + (GLint)maximumVaryingVectorsForThisDevice;
  19. + (BOOL)deviceSupportsOpenGLESExtension:(NSString *)extension;
  20. + (BOOL)deviceSupportsRedTextures;
  21. + (BOOL)deviceSupportsFramebufferReads;
  22. // 纹理大小调整,保证纹理不超过OpenGLES支持最大的尺寸
  23. + (CGSize)sizeThatFitsWithinATextureForSize:(CGSize)inputSize;
  24. // 将渲染缓存呈现在设备上
  25. - (void)presentBufferForDisplay;
  26. // 创建GLProgram,首先在缓存中查找,如果没有则创建
  27. - (GLProgram *)programForVertexShaderString:(NSString *)vertexShaderString fragmentShaderString:(NSString *)fragmentShaderString;
  28. // 创建Sharegroup
  29. - (void)useSharegroup:(EAGLSharegroup *)sharegroup;
  30. // Manage fast texture upload
  31. + (BOOL)supportsFastTextureUpload;

初始化

  1. - (id)init;
  2. {
  3. if (!(self = [super init]))
  4. {
  5. return nil;
  6. }
  7. // 创建OpenGL渲染队列
  8. openGLESContextQueueKey = &openGLESContextQueueKey;
  9. _contextQueue = dispatch_queue_create("com.sunsetlakesoftware.GPUImage.openGLESContextQueue", GPUImageDefaultQueueAttribute());
  10. #if OS_OBJECT_USE_OBJC
  11. // 设置队列标识
  12. dispatch_queue_set_specific(_contextQueue, openGLESContextQueueKey, (__bridge void *)self, NULL);
  13. #endif
  14. // 初始化着色器缓存相关数组
  15. shaderProgramCache = [[NSMutableDictionary alloc] init];
  16. shaderProgramUsageHistory = [[NSMutableArray alloc] init];
  17. return self;
  18. }

调整纹理大小

  1. + (CGSize)sizeThatFitsWithinATextureForSize:(CGSize)inputSize;
  2. {
  3. GLint maxTextureSize = [self maximumTextureSizeForThisDevice];
  4. if ( (inputSize.width < maxTextureSize) && (inputSize.height < maxTextureSize) )
  5. {
  6. return inputSize;
  7. }
  8. CGSize adjustedSize;
  9. if (inputSize.width > inputSize.height)
  10. {
  11. adjustedSize.width = (CGFloat)maxTextureSize;
  12. adjustedSize.height = ((CGFloat)maxTextureSize / inputSize.width) * inputSize.height;
  13. }
  14. else
  15. {
  16. adjustedSize.height = (CGFloat)maxTextureSize;
  17. adjustedSize.width = ((CGFloat)maxTextureSize / inputSize.height) * inputSize.width;
  18. }
  19. return adjustedSize;
  20. }

获取OpenGLES支持的最大纹理尺寸

  1. + (GLint)maximumTextureSizeForThisDevice;
  2. {
  3. static dispatch_once_t pred;
  4. static GLint maxTextureSize = 0;
  5. dispatch_once(&pred, ^{
  6. [self useImageProcessingContext];
  7. glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
  8. });
  9. return maxTextureSize;
  10. }

创建GLProgram,首先在缓存中查找,如果没有则创建

  1. - (GLProgram *)programForVertexShaderString:(NSString *)vertexShaderString fragmentShaderString:(NSString *)fragmentShaderString;
  2. {
  3. NSString *lookupKeyForShaderProgram = [NSString stringWithFormat:@"V: %@ - F: %@", vertexShaderString, fragmentShaderString];
  4. GLProgram *programFromCache = [shaderProgramCache objectForKey:lookupKeyForShaderProgram];
  5. if (programFromCache == nil)
  6. {
  7. programFromCache = [[GLProgram alloc] initWithVertexShaderString:vertexShaderString fragmentShaderString:fragmentShaderString];
  8. [shaderProgramCache setObject:programFromCache forKey:lookupKeyForShaderProgram];
  9. }
  10. return programFromCache;
  11. }

创建EAGLContext上下文对象

使用的是kEAGLRenderingAPIOpenGLES2的API也就是OpenGL ES 2.0

  1. - (EAGLContext *)createContext;
  2. {
  3. EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:_sharegroup];
  4. NSAssert(context != nil, @"Unable to create an OpenGL ES 2.0 context. The GPUImage framework requires OpenGL ES 2.0 support to work.");
  5. return context;
  6. }

设置当前的上下文对象,以及当前的着色器程序

  1. - (void)setContextShaderProgram:(GLProgram *)shaderProgram;
  2. {
  3. EAGLContext *imageProcessingContext = [self context];
  4. if ([EAGLContext currentContext] != imageProcessingContext)
  5. {
  6. [EAGLContext setCurrentContext:imageProcessingContext];
  7. }
  8. if (self.currentShaderProgram != shaderProgram)
  9. {
  10. self.currentShaderProgram = shaderProgram;
  11. [shaderProgram use];
  12. }
  13. }

参考

GPUImage源码解读之GPUImageContext

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注