diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 77a6e525c49a2..8e5db362201d3 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -679,7 +679,7 @@ static void android_view_GLES20Canvas_resetDisplayListRenderer(JNIEnv* env, static void android_view_GLES20Canvas_destroyDisplayList(JNIEnv* env, jobject clazz, DisplayList* displayList) { - delete displayList; + DisplayList::destroyDisplayListDeferred(displayList); } static bool android_view_GLES20Canvas_drawDisplayList(JNIEnv* env, diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index 0ef8469033431..123695ab4a858 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -20,6 +20,7 @@ #include #include "Caches.h" +#include "DisplayListRenderer.h" #include "Properties.h" #include "LayerRenderer.h" @@ -199,6 +200,13 @@ void Caches::clearGarbage() { LayerRenderer::destroyLayer(layer); } mLayerGarbage.clear(); + + count = mDisplayListGarbage.size(); + for (size_t i = 0; i < count; i++) { + DisplayList* displayList = mDisplayListGarbage.itemAt(i); + delete displayList; + } + mDisplayListGarbage.clear(); } void Caches::deleteLayerDeferred(Layer* layer) { @@ -206,6 +214,11 @@ void Caches::deleteLayerDeferred(Layer* layer) { mLayerGarbage.push(layer); } +void Caches::deleteDisplayListDeferred(DisplayList* displayList) { + Mutex::Autolock _l(mGarbageLock); + mDisplayListGarbage.push(displayList); +} + void Caches::flush(FlushMode mode) { FLUSH_LOGD("Flushing caches (mode %d)", mode); diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h index f8c7bccad628f..65ff9ad3423c2 100644 --- a/libs/hwui/Caches.h +++ b/libs/hwui/Caches.h @@ -90,6 +90,8 @@ struct CacheLogger { // Caches /////////////////////////////////////////////////////////////////////////////// +class DisplayList; + class ANDROID_API Caches: public Singleton { Caches(); @@ -141,6 +143,11 @@ public: */ void deleteLayerDeferred(Layer* layer); + /* + * Can be used to delete a display list from a non EGL thread. + */ + void deleteDisplayListDeferred(DisplayList* layer); + /** * Binds the VBO used to render simple textured quads. */ @@ -269,6 +276,7 @@ private: mutable Mutex mGarbageLock; Vector mLayerGarbage; + Vector mDisplayListGarbage; DebugLevel mDebugLevel; bool mInitialized; diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index babfd04e0d12f..d9b0e5a9096bb 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -101,6 +101,13 @@ DisplayList::~DisplayList() { clearResources(); } +void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) { + if (displayList) { + DISPLAY_LIST_LOGD("Deferring display list destruction"); + Caches::getInstance().deleteDisplayListDeferred(displayList); + } +} + void DisplayList::clearResources() { sk_free((void*) mReader.base()); diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 96b87cc78b4e3..02f8438514e9c 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -119,16 +119,16 @@ public: static const char* OP_NAMES[]; - void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false); - ANDROID_API size_t getSize(); + ANDROID_API static void destroyDisplayListDeferred(DisplayList* displayList); + ANDROID_API static void outputLogBuffer(int fd); + + void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false); bool replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level = 0); void output(OpenGLRenderer& renderer, uint32_t level = 0); - ANDROID_API static void outputLogBuffer(int fd); - void setRenderable(bool renderable) { mIsRenderable = renderable; }