123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- //
- // STGLPreview.m
- //
- // Created by sluin on 2017/1/11.
- // Copyright © 2017年 SenseTime. All rights reserved.
- //
- #import "STGLPreview.h"
- #import "STVFShader.h"
- // Attribute index.
- enum {
- ATTRIB_VERTEX,
- ATTRIB_TEXTUREPOSITON,
- NUM_ATTRIBUTES
- };
- @interface STGLPreview ()
- {
- /* The pixel dimensions of the backbuffer */
- GLint backingWidth, backingHeight;
-
- /* OpenGL names for the renderbuffer and framebuffers used to render to this view */
- GLuint viewRenderbuffer, viewFramebuffer;
- GLuint positionRenderTexture;
- GLuint positionRenderbuffer, positionFramebuffer;
-
- GLuint stDisplayProgram;
-
- int uniformLocation;
- }
- @end
- @implementation STGLPreview
- // Override the class method to return the OpenGL layer, as opposed to the normal CALayer
- + (Class) layerClass
- {
- return [CAEAGLLayer class];
- }
- - (instancetype)initWithFrame:(CGRect)frame context:(EAGLContext *)context
- {
- self = [super initWithFrame:frame];
-
- if (self) {
-
- // Set scaling to account for Retina display
- if ([self respondsToSelector:@selector(setContentScaleFactor:)])
- {
- self.contentScaleFactor = [[UIScreen mainScreen] scale];
- }
-
- // Do OpenGL Core Animation layer setup
- CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
- eaglLayer.opaque = YES;
- eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
-
- _glContext = context;
-
- if (!_glContext) {
-
- return nil;
- }
-
- if ([EAGLContext currentContext] != _glContext) {
-
- if (![EAGLContext setCurrentContext:_glContext]) {
-
- return nil;
- }
- }
-
- if (![self createFramebuffers]) {
-
- return nil;
- }
-
- [self loadVertexShader:@"STDisplayShader"
- fragmentShader:@"STDisplayShader"
- forProgram:&stDisplayProgram];
-
- self.clipsToBounds = YES;
- self.contentMode = UIViewContentModeScaleAspectFill;
-
- }
- return self;
- }
- - (void)dealloc
- {
- [self destroyFramebuffer];
- }
- - (BOOL)createFramebuffers
- {
- glEnable(GL_TEXTURE_2D);
- glDisable(GL_DEPTH_TEST);
-
- // Onscreen framebuffer object
- glGenFramebuffers(1, &viewFramebuffer);
- glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
-
- glGenRenderbuffers(1, &viewRenderbuffer);
- glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
-
- [_glContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];
-
- glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
- glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
-
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, viewRenderbuffer);
-
- if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
-
- NSLog(@"STGLPreview : failure with framebuffer generation");
-
- return NO;
- }
-
- // Offscreen position framebuffer object
- glGenFramebuffers(1, &positionFramebuffer);
- glBindFramebuffer(GL_FRAMEBUFFER, positionFramebuffer);
-
- glGenRenderbuffers(1, &positionRenderbuffer);
- glBindRenderbuffer(GL_RENDERBUFFER, positionRenderbuffer);
-
- // glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, (GLsizei)self.frame.size.width, (GLsizei)self.frame.size.height);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, positionRenderbuffer);
-
-
- // Offscreen position framebuffer texture target
- glGenTextures(1, &positionRenderTexture);
- glBindTexture(GL_TEXTURE_2D, positionRenderTexture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)self.frame.size.width, (GLsizei)self.frame.size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, positionRenderTexture, 0);
-
- return YES;
- }
- - (void)destroyFramebuffer;
- {
- if (viewFramebuffer) {
-
- glDeleteFramebuffers(1, &viewFramebuffer);
- viewFramebuffer = 0;
- }
-
- if (viewRenderbuffer) {
-
- glDeleteRenderbuffers(1, &viewRenderbuffer);
- viewRenderbuffer = 0;
- }
- }
- - (BOOL)loadVertexShader:(NSString *)vertexShaderName
- fragmentShader:(NSString *)fragmentShaderName
- forProgram:(GLuint *)programPointer;
- {
- GLuint vertexShader, fragShader;
-
- // Create shader program.
- *programPointer = glCreateProgram();
-
- // Create and compile vertex shader.
- if (![self compileShader:&vertexShader type:GL_VERTEX_SHADER shaderString:vsh]) {
-
- NSLog(@"STGLPreview : failed to compile vertex shader");
- return NO;
- }
-
- // Create and compile fragment shader.
- if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER shaderString:fsh]) {
-
- NSLog(@"STGLPreview : failed to compile fragment shader");
- return NO;
- }
-
- // Attach vertex shader to program.
- glAttachShader(*programPointer, vertexShader);
-
- // Attach fragment shader to program.
- glAttachShader(*programPointer, fragShader);
-
- // Bind attribute locations.
- // This needs to be done prior to linking.
- glBindAttribLocation(*programPointer, ATTRIB_VERTEX, "position");
- glBindAttribLocation(*programPointer, ATTRIB_TEXTUREPOSITON, "inputTextureCoordinate");
-
- // Link program.
- if (![self linkProgram:*programPointer]) {
-
- NSLog(@"STGLPreview : failed to link program: %d", *programPointer);
-
- if (vertexShader) {
-
- glDeleteShader(vertexShader);
- vertexShader = 0;
- }
- if (fragShader) {
-
- glDeleteShader(fragShader);
- fragShader = 0;
- }
- if (*programPointer) {
-
- glDeleteProgram(*programPointer);
- *programPointer = 0;
- }
-
- return NO;
- }
-
- // Get uniform locations.
- uniformLocation = glGetUniformLocation(*programPointer, "videoFrame");
-
- // Release vertex and fragment shaders.
- if (vertexShader) {
-
- glDeleteShader(vertexShader);
- }
- if (fragShader) {
-
- glDeleteShader(fragShader);
- }
-
- return YES;
- }
- - (BOOL)compileShader:(GLuint *)shader type:(GLenum)type shaderString:(const char *)str
- {
- GLint status;
- const GLchar *source;
- source = (GLchar *)str;
- if (!source) {
-
- NSLog(@"STGLPreview : failed to load vertex shader");
-
- return NO;
- }
-
- *shader = glCreateShader(type);
- glShaderSource(*shader, 1, &source, NULL);
- glCompileShader(*shader);
-
- glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
- if (status == 0) {
-
- glDeleteShader(*shader);
-
- return NO;
- }
-
- return YES;
- }
- - (BOOL)linkProgram:(GLuint)prog
- {
- GLint status;
-
- glLinkProgram(prog);
-
- glGetProgramiv(prog, GL_LINK_STATUS, &status);
-
- if (0 == status) {
-
- return NO;
- }else{
-
- return YES;
- }
- }
- - (void)renderTexture:(GLuint)texture
- {
- if ([EAGLContext setCurrentContext:self.glContext]) {
-
- [self drawFrameWithTexture:texture];
- }
- }
- - (BOOL)drawFrameWithTexture:(GLuint)texture
- {
- static const GLfloat squareVertices[] = {
- -1.0f, -1.0f,
- 1.0f, -1.0f,
- -1.0f, 1.0f,
- 1.0f, 1.0f,
- };
-
- static const GLfloat textureVertices[] = {
- 0.0f, 1.0f,
- 1.0f, 1.0f,
- 0.0f, 0.0f,
- 1.0f, 0.0f,
- };
-
- // Use shader program.
- if (!viewFramebuffer) {
-
- [self createFramebuffers];
- }
-
- glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
-
- glViewport(0, 0, backingWidth, backingHeight);
- glUseProgram(stDisplayProgram);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, texture);
-
- // Update uniform values
- glUniform1i(uniformLocation, 0);
-
- // Update attribute values.
- glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
- glEnableVertexAttribArray(ATTRIB_VERTEX);
- glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureVertices);
- glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
- BOOL isSuccess = NO;
-
- if (_glContext) {
-
- glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
- isSuccess = [_glContext presentRenderbuffer:GL_RENDERBUFFER];
- }
-
- return isSuccess;
- }
- @end
|