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