Special case EGL_BAD_SURFACE

 Bug: 17516789

Change-Id: I3dcb10360c2aef6326f7dbbff6815866d4c143b6
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 5e6796c..832d170 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -91,7 +91,9 @@
 }
 
 void CanvasContext::swapBuffers() {
-    mEglManager.swapBuffers(mEglSurface);
+    if (CC_UNLIKELY(!mEglManager.swapBuffers(mEglSurface))) {
+        setSurface(NULL);
+    }
     mHaveNewSurface = false;
 }
 
@@ -102,8 +104,8 @@
 }
 
 bool CanvasContext::initialize(ANativeWindow* window) {
-    if (mCanvas) return false;
     setSurface(window);
+    if (mCanvas) return false;
     mCanvas = new OpenGLRenderer(mRenderThread.renderState());
     mCanvas->initProperties();
     return true;
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index e030cdb..a87834e 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -254,11 +254,23 @@
     eglBeginFrame(mEglDisplay, surface);
 }
 
-void EglManager::swapBuffers(EGLSurface surface) {
+bool EglManager::swapBuffers(EGLSurface surface) {
     eglSwapBuffers(mEglDisplay, surface);
     EGLint err = eglGetError();
-    LOG_ALWAYS_FATAL_IF(err != EGL_SUCCESS,
-            "Encountered EGL error %d %s during rendering", err, egl_error_str(err));
+    if (CC_LIKELY(err == EGL_SUCCESS)) {
+        return true;
+    }
+    if (err == EGL_BAD_SURFACE) {
+        // For some reason our surface was destroyed out from under us
+        // This really shouldn't happen, but if it does we can recover easily
+        // by just not trying to use the surface anymore
+        ALOGW("swapBuffers encountered EGL_BAD_SURFACE on %p, halting rendering...", surface);
+        return false;
+    }
+    LOG_ALWAYS_FATAL("Encountered EGL error %d %s during rendering",
+            err, egl_error_str(err));
+    // Impossible to hit this, but the compiler doesn't know that
+    return false;
 }
 
 bool EglManager::enableDirtyRegions(EGLSurface surface) {
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index a844cfc..71213fb 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -47,7 +47,7 @@
     // Returns true if the current surface changed, false if it was already current
     bool makeCurrent(EGLSurface surface);
     void beginFrame(EGLSurface surface, EGLint* width, EGLint* height);
-    void swapBuffers(EGLSurface surface);
+    bool swapBuffers(EGLSurface surface);
 
     bool enableDirtyRegions(EGLSurface surface);