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