Program.cpp revision 49457ac092071a8f964f7f69156093657ccdc3d0
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 21#include "Program.h" 22#include "ProgramCache.h" 23#include "Description.h" 24#include <utils/String8.h> 25 26namespace android { 27 28Program::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 mProjectionMatrixLoc = glGetUniformLocation(programId, "projection"); 62 mTextureMatrixLoc = glGetUniformLocation(programId, "texture"); 63 mSamplerLoc = glGetUniformLocation(programId, "sampler"); 64 mColorLoc = glGetUniformLocation(programId, "color"); 65 mAlphaPlaneLoc = glGetUniformLocation(programId, "alphaPlane"); 66 67 // set-up the default values for our uniforms 68 glUseProgram(programId); 69 const GLfloat m[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 }; 70 glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, m); 71 glEnableVertexAttribArray(0); 72 } 73} 74 75Program::~Program() { 76} 77 78bool Program::isValid() const { 79 return mInitialized; 80} 81 82void Program::use() { 83 glUseProgram(mProgram); 84} 85 86GLuint Program::getAttrib(const char* name) const { 87 // TODO: maybe use a local cache 88 return glGetAttribLocation(mProgram, name); 89} 90 91GLint Program::getUniform(const char* name) const { 92 // TODO: maybe use a local cache 93 return glGetUniformLocation(mProgram, name); 94} 95 96GLuint Program::buildShader(const char* source, GLenum type) { 97 GLuint shader = glCreateShader(type); 98 glShaderSource(shader, 1, &source, 0); 99 glCompileShader(shader); 100 GLint status; 101 glGetShaderiv(shader, GL_COMPILE_STATUS, &status); 102 if (status != GL_TRUE) { 103 // Some drivers return wrong values for GL_INFO_LOG_LENGTH 104 // use a fixed size instead 105 GLchar log[512]; 106 glGetShaderInfoLog(shader, sizeof(log), 0, log); 107 ALOGE("Error while compiling shader: \n%s\n%s", source, log); 108 glDeleteShader(shader); 109 return 0; 110 } 111 return shader; 112} 113 114String8& Program::dumpShader(String8& result, GLenum type) { 115 GLuint shader = GL_FRAGMENT_SHADER ? mFragmentShader : mVertexShader; 116 GLint l; 117 glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &l); 118 char* src = new char[l]; 119 glGetShaderSource(shader, l, NULL, src); 120 result.append(src); 121 delete [] src; 122 return result; 123} 124 125void Program::setUniforms(const Description& desc) { 126 127 // TODO: we should have a mechanism here to not always reset uniforms that 128 // didn't change for this program. 129 130 if (mSamplerLoc >= 0) { 131 glUniform1i(mSamplerLoc, 0); 132 glUniformMatrix4fv(mTextureMatrixLoc, 1, GL_FALSE, desc.mTexture.getMatrix()); 133 } 134 if (mAlphaPlaneLoc >= 0) { 135 glUniform1f(mAlphaPlaneLoc, desc.mPlaneAlpha); 136 } 137 if (mColorLoc >= 0) { 138 glUniform4fv(mColorLoc, 1, desc.mColor); 139 } 140 // these uniforms are always present 141 glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.mProjectionMatrix); 142} 143 144} /* namespace android */ 145