summaryrefslogtreecommitdiffstats
path: root/opengl
diff options
context:
space:
mode:
authorMichael Lentine <mlentine@google.com>2015-01-28 22:38:42 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-01-28 22:38:42 +0000
commit2f1e3b4d219d1ad3fe66cc9abb4ed61be9906ed1 (patch)
tree94092f3a92ff741bc7fdf101b85d84ae9965d140 /opengl
parente55073a96ca7e9447592988614664b3c9666d93a (diff)
parentd6fce7ab66e5d33e3ee16247485d1b8c26dd7ee8 (diff)
downloadframeworks_native-2f1e3b4d219d1ad3fe66cc9abb4ed61be9906ed1.zip
frameworks_native-2f1e3b4d219d1ad3fe66cc9abb4ed61be9906ed1.tar.gz
frameworks_native-2f1e3b4d219d1ad3fe66cc9abb4ed61be9906ed1.tar.bz2
am d6fce7ab: Merge "Remove lock around ref count check in terminate." into lmp-mr1-dev
* commit 'd6fce7ab66e5d33e3ee16247485d1b8c26dd7ee8': Remove lock around ref count check in terminate.
Diffstat (limited to 'opengl')
-rw-r--r--opengl/libs/EGL/egl_display.cpp263
-rw-r--r--opengl/libs/EGL/egl_display.h4
2 files changed, 147 insertions, 120 deletions
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 7784ca6..ec59235 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -57,7 +57,7 @@ static bool findExtension(const char* exts, const char* name, size_t nameLen) {
egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];
egl_display_t::egl_display_t() :
- magic('_dpy'), finishOnSwap(false), traceGpuCompletion(false), refs(0) {
+ magic('_dpy'), finishOnSwap(false), traceGpuCompletion(false), refs(0), eglIsInitialized(false) {
}
egl_display_t::~egl_display_t() {
@@ -120,163 +120,188 @@ EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {
EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
- Mutex::Autolock _l(lock);
+ {
+ Mutex::Autolock _rf(refLock);
- if (refs > 0) {
- if (major != NULL)
- *major = VERSION_MAJOR;
- if (minor != NULL)
- *minor = VERSION_MINOR;
refs++;
- return EGL_TRUE;
+ if (refs > 1) {
+ if (major != NULL)
+ *major = VERSION_MAJOR;
+ if (minor != NULL)
+ *minor = VERSION_MINOR;
+ while(!eglIsInitialized) refCond.wait(refLock);
+ return EGL_TRUE;
+ }
+
+ while(eglIsInitialized) refCond.wait(refLock);
}
+ {
+ Mutex::Autolock _l(lock);
+
#if EGL_TRACE
- // Called both at early_init time and at this time. (Early_init is pre-zygote, so
- // the information from that call may be stale.)
- initEglTraceLevel();
- initEglDebugLevel();
+ // Called both at early_init time and at this time. (Early_init is pre-zygote, so
+ // the information from that call may be stale.)
+ initEglTraceLevel();
+ initEglDebugLevel();
#endif
- setGLHooksThreadSpecific(&gHooksNoContext);
-
- // initialize each EGL and
- // build our own extension string first, based on the extension we know
- // and the extension supported by our client implementation
+ setGLHooksThreadSpecific(&gHooksNoContext);
- egl_connection_t* const cnx = &gEGLImpl;
- cnx->major = -1;
- cnx->minor = -1;
- if (cnx->dso) {
- EGLDisplay idpy = disp.dpy;
- if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
- //ALOGD("initialized dpy=%p, ver=%d.%d, cnx=%p",
- // idpy, cnx->major, cnx->minor, cnx);
-
- // display is now initialized
- disp.state = egl_display_t::INITIALIZED;
-
- // get the query-strings for this display for each implementation
- disp.queryString.vendor = cnx->egl.eglQueryString(idpy,
- EGL_VENDOR);
- disp.queryString.version = cnx->egl.eglQueryString(idpy,
- EGL_VERSION);
- disp.queryString.extensions = cnx->egl.eglQueryString(idpy,
- EGL_EXTENSIONS);
- disp.queryString.clientApi = cnx->egl.eglQueryString(idpy,
- EGL_CLIENT_APIS);
+ // initialize each EGL and
+ // build our own extension string first, based on the extension we know
+ // and the extension supported by our client implementation
- } else {
- ALOGW("eglInitialize(%p) failed (%s)", idpy,
- egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
+ egl_connection_t* const cnx = &gEGLImpl;
+ cnx->major = -1;
+ cnx->minor = -1;
+ if (cnx->dso) {
+ EGLDisplay idpy = disp.dpy;
+ if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
+ //ALOGD("initialized dpy=%p, ver=%d.%d, cnx=%p",
+ // idpy, cnx->major, cnx->minor, cnx);
+
+ // display is now initialized
+ disp.state = egl_display_t::INITIALIZED;
+
+ // get the query-strings for this display for each implementation
+ disp.queryString.vendor = cnx->egl.eglQueryString(idpy,
+ EGL_VENDOR);
+ disp.queryString.version = cnx->egl.eglQueryString(idpy,
+ EGL_VERSION);
+ disp.queryString.extensions = cnx->egl.eglQueryString(idpy,
+ EGL_EXTENSIONS);
+ disp.queryString.clientApi = cnx->egl.eglQueryString(idpy,
+ EGL_CLIENT_APIS);
+
+ } else {
+ ALOGW("eglInitialize(%p) failed (%s)", idpy,
+ egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
+ }
}
- }
- // the query strings are per-display
- mVendorString.setTo(sVendorString);
- mVersionString.setTo(sVersionString);
- mClientApiString.setTo(sClientApiString);
-
- mExtensionString.setTo(gBuiltinExtensionString);
- char const* start = gExtensionString;
- char const* end;
- do {
- // find the space separating this extension for the next one
- end = strchr(start, ' ');
- if (end) {
- // length of the extension string
- const size_t len = end - start;
- if (len) {
- // NOTE: we could avoid the copy if we had strnstr.
- const String8 ext(start, len);
- if (findExtension(disp.queryString.extensions, ext.string(),
- len)) {
- mExtensionString.append(start, len+1);
+ // the query strings are per-display
+ mVendorString.setTo(sVendorString);
+ mVersionString.setTo(sVersionString);
+ mClientApiString.setTo(sClientApiString);
+
+ mExtensionString.setTo(gBuiltinExtensionString);
+ char const* start = gExtensionString;
+ char const* end;
+ do {
+ // find the space separating this extension for the next one
+ end = strchr(start, ' ');
+ if (end) {
+ // length of the extension string
+ const size_t len = end - start;
+ if (len) {
+ // NOTE: we could avoid the copy if we had strnstr.
+ const String8 ext(start, len);
+ if (findExtension(disp.queryString.extensions, ext.string(),
+ len)) {
+ mExtensionString.append(start, len+1);
+ }
}
+ // process the next extension string, and skip the space.
+ start = end + 1;
}
- // process the next extension string, and skip the space.
- start = end + 1;
+ } while (end);
+
+ egl_cache_t::get()->initialize(this);
+
+ char value[PROPERTY_VALUE_MAX];
+ property_get("debug.egl.finish", value, "0");
+ if (atoi(value)) {
+ finishOnSwap = true;
}
- } while (end);
- egl_cache_t::get()->initialize(this);
+ property_get("debug.egl.traceGpuCompletion", value, "0");
+ if (atoi(value)) {
+ traceGpuCompletion = true;
+ }
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.egl.finish", value, "0");
- if (atoi(value)) {
- finishOnSwap = true;
- }
+ if (major != NULL)
+ *major = VERSION_MAJOR;
+ if (minor != NULL)
+ *minor = VERSION_MINOR;
- property_get("debug.egl.traceGpuCompletion", value, "0");
- if (atoi(value)) {
- traceGpuCompletion = true;
+ mHibernation.setDisplayValid(true);
}
- refs++;
- if (major != NULL)
- *major = VERSION_MAJOR;
- if (minor != NULL)
- *minor = VERSION_MINOR;
-
- mHibernation.setDisplayValid(true);
+ {
+ Mutex::Autolock _rf(refLock);
+ eglIsInitialized = true;
+ refCond.broadcast();
+ }
return EGL_TRUE;
}
EGLBoolean egl_display_t::terminate() {
- Mutex::Autolock _l(lock);
-
- if (refs == 0) {
- /*
- * From the EGL spec (3.2):
- * "Termination of a display that has already been terminated,
- * (...), is allowed, but the only effect of such a call is
- * to return EGL_TRUE (...)
- */
- return EGL_TRUE;
- }
+ {
+ Mutex::Autolock _rl(refLock);
+ if (refs == 0) {
+ /*
+ * From the EGL spec (3.2):
+ * "Termination of a display that has already been terminated,
+ * (...), is allowed, but the only effect of such a call is
+ * to return EGL_TRUE (...)
+ */
+ return EGL_TRUE;
+ }
- // this is specific to Android, display termination is ref-counted.
- if (refs > 1) {
+ // this is specific to Android, display termination is ref-counted.
refs--;
- return EGL_TRUE;
+ if (refs > 0) {
+ return EGL_TRUE;
+ }
}
EGLBoolean res = EGL_FALSE;
- egl_connection_t* const cnx = &gEGLImpl;
- if (cnx->dso && disp.state == egl_display_t::INITIALIZED) {
- if (cnx->egl.eglTerminate(disp.dpy) == EGL_FALSE) {
- ALOGW("eglTerminate(%p) failed (%s)", disp.dpy,
- egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
+
+ {
+ Mutex::Autolock _l(lock);
+
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && disp.state == egl_display_t::INITIALIZED) {
+ if (cnx->egl.eglTerminate(disp.dpy) == EGL_FALSE) {
+ ALOGW("eglTerminate(%p) failed (%s)", disp.dpy,
+ egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
+ }
+ // REVISIT: it's unclear what to do if eglTerminate() fails
+ disp.state = egl_display_t::TERMINATED;
+ res = EGL_TRUE;
}
- // REVISIT: it's unclear what to do if eglTerminate() fails
- disp.state = egl_display_t::TERMINATED;
- res = EGL_TRUE;
- }
- mHibernation.setDisplayValid(false);
+ mHibernation.setDisplayValid(false);
- // Reset the extension string since it will be regenerated if we get
- // reinitialized.
- mExtensionString.setTo("");
+ // Reset the extension string since it will be regenerated if we get
+ // reinitialized.
+ mExtensionString.setTo("");
- // Mark all objects remaining in the list as terminated, unless
- // there are no reference to them, it which case, we're free to
- // delete them.
- size_t count = objects.size();
- ALOGW_IF(count, "eglTerminate() called w/ %d objects remaining", count);
- for (size_t i=0 ; i<count ; i++) {
- egl_object_t* o = objects.itemAt(i);
- o->destroy();
+ // Mark all objects remaining in the list as terminated, unless
+ // there are no reference to them, it which case, we're free to
+ // delete them.
+ size_t count = objects.size();
+ ALOGW_IF(count, "eglTerminate() called w/ %d objects remaining", count);
+ for (size_t i=0 ; i<count ; i++) {
+ egl_object_t* o = objects.itemAt(i);
+ o->destroy();
+ }
+
+ // this marks all object handles are "terminated"
+ objects.clear();
}
- // this marks all object handles are "terminated"
- objects.clear();
+ {
+ Mutex::Autolock _rl(refLock);
+ eglIsInitialized = false;
+ refCond.broadcast();
+ }
- refs--;
return res;
}
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 0a6e425..2d86295 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -131,7 +131,9 @@ private:
void leave() { return mHibernation.decWakeCount(HibernationMachine::WEAK); }
uint32_t refs;
- mutable Mutex lock;
+ bool eglIsInitialized;
+ mutable Mutex lock, refLock;
+ mutable Condition refCond;
SortedVector<egl_object_t*> objects;
String8 mVendorString;
String8 mVersionString;