Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit acfdf0ea authored by Android Build Merger (Role)'s avatar Android Build Merger (Role) Committed by Android (Google) Code Review
Browse files

Merge "Merge \"update GlSurfaceView:onPause/Resume docs\" into nyc-mr1-dev am:...

Merge "Merge \"update GlSurfaceView:onPause/Resume docs\" into nyc-mr1-dev am: ee557b2b" into nyc-mr1-dev-plus-aosp
parents 7b64f668 3d6831ef
Loading
Loading
Loading
Loading
+31 −131
Original line number Original line Diff line number Diff line
@@ -16,6 +16,13 @@


package android.opengl;
package android.opengl;


import android.content.Context;
import android.os.Trace;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.io.Writer;
import java.io.Writer;
import java.lang.ref.WeakReference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.ArrayList;
@@ -29,15 +36,6 @@ import javax.microedition.khronos.egl.EGLSurface;
import javax.microedition.khronos.opengles.GL;
import javax.microedition.khronos.opengles.GL;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL10;


import android.content.Context;
import android.content.pm.ConfigurationInfo;
import android.os.SystemProperties;
import android.os.Trace;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
/**
 * An implementation of SurfaceView that uses the dedicated surface for
 * An implementation of SurfaceView that uses the dedicated surface for
 * displaying OpenGL rendering.
 * displaying OpenGL rendering.
@@ -119,9 +117,9 @@ import android.view.SurfaceView;
 * {@link #setRenderMode}. The default is continuous rendering.
 * {@link #setRenderMode}. The default is continuous rendering.
 * <p>
 * <p>
 * <h3>Activity Life-cycle</h3>
 * <h3>Activity Life-cycle</h3>
 * A GLSurfaceView must be notified when the activity is paused and resumed. GLSurfaceView clients
 * A GLSurfaceView must be notified when to pause and resume rendering. GLSurfaceView clients
 * are required to call {@link #onPause()} when the activity pauses and
 * are required to call {@link #onPause()} when the activity stops and
 * {@link #onResume()} when the activity resumes. These calls allow GLSurfaceView to
 * {@link #onResume()} when the activity starts. These calls allow GLSurfaceView to
 * pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate
 * pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate
 * the OpenGL display.
 * the OpenGL display.
 * <p>
 * <p>
@@ -294,10 +292,12 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
     * resumed.
     * resumed.
     * <p>
     * <p>
     * If set to true, then the EGL context may be preserved when the GLSurfaceView is paused.
     * If set to true, then the EGL context may be preserved when the GLSurfaceView is paused.
     * Whether the EGL context is actually preserved or not depends upon whether the
     * <p>
     * Android device that the program is running on can support an arbitrary number of EGL
     * Prior to API level 11, whether the EGL context is actually preserved or not
     * contexts or not. Devices that can only support a limited number of EGL contexts must
     * depends upon whether the Android device can support an arbitrary number of
     * release the  EGL context in order to allow multiple applications to share the GPU.
     * EGL contexts or not. Devices that can only support a limited number of EGL
     * contexts must release the EGL context in order to allow multiple applications
     * to share the GPU.
     * <p>
     * <p>
     * If set to false, the EGL context will be released when the GLSurfaceView is paused,
     * If set to false, the EGL context will be released when the GLSurfaceView is paused,
     * and recreated when the GLSurfaceView is resumed.
     * and recreated when the GLSurfaceView is resumed.
@@ -554,9 +554,13 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback




    /**
    /**
     * Inform the view that the activity is paused. The owner of this view must
     * Pause the rendering thread, optionally tearing down the EGL context
     * call this method when the activity is paused. Calling this method will
     * depending upon the value of {@link #setPreserveEGLContextOnPause(boolean)}.
     * pause the rendering thread.
     *
     * This method should be called when it is no longer desirable for the
     * GLSurfaceView to continue rendering, such as in response to
     * {@link android.app.Activity#onStop Activity.onStop}.
     *
     * Must not be called before a renderer has been set.
     * Must not be called before a renderer has been set.
     */
     */
    public void onPause() {
    public void onPause() {
@@ -564,10 +568,12 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
    }
    }


    /**
    /**
     * Inform the view that the activity is resumed. The owner of this view must
     * Resumes the rendering thread, re-creating the OpenGL context if necessary. It
     * call this method when the activity is resumed. Calling this method will
     * is the counterpart to {@link #onPause()}.
     * recreate the OpenGL display and resume the rendering
     *
     * thread.
     * This method should typically be called in
     * {@link android.app.Activity#onStart Activity.onStart}.
     *
     * Must not be called before a renderer has been set.
     * Must not be called before a renderer has been set.
     */
     */
    public void onResume() {
    public void onResume() {
@@ -1354,7 +1360,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
                                GLSurfaceView view = mGLSurfaceViewWeakRef.get();
                                GLSurfaceView view = mGLSurfaceViewWeakRef.get();
                                boolean preserveEglContextOnPause = view == null ?
                                boolean preserveEglContextOnPause = view == null ?
                                        false : view.mPreserveEGLContextOnPause;
                                        false : view.mPreserveEGLContextOnPause;
                                if (!preserveEglContextOnPause || sGLThreadManager.shouldReleaseEGLContextWhenPausing()) {
                                if (!preserveEglContextOnPause) {
                                    stopEglContextLocked();
                                    stopEglContextLocked();
                                    if (LOG_SURFACE) {
                                    if (LOG_SURFACE) {
                                        Log.i("GLThread", "releasing EGL context because paused tid=" + getId());
                                        Log.i("GLThread", "releasing EGL context because paused tid=" + getId());
@@ -1362,16 +1368,6 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
                                }
                                }
                            }
                            }


                            // When pausing, optionally terminate EGL:
                            if (pausing) {
                                if (sGLThreadManager.shouldTerminateEGLWhenPausing()) {
                                    mEglHelper.finish();
                                    if (LOG_SURFACE) {
                                        Log.i("GLThread", "terminating EGL because paused tid=" + getId());
                                    }
                                }
                            }

                            // Have we lost the SurfaceView surface?
                            // Have we lost the SurfaceView surface?
                            if ((! mHasSurface) && (! mWaitingForSurface)) {
                            if ((! mHasSurface) && (! mWaitingForSurface)) {
                                if (LOG_SURFACE) {
                                if (LOG_SURFACE) {
@@ -1411,7 +1407,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
                                if (! mHaveEglContext) {
                                if (! mHaveEglContext) {
                                    if (askedToReleaseEglContext) {
                                    if (askedToReleaseEglContext) {
                                        askedToReleaseEglContext = false;
                                        askedToReleaseEglContext = false;
                                    } else if (sGLThreadManager.tryAcquireEglContextLocked(this)) {
                                    } else {
                                        try {
                                        try {
                                            mEglHelper.start();
                                            mEglHelper.start();
                                        } catch (RuntimeException t) {
                                        } catch (RuntimeException t) {
@@ -1506,7 +1502,6 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
                    if (createGlInterface) {
                    if (createGlInterface) {
                        gl = (GL10) mEglHelper.createGL();
                        gl = (GL10) mEglHelper.createGL();


                        sGLThreadManager.checkGLDriver(gl);
                        createGlInterface = false;
                        createGlInterface = false;
                    }
                    }


@@ -1888,111 +1883,16 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
                Log.i("GLThread", "exiting tid=" +  thread.getId());
                Log.i("GLThread", "exiting tid=" +  thread.getId());
            }
            }
            thread.mExited = true;
            thread.mExited = true;
            if (mEglOwner == thread) {
                mEglOwner = null;
            }
            notifyAll();
            notifyAll();
        }
        }


        /*
         * Tries once to acquire the right to use an EGL
         * context. Does not block. Requires that we are already
         * in the sGLThreadManager monitor when this is called.
         *
         * @return true if the right to use an EGL context was acquired.
         */
        public boolean tryAcquireEglContextLocked(GLThread thread) {
            if (mEglOwner == thread || mEglOwner == null) {
                mEglOwner = thread;
                notifyAll();
                return true;
            }
            checkGLESVersion();
            if (mMultipleGLESContextsAllowed) {
                return true;
            }
            // Notify the owning thread that it should release the context.
            // TODO: implement a fairness policy. Currently
            // if the owning thread is drawing continuously it will just
            // reacquire the EGL context.
            if (mEglOwner != null) {
                mEglOwner.requestReleaseEglContextLocked();
            }
            return false;
        }

        /*
        /*
         * Releases the EGL context. Requires that we are already in the
         * Releases the EGL context. Requires that we are already in the
         * sGLThreadManager monitor when this is called.
         * sGLThreadManager monitor when this is called.
         */
         */
        public void releaseEglContextLocked(GLThread thread) {
        public void releaseEglContextLocked(GLThread thread) {
            if (mEglOwner == thread) {
                mEglOwner = null;
            }
            notifyAll();
            notifyAll();
        }
        }

        public synchronized boolean shouldReleaseEGLContextWhenPausing() {
            // Release the EGL context when pausing even if
            // the hardware supports multiple EGL contexts.
            // Otherwise the device could run out of EGL contexts.
            return mLimitedGLESContexts;
        }

        public synchronized boolean shouldTerminateEGLWhenPausing() {
            checkGLESVersion();
            return !mMultipleGLESContextsAllowed;
        }

        public synchronized void checkGLDriver(GL10 gl) {
            if (! mGLESDriverCheckComplete) {
                checkGLESVersion();
                String renderer = gl.glGetString(GL10.GL_RENDERER);
                if (mGLESVersion < kGLES_20) {
                    mMultipleGLESContextsAllowed =
                        ! renderer.startsWith(kMSM7K_RENDERER_PREFIX);
                    notifyAll();
                }
                mLimitedGLESContexts = !mMultipleGLESContextsAllowed;
                if (LOG_SURFACE) {
                    Log.w(TAG, "checkGLDriver renderer = \"" + renderer + "\" multipleContextsAllowed = "
                        + mMultipleGLESContextsAllowed
                        + " mLimitedGLESContexts = " + mLimitedGLESContexts);
                }
                mGLESDriverCheckComplete = true;
            }
        }

        private void checkGLESVersion() {
            if (! mGLESVersionCheckComplete) {
                mGLESVersion = SystemProperties.getInt(
                        "ro.opengles.version",
                        ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
                if (mGLESVersion >= kGLES_20) {
                    mMultipleGLESContextsAllowed = true;
                }
                if (LOG_SURFACE) {
                    Log.w(TAG, "checkGLESVersion mGLESVersion =" +
                            " " + mGLESVersion + " mMultipleGLESContextsAllowed = " + mMultipleGLESContextsAllowed);
                }
                mGLESVersionCheckComplete = true;
            }
        }

        /**
         * This check was required for some pre-Android-3.0 hardware. Android 3.0 provides
         * support for hardware-accelerated views, therefore multiple EGL contexts are
         * supported on all Android 3.0+ EGL drivers.
         */
        private boolean mGLESVersionCheckComplete;
        private int mGLESVersion;
        private boolean mGLESDriverCheckComplete;
        private boolean mMultipleGLESContextsAllowed;
        private boolean mLimitedGLESContexts;
        private static final int kGLES_20 = 0x20000;
        private static final String kMSM7K_RENDERER_PREFIX =
            "Q3Dimension MSM7500 ";
        private GLThread mEglOwner;
    }
    }


    private static final GLThreadManager sGLThreadManager = new GLThreadManager();
    private static final GLThreadManager sGLThreadManager = new GLThreadManager();