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 ;
@@ -343,6 +344,15 @@ static void trimMemory(int level) {
343344 Gl20Renderer .trimMemory (level );
344345 }
345346
347+ /**
348+ * Invoke this method when the system needs to clean up all resources
349+ * associated with hardware rendering.
350+ */
351+ static void terminate () {
352+ Log .d (LOG_TAG , "Terminating hardware rendering" );
353+ Gl20Renderer .terminate ();
354+ }
355+
346356 /**
347357 * Indicates whether hardware acceleration is currently enabled.
348358 *
@@ -651,6 +661,8 @@ GL createEglSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException
651661 throw new Surface .OutOfResourcesException ("eglMakeCurrent failed "
652662 + GLUtils .getEGLErrorString (sEgl .eglGetError ()));
653663 }
664+
665+ initCaches ();
654666
655667 // If mDirtyRegions is set, this means we have an EGL configuration
656668 // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set
@@ -671,6 +683,8 @@ GL createEglSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException
671683 return mEglContext .getGL ();
672684 }
673685
686+ abstract void initCaches ();
687+
674688 EGLContext createContext (EGL10 egl , EGLDisplay eglDisplay , EGLConfig eglConfig ) {
675689 int [] attribs = { EGL_CONTEXT_CLIENT_VERSION , mGlVersion , EGL_NONE };
676690
@@ -914,6 +928,11 @@ int[] getConfig(boolean dirtyRegions) {
914928 EGL_NONE
915929 };
916930 }
931+
932+ @ Override
933+ void initCaches () {
934+ GLES20Canvas .initCaches ();
935+ }
917936
918937 @ Override
919938 boolean canDraw () {
@@ -1006,16 +1025,7 @@ static void trimMemory(int level) {
10061025 if (eglContext == null ) {
10071026 return ;
10081027 } else {
1009- synchronized (sPbufferLock ) {
1010- // Create a temporary 1x1 pbuffer so we have a context
1011- // to clear our OpenGL objects
1012- if (sPbuffer == null ) {
1013- sPbuffer = sEgl .eglCreatePbufferSurface (sEglDisplay , sEglConfig , new int [] {
1014- EGL_WIDTH , 1 , EGL_HEIGHT , 1 , EGL_NONE
1015- });
1016- }
1017- }
1018- sEgl .eglMakeCurrent (sEglDisplay , sPbuffer , sPbuffer , eglContext );
1028+ usePbufferSurface (eglContext );
10191029 }
10201030
10211031 switch (level ) {
@@ -1029,5 +1039,46 @@ static void trimMemory(int level) {
10291039 break ;
10301040 }
10311041 }
1042+
1043+ private static void usePbufferSurface (EGLContext eglContext ) {
1044+ synchronized (sPbufferLock ) {
1045+ // Create a temporary 1x1 pbuffer so we have a context
1046+ // to clear our OpenGL objects
1047+ if (sPbuffer == null ) {
1048+ sPbuffer = sEgl .eglCreatePbufferSurface (sEglDisplay , sEglConfig , new int [] {
1049+ EGL_WIDTH , 1 , EGL_HEIGHT , 1 , EGL_NONE
1050+ });
1051+ }
1052+ }
1053+ sEgl .eglMakeCurrent (sEglDisplay , sPbuffer , sPbuffer , eglContext );
1054+ }
1055+
1056+ static void terminate () {
1057+ synchronized (sEglLock ) {
1058+ if (sEgl == null ) return ;
1059+
1060+ if (EGLImpl .getInitCount (sEglDisplay ) == 1 ) {
1061+ EGLContext eglContext = sEglContextStorage .get ();
1062+ if (eglContext == null ) return ;
1063+
1064+ usePbufferSurface (eglContext );
1065+ GLES20Canvas .terminateCaches ();
1066+
1067+ sEgl .eglDestroyContext (sEglDisplay , eglContext );
1068+ sEglContextStorage .remove ();
1069+
1070+ sEgl .eglDestroySurface (sEglDisplay , sPbuffer );
1071+ sEgl .eglMakeCurrent (sEglDisplay , EGL_NO_SURFACE , EGL_NO_SURFACE , EGL_NO_CONTEXT );
1072+
1073+ sEgl .eglReleaseThread ();
1074+ sEgl .eglTerminate (sEglDisplay );
1075+
1076+ sEgl = null ;
1077+ sEglDisplay = null ;
1078+ sEglConfig = null ;
1079+ sPbuffer = null ;
1080+ }
1081+ }
1082+ }
10321083 }
10331084}
0 commit comments