• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <math/mat4.h>
23 #include "Description.h"
24 #include "Program.h"
25 #include "ProgramCache.h"
26 
27 namespace android {
28 
Program(const ProgramCache::Key &,const char * vertex,const char * fragment)29 Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const char* fragment)
30       : mInitialized(false) {
31     GLuint vertexId = buildShader(vertex, GL_VERTEX_SHADER);
32     GLuint fragmentId = buildShader(fragment, GL_FRAGMENT_SHADER);
33     GLuint programId = glCreateProgram();
34     glAttachShader(programId, vertexId);
35     glAttachShader(programId, fragmentId);
36     glBindAttribLocation(programId, position, "position");
37     glBindAttribLocation(programId, texCoords, "texCoords");
38     glLinkProgram(programId);
39 
40     GLint status;
41     glGetProgramiv(programId, GL_LINK_STATUS, &status);
42     if (status != GL_TRUE) {
43         ALOGE("Error while linking shaders:");
44         GLint infoLen = 0;
45         glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLen);
46         if (infoLen > 1) {
47             GLchar log[infoLen];
48             glGetProgramInfoLog(programId, infoLen, 0, &log[0]);
49             ALOGE("%s", log);
50         }
51         glDetachShader(programId, vertexId);
52         glDetachShader(programId, fragmentId);
53         glDeleteShader(vertexId);
54         glDeleteShader(fragmentId);
55         glDeleteProgram(programId);
56     } else {
57         mProgram = programId;
58         mVertexShader = vertexId;
59         mFragmentShader = fragmentId;
60         mInitialized = true;
61         mProjectionMatrixLoc = glGetUniformLocation(programId, "projection");
62         mTextureMatrixLoc = glGetUniformLocation(programId, "texture");
63         mSamplerLoc = glGetUniformLocation(programId, "sampler");
64         mColorLoc = glGetUniformLocation(programId, "color");
65         mDisplayMaxLuminanceLoc = glGetUniformLocation(programId, "displayMaxLuminance");
66         mInputTransformMatrixLoc = glGetUniformLocation(programId, "inputTransformMatrix");
67         mOutputTransformMatrixLoc = glGetUniformLocation(programId, "outputTransformMatrix");
68 
69         // set-up the default values for our uniforms
70         glUseProgram(programId);
71         glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, mat4().asArray());
72         glEnableVertexAttribArray(0);
73     }
74 }
75 
~Program()76 Program::~Program() {}
77 
isValid() const78 bool Program::isValid() const {
79     return mInitialized;
80 }
81 
use()82 void Program::use() {
83     glUseProgram(mProgram);
84 }
85 
getAttrib(const char * name) const86 GLuint Program::getAttrib(const char* name) const {
87     // TODO: maybe use a local cache
88     return glGetAttribLocation(mProgram, name);
89 }
90 
getUniform(const char * name) const91 GLint Program::getUniform(const char* name) const {
92     // TODO: maybe use a local cache
93     return glGetUniformLocation(mProgram, name);
94 }
95 
buildShader(const char * source,GLenum type)96 GLuint 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 
dumpShader(String8 & result,GLenum)114 String8& 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, nullptr, src);
120     result.append(src);
121     delete[] src;
122     return result;
123 }
124 
setUniforms(const Description & desc)125 void Program::setUniforms(const Description& desc) {
126     // TODO: we should have a mechanism here to not always reset uniforms that
127     // didn't change for this program.
128 
129     if (mSamplerLoc >= 0) {
130         glUniform1i(mSamplerLoc, 0);
131         glUniformMatrix4fv(mTextureMatrixLoc, 1, GL_FALSE, desc.mTexture.getMatrix().asArray());
132     }
133     if (mColorLoc >= 0) {
134         const float color[4] = {desc.mColor.r, desc.mColor.g, desc.mColor.b, desc.mColor.a};
135         glUniform4fv(mColorLoc, 1, color);
136     }
137     if (mInputTransformMatrixLoc >= 0) {
138         // If the input transform matrix is not identity matrix, we want to merge
139         // the saturation matrix with input transform matrix so that the saturation
140         // matrix is applied at the correct stage.
141         mat4 inputTransformMatrix = mat4(desc.mInputTransformMatrix) * desc.mSaturationMatrix;
142         glUniformMatrix4fv(mInputTransformMatrixLoc, 1, GL_FALSE, inputTransformMatrix.asArray());
143     }
144     if (mOutputTransformMatrixLoc >= 0) {
145         // The output transform matrix and color matrix can be combined as one matrix
146         // that is applied right before applying OETF.
147         mat4 outputTransformMatrix = desc.mColorMatrix * desc.mOutputTransformMatrix;
148         // If there is no input transform matrix, we want to merge the saturation
149         // matrix with output transform matrix to avoid extra matrix multiplication
150         // in shader.
151         if (mInputTransformMatrixLoc < 0) {
152             outputTransformMatrix *= desc.mSaturationMatrix;
153         }
154         glUniformMatrix4fv(mOutputTransformMatrixLoc, 1, GL_FALSE,
155                            outputTransformMatrix.asArray());
156     }
157     if (mDisplayMaxLuminanceLoc >= 0) {
158         glUniform1f(mDisplayMaxLuminanceLoc, desc.mDisplayMaxLuminance);
159     }
160     // these uniforms are always present
161     glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.mProjectionMatrix.asArray());
162 }
163 
164 } /* namespace android */
165