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