OSDN Git Service

egl: recover from failed eglMakeCurrent
authorMike Stroyan <stroyan@google.com>
Mon, 8 May 2017 16:47:24 +0000 (10:47 -0600)
committerMike Stroyan <stroyan@google.com>
Mon, 8 May 2017 17:43:28 +0000 (11:43 -0600)
Some drivers don't actually restore current context when
eglMakeCurrent fails.  Restore the current context directly.

Bug: 37244059
Change-Id: I857da78078dd212b523d690415cf525ecd463961
Fixes: 37244059
Test: android.server.cts.ActivityManagerDisplayTests

opengl/libs/EGL/eglApi.cpp

index 9de15d0..10f4e66 100644 (file)
@@ -829,6 +829,42 @@ EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
             egl_tls_t::setContext(EGL_NO_CONTEXT);
         }
     } else {
+        // Force return to current context for drivers that cannot handle errors
+        EGLBoolean restore_result = EGL_FALSE;
+
+        // get a reference to the old current objects
+        ContextRef _c2(dp.get(), cur_c);
+        SurfaceRef _d2(dp.get(), cur_c->draw);
+        SurfaceRef _r2(dp.get(), cur_c->read);
+
+        if (cur_c == NULL) {
+            restore_result = dp->makeCurrent(c, cur_c,
+                    EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT,
+                    EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+        } else {
+            c = cur_c;
+            impl_ctx = c->context;
+            impl_draw = EGL_NO_SURFACE;
+            if (cur_c->draw != EGL_NO_SURFACE) {
+                d = get_surface(cur_c->draw);
+                impl_draw = d->surface;
+            }
+            impl_read = EGL_NO_SURFACE;
+            if (cur_c->read != EGL_NO_SURFACE) {
+                r = get_surface(cur_c->read);
+                impl_read = r->surface;
+            }
+            restore_result = dp->makeCurrent(c, cur_c,
+                    cur_c->draw, cur_c->read, cur_c->context,
+                    impl_draw, impl_read, impl_ctx);
+        }
+        if (restore_result == EGL_TRUE) {
+            _c2.acquire();
+            _r2.acquire();
+            _d2.acquire();
+        } else {
+            ALOGE("Could not restore original EGL context");
+        }
         // this will ALOGE the error
         egl_connection_t* const cnx = &gEGLImpl;
         result = setError(cnx->egl.eglGetError(), (EGLBoolean)EGL_FALSE);