GPUImage源码解读之GPUImageFramebuffer
简介
OpenGL ES的FrameBuffer是渲染发生的地方,普通的2D图形的渲染默认发生在屏幕上;而三维的图形渲染则除了包括像素点的颜色,还有Depth Buffer,Stencil Buffer等其他空间。因此,FrameBuffer就是一个这些Buffer的一个集合。
默认情况下,FrameBuffer存在于现存中,但是当需要进行多次渲染或者离屏渲染的时候,可以通过创建一个离屏的FrameBuffer进行渲染。当需要渲染3D效果时,除了创建frameBuffer以外,还需要创建相应的Render Buffer, Depth Buffer, Stencil Buffer,并且将它们attach到frameBuffer上;而当只需要渲染2D图形时,可以直接生成一个Texture,并且将FrameBuffer渲染的结果放入Texture中。
生成一个FrameBuffer的代码:
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
由于存在离屏渲染的情况,实际渲染开始之前,需要先激活目标FrameBuffer,而在渲染完成之后,需要将FrameBuffer绑定为0,回到默认的FrameBuffer,才能够显示在屏幕上:
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
//Rendering Code
glBindFramebuffer(GL_FRAMEBUFFER, 0);
如果要渲染一个2D图像到一个Texture上,则还需要先生成一个Texture,并且将Texture绑定到FrameBuffer上。当使用FrameBuffer进行流的传递的时候,则可以使用这个Texture:
glActiveTexture(GL_TEXTURE1);
glGenTextures(1, &_texture);
glBindTexture(GL_TEXTURE_2D, _texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// This is necessary for non-power-of-two textures
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, _texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)_size.width, (int)_size.height, 0,GL_RGBA, GL_UNSIGNED_BYTE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0);
GPUImageFrameBuffer
GPUImageFrameBuffer不只是简单的对OpenGL ES的FrameBuffer的对象化封装,而是一个对渲染对象的对象化封装。它生成的可以是一个带有Texture作为Attachment的FrameBuffer,也可以仅仅生成一个Texture作为渲染对象。它的主要功能有:
- 生成渲染对象,FrameBuffer或者Texture,带的参数包括size和texture option,这两个参数主要是用于FrameBuffer的重用,GPUImageFramebufferCache中会介绍到:
- (id)initWithSize:(CGSize)framebufferSize;
- (id)initWithSize:(CGSize)framebufferSize textureOptions:(GPUTextureOptions)fboTextureOptions onlyTexture:(BOOL)onlyGenerateTexture;
- (id)initWithSize:(CGSize)framebufferSize overriddenTexture:(GLuint)inputTexture;
- FrameBuffer的管理,在渲染的时候激活frameBuffer:
- (void)activateFramebuffer;
- FrameBuffer的引用计数。同样用于FrameBuffer的重用,GPUImageFramebufferCache会详细介绍:
- (void)lock;
- (void)unlock;
- (void)clearAllLocks;
- (void)disableReferenceCounting;
- (void)enableReferenceCounting;
- 从FrameBuffer中生成图片或者源数据:
- (CGImageRef)newCGImageFromFramebufferContents;
- (GLubyte *)byteBuffer;
GPUImageFrameBuffer的引用计数
由于GPUImageFrameBuffer需要重用,因此,当FrameBuffer的引用为0的时候,这个FrameBuffer就会被放到Cache中,来给其他的需要的地方进行使用。因此作者给GPUImageFrameBuffer引入了引用计数的概念。
引用计数的概念其实和OC自带的MRC有点类似,每当一个地方需要使用这个FrameBuffer的时候,手动调用lock方法,使引用计数+1;当渲染完毕或者这个FrameBuffer使用完毕的时候,手动调用unlock方法,使引用计数-1;当引用计数为0的时候,FrameBuffer会被归还到Cache中。
调用增加FrameBuffer引用计数方法的地方:
- 每次从Cache中获取到一个FrameBuffer的时候,都会调用一次lock方法,因为既然获取了FrameBuffer就是需要使用它进行渲染的时候,因此这个是最合适的调用时机;
- 将一个FrameBuffer作为Output传给下一个Input的时候,会调用setInputFrameBuffer:atIndex:方法。因为这个FrameBuffer会被传递给下一个input进行使用,因此我们需要手动的将这个FrameBuffer的引用计数+1;
- 如果需要将一个Filter的输出进行截图的话(usingNextFrameForImageCapture == YES),也需要手动调用lock方法。因为默认情况下,当下一个input渲染完成之后,就会释放这个FrameBuffer。如果你需要对当前的Filter的输出进行截图的话,则需要保留住这个FrameBuffer。
调用减少FrameBuffer引用计数方法的地方:
- 在renderToTextureWithVertices:textureCoordinates:渲染完成之后,需要将从上一个Output中传过来的所有InputFrameBuffer都unlock掉;
- 在informTargetsAboutNewFrameAtTime:通知下一个input之后,需要将当前的这个Output中的outputFrameBuffer给unlock掉;
不需要引用计数的情况:
在有些地方我们是不需要使用引用计数的,比如GPUImagePicture。因为生成了Picture之后,它只会有一个outputFrameBuffer。而且这个frameBuffer只有在GPUImagePicture初始化的时候生成。因此这个FrameBuffer不能被释放,否则以后它的target就不能使用了。因此GPUImagePicture初始化的时候调用了disableReferenceCounting方法。只有当这个GPUImagePicture在dealloc的时候才能被释放。
GPUImage源码解读之GPUImageFramebuffer的更多相关文章
- GPUImage源码解读之GPUImageFramebufferCache
简介 由于GPUImage添加滤镜可以形成一个FilterChain,因此,在渲染的过程中,可能会需要很多个FrameBuffer,但是正如上文所说,每生成一个FrameBuffer都需要占用一定的内 ...
- GPUImage源码解读之GLProgram
简述 GLProgram是GPUImage中代表openGL ES 中的program,具有glprogram功能.其实是作者对OpenGL ES program的面向对象封装 初始化 - (id)i ...
- GPUImage源码解读之GPUImageContext
GPUImageContext类,提供OpenGL ES基本上下文,GPUImage相关处理线程,GLProgram缓存.帧缓存.由于是上下文对象,因此该模块提供的更多是存取.设置相关的方法. 属性列 ...
- SDWebImage源码解读之SDWebImageDownloaderOperation
第七篇 前言 本篇文章主要讲解下载操作的相关知识,SDWebImageDownloaderOperation的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...
- SDWebImage源码解读 之 NSData+ImageContentType
第一篇 前言 从今天开始,我将开启一段源码解读的旅途了.在这里先暂时不透露具体解读的源码到底是哪些?因为也可能随着解读的进行会更改计划.但能够肯定的是,这一系列之中肯定会有Swift版本的代码. 说说 ...
- SDWebImage源码解读 之 UIImage+GIF
第二篇 前言 本篇是和GIF相关的一个UIImage的分类.主要提供了三个方法: + (UIImage *)sd_animatedGIFNamed:(NSString *)name ----- 根据名 ...
- SDWebImage源码解读 之 SDWebImageCompat
第三篇 前言 本篇主要解读SDWebImage的配置文件.正如compat的定义,该配置文件主要是兼容Apple的其他设备.也许我们真实的开发平台只有一个,但考虑各个平台的兼容性,对于框架有着很重要的 ...
- SDWebImage源码解读_之SDWebImageDecoder
第四篇 前言 首先,我们要弄明白一个问题? 为什么要对UIImage进行解码呢?难道不能直接使用吗? 其实不解码也是可以使用的,假如说我们通过imageNamed:来加载image,系统默认会在主线程 ...
- SDWebImage源码解读之SDWebImageCache(上)
第五篇 前言 本篇主要讲解图片缓存类的知识,虽然只涉及了图片方面的缓存的设计,但思想同样适用于别的方面的设计.在架构上来说,缓存算是存储设计的一部分.我们把各种不同的存储内容按照功能进行切割后,图片缓 ...
随机推荐
- 01_dubbo实例_服务分组
[为什么要服务分组?] 当一个接口有多种实现时,可以用group区分. [ Provider 的配置信息] <?xml version="1.0" encoding=&quo ...
- c++开发ocx入门实践一
原文:http://blog.csdn.net/yhhyhhyhhyhh/article/details/51374200 最近项目中利用ocx封装了底层视频播放及处理的控件,以供c#和web调用.对 ...
- Http重要知识点
- 【转】ubunt 安装 yum出现 ubuntu 解决“无法获得锁 /var/lib/dpkg/lock -open (11:资源暂时不可用)”的方法
今天本来是用xshell 链接本地的linux的,然而链接的时候没有主动弹出输入 用户名和密码的对话框,google搜了下,遇到了上面的问题. 解决办法如下:1.终端输入 ps aux ,列出进程. ...
- geoserver 知识小计
http://localhost:8888/geoserver/wms?service=WMS&request=GetCapabilities 这个地址用于获取发布的WMS服务的属性,用于获取 ...
- androidcarsh
package com.oval.cft; import java.io.File;import java.io.FileOutputStream;import java.io.PrintWriter ...
- scp 上传和下载文件
mac和linux自带scp命令,windows的话请考虑gitbash或者专业linux工具 (默认端口为22,所以-p可不写) 上传文件 scp -p /home/lnmp.gz root@ip: ...
- 如何在 Linux 虚拟机上扩展根文件系统
问题描述 通过 Azure 平台部署的 Linux 虚拟机默认的根文件系统容量有限,需要进行扩展. 问题分析 由于 Azure 平台部署的 Linux 虚拟机默认根文件系统容量比较小,客户在使用过程中 ...
- Maximum Subarray解题报告zz
http://fisherlei.blogspot.com/2012/12/leetcode-maximum-subarray.html Find the contiguous subarray wi ...
- pt-mysql-summary
pt-mysql-summary主要用来输出MySQL的基本信息,可以作为数据库巡检以及刚开始熟悉数据库环境时候进行使用: [root@mxqmongodb2 bin]# ./pt-mysql-sum ...