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