1 /*
2  * Copyright 2019 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 "GenericProgram.h"
18 
19 #include <GLES/gl.h>
20 #include <GLES/glext.h>
21 #include <GLES2/gl2.h>
22 #include <GLES2/gl2ext.h>
23 
24 namespace android {
25 namespace renderengine {
26 namespace gl {
27 
GenericProgram(GLESRenderEngine & engine)28 GenericProgram::GenericProgram(GLESRenderEngine& engine) : mEngine(engine) {}
29 
~GenericProgram()30 GenericProgram::~GenericProgram() {
31     if (mVertexShaderHandle != 0) {
32         if (mProgramHandle != 0) {
33             glDetachShader(mProgramHandle, mVertexShaderHandle);
34         }
35         glDeleteShader(mVertexShaderHandle);
36     }
37 
38     if (mFragmentShaderHandle != 0) {
39         if (mProgramHandle != 0) {
40             glDetachShader(mProgramHandle, mFragmentShaderHandle);
41         }
42         glDeleteShader(mFragmentShaderHandle);
43     }
44 
45     if (mProgramHandle != 0) {
46         glDeleteProgram(mProgramHandle);
47     }
48 }
49 
compile(string vertexShader,string fragmentShader)50 void GenericProgram::compile(string vertexShader, string fragmentShader) {
51     mVertexShaderHandle = compileShader(GL_VERTEX_SHADER, vertexShader);
52     mFragmentShaderHandle = compileShader(GL_FRAGMENT_SHADER, fragmentShader);
53     if (mVertexShaderHandle == 0 || mFragmentShaderHandle == 0) {
54         ALOGE("Aborting program creation.");
55         return;
56     }
57     mProgramHandle = createAndLink(mVertexShaderHandle, mFragmentShaderHandle);
58     mEngine.checkErrors("Linking program");
59 }
60 
useProgram() const61 void GenericProgram::useProgram() const {
62     glUseProgram(mProgramHandle);
63 }
64 
compileShader(GLuint type,string src) const65 GLuint GenericProgram::compileShader(GLuint type, string src) const {
66     const GLuint shader = glCreateShader(type);
67     if (shader == 0) {
68         mEngine.checkErrors("Creating shader");
69         return 0;
70     }
71     const GLchar* charSrc = (const GLchar*)src.c_str();
72     glShaderSource(shader, 1, &charSrc, nullptr);
73     glCompileShader(shader);
74 
75     GLint isCompiled = 0;
76     glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
77     if (isCompiled == GL_FALSE) {
78         GLint maxLength = 0;
79         glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
80         string errorLog;
81         errorLog.reserve(maxLength);
82         glGetShaderInfoLog(shader, maxLength, &maxLength, errorLog.data());
83         glDeleteShader(shader);
84         ALOGE("Error compiling shader: %s", errorLog.c_str());
85         return 0;
86     }
87     return shader;
88 }
createAndLink(GLuint vertexShader,GLuint fragmentShader) const89 GLuint GenericProgram::createAndLink(GLuint vertexShader, GLuint fragmentShader) const {
90     const GLuint program = glCreateProgram();
91     mEngine.checkErrors("Creating program");
92 
93     glAttachShader(program, vertexShader);
94     glAttachShader(program, fragmentShader);
95     glLinkProgram(program);
96     mEngine.checkErrors("Linking program");
97     return program;
98 }
99 
getUniformLocation(const string name) const100 GLuint GenericProgram::getUniformLocation(const string name) const {
101     if (mProgramHandle == 0) {
102         ALOGE("Can't get location of %s on an invalid program.", name.c_str());
103         return -1;
104     }
105     return glGetUniformLocation(mProgramHandle, (const GLchar*)name.c_str());
106 }
107 
getAttributeLocation(const string name) const108 GLuint GenericProgram::getAttributeLocation(const string name) const {
109     if (mProgramHandle == 0) {
110         ALOGE("Can't get location of %s on an invalid program.", name.c_str());
111         return -1;
112     }
113     return glGetAttribLocation(mProgramHandle, (const GLchar*)name.c_str());
114 }
115 
isValid() const116 bool GenericProgram::isValid() const {
117     return mProgramHandle != 0;
118 }
119 
120 } // namespace gl
121 } // namespace renderengine
122 } // namespace android
123