• GPUImage源码解读之GPUImageContext


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

    • 属性列表
    // GPUImage处理OpenGL绘制的相关队列,串行队列
    @property(readonly, nonatomic) dispatch_queue_t contextQueue;
    // 当前使用的着色器程序
    @property(readwrite, retain, nonatomic) GLProgram *currentShaderProgram;
    // OpenGLES上下文对象
    @property(readonly, retain, nonatomic) EAGLContext *context;
    // CoreVideo中的纹理缓存
    @property(readonly) CVOpenGLESTextureCacheRef coreVideoTextureCache;
    // 帧缓存
    @property(readonly) GPUImageFramebufferCache *framebufferCache;
    
    • 初始化过程。在初始化的过程中通过dispatch_queue_set_specific设置队列标识
    - (id)init;
    {
        if (!(self = [super init]))
        {
            return nil;
        }
        
        // 创建OpenGL渲染队列
        openGLESContextQueueKey = &openGLESContextQueueKey;
        _contextQueue = dispatch_queue_create("com.sunsetlakesoftware.GPUImage.openGLESContextQueue", GPUImageDefaultQueueAttribute());
        
    #if OS_OBJECT_USE_OBJC
        // 设置队列标识
        dispatch_queue_set_specific(_contextQueue, openGLESContextQueueKey, (__bridge void *)self, NULL);
    #endif
        // 初始化着色器缓存相关数组
        shaderProgramCache = [[NSMutableDictionary alloc] init];
        shaderProgramUsageHistory = [[NSMutableArray alloc] init];
        
        return self;
    }
    
    • 方法列表
    // 获取队列标识
    + (void *)contextKey;
    // 单例对象
    + (GPUImageContext *)sharedImageProcessingContext;
    // 获取处理队列
    + (dispatch_queue_t)sharedContextQueue;
    // 帧缓存
    + (GPUImageFramebufferCache *)sharedFramebufferCache;
    // 设置当前上下文
    + (void)useImageProcessingContext;
    - (void)useAsCurrentContext;
    // 设置当前的GL程序
    + (void)setActiveShaderProgram:(GLProgram *)shaderProgram;
    - (void)setContextShaderProgram:(GLProgram *)shaderProgram;
    // 获取设备OpenGLES相关特性的支持情况
    + (GLint)maximumTextureSizeForThisDevice;
    + (GLint)maximumTextureUnitsForThisDevice;
    + (GLint)maximumVaryingVectorsForThisDevice;
    + (BOOL)deviceSupportsOpenGLESExtension:(NSString *)extension;
    + (BOOL)deviceSupportsRedTextures;
    + (BOOL)deviceSupportsFramebufferReads;
    // 纹理大小调整,保证纹理不超过OpenGLES支持最大的尺寸
    + (CGSize)sizeThatFitsWithinATextureForSize:(CGSize)inputSize;
    // 将渲染缓存呈现在设备上
    - (void)presentBufferForDisplay;
    // 创建GLProgram,首先在缓存中查找,如果没有则创建
    - (GLProgram *)programForVertexShaderString:(NSString *)vertexShaderString fragmentShaderString:(NSString *)fragmentShaderString;
    // 创建Sharegroup
    - (void)useSharegroup:(EAGLSharegroup *)sharegroup;
    // Manage fast texture upload
    + (BOOL)supportsFastTextureUpload;
    
    

    由于GPUImageContext相当于一个上下文对象,主要是管理其它的对象,因此该类没有太多复杂的业务,这里主要看一下几个方法:

    • 调整纹理大小,保证纹理不超过OpenGLES支持最大的尺寸:
    + (CGSize)sizeThatFitsWithinATextureForSize:(CGSize)inputSize;
    {
        GLint maxTextureSize = [self maximumTextureSizeForThisDevice]; 
        if ( (inputSize.width < maxTextureSize) && (inputSize.height < maxTextureSize) )
        {
            return inputSize;
        }
        
        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;
        }
    
        return adjustedSize;
    }
    
    • 获取OpenGLES支持的最大纹理尺寸
    + (GLint)maximumTextureSizeForThisDevice;
    {
        static dispatch_once_t pred;
        static GLint maxTextureSize = 0;
        
        dispatch_once(&pred, ^{
            [self useImageProcessingContext];
            glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
        });
    
        return maxTextureSize;
    }
    
    
    • 创建GLProgram,首先在缓存中查找,如果没有则创建
    - (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];
    //            }
    //        }
        }
        
        return programFromCache;
    }
    
    • 创建EAGLContext上下文对象,使用的是kEAGLRenderingAPIOpenGLES2的API也就是OpenGL ES 2.0
    - (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.");
        return context;
    }
    
    
    • 设置当前的上下文对象,以及当前的着色器程序
    - (void)setContextShaderProgram:(GLProgram *)shaderProgram;
    {
        EAGLContext *imageProcessingContext = [self context];
        if ([EAGLContext currentContext] != imageProcessingContext)
        {
            [EAGLContext setCurrentContext:imageProcessingContext];
        }
        
        if (self.currentShaderProgram != shaderProgram)
        {
            self.currentShaderProgram = shaderProgram;
            [shaderProgram use];
        }
    }
    

    总结

    GLProgram 与着色器程序创建息息相关,其中包括创建、编译、链接、使用等过程。
    GPUImageContext 是GPUImage的上下文对象,管理着OpenGLES上下文对象,管理着GL程序,管理着帧缓存等GPUImage中的基本组件。

  • 相关阅读:
    ES6 基础
    JavaScript 基础
    Java 虚拟机
    MinIO 搭建使用
    .NET 半天搭建Jenkins持续集成与自动化部署系统
    驱动领域DDD的微服务设计和开发实战
    走向架构师必备的技能
    分布式系统与消息的投递¶
    求数组的子数组之和的最大值
    KVO初探
  • 原文地址:https://www.cnblogs.com/tmacforever/p/9120536.html
Copyright © 2020-2023  润新知