blob: e2dbd76e64a44deca1fb7f8ff16154c18021f5b2 [file] [log] [blame]
Steve Kondik55db0532017-06-12 11:27:18 -07001/*
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#define LOG_TAG "VNC"
18//#define LOG_NDEBUG 0
19#include <utils/Log.h>
20
21#include "Program.h"
22
Steve Kondik4d99fc72017-06-13 08:06:56 -070023#include <GLES3/gl3.h>
24#include <GLES3/gl3ext.h>
Steve Kondik55db0532017-06-12 11:27:18 -070025#include <GLES2/gl2ext.h>
26
27#include <assert.h>
28
29using namespace android;
30
31// 4x4 identity matrix
32const float Program::kIdentity[] = {
33 1.0f, 0.0f, 0.0f, 0.0f,
34 0.0f, 1.0f, 0.0f, 0.0f,
35 0.0f, 0.0f, 1.0f, 0.0f,
36 0.0f, 0.0f, 0.0f, 1.0f
37};
38
39// Simple vertex shader. Texture coord calc includes matrix for GLConsumer
40// transform.
41static const char* kVertexShader =
42 "uniform mat4 uMVPMatrix;\n"
43 "uniform mat4 uGLCMatrix;\n"
44 "attribute vec4 aPosition;\n"
45 "attribute vec4 aTextureCoord;\n"
46 "varying vec2 vTextureCoord;\n"
47 "void main() {\n"
48 " gl_Position = uMVPMatrix * aPosition;\n"
49 " vTextureCoord = (uGLCMatrix * aTextureCoord).xy;\n"
50 "}\n";
51
52// Trivial fragment shader for external texture.
53static const char* kExtFragmentShader =
54 "#extension GL_OES_EGL_image_external : require\n"
55 "precision mediump float;\n"
56 "varying vec2 vTextureCoord;\n"
57 "uniform samplerExternalOES uTexture;\n"
58 "void main() {\n"
59 " gl_FragColor = texture2D(uTexture, vTextureCoord);\n"
60 "}\n";
61
62// Trivial fragment shader for mundane texture.
63static const char* kFragmentShader =
64 "precision mediump float;\n"
65 "varying vec2 vTextureCoord;\n"
66 "uniform sampler2D uTexture;\n"
67 "void main() {\n"
68 " gl_FragColor = texture2D(uTexture, vTextureCoord);\n"
69 //" gl_FragColor = vec4(0.2, 1.0, 0.2, 1.0);\n"
70 "}\n";
71
72status_t Program::setup(ProgramType type) {
73 ALOGV("Program::setup type=%d", type);
74 status_t err;
75
76 mProgramType = type;
77
78 GLuint program;
79 if (type == PROGRAM_TEXTURE_2D) {
80 err = createProgram(&program, kVertexShader, kFragmentShader);
81 } else {
82 err = createProgram(&program, kVertexShader, kExtFragmentShader);
83 }
84 if (err != NO_ERROR) {
85 return err;
86 }
87 assert(program != 0);
88
89 maPositionLoc = glGetAttribLocation(program, "aPosition");
90 maTextureCoordLoc = glGetAttribLocation(program, "aTextureCoord");
91 muMVPMatrixLoc = glGetUniformLocation(program, "uMVPMatrix");
92 muGLCMatrixLoc = glGetUniformLocation(program, "uGLCMatrix");
93 muTextureLoc = glGetUniformLocation(program, "uTexture");
94 if ((maPositionLoc | maTextureCoordLoc | muMVPMatrixLoc |
95 muGLCMatrixLoc | muTextureLoc) == -1) {
96 ALOGE("Attrib/uniform lookup failed: %#x", glGetError());
97 glDeleteProgram(program);
98 return UNKNOWN_ERROR;
99 }
100
101 mProgram = program;
102 return NO_ERROR;
103}
104
105void Program::release() {
106 ALOGV("Program::release");
107 if (mProgram != 0) {
108 glDeleteProgram(mProgram);
109 mProgram = 0;
110 }
111}
112
113status_t Program::createProgram(GLuint* outPgm, const char* vertexShader,
114 const char* fragmentShader) {
115 GLuint vs, fs;
116 status_t err;
117
118 err = compileShader(GL_VERTEX_SHADER, vertexShader, &vs);
119 if (err != NO_ERROR) {
120 return err;
121 }
122 err = compileShader(GL_FRAGMENT_SHADER, fragmentShader, &fs);
123 if (err != NO_ERROR) {
124 glDeleteShader(vs);
125 return err;
126 }
127
128 GLuint program;
129 err = linkShaderProgram(vs, fs, &program);
130 glDeleteShader(vs);
131 glDeleteShader(fs);
132 if (err == NO_ERROR) {
133 *outPgm = program;
134 }
135 return err;
136}
137
138status_t Program::compileShader(GLenum shaderType, const char* src,
139 GLuint* outShader) {
140 GLuint shader = glCreateShader(shaderType);
141 if (shader == 0) {
142 ALOGE("glCreateShader error: %#x", glGetError());
143 return UNKNOWN_ERROR;
144 }
145
146 glShaderSource(shader, 1, &src, NULL);
147 glCompileShader(shader);
148
149 GLint compiled = 0;
150 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
151 if (!compiled) {
152 ALOGE("Compile of shader type %d failed", shaderType);
153 GLint infoLen = 0;
154 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
155 if (infoLen) {
156 char* buf = new char[infoLen];
157 if (buf) {
158 glGetShaderInfoLog(shader, infoLen, NULL, buf);
159 ALOGE("Compile log: %s", buf);
160 delete[] buf;
161 }
162 }
163 glDeleteShader(shader);
164 return UNKNOWN_ERROR;
165 }
166 *outShader = shader;
167 return NO_ERROR;
168}
169
170status_t Program::linkShaderProgram(GLuint vs, GLuint fs, GLuint* outPgm) {
171 GLuint program = glCreateProgram();
172 if (program == 0) {
173 ALOGE("glCreateProgram error: %#x", glGetError());
174 return UNKNOWN_ERROR;
175 }
176
177 glAttachShader(program, vs);
178 glAttachShader(program, fs);
179 glLinkProgram(program);
180 GLint linkStatus = GL_FALSE;
181 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
182 if (linkStatus != GL_TRUE) {
183 ALOGE("glLinkProgram failed");
184 GLint bufLength = 0;
185 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
186 if (bufLength) {
187 char* buf = new char[bufLength];
188 if (buf) {
189 glGetProgramInfoLog(program, bufLength, NULL, buf);
190 ALOGE("Link log: %s", buf);
191 delete[] buf;
192 }
193 }
194 glDeleteProgram(program);
195 return UNKNOWN_ERROR;
196 }
197
198 *outPgm = program;
199 return NO_ERROR;
200}
201
202
203
204status_t Program::blit(GLuint texName, const float* texMatrix,
205 int32_t x, int32_t y, int32_t w, int32_t h, bool invert) const {
206 ALOGV("Program::blit %d xy=%d,%d wh=%d,%d", texName, x, y, w, h);
207
208 const float pos[] = {
209 float(x), float(y+h),
210 float(x+w), float(y+h),
211 float(x), float(y),
212 float(x+w), float(y),
213 };
214 const float uv[] = {
215 0.0f, 0.0f,
216 1.0f, 0.0f,
217 0.0f, 1.0f,
218 1.0f, 1.0f,
219 };
220 status_t err;
221
222 err = beforeDraw(texName, texMatrix, pos, uv, invert);
223 if (err == NO_ERROR) {
224 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
225 err = afterDraw();
226 }
227 return err;
228}
229
230status_t Program::drawTriangles(GLuint texName, const float* texMatrix,
231 const float* vertices, const float* texes, size_t count) const {
232 ALOGV("Program::drawTriangles texName=%d", texName);
233
234 status_t err;
235
236 err = beforeDraw(texName, texMatrix, vertices, texes, false);
237 if (err == NO_ERROR) {
238 glDrawArrays(GL_TRIANGLES, 0, count);
239 err = afterDraw();
240 }
241 return err;
242}
243
244status_t Program::beforeDraw(GLuint texName, const float* texMatrix,
245 const float* vertices, const float* texes, bool invert) const {
246 // Create an orthographic projection matrix based on viewport size.
247 GLint vp[4];
248 glGetIntegerv(GL_VIEWPORT, vp);
249 float screenToNdc[16] = {
250 2.0f/float(vp[2]), 0.0f, 0.0f, 0.0f,
251 0.0f, -2.0f/float(vp[3]), 0.0f, 0.0f,
252 0.0f, 0.0f, 1.0f, 0.0f,
253 -1.0f, 1.0f, 0.0f, 1.0f,
254 };
255 if (invert) {
256 screenToNdc[5] = -screenToNdc[5];
257 screenToNdc[13] = -screenToNdc[13];
258 }
259
260 glUseProgram(mProgram);
261
262 glVertexAttribPointer(maPositionLoc, 2, GL_FLOAT, GL_FALSE, 0, vertices);
263 glVertexAttribPointer(maTextureCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, texes);
264 glEnableVertexAttribArray(maPositionLoc);
265 glEnableVertexAttribArray(maTextureCoordLoc);
266
267 glUniformMatrix4fv(muMVPMatrixLoc, 1, GL_FALSE, screenToNdc);
268 glUniformMatrix4fv(muGLCMatrixLoc, 1, GL_FALSE, texMatrix);
269
270 glActiveTexture(GL_TEXTURE0);
271
272 switch (mProgramType) {
273 case PROGRAM_EXTERNAL_TEXTURE:
274 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texName);
275 break;
276 case PROGRAM_TEXTURE_2D:
277 glBindTexture(GL_TEXTURE_2D, texName);
278 break;
279 default:
280 ALOGE("unexpected program type %d", mProgramType);
281 return UNKNOWN_ERROR;
282 }
283
284 glUniform1i(muTextureLoc, 0);
285
286 GLenum glErr;
287 if ((glErr = glGetError()) != GL_NO_ERROR) {
288 ALOGE("GL error before draw: %#x", glErr);
289 glDisableVertexAttribArray(maPositionLoc);
290 glDisableVertexAttribArray(maTextureCoordLoc);
291 return UNKNOWN_ERROR;
292 }
293
294 return NO_ERROR;
295}
296
297status_t Program::afterDraw() const {
298 glDisableVertexAttribArray(maPositionLoc);
299 glDisableVertexAttribArray(maTextureCoordLoc);
300
301 GLenum glErr;
302 if ((glErr = glGetError()) != GL_NO_ERROR) {
303 ALOGE("GL error after draw: %#x", glErr);
304 return UNKNOWN_ERROR;
305 }
306
307 return NO_ERROR;
308}