1/* 2 ** Copyright 2011, The Android Open Source Project 3 ** 4 ** Licensed under the Apache License, Version 2.0 (the "License"); 5 ** you may not use this file except in compliance with the License. 6 ** You may obtain a copy of the License at 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 10 ** Unless required by applicable law or agreed to in writing, software 11 ** distributed under the License is distributed on an "AS IS" BASIS, 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 17#include <stdlib.h> 18#include <pthread.h> 19 20#include <cutils/log.h> 21#include <cutils/properties.h> 22 23#include <utils/CallStack.h> 24 25#include <EGL/egl.h> 26 27#include "egl_tls.h" 28 29 30namespace android { 31 32pthread_key_t egl_tls_t::sKey = -1; 33pthread_mutex_t egl_tls_t::sLockKey = PTHREAD_MUTEX_INITIALIZER; 34 35egl_tls_t::egl_tls_t() 36 : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) { 37} 38 39const char *egl_tls_t::egl_strerror(EGLint err) { 40 switch (err) { 41 case EGL_SUCCESS: return "EGL_SUCCESS"; 42 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; 43 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; 44 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; 45 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; 46 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; 47 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; 48 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; 49 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; 50 case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; 51 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; 52 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; 53 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; 54 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; 55 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; 56 default: return "UNKNOWN"; 57 } 58} 59 60void egl_tls_t::validateTLSKey() 61{ 62 if (sKey == -1) { 63 pthread_mutex_lock(&sLockKey); 64 if (sKey == -1) 65 pthread_key_create(&sKey, NULL); 66 pthread_mutex_unlock(&sLockKey); 67 } 68} 69 70void egl_tls_t::setErrorEtcImpl( 71 const char* caller, int line, EGLint error, bool quiet) { 72 validateTLSKey(); 73 egl_tls_t* tls = getTLS(); 74 if (tls->error != error) { 75 if (!quiet) { 76 ALOGE("%s:%d error %x (%s)", 77 caller, line, error, egl_strerror(error)); 78 char value[PROPERTY_VALUE_MAX]; 79 property_get("debug.egl.callstack", value, "0"); 80 if (atoi(value)) { 81 CallStack stack(LOG_TAG); 82 } 83 } 84 tls->error = error; 85 } 86} 87 88bool egl_tls_t::logNoContextCall() { 89 egl_tls_t* tls = getTLS(); 90 if (tls->logCallWithNoContext == true) { 91 tls->logCallWithNoContext = false; 92 return true; 93 } 94 return false; 95} 96 97egl_tls_t* egl_tls_t::getTLS() { 98 egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey); 99 if (tls == 0) { 100 tls = new egl_tls_t; 101 pthread_setspecific(sKey, tls); 102 } 103 return tls; 104} 105 106void egl_tls_t::clearTLS() { 107 if (sKey != -1) { 108 egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey); 109 if (tls) { 110 delete tls; 111 pthread_setspecific(sKey, 0); 112 } 113 } 114} 115 116void egl_tls_t::clearError() { 117 // This must clear the error from all the underlying EGL implementations as 118 // well as the EGL wrapper layer. 119 eglGetError(); 120} 121 122EGLint egl_tls_t::getError() { 123 if (sKey == -1) 124 return EGL_SUCCESS; 125 egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey); 126 if (!tls) return EGL_SUCCESS; 127 EGLint error = tls->error; 128 tls->error = EGL_SUCCESS; 129 return error; 130} 131 132void egl_tls_t::setContext(EGLContext ctx) { 133 validateTLSKey(); 134 getTLS()->ctx = ctx; 135} 136 137EGLContext egl_tls_t::getContext() { 138 if (sKey == -1) 139 return EGL_NO_CONTEXT; 140 egl_tls_t* tls = (egl_tls_t *)pthread_getspecific(sKey); 141 if (!tls) return EGL_NO_CONTEXT; 142 return tls->ctx; 143} 144 145 146} // namespace android 147