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 "egl_tls.h"
18 
19 #include <stdlib.h>
20 
21 #include <cutils/properties.h>
22 #include <log/log.h>
23 #include "CallStack.h"
24 
25 namespace android {
26 
27 pthread_key_t egl_tls_t::sKey = TLS_KEY_NOT_INITIALIZED;
28 pthread_once_t egl_tls_t::sOnceKey = PTHREAD_ONCE_INIT;
29 
egl_tls_t()30 egl_tls_t::egl_tls_t()
31     : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(true) {
32 }
33 
egl_strerror(EGLint err)34 const char *egl_tls_t::egl_strerror(EGLint err) {
35     switch (err) {
36         case EGL_SUCCESS:               return "EGL_SUCCESS";
37         case EGL_NOT_INITIALIZED:       return "EGL_NOT_INITIALIZED";
38         case EGL_BAD_ACCESS:            return "EGL_BAD_ACCESS";
39         case EGL_BAD_ALLOC:             return "EGL_BAD_ALLOC";
40         case EGL_BAD_ATTRIBUTE:         return "EGL_BAD_ATTRIBUTE";
41         case EGL_BAD_CONFIG:            return "EGL_BAD_CONFIG";
42         case EGL_BAD_CONTEXT:           return "EGL_BAD_CONTEXT";
43         case EGL_BAD_CURRENT_SURFACE:   return "EGL_BAD_CURRENT_SURFACE";
44         case EGL_BAD_DISPLAY:           return "EGL_BAD_DISPLAY";
45         case EGL_BAD_MATCH:             return "EGL_BAD_MATCH";
46         case EGL_BAD_NATIVE_PIXMAP:     return "EGL_BAD_NATIVE_PIXMAP";
47         case EGL_BAD_NATIVE_WINDOW:     return "EGL_BAD_NATIVE_WINDOW";
48         case EGL_BAD_PARAMETER:         return "EGL_BAD_PARAMETER";
49         case EGL_BAD_SURFACE:           return "EGL_BAD_SURFACE";
50         case EGL_CONTEXT_LOST:          return "EGL_CONTEXT_LOST";
51         default: return "UNKNOWN";
52     }
53 }
54 
validateTLSKey()55 void egl_tls_t::validateTLSKey()
56 {
57     struct TlsKeyInitializer {
58         static void create() {
59             pthread_key_create(&sKey, (void (*)(void*))&eglReleaseThread);
60         }
61     };
62     pthread_once(&sOnceKey, TlsKeyInitializer::create);
63 }
64 
setErrorEtcImpl(const char * caller,int line,EGLint error,bool quiet)65 void egl_tls_t::setErrorEtcImpl(
66         const char* caller, int line, EGLint error, bool quiet) {
67     validateTLSKey();
68     egl_tls_t* tls = getTLS();
69     if (tls->error != error) {
70         if (!quiet) {
71             ALOGE("%s:%d error %x (%s)",
72                     caller, line, error, egl_strerror(error));
73             char value[PROPERTY_VALUE_MAX];
74             property_get("debug.egl.callstack", value, "0");
75             if (atoi(value)) {
76                 CallStack::log(LOG_TAG);
77             }
78         }
79         tls->error = error;
80     }
81 }
82 
logNoContextCall()83 bool egl_tls_t::logNoContextCall() {
84     egl_tls_t* tls = getTLS();
85     if (tls->logCallWithNoContext) {
86         tls->logCallWithNoContext = false;
87         return true;
88     }
89     return false;
90 
91 }
92 
getTLS()93 egl_tls_t* egl_tls_t::getTLS() {
94     egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
95     if (tls == 0) {
96         tls = new egl_tls_t;
97         pthread_setspecific(sKey, tls);
98     }
99     return tls;
100 }
101 
clearTLS()102 void egl_tls_t::clearTLS() {
103     if (sKey != TLS_KEY_NOT_INITIALIZED) {
104         egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
105         if (tls) {
106             pthread_setspecific(sKey, 0);
107             delete tls;
108         }
109     }
110 }
111 
clearError()112 void egl_tls_t::clearError() {
113     // This must clear the error from all the underlying EGL implementations as
114     // well as the EGL wrapper layer.
115     eglGetError();
116 }
117 
getError()118 EGLint egl_tls_t::getError() {
119     if (sKey == TLS_KEY_NOT_INITIALIZED) {
120         return EGL_SUCCESS;
121     }
122     egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
123     if (!tls) {
124         return EGL_SUCCESS;
125     }
126     EGLint error = tls->error;
127     tls->error = EGL_SUCCESS;
128     return error;
129 }
130 
setContext(EGLContext ctx)131 void egl_tls_t::setContext(EGLContext ctx) {
132     validateTLSKey();
133     getTLS()->ctx = ctx;
134 }
135 
getContext()136 EGLContext egl_tls_t::getContext() {
137     if (sKey == TLS_KEY_NOT_INITIALIZED) {
138         return EGL_NO_CONTEXT;
139     }
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