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;
}
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index c0449a1..92e1529 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -193,7 +193,7 @@
GLuint mVpWidth;
GLuint mVpHeight;
Description mState;
- GLShadowTexture mShadowTexture;
+ std::unique_ptr<GLShadowTexture> mShadowTexture = nullptr;
mat4 mSrgbToXyz;
mat4 mDisplayP3ToXyz;
@@ -294,7 +294,7 @@
friend class BlurFilter;
friend class GenericProgram;
std::unique_ptr<FlushTracer> mFlushTracer;
- std::unique_ptr<ImageManager> mImageManager = std::make_unique<ImageManager>(this);
+ std::unique_ptr<ImageManager> mImageManager;
};
} // namespace gl
diff --git a/libs/renderengine/gl/GLFramebuffer.cpp b/libs/renderengine/gl/GLFramebuffer.cpp
index 383486b..58d6caa 100644
--- a/libs/renderengine/gl/GLFramebuffer.cpp
+++ b/libs/renderengine/gl/GLFramebuffer.cpp
@@ -38,6 +38,7 @@
}
GLFramebuffer::~GLFramebuffer() {
+ setNativeWindowBuffer(nullptr, false, false);
glDeleteFramebuffers(1, &mFramebufferName);
glDeleteTextures(1, &mTextureName);
}
diff --git a/libs/renderengine/gl/Program.cpp b/libs/renderengine/gl/Program.cpp
index a172c56..26f6166 100644
--- a/libs/renderengine/gl/Program.cpp
+++ b/libs/renderengine/gl/Program.cpp
@@ -82,6 +82,14 @@
}
}
+Program::~Program() {
+ glDetachShader(mProgram, mVertexShader);
+ glDetachShader(mProgram, mFragmentShader);
+ glDeleteShader(mVertexShader);
+ glDeleteShader(mFragmentShader);
+ glDeleteProgram(mProgram);
+}
+
bool Program::isValid() const {
return mInitialized;
}
diff --git a/libs/renderengine/gl/Program.h b/libs/renderengine/gl/Program.h
index 4292645..41f1bf8 100644
--- a/libs/renderengine/gl/Program.h
+++ b/libs/renderengine/gl/Program.h
@@ -54,7 +54,7 @@
};
Program(const ProgramCache::Key& needs, const char* vertex, const char* fragment);
- ~Program() = default;
+ ~Program();
/* whether this object is usable */
bool isValid() const;
diff --git a/libs/renderengine/gl/ProgramCache.h b/libs/renderengine/gl/ProgramCache.h
index 37bb651..535d21c 100644
--- a/libs/renderengine/gl/ProgramCache.h
+++ b/libs/renderengine/gl/ProgramCache.h
@@ -203,6 +203,8 @@
// if none can be found.
void useProgram(const EGLContext context, const Description& description);
+ void purgeCaches() { mCaches.clear(); }
+
private:
// compute a cache Key from a Description
static Key computeKey(const Description& description);