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; 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 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) 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 63 void engine_free_backup(void* context) 64 { 65 EngineContext* callerContext = (EngineContext*)(context); 66 67 delete callerContext; 68 } 69 70 //----------------------------------------------------------------------------- 71 // initialize GL 72 // 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. 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 //----------------------------------------------------------------------------- 134 void engine_deleteInputBuffer(unsigned int id) 135 //----------------------------------------------------------------------------- 136 { 137 if (id != 0) { 138 GL(glDeleteTextures(1, &id)); 139 } 140 } 141 142 //----------------------------------------------------------------------------- 143 void engine_deleteProgram(unsigned int id) 144 //----------------------------------------------------------------------------- 145 { 146 if (id != 0) { 147 GL(glDeleteProgram(id)); 148 } 149 } 150 151 //----------------------------------------------------------------------------- 152 void engine_setData2f(int location, float* data) 153 //----------------------------------------------------------------------------- 154 { 155 GL(glUniform2f(location, data[0], data[1])); 156 } 157 158 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 289 void engine_setProgram(int id) 290 //----------------------------------------------------------------------------- 291 { 292 GL(glUseProgram(id)); 293 } 294 295 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 335 void checkGlError(const char *file, int line) 336 //----------------------------------------------------------------------------- 337 { 338 for (GLint error = glGetError(); error; error = glGetError()) { 339 char *pError; 340 switch (error) { 341 case GL_NO_ERROR: 342 pError = (char *)"GL_NO_ERROR"; 343 break; 344 case GL_INVALID_ENUM: 345 pError = (char *)"GL_INVALID_ENUM"; 346 break; 347 case GL_INVALID_VALUE: 348 pError = (char *)"GL_INVALID_VALUE"; 349 break; 350 case GL_INVALID_OPERATION: 351 pError = (char *)"GL_INVALID_OPERATION"; 352 break; 353 case GL_OUT_OF_MEMORY: 354 pError = (char *)"GL_OUT_OF_MEMORY"; 355 break; 356 case GL_INVALID_FRAMEBUFFER_OPERATION: 357 pError = (char *)"GL_INVALID_FRAMEBUFFER_OPERATION"; 358 break; 359 360 default: 361 ALOGE("glError (0x%x) %s:%d\n", error, file, line); 362 return; 363 } 364 365 ALOGE("glError (%s) %s:%d\n", pError, file, line); 366 return; 367 } 368 return; 369 } 370 371 //----------------------------------------------------------------------------- 372 void checkEglError(const char *file, int line) 373 //----------------------------------------------------------------------------- 374 { 375 for (int i = 0; i < 5; i++) { 376 const EGLint error = eglGetError(); 377 if (error == EGL_SUCCESS) { 378 break; 379 } 380 381 char *pError; 382 switch (error) { 383 case EGL_SUCCESS: 384 pError = (char *)"EGL_SUCCESS"; 385 break; 386 case EGL_NOT_INITIALIZED: 387 pError = (char *)"EGL_NOT_INITIALIZED"; 388 break; 389 case EGL_BAD_ACCESS: 390 pError = (char *)"EGL_BAD_ACCESS"; 391 break; 392 case EGL_BAD_ALLOC: 393 pError = (char *)"EGL_BAD_ALLOC"; 394 break; 395 case EGL_BAD_ATTRIBUTE: 396 pError = (char *)"EGL_BAD_ATTRIBUTE"; 397 break; 398 case EGL_BAD_CONTEXT: 399 pError = (char *)"EGL_BAD_CONTEXT"; 400 break; 401 case EGL_BAD_CONFIG: 402 pError = (char *)"EGL_BAD_CONFIG"; 403 break; 404 case EGL_BAD_CURRENT_SURFACE: 405 pError = (char *)"EGL_BAD_CURRENT_SURFACE"; 406 break; 407 case EGL_BAD_DISPLAY: 408 pError = (char *)"EGL_BAD_DISPLAY"; 409 break; 410 case EGL_BAD_SURFACE: 411 pError = (char *)"EGL_BAD_SURFACE"; 412 break; 413 case EGL_BAD_MATCH: 414 pError = (char *)"EGL_BAD_MATCH"; 415 break; 416 case EGL_BAD_PARAMETER: 417 pError = (char *)"EGL_BAD_PARAMETER"; 418 break; 419 case EGL_BAD_NATIVE_PIXMAP: 420 pError = (char *)"EGL_BAD_NATIVE_PIXMAP"; 421 break; 422 case EGL_BAD_NATIVE_WINDOW: 423 pError = (char *)"EGL_BAD_NATIVE_WINDOW"; 424 break; 425 case EGL_CONTEXT_LOST: 426 pError = (char *)"EGL_CONTEXT_LOST"; 427 break; 428 default: 429 ALOGE("eglError (0x%x) %s:%d\n", error, file, line); 430 return; 431 } 432 ALOGE("eglError (%s) %s:%d\n", pError, file, line); 433 return; 434 } 435 return; 436 } 437