Tidy up GL resources

Currently it's not safe to destroy and recreate RenderEngine because
certain GL resources are persisted in GLESRenderEngine, which is
imposing limitations on testing. This patch adds some cleanup steps,
including:
* Supporting destruction of glPrograms once they're unused.
* Purging the ProgramCache of shaders when RenderEngine is destroyed
* Tidy up Framebuffer destruction when backed by an EGLImage
* Make sure shadow resources are destroyed prior to display termination
* Disable vertex attribute used for positioning layers.
* Check that EGL objects are valid before display termination.

Bug: 173416417
Test: librenderengine_test, and observe logcat
Change-Id: Id5d858d21a400ef170788d917f0bc0ac5e318bdc
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 6b6b0c0..279e648 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -15,6 +15,7 @@
  */
 
 //#define LOG_NDEBUG 0
+#include "EGL/egl.h"
 #undef LOG_TAG
 #define LOG_TAG "RenderEngine"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
@@ -446,19 +447,34 @@
                                           mPlaceholderBuffer, attributes);
     ALOGE_IF(mPlaceholderImage == EGL_NO_IMAGE_KHR, "Failed to create placeholder image: %#x",
              eglGetError());
+
+    mShadowTexture = std::make_unique<GLShadowTexture>();
 }
 
 GLESRenderEngine::~GLESRenderEngine() {
     // Destroy the image manager first.
     mImageManager = nullptr;
+    mShadowTexture = nullptr;
     cleanFramebufferCache();
+    ProgramCache::getInstance().purgeCaches();
     std::lock_guard<std::mutex> lock(mRenderingMutex);
+    glDisableVertexAttribArray(Program::position);
     unbindFrameBuffer(mDrawingBuffer.get());
     mDrawingBuffer = nullptr;
     eglDestroyImageKHR(mEGLDisplay, mPlaceholderImage);
     mImageCache.clear();
-    eglDestroyContext(mEGLDisplay, mEGLContext);
-    eglDestroyContext(mEGLDisplay, mProtectedEGLContext);
+    if (mStubSurface != EGL_NO_SURFACE) {
+        eglDestroySurface(mEGLDisplay, mStubSurface);
+    }
+    if (mProtectedStubSurface != EGL_NO_SURFACE) {
+        eglDestroySurface(mEGLDisplay, mProtectedStubSurface);
+    }
+    if (mEGLContext != EGL_NO_CONTEXT) {
+        eglDestroyContext(mEGLDisplay, mEGLContext);
+    }
+    if (mProtectedEGLContext != EGL_NO_CONTEXT) {
+        eglDestroyContext(mEGLDisplay, mProtectedEGLContext);
+    }
     eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
     eglTerminate(mEGLDisplay);
     eglReleaseThread();
@@ -1803,7 +1819,7 @@
 
     mState.cornerRadius = 0.0f;
     mState.drawShadows = true;
-    setupLayerTexturing(mShadowTexture.getTexture());
+    setupLayerTexturing(mShadowTexture->getTexture());
     drawMesh(mesh);
     mState.drawShadows = false;
 }