GPUImageFramebuffer类用于管理帧缓冲对象,负责帧缓冲对象的创建和销毁,读取帧缓冲内容

  属性

  @property(readonly) CGSize size

  说明:只读属性,在实现中,设置缓冲区的size

 

  @property(readonly) GPUTextureOptions textureOptions

  说明:纹理的选项

 

  @property(readonly) GLuint texture

  说明:管理纹理

 

  @property(readonly) BOOL missingFramebuffer

  说明:指示是否丢失帧缓冲对象

  

  方法

   - (id)initWithSize:(CGSize)framebufferSize

    说明:创建一个size为framebufferSize大小的帧缓冲对象

    参数:framebuffer的size。

    返回:创建成功的帧缓冲对象。

    实现

- (id)initWithSize:(CGSize)framebufferSize;
{
GPUTextureOptions defaultTextureOptions;
defaultTextureOptions.minFilter = GL_LINEAR;
defaultTextureOptions.magFilter = GL_LINEAR;
defaultTextureOptions.wrapS = GL_CLAMP_TO_EDGE;
defaultTextureOptions.wrapT = GL_CLAMP_TO_EDGE;
defaultTextureOptions.internalFormat = GL_RGBA;
defaultTextureOptions.format = GL_BGRA;
defaultTextureOptions.type = GL_UNSIGNED_BYTE; if (!(self = [self initWithSize:framebufferSize textureOptions:defaultTextureOptions onlyTexture:NO]))
{
return nil;
} return self;
}

 

     - (id)initWithSize:(CGSize)framebufferSize textureOptions:(GPUTextureOptions)fboTextureOptions onlyTexture:(BOOL)onlyGenerateTexture

    说明:创建一个size为framebufferSize大小的帧缓冲对象

    参数:framebufferSize为framebuffer的size。fboTextureOptions是纹理的详细配置。onlyGenerateTexture说明是否只创建纹理而不创建陈帧缓冲对象。

    返回:创建成功的帧缓冲对象。

    实现

- (id)initWithSize:(CGSize)framebufferSize textureOptions:(GPUTextureOptions)fboTextureOptions onlyTexture:(BOOL)onlyGenerateTexture;
{
if (!(self = [super init]))
{
return nil;
} _textureOptions = fboTextureOptions;
_size = framebufferSize;
framebufferReferenceCount = ;
referenceCountingDisabled = NO;
_missingFramebuffer = onlyGenerateTexture; if (_missingFramebuffer)
{
runSynchronouslyOnVideoProcessingQueue(^{
[GPUImageContext useImageProcessingContext];
[self generateTexture];
framebuffer = ;
});
}
else
{
[self generateFramebuffer];
}
return self;
}

   - (id)initWithSize:(CGSize)framebufferSize overriddenTexture:(GLuint)inputTexture

    说明:创建一个size为framebufferSize大小的帧缓冲对象

    参数:inputTexture为输入的纹理,用于渲染图片。

    返回:创建成功的帧缓冲对象。

    实现

- (id)initWithSize:(CGSize)framebufferSize overriddenTexture:(GLuint)inputTexture;
{
if (!(self = [super init]))
{
return nil;
} GPUTextureOptions defaultTextureOptions;
defaultTextureOptions.minFilter = GL_LINEAR;
defaultTextureOptions.magFilter = GL_LINEAR;
defaultTextureOptions.wrapS = GL_CLAMP_TO_EDGE;
defaultTextureOptions.wrapT = GL_CLAMP_TO_EDGE;
defaultTextureOptions.internalFormat = GL_RGBA;
defaultTextureOptions.format = GL_BGRA;
defaultTextureOptions.type = GL_UNSIGNED_BYTE; _textureOptions = defaultTextureOptions;
_size = framebufferSize;
framebufferReferenceCount = ;
referenceCountingDisabled = YES; _texture = inputTexture; return self;
}

   - (void)activateFramebuffer

    说明:激活刚创建的framebuffer对象。只有调用它后,才会起作用。

    实现 

- (void)activateFramebuffer;
{
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glViewport(, , (int)_size.width, (int)_size.height);
}

   - (void)lock

    说明:引用计数管理 +1

    实现

- (void)lock;
{
if (referenceCountingDisabled)
{
return;
} framebufferReferenceCount++;
}

   - (void)unlock

    说明:引用计数管理 -1

    实现

