1 /*Gluint 2 * Copyright 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdint.h> 18 19 #include <log/log.h> 20 #include <utils/String8.h> 21 22 #include "Program.h" 23 #include "ProgramCache.h" 24 #include "Description.h" 25 26 namespace android { 27 28 Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const char* fragment) 29 : mInitialized(false) { 30 GLuint vertexId = buildShader(vertex, GL_VERTEX_SHADER); 31 GLuint fragmentId = buildShader(fragment, GL_FRAGMENT_SHADER); 32 GLuint programId = glCreateProgram(); 33 glAttachShader(programId, vertexId); 34 glAttachShader(programId, fragmentId); 35 glBindAttribLocation(programId, position, "position"); 36 glBindAttribLocation(programId, texCoords, "texCoords"); 37 glLinkProgram(programId); 38 39 GLint status; 40 glGetProgramiv(programId, GL_LINK_STATUS, &status); 41 if (status != GL_TRUE) { 42 ALOGE("Error while linking shaders:"); 43 GLint infoLen = 0; 44 glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLen); 45 if (infoLen > 1) { 46 GLchar log[infoLen]; 47 glGetProgramInfoLog(programId, infoLen, 0, &log[0]); 48 ALOGE("%s", log); 49 } 50 glDetachShader(programId, vertexId); 51 glDetachShader(programId, fragmentId); 52 glDeleteShader(vertexId); 53 glDeleteShader(fragmentId); 54 glDeleteProgram(programId); 55 } else { 56 mProgram = programId; 57 mVertexShader = vertexId; 58 mFragmentShader = fragmentId; 59 mInitialized = true; 60 61 mColorMatrixLoc = glGetUniformLocation(programId, "colorMatrix"); 62 mProjectionMatrixLoc = glGetUniformLocation(programId, "projection"); 63 mTextureMatrixLoc = glGetUniformLocation(programId, "texture"); 64 mSamplerLoc = glGetUniformLocation(programId, "sampler"); 65 mColorLoc = glGetUniformLocation(programId, "color"); 66 mAlphaPlaneLoc = glGetUniformLocation(programId, "alphaPlane"); 67 68 // set-up the default values for our uniforms 69 glUseProgram(programId); 70 const GLfloat m[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 }; 71 glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, m); 72 glEnableVertexAttribArray(0); 73 } 74 } 75 76 Program::~Program() { 77 } 78 79 bool Program::isValid() const { 80 return mInitialized; 81 } 82 83 void Program::use() { 84 glUseProgram(mProgram); 85 } 86 87 GLuint Program::getAttrib(const char* name) const { 88 // TODO: maybe use a local cache 89 return glGetAttribLocation(mProgram, name); 90 } 91 92 GLint Program::getUniform(const char* name) const { 93 // TODO: maybe use a local cache 94 return glGetUniformLocation(mProgram, name); 95 } 96 97 GLuint Program::buildShader(const char* source, GLenum type) { 98 GLuint shader = glCreateShader(type); 99 glShaderSource(shader, 1, &source, 0); 100 glCompileShader(shader); 101 GLint status; 102 glGetShaderiv(shader, GL_COMPILE_STATUS, &status); 103 if (status != GL_TRUE) { 104 // Some drivers return wrong values for GL_INFO_LOG_LENGTH 105 // use a fixed size instead 106 GLchar log[512]; 107 glGetShaderInfoLog(shader, sizeof(log), 0, log); 108 ALOGE("Error while compiling shader: \n%s\n%s", source, log); 109 glDeleteShader(shader); 110 return 0; 111 } 112 return shader; 113 } 114 115 String8& Program::dumpShader(String8& result, GLenum /*type*/) { 116 GLuint shader = GL_FRAGMENT_SHADER ? mFragmentShader : mVertexShader; 117 GLint l; 118 glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &l); 119 char* src = new char[l]; 120 glGetShaderSource(shader, l, NULL, src); 121 result.append(src); 122 delete [] src; 123 return result; 124 } 125 126 void Program::setUniforms(const Description& desc) { 127 128 // TODO: we should have a mechanism here to not always reset uniforms that 129 // didn't change for this program. 130 131 if (mSamplerLoc >= 0) { 132 glUniform1i(mSamplerLoc, 0); 133 glUniformMatrix4fv(mTextureMatrixLoc, 1, GL_FALSE, desc.mTexture.getMatrix().asArray()); 134 } 135 if (mAlphaPlaneLoc >= 0) { 136 glUniform1f(mAlphaPlaneLoc, desc.mPlaneAlpha); 137 } 138 if (mColorLoc >= 0) { 139 glUniform4fv(mColorLoc, 1, desc.mColor); 140 } 141 if (mColorMatrixLoc >= 0) { 142 glUniformMatrix4fv(mColorMatrixLoc, 1, GL_FALSE, desc.mColorMatrix.asArray()); 143 } 144 // these uniforms are always present 145 glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.mProjectionMatrix.asArray()); 146 } 147 148 } /* namespace android */ 149