1518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian/*
2518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ** Copyright 2011, The Android Open Source Project
3518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian **
4518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ** Licensed under the Apache License, Version 2.0 (the "License");
5518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ** you may not use this file except in compliance with the License.
6518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ** You may obtain a copy of the License at
7518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian **
8518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian **     http://www.apache.org/licenses/LICENSE-2.0
9518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian **
10518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ** Unless required by applicable law or agreed to in writing, software
11518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ** distributed under the License is distributed on an "AS IS" BASIS,
12518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ** See the License for the specific language governing permissions and
14518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ** limitations under the License.
15518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian */
16518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
17ecfe091af3e3e5d7165fe64a5f9c84c4576a6c06Mathias Agopian#include <stdlib.h>
18518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <pthread.h>
19518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
20518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <cutils/log.h>
21ecfe091af3e3e5d7165fe64a5f9c84c4576a6c06Mathias Agopian#include <cutils/properties.h>
22ecfe091af3e3e5d7165fe64a5f9c84c4576a6c06Mathias Agopian
23ecfe091af3e3e5d7165fe64a5f9c84c4576a6c06Mathias Agopian#include <utils/CallStack.h>
24518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
25518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <EGL/egl.h>
26518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
27518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include "egl_tls.h"
28518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
29518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
30518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopiannamespace android {
31518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
324e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopianpthread_key_t egl_tls_t::sKey = TLS_KEY_NOT_INITIALIZED;
334e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopianpthread_once_t egl_tls_t::sOnceKey = PTHREAD_ONCE_INIT;
34518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
35518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianegl_tls_t::egl_tls_t()
360469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) {
37518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
38518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
39518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianconst char *egl_tls_t::egl_strerror(EGLint err) {
40518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    switch (err) {
41518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        case EGL_SUCCESS:               return "EGL_SUCCESS";
42518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        case EGL_NOT_INITIALIZED:       return "EGL_NOT_INITIALIZED";
43518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        case EGL_BAD_ACCESS:            return "EGL_BAD_ACCESS";
44518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        case EGL_BAD_ALLOC:             return "EGL_BAD_ALLOC";
45518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        case EGL_BAD_ATTRIBUTE:         return "EGL_BAD_ATTRIBUTE";
46518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        case EGL_BAD_CONFIG:            return "EGL_BAD_CONFIG";
47518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        case EGL_BAD_CONTEXT:           return "EGL_BAD_CONTEXT";
48518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        case EGL_BAD_CURRENT_SURFACE:   return "EGL_BAD_CURRENT_SURFACE";
49518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        case EGL_BAD_DISPLAY:           return "EGL_BAD_DISPLAY";
50518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        case EGL_BAD_MATCH:             return "EGL_BAD_MATCH";
51518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        case EGL_BAD_NATIVE_PIXMAP:     return "EGL_BAD_NATIVE_PIXMAP";
52518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        case EGL_BAD_NATIVE_WINDOW:     return "EGL_BAD_NATIVE_WINDOW";
53518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        case EGL_BAD_PARAMETER:         return "EGL_BAD_PARAMETER";
54518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        case EGL_BAD_SURFACE:           return "EGL_BAD_SURFACE";
55518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        case EGL_CONTEXT_LOST:          return "EGL_CONTEXT_LOST";
56518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        default: return "UNKNOWN";
57518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
58518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
59518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
60518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid egl_tls_t::validateTLSKey()
61518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian{
624e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian    struct TlsKeyInitializer {
634e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian        static void create() {
644e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian            pthread_key_create(&sKey, (void (*)(void*))&eglReleaseThread);
654e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian        }
664e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian    };
674e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian    pthread_once(&sOnceKey, TlsKeyInitializer::create);
68518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
69518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
700e8bbee5775d81c7bbc479b995496cac9238559fMathias Agopianvoid egl_tls_t::setErrorEtcImpl(
710e8bbee5775d81c7bbc479b995496cac9238559fMathias Agopian        const char* caller, int line, EGLint error, bool quiet) {
72518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    validateTLSKey();
73518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    egl_tls_t* tls = getTLS();
74518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    if (tls->error != error) {
750e8bbee5775d81c7bbc479b995496cac9238559fMathias Agopian        if (!quiet) {
76e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block            ALOGE("%s:%d error %x (%s)",
770e8bbee5775d81c7bbc479b995496cac9238559fMathias Agopian                    caller, line, error, egl_strerror(error));
780e8bbee5775d81c7bbc479b995496cac9238559fMathias Agopian            char value[PROPERTY_VALUE_MAX];
790e8bbee5775d81c7bbc479b995496cac9238559fMathias Agopian            property_get("debug.egl.callstack", value, "0");
800e8bbee5775d81c7bbc479b995496cac9238559fMathias Agopian            if (atoi(value)) {
81cab25d680e644d962041d05a319e485b96136a5dMathias Agopian                CallStack stack(LOG_TAG);
820e8bbee5775d81c7bbc479b995496cac9238559fMathias Agopian            }
83ecfe091af3e3e5d7165fe64a5f9c84c4576a6c06Mathias Agopian        }
840e8bbee5775d81c7bbc479b995496cac9238559fMathias Agopian        tls->error = error;
85518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
86518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
87518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
88518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianbool egl_tls_t::logNoContextCall() {
89518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    egl_tls_t* tls = getTLS();
90518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    if (tls->logCallWithNoContext == true) {
91518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        tls->logCallWithNoContext = false;
92518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        return true;
93518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
94518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    return false;
95518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
96518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
97518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianegl_tls_t* egl_tls_t::getTLS() {
98518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
99518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    if (tls == 0) {
100518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        tls = new egl_tls_t;
101518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        pthread_setspecific(sKey, tls);
102518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
103518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    return tls;
104518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
105518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
106518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid egl_tls_t::clearTLS() {
1074e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian    if (sKey != TLS_KEY_NOT_INITIALIZED) {
108518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
109518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (tls) {
110518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            pthread_setspecific(sKey, 0);
1114e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian            delete tls;
112518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
113518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
114518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
115518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
116518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid egl_tls_t::clearError() {
117518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    // This must clear the error from all the underlying EGL implementations as
118518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    // well as the EGL wrapper layer.
119518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    eglGetError();
120518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
121518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
122518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias AgopianEGLint egl_tls_t::getError() {
1234e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian    if (sKey == TLS_KEY_NOT_INITIALIZED) {
124518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        return EGL_SUCCESS;
1254e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian    }
126518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
1274e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian    if (!tls) {
1284e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian        return EGL_SUCCESS;
1294e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian    }
130518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    EGLint error = tls->error;
131518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    tls->error = EGL_SUCCESS;
132518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    return error;
133518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
134518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
135518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid egl_tls_t::setContext(EGLContext ctx) {
136518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    validateTLSKey();
137518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    getTLS()->ctx = ctx;
138518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
139518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
140518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias AgopianEGLContext egl_tls_t::getContext() {
1414e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian    if (sKey == TLS_KEY_NOT_INITIALIZED) {
142518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        return EGL_NO_CONTEXT;
1434e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian    }
144518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    egl_tls_t* tls = (egl_tls_t *)pthread_getspecific(sKey);
145518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    if (!tls) return EGL_NO_CONTEXT;
146518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    return tls->ctx;
147518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
148518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
149518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
150518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} // namespace android
151