1717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn/* 2717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * Copyright (C) 2010 The Android Open Source Project 3717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * 4717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); 5717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * you may not use this file except in compliance with the License. 6717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * You may obtain a copy of the License at 7717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * 8717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0 9717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * 10717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * Unless required by applicable law or agreed to in writing, software 11717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, 12717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * See the License for the specific language governing permissions and 14717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * limitations under the License. 15717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn */ 16717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 17717a25dc2a411edb548859cd6870363346c71b01Dianne Hackbornpackage android.opengl; 18717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 19717a25dc2a411edb548859cd6870363346c71b01Dianne Hackbornimport static javax.microedition.khronos.egl.EGL10.EGL_DEFAULT_DISPLAY; 20717a25dc2a411edb548859cd6870363346c71b01Dianne Hackbornimport static javax.microedition.khronos.egl.EGL10.EGL_NO_DISPLAY; 21717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 22717a25dc2a411edb548859cd6870363346c71b01Dianne Hackbornimport java.util.ArrayList; 23717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 24717a25dc2a411edb548859cd6870363346c71b01Dianne Hackbornimport javax.microedition.khronos.egl.EGL10; 25717a25dc2a411edb548859cd6870363346c71b01Dianne Hackbornimport javax.microedition.khronos.egl.EGLContext; 26717a25dc2a411edb548859cd6870363346c71b01Dianne Hackbornimport javax.microedition.khronos.egl.EGLDisplay; 27717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 28717a25dc2a411edb548859cd6870363346c71b01Dianne Hackbornimport android.os.Looper; 29717a25dc2a411edb548859cd6870363346c71b01Dianne Hackbornimport android.util.Log; 30717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 31717a25dc2a411edb548859cd6870363346c71b01Dianne Hackbornimport com.google.android.gles_jni.EGLImpl; 32717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 33717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn/** 34717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * The per-process memory overhead of hardware accelerated graphics can 35717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * be quite large on some devices. For small memory devices, being able to 36717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * terminate all EGL contexts so that this graphics driver memory can be 37717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * reclaimed can significant improve the overall behavior of the device. This 38717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * class helps app developers participate in releasing their EGL context 39717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * when appropriate and possible. 40717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * 41717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * <p>To use, simple instantiate this class with the EGLContext you create. 42717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * When you have done this, if the device is getting low on memory and all 43717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * of the currently created EGL contexts in the process are being managed 44717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * through this class, then they will all be asked to terminate through the 45717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * call to {@link #onTerminate}. 46dccf73a50cb2a219182e141bac1d9da82fdaf4d7Romain Guy * 47dccf73a50cb2a219182e141bac1d9da82fdaf4d7Romain Guy * @hide 48717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn */ 49717a25dc2a411edb548859cd6870363346c71b01Dianne Hackbornpublic abstract class ManagedEGLContext { 50717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn static final String TAG = "ManagedEGLContext"; 51717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 5231f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy static final ArrayList<ManagedEGLContext> sActive = new ArrayList<ManagedEGLContext>(); 53717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 54717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn final EGLContext mContext; 55717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 56717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn /** 57717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * Instantiate to manage the given EGLContext. 58717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn */ 59717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn public ManagedEGLContext(EGLContext context) { 60717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn mContext = context; 61717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn synchronized (sActive) { 62717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn sActive.add(this); 63717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 64717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 65717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 66717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn /** 67717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * Retrieve the EGLContext being managed by the class. 68717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn */ 69717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn public EGLContext getContext() { 70717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn return mContext; 71717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 72717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 73717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn /** 74717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * Force-terminate the ManagedEGLContext. This will cause 75717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * {@link #onTerminate(EGLContext)} to be called. You <em>must</em> 76717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * call this when destroying the EGLContext, so that the framework 77717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * knows to stop managing it. 78717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn */ 79717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn public void terminate() { 80717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn execTerminate(); 81717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 82717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 83717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn void execTerminate() { 84717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn onTerminate(mContext); 85717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 86717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 87717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn /** 88717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * Override this method to destroy the EGLContext when appropriate. 89717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * <em>Note that this method is always called on the main thread 90717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * of the process.</em> If your EGLContext was created on a different 91717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * thread, you will need to implement this method to hand off the work 92717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn * of destroying the context to that thread. 93717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn */ 94717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn public abstract void onTerminate(EGLContext context); 95717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 96717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn /** @hide */ 97717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn public static boolean doTerminate() { 98717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn ArrayList<ManagedEGLContext> active; 99717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 100717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn if (Looper.getMainLooper() != Looper.myLooper()) { 101717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn throw new IllegalStateException("Called on wrong thread"); 102717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 103717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 104717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn synchronized (sActive) { 105717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn // If there are no active managed contexts, we will not even 106717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn // try to terminate. 107717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn if (sActive.size() <= 0) { 108717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn return false; 109717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 110717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 111717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn // Need to check how many EGL contexts are actually running, 112717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn // to compare with how many we are managing. 113717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn EGL10 egl = (EGL10) EGLContext.getEGL(); 114717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn EGLDisplay display = egl.eglGetDisplay(EGL_DEFAULT_DISPLAY); 115717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 116717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn if (display == EGL_NO_DISPLAY) { 117717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn Log.w(TAG, "doTerminate failed: no display"); 118717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn return false; 119717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 120717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 121717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn if (EGLImpl.getInitCount(display) != sActive.size()) { 122717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn Log.w(TAG, "doTerminate failed: EGL count is " + EGLImpl.getInitCount(display) 123717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn + " but managed count is " + sActive.size()); 124717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn return false; 125717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 126717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 127717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn active = new ArrayList<ManagedEGLContext>(sActive); 128717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn sActive.clear(); 129717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 130717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 13131f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy for (int i = 0; i < active.size(); i++) { 132717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn active.get(i).execTerminate(); 133717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 134717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 135717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn return true; 136717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 137717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn} 138