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 
30 namespace android {
31 
32 pthread_key_t egl_tls_t::sKey = TLS_KEY_NOT_INITIALIZED;
33 pthread_once_t egl_tls_t::sOnceKey = PTHREAD_ONCE_INIT;
34 
egl_tls_t()35 egl_tls_t::egl_tls_t()
36     : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) {
37 }
38 
egl_strerror(EGLint err)39 const 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 
validateTLSKey()60 void egl_tls_t::validateTLSKey()
61 {
62     struct TlsKeyInitializer {
63         static void create() {
64             pthread_key_create(&sKey, (void (*)(void*))&eglReleaseThread);
65         }
66     };
67     pthread_once(&sOnceKey, TlsKeyInitializer::create);
68 }
69 
setErrorEtcImpl(const char * caller,int line,EGLint error,bool quiet)70 void 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 
logNoContextCall()88 bool 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 
getTLS()97 egl_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 
clearTLS()106 void egl_tls_t::clearTLS() {
107     if (sKey != TLS_KEY_NOT_INITIALIZED) {
108         egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
109         if (tls) {
110             pthread_setspecific(sKey, 0);
111             delete tls;
112         }
113     }
114 }
115 
clearError()116 void 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 
getError()122 EGLint egl_tls_t::getError() {
123     if (sKey == TLS_KEY_NOT_INITIALIZED) {
124         return EGL_SUCCESS;
125     }
126     egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
127     if (!tls) {
128         return EGL_SUCCESS;
129     }
130     EGLint error = tls->error;
131     tls->error = EGL_SUCCESS;
132     return error;
133 }
134 
setContext(EGLContext ctx)135 void egl_tls_t::setContext(EGLContext ctx) {
136     validateTLSKey();
137     getTLS()->ctx = ctx;
138 }
139 
getContext()140 EGLContext egl_tls_t::getContext() {
141     if (sKey == TLS_KEY_NOT_INITIALIZED) {
142         return EGL_NO_CONTEXT;
143     }
144     egl_tls_t* tls = (egl_tls_t *)pthread_getspecific(sKey);
145     if (!tls) return EGL_NO_CONTEXT;
146     return tls->ctx;
147 }
148 
149 
150 } // namespace android
151