- (void)unlock;
{
if (referenceCountingDisabled)
{
return;
} NSAssert(framebufferReferenceCount > , @"Tried to overrelease a framebuffer, did you forget to call -useNextFrameForImageCapture before using -imageFromCurrentFramebuffer?");
framebufferReferenceCount--;
if (framebufferReferenceCount < )
{
[[GPUImageContext sharedFramebufferCache] returnFramebufferToCache:self];
}
}

   - (void)clearAllLocks

    说明:引用计数管理 设置为0

    实现

- (void)clearAllLocks;
{
framebufferReferenceCount = ;
}

   - (void)disableReferenceCounting

    说明:引用计数管理 禁用引用计数

    实现

- (void)disableReferenceCounting;
{
referenceCountingDisabled = YES;
}

   - (void)enableReferenceCounting

    说明:引用计数管理 启用引用计数

    实现

- (void)enableReferenceCounting;
{
referenceCountingDisabled = NO;
}

   - (CGImageRef)newCGImageFromFramebufferContents

    说明:输出帧缓冲内容。【说明待更新......】

    实现

- (CGImageRef)newCGImageFromFramebufferContents;
{
// a CGImage can only be created from a 'normal' color texture
NSAssert(self.textureOptions.internalFormat == GL_RGBA, @"For conversion to a CGImage the output texture format for this filter must be GL_RGBA.");
NSAssert(self.textureOptions.type == GL_UNSIGNED_BYTE, @"For conversion to a CGImage the type of the output texture of this filter must be GL_UNSIGNED_BYTE."); __block CGImageRef cgImageFromBytes; runSynchronouslyOnVideoProcessingQueue(^{
[GPUImageContext useImageProcessingContext]; NSUInteger totalBytesForImage = (int)_size.width * (int)_size.height * ;
// It appears that the width of a texture must be padded out to be a multiple of 8 (32 bytes) if reading from it using a texture cache GLubyte *rawImagePixels; CGDataProviderRef dataProvider = NULL;
if ([GPUImageContext supportsFastTextureUpload])
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSUInteger paddedWidthOfImage = CVPixelBufferGetBytesPerRow(renderTarget) / 4.0;
NSUInteger paddedBytesForImage = paddedWidthOfImage * (int)_size.height * ; glFinish();
CFRetain(renderTarget); // I need to retain the pixel buffer here and release in the data source callback to prevent its bytes from being prematurely deallocated during a photo write operation
[self lockForReading];
rawImagePixels = (GLubyte *)CVPixelBufferGetBaseAddress(renderTarget);
dataProvider = CGDataProviderCreateWithData((__bridge_retained void*)self, rawImagePixels, paddedBytesForImage, dataProviderUnlockCallback);
[[GPUImageContext sharedFramebufferCache] addFramebufferToActiveImageCaptureList:self]; // In case the framebuffer is swapped out on the filter, need to have a strong reference to it somewhere for it to hang on while the image is in existence
#else
#endif
}
else
{
[self activateFramebuffer];
rawImagePixels = (GLubyte *)malloc(totalBytesForImage);
glReadPixels(, , (int)_size.width, (int)_size.height, GL_RGBA, GL_UNSIGNED_BYTE, rawImagePixels);
dataProvider = CGDataProviderCreateWithData(NULL, rawImagePixels, totalBytesForImage, dataProviderReleaseCallback);
[self unlock]; // Don't need to keep this around anymore
} CGColorSpaceRef defaultRGBColorSpace = CGColorSpaceCreateDeviceRGB(); if ([GPUImageContext supportsFastTextureUpload])
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
cgImageFromBytes = CGImageCreate((int)_size.width, (int)_size.height, , , CVPixelBufferGetBytesPerRow(renderTarget), defaultRGBColorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst, dataProvider, NULL, NO, kCGRenderingIntentDefault);
#else
#endif
}
else
{
cgImageFromBytes = CGImageCreate((int)_size.width, (int)_size.height, , , * (int)_size.width, defaultRGBColorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaLast, dataProvider, NULL, NO, kCGRenderingIntentDefault);
} // Capture image with current device orientation
CGDataProviderRelease(dataProvider);
CGColorSpaceRelease(defaultRGBColorSpace); }); return cgImageFromBytes;
}

   - (void)restoreRenderTarget

    说明:还原渲染目标对象

    实现

