1 /*
2 ** Copyright 2007, 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
19 #include <hardware/gralloc.h>
20
21 #include <EGL/egl.h>
22
23 #include <cutils/properties.h>
24
25 #include <log/log.h>
26
27 #include "../egl_impl.h"
28
29 #include "egldefs.h"
30 #include "egl_tls.h"
31 #include "egl_display.h"
32 #include "egl_object.h"
33 #include "egl_layers.h"
34 #include "CallStack.h"
35 #include "Loader.h"
36
37 // ----------------------------------------------------------------------------
38 namespace android {
39 // ----------------------------------------------------------------------------
40
41 egl_connection_t gEGLImpl;
42 gl_hooks_t gHooks[2];
43 gl_hooks_t gHooksNoContext;
44 pthread_key_t gGLWrapperKey = -1;
45
46 // ----------------------------------------------------------------------------
47
setGLHooksThreadSpecific(gl_hooks_t const * value)48 void setGLHooksThreadSpecific(gl_hooks_t const *value) {
49 setGlThreadSpecific(value);
50 }
51
52 /*****************************************************************************/
53
gl_no_context()54 static int gl_no_context() {
55 if (egl_tls_t::logNoContextCall()) {
56 char const* const error = "call to OpenGL ES API with "
57 "no current context (logged once per thread)";
58 if (LOG_NDEBUG) {
59 ALOGE(error);
60 } else {
61 LOG_ALWAYS_FATAL(error);
62 }
63 char value[PROPERTY_VALUE_MAX];
64 property_get("debug.egl.callstack", value, "0");
65 if (atoi(value)) {
66 CallStack::log(LOG_TAG);
67 }
68 }
69 return 0;
70 }
71
early_egl_init(void)72 static void early_egl_init(void)
73 {
74 int numHooks = sizeof(gHooksNoContext) / sizeof(EGLFuncPointer);
75 EGLFuncPointer *iter = reinterpret_cast<EGLFuncPointer*>(&gHooksNoContext);
76 for (int hook = 0; hook < numHooks; ++hook) {
77 *(iter++) = reinterpret_cast<EGLFuncPointer>(gl_no_context);
78 }
79
80 setGLHooksThreadSpecific(&gHooksNoContext);
81 }
82
83 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
84 static int sEarlyInitState = pthread_once(&once_control, &early_egl_init);
85
86 // ----------------------------------------------------------------------------
87
validate_display(EGLDisplay dpy)88 egl_display_ptr validate_display(EGLDisplay dpy) {
89 egl_display_ptr dp = get_display(dpy);
90 if (!dp)
91 return setError(EGL_BAD_DISPLAY, egl_display_ptr(nullptr));
92 if (!dp->isReady())
93 return setError(EGL_NOT_INITIALIZED, egl_display_ptr(nullptr));
94
95 return dp;
96 }
97
validate_display_connection(EGLDisplay dpy,egl_connection_t * & cnx)98 egl_display_ptr validate_display_connection(EGLDisplay dpy,
99 egl_connection_t*& cnx) {
100 cnx = nullptr;
101 egl_display_ptr dp = validate_display(dpy);
102 if (!dp)
103 return dp;
104 cnx = &gEGLImpl;
105 if (cnx->dso == nullptr) {
106 return setError(EGL_BAD_CONFIG, egl_display_ptr(nullptr));
107 }
108 return dp;
109 }
110
111 // ----------------------------------------------------------------------------
112
egl_get_string_for_current_context(GLenum name)113 const GLubyte * egl_get_string_for_current_context(GLenum name) {
114 // NOTE: returning NULL here will fall-back to the default
115 // implementation.
116
117 EGLContext context = egl_tls_t::getContext();
118 if (context == EGL_NO_CONTEXT)
119 return nullptr;
120
121 egl_context_t const * const c = get_context(context);
122 if (c == nullptr) // this should never happen, by construction
123 return nullptr;
124
125 if (name != GL_EXTENSIONS)
126 return nullptr;
127
128 return (const GLubyte *)c->gl_extensions.c_str();
129 }
130
egl_get_string_for_current_context(GLenum name,GLuint index)131 const GLubyte * egl_get_string_for_current_context(GLenum name, GLuint index) {
132 // NOTE: returning NULL here will fall-back to the default
133 // implementation.
134
135 EGLContext context = egl_tls_t::getContext();
136 if (context == EGL_NO_CONTEXT)
137 return nullptr;
138
139 egl_context_t const * const c = get_context(context);
140 if (c == nullptr) // this should never happen, by construction
141 return nullptr;
142
143 if (name != GL_EXTENSIONS)
144 return nullptr;
145
146 // if index is out of bounds, assume it will be in the default
147 // implementation too, so we don't have to generate a GL error here
148 if (index >= c->tokenized_gl_extensions.size())
149 return nullptr;
150
151 return (const GLubyte *)c->tokenized_gl_extensions[index].c_str();
152 }
153
egl_get_num_extensions_for_current_context()154 GLint egl_get_num_extensions_for_current_context() {
155 // NOTE: returning -1 here will fall-back to the default
156 // implementation.
157
158 EGLContext context = egl_tls_t::getContext();
159 if (context == EGL_NO_CONTEXT)
160 return -1;
161
162 egl_context_t const * const c = get_context(context);
163 if (c == nullptr) // this should never happen, by construction
164 return -1;
165
166 return (GLint)c->tokenized_gl_extensions.size();
167 }
168
egl_get_connection()169 egl_connection_t* egl_get_connection() {
170 return &gEGLImpl;
171 }
172
173 // ----------------------------------------------------------------------------
174
175 // this mutex protects:
176 // d->disp[]
177 // egl_init_drivers_locked()
178 //
egl_init_drivers_locked()179 static EGLBoolean egl_init_drivers_locked() {
180 if (sEarlyInitState) {
181 // initialized by static ctor. should be set here.
182 return EGL_FALSE;
183 }
184
185 // get our driver loader
186 Loader& loader(Loader::getInstance());
187
188 // dynamically load our EGL implementation
189 egl_connection_t* cnx = &gEGLImpl;
190 cnx->hooks[egl_connection_t::GLESv1_INDEX] = &gHooks[egl_connection_t::GLESv1_INDEX];
191 cnx->hooks[egl_connection_t::GLESv2_INDEX] = &gHooks[egl_connection_t::GLESv2_INDEX];
192 cnx->dso = loader.open(cnx);
193
194 // Check to see if any layers are enabled and route functions through them
195 if (cnx->dso) {
196 // Layers can be enabled long after the drivers have been loaded.
197 // They will only be initialized once.
198 LayerLoader& layer_loader(LayerLoader::getInstance());
199 layer_loader.InitLayers(cnx);
200 }
201
202 return cnx->dso ? EGL_TRUE : EGL_FALSE;
203 }
204
205 static pthread_mutex_t sInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
206
egl_init_drivers()207 EGLBoolean egl_init_drivers() {
208 EGLBoolean res;
209 pthread_mutex_lock(&sInitDriverMutex);
210 res = egl_init_drivers_locked();
211 pthread_mutex_unlock(&sInitDriverMutex);
212 return res;
213 }
214
215 static pthread_mutex_t sLogPrintMutex = PTHREAD_MUTEX_INITIALIZER;
216 static std::chrono::steady_clock::time_point sLogPrintTime;
217 static constexpr std::chrono::seconds DURATION(1);
218
gl_unimplemented()219 void gl_unimplemented() {
220 bool printLog = false;
221 auto now = std::chrono::steady_clock::now();
222 pthread_mutex_lock(&sLogPrintMutex);
223 if ((now - sLogPrintTime) > DURATION) {
224 sLogPrintTime = now;
225 printLog = true;
226 }
227 pthread_mutex_unlock(&sLogPrintMutex);
228 if (printLog) {
229 ALOGE("called unimplemented OpenGL ES API");
230 char value[PROPERTY_VALUE_MAX];
231 property_get("debug.egl.callstack", value, "0");
232 if (atoi(value)) {
233 CallStack::log(LOG_TAG);
234 }
235 }
236 }
237
gl_noop()238 void gl_noop() {
239 }
240
241 // ----------------------------------------------------------------------------
242
setGlThreadSpecific(gl_hooks_t const * value)243 void setGlThreadSpecific(gl_hooks_t const *value) {
244 gl_hooks_t const * volatile * tls_hooks = get_tls_hooks();
245 tls_hooks[TLS_SLOT_OPENGL_API] = value;
246 }
247
248 // ----------------------------------------------------------------------------
249 // GL / EGL hooks
250 // ----------------------------------------------------------------------------
251
252 #undef GL_ENTRY
253 #undef EGL_ENTRY
254 #define GL_ENTRY(_r, _api, ...) #_api,
255 #define EGL_ENTRY(_r, _api, ...) #_api,
256
257 char const * const gl_names[] = {
258 #include "../entries.in"
259 nullptr
260 };
261
262 char const * const gl_names_1[] = {
263 #include "../entries_gles1.in"
264 nullptr
265 };
266
267 char const * const egl_names[] = {
268 #include "egl_entries.in"
269 nullptr
270 };
271
272 char const * const platform_names[] = {
273 #include "platform_entries.in"
274 nullptr
275 };
276
277 #undef GL_ENTRY
278 #undef EGL_ENTRY
279
280
281 // ----------------------------------------------------------------------------
282 }; // namespace android
283 // ----------------------------------------------------------------------------
284
285