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