- (void)restoreRenderTarget;
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
[self unlockAfterReading];
CFRelease(renderTarget);
#else
#endif
}

   - (void)lockForReading

    说明:锁定PixelBuffer

    实现:

- (void)lockForReading
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
if ([GPUImageContext supportsFastTextureUpload])
{
if (readLockCount == )
{
CVPixelBufferLockBaseAddress(renderTarget, );
}
readLockCount++;
}
#endif
}

   - (void)unlockAfterReading

    说明:解锁PixelBuffer

- (void)unlockAfterReading
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
if ([GPUImageContext supportsFastTextureUpload])
{
NSAssert(readLockCount > , @"Unbalanced call to -[GPUImageFramebuffer unlockAfterReading]");
readLockCount--;
if (readLockCount == )
{
CVPixelBufferUnlockBaseAddress(renderTarget, );
}
}
#endif
}

   - (NSUInteger)bytesPerRow

    说明:获取pixel buffer的行字节数

    实现

- (NSUInteger)bytesPerRow;
{
if ([GPUImageContext supportsFastTextureUpload])
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
return CVPixelBufferGetBytesPerRow(renderTarget);
#else
return _size.width * ; // TODO: do more with this on the non-texture-cache side
#endif
}
else
{
return _size.width * ;
}
}

   - (GLubyte *)byteBuffer

    说明:获取pixel buffer的基地址

    实现

- (GLubyte *)byteBuffer;
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
[self lockForReading];
GLubyte * bufferBytes = CVPixelBufferGetBaseAddress(renderTarget);
[self unlockAfterReading];
return bufferBytes;
#else
return NULL; // TODO: do more with this on the non-texture-cache side
#endif
}

完整代码

#import <Foundation/Foundation.h>

#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
#else
#import <OpenGL/OpenGL.h>
#import <OpenGL/gl.h>
#endif #import <QuartzCore/QuartzCore.h>
#import <CoreMedia/CoreMedia.h> typedef struct GPUTextureOptions {
GLenum minFilter;
GLenum magFilter;
GLenum wrapS;
GLenum wrapT;
GLenum internalFormat;
GLenum format;
GLenum type;
} GPUTextureOptions; @interface GPUImageFramebuffer : NSObject @property(readonly) CGSize size;
@property(readonly) GPUTextureOptions textureOptions;
@property(readonly) GLuint texture;
@property(readonly) BOOL missingFramebuffer; // Initialization and teardown
- (id)initWithSize:(CGSize)framebufferSize;
- (id)initWithSize:(CGSize)framebufferSize textureOptions:(GPUTextureOptions)fboTextureOptions onlyTexture:(BOOL)onlyGenerateTexture;
- (id)initWithSize:(CGSize)framebufferSize overriddenTexture:(GLuint)inputTexture; // Usage
- (void)activateFramebuffer; // Reference counting
- (void)lock;
- (void)unlock;
- (void)clearAllLocks;
- (void)disableReferenceCounting;
- (void)enableReferenceCounting; // Image capture
- (CGImageRef)newCGImageFromFramebufferContents;
- (void)restoreRenderTarget; // Raw data bytes
- (void)lockForReading;
- (void)unlockAfterReading;
- (NSUInteger)bytesPerRow;
- (GLubyte *)byteBuffer; @end

 

