diff options
Diffstat (limited to 'opengl/java')
| -rw-r--r-- | opengl/java/android/opengl/GLSurfaceView.java | 91 |
1 files changed, 71 insertions, 20 deletions
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java index 952eff2..cbe5be4 100644 --- a/opengl/java/android/opengl/GLSurfaceView.java +++ b/opengl/java/android/opengl/GLSurfaceView.java @@ -18,7 +18,6 @@ package android.opengl; import java.io.Writer; import java.util.ArrayList; -import java.util.concurrent.Semaphore; import javax.microedition.khronos.egl.EGL10; import javax.microedition.khronos.egl.EGL11; @@ -30,6 +29,8 @@ import javax.microedition.khronos.opengles.GL; import javax.microedition.khronos.opengles.GL10; import android.content.Context; +import android.content.pm.ConfigurationInfo; +import android.os.SystemProperties; import android.util.AttributeSet; import android.util.Log; import android.view.SurfaceHolder; @@ -682,7 +683,10 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { int[] num_config = new int[1]; - egl.eglChooseConfig(display, mConfigSpec, null, 0, num_config); + if (!egl.eglChooseConfig(display, mConfigSpec, null, 0, + num_config)) { + throw new IllegalArgumentException("eglChooseConfig failed"); + } int numConfigs = num_config[0]; @@ -692,8 +696,10 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } EGLConfig[] configs = new EGLConfig[numConfigs]; - egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, - num_config); + if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, + num_config)) { + throw new IllegalArgumentException("eglChooseConfig#2 failed"); + } EGLConfig config = chooseConfig(egl, display, configs); if (config == null) { throw new IllegalArgumentException("No config chosen"); @@ -818,11 +824,17 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback */ mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); + if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { + throw new RuntimeException("eglGetDisplay failed"); + } + /* * We can now initialize EGL for that display */ int[] version = new int[2]; - mEgl.eglInitialize(mEglDisplay, version); + if(!mEgl.eglInitialize(mEglDisplay, version)) { + throw new RuntimeException("eglInitialize failed"); + } mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); /* @@ -1059,6 +1071,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } if (changed) { gl = (GL10) mEglHelper.createSurface(getHolder()); + sGLThreadManager.checkGLDriver(gl); tellRendererSurfaceChanged = true; } if (tellRendererSurfaceCreated) { @@ -1272,37 +1285,75 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } } - static class GLThreadManager { - public boolean shouldQuit(GLThread thread) { - synchronized(this) { - return thread != mMostRecentGLThread; - } - } + private static class GLThreadManager { public void start(GLThread thread) throws InterruptedException { + if (! mGLESVersionCheckComplete) { + mGLESVersion = SystemProperties.getInt( + "ro.opengles.version", + ConfigurationInfo.GL_ES_VERSION_UNDEFINED); + if (mGLESVersion >= kGLES_20) { + mMultipleGLESContextsAllowed = true; + } + mGLESVersionCheckComplete = true; + } + GLThread oldThread = null; synchronized(this) { mMostRecentGLThread = thread; oldThread = mMostRecentGLThread; + + while ((! mMultipleGLESContextsAllowed) + && mGLContextCount > 0) { + wait(); + } + + mGLContextCount++; } - if (oldThread != null) { + + if (oldThread != null && ! mMultipleGLESContextsAllowed) { synchronized(oldThread) { oldThread.notifyAll(); } } - sEglSemaphore.acquire(); } - public void end(GLThread thread) { - sEglSemaphore.release(); - synchronized(this) { - if (mMostRecentGLThread == thread) { - mMostRecentGLThread = null; + + public synchronized void end(GLThread thread) { + mGLContextCount--; + notifyAll(); + if (mMostRecentGLThread == thread) { + mMostRecentGLThread = null; + } + } + + public synchronized void checkGLDriver(GL10 gl) { + if (! mGLESDriverCheckComplete) { + if (mGLESVersion < kGLES_20) { + String renderer = gl.glGetString(GL10.GL_RENDERER); + mMultipleGLESContextsAllowed = + ! renderer.startsWith(kMSM7K_RENDERER_PREFIX); + notifyAll(); } + mGLESDriverCheckComplete = true; } } + + public boolean shouldQuit(GLThread thread) { + synchronized(this) { + return thread != mMostRecentGLThread; + } + } + + private boolean mGLESVersionCheckComplete; + private int mGLESVersion; private GLThread mMostRecentGLThread; - } + private boolean mGLESDriverCheckComplete; + private boolean mMultipleGLESContextsAllowed; + private int mGLContextCount; + private static final int kGLES_20 = 0x20000; + private static final String kMSM7K_RENDERER_PREFIX = + "Q3Dimension MSM7500 "; + }; - private static final Semaphore sEglSemaphore = new Semaphore(1); private static final GLThreadManager sGLThreadManager = new GLThreadManager(); private boolean mSizeChanged = true; |
