123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- // Copyright (C) 2018 Beijing Bytedance Network Technology Co., Ltd.
- #import "BEGLView.h"
- #import <UIKit/UIKit.h>
- #import <Masonry.h>
- #import <UIView+Toast.h>
- @interface BEGLView () {
- GLuint _displayTextureID;
- BOOL _shouldDeleteTextureID;
-
- GLuint _renderProgram;
- GLuint _renderLocation;
- GLuint _renderInputImageTexture;
- GLuint _renderTextureCoordinate;
- GLfloat vertex[8];
-
- unsigned char* saveTextureBuffer;
- GLuint _saveTexture;
- GLuint _frameBuffer;
-
- CGSize _savedSize;
- }
- @property (nonatomic, strong) CIContext *ciContext;
- @property (nonatomic, strong) EAGLContext *glContext;
- @property (nonatomic, assign) unsigned int screenWidth;
- @property (nonatomic, assign) unsigned int screenHeight;
- @property (nonatomic, strong) UIImageView *imageView;
- @end
- static float TEXTURE_FLIPPED[] = {0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,};
- static float CUBE[] = {-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,};
- static float TEXTURE_RORATION_0[] = {0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,};
- #define TTF_STRINGIZE(x) #x
- #define TTF_STRINGIZE2(x) TTF_STRINGIZE(x)
- #define TTF_SHADER_STRING(text) @ TTF_STRINGIZE2(text)
- static NSString *const RENDER_VERTEX = TTF_SHADER_STRING
- (
- attribute vec4 position;
- attribute vec4 inputTextureCoordinate;
- varying vec2 textureCoordinate;
- void main(){
- float scale = 1.05;
- mat4 s = mat4(scale, 0.0, 0.0, 0.0,
- 0.0, scale, 0.0, 0.0,
- 0.0, 0.0, scale, 0.0,
- 0.0, 0.0, 0.0, 1.0);
- textureCoordinate = inputTextureCoordinate.xy;
- gl_Position = s * position;
- }
- );
- static NSString *const RENDER_FRAGMENT = TTF_SHADER_STRING
- (
- precision mediump float;
- varying highp vec2 textureCoordinate;
- uniform sampler2D inputImageTexture;
- void main()
- {
- gl_FragColor = texture2D(inputImageTexture, textureCoordinate);
- }
- );
- @implementation BEGLView
- - (void)dealloc
- {
- //NSLog(@"%@", NSStringFromSelector(_cmd));
- free(saveTextureBuffer);
- glDeleteTextures(1, &_saveTexture);
- glDeleteFramebuffers(1, &_frameBuffer);
- }
- - (instancetype)initWithFrame:(CGRect)frame {
- self = [super initWithFrame:frame];
- if (self) {
- self.glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
- self.ciContext = [CIContext contextWithEAGLContext:self.glContext];
- self.context = self.glContext;
-
- if ([EAGLContext currentContext] != self.glContext) {
- [EAGLContext setCurrentContext:self.glContext];
- }
- [self loadRenderShader];
-
- // CGFloat scale = [UIScreen mainScreen].scale;
- // UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
- // if (orientation == UIInterfaceOrientationPortrait
- // || orientation == UIInterfaceOrientationPortraitUpsideDown) {
- // _screenWidth = [UIScreen mainScreen].bounds.size.width * scale;
- // _screenHeight = [UIScreen mainScreen].bounds.size.height * scale;
- // } else {
- // _screenHeight = [UIScreen mainScreen].bounds.size.width * scale;
- // _screenWidth = [UIScreen mainScreen].bounds.size.height * scale;
- // }
- //
- // float ratio[2] = {1.0, 1.0};
- // [self calcVertex:_screenWidth height:_screenHeight ratios:ratio];
- //
- // for (int i = 0; i < 4; i ++){
- // vertex[i * 2] = CUBE[i * 2] / ratio[1];
- // vertex[i * 2 + 1] = CUBE[i * 2 + 1] / ratio[0];
- // }
- // saveTextureBuffer = malloc(_screenHeight * _screenWidth * 4);
- //
- // glGenTextures(1, &_saveTexture);
- // glGenFramebuffers(1, &_frameBuffer);
- //
- //// [CSToastManager setQueueEnabled:YES];
- }
- return self;
- }
- - (void)reloadDraw{
- CGFloat scale = [UIScreen mainScreen].scale;
- _screenWidth = self.f_width * scale;
- _screenHeight = self.f_heigh * scale;
-
- float ratio[2] = {1.0, 1.0};
- [self calcVertex:_screenWidth height:_screenHeight ratios:ratio];
-
- for (int i = 0; i < 4; i ++){
- vertex[i * 2] = CUBE[i * 2] / ratio[1];
- vertex[i * 2 + 1] = CUBE[i * 2 + 1] / ratio[0];
- }
- saveTextureBuffer = malloc(_screenHeight * _screenWidth * 4);
-
- glGenTextures(1, &_saveTexture);
- glGenFramebuffers(1, &_frameBuffer);
-
- //[CSToastManager setQueueEnabled:YES];
- }
- - (void)resetWidthAndHeight {
- // CGFloat scale = [UIScreen mainScreen].scale;
- // _screenWidth = [UIScreen mainScreen].bounds.size.width * scale;
- // _screenHeight = [UIScreen mainScreen].bounds.size.height * scale;
- CGFloat scale = [UIScreen mainScreen].scale;
- _screenWidth = self.f_width * scale;
- _screenHeight = self.f_heigh * scale;
- }
- /*
- * 将纹理绘制到屏幕上
- */
- - (void)renderWithTexture:(unsigned int)name
- size:(CGSize)size
- flipped:(BOOL)flipped
- applyingOrientation:(int)orientation
- savingCurrentTexture:(bool)enableSaving{
-
- if ([EAGLContext currentContext] != self.glContext) {
- [EAGLContext setCurrentContext:self.glContext];
- }
-
- if (!glIsTexture(name)) {
- return;
- }
-
- _displayTextureID = name;
- if (!self.window) {
- //glDeleteTextures(1, &_displayTextureID);
- _shouldDeleteTextureID = NO;
- return;
- }
-
- if (enableSaving) {
- [self textureToImage:name withBuffer:saveTextureBuffer Width:_screenWidth height:_screenHeight];
-
- CGDataProviderRef provider = CGDataProviderCreateWithData(
- NULL,
- saveTextureBuffer,
- _screenWidth * _screenHeight * 4,
- NULL);
-
- CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
- CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
- CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
-
- CGImageRef imageRef = CGImageCreate(_screenWidth,
- _screenHeight,
- 8,
- 4 * 8,
- 4 * _screenWidth,
- colorSpaceRef,
- bitmapInfo,
- provider,
- NULL,
- NO,
- renderingIntent);
-
- //free(buffer);
- UIImage *uiImage = [UIImage imageWithCGImage:imageRef];
- CGDataProviderRelease(provider);
- CGColorSpaceRelease(colorSpaceRef);
- CGImageRelease(imageRef);
-
- UIImageWriteToSavedPhotosAlbum(uiImage, self, @selector(image:didFinishSavingWithError:contextInfo:), (__bridge void*)self);
- }
-
- if (!_shouldDeleteTextureID){
- _shouldDeleteTextureID = YES;
- [self display];
- }
- }
- - (void) textureToImage:(GLuint)texture withBuffer:(unsigned char*)buffer Width:(int)rWidth height:(int)rHeight{
- glBindTexture(GL_TEXTURE_2D, _saveTexture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rWidth, rHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-
- glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _saveTexture, 0);
-
- glUseProgram(_renderProgram);
- glVertexAttribPointer(_renderLocation, 2, GL_FLOAT, false, 0, vertex);
- glEnableVertexAttribArray(_renderLocation);
- glVertexAttribPointer(_renderTextureCoordinate, 2, GL_FLOAT, false, 0, TEXTURE_RORATION_0);
- glEnableVertexAttribArray(_renderTextureCoordinate);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, texture);
- glUniform1i(_renderInputImageTexture, 0);
- glViewport(0, 0, rWidth, rHeight);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
- glDisableVertexAttribArray(_renderLocation);
- glDisableVertexAttribArray(_renderTextureCoordinate);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- glReadPixels(0, 0, rWidth, rHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- [self checkGLError];
- }
- - (void)image:(UIImage*)image didFinishSavingWithError:(NSError*)error contextInfo:(void *)contextInfo{
- if (error){
- //NSLog(@"fail to save photo");
- }else {
- ////NSLog(@"image = %@, error = %@, contextInfo = %@", image, error, contextInfo);
- [self makeToast:NSLocalizedString(@"ablum_have_been_saved", nil) duration:(NSTimeInterval)(3.0) position:CSToastPositionCenter];
- }
- }
- - (void) calcVertex:(int)iWidth height:(int)iHeight ratios:(float *)retRatio{
- int outputWidth = iWidth;
- int outputHeight = iHeight;
-
- int imageHeight = 1280;
- int imageWidth = 720;
-
- float ratio1 = (float)outputWidth / imageWidth;
- float ratio2 = (float)outputHeight / imageHeight;
-
- float ratio = MIN(ratio1, ratio2);
-
- int imageNewHeight = round(imageHeight * ratio);
- int imageNewWidth = round(imageWidth * ratio);
-
- float ratioHeight = imageNewHeight / (float)outputHeight;
- float ratioWidth = imageNewWidth / (float)outputWidth;
-
- retRatio[0] = ratioWidth;
- retRatio[1] = ratioHeight;
- }
- - (void)drawRect:(CGRect)rect {
- [super drawRect:rect];
-
- CGSize size = self.bounds.size;
- if (!CGSizeEqualToSize(size, _savedSize)) {
- [self resetWidthAndHeight];
- _savedSize = size;
- }
-
- if (_shouldDeleteTextureID) {
-
- glClearColor(0.0, 0.0, 0.0, 0.0);
- glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
-
- glUseProgram(_renderProgram);
-
- glVertexAttribPointer(_renderLocation, 2, GL_FLOAT, false, 0, vertex);
- glEnableVertexAttribArray(_renderLocation);
- glVertexAttribPointer(_renderTextureCoordinate, 2, GL_FLOAT, false, 0, TEXTURE_FLIPPED);
- glEnableVertexAttribArray(_renderTextureCoordinate);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, _displayTextureID);
- glUniform1i(_renderInputImageTexture, 0);
- glViewport(0, 0, _screenWidth, _screenHeight);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
- glDisableVertexAttribArray(_renderLocation);
- glDisableVertexAttribArray(_renderTextureCoordinate);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- glUseProgram(0);
- glFlush();
-
- //glDeleteTextures(1, &_displayTextureID);
- _shouldDeleteTextureID = NO;
- }
- }
- /*
- * load resize shader
- */
- - (void) loadRenderShader{
- // GLuint vertexShader = [BERenderHelper compileShader:RENDER_VERTEX withType:GL_VERTEX_SHADER];
- // GLuint fragmentShader = [BERenderHelper compileShader:RENDER_FRAGMENT withType:GL_FRAGMENT_SHADER];
- //
- // _renderProgram = glCreateProgram();
- // glAttachShader(_renderProgram, vertexShader);
- // glAttachShader(_renderProgram, fragmentShader);
- // glLinkProgram(_renderProgram);
- //
- // GLint linkSuccess;
- // glGetProgramiv(_renderProgram, GL_LINK_STATUS, &linkSuccess);
- // if (linkSuccess == GL_FALSE){
- // //NSLog(@"BERenderHelper link shader error");
- // }
- //
- // glUseProgram(_renderProgram);
- // _renderLocation = glGetAttribLocation(_renderProgram, "position");
- // _renderTextureCoordinate = glGetAttribLocation(_renderProgram, "inputTextureCoordinate");
- // _renderInputImageTexture = glGetUniformLocation(_renderProgram, "inputImageTexture");
- //
- // if (vertexShader)
- // glDeleteShader(vertexShader);
- //
- // if (fragmentShader)
- // glDeleteShader(fragmentShader);
- }
- - (void)releaseContext {
- [EAGLContext setCurrentContext:nil];
- }
- #pragma mark - getter
- - (UIImageView*)imageView{
- if(!_imageView){
- _imageView = [[UIImageView alloc] init];
- }
- return _imageView;
- }
- - (void)checkGLError {
- int error = glGetError();
- if (error != GL_NO_ERROR) {
- //NSLog(@"%d", error);
- @throw [NSException exceptionWithName:@"GLError" reason:@"error " userInfo:nil];
- }
- }
- @end
|