#import "GPUImageFramebuffer.h"
#import "GPUImageOutput.h" @interface GPUImageFramebuffer()
{
GLuint framebuffer;
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
CVPixelBufferRef renderTarget;
CVOpenGLESTextureRef renderTexture;
NSUInteger readLockCount;
#else
#endif
NSUInteger framebufferReferenceCount;
BOOL referenceCountingDisabled;
} - (void)generateFramebuffer;
- (void)generateTexture;
- (void)destroyFramebuffer; @end void dataProviderReleaseCallback (void *info, const void *data, size_t size);
void dataProviderUnlockCallback (void *info, const void *data, size_t size); @implementation GPUImageFramebuffer @synthesize size = _size;
@synthesize textureOptions = _textureOptions;
@synthesize texture = _texture;
@synthesize missingFramebuffer = _missingFramebuffer; #pragma mark -
#pragma mark Initialization and teardown - (id)initWithSize:(CGSize)framebufferSize textureOptions:(GPUTextureOptions)fboTextureOptions onlyTexture:(BOOL)onlyGenerateTexture;
{
if (!(self = [super init]))
{
return nil;
} _textureOptions = fboTextureOptions;
_size = framebufferSize;
framebufferReferenceCount = ;
referenceCountingDisabled = NO;
_missingFramebuffer = onlyGenerateTexture; if (_missingFramebuffer)
{
runSynchronouslyOnVideoProcessingQueue(^{
[GPUImageContext useImageProcessingContext];
[self generateTexture];
framebuffer = ;
});
}
else
{
[self generateFramebuffer];
}
return self;
} - (id)initWithSize:(CGSize)framebufferSize overriddenTexture:(GLuint)inputTexture;
{
if (!(self = [super init]))
{
return nil;
} GPUTextureOptions defaultTextureOptions;
defaultTextureOptions.minFilter = GL_LINEAR;
defaultTextureOptions.magFilter = GL_LINEAR;
defaultTextureOptions.wrapS = GL_CLAMP_TO_EDGE;
defaultTextureOptions.wrapT = GL_CLAMP_TO_EDGE;
defaultTextureOptions.internalFormat = GL_RGBA;
defaultTextureOptions.format = GL_BGRA;
defaultTextureOptions.type = GL_UNSIGNED_BYTE; _textureOptions = defaultTextureOptions;
_size = framebufferSize;
framebufferReferenceCount = ;
referenceCountingDisabled = YES; _texture = inputTexture; return self;
} - (id)initWithSize:(CGSize)framebufferSize;
{
GPUTextureOptions defaultTextureOptions;
defaultTextureOptions.minFilter = GL_LINEAR;
defaultTextureOptions.magFilter = GL_LINEAR;
defaultTextureOptions.wrapS = GL_CLAMP_TO_EDGE;
defaultTextureOptions.wrapT = GL_CLAMP_TO_EDGE;
defaultTextureOptions.internalFormat = GL_RGBA;
defaultTextureOptions.format = GL_BGRA;
defaultTextureOptions.type = GL_UNSIGNED_BYTE; if (!(self = [self initWithSize:framebufferSize textureOptions:defaultTextureOptions onlyTexture:NO]))
{
return nil;
} return self;
} - (void)dealloc
{
[self destroyFramebuffer];
} #pragma mark -
#pragma mark Internal - (void)generateTexture;
{
glActiveTexture(GL_TEXTURE1);
glGenTextures(, &_texture);
glBindTexture(GL_TEXTURE_2D, _texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _textureOptions.minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _textureOptions.magFilter);
// This is necessary for non-power-of-two textures
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _textureOptions.wrapS);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _textureOptions.wrapT); // TODO: Handle mipmaps
} - (void)generateFramebuffer;
{
runSynchronouslyOnVideoProcessingQueue(^{
[GPUImageContext useImageProcessingContext]; glGenFramebuffers(, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); // By default, all framebuffers on iOS 5.0+ devices are backed by texture caches, using one shared cache
if ([GPUImageContext supportsFastTextureUpload])
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
CVOpenGLESTextureCacheRef coreVideoTextureCache = [[GPUImageContext sharedImageProcessingContext] coreVideoTextureCache];
// Code originally sourced from http://allmybrain.com/2011/12/08/rendering-to-a-texture-with-ios-5-texture-cache-api/ CFDictionaryRef empty; // empty value for attr value.
CFMutableDictionaryRef attrs;
empty = CFDictionaryCreate(kCFAllocatorDefault, NULL, NULL, , &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); // our empty IOSurface properties dictionary
attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, , &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(attrs, kCVPixelBufferIOSurfacePropertiesKey, empty); CVReturn err = CVPixelBufferCreate(kCFAllocatorDefault, (int)_size.width, (int)_size.height, kCVPixelFormatType_32BGRA, attrs, &renderTarget);
if (err)
{
NSLog(@"FBO size: %f, %f", _size.width, _size.height);
NSAssert(NO, @"Error at CVPixelBufferCreate %d", err);
} err = CVOpenGLESTextureCacheCreateTextureFromImage (kCFAllocatorDefault, coreVideoTextureCache, renderTarget,
NULL, // texture attributes
GL_TEXTURE_2D,
_textureOptions.internalFormat, // opengl format
(int)_size.width,
(int)_size.height,
_textureOptions.format, // native iOS format
_textureOptions.type,
,
&renderTexture);
if (err)
{
NSAssert(NO, @"Error at CVOpenGLESTextureCacheCreateTextureFromImage %d", err);
} CFRelease(attrs);
CFRelease(empty); glBindTexture(CVOpenGLESTextureGetTarget(renderTexture), CVOpenGLESTextureGetName(renderTexture));
_texture = CVOpenGLESTextureGetName(renderTexture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _textureOptions.wrapS);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _textureOptions.wrapT); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, CVOpenGLESTextureGetName(renderTexture), );
#endif
}
else
{
[self generateTexture]; glBindTexture(GL_TEXTURE_2D, _texture); glTexImage2D(GL_TEXTURE_2D, , _textureOptions.internalFormat, (int)_size.width, (int)_size.height, , _textureOptions.format, _textureOptions.type, );
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, );
} #ifndef NS_BLOCK_ASSERTIONS
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
NSAssert(status == GL_FRAMEBUFFER_COMPLETE, @"Incomplete filter FBO: %d", status);
#endif glBindTexture(GL_TEXTURE_2D, );
});
} - (void)destroyFramebuffer;
{
runSynchronouslyOnVideoProcessingQueue(^{
[GPUImageContext useImageProcessingContext]; if (framebuffer)
{
glDeleteFramebuffers(, &framebuffer);
framebuffer = ;
} if ([GPUImageContext supportsFastTextureUpload] && (!_missingFramebuffer))
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
if (renderTarget)
{
CFRelease(renderTarget);
renderTarget = NULL;
} if (renderTexture)
{
CFRelease(renderTexture);
renderTexture = NULL;
}
#endif
}
else
{
glDeleteTextures(, &_texture);
} });
} #pragma mark -
#pragma mark Usage - (void)activateFramebuffer;
{
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glViewport(, , (int)_size.width, (int)_size.height);
} #pragma mark -
#pragma mark Reference counting - (void)lock;
{
if (referenceCountingDisabled)
{
return;
} framebufferReferenceCount++;
} - (void)unlock;
{
if (referenceCountingDisabled)
{
return;
} NSAssert(framebufferReferenceCount > , @"Tried to overrelease a framebuffer, did you forget to call -useNextFrameForImageCapture before using -imageFromCurrentFramebuffer?");
framebufferReferenceCount--;
if (framebufferReferenceCount < )
{
[[GPUImageContext sharedFramebufferCache] returnFramebufferToCache:self];
}
} - (void)clearAllLocks;
{
framebufferReferenceCount = ;
} - (void)disableReferenceCounting;
{
referenceCountingDisabled = YES;
} - (void)enableReferenceCounting;
{
referenceCountingDisabled = NO;
} #pragma mark -
#pragma mark Image capture void dataProviderReleaseCallback (void *info, const void *data, size_t size)
{
free((void *)data);
} void dataProviderUnlockCallback (void *info, const void *data, size_t size)
{
GPUImageFramebuffer *framebuffer = (__bridge_transfer GPUImageFramebuffer*)info; [framebuffer restoreRenderTarget];
[framebuffer unlock];
[[GPUImageContext sharedFramebufferCache] removeFramebufferFromActiveImageCaptureList:framebuffer];
} - (CGImageRef)newCGImageFromFramebufferContents;
{
// a CGImage can only be created from a 'normal' color texture
NSAssert(self.textureOptions.internalFormat == GL_RGBA, @"For conversion to a CGImage the output texture format for this filter must be GL_RGBA.");
NSAssert(self.textureOptions.type == GL_UNSIGNED_BYTE, @"For conversion to a CGImage the type of the output texture of this filter must be GL_UNSIGNED_BYTE."); __block CGImageRef cgImageFromBytes; runSynchronouslyOnVideoProcessingQueue(^{
[GPUImageContext useImageProcessingContext]; NSUInteger totalBytesForImage = (int)_size.width * (int)_size.height * ;
// It appears that the width of a texture must be padded out to be a multiple of 8 (32 bytes) if reading from it using a texture cache GLubyte *rawImagePixels; CGDataProviderRef dataProvider = NULL;
if ([GPUImageContext supportsFastTextureUpload])
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSUInteger paddedWidthOfImage = CVPixelBufferGetBytesPerRow(renderTarget) / 4.0;
NSUInteger paddedBytesForImage = paddedWidthOfImage * (int)_size.height * ; glFinish();
CFRetain(renderTarget); // I need to retain the pixel buffer here and release in the data source callback to prevent its bytes from being prematurely deallocated during a photo write operation
[self lockForReading];
rawImagePixels = (GLubyte *)CVPixelBufferGetBaseAddress(renderTarget);
dataProvider = CGDataProviderCreateWithData((__bridge_retained void*)self, rawImagePixels, paddedBytesForImage, dataProviderUnlockCallback);
[[GPUImageContext sharedFramebufferCache] addFramebufferToActiveImageCaptureList:self]; // In case the framebuffer is swapped out on the filter, need to have a strong reference to it somewhere for it to hang on while the image is in existence
#else
#endif
}
else
{
[self activateFramebuffer];
rawImagePixels = (GLubyte *)malloc(totalBytesForImage);
glReadPixels(, , (int)_size.width, (int)_size.height, GL_RGBA, GL_UNSIGNED_BYTE, rawImagePixels);
dataProvider = CGDataProviderCreateWithData(NULL, rawImagePixels, totalBytesForImage, dataProviderReleaseCallback);
[self unlock]; // Don't need to keep this around anymore
} CGColorSpaceRef defaultRGBColorSpace = CGColorSpaceCreateDeviceRGB(); if ([GPUImageContext supportsFastTextureUpload])
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
cgImageFromBytes = CGImageCreate((int)_size.width, (int)_size.height, , , CVPixelBufferGetBytesPerRow(renderTarget), defaultRGBColorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst, dataProvider, NULL, NO, kCGRenderingIntentDefault);
#else
#endif
}
else
{
cgImageFromBytes = CGImageCreate((int)_size.width, (int)_size.height, , , * (int)_size.width, defaultRGBColorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaLast, dataProvider, NULL, NO, kCGRenderingIntentDefault);
} // Capture image with current device orientation
CGDataProviderRelease(dataProvider);
CGColorSpaceRelease(defaultRGBColorSpace); }); return cgImageFromBytes;
} - (void)restoreRenderTarget;
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
[self unlockAfterReading];
CFRelease(renderTarget);
#else
#endif
} #pragma mark -
#pragma mark Raw data bytes - (void)lockForReading
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
if ([GPUImageContext supportsFastTextureUpload])
{
if (readLockCount == )
{
CVPixelBufferLockBaseAddress(renderTarget, );
}
readLockCount++;
}
#endif
} - (void)unlockAfterReading
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
if ([GPUImageContext supportsFastTextureUpload])
{
NSAssert(readLockCount > , @"Unbalanced call to -[GPUImageFramebuffer unlockAfterReading]");
readLockCount--;
if (readLockCount == )
{
CVPixelBufferUnlockBaseAddress(renderTarget, );
}
}
#endif
} - (NSUInteger)bytesPerRow;
{
if ([GPUImageContext supportsFastTextureUpload])
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
return CVPixelBufferGetBytesPerRow(renderTarget);
#else
return _size.width * ; // TODO: do more with this on the non-texture-cache side
#endif
}
else
{
return _size.width * ;
}
} - (GLubyte *)byteBuffer;
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
[self lockForReading];
GLubyte * bufferBytes = CVPixelBufferGetBaseAddress(renderTarget);
[self unlockAfterReading];
return bufferBytes;
#else
return NULL; // TODO: do more with this on the non-texture-cache side
#endif
} - (GLuint)texture;
{
// NSLog(@"Accessing texture: %d from FB: %@", _texture, self);
return _texture;
} @end

  

