2525import android .os .SystemClock ;
2626import android .os .SystemProperties ;
2727import android .util .Log ;
28+ import com .google .android .gles_jni .EGLImpl ;
2829
2930import javax .microedition .khronos .egl .EGL10 ;
3031import javax .microedition .khronos .egl .EGL11 ;
@@ -324,6 +325,15 @@ static void trimMemory(int level) {
324325 Gl20Renderer .trimMemory (level );
325326 }
326327
328+ /**
329+ * Invoke this method when the system needs to clean up all resources
330+ * associated with hardware rendering.
331+ */
332+ static void terminate () {
333+ Log .d (LOG_TAG , "Terminating hardware rendering" );
334+ Gl20Renderer .terminate ();
335+ }
336+
327337 /**
328338 * Indicates whether hardware acceleration is currently enabled.
329339 *
@@ -632,6 +642,8 @@ GL createEglSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException
632642 throw new Surface .OutOfResourcesException ("eglMakeCurrent failed "
633643 + GLUtils .getEGLErrorString (sEgl .eglGetError ()));
634644 }
645+
646+ initCaches ();
635647
636648 // If mDirtyRegions is set, this means we have an EGL configuration
637649 // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set
@@ -652,6 +664,8 @@ GL createEglSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException
652664 return mEglContext .getGL ();
653665 }
654666
667+ abstract void initCaches ();
668+
655669 EGLContext createContext (EGL10 egl , EGLDisplay eglDisplay , EGLConfig eglConfig ) {
656670 int [] attribs = { EGL_CONTEXT_CLIENT_VERSION , mGlVersion , EGL_NONE };
657671
@@ -895,6 +909,11 @@ int[] getConfig(boolean dirtyRegions) {
895909 EGL_NONE
896910 };
897911 }
912+
913+ @ Override
914+ void initCaches () {
915+ GLES20Canvas .initCaches ();
916+ }
898917
899918 @ Override
900919 boolean canDraw () {
@@ -987,16 +1006,7 @@ static void trimMemory(int level) {
9871006 if (eglContext == null ) {
9881007 return ;
9891008 } else {
990- synchronized (sPbufferLock ) {
991- // Create a temporary 1x1 pbuffer so we have a context
992- // to clear our OpenGL objects
993- if (sPbuffer == null ) {
994- sPbuffer = sEgl .eglCreatePbufferSurface (sEglDisplay , sEglConfig , new int [] {
995- EGL_WIDTH , 1 , EGL_HEIGHT , 1 , EGL_NONE
996- });
997- }
998- }
999- sEgl .eglMakeCurrent (sEglDisplay , sPbuffer , sPbuffer , eglContext );
1009+ usePbufferSurface (eglContext );
10001010 }
10011011
10021012 switch (level ) {
@@ -1010,5 +1020,46 @@ static void trimMemory(int level) {
10101020 break ;
10111021 }
10121022 }
1023+
1024+ private static void usePbufferSurface (EGLContext eglContext ) {
1025+ synchronized (sPbufferLock ) {
1026+ // Create a temporary 1x1 pbuffer so we have a context
1027+ // to clear our OpenGL objects
1028+ if (sPbuffer == null ) {
1029+ sPbuffer = sEgl .eglCreatePbufferSurface (sEglDisplay , sEglConfig , new int [] {
1030+ EGL_WIDTH , 1 , EGL_HEIGHT , 1 , EGL_NONE
1031+ });
1032+ }
1033+ }
1034+ sEgl .eglMakeCurrent (sEglDisplay , sPbuffer , sPbuffer , eglContext );
1035+ }
1036+
1037+ static void terminate () {
1038+ synchronized (sEglLock ) {
1039+ if (sEgl == null ) return ;
1040+
1041+ if (EGLImpl .getInitCount (sEglDisplay ) == 1 ) {
1042+ EGLContext eglContext = sEglContextStorage .get ();
1043+ if (eglContext == null ) return ;
1044+
1045+ usePbufferSurface (eglContext );
1046+ GLES20Canvas .terminateCaches ();
1047+
1048+ sEgl .eglDestroyContext (sEglDisplay , eglContext );
1049+ sEglContextStorage .remove ();
1050+
1051+ sEgl .eglDestroySurface (sEglDisplay , sPbuffer );
1052+ sEgl .eglMakeCurrent (sEglDisplay , EGL_NO_SURFACE , EGL_NO_SURFACE , EGL_NO_CONTEXT );
1053+
1054+ sEgl .eglReleaseThread ();
1055+ sEgl .eglTerminate (sEglDisplay );
1056+
1057+ sEgl = null ;
1058+ sEglDisplay = null ;
1059+ sEglConfig = null ;
1060+ sPbuffer = null ;
1061+ }
1062+ }
1063+ }
10131064 }
10141065}
0 commit comments