From 541de498ec7356c5e4af92500cf2fb8fc707fd50 Mon Sep 17 00:00:00 2001 From: Pablo Ceballos Date: Sat, 9 Apr 2016 15:56:12 -0700 Subject: [PATCH] EGL: Ensure surfaces are disconnected when destroyed When eglDestroySurface is called, remove all references to the surface in all contexts. This ensures that the surface is disconnected immediately. Bug 27455025 Change-Id: I0edaf039d320dc40122657db32abdc418665841a --- opengl/libs/EGL/eglApi.cpp | 1 + opengl/libs/EGL/egl_display.cpp | 25 +++++++++++++++++++++++++ opengl/libs/EGL/egl_display.h | 8 ++++++++ opengl/libs/EGL/egl_object.cpp | 6 ++++++ opengl/libs/EGL/egl_object.h | 5 +++-- 5 files changed, 43 insertions(+), 2 deletions(-) diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index e7703d8f6d..943906ffc2 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -603,6 +603,7 @@ EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface); if (result == EGL_TRUE) { _s.terminate(); + dp->removeSurface(surface); } return result; } diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp index 6a9d7b6e8f..d849693d9a 100644 --- a/opengl/libs/EGL/egl_display.cpp +++ b/opengl/libs/EGL/egl_display.cpp @@ -89,6 +89,31 @@ bool egl_display_t::getObject(egl_object_t* object) const { return false; } +void egl_display_t::addContext(egl_context_t* context) { + Mutex::Autolock _l(lock); + contexts.add(context); +} + +void egl_display_t::removeContext(egl_context_t* context) { + Mutex::Autolock _l(lock); + contexts.remove(context); +} + +void egl_display_t::removeSurface(EGLSurface surface) const { + Mutex::Autolock _l(lock); + for (size_t i = 0; i < contexts.size(); i++) { + egl_context_t* context = contexts[i]; + if (context->read == surface) { + SurfaceRef _r(get_surface(context->read)); + _r.release(); + } + if (context->draw == surface) { + SurfaceRef _d(get_surface(context->draw)); + _d.release(); + } + } +} + EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp) { if (uintptr_t(disp) >= NUM_DISPLAYS) return NULL; diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h index 2d862951c1..0ede705b27 100644 --- a/opengl/libs/EGL/egl_display.h +++ b/opengl/libs/EGL/egl_display.h @@ -68,6 +68,13 @@ public: // add reference to this object. returns true if this is a valid object. bool getObject(egl_object_t* object) const; + // add context to this display's list + void addContext(egl_context_t* context); + // remove context from this display's list + void removeContext(egl_context_t* context); + // search for surface on all contexts and remove the references + void removeSurface(EGLSurface surface) const; + // These notifications allow the display to keep track of how many window // surfaces exist, which it uses to decide whether to hibernate the // underlying EGL implementation. They can be called by any thread without @@ -135,6 +142,7 @@ private: mutable Mutex lock, refLock; mutable Condition refCond; SortedVector objects; + SortedVector contexts; String8 mVendorString; String8 mVersionString; String8 mClientApiString; diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp index 918faa80a5..8859387af7 100644 --- a/opengl/libs/EGL/egl_object.cpp +++ b/opengl/libs/EGL/egl_object.cpp @@ -91,6 +91,12 @@ egl_context_t::egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig confi egl_connection_t const* cnx, int version) : egl_object_t(get_display_nowake(dpy)), dpy(dpy), context(context), config(config), read(0), draw(0), cnx(cnx), version(version) { + get_display_nowake(dpy)->addContext(this); +} + +void egl_context_t::terminate() { + display->removeContext(this); + egl_object_t::terminate(); } void egl_context_t::onLooseCurrent() { diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h index 17a8304231..8268900a41 100644 --- a/opengl/libs/EGL/egl_object.h +++ b/opengl/libs/EGL/egl_object.h @@ -40,11 +40,12 @@ namespace android { class egl_display_t; class egl_object_t { - egl_display_t *display; mutable volatile int32_t count; protected: virtual ~egl_object_t(); + virtual void terminate(); + egl_display_t *display; public: egl_object_t(egl_display_t* display); @@ -55,7 +56,6 @@ public: inline egl_display_t* getDisplay() const { return display; } private: - void terminate(); static bool get(egl_display_t const* display, egl_object_t* object); public: @@ -143,6 +143,7 @@ public: class egl_context_t: public egl_object_t { protected: ~egl_context_t() {} + void terminate() override; public: typedef egl_object_t::LocalRef Ref; -- 2.11.0