Program.cpp revision f9764a4f532561f6e2e985ff3b25112f1132ce44
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
21namespace android {
22namespace uirenderer {
23
24///////////////////////////////////////////////////////////////////////////////
25// Shaders
26///////////////////////////////////////////////////////////////////////////////
27
28#define SHADER_SOURCE(name, source) const char* name = #source
29
30#include "shaders/drawColor.vert"
31#include "shaders/drawColor.frag"
32
33#include "shaders/drawTexture.vert"
34#include "shaders/drawTexture.frag"
35
36#include "shaders/drawLinearGradient.vert"
37#include "shaders/drawLinearGradient.frag"
38
39///////////////////////////////////////////////////////////////////////////////
40// Base program
41///////////////////////////////////////////////////////////////////////////////
42
43Program::Program(const char* vertex, const char* fragment) {
44    vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
45    fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
46
47    id = glCreateProgram();
48    glAttachShader(id, vertexShader);
49    glAttachShader(id, fragmentShader);
50    glLinkProgram(id);
51
52    GLint status;
53    glGetProgramiv(id, GL_LINK_STATUS, &status);
54    if (status != GL_TRUE) {
55        GLint infoLen = 0;
56        glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLen);
57        if (infoLen > 1) {
58            char* log = (char*) malloc(sizeof(char) * infoLen);
59            glGetProgramInfoLog(id, infoLen, 0, log);
60            LOGE("Error while linking shaders: %s", log);
61            delete log;
62        }
63        glDeleteProgram(id);
64    }
65
66    mUse = false;
67}
68
69Program::~Program() {
70    glDeleteShader(vertexShader);
71    glDeleteShader(fragmentShader);
72    glDeleteProgram(id);
73}
74
75void Program::use() {
76    glUseProgram(id);
77    mUse = true;
78}
79
80void Program::remove() {
81    mUse = false;
82}
83
84int Program::addAttrib(const char* name) {
85    int slot = glGetAttribLocation(id, name);
86    attributes.add(name, slot);
87    return slot;
88}
89
90int Program::getAttrib(const char* name) {
91    return attributes.valueFor(name);
92}
93
94int Program::addUniform(const char* name) {
95    int slot = glGetUniformLocation(id, name);
96    uniforms.add(name, slot);
97    return slot;
98}
99
100int Program::getUniform(const char* name) {
101    return uniforms.valueFor(name);
102}
103
104GLuint Program::buildShader(const char* source, GLenum type) {
105    GLuint shader = glCreateShader(type);
106    glShaderSource(shader, 1, &source, 0);
107    glCompileShader(shader);
108
109    GLint status;
110    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
111    if (status != GL_TRUE) {
112        // Some drivers return wrong values for GL_INFO_LOG_LENGTH
113        // use a fixed size instead
114        GLchar log[512];
115        glGetShaderInfoLog(shader, sizeof(log), 0, &log[0]);
116        LOGE("Error while compiling shader: %s", log);
117        glDeleteShader(shader);
118    }
119
120    return shader;
121}
122
123///////////////////////////////////////////////////////////////////////////////
124// Draw color
125///////////////////////////////////////////////////////////////////////////////
126
127DrawColorProgram::DrawColorProgram():
128        Program(gDrawColorVertexShader, gDrawColorFragmentShader) {
129    getAttribsAndUniforms();
130}
131
132DrawColorProgram::DrawColorProgram(const char* vertex, const char* fragment):
133        Program(vertex, fragment) {
134    getAttribsAndUniforms();
135}
136
137void DrawColorProgram::getAttribsAndUniforms() {
138    position = addAttrib("position");
139    color = addUniform("color");
140    transform = addUniform("transform");
141}
142
143void DrawColorProgram::set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
144        const mat4& transformMatrix) {
145    mat4 t(projectionMatrix);
146    t.multiply(transformMatrix);
147    t.multiply(modelViewMatrix);
148
149    glUniformMatrix4fv(transform, 1, GL_FALSE, &t.data[0]);
150}
151
152void DrawColorProgram::use() {
153    Program::use();
154    glEnableVertexAttribArray(position);
155}
156
157void DrawColorProgram::remove() {
158    Program::remove();
159    glDisableVertexAttribArray(position);
160}
161
162///////////////////////////////////////////////////////////////////////////////
163// Draw texture
164///////////////////////////////////////////////////////////////////////////////
165
166DrawTextureProgram::DrawTextureProgram():
167        DrawColorProgram(gDrawTextureVertexShader, gDrawTextureFragmentShader) {
168    texCoords = addAttrib("texCoords");
169    sampler = addUniform("sampler");
170}
171
172void DrawTextureProgram::use() {
173    DrawColorProgram::use();
174    glActiveTexture(GL_TEXTURE0);
175    glUniform1i(sampler, 0);
176    glEnableVertexAttribArray(texCoords);
177}
178
179void DrawTextureProgram::remove() {
180    DrawColorProgram::remove();
181    glDisableVertexAttribArray(texCoords);
182}
183
184///////////////////////////////////////////////////////////////////////////////
185// Draw linear gradient
186///////////////////////////////////////////////////////////////////////////////
187
188DrawLinearGradientProgram::DrawLinearGradientProgram():
189        DrawColorProgram(gDrawLinearGradientVertexShader, gDrawLinearGradientFragmentShader) {
190    gradient = addUniform("gradient");
191    gradientLength = addUniform("gradientLength");
192    sampler = addUniform("sampler");
193}
194
195void DrawLinearGradientProgram::use() {
196    DrawColorProgram::use();
197    glActiveTexture(GL_TEXTURE0);
198    glUniform1i(sampler, 0);
199}
200
201void DrawLinearGradientProgram::remove() {
202    DrawColorProgram::remove();
203}
204
205}; // namespace uirenderer
206}; // namespace android
207