| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645 |
- // QGHWDMP4OpenGLView.m
- // Tencent is pleased to support the open source community by making vap available.
- //
- // Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
- //
- // Licensed under the MIT License (the "License"); you may not use this file except in
- // compliance with the License. You may obtain a copy of the License at
- //
- // http://opensource.org/licenses/MIT
- //
- // Unless required by applicable law or agreed to in writing, software distributed under the License is
- // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- // either express or implied. See the License for the specific language governing permissions and
- // limitations under the License.
- #import "QGHWDMP4OpenGLView.h"
- #import <QuartzCore/QuartzCore.h>
- #import <AVFoundation/AVUtilities.h>
- #import <mach/mach_time.h>
- #import <GLKit/GLKit.h>
- #import "VAPMacros.h"
- // Uniform index.
- enum {
- HWD_UNIFORM_Y,
- HWD_UNIFORM_UV,
- HWD_UNIFORM_COLOR_CONVERSION_MATRIX,
- HWD_NUM_UNIFORMS
- };
- GLint hwd_uniforms[HWD_NUM_UNIFORMS];
- // Attribute index.
- enum {
- ATTRIB_VERTEX,
- ATTRIB_TEXCOORD_RGB,
- ATTRIB_TEXCOORD_ALPHA,
- NUM_ATTRIBUTES
- };
- // BT.709-HDTV.
- static const GLfloat kQGColorConversion709[] = {
- 1.164, 1.164, 1.164,
- 0.0, -0.213, 2.112,
- 1.793, -0.533, 0.0,
- };
- // BT.601 full range-http://www.equasys.de/colorconversion.html
- const GLfloat kQGColorConversion601FullRange[] = {
- 1.0, 1.0, 1.0,
- 0.0, -0.343, 1.765,
- 1.4, -0.711, 0.0,
- };
- // texture coords for blend
- const GLfloat textureCoordLeft[] = { // 左侧
- 0.5, 0.0,
- 0.0, 0.0,
- 0.5, 1.0,
- 0.0, 1.0
- };
- const GLfloat textureCoordRight[] = { // 右侧
- 1.0, 0.0,
- 0.5, 0.0,
- 1.0, 1.0,
- 0.5, 1.0
- };
- const GLfloat textureCoordTop[] = { // 上侧
- 1.0, 0.0,
- 0.0, 0.0,
- 1.0, 0.5,
- 0.0, 0.5
- };
- const GLfloat textureCoordBottom[] = { // 下侧
- 1.0, 0.5,
- 0.0, 0.5,
- 1.0, 1.0,
- 0.0, 1.0
- };
- #undef cos
- #undef sin
- NSString *const kVertexShaderSource = SHADER_STRING
- (
- attribute vec4 position;
- attribute vec2 RGBTexCoord;
- attribute vec2 alphaTexCoord;
-
- varying vec2 RGBTexCoordVarying;
- varying vec2 alphaTexCoordVarying;
-
- void main()
- {
- float preferredRotation = 3.14;
- mat4 rotationMatrix = mat4(cos(preferredRotation), -sin(preferredRotation), 0.0, 0.0,sin(preferredRotation),cos(preferredRotation), 0.0, 0.0,0.0,0.0,1.0,0.0,0.0,0.0, 0.0,1.0);
- gl_Position = rotationMatrix * position;
- RGBTexCoordVarying = RGBTexCoord;
- alphaTexCoordVarying = alphaTexCoord;
- }
- );
- NSString *const kFragmentShaderSource = SHADER_STRING
- (
- varying highp vec2 RGBTexCoordVarying;
- varying highp vec2 alphaTexCoordVarying;
- precision mediump float;
-
- uniform sampler2D SamplerY;
- uniform sampler2D SamplerUV;
- uniform mat3 colorConversionMatrix;
-
- void main()
- {
- mediump vec3 yuv_rgb;
- lowp vec3 rgb_rgb;
-
- mediump vec3 yuv_alpha;
- lowp vec3 rgb_alpha;
-
- // Subtract constants to map the video range start at 0
- yuv_rgb.x = (texture2D(SamplerY, RGBTexCoordVarying).r);// - (16.0/255.0));
- yuv_rgb.yz = (texture2D(SamplerUV, RGBTexCoordVarying).ra - vec2(0.5, 0.5));
-
- rgb_rgb = colorConversionMatrix * yuv_rgb;
-
-
- yuv_alpha.x = (texture2D(SamplerY, alphaTexCoordVarying).r);// - (16.0/255.0));
- yuv_alpha.yz = (texture2D(SamplerUV, alphaTexCoordVarying).ra - vec2(0.5, 0.5));
-
- rgb_alpha = colorConversionMatrix * yuv_alpha;
-
-
- gl_FragColor = vec4(rgb_rgb,rgb_alpha.r);
- // gl_FragColor = vec4(1, 0, 0, 1);
- }
- );
- @interface QGHWDMP4OpenGLView() {
- GLint _backingWidth;
- GLint _backingHeight;
- CVOpenGLESTextureRef _lumaTexture;
- CVOpenGLESTextureRef _chromaTexture;
- CVOpenGLESTextureCacheRef _textureCache;
- GLuint _frameBufferHandle;
- GLuint _colorBufferHandle;
- const GLfloat *_preferredConversion;
- }
- @property GLuint program;
- - (void)setupBuffers;
- - (void)cleanupTextures;
- - (BOOL)isValidateProgram:(GLuint)prog;
- - (BOOL)loadShaders;
- - (BOOL)compileShader:(GLuint *)shader type:(GLenum)type URL:(NSURL *)URL;
- - (BOOL)linkProgram:(GLuint)prog;
- @end
- @implementation QGHWDMP4OpenGLView
- + (Class)layerClass {
-
- return [CAEAGLLayer class];
- }
- - (id)initWithCoder:(NSCoder *)aDecoder {
- if ((self = [super initWithCoder:aDecoder])) {
- if (![self commonInit]) {
- return nil;
- }
- }
- return self;
- }
- - (instancetype)init {
-
- if (self = [super init]) {
- if (![self commonInit]) {
- return nil;
- }
- }
- return self;
- }
- - (instancetype)initWithFrame:(CGRect)frame {
-
- if (self = [super initWithFrame:frame]) {
- if (![self commonInit]) {
- return nil;
- }
- }
- return self;
- }
- - (BOOL)commonInit {
-
- self.contentScaleFactor = [[UIScreen mainScreen] scale];
- CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
- eaglLayer.opaque = NO;
- eaglLayer.drawableProperties = @{ kEAGLDrawablePropertyRetainedBacking :[NSNumber numberWithBool:NO],
- kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8};
- _glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
- if (!_glContext || ![EAGLContext setCurrentContext:_glContext] || ![self loadShaders]) {
- return NO;
- }
- _preferredConversion = kQGColorConversion709;
- return YES;
- }
- - (void)dealloc {
-
- [self cleanupTextures];
- if(_textureCache) {
- CFRelease(_textureCache);
- }
- if ([self.displayDelegate respondsToSelector:@selector(onViewUnavailableStatus)]) {
- [self.displayDelegate onViewUnavailableStatus];
- }
- }
- # pragma mark - OpenGL setup
- /**
- 初始化opengl环境
- */
- - (void)setupGL {
-
- VAP_Info(kQGVAPModuleCommon, @"setupGL");
- [EAGLContext setCurrentContext:_glContext];
- [self setupBuffers];
- [self loadShaders];
- glUseProgram(self.program);
- glUniform1i(hwd_uniforms[HWD_UNIFORM_Y], 0);
- glUniform1i(hwd_uniforms[HWD_UNIFORM_UV], 1);
- glUniformMatrix3fv(hwd_uniforms[HWD_UNIFORM_COLOR_CONVERSION_MATRIX], 1, GL_FALSE, _preferredConversion);
- // Create CVOpenGLESTextureCacheRef for optimal CVPixelBufferRef to GLES texture conversion.
- if (!_textureCache) {
- CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, _glContext, NULL, &_textureCache);
- if (err != noErr) {
- VAP_Event(kQGVAPModuleCommon, @"Error at CVOpenGLESTextureCacheCreate %d", err);
- return;
- }
- }
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- }
- #pragma mark - Utilities
- - (void)setupBuffers {
-
- glDisable(GL_DEPTH_TEST);
- glEnableVertexAttribArray(ATTRIB_VERTEX);
- glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
- glEnableVertexAttribArray(ATTRIB_TEXCOORD_RGB);
- glVertexAttribPointer(ATTRIB_TEXCOORD_RGB, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
- glEnableVertexAttribArray(ATTRIB_TEXCOORD_ALPHA);
- glVertexAttribPointer(ATTRIB_TEXCOORD_ALPHA, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
- glGenFramebuffers(1, &_frameBufferHandle);
- glBindFramebuffer(GL_FRAMEBUFFER, _frameBufferHandle);
- glGenRenderbuffers(1, &_colorBufferHandle);
- glBindRenderbuffer(GL_RENDERBUFFER, _colorBufferHandle);
- [_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, _colorBufferHandle);
- if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
- VAP_Event(kQGVAPModuleCommon, @"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
- }
- }
- - (void)layoutSubviews {
-
- [super layoutSubviews];
- [self updateBackingSize];
- }
- /**
- 根据容器大小更新渲染尺寸
- */
- - (void)updateBackingSize {
-
- if ([EAGLContext currentContext] != _glContext) {
- [EAGLContext setCurrentContext:_glContext];
- }
- [_glContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];
- glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_backingWidth);
- glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_backingHeight);
- }
- - (void)cleanupTextures {
-
- if (_lumaTexture) {
- CFRelease(_lumaTexture);
- _lumaTexture = NULL;
- }
- if (_chromaTexture) {
- CFRelease(_chromaTexture);
- _chromaTexture = NULL;
- }
- CVOpenGLESTextureCacheFlush(_textureCache, 0);
- }
- #pragma mark - OpenGLES drawing
- /**
- 上屏
-
- @param pixelBuffer 硬解出来的samplebuffer数据
- */
- - (void)displayPixelBuffer:(CVPixelBufferRef)pixelBuffer {
-
- if (!self.window && [self.displayDelegate respondsToSelector:@selector(onViewUnavailableStatus)]) {
- [self.displayDelegate onViewUnavailableStatus];
- return ;
- }
-
- if ([EAGLContext currentContext] != _glContext) {
- [EAGLContext setCurrentContext:_glContext];
- }
-
- CVReturn err;
- if (pixelBuffer != NULL) {
- int frameWidth = (int)CVPixelBufferGetWidth(pixelBuffer);
- int frameHeight = (int)CVPixelBufferGetHeight(pixelBuffer);
-
- if (!_textureCache) {
- VAP_Event(kQGVAPModuleCommon, @"No video texture cache");
- return;
- }
- [self cleanupTextures];
- _preferredConversion = kQGColorConversion601FullRange;
-
- //y
- glActiveTexture(GL_TEXTURE0);
- err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
- _textureCache,
- pixelBuffer,
- NULL,
- GL_TEXTURE_2D,
- GL_LUMINANCE,
- frameWidth,
- frameHeight,
- GL_LUMINANCE,
- GL_UNSIGNED_BYTE,
- 0,
- &_lumaTexture);
- if (err) {
- VAP_Event(kQGVAPModuleCommon, @"Error at CVOpenGLESTextureCacheCreateTextureFromImage %d", err);
- }
-
- glBindTexture(CVOpenGLESTextureGetTarget(_lumaTexture), CVOpenGLESTextureGetName(_lumaTexture));
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- // uv
- glActiveTexture(GL_TEXTURE1);
- err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
- _textureCache,
- pixelBuffer,
- NULL,
- GL_TEXTURE_2D,
- GL_LUMINANCE_ALPHA,
- frameWidth / 2.0,
- frameHeight / 2.0,
- GL_LUMINANCE_ALPHA,
- GL_UNSIGNED_BYTE,
- 1,
- &_chromaTexture);
- if (err) {
- VAP_Error(kQGVAPModuleCommon, @"Error at CVOpenGLESTextureCacheCreateTextureFromImage %d", err);
- }
-
- glBindTexture(CVOpenGLESTextureGetTarget(_chromaTexture), CVOpenGLESTextureGetName(_chromaTexture));
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glBindFramebuffer(GL_FRAMEBUFFER, _frameBufferHandle);
-
- // Set the view port to the entire view.
- glViewport(0, 0, _backingWidth, _backingHeight);
- }
-
- // glClearColor(0.1f, 0.0f, 0.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
-
- glUseProgram(self.program);
- glUniformMatrix3fv(hwd_uniforms[HWD_UNIFORM_COLOR_CONVERSION_MATRIX], 1, GL_FALSE, _preferredConversion);
-
- // 根据视频的方向和高宽比设置四个顶点。
- CGRect vertexRect = AVMakeRectWithAspectRatioInsideRect(CGSizeMake(_backingWidth, _backingHeight), self.layer.bounds);
-
- // 计算归一化四坐标来绘制坐标系。
- CGSize normalizedSamplingSize = CGSizeMake(0.0, 0.0);
- CGSize cropScaleAmount = CGSizeMake(vertexRect.size.width/self.layer.bounds.size.width, vertexRect.size.height/self.layer.bounds.size.height);
-
- if (cropScaleAmount.width > cropScaleAmount.height) {
- normalizedSamplingSize.width = 1.0;
- normalizedSamplingSize.height = cropScaleAmount.height/cropScaleAmount.width;
- } else {
- normalizedSamplingSize.width = 1.0;
- normalizedSamplingSize.height = cropScaleAmount.width/cropScaleAmount.height;
- }
-
- GLfloat quadVertexData [] = {
- -1 * normalizedSamplingSize.width, -1 * normalizedSamplingSize.height,
- normalizedSamplingSize.width, -1 * normalizedSamplingSize.height,
- -1 * normalizedSamplingSize.width, normalizedSamplingSize.height,
- normalizedSamplingSize.width, normalizedSamplingSize.height,
- };
-
- // 更新顶点数据
- glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, quadVertexData);
- glEnableVertexAttribArray(ATTRIB_VERTEX);
- glVertexAttribPointer(ATTRIB_TEXCOORD_RGB, 2, GL_FLOAT, 0, 0, [self quadTextureRGBData]);
- glEnableVertexAttribArray(ATTRIB_TEXCOORD_RGB);
- glVertexAttribPointer(ATTRIB_TEXCOORD_ALPHA, 2, GL_FLOAT, 0, 0, [self quedTextureAlphaData]);
- glEnableVertexAttribArray(ATTRIB_TEXCOORD_ALPHA);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- glBindRenderbuffer(GL_RENDERBUFFER, _colorBufferHandle);
- if ([EAGLContext currentContext] == _glContext && !self.pause && self.window && [UIApplication sharedApplication].applicationState != UIApplicationStateBackground) {
- [_glContext presentRenderbuffer:GL_RENDERBUFFER];
- }
- }
- - (const void *)quedTextureAlphaData {
- switch (self.blendMode) {
- case QGHWDTextureBlendMode_AlphaLeft:
- return textureCoordLeft;
- case QGHWDTextureBlendMode_AlphaRight:
- return textureCoordRight;
- case QGHWDTextureBlendMode_AlphaTop:
- return textureCoordTop;
- case QGHWDTextureBlendMode_AlphaBottom:
- return textureCoordBottom;
- default:
- return textureCoordLeft;
- }
- }
- - (const void *)quadTextureRGBData {
- switch (self.blendMode) {
- case QGHWDTextureBlendMode_AlphaLeft:
- return textureCoordRight;
- case QGHWDTextureBlendMode_AlphaRight:
- return textureCoordLeft;
- case QGHWDTextureBlendMode_AlphaTop:
- return textureCoordBottom;
- case QGHWDTextureBlendMode_AlphaBottom:
- return textureCoordTop;
- default:
- return textureCoordRight;
- }
- }
- #pragma mark - OpenGL ES 2 shader compilation
- - (BOOL)loadShaders {
-
- GLuint vShader, fShader;
- self.program = glCreateProgram();
- // Create and compile the vertex shader.
- if (![self compileShader:&vShader type:GL_VERTEX_SHADER source:kVertexShaderSource]) {
- VAP_Error(kQGVAPModuleCommon, @"Failed to compile vertex shader");
- return NO;
- }
- // Create and compile fragment shader.
- if (![self compileShader:&fShader type:GL_FRAGMENT_SHADER source:kFragmentShaderSource]) {
- VAP_Error(kQGVAPModuleCommon, @"Failed to compile fragment shader");
- return NO;
- }
- // Attach vertex shader to program.
- glAttachShader(self.program, vShader);
- // Attach fragment shader to program.
- glAttachShader(self.program, fShader);
- // Bind attribute locations. This needs to be done prior to linking.
- glBindAttribLocation(self.program, ATTRIB_VERTEX, "position");
- glBindAttribLocation(self.program, ATTRIB_TEXCOORD_RGB, "RGBTexCoord");
- glBindAttribLocation(self.program, ATTRIB_TEXCOORD_ALPHA, "alphaTexCoord");
- // Link the program.
- if (![self linkProgram:self.program]) {
- VAP_Event(kQGVAPModuleCommon, @"Failed to link program: %d", self.program);
- if (vShader) {
- glDeleteShader(vShader);
- vShader = 0;
- }
- if (fShader) {
- glDeleteShader(fShader);
- fShader = 0;
- }
- if (self.program) {
- glDeleteProgram(self.program);
- self.program = 0;
- }
- return NO;
- }
-
- // Get uniforms' location.
- hwd_uniforms[HWD_UNIFORM_Y] = glGetUniformLocation(self.program, "SamplerY");
- hwd_uniforms[HWD_UNIFORM_UV] = glGetUniformLocation(self.program, "SamplerUV");
- hwd_uniforms[HWD_UNIFORM_COLOR_CONVERSION_MATRIX] = glGetUniformLocation(self.program, "colorConversionMatrix");
-
- // Release vertex and fragment shaders.
- if (vShader) {
- glDetachShader(self.program, vShader);
- glDeleteShader(vShader);
- }
- if (fShader) {
- glDetachShader(self.program, fShader);
- glDeleteShader(fShader);
- }
- return YES;
- }
- - (BOOL)compileShader:(GLuint *)shader type:(GLenum)type source:(const NSString *)sourceString {
-
- GLint status;
- const GLchar *source;
- source = (GLchar *)[sourceString UTF8String];
- *shader = glCreateShader(type);
- glShaderSource(*shader, 1, &source, NULL);
- glCompileShader(*shader);
- #if defined(DEBUG)
- GLint lengthOfLog;
- glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &lengthOfLog);
- if (lengthOfLog > 0) {
- GLchar *log = (GLchar *)malloc(lengthOfLog);
- glGetShaderInfoLog(*shader, lengthOfLog, &lengthOfLog, log);
- VAP_Info(kQGVAPModuleCommon, @"MODULE_DECODE Shader compile log:\n%s", log)
- free(log);
- }
- #endif
- glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
- if (status == 0) {
- glDeleteShader(*shader);
- return NO;
- }
- return YES;
- }
- - (BOOL)compileShader:(GLuint *)shader type:(GLenum)type URL:(NSURL *)URL {
-
- VAP_Info(kQGVAPModuleCommon, @"compileShader");
- NSError *error;
- NSString *sourceString = [[NSString alloc] initWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:&error];
- if (sourceString == nil) {
- VAP_Event(kQGVAPModuleCommon, @"Failed to load vertex shader: %@", [error localizedDescription]);
- return NO;
- }
-
- const GLchar *source;
- source = (GLchar *)[sourceString UTF8String];
- *shader = glCreateShader(type);
- glShaderSource(*shader, 1, &source, NULL);
- glCompileShader(*shader);
-
- #if defined(DEBUG)
- GLint lengthOfLog;
- glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &lengthOfLog);
- if (lengthOfLog > 0) {
- GLchar *log = (GLchar *)malloc(lengthOfLog);
- glGetShaderInfoLog(*shader, lengthOfLog, &lengthOfLog, log);
- VAP_Info(kQGVAPModuleCommon, @"Shader compile log:\n%s", log);
- free(log);
- }
- #endif
-
- GLint status;
- glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
- if (status == 0) {
- glDeleteShader(*shader);
- return NO;
- }
-
- return YES;
- }
- - (BOOL)linkProgram:(GLuint)prog {
-
- GLint status;
- glLinkProgram(prog);
-
- #if defined(DEBUG)
- GLint lengthOfLog;
- glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &lengthOfLog);
- if (lengthOfLog > 0) {
- GLchar *log = (GLchar *)malloc(lengthOfLog);
- glGetProgramInfoLog(prog, lengthOfLog, &lengthOfLog, log);
- VAP_Info(kQGVAPModuleCommon, @"Program link log:\n%s", log);
- free(log);
- }
- #endif
-
- glGetProgramiv(prog, GL_LINK_STATUS, &status);
- if (status == 0) {
- return NO;
- }
-
- return YES;
- }
- - (BOOL)isValidateProgram:(GLuint)prog {
-
- GLint logLength, status;
- glValidateProgram(prog);
- glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
- if (logLength > 0) {
- GLchar *log = (GLchar *)malloc(logLength);
- glGetProgramInfoLog(prog, logLength, &logLength, log);
- VAP_Info(kQGVAPModuleCommon, @"Program validate log:\n%s", log);
- free(log);
- }
-
- glGetProgramiv(prog, GL_VALIDATE_STATUS, &status);
- if (status == 0) {
- VAP_Event(kQGVAPModuleCommon, @"program is not valid:%@",@(status));
- return NO;
- }
- VAP_Info(kQGVAPModuleCommon, @"programe is valid");
- return YES;
- }
- - (void)dispose {
-
- glDisableVertexAttribArray(ATTRIB_VERTEX);
- glDisableVertexAttribArray(ATTRIB_TEXCOORD_RGB);
- glDisableVertexAttribArray(ATTRIB_TEXCOORD_ALPHA);
- }
- @end
|