/* * Copyright 2013 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 #include "JNIHelper.h" namespace ndk_helper { #define DEBUG (1) bool shader::CompileShader( GLuint* shader, const GLenum type, const char* str_file_name, const std::map& map_parameters) { std::vector data; if (!JNIHelper::GetInstance()->ReadFile(str_file_name, &data)) { LOGI("Can not open a file:%s", str_file_name); return false; } const char REPLACEMENT_TAG = '*'; // Fill-in parameters std::string str(data.begin(), data.end()); std::string str_replacement_map(data.size(), ' '); std::map::const_iterator it = map_parameters.begin(); std::map::const_iterator itEnd = map_parameters.end(); while (it != itEnd) { size_t pos = 0; while ((pos = str.find(it->first, pos)) != std::string::npos) { // Check if the sub string is already touched size_t replaced_pos = str_replacement_map.find(REPLACEMENT_TAG, pos); if (replaced_pos == std::string::npos || replaced_pos > pos) { str.replace(pos, it->first.length(), it->second); str_replacement_map.replace(pos, it->first.length(), it->first.length(), REPLACEMENT_TAG); pos += it->second.length(); } else { // The replacement target has been touched by other tag, skipping them pos += it->second.length(); } } it++; } LOGI("Patched Shdader:\n%s", str.c_str()); std::vector v(str.begin(), str.end()); str.clear(); return shader::CompileShader(shader, type, v); } bool shader::CompileShader(GLuint* shader, const GLenum type, const GLchar* source, const int32_t iSize) { if (source == NULL || iSize <= 0) return false; *shader = glCreateShader(type); glShaderSource(*shader, 1, &source, &iSize); // Not specifying 3rd parameter // (size) could be troublesome.. glCompileShader(*shader); #if defined(DEBUG) GLint logLength; glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); if (logLength > 0) { GLchar* log = (GLchar*)malloc(logLength); glGetShaderInfoLog(*shader, logLength, &logLength, log); LOGI("Shader compile log:\n%s", log); free(log); } #endif GLint status; glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); if (status == 0) { glDeleteShader(*shader); return false; } return true; } bool shader::CompileShader(GLuint* shader, const GLenum type, std::vector& data) { if (!data.size()) return false; const GLchar* source = (GLchar*)&data[0]; int32_t iSize = data.size(); return shader::CompileShader(shader, type, source, iSize); } bool shader::CompileShader(GLuint* shader, const GLenum type, const char* strFileName) { std::vector data; bool b = JNIHelper::GetInstance()->ReadFile(strFileName, &data); if (!b) { LOGI("Can not open a file:%s", strFileName); return false; } return shader::CompileShader(shader, type, data); } bool shader::LinkProgram(const GLuint prog) { GLint status; glLinkProgram(prog); #if defined(DEBUG) GLint logLength; glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); if (logLength > 0) { GLchar* log = (GLchar*)malloc(logLength); glGetProgramInfoLog(prog, logLength, &logLength, log); LOGI("Program link log:\n%s", log); free(log); } #endif glGetProgramiv(prog, GL_LINK_STATUS, &status); if (status == 0) { LOGI("Program link failed\n"); return false; } return true; } bool shader::ValidateProgram(const 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); LOGI("Program validate log:\n%s", log); free(log); } glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); if (status == 0) return false; return true; } } // namespace ndk_helper