blob: 4d6839bfe32f6fd233f53518a97ca27d5ce3ffab [file] [log] [blame]
Mathias Agopian3f844832013-08-07 21:24:32 -07001/*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
Peiyong Lin833074a2018-08-28 11:53:54 -070017#include "Program.h"
Peiyong Lincbc184f2018-08-22 13:24:10 -070018
Mathias Agopian3f844832013-08-07 21:24:32 -070019#include <stdint.h>
20
Mark Salyzyn7823e122016-09-29 08:08:05 -070021#include <log/log.h>
Chia-I Wub027f802017-11-29 14:00:52 -080022#include <math/mat4.h>
Peiyong Lin833074a2018-08-28 11:53:54 -070023#include <renderengine/private/Description.h>
Peiyong Lincbc184f2018-08-22 13:24:10 -070024#include <utils/String8.h>
Peiyong Lin833074a2018-08-28 11:53:54 -070025#include "ProgramCache.h"
Mathias Agopian3f844832013-08-07 21:24:32 -070026
27namespace android {
Peiyong Lin833074a2018-08-28 11:53:54 -070028namespace renderengine {
29namespace gl {
Mathias Agopian3f844832013-08-07 21:24:32 -070030
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -070031Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const char* fragment)
Chia-I Wub027f802017-11-29 14:00:52 -080032 : mInitialized(false) {
Mathias Agopian3f844832013-08-07 21:24:32 -070033 GLuint vertexId = buildShader(vertex, GL_VERTEX_SHADER);
34 GLuint fragmentId = buildShader(fragment, GL_FRAGMENT_SHADER);
35 GLuint programId = glCreateProgram();
36 glAttachShader(programId, vertexId);
37 glAttachShader(programId, fragmentId);
38 glBindAttribLocation(programId, position, "position");
39 glBindAttribLocation(programId, texCoords, "texCoords");
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;
Mathias Agopian3f844832013-08-07 21:24:32 -070063 mProjectionMatrixLoc = glGetUniformLocation(programId, "projection");
64 mTextureMatrixLoc = glGetUniformLocation(programId, "texture");
65 mSamplerLoc = glGetUniformLocation(programId, "sampler");
66 mColorLoc = glGetUniformLocation(programId, "color");
Peiyong Linfb069302018-04-25 14:34:31 -070067 mDisplayMaxLuminanceLoc = glGetUniformLocation(programId, "displayMaxLuminance");
Peiyong Lina296b0c2018-04-30 16:55:29 -070068 mInputTransformMatrixLoc = glGetUniformLocation(programId, "inputTransformMatrix");
69 mOutputTransformMatrixLoc = glGetUniformLocation(programId, "outputTransformMatrix");
Mathias Agopian3f844832013-08-07 21:24:32 -070070
71 // set-up the default values for our uniforms
72 glUseProgram(programId);
Chia-I Wub027f802017-11-29 14:00:52 -080073 glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, mat4().asArray());
Mathias Agopian3f844832013-08-07 21:24:32 -070074 glEnableVertexAttribArray(0);
75 }
76}
77
Chia-I Wub027f802017-11-29 14:00:52 -080078Program::~Program() {}
Mathias Agopian3f844832013-08-07 21:24:32 -070079
80bool Program::isValid() const {
81 return mInitialized;
82}
83
84void Program::use() {
85 glUseProgram(mProgram);
86}
87
88GLuint Program::getAttrib(const char* name) const {
89 // TODO: maybe use a local cache
90 return glGetAttribLocation(mProgram, name);
91}
92
93GLint Program::getUniform(const char* name) const {
94 // TODO: maybe use a local cache
95 return glGetUniformLocation(mProgram, name);
96}
97
98GLuint 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
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -0700116String8& Program::dumpShader(String8& result, GLenum /*type*/) {
Mathias Agopian3f844832013-08-07 21:24:32 -0700117 GLuint shader = GL_FRAGMENT_SHADER ? mFragmentShader : mVertexShader;
118 GLint l;
119 glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &l);
120 char* src = new char[l];
Peiyong Lin566a3b42018-01-09 18:22:43 -0800121 glGetShaderSource(shader, l, nullptr, src);
Mathias Agopian3f844832013-08-07 21:24:32 -0700122 result.append(src);
Chia-I Wub027f802017-11-29 14:00:52 -0800123 delete[] src;
Mathias Agopian3f844832013-08-07 21:24:32 -0700124 return result;
125}
126
127void Program::setUniforms(const Description& desc) {
Mathias Agopian3f844832013-08-07 21:24:32 -0700128 // 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);
Mathias Agopiana8c386f2013-08-26 20:42:07 -0700133 glUniformMatrix4fv(mTextureMatrixLoc, 1, GL_FALSE, desc.mTexture.getMatrix().asArray());
Mathias Agopian3f844832013-08-07 21:24:32 -0700134 }
Mathias Agopian3f844832013-08-07 21:24:32 -0700135 if (mColorLoc >= 0) {
chaviw89e197a2017-10-05 15:38:42 -0700136 const float color[4] = {desc.mColor.r, desc.mColor.g, desc.mColor.b, desc.mColor.a};
chaviw13fdc492017-06-27 12:40:18 -0700137 glUniform4fv(mColorLoc, 1, color);
Mathias Agopian3f844832013-08-07 21:24:32 -0700138 }
Peiyong Lina296b0c2018-04-30 16:55:29 -0700139 if (mInputTransformMatrixLoc >= 0) {
Chia-I Wud49d6692018-06-27 07:17:41 +0800140 mat4 inputTransformMatrix = mat4(desc.mInputTransformMatrix);
Peiyong Lin00f9c022018-05-09 15:35:33 -0700141 glUniformMatrix4fv(mInputTransformMatrixLoc, 1, GL_FALSE, inputTransformMatrix.asArray());
Peiyong Lina296b0c2018-04-30 16:55:29 -0700142 }
143 if (mOutputTransformMatrixLoc >= 0) {
144 // The output transform matrix and color matrix can be combined as one matrix
145 // that is applied right before applying OETF.
146 mat4 outputTransformMatrix = desc.mColorMatrix * desc.mOutputTransformMatrix;
147 glUniformMatrix4fv(mOutputTransformMatrixLoc, 1, GL_FALSE,
148 outputTransformMatrix.asArray());
Mathias Agopianff2ed702013-09-01 21:36:12 -0700149 }
Peiyong Linfb069302018-04-25 14:34:31 -0700150 if (mDisplayMaxLuminanceLoc >= 0) {
151 glUniform1f(mDisplayMaxLuminanceLoc, desc.mDisplayMaxLuminance);
152 }
Mathias Agopian3f844832013-08-07 21:24:32 -0700153 // these uniforms are always present
Mathias Agopiana8c386f2013-08-26 20:42:07 -0700154 glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.mProjectionMatrix.asArray());
Mathias Agopian3f844832013-08-07 21:24:32 -0700155}
156
Peiyong Lin833074a2018-08-28 11:53:54 -0700157} // namespace gl
158} // namespace renderengine
159} // namespace android