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