OSDN Git Service

am f29b86b2: (-s ours) am 76942a49: Merge "egl: Reintroduce eglGetRenderBufferANDROID"
[android-x86/frameworks-native.git] / opengl / libs / EGL / egl_display.cpp
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 #define __STDC_LIMIT_MACROS 1
18
19 #include <string.h>
20
21 #include "egl_cache.h"
22 #include "egl_display.h"
23 #include "egl_object.h"
24 #include "egl_tls.h"
25 #include "egl_impl.h"
26 #include "Loader.h"
27 #include <cutils/properties.h>
28
29 // ----------------------------------------------------------------------------
30 namespace android {
31 // ----------------------------------------------------------------------------
32
33 static char const * const sVendorString     = "Android";
34 static char const * const sVersionString    = "1.4 Android META-EGL";
35 static char const * const sClientApiString  = "OpenGL_ES";
36
37 // this is the list of EGL extensions that are exposed to applications
38 // some of them are mandatory because used by the ANDROID system.
39 //
40 // mandatory extensions are required per the CDD and not explicitly
41 // checked during EGL initialization. the system *assumes* these extensions
42 // are present. the system may not function properly if some mandatory
43 // extensions are missing.
44 //
45 // NOTE: sExtensionString MUST be have a single space as the last character.
46 //
47 static char const * const sExtensionString  =
48         "EGL_KHR_image "                        // mandatory
49         "EGL_KHR_image_base "                   // mandatory
50         "EGL_KHR_image_pixmap "
51         "EGL_KHR_gl_texture_2D_image "
52         "EGL_KHR_gl_texture_cubemap_image "
53         "EGL_KHR_gl_renderbuffer_image "
54         "EGL_KHR_fence_sync "
55         "EGL_EXT_create_context_robustness "
56         "EGL_NV_system_time "
57         "EGL_ANDROID_image_native_buffer "      // mandatory
58         ;
59
60 // extensions not exposed to applications but used by the ANDROID system
61 //      "EGL_ANDROID_recordable "               // mandatory
62 //      "EGL_ANDROID_framebuffer_target "       // mandatory for HWC 1.1
63 //      "EGL_ANDROID_blob_cache "               // strongly recommended
64 //      "EGL_ANDROID_native_fence_sync "        // strongly recommended
65 //      "EGL_IMG_hibernate_process "            // optional
66
67 extern void initEglTraceLevel();
68 extern void initEglDebugLevel();
69 extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
70
71 // ----------------------------------------------------------------------------
72
73 egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];
74
75 egl_display_t::egl_display_t() :
76     magic('_dpy'), finishOnSwap(false), traceGpuCompletion(false), refs(0) {
77 }
78
79 egl_display_t::~egl_display_t() {
80     magic = 0;
81     egl_cache_t::get()->terminate();
82 }
83
84 egl_display_t* egl_display_t::get(EGLDisplay dpy) {
85     uintptr_t index = uintptr_t(dpy)-1U;
86     return (index >= NUM_DISPLAYS) ? NULL : &sDisplay[index];
87 }
88
89 void egl_display_t::addObject(egl_object_t* object) {
90     Mutex::Autolock _l(lock);
91     objects.add(object);
92 }
93
94 void egl_display_t::removeObject(egl_object_t* object) {
95     Mutex::Autolock _l(lock);
96     objects.remove(object);
97 }
98
99 bool egl_display_t::getObject(egl_object_t* object) const {
100     Mutex::Autolock _l(lock);
101     if (objects.indexOf(object) >= 0) {
102         if (object->getDisplay() == this) {
103             object->incRef();
104             return true;
105         }
106     }
107     return false;
108 }
109
110 EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp) {
111     if (uintptr_t(disp) >= NUM_DISPLAYS)
112         return NULL;
113
114     return sDisplay[uintptr_t(disp)].getDisplay(disp);
115 }
116
117 EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {
118
119     Mutex::Autolock _l(lock);
120
121     // get our driver loader
122     Loader& loader(Loader::getInstance());
123
124     egl_connection_t* const cnx = &gEGLImpl;
125     if (cnx->dso && disp.dpy == EGL_NO_DISPLAY) {
126         EGLDisplay dpy = cnx->egl.eglGetDisplay(display);
127         disp.dpy = dpy;
128         if (dpy == EGL_NO_DISPLAY) {
129             loader.close(cnx->dso);
130             cnx->dso = NULL;
131         }
132     }
133
134     return EGLDisplay(uintptr_t(display) + 1U);
135 }
136
137 EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
138
139     Mutex::Autolock _l(lock);
140
141     if (refs > 0) {
142         if (major != NULL)
143             *major = VERSION_MAJOR;
144         if (minor != NULL)
145             *minor = VERSION_MINOR;
146         refs++;
147         return EGL_TRUE;
148     }
149
150 #if EGL_TRACE
151
152     // Called both at early_init time and at this time. (Early_init is pre-zygote, so
153     // the information from that call may be stale.)
154     initEglTraceLevel();
155     initEglDebugLevel();
156
157 #endif
158
159     setGLHooksThreadSpecific(&gHooksNoContext);
160
161     // initialize each EGL and
162     // build our own extension string first, based on the extension we know
163     // and the extension supported by our client implementation
164
165     egl_connection_t* const cnx = &gEGLImpl;
166     cnx->major = -1;
167     cnx->minor = -1;
168     if (cnx->dso) {
169
170 #if defined(ADRENO130)
171 #warning "Adreno-130 eglInitialize() workaround"
172         /*
173          * The ADRENO 130 driver returns a different EGLDisplay each time
174          * eglGetDisplay() is called, but also makes the EGLDisplay invalid
175          * after eglTerminate() has been called, so that eglInitialize()
176          * cannot be called again. Therefore, we need to make sure to call
177          * eglGetDisplay() before calling eglInitialize();
178          */
179         if (i == IMPL_HARDWARE) {
180             disp[i].dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
181         }
182 #endif
183
184         EGLDisplay idpy = disp.dpy;
185         if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
186             //ALOGD("initialized dpy=%p, ver=%d.%d, cnx=%p",
187             //        idpy, cnx->major, cnx->minor, cnx);
188
189             // display is now initialized
190             disp.state = egl_display_t::INITIALIZED;
191
192             // get the query-strings for this display for each implementation
193             disp.queryString.vendor = cnx->egl.eglQueryString(idpy,
194                     EGL_VENDOR);
195             disp.queryString.version = cnx->egl.eglQueryString(idpy,
196                     EGL_VERSION);
197             disp.queryString.extensions = cnx->egl.eglQueryString(idpy,
198                     EGL_EXTENSIONS);
199             disp.queryString.clientApi = cnx->egl.eglQueryString(idpy,
200                     EGL_CLIENT_APIS);
201
202         } else {
203             ALOGW("eglInitialize(%p) failed (%s)", idpy,
204                     egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
205         }
206     }
207
208     // the query strings are per-display
209     mVendorString.setTo(sVendorString);
210     mVersionString.setTo(sVersionString);
211     mClientApiString.setTo(sClientApiString);
212
213     // we only add extensions that exist in the implementation
214     char const* start = sExtensionString;
215     char const* end;
216     do {
217         // find the space separating this extension for the next one
218         end = strchr(start, ' ');
219         if (end) {
220             // length of the extension string
221             const size_t len = end - start;
222             if (len) {
223                 // NOTE: we could avoid the copy if we had strnstr.
224                 const String8 ext(start, len);
225                 // now look for this extension
226                 if (disp.queryString.extensions) {
227                     // if we find it, add this extension string to our list
228                     // (and don't forget the space)
229                     const char* match = strstr(disp.queryString.extensions, ext.string());
230                     if (match && (match[len] == ' ' || match[len] == 0)) {
231                         mExtensionString.append(start, len+1);
232                     }
233                 }
234             }
235             // process the next extension string, and skip the space.
236             start = end + 1;
237         }
238     } while (end);
239
240     egl_cache_t::get()->initialize(this);
241
242     char value[PROPERTY_VALUE_MAX];
243     property_get("debug.egl.finish", value, "0");
244     if (atoi(value)) {
245         finishOnSwap = true;
246     }
247
248     property_get("debug.egl.traceGpuCompletion", value, "0");
249     if (atoi(value)) {
250         traceGpuCompletion = true;
251     }
252
253     refs++;
254     if (major != NULL)
255         *major = VERSION_MAJOR;
256     if (minor != NULL)
257         *minor = VERSION_MINOR;
258
259     mHibernation.setDisplayValid(true);
260
261     return EGL_TRUE;
262 }
263
264 EGLBoolean egl_display_t::terminate() {
265
266     Mutex::Autolock _l(lock);
267
268     if (refs == 0) {
269         /*
270          * From the EGL spec (3.2):
271          * "Termination of a display that has already been terminated,
272          *  (...), is allowed, but the only effect of such a call is
273          *  to return EGL_TRUE (...)
274          */
275         return EGL_TRUE;
276     }
277
278     // this is specific to Android, display termination is ref-counted.
279     if (refs > 1) {
280         refs--;
281         return EGL_TRUE;
282     }
283
284     EGLBoolean res = EGL_FALSE;
285     egl_connection_t* const cnx = &gEGLImpl;
286     if (cnx->dso && disp.state == egl_display_t::INITIALIZED) {
287         if (cnx->egl.eglTerminate(disp.dpy) == EGL_FALSE) {
288             ALOGW("eglTerminate(%p) failed (%s)", disp.dpy,
289                     egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
290         }
291         // REVISIT: it's unclear what to do if eglTerminate() fails
292         disp.state = egl_display_t::TERMINATED;
293         res = EGL_TRUE;
294     }
295
296     mHibernation.setDisplayValid(false);
297
298     // Reset the extension string since it will be regenerated if we get
299     // reinitialized.
300     mExtensionString.setTo("");
301
302     // Mark all objects remaining in the list as terminated, unless
303     // there are no reference to them, it which case, we're free to
304     // delete them.
305     size_t count = objects.size();
306     ALOGW_IF(count, "eglTerminate() called w/ %d objects remaining", count);
307     for (size_t i=0 ; i<count ; i++) {
308         egl_object_t* o = objects.itemAt(i);
309         o->destroy();
310     }
311
312     // this marks all object handles are "terminated"
313     objects.clear();
314
315     refs--;
316     return res;
317 }
318
319 void egl_display_t::loseCurrent(egl_context_t * cur_c)
320 {
321     if (cur_c) {
322         egl_display_t* display = cur_c->getDisplay();
323         if (display) {
324             display->loseCurrentImpl(cur_c);
325         }
326     }
327 }
328
329 void egl_display_t::loseCurrentImpl(egl_context_t * cur_c)
330 {
331     // by construction, these are either 0 or valid (possibly terminated)
332     // it should be impossible for these to be invalid
333     ContextRef _cur_c(cur_c);
334     SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : NULL);
335     SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL);
336
337     { // scope for the lock
338         Mutex::Autolock _l(lock);
339         cur_c->onLooseCurrent();
340
341     }
342
343     // This cannot be called with the lock held because it might end-up
344     // calling back into EGL (in particular when a surface is destroyed
345     // it calls ANativeWindow::disconnect
346     _cur_c.release();
347     _cur_r.release();
348     _cur_d.release();
349 }
350
351 EGLBoolean egl_display_t::makeCurrent(egl_context_t* c, egl_context_t* cur_c,
352         EGLSurface draw, EGLSurface read, EGLContext ctx,
353         EGLSurface impl_draw, EGLSurface impl_read, EGLContext impl_ctx)
354 {
355     EGLBoolean result;
356
357     // by construction, these are either 0 or valid (possibly terminated)
358     // it should be impossible for these to be invalid
359     ContextRef _cur_c(cur_c);
360     SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : NULL);
361     SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL);
362
363     { // scope for the lock
364         Mutex::Autolock _l(lock);
365         if (c) {
366             result = c->cnx->egl.eglMakeCurrent(
367                     disp.dpy, impl_draw, impl_read, impl_ctx);
368             if (result == EGL_TRUE) {
369                 c->onMakeCurrent(draw, read);
370                 if (!cur_c) {
371                     mHibernation.incWakeCount(HibernationMachine::STRONG);
372                 }
373             }
374         } else {
375             result = cur_c->cnx->egl.eglMakeCurrent(
376                     disp.dpy, impl_draw, impl_read, impl_ctx);
377             if (result == EGL_TRUE) {
378                 cur_c->onLooseCurrent();
379                 mHibernation.decWakeCount(HibernationMachine::STRONG);
380             }
381         }
382     }
383
384     if (result == EGL_TRUE) {
385         // This cannot be called with the lock held because it might end-up
386         // calling back into EGL (in particular when a surface is destroyed
387         // it calls ANativeWindow::disconnect
388         _cur_c.release();
389         _cur_r.release();
390         _cur_d.release();
391     }
392
393     return result;
394 }
395
396 // ----------------------------------------------------------------------------
397
398 bool egl_display_t::HibernationMachine::incWakeCount(WakeRefStrength strength) {
399     Mutex::Autolock _l(mLock);
400     ALOGE_IF(mWakeCount < 0 || mWakeCount == INT32_MAX,
401              "Invalid WakeCount (%d) on enter\n", mWakeCount);
402
403     mWakeCount++;
404     if (strength == STRONG)
405         mAttemptHibernation = false;
406
407     if (CC_UNLIKELY(mHibernating)) {
408         ALOGV("Awakening\n");
409         egl_connection_t* const cnx = &gEGLImpl;
410
411         // These conditions should be guaranteed before entering hibernation;
412         // we don't want to get into a state where we can't wake up.
413         ALOGD_IF(!mDpyValid || !cnx->egl.eglAwakenProcessIMG,
414                  "Invalid hibernation state, unable to awaken\n");
415
416         if (!cnx->egl.eglAwakenProcessIMG()) {
417             ALOGE("Failed to awaken EGL implementation\n");
418             return false;
419         }
420         mHibernating = false;
421     }
422     return true;
423 }
424
425 void egl_display_t::HibernationMachine::decWakeCount(WakeRefStrength strength) {
426     Mutex::Autolock _l(mLock);
427     ALOGE_IF(mWakeCount <= 0, "Invalid WakeCount (%d) on leave\n", mWakeCount);
428
429     mWakeCount--;
430     if (strength == STRONG)
431         mAttemptHibernation = true;
432
433     if (mWakeCount == 0 && CC_UNLIKELY(mAttemptHibernation)) {
434         egl_connection_t* const cnx = &gEGLImpl;
435         mAttemptHibernation = false;
436         if (mAllowHibernation && mDpyValid &&
437                 cnx->egl.eglHibernateProcessIMG &&
438                 cnx->egl.eglAwakenProcessIMG) {
439             ALOGV("Hibernating\n");
440             if (!cnx->egl.eglHibernateProcessIMG()) {
441                 ALOGE("Failed to hibernate EGL implementation\n");
442                 return;
443             }
444             mHibernating = true;
445         }
446     }
447 }
448
449 void egl_display_t::HibernationMachine::setDisplayValid(bool valid) {
450     Mutex::Autolock _l(mLock);
451     mDpyValid = valid;
452 }
453
454 // ----------------------------------------------------------------------------
455 }; // namespace android
456 // ----------------------------------------------------------------------------