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 
26 namespace android {
27 
Program(const ProgramCache::Key &,const char * vertex,const char * fragment)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 
~Program()76 Program::~Program() {
77 }
78 
isValid() const79 bool Program::isValid() const {
80     return mInitialized;
81 }
82 
use()83 void Program::use() {
84     glUseProgram(mProgram);
85 }
86 
getAttrib(const char * name) const87 GLuint Program::getAttrib(const char* name) const {
88     // TODO: maybe use a local cache
89     return glGetAttribLocation(mProgram, name);
90 }
91 
getUniform(const char * name) const92 GLint Program::getUniform(const char* name) const {
93     // TODO: maybe use a local cache
94     return glGetUniformLocation(mProgram, name);
95 }
96 
buildShader(const char * source,GLenum type)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 
dumpShader(String8 & result,GLenum)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 
setUniforms(const Description & desc)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