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() 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. 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 //----------------------------------------------------------------------------- 106 void engine_deleteInputBuffer(unsigned int id) 107 //----------------------------------------------------------------------------- 108 { 109 if (id != 0) { 110 GL(glDeleteTextures(1, &id)); 111 } 112 } 113 114 //----------------------------------------------------------------------------- 115 void engine_deleteProgram(unsigned int id) 116 //----------------------------------------------------------------------------- 117 { 118 if (id != 0) { 119 GL(glDeleteProgram(id)); 120 } 121 } 122 123 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 254 void engine_setProgram(int id) 255 //----------------------------------------------------------------------------- 256 { 257 GL(glUseProgram(id)); 258 } 259 260 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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 //----------------------------------------------------------------------------- 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