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 "Program.h" 18 19 #include <stdint.h> 20 21 #include <log/log.h> 22 #include <math/mat4.h> 23 #include <utils/String8.h> 24 #include "ProgramCache.h" 25 26 namespace android { 27 namespace renderengine { 28 namespace gl { 29 30 Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const char* fragment) 31 : mInitialized(false) { 32 GLuint vertexId = buildShader(vertex, GL_VERTEX_SHADER); 33 GLuint fragmentId = buildShader(fragment, GL_FRAGMENT_SHADER); 34 GLuint programId = glCreateProgram(); 35 glAttachShader(programId, vertexId); 36 glAttachShader(programId, fragmentId); 37 glBindAttribLocation(programId, position, "position"); 38 glBindAttribLocation(programId, texCoords, "texCoords"); 39 glBindAttribLocation(programId, cropCoords, "cropCoords"); 40 glLinkProgram(programId); 41 42 GLint status; 43 glGetProgramiv(programId, GL_LINK_STATUS, &status); 44 if (status != GL_TRUE) { 45 ALOGE("Error while linking shaders:"); 46 GLint infoLen = 0; 47 glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLen); 48 if (infoLen > 1) { 49 GLchar log[infoLen]; 50 glGetProgramInfoLog(programId, infoLen, 0, &log[0]); 51 ALOGE("%s", log); 52 } 53 glDetachShader(programId, vertexId); 54 glDetachShader(programId, fragmentId); 55 glDeleteShader(vertexId); 56 glDeleteShader(fragmentId); 57 glDeleteProgram(programId); 58 } else { 59 mProgram = programId; 60 mVertexShader = vertexId; 61 mFragmentShader = fragmentId; 62 mInitialized = true; 63 mProjectionMatrixLoc = glGetUniformLocation(programId, "projection"); 64 mTextureMatrixLoc = glGetUniformLocation(programId, "texture"); 65 mSamplerLoc = glGetUniformLocation(programId, "sampler"); 66 mColorLoc = glGetUniformLocation(programId, "color"); 67 mDisplayMaxLuminanceLoc = glGetUniformLocation(programId, "displayMaxLuminance"); 68 mInputTransformMatrixLoc = glGetUniformLocation(programId, "inputTransformMatrix"); 69 mOutputTransformMatrixLoc = glGetUniformLocation(programId, "outputTransformMatrix"); 70 mCornerRadiusLoc = glGetUniformLocation(programId, "cornerRadius"); 71 mCropCenterLoc = glGetUniformLocation(programId, "cropCenter"); 72 73 // set-up the default values for our uniforms 74 glUseProgram(programId); 75 glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, mat4().asArray()); 76 glEnableVertexAttribArray(0); 77 } 78 } 79 80 bool Program::isValid() const { 81 return mInitialized; 82 } 83 84 void Program::use() { 85 glUseProgram(mProgram); 86 } 87 88 GLuint Program::getAttrib(const char* name) const { 89 // TODO: maybe use a local cache 90 return glGetAttribLocation(mProgram, name); 91 } 92 93 GLint Program::getUniform(const char* name) const { 94 // TODO: maybe use a local cache 95 return glGetUniformLocation(mProgram, name); 96 } 97 98 GLuint Program::buildShader(const char* source, GLenum type) { 99 GLuint shader = glCreateShader(type); 100 glShaderSource(shader, 1, &source, 0); 101 glCompileShader(shader); 102 GLint status; 103 glGetShaderiv(shader, GL_COMPILE_STATUS, &status); 104 if (status != GL_TRUE) { 105 // Some drivers return wrong values for GL_INFO_LOG_LENGTH 106 // use a fixed size instead 107 GLchar log[512]; 108 glGetShaderInfoLog(shader, sizeof(log), 0, log); 109 ALOGE("Error while compiling shader: \n%s\n%s", source, log); 110 glDeleteShader(shader); 111 return 0; 112 } 113 return shader; 114 } 115 116 void Program::setUniforms(const Description& desc) { 117 // TODO: we should have a mechanism here to not always reset uniforms that 118 // didn't change for this program. 119 120 if (mSamplerLoc >= 0) { 121 glUniform1i(mSamplerLoc, 0); 122 glUniformMatrix4fv(mTextureMatrixLoc, 1, GL_FALSE, desc.texture.getMatrix().asArray()); 123 } 124 if (mColorLoc >= 0) { 125 const float color[4] = {desc.color.r, desc.color.g, desc.color.b, desc.color.a}; 126 glUniform4fv(mColorLoc, 1, color); 127 } 128 if (mInputTransformMatrixLoc >= 0) { 129 mat4 inputTransformMatrix = desc.inputTransformMatrix; 130 glUniformMatrix4fv(mInputTransformMatrixLoc, 1, GL_FALSE, inputTransformMatrix.asArray()); 131 } 132 if (mOutputTransformMatrixLoc >= 0) { 133 // The output transform matrix and color matrix can be combined as one matrix 134 // that is applied right before applying OETF. 135 mat4 outputTransformMatrix = desc.colorMatrix * desc.outputTransformMatrix; 136 glUniformMatrix4fv(mOutputTransformMatrixLoc, 1, GL_FALSE, outputTransformMatrix.asArray()); 137 } 138 if (mDisplayMaxLuminanceLoc >= 0) { 139 glUniform1f(mDisplayMaxLuminanceLoc, desc.displayMaxLuminance); 140 } 141 if (mCornerRadiusLoc >= 0) { 142 glUniform1f(mCornerRadiusLoc, desc.cornerRadius); 143 } 144 if (mCropCenterLoc >= 0) { 145 glUniform2f(mCropCenterLoc, desc.cropSize.x / 2.0f, desc.cropSize.y / 2.0f); 146 } 147 // these uniforms are always present 148 glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.projectionMatrix.asArray()); 149 } 150 151 } // namespace gl 152 } // namespace renderengine 153 } // namespace android 154