GPUImage源码阅读(一):CVOpenGLESTextureCache 理解

对于 iOS 5.0+ 的设备,Core Video 允许 OpenGL ES 的 texture 和一个 image buffer 绑定,从而省略掉创建 texture 的步骤,也方便对 image buffer 操作,例如以多种格式读取其中的数据而不是用 glReadPixels 这样比较费时的方法。Core Video 中的 OpenGL ES texture 类型为 CVOpenGLESTextureRef,定义为

A texture-based image buffer that supplies source image data to OpenGL ES.

image buffer 类型为 CVImageBufferRef,在文档中可以看到两个类型其实是一回事:

typedef CVImageBufferRef CVOpenGLESTextureRef;

这些 texture 是由 CVOpenGLESTextureCache 缓存、管理的。可以用 CVOpenGLESTextureCacheCreateTextureFromImage 来从 image buffer 得到 texture 并将两者绑定,该 texture 可能是新建的或缓存的但未使用的。用 CVOpenGLESTextureCacheFlush 来清理未使用的缓存。

以上的 image buffer 需要满足一定条件:

To create a CVOpenGLESTexture object successfully, the pixel buffer passed to CVOpenGLESTextureCacheCreateTextureFromImage() must be backed by an IOSurface.

camera API 得到的 image buffer(CVPixelBufferRef)已经满足条件,在 Apple 的官方 sample code 中有从视频文件的一帧 image buffer 映射到相应 texture 并在 shader 中使用的示例。

但如果要自己创建空的 image buffer 并和 texture 绑定用来 render,那么创建时需要为 dictionary 指定一个特殊的 key:kCVPixelBufferIOSurfacePropertiesKey。代码示例:

CFDictionaryRef empty; // empty value for attr value.
CFMutableDictionaryRef attrs;
empty = CFDictionaryCreate(kCFAllocatorDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); // our empty IOSurface properties dictionary
attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(attrs, kCVPixelBufferIOSurfacePropertiesKey, empty);
  
CVPixelBufferRef renderTarget;
CVReturn err = CVPixelBufferCreate(kCFAllocatorDefault, (int)_size.width, (int)_size.height, kCVPixelFormatType_32BGRA, attrs, &renderTarget);

接下来的使用方法就和 sample code 中类似了。

参考:

  1. CVOpenGLESTextureCache
  2. Rendering to a texture with iOS 5 texture cache api
  3. Creating IOSurface-backed CVPixelBuffers for accessing video data in OpenGL ES

你可能感兴趣的:(GPUImage源码阅读(一):CVOpenGLESTextureCache 理解)