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 <utils/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 // store the current context(caller)
engine_backup()51 void* engine_backup()
52 {
53   EngineContext* callerContext = new EngineContext();
54   // store the previous display/context
55   callerContext->eglDisplay = eglGetCurrentDisplay();
56   callerContext->eglContext = eglGetCurrentContext();
57   callerContext->eglSurface = eglGetCurrentSurface(EGL_DRAW);
58 
59   return (void*)callerContext;
60 }
61 //-----------------------------------------------------------------------------
62 // frees the backed up caller context
engine_free_backup(void * context)63 void engine_free_backup(void* context)
64 {
65   EngineContext* callerContext = (EngineContext*)(context);
66 
67   delete callerContext;
68 }
69 
70 //-----------------------------------------------------------------------------
71 // initialize GL
72 //
engine_initialize(bool isSecure)73 void* engine_initialize(bool isSecure)
74 //-----------------------------------------------------------------------------
75 {
76   EngineContext* engineContext = new EngineContext();
77 
78   // display
79   engineContext->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
80   EGL(eglBindAPI(EGL_OPENGL_ES_API));
81 
82   // initialize
83   EGL(eglInitialize(engineContext->eglDisplay, 0, 0));
84 
85   // config
86   EGLConfig eglConfig;
87   EGLint eglConfigAttribList[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
88                                   EGL_RED_SIZE,     8,
89                                   EGL_GREEN_SIZE,   8,
90                                   EGL_BLUE_SIZE,    8,
91                                   EGL_ALPHA_SIZE,   8,
92                                   EGL_NONE};
93   int numConfig = 0;
94   EGL(eglChooseConfig(engineContext->eglDisplay, eglConfigAttribList, &eglConfig, 1, &numConfig));
95 
96   // context
97   EGLint eglContextAttribList[] = {EGL_CONTEXT_CLIENT_VERSION, 3,
98                                    isSecure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
99                                    isSecure ? EGL_TRUE : EGL_NONE,
100                                    EGL_NONE};
101   engineContext->eglContext = eglCreateContext(engineContext->eglDisplay, eglConfig, NULL, eglContextAttribList);
102 
103   // surface
104   EGLint eglSurfaceAttribList[] = {EGL_WIDTH, 1,
105                                    EGL_HEIGHT, 1,
106                                    isSecure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
107                                    isSecure ? EGL_TRUE : EGL_NONE,
108                                    EGL_NONE};
109   engineContext->eglSurface = eglCreatePbufferSurface(engineContext->eglDisplay, eglConfig, eglSurfaceAttribList);
110 
111   eglMakeCurrent(engineContext->eglDisplay, engineContext->eglSurface, engineContext->eglSurface, engineContext->eglContext);
112 
113   ALOGI("In %s context = %p", __FUNCTION__, (void *)(engineContext->eglContext));
114 
115   return (void*)(engineContext);
116 }
117 
118 //-----------------------------------------------------------------------------
119 // Shutdown.
engine_shutdown(void * context)120 void engine_shutdown(void* context)
121 //-----------------------------------------------------------------------------
122 {
123   EngineContext* engineContext = (EngineContext*)context;
124   EGL(eglMakeCurrent(engineContext->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
125   EGL(eglDestroySurface(engineContext->eglDisplay, engineContext->eglSurface));
126   EGL(eglDestroyContext(engineContext->eglDisplay, engineContext->eglContext));
127   EGL(eglTerminate(engineContext->eglDisplay));
128   engineContext->eglDisplay = EGL_NO_DISPLAY;
129   engineContext->eglContext = EGL_NO_CONTEXT;
130   engineContext->eglSurface = EGL_NO_SURFACE;
131 }
132 
133 //-----------------------------------------------------------------------------
engine_deleteInputBuffer(unsigned int id)134 void engine_deleteInputBuffer(unsigned int id)
135 //-----------------------------------------------------------------------------
136 {
137   if (id != 0) {
138     GL(glDeleteTextures(1, &id));
139   }
140 }
141 
142 //-----------------------------------------------------------------------------
engine_deleteProgram(unsigned int id)143 void engine_deleteProgram(unsigned int id)
144 //-----------------------------------------------------------------------------
145 {
146   if (id != 0) {
147     GL(glDeleteProgram(id));
148   }
149 }
150 
151 //-----------------------------------------------------------------------------
engine_setData2f(int location,float * data)152 void engine_setData2f(int location, float* data)
153 //-----------------------------------------------------------------------------
154 {
155     GL(glUniform2f(location, data[0], data[1]));
156 }
157 
158 //-----------------------------------------------------------------------------
engine_load3DTexture(void * colorMapData,int sz,int format)159 unsigned int engine_load3DTexture(void *colorMapData, int sz, int format)
160 //-----------------------------------------------------------------------------
161 {
162   GLuint texture = 0;
163   GL(glGenTextures(1, &texture));
164   GL(glBindTexture(GL_TEXTURE_3D, texture));
165   GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
166   GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
167   GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE));
168   GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
169   GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
170 
171   GL(glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB10_A2, sz, sz, sz, 0, GL_RGBA,
172                   GL_UNSIGNED_INT_2_10_10_10_REV, colorMapData));
173 
174   return texture;
175 }
176 //-----------------------------------------------------------------------------
engine_load1DTexture(void * data,int sz,int format)177 unsigned int engine_load1DTexture(void *data, int sz, int format)
178 //-----------------------------------------------------------------------------
179 {
180   GLuint texture = 0;
181   if ((data != 0) && (sz != 0)) {
182     GL(glGenTextures(1, &texture));
183     GL(glBindTexture(GL_TEXTURE_2D, texture));
184     GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
185     GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
186     GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
187     GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
188 
189     GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, sz, 1, 0, GL_RGBA,
190                     GL_UNSIGNED_INT_2_10_10_10_REV, data));
191   }
192   return texture;
193 }
194 
195 //-----------------------------------------------------------------------------
dumpShaderLog(int shader)196 void dumpShaderLog(int shader)
197 //-----------------------------------------------------------------------------
198 {
199   int success = 0;
200   GLchar infoLog[512];
201   GL(glGetShaderiv(shader, GL_COMPILE_STATUS, &success));
202   if (!success) {
203     glGetShaderInfoLog(shader, 512, NULL, infoLog);
204     ALOGI("Shader Failed to compile: %s\n", infoLog);
205   }
206 }
207 
208 //-----------------------------------------------------------------------------
engine_loadProgram(int vertexEntries,const char ** vertex,int fragmentEntries,const char ** fragment)209 GLuint engine_loadProgram(int vertexEntries, const char **vertex, int fragmentEntries,
210                           const char **fragment)
211 //-----------------------------------------------------------------------------
212 {
213   GLuint progId = glCreateProgram();
214 
215   int vertId = glCreateShader(GL_VERTEX_SHADER);
216   int fragId = glCreateShader(GL_FRAGMENT_SHADER);
217 
218   GL(glShaderSource(vertId, vertexEntries, vertex, 0));
219   GL(glCompileShader(vertId));
220   dumpShaderLog(vertId);
221 
222   GL(glShaderSource(fragId, fragmentEntries, fragment, 0));
223   GL(glCompileShader(fragId));
224   dumpShaderLog(fragId);
225 
226   GL(glAttachShader(progId, vertId));
227   GL(glAttachShader(progId, fragId));
228 
229   GL(glLinkProgram(progId));
230 
231   GL(glDetachShader(progId, vertId));
232   GL(glDetachShader(progId, fragId));
233 
234   GL(glDeleteShader(vertId));
235   GL(glDeleteShader(fragId));
236 
237   return progId;
238 }
239 
240 //-----------------------------------------------------------------------------
WaitOnNativeFence(int fd)241 void WaitOnNativeFence(int fd)
242 //-----------------------------------------------------------------------------
243 {
244   if (fd != -1) {
245     EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fd, EGL_NONE};
246 
247     EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
248 
249     if (sync == EGL_NO_SYNC_KHR) {
250       ALOGE("%s - Failed to Create sync from source fd", __FUNCTION__);
251     } else {
252       // the gpu will wait for this sync - not this cpu thread.
253       EGL(eglWaitSyncKHR(eglGetCurrentDisplay(), sync, 0));
254       EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), sync));
255     }
256   }
257 }
258 
259 //-----------------------------------------------------------------------------
CreateNativeFence()260 int CreateNativeFence()
261 //-----------------------------------------------------------------------------
262 {
263   int fd = -1;
264 
265   EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
266   GL(glFlush());
267   if (sync == EGL_NO_SYNC_KHR) {
268     ALOGE("%s - Failed to Create Native Fence sync", __FUNCTION__);
269   } else {
270     fd = eglDupNativeFenceFDANDROID(eglGetCurrentDisplay(), sync);
271     if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
272       ALOGE("%s - Failed to dup sync", __FUNCTION__);
273     }
274     EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), sync));
275   }
276 
277   return fd;
278 }
279 
280 //-----------------------------------------------------------------------------
engine_setDestination(int id,int x,int y,int w,int h)281 void engine_setDestination(int id, int x, int y, int w, int h)
282 //-----------------------------------------------------------------------------
283 {
284   GL(glBindFramebuffer(GL_FRAMEBUFFER, id));
285   GL(glViewport(x, y, w, h));
286 }
287 
288 //-----------------------------------------------------------------------------
engine_setProgram(int id)289 void engine_setProgram(int id)
290 //-----------------------------------------------------------------------------
291 {
292   GL(glUseProgram(id));
293 }
294 
295 //-----------------------------------------------------------------------------
engine_set2DInputBuffer(int binding,unsigned int id)296 void engine_set2DInputBuffer(int binding, unsigned int id)
297 //-----------------------------------------------------------------------------
298 {
299   GL(glActiveTexture(GL_TEXTURE0 + binding));
300   GL(glBindTexture(GL_TEXTURE_2D, id));
301 }
302 
303 //-----------------------------------------------------------------------------
engine_set3DInputBuffer(int binding,unsigned int id)304 void engine_set3DInputBuffer(int binding, unsigned int id)
305 //-----------------------------------------------------------------------------
306 {
307   GL(glActiveTexture(GL_TEXTURE0 + binding));
308   GL(glBindTexture(GL_TEXTURE_3D, id));
309 }
310 
311 //-----------------------------------------------------------------------------
engine_setExternalInputBuffer(int binding,unsigned int id)312 void engine_setExternalInputBuffer(int binding, unsigned int id)
313 //-----------------------------------------------------------------------------
314 {
315   GL(glActiveTexture(GL_TEXTURE0 + binding));
316   GL(glBindTexture(0x8D65, id));
317 }
318 
319 //-----------------------------------------------------------------------------
engine_blit(int srcFenceFd)320 int engine_blit(int srcFenceFd)
321 //-----------------------------------------------------------------------------
322 {
323   int fd = -1;
324   WaitOnNativeFence(srcFenceFd);
325   float fullscreen_vertices[]{0.0f, 2.0f, 0.0f, 0.0f, 2.0f, 0.0f};
326   GL(glEnableVertexAttribArray(0));
327   GL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, fullscreen_vertices));
328   GL(glDrawArrays(GL_TRIANGLES, 0, 3));
329   fd = CreateNativeFence();
330   GL(glFlush());
331   return fd;
332 }
333 
334 //-----------------------------------------------------------------------------
checkGlError(const char * file,int line)335 void checkGlError(const char *file, int line)
336 //-----------------------------------------------------------------------------
337 {
338   for (GLint error = glGetError(); error; error = glGetError()) {
339     const char *pError = "<unknown error>";
340     switch (error) {
341       case GL_NO_ERROR:
342         pError = "GL_NO_ERROR";
343         break;
344       case GL_INVALID_ENUM:
345         pError = "GL_INVALID_ENUM";
346         break;
347       case GL_INVALID_VALUE:
348         pError = "GL_INVALID_VALUE";
349         break;
350       case GL_INVALID_OPERATION:
351         pError = "GL_INVALID_OPERATION";
352         break;
353       case GL_OUT_OF_MEMORY:
354         pError = "GL_OUT_OF_MEMORY";
355         break;
356       case GL_INVALID_FRAMEBUFFER_OPERATION:
357         pError = "GL_INVALID_FRAMEBUFFER_OPERATION";
358         break;
359     }
360 
361     ALOGE("glError (%s) %s:%d\n", pError, file, line);
362   }
363 }
364 
365 //-----------------------------------------------------------------------------
checkEglError(const char * file,int line)366 void checkEglError(const char *file, int line)
367 //-----------------------------------------------------------------------------
368 {
369   for (int i = 0; i < 5; i++) {
370     const EGLint error = eglGetError();
371     if (error == EGL_SUCCESS) {
372       break;
373     }
374 
375     const char *pError = "<unknown error>";
376     switch (error) {
377       case EGL_SUCCESS:
378         pError = "EGL_SUCCESS";
379         break;
380       case EGL_NOT_INITIALIZED:
381         pError = "EGL_NOT_INITIALIZED";
382         break;
383       case EGL_BAD_ACCESS:
384         pError = "EGL_BAD_ACCESS";
385         break;
386       case EGL_BAD_ALLOC:
387         pError = "EGL_BAD_ALLOC";
388         break;
389       case EGL_BAD_ATTRIBUTE:
390         pError = "EGL_BAD_ATTRIBUTE";
391         break;
392       case EGL_BAD_CONTEXT:
393         pError = "EGL_BAD_CONTEXT";
394         break;
395       case EGL_BAD_CONFIG:
396         pError = "EGL_BAD_CONFIG";
397         break;
398       case EGL_BAD_CURRENT_SURFACE:
399         pError = "EGL_BAD_CURRENT_SURFACE";
400         break;
401       case EGL_BAD_DISPLAY:
402         pError = "EGL_BAD_DISPLAY";
403         break;
404       case EGL_BAD_SURFACE:
405         pError = "EGL_BAD_SURFACE";
406         break;
407       case EGL_BAD_MATCH:
408         pError = "EGL_BAD_MATCH";
409         break;
410       case EGL_BAD_PARAMETER:
411         pError = "EGL_BAD_PARAMETER";
412         break;
413       case EGL_BAD_NATIVE_PIXMAP:
414         pError = "EGL_BAD_NATIVE_PIXMAP";
415         break;
416       case EGL_BAD_NATIVE_WINDOW:
417         pError = "EGL_BAD_NATIVE_WINDOW";
418         break;
419       case EGL_CONTEXT_LOST:
420         pError = "EGL_CONTEXT_LOST";
421         break;
422     }
423     ALOGE("eglError (%s) %s:%d\n", pError, file, line);
424   }
425 }
426