Merge "fix a dead-lock in eglMakeCurrent"

This commit is contained in:
Mathias Agopian 2012-02-03 15:35:45 -08:00 committed by Android (Google) Code Review
commit 2e6ae0138b
2 changed files with 53 additions and 21 deletions

View File

@ -345,42 +345,73 @@ EGLBoolean egl_display_t::terminate() {
void egl_display_t::loseCurrent(egl_context_t * cur_c) void egl_display_t::loseCurrent(egl_context_t * cur_c)
{ {
if (cur_c) { if (cur_c) {
egl_surface_t * cur_r = get_surface(cur_c->read); egl_display_t* display = cur_c->getDisplay();
egl_surface_t * cur_d = get_surface(cur_c->draw); if (display) {
display->loseCurrentImpl(cur_c);
}
}
}
void egl_display_t::loseCurrentImpl(egl_context_t * cur_c)
{
// by construction, these are either 0 or valid (possibly terminated) // by construction, these are either 0 or valid (possibly terminated)
// it should be impossible for these to be invalid // it should be impossible for these to be invalid
ContextRef _cur_c(cur_c); ContextRef _cur_c(cur_c);
SurfaceRef _cur_r(cur_r); SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : NULL);
SurfaceRef _cur_d(cur_d); SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL);
{ // scope for the lock
Mutex::Autolock _l(lock);
cur_c->onLooseCurrent(); cur_c->onLooseCurrent();
}
// This cannot be called with the lock held because it might end-up
// calling back into EGL (in particular when a surface is destroyed
// it calls ANativeWindow::disconnect
_cur_c.release(); _cur_c.release();
_cur_r.release(); _cur_r.release();
_cur_d.release(); _cur_d.release();
} }
}
EGLBoolean egl_display_t::makeCurrent(egl_context_t* c, egl_context_t* cur_c, EGLBoolean egl_display_t::makeCurrent(egl_context_t* c, egl_context_t* cur_c,
EGLSurface draw, EGLSurface read, EGLContext ctx, EGLSurface draw, EGLSurface read, EGLContext ctx,
EGLSurface impl_draw, EGLSurface impl_read, EGLContext impl_ctx) EGLSurface impl_draw, EGLSurface impl_read, EGLContext impl_ctx)
{ {
Mutex::Autolock _l(lock);
EGLBoolean result; EGLBoolean result;
// by construction, these are either 0 or valid (possibly terminated)
// it should be impossible for these to be invalid
ContextRef _cur_c(cur_c);
SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : NULL);
SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL);
{ // scope for the lock
Mutex::Autolock _l(lock);
if (c) { if (c) {
result = c->cnx->egl.eglMakeCurrent( result = c->cnx->egl.eglMakeCurrent(
disp[c->impl].dpy, impl_draw, impl_read, impl_ctx); disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
if (result == EGL_TRUE) {
c->onMakeCurrent(draw, read);
}
} else { } else {
result = cur_c->cnx->egl.eglMakeCurrent( result = cur_c->cnx->egl.eglMakeCurrent(
disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx); disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
}
if (result == EGL_TRUE) { if (result == EGL_TRUE) {
loseCurrent(cur_c); cur_c->onLooseCurrent();
if (c) {
c->onMakeCurrent(draw, read);
} }
} }
}
if (result == EGL_TRUE) {
// This cannot be called with the lock held because it might end-up
// calling back into EGL (in particular when a surface is destroyed
// it calls ANativeWindow::disconnect
_cur_c.release();
_cur_r.release();
_cur_d.release();
}
return result; return result;
} }

View File

@ -64,6 +64,7 @@ struct egl_config_t {
class EGLAPI egl_display_t { // marked as EGLAPI for testing purposes class EGLAPI egl_display_t { // marked as EGLAPI for testing purposes
static egl_display_t sDisplay[NUM_DISPLAYS]; static egl_display_t sDisplay[NUM_DISPLAYS];
EGLDisplay getDisplay(EGLNativeDisplayType display); EGLDisplay getDisplay(EGLNativeDisplayType display);
void loseCurrentImpl(egl_context_t * cur_c);
public: public:
enum { enum {