blob: 0f92864635c8fa6514fedc9c346b4767c6575dea [file] [log] [blame]
Mathias Agopian518ec112011-05-13 16:21:08 -07001/*
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
Jamie Gennisaca51c02011-11-03 17:42:43 -070017#include "egl_cache.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070018#include "egl_display.h"
19#include "egl_object.h"
20#include "egl_tls.h"
21#include "egl_impl.h"
22#include "Loader.h"
23
24// ----------------------------------------------------------------------------
25namespace android {
26// ----------------------------------------------------------------------------
27
28extern void initEglTraceLevel();
29extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
30
31static int cmp_configs(const void* a, const void *b) {
32 const egl_config_t& c0 = *(egl_config_t const *)a;
33 const egl_config_t& c1 = *(egl_config_t const *)b;
34 return c0<c1 ? -1 : (c1<c0 ? 1 : 0);
35}
36
37// ----------------------------------------------------------------------------
38
39egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];
40
41egl_display_t::egl_display_t() :
42 magic('_dpy'), numTotalConfigs(0), configs(0), refs(0) {
43}
44
45egl_display_t::~egl_display_t() {
46 magic = 0;
47}
48
49egl_display_t* egl_display_t::get(EGLDisplay dpy) {
50 uintptr_t index = uintptr_t(dpy)-1U;
51 return (index >= NUM_DISPLAYS) ? NULL : &sDisplay[index];
52}
53
54void egl_display_t::addObject(egl_object_t* object) {
55 Mutex::Autolock _l(lock);
56 objects.add(object);
57}
58
Mathias Agopian5b287a62011-05-16 18:58:55 -070059void egl_display_t::removeObject(egl_object_t* object) {
60 Mutex::Autolock _l(lock);
61 objects.remove(object);
62}
63
Mathias Agopian518ec112011-05-13 16:21:08 -070064bool egl_display_t::getObject(egl_object_t* object) {
65 Mutex::Autolock _l(lock);
66 if (objects.indexOf(object) >= 0) {
67 object->incRef();
68 return true;
69 }
70 return false;
71}
72
Mathias Agopian518ec112011-05-13 16:21:08 -070073EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp) {
74 if (uintptr_t(disp) >= NUM_DISPLAYS)
75 return NULL;
76
77 return sDisplay[uintptr_t(disp)].getDisplay(disp);
78}
79
80EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {
81
82 Mutex::Autolock _l(lock);
83
84 // get our driver loader
85 Loader& loader(Loader::getInstance());
86
87 for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
88 egl_connection_t* const cnx = &gEGLImpl[i];
89 if (cnx->dso && disp[i].dpy == EGL_NO_DISPLAY) {
90 EGLDisplay dpy = cnx->egl.eglGetDisplay(display);
91 disp[i].dpy = dpy;
92 if (dpy == EGL_NO_DISPLAY) {
93 loader.close(cnx->dso);
94 cnx->dso = NULL;
95 }
96 }
97 }
98
99 return EGLDisplay(uintptr_t(display) + 1U);
100}
101
102EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
103
104 Mutex::Autolock _l(lock);
105
106 if (refs > 0) {
107 if (major != NULL)
108 *major = VERSION_MAJOR;
109 if (minor != NULL)
110 *minor = VERSION_MINOR;
111 refs++;
112 return EGL_TRUE;
113 }
114
115#if EGL_TRACE
116
117 // Called both at early_init time and at this time. (Early_init is pre-zygote, so
118 // the information from that call may be stale.)
119 initEglTraceLevel();
120
121#endif
122
123 setGLHooksThreadSpecific(&gHooksNoContext);
124
125 // initialize each EGL and
126 // build our own extension string first, based on the extension we know
127 // and the extension supported by our client implementation
128 for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
129 egl_connection_t* const cnx = &gEGLImpl[i];
130 cnx->major = -1;
131 cnx->minor = -1;
132 if (!cnx->dso)
133 continue;
134
135#if defined(ADRENO130)
136#warning "Adreno-130 eglInitialize() workaround"
137 /*
138 * The ADRENO 130 driver returns a different EGLDisplay each time
139 * eglGetDisplay() is called, but also makes the EGLDisplay invalid
140 * after eglTerminate() has been called, so that eglInitialize()
141 * cannot be called again. Therefore, we need to make sure to call
142 * eglGetDisplay() before calling eglInitialize();
143 */
144 if (i == IMPL_HARDWARE) {
145 disp[i].dpy =
146 cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
147 }
148#endif
149
150 EGLDisplay idpy = disp[i].dpy;
151 if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
152 //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
153 // i, idpy, cnx->major, cnx->minor, cnx);
154
155 // display is now initialized
156 disp[i].state = egl_display_t::INITIALIZED;
157
158 // get the query-strings for this display for each implementation
159 disp[i].queryString.vendor = cnx->egl.eglQueryString(idpy,
160 EGL_VENDOR);
161 disp[i].queryString.version = cnx->egl.eglQueryString(idpy,
162 EGL_VERSION);
163 disp[i].queryString.extensions = cnx->egl.eglQueryString(idpy,
164 EGL_EXTENSIONS);
165 disp[i].queryString.clientApi = cnx->egl.eglQueryString(idpy,
166 EGL_CLIENT_APIS);
167
168 } else {
169 LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
170 egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
171 }
172 }
173
Jamie Gennisaca51c02011-11-03 17:42:43 -0700174 egl_cache_t::get()->initialize(this);
175
Mathias Agopian518ec112011-05-13 16:21:08 -0700176 EGLBoolean res = EGL_FALSE;
177 for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
178 egl_connection_t* const cnx = &gEGLImpl[i];
179 if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
180 EGLint n;
181 if (cnx->egl.eglGetConfigs(disp[i].dpy, 0, 0, &n)) {
182 disp[i].config = (EGLConfig*) malloc(sizeof(EGLConfig) * n);
183 if (disp[i].config) {
184 if (cnx->egl.eglGetConfigs(disp[i].dpy, disp[i].config, n,
185 &disp[i].numConfigs)) {
186 numTotalConfigs += n;
187 res = EGL_TRUE;
188 }
189 }
190 }
191 }
192 }
193
194 if (res == EGL_TRUE) {
195 configs = new egl_config_t[numTotalConfigs];
196 for (int i = 0, k = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
197 egl_connection_t* const cnx = &gEGLImpl[i];
198 if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
199 for (int j = 0; j < disp[i].numConfigs; j++) {
200 configs[k].impl = i;
201 configs[k].config = disp[i].config[j];
202 configs[k].configId = k + 1; // CONFIG_ID start at 1
203 // store the implementation's CONFIG_ID
204 cnx->egl.eglGetConfigAttrib(disp[i].dpy, disp[i].config[j],
205 EGL_CONFIG_ID, &configs[k].implConfigId);
206 k++;
207 }
208 }
209 }
210
211 // sort our configurations so we can do binary-searches
212 qsort(configs, numTotalConfigs, sizeof(egl_config_t), cmp_configs);
213
214 refs++;
215 if (major != NULL)
216 *major = VERSION_MAJOR;
217 if (minor != NULL)
218 *minor = VERSION_MINOR;
219 return EGL_TRUE;
220 }
221 return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
222}
223
224EGLBoolean egl_display_t::terminate() {
225
226 Mutex::Autolock _l(lock);
227
228 if (refs == 0) {
229 return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
230 }
231
232 // this is specific to Android, display termination is ref-counted.
233 if (refs > 1) {
234 refs--;
235 return EGL_TRUE;
236 }
237
238 EGLBoolean res = EGL_FALSE;
239 for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
240 egl_connection_t* const cnx = &gEGLImpl[i];
241 if (cnx->dso && disp[i].state == egl_display_t::INITIALIZED) {
242 if (cnx->egl.eglTerminate(disp[i].dpy) == EGL_FALSE) {
243 LOGW("%d: eglTerminate(%p) failed (%s)", i, disp[i].dpy,
244 egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
245 }
246 // REVISIT: it's unclear what to do if eglTerminate() fails
247 free(disp[i].config);
248
249 disp[i].numConfigs = 0;
250 disp[i].config = 0;
251 disp[i].state = egl_display_t::TERMINATED;
252
253 res = EGL_TRUE;
254 }
255 }
256
Mathias Agopian5b287a62011-05-16 18:58:55 -0700257 // Mark all objects remaining in the list as terminated, unless
258 // there are no reference to them, it which case, we're free to
259 // delete them.
260 size_t count = objects.size();
261 LOGW_IF(count, "eglTerminate() called w/ %d objects remaining", count);
262 for (size_t i=0 ; i<count ; i++) {
263 egl_object_t* o = objects.itemAt(i);
264 o->destroy();
265 }
266
267 // this marks all object handles are "terminated"
268 objects.clear();
Mathias Agopian518ec112011-05-13 16:21:08 -0700269
270 refs--;
271 numTotalConfigs = 0;
272 delete[] configs;
273 return res;
274}
275
276
277// ----------------------------------------------------------------------------
278}; // namespace android
279// ----------------------------------------------------------------------------