summaryrefslogtreecommitdiffstats
path: root/opengl/java
diff options
context:
space:
mode:
authorJack Palevich <jackpal@google.com>2009-09-21 19:31:42 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2009-09-21 19:31:42 -0700
commite2317438433d4f2f822fe0c3659e70c89f6a707f (patch)
treeb3ea23b2a1a1eb6da5694c9ad9086f8f3e93dab2 /opengl/java
parent4a1d8788dec5630b7a1874f661c6cbd1fc863328 (diff)
parent1167b43c3d1ca232c9b4e0a75343b6b3cb90f0df (diff)
downloadframeworks_base-e2317438433d4f2f822fe0c3659e70c89f6a707f.zip
frameworks_base-e2317438433d4f2f822fe0c3659e70c89f6a707f.tar.gz
frameworks_base-e2317438433d4f2f822fe0c3659e70c89f6a707f.tar.bz2
am 1167b43c: Merge change 26317 into eclair
Merge commit '1167b43c3d1ca232c9b4e0a75343b6b3cb90f0df' into eclair-plus-aosp * commit '1167b43c3d1ca232c9b4e0a75343b6b3cb90f0df': Allow GLSurfaceView clients to customize EGL Surfaces and Contexts.
Diffstat (limited to 'opengl/java')
-rw-r--r--opengl/java/android/opengl/GLSurfaceView.java278
1 files changed, 184 insertions, 94 deletions
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 07c19b4..b3a19e3 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -271,18 +271,52 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
* @param renderer the renderer to use to perform OpenGL drawing.
*/
public void setRenderer(Renderer renderer) {
- if (mGLThread != null) {
- throw new IllegalStateException(
- "setRenderer has already been called for this instance.");
- }
+ checkRenderThreadState();
if (mEGLConfigChooser == null) {
mEGLConfigChooser = new SimpleEGLConfigChooser(true);
}
+ if (mEGLContextFactory == null) {
+ mEGLContextFactory = new DefaultContextFactory();
+ }
+ if (mEGLWindowSurfaceFactory == null) {
+ mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();
+ }
mGLThread = new GLThread(renderer);
mGLThread.start();
}
/**
+ * @hide
+ * Install a custom EGLContextFactory.
+ * <p>If this method is
+ * called, it must be called before {@link #setRenderer(Renderer)}
+ * is called.
+ * <p>
+ * If this method is not called, then by default
+ * a context will be created with no shared context and
+ * with a null attribute list.
+ */
+ public void setContextFactory(EGLContextFactory factory) {
+ checkRenderThreadState();
+ mEGLContextFactory = factory;
+ }
+
+ /**
+ * @hide
+ * Install a custom EGLWindowSurfaceFactory.
+ * <p>If this method is
+ * called, it must be called before {@link #setRenderer(Renderer)}
+ * is called.
+ * <p>
+ * If this method is not called, then by default
+ * a window surface will be created with a null attribute list.
+ */
+ public void setWindowSurfaceFactory(EGLWindowSurfaceFactory factory) {
+ checkRenderThreadState();
+ mEGLWindowSurfaceFactory = factory;
+ }
+
+ /**
* Install a custom EGLConfigChooser.
* <p>If this method is
* called, it must be called before {@link #setRenderer(Renderer)}
@@ -294,10 +328,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
* @param configChooser
*/
public void setEGLConfigChooser(EGLConfigChooser configChooser) {
- if (mGLThread != null) {
- throw new IllegalStateException(
- "setRenderer has already been called for this instance.");
- }
+ checkRenderThreadState();
mEGLConfigChooser = configChooser;
}
@@ -578,6 +609,56 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
}
/**
+ * @hide
+ * An interface for customizing the eglCreateContext and eglDestroyContext calls.
+ * <p>
+ * This interface must be implemented by clients wishing to call
+ * {@link GLSurfaceView#setEGLContextFactory(EGLContextFactory)}
+ */
+ public interface EGLContextFactory {
+ EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig);
+ void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context);
+ }
+
+ private static class DefaultContextFactory implements EGLContextFactory {
+
+ public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) {
+ return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, null);
+ }
+
+ public void destroyContext(EGL10 egl, EGLDisplay display,
+ EGLContext context) {
+ egl.eglDestroyContext(display, context);
+ }
+ }
+
+ /**
+ * @hide
+ * An interface for customizing the eglCreateWindowSurface and eglDestroySurface calls.
+ * <p>
+ * This interface must be implemented by clients wishing to call
+ * {@link GLSurfaceView#setEGLContextCreator(EGLContextCreator)}
+ */
+ public interface EGLWindowSurfaceFactory {
+ EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config,
+ Object nativeWindow);
+ void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface);
+ }
+
+ private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory {
+
+ public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display,
+ EGLConfig config, Object nativeWindow) {
+ return egl.eglCreateWindowSurface(display, config, nativeWindow, null);
+ }
+
+ public void destroySurface(EGL10 egl, EGLDisplay display,
+ EGLSurface surface) {
+ egl.eglDestroySurface(display, surface);
+ }
+ }
+
+ /**
* An interface for choosing an EGLConfig configuration from a list of
* potential configurations.
* <p>
@@ -751,8 +832,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
* Create an OpenGL ES context. This must be done only once, an
* OpenGL context is a somewhat heavy object.
*/
- mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig,
- EGL10.EGL_NO_CONTEXT, null);
+ mEglContext = mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);
mEglSurface = null;
}
@@ -774,14 +854,14 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
*/
mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
- mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
+ mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface);
}
/*
* Create an EGL surface we can render into.
*/
- mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay,
- mEglConfig, holder, null);
+ mEglSurface = mEGLWindowSurfaceFactory.createWindowSurface(mEgl,
+ mEglDisplay, mEglConfig, holder);
/*
* Before we can issue GL commands, we need to make sure
@@ -790,7 +870,6 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
mEglContext);
-
GL gl = mEglContext.getGL();
if (mGLWrapper != null) {
gl = mGLWrapper.wrap(gl);
@@ -831,14 +910,14 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_CONTEXT);
- mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
+ mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface);
mEglSurface = null;
}
}
public void finish() {
if (mEglContext != null) {
- mEgl.eglDestroyContext(mEglDisplay, mEglContext);
+ mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext);
mEglContext = null;
}
if (mEglDisplay != null) {
@@ -898,92 +977,93 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
private void guardedRun() throws InterruptedException {
mEglHelper = new EglHelper();
- mEglHelper.start();
-
- GL10 gl = null;
- boolean tellRendererSurfaceCreated = true;
- boolean tellRendererSurfaceChanged = true;
+ try {
+ mEglHelper.start();
- /*
- * This is our main activity thread's loop, we go until
- * asked to quit.
- */
- while (!mDone) {
+ GL10 gl = null;
+ boolean tellRendererSurfaceCreated = true;
+ boolean tellRendererSurfaceChanged = true;
/*
- * Update the asynchronous state (window size)
+ * This is our main activity thread's loop, we go until
+ * asked to quit.
*/
- int w, h;
- boolean changed;
- boolean needStart = false;
- synchronized (this) {
- Runnable r;
- while ((r = getEvent()) != null) {
- r.run();
- }
- if (mPaused) {
- mEglHelper.destroySurface();
- mEglHelper.finish();
- needStart = true;
- }
- while (needToWait()) {
- if (!mHasSurface) {
- if (!mWaitingForSurface) {
- mEglHelper.destroySurface();
- mWaitingForSurface = true;
- notify();
+ while (!mDone) {
+
+ /*
+ * Update the asynchronous state (window size)
+ */
+ int w, h;
+ boolean changed;
+ boolean needStart = false;
+ synchronized (this) {
+ Runnable r;
+ while ((r = getEvent()) != null) {
+ r.run();
+ }
+ if (mPaused) {
+ mEglHelper.destroySurface();
+ mEglHelper.finish();
+ needStart = true;
+ }
+ while (needToWait()) {
+ if (!mHasSurface) {
+ if (!mWaitingForSurface) {
+ mEglHelper.destroySurface();
+ mWaitingForSurface = true;
+ notify();
+ }
}
+ wait();
+ }
+ if (mDone) {
+ break;
+ }
+ changed = mSizeChanged;
+ w = mWidth;
+ h = mHeight;
+ mSizeChanged = false;
+ mRequestRender = false;
+ if (mHasSurface && mWaitingForSurface) {
+ changed = true;
+ mWaitingForSurface = false;
}
- wait();
- }
- if (mDone) {
- break;
}
- changed = mSizeChanged;
- w = mWidth;
- h = mHeight;
- mSizeChanged = false;
- mRequestRender = false;
- if (mHasSurface && mWaitingForSurface) {
+ if (needStart) {
+ mEglHelper.start();
+ tellRendererSurfaceCreated = true;
changed = true;
- mWaitingForSurface = false;
- mRequestRender = true; // Forces a redraw for RENDERMODE_RENDER_WHEN_DIRTY
}
- }
- if (needStart) {
- mEglHelper.start();
- tellRendererSurfaceCreated = true;
- changed = true;
- }
- if (changed) {
- gl = (GL10) mEglHelper.createSurface(getHolder());
- tellRendererSurfaceChanged = true;
- }
- if (tellRendererSurfaceCreated) {
- mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
- tellRendererSurfaceCreated = false;
- }
- if (tellRendererSurfaceChanged) {
- mRenderer.onSurfaceChanged(gl, w, h);
- tellRendererSurfaceChanged = false;
- }
- if ((w > 0) && (h > 0)) {
- /* draw a frame here */
- mRenderer.onDrawFrame(gl);
-
- /*
- * Once we're done with GL, we need to call swapBuffers()
- * to instruct the system to display the rendered frame
- */
- mEglHelper.swap();
- }
- }
-
- /*
- * clean-up everything...
- */
- mEglHelper.destroySurface();
- mEglHelper.finish();
+ if (changed) {
+ gl = (GL10) mEglHelper.createSurface(getHolder());
+ tellRendererSurfaceChanged = true;
+ }
+ if (tellRendererSurfaceCreated) {
+ mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
+ tellRendererSurfaceCreated = false;
+ }
+ if (tellRendererSurfaceChanged) {
+ mRenderer.onSurfaceChanged(gl, w, h);
+ tellRendererSurfaceChanged = false;
+ }
+ if ((w > 0) && (h > 0)) {
+ /* draw a frame here */
+ mRenderer.onDrawFrame(gl);
+
+ /*
+ * Once we're done with GL, we need to call swapBuffers()
+ * to instruct the system to display the rendered frame
+ */
+ mEglHelper.swap();
+ }
+ }
+ } finally {
+ /*
+ * clean-up everything...
+ */
+ mEglHelper.destroySurface();
+ mEglHelper.finish();
+ }
}
private boolean needToWait() {
@@ -1038,7 +1118,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
synchronized(this) {
mHasSurface = false;
notify();
- while(!mWaitingForSurface) {
+ while(!mWaitingForSurface && isAlive()) {
try {
wait();
} catch (InterruptedException e) {
@@ -1149,11 +1229,21 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
private StringBuilder mBuilder = new StringBuilder();
}
+
+ private void checkRenderThreadState() {
+ if (mGLThread != null) {
+ throw new IllegalStateException(
+ "setRenderer has already been called for this instance.");
+ }
+ }
+
private static final Semaphore sEglSemaphore = new Semaphore(1);
private boolean mSizeChanged = true;
private GLThread mGLThread;
private EGLConfigChooser mEGLConfigChooser;
+ private EGLContextFactory mEGLContextFactory;
+ private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory;
private GLWrapper mGLWrapper;
private int mDebugFlags;
}