/* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * 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. */ #include "shader.h" #include #include #include // Given shader source, load and compile it static GLuint loadShader(GLenum type, const char *shaderSrc, const char *name) { // Create the shader object GLuint shader = glCreateShader (type); if (shader == 0) { return 0; } // Load and compile the shader glShaderSource(shader, 1, &shaderSrc, nullptr); glCompileShader(shader); // Verify the compilation worked as expected GLint compiled = 0; glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); if (!compiled) { LOG(ERROR) << "Error compiling " << (type==GL_VERTEX_SHADER ? "vtx":"pxl") << " shader for " << name; GLint size = 0; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size); if (size > 0) { // Get and report the error message std::unique_ptr infoLog(new char[size]); glGetShaderInfoLog(shader, size, NULL, infoLog.get()); LOG(ERROR) << " msg:\n" << infoLog.get(); } glDeleteShader(shader); return 0; } return shader; } // Create a program object given vertex and pixels shader source GLuint buildShaderProgram(const char* vtxSrc, const char* pxlSrc, const char* name) { GLuint program = glCreateProgram(); if (program == 0) { LOG(ERROR) << "Failed to allocate program object"; return 0; } // Compile the shaders and bind them to this program GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vtxSrc, name); if (vertexShader == 0) { LOG(ERROR) << "Failed to load vertex shader"; glDeleteProgram(program); return 0; } GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pxlSrc, name); if (pixelShader == 0) { LOG(ERROR) << "Failed to load pixel shader"; glDeleteProgram(program); glDeleteShader(vertexShader); return 0; } glAttachShader(program, vertexShader); glAttachShader(program, pixelShader); // Link the program glLinkProgram(program); GLint linked = 0; glGetProgramiv(program, GL_LINK_STATUS, &linked); if (!linked) { LOG(ERROR) << "Error linking program."; GLint size = 0; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &size); if (size > 0) { // Get and report the error message std::unique_ptr infoLog(new char[size]); glGetProgramInfoLog(program, size, NULL, infoLog.get()); LOG(ERROR) << " msg: " << infoLog.get(); } glDeleteProgram(program); glDeleteShader(vertexShader); glDeleteShader(pixelShader); return 0; } return program; }