• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 #define LOG_TAG "OpenGLRenderer"
18 
19 #include "Program.h"
20 
21 namespace android {
22 namespace uirenderer {
23 
24 ///////////////////////////////////////////////////////////////////////////////
25 // Base program
26 ///////////////////////////////////////////////////////////////////////////////
27 
Program(const char * vertex,const char * fragment)28 Program::Program(const char* vertex, const char* fragment) {
29     mInitialized = false;
30 
31     vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
32     if (vertexShader) {
33 
34         fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
35         if (fragmentShader) {
36 
37             id = glCreateProgram();
38             glAttachShader(id, vertexShader);
39             glAttachShader(id, fragmentShader);
40             glLinkProgram(id);
41 
42             GLint status;
43             glGetProgramiv(id, GL_LINK_STATUS, &status);
44             if (status != GL_TRUE) {
45                 LOGE("Error while linking shaders:");
46                 GLint infoLen = 0;
47                 glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLen);
48                 if (infoLen > 1) {
49                     GLchar log[infoLen];
50                     glGetProgramInfoLog(id, infoLen, 0, &log[0]);
51                     LOGE("%s", log);
52                 }
53                 glDeleteShader(vertexShader);
54                 glDeleteShader(fragmentShader);
55                 glDeleteProgram(id);
56             } else {
57                 mInitialized = true;
58             }
59         }
60     }
61 
62     mUse = false;
63 
64     if (mInitialized) {
65         position = addAttrib("position");
66         transform = addUniform("transform");
67     }
68 }
69 
~Program()70 Program::~Program() {
71     if (mInitialized) {
72         glDeleteShader(vertexShader);
73         glDeleteShader(fragmentShader);
74         glDeleteProgram(id);
75     }
76 }
77 
addAttrib(const char * name)78 int Program::addAttrib(const char* name) {
79     int slot = glGetAttribLocation(id, name);
80     attributes.add(name, slot);
81     return slot;
82 }
83 
getAttrib(const char * name)84 int Program::getAttrib(const char* name) {
85     ssize_t index = attributes.indexOfKey(name);
86     if (index >= 0) {
87         return attributes.valueAt(index);
88     }
89     return addAttrib(name);
90 }
91 
addUniform(const char * name)92 int Program::addUniform(const char* name) {
93     int slot = glGetUniformLocation(id, name);
94     uniforms.add(name, slot);
95     return slot;
96 }
97 
getUniform(const char * name)98 int Program::getUniform(const char* name) {
99     ssize_t index = uniforms.indexOfKey(name);
100     if (index >= 0) {
101         return uniforms.valueAt(index);
102     }
103     return addUniform(name);
104 }
105 
buildShader(const char * source,GLenum type)106 GLuint Program::buildShader(const char* source, GLenum type) {
107     GLuint shader = glCreateShader(type);
108     glShaderSource(shader, 1, &source, 0);
109     glCompileShader(shader);
110 
111     GLint status;
112     glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
113     if (status != GL_TRUE) {
114         // Some drivers return wrong values for GL_INFO_LOG_LENGTH
115         // use a fixed size instead
116         GLchar log[512];
117         glGetShaderInfoLog(shader, sizeof(log), 0, &log[0]);
118         LOGE("Error while compiling shader: %s", log);
119         glDeleteShader(shader);
120         return 0;
121     }
122 
123     return shader;
124 }
125 
set(const mat4 & projectionMatrix,const mat4 & modelViewMatrix,const mat4 & transformMatrix,bool offset)126 void Program::set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
127         const mat4& transformMatrix, bool offset) {
128     mat4 t(projectionMatrix);
129     if (offset) {
130         // offset screenspace xy by an amount that compensates for typical precision issues
131         // in GPU hardware that tends to paint hor/vert lines in pixels shifted up and to the left.
132         // This offset value is based on an assumption that some hardware may use as little
133         // as 12.4 precision, so we offset by slightly more than 1/16.
134         t.translate(.375, .375, 0);
135     }
136     t.multiply(transformMatrix);
137     t.multiply(modelViewMatrix);
138 
139     glUniformMatrix4fv(transform, 1, GL_FALSE, &t.data[0]);
140 }
141 
setColor(const float r,const float g,const float b,const float a)142 void Program::setColor(const float r, const float g, const float b, const float a) {
143     glUniform4f(getUniform("color"), r, g, b, a);
144 }
145 
use()146 void Program::use() {
147     glUseProgram(id);
148     mUse = true;
149 
150     glEnableVertexAttribArray(position);
151 }
152 
remove()153 void Program::remove() {
154     mUse = false;
155 
156     glDisableVertexAttribArray(position);
157 }
158 
159 }; // namespace uirenderer
160 }; // namespace android
161