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