1 /*
2 * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
3 * Not a Contribution.
4 *
5 * Copyright 2015 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #include "glengine.h"
21 #include <log/log.h>
22 #include "engine.h"
23
24 void checkGlError(const char *, int);
25 void checkEglError(const char *, int);
26
27 class EngineContext {
28 public:
29 EGLDisplay eglDisplay;
30 EGLContext eglContext;
31 EGLSurface eglSurface;
EngineContext()32 EngineContext()
33 {
34 eglDisplay = EGL_NO_DISPLAY;
35 eglContext = EGL_NO_CONTEXT;
36 eglSurface = EGL_NO_SURFACE;
37 }
38 };
39
40 //-----------------------------------------------------------------------------
41 // Make Current
engine_bind(void * context)42 void engine_bind(void* context)
43 //-----------------------------------------------------------------------------
44 {
45 EngineContext* engineContext = (EngineContext*)(context);
46 EGL(eglMakeCurrent(engineContext->eglDisplay, engineContext->eglSurface, engineContext->eglSurface, engineContext->eglContext));
47 }
48
49 //-----------------------------------------------------------------------------
50 // initialize GL
51 //
engine_initialize(bool isSecure)52 void* engine_initialize(bool isSecure)
53 //-----------------------------------------------------------------------------
54 {
55 EngineContext* engineContext = new EngineContext();
56
57 // display
58 engineContext->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
59 EGL(eglBindAPI(EGL_OPENGL_ES_API));
60
61 // initialize
62 EGL(eglInitialize(engineContext->eglDisplay, 0, 0));
63
64 // config
65 EGLConfig eglConfig;
66 EGLint eglConfigAttribList[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
67 EGL_RED_SIZE, 8,
68 EGL_GREEN_SIZE, 8,
69 EGL_BLUE_SIZE, 8,
70 EGL_ALPHA_SIZE, 8,
71 EGL_NONE};
72 int numConfig = 0;
73 EGL(eglChooseConfig(engineContext->eglDisplay, eglConfigAttribList, &eglConfig, 1, &numConfig));
74
75 // context
76 EGLint eglContextAttribList[] = {EGL_CONTEXT_CLIENT_VERSION, 3,
77 isSecure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
78 isSecure ? EGL_TRUE : EGL_NONE,
79 EGL_NONE};
80 engineContext->eglContext = eglCreateContext(engineContext->eglDisplay, eglConfig, NULL, eglContextAttribList);
81
82 // surface
83 EGLint eglSurfaceAttribList[] = {EGL_WIDTH, 1,
84 EGL_HEIGHT, 1,
85 isSecure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
86 isSecure ? EGL_TRUE : EGL_NONE,
87 EGL_NONE};
88 engineContext->eglSurface = eglCreatePbufferSurface(engineContext->eglDisplay, eglConfig, eglSurfaceAttribList);
89
90 eglMakeCurrent(engineContext->eglDisplay, engineContext->eglSurface, engineContext->eglSurface, engineContext->eglContext);
91
92 ALOGI("In %s context = %p", __FUNCTION__, (void *)(engineContext->eglContext));
93
94 return (void*)(engineContext);
95 }
96
97 //-----------------------------------------------------------------------------
98 // Shutdown.
engine_shutdown(void * context)99 void engine_shutdown(void* context)
100 //-----------------------------------------------------------------------------
101 {
102 EngineContext* engineContext = (EngineContext*)context;
103 EGL(eglMakeCurrent(engineContext->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
104 EGL(eglDestroySurface(engineContext->eglDisplay, engineContext->eglSurface));
105 EGL(eglDestroyContext(engineContext->eglDisplay, engineContext->eglContext));
106 EGL(eglTerminate(engineContext->eglDisplay));
107 engineContext->eglDisplay = EGL_NO_DISPLAY;
108 engineContext->eglContext = EGL_NO_CONTEXT;
109 engineContext->eglSurface = EGL_NO_SURFACE;
110 }
111
112 //-----------------------------------------------------------------------------
engine_deleteInputBuffer(unsigned int id)113 void engine_deleteInputBuffer(unsigned int id)
114 //-----------------------------------------------------------------------------
115 {
116 if (id != 0) {
117 GL(glDeleteTextures(1, &id));
118 }
119 }
120
121 //-----------------------------------------------------------------------------
engine_deleteProgram(unsigned int id)122 void engine_deleteProgram(unsigned int id)
123 //-----------------------------------------------------------------------------
124 {
125 if (id != 0) {
126 GL(glDeleteProgram(id));
127 }
128 }
129
130 //-----------------------------------------------------------------------------
engine_setData2f(int location,float * data)131 void engine_setData2f(int location, float* data)
132 //-----------------------------------------------------------------------------
133 {
134 GL(glUniform2f(location, data[0], data[1]));
135 }
136
137 //-----------------------------------------------------------------------------
engine_load3DTexture(void * colorMapData,int sz,int format)138 unsigned int engine_load3DTexture(void *colorMapData, int sz, int format)
139 //-----------------------------------------------------------------------------
140 {
141 GLuint texture = 0;
142 GL(glGenTextures(1, &texture));
143 GL(glBindTexture(GL_TEXTURE_3D, texture));
144 GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
145 GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
146 GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE));
147 GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
148 GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
149
150 GL(glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB10_A2, sz, sz, sz, 0, GL_RGBA,
151 GL_UNSIGNED_INT_2_10_10_10_REV, colorMapData));
152
153 return texture;
154 }
155 //-----------------------------------------------------------------------------
engine_load1DTexture(void * data,int sz,int format)156 unsigned int engine_load1DTexture(void *data, int sz, int format)
157 //-----------------------------------------------------------------------------
158 {
159 GLuint texture = 0;
160 if ((data != 0) && (sz != 0)) {
161 GL(glGenTextures(1, &texture));
162 GL(glBindTexture(GL_TEXTURE_2D, texture));
163 GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
164 GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
165 GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
166 GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
167
168 GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, sz, 1, 0, GL_RGBA,
169 GL_UNSIGNED_INT_2_10_10_10_REV, data));
170 }
171 return texture;
172 }
173
174 //-----------------------------------------------------------------------------
dumpShaderLog(int shader)175 void dumpShaderLog(int shader)
176 //-----------------------------------------------------------------------------
177 {
178 int success = 0;
179 GLchar infoLog[512];
180 GL(glGetShaderiv(shader, GL_COMPILE_STATUS, &success));
181 if (!success) {
182 glGetShaderInfoLog(shader, 512, NULL, infoLog);
183 ALOGI("Shader Failed to compile: %s\n", infoLog);
184 }
185 }
186
187 //-----------------------------------------------------------------------------
engine_loadProgram(int vertexEntries,const char ** vertex,int fragmentEntries,const char ** fragment)188 GLuint engine_loadProgram(int vertexEntries, const char **vertex, int fragmentEntries,
189 const char **fragment)
190 //-----------------------------------------------------------------------------
191 {
192 GLuint progId = glCreateProgram();
193
194 int vertId = glCreateShader(GL_VERTEX_SHADER);
195 int fragId = glCreateShader(GL_FRAGMENT_SHADER);
196
197 GL(glShaderSource(vertId, vertexEntries, vertex, 0));
198 GL(glCompileShader(vertId));
199 dumpShaderLog(vertId);
200
201 GL(glShaderSource(fragId, fragmentEntries, fragment, 0));
202 GL(glCompileShader(fragId));
203 dumpShaderLog(fragId);
204
205 GL(glAttachShader(progId, vertId));
206 GL(glAttachShader(progId, fragId));
207
208 GL(glLinkProgram(progId));
209
210 GL(glDetachShader(progId, vertId));
211 GL(glDetachShader(progId, fragId));
212
213 GL(glDeleteShader(vertId));
214 GL(glDeleteShader(fragId));
215
216 return progId;
217 }
218
219 //-----------------------------------------------------------------------------
WaitOnNativeFence(int fd)220 void WaitOnNativeFence(int fd)
221 //-----------------------------------------------------------------------------
222 {
223 if (fd != -1) {
224 EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fd, EGL_NONE};
225
226 EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
227
228 if (sync == EGL_NO_SYNC_KHR) {
229 ALOGE("%s - Failed to Create sync from source fd", __FUNCTION__);
230 } else {
231 // the gpu will wait for this sync - not this cpu thread.
232 EGL(eglWaitSyncKHR(eglGetCurrentDisplay(), sync, 0));
233 EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), sync));
234 }
235 }
236 }
237
238 //-----------------------------------------------------------------------------
CreateNativeFence()239 int CreateNativeFence()
240 //-----------------------------------------------------------------------------
241 {
242 int fd = -1;
243
244 EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
245 GL(glFlush());
246 if (sync == EGL_NO_SYNC_KHR) {
247 ALOGE("%s - Failed to Create Native Fence sync", __FUNCTION__);
248 } else {
249 fd = eglDupNativeFenceFDANDROID(eglGetCurrentDisplay(), sync);
250 if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
251 ALOGE("%s - Failed to dup sync", __FUNCTION__);
252 }
253 EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), sync));
254 }
255
256 return fd;
257 }
258
259 //-----------------------------------------------------------------------------
engine_setDestination(int id,int x,int y,int w,int h)260 void engine_setDestination(int id, int x, int y, int w, int h)
261 //-----------------------------------------------------------------------------
262 {
263 GL(glBindFramebuffer(GL_FRAMEBUFFER, id));
264 GL(glViewport(x, y, w, h));
265 }
266
267 //-----------------------------------------------------------------------------
engine_setProgram(int id)268 void engine_setProgram(int id)
269 //-----------------------------------------------------------------------------
270 {
271 GL(glUseProgram(id));
272 }
273
274 //-----------------------------------------------------------------------------
engine_set2DInputBuffer(int binding,unsigned int id)275 void engine_set2DInputBuffer(int binding, unsigned int id)
276 //-----------------------------------------------------------------------------
277 {
278 GL(glActiveTexture(GL_TEXTURE0 + binding));
279 GL(glBindTexture(GL_TEXTURE_2D, id));
280 }
281
282 //-----------------------------------------------------------------------------
engine_set3DInputBuffer(int binding,unsigned int id)283 void engine_set3DInputBuffer(int binding, unsigned int id)
284 //-----------------------------------------------------------------------------
285 {
286 GL(glActiveTexture(GL_TEXTURE0 + binding));
287 GL(glBindTexture(GL_TEXTURE_3D, id));
288 }
289
290 //-----------------------------------------------------------------------------
engine_setExternalInputBuffer(int binding,unsigned int id)291 void engine_setExternalInputBuffer(int binding, unsigned int id)
292 //-----------------------------------------------------------------------------
293 {
294 GL(glActiveTexture(GL_TEXTURE0 + binding));
295 GL(glBindTexture(0x8D65, id));
296 }
297
298 //-----------------------------------------------------------------------------
engine_blit(int srcFenceFd)299 int engine_blit(int srcFenceFd)
300 //-----------------------------------------------------------------------------
301 {
302 int fd = -1;
303 WaitOnNativeFence(srcFenceFd);
304 float fullscreen_vertices[]{0.0f, 2.0f, 0.0f, 0.0f, 2.0f, 0.0f};
305 GL(glEnableVertexAttribArray(0));
306 GL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, fullscreen_vertices));
307 GL(glDrawArrays(GL_TRIANGLES, 0, 3));
308 fd = CreateNativeFence();
309 GL(glFlush());
310 return fd;
311 }
312
313 //-----------------------------------------------------------------------------
checkGlError(const char * file,int line)314 void checkGlError(const char *file, int line)
315 //-----------------------------------------------------------------------------
316 {
317 for (GLint error = glGetError(); error; error = glGetError()) {
318 const char *pError = "<unknown error>";
319 switch (error) {
320 case GL_NO_ERROR:
321 pError = "GL_NO_ERROR";
322 break;
323 case GL_INVALID_ENUM:
324 pError = "GL_INVALID_ENUM";
325 break;
326 case GL_INVALID_VALUE:
327 pError = "GL_INVALID_VALUE";
328 break;
329 case GL_INVALID_OPERATION:
330 pError = "GL_INVALID_OPERATION";
331 break;
332 case GL_OUT_OF_MEMORY:
333 pError = "GL_OUT_OF_MEMORY";
334 break;
335 case GL_INVALID_FRAMEBUFFER_OPERATION:
336 pError = "GL_INVALID_FRAMEBUFFER_OPERATION";
337 break;
338 }
339
340 ALOGE("glError (%s) %s:%d\n", pError, file, line);
341 }
342 }
343
344 //-----------------------------------------------------------------------------
checkEglError(const char * file,int line)345 void checkEglError(const char *file, int line)
346 //-----------------------------------------------------------------------------
347 {
348 for (int i = 0; i < 5; i++) {
349 const EGLint error = eglGetError();
350 if (error == EGL_SUCCESS) {
351 break;
352 }
353
354 const char *pError = "<unknown error>";
355 switch (error) {
356 case EGL_SUCCESS:
357 pError = "EGL_SUCCESS";
358 break;
359 case EGL_NOT_INITIALIZED:
360 pError = "EGL_NOT_INITIALIZED";
361 break;
362 case EGL_BAD_ACCESS:
363 pError = "EGL_BAD_ACCESS";
364 break;
365 case EGL_BAD_ALLOC:
366 pError = "EGL_BAD_ALLOC";
367 break;
368 case EGL_BAD_ATTRIBUTE:
369 pError = "EGL_BAD_ATTRIBUTE";
370 break;
371 case EGL_BAD_CONTEXT:
372 pError = "EGL_BAD_CONTEXT";
373 break;
374 case EGL_BAD_CONFIG:
375 pError = "EGL_BAD_CONFIG";
376 break;
377 case EGL_BAD_CURRENT_SURFACE:
378 pError = "EGL_BAD_CURRENT_SURFACE";
379 break;
380 case EGL_BAD_DISPLAY:
381 pError = "EGL_BAD_DISPLAY";
382 break;
383 case EGL_BAD_SURFACE:
384 pError = "EGL_BAD_SURFACE";
385 break;
386 case EGL_BAD_MATCH:
387 pError = "EGL_BAD_MATCH";
388 break;
389 case EGL_BAD_PARAMETER:
390 pError = "EGL_BAD_PARAMETER";
391 break;
392 case EGL_BAD_NATIVE_PIXMAP:
393 pError = "EGL_BAD_NATIVE_PIXMAP";
394 break;
395 case EGL_BAD_NATIVE_WINDOW:
396 pError = "EGL_BAD_NATIVE_WINDOW";
397 break;
398 case EGL_CONTEXT_LOST:
399 pError = "EGL_CONTEXT_LOST";
400 break;
401 }
402 ALOGE("eglError (%s) %s:%d\n", pError, file, line);
403 }
404 }
405