GPUImage API文档之GPUImageFramebuffer类的更多相关文章

  1. GPUImage API 文档之GPUImageFilter类

    GPUImageFilter类 方法 - (id)initWithVertexShaderFromString:(NSString *)vertexShaderString fragmentShade ...

  2. GPUImage API 文档之GPUImageOutput类

    GPUImageOutput类将静态图像纹理上传到OpenGL ES中,然后使用这些纹理去处理进程链中的下一个对象.它的子类可以获得滤镜处理后的图片功能.[本文讲的很少,由于有许多地方不清楚,以后会更 ...

  3. GPUImage API文档之GPUImageContext类

    GPUImageContext类,提供OpenGL ES基本环境,我们一般不会用到,所以讲的很简单. 属性 @property(readonly, nonatomic) dispatch_queue_ ...

  4. GPUImage API文档之GPUImageFramebufferCache类

    GPUImageFramebufferCache类负责管理GPUImageFramebuffer对象,是一个GPUImageFramebuffer对象的缓存. 方法 - (GPUImageFrameb ...

  5. GPUImage API 文档之GPUImagePicture类

    GPUImagePicture类静态图像处理操作,它可以是需要处理的静态图像,也可以是一张作为纹理使用的图片,调用向它发送processImage消息,进行图像滤镜处理. 方法 - (id)initW ...

  6. GPUImage API文档之GLProgram类

    GLProgram是GPUImage中代表openGL ES 中的program,具有glprogram功能. 属性 @property(readwrite, nonatomic) BOOL init ...

  7. GPUImage API文档之GPUImageInput协议

    GPUImageInput协议主要包含一些输入需要渲染目标的操作. - (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)t ...

  8. 通过API文档查询Math类的方法,打印出近似圆,只要给定不同半径,圆的大小就会随之发生改变

    package question; import java.util.Scanner; import java.lang.Math; public class MathTest { /** * 未搞懂 ...

  9. Java,面试题,简历,Linux,大数据,常用开发工具类,API文档,电子书,各种思维导图资源,百度网盘资源,BBS论坛系统 ERP管理系统 OA办公自动化管理系统 车辆管理系统 各种后台管理系统

    Java,面试题,简历,Linux,大数据,常用开发工具类,API文档,电子书,各种思维导图资源,百度网盘资源BBS论坛系统 ERP管理系统 OA办公自动化管理系统 车辆管理系统 家庭理财系统 各种后 ...

随机推荐

  1. OpenOCD Debug Adapter Configuration

    Correctly installing OpenOCD includes making your operating system give OpenOCD access to debug adap ...

  2. IAR EWARM 字体设置

    如果只想简单的设置,可进行如下设置 Tools->IDE Options->Editor->Colors and Fonts->Editor Font->Font 但是这 ...

  3. effective C++ 读书笔记 条款08

    条款08  别让异常逃离析构函数: 假设在析构函数其中发生了异常,程序可能会过早结束或者导致不明白行为(异常从析构函数传播出去) 看代码: #include <iostream> usin ...

  4. 使用Edge模式通知Internet Explorer以最高级别的可用模式显示内容

    一.EasyUI$的window('open')在IE8下兼容性问题 今天在公司使用EasyUI的$('#win').window('open');方法打开一个window窗体时发现EaysUI的脚本 ...

  5. 为什么我不再用 .NET 框架

    .NET平台很棒.真的很棒.直到它不再那么棒.我为什么不再用.NET?简单来说,它限制了我们选择的能力(对我来说很重要),转移了我们的注意力,使得我们向内认知它的安全性,替代了帮助我们认知外面广阔世界 ...

  6. FreeCommander 学习手册

    概述 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3470728.html FreeCommander(下文简称FC),是Windows下面比较强大的文 ...

  7. iOS本地化应用程序

    因为使用的是xcode4,应用程序本地化的问题跟以前的版本还是有些不同,在网上找了些资料对于xcode4以上的版本资料还是相对较少,有些最后要通过手动创建文件,这样操作实在是太麻烦,所以经过一个下午的 ...

  8. mysql 和 sqlite 区别 及 SQLite Expert Professional sqliteManager 区别

    mysql 和 sqlite 区别 SQLITE是单机数据库.功能简约,小型化,追求最大磁盘效率MYSQL是完善的服务器数据库.功能全面,综合化,追求最大并发效率 MYSQL.Sybase.Oracl ...

  9. PL/SQL报错:Initialization error Oracle client not properly installed

    安装PL/SQL8.4后,连接数据库 提示错误Initialization error Oracle client not properly installed 解决方案: 1.下载instancec ...

  10. android之lint警告This Handler class should be static or leaks might occur

    更新到adt2.0的开发者们可能会在handler上发现这么一条警告:This Handler class should be static or leaks might occur . 首先在ADT ...