aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2010-02-19 17:59:50 -0800
committerDavid 'Digit' Turner <digit@google.com>2010-02-21 12:23:51 -0800
commitefebd72894aad26a628b7046d405c8dd730879cc (patch)
tree1e056864b95b9c123a246929e059ad03e192be25
parent450766678abf628559f96700082d29689ad1b2b6 (diff)
downloadndk-efebd72894aad26a628b7046d405c8dd730879cc.tar.gz
Update hello-gl2 sample to properly implement EGL Config selection.
Also add some comments to explicit what is being done here. + add <uses-feature android:glEsVersion="0x00020000"/> to AndroidManifest.xml
-rw-r--r--apps/hello-gl2/project/AndroidManifest.xml1
-rw-r--r--apps/hello-gl2/project/src/com/android/gl2jni/GL2JNIView.java123
2 files changed, 84 insertions, 40 deletions
diff --git a/apps/hello-gl2/project/AndroidManifest.xml b/apps/hello-gl2/project/AndroidManifest.xml
index 0ef6fb0db..5a4d5f277 100644
--- a/apps/hello-gl2/project/AndroidManifest.xml
+++ b/apps/hello-gl2/project/AndroidManifest.xml
@@ -32,5 +32,6 @@
</intent-filter>
</activity>
</application>
+ <uses-feature android:glEsVersion="0x00020000"/>
<uses-sdk android:minSdkVersion="5"/>
</manifest>
diff --git a/apps/hello-gl2/project/src/com/android/gl2jni/GL2JNIView.java b/apps/hello-gl2/project/src/com/android/gl2jni/GL2JNIView.java
index 72b1dfb9b..060290a76 100644
--- a/apps/hello-gl2/project/src/com/android/gl2jni/GL2JNIView.java
+++ b/apps/hello-gl2/project/src/com/android/gl2jni/GL2JNIView.java
@@ -33,6 +33,7 @@ package com.android.gl2jni;
import android.content.Context;
+import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import android.util.Log;
@@ -46,16 +47,26 @@ import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.opengles.GL10;
/**
- * An implementation of SurfaceView that uses the dedicated surface for
- * displaying an OpenGL animation. This allows the animation to run in a
- * separate thread, without requiring that it be driven by the update mechanism
- * of the view hierarchy.
+ * A simple GLSurfaceView sub-class that demonstrate how to perform
+ * OpenGL ES 2.0 rendering into a GL Surface. Note the following important
+ * details:
*
- * The application-specific rendering code is delegated to a GLView.Renderer
- * instance.
+ * - The class must use a custom context factory to enable 2.0 rendering.
+ * See ContextFactory class definition below.
+ *
+ * - The class must use a custom EGLConfigChooser to be able to select
+ * an EGLConfig that supports 2.0. This is done by providing a config
+ * specification to eglChooseConfig() that has the attribute
+ * EGL10.ELG_RENDERABLE_TYPE containing the EGL_OPENGL_ES2_BIT flag
+ * set. See ConfigChooser class definition below.
+ *
+ * - The class must select the surface's format, then choose an EGLConfig
+ * that matches it exactly (with regards to red/green/blue/alpha channels
+ * bit depths). Failure to do so would result in an EGL_BAD_MATCH error.
*/
class GL2JNIView extends GLSurfaceView {
private static String TAG = "GL2JNIView";
+ private static final boolean DEBUG = false;
public GL2JNIView(Context context) {
super(context);
@@ -68,10 +79,31 @@ class GL2JNIView extends GLSurfaceView {
}
private void init(boolean translucent, int depth, int stencil) {
+
+ /* By default, GLSurfaceView() creates a RGB_565 opaque surface.
+ * If we want a translucent one, we should change the surface's
+ * format here, using PixelFormat.TRANSLUCENT for GL Surfaces
+ * is interpreted as any 32-bit surface with alpha by SurfaceFlinger.
+ */
+ if (translucent) {
+ this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
+ }
+
+ /* Setup the context factory for 2.0 rendering.
+ * See ContextFactory class definition below
+ */
setEGLContextFactory(new ContextFactory());
+
+ /* We need to choose an EGLConfig that matches the format of
+ * our surface exactly. This is going to be done in our
+ * custom config chooser. See ConfigChooser class definition
+ * below.
+ */
setEGLConfigChooser( translucent ?
- new ConfigChooser(8,8,8,8, depth, stencil) :
- new ConfigChooser(5,6,5,0, depth, stencil));
+ new ConfigChooser(8, 8, 8, 8, depth, stencil) :
+ new ConfigChooser(5, 6, 5, 0, depth, stencil) );
+
+ /* Set the renderer responsible for frame rendering */
setRenderer(new Renderer());
}
@@ -99,15 +131,6 @@ class GL2JNIView extends GLSurfaceView {
}
private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
- private static int EGL_OPENGL_ES2_BIT = 4;
- private static int[] s_configAttribs2 =
- {
- EGL10.EGL_RED_SIZE, 4,
- EGL10.EGL_GREEN_SIZE, 4,
- EGL10.EGL_BLUE_SIZE, 4,
- EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL10.EGL_NONE
- };
public ConfigChooser(int r, int g, int b, int a, int depth, int stencil) {
mRedSize = r;
@@ -118,8 +141,24 @@ class GL2JNIView extends GLSurfaceView {
mStencilSize = stencil;
}
+ /* This EGL config specification is used to specify 2.0 rendering.
+ * We use a minimum size of 4 bits for red/green/blue, but will
+ * perform actual matching in chooseConfig() below.
+ */
+ private static int EGL_OPENGL_ES2_BIT = 4;
+ private static int[] s_configAttribs2 =
+ {
+ EGL10.EGL_RED_SIZE, 4,
+ EGL10.EGL_GREEN_SIZE, 4,
+ EGL10.EGL_BLUE_SIZE, 4,
+ EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL10.EGL_NONE
+ };
+
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
+ /* Get the number of minimally matching EGL configurations
+ */
int[] num_config = new int[1];
egl.eglChooseConfig(display, s_configAttribs2, null, 0, num_config);
@@ -128,41 +167,46 @@ class GL2JNIView extends GLSurfaceView {
if (numConfigs <= 0) {
throw new IllegalArgumentException("No configs match configSpec");
}
+
+ /* Allocate then read the array of minimally matching EGL configs
+ */
EGLConfig[] configs = new EGLConfig[numConfigs];
egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config);
- // printConfigs(egl, display, configs);
+
+ if (DEBUG) {
+ printConfigs(egl, display, configs);
+ }
+ /* Now return the "best" one
+ */
return chooseConfig(egl, display, configs);
}
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
EGLConfig[] configs) {
- EGLConfig closestConfig = null;
- int closestDistance = 1000;
for(EGLConfig config : configs) {
int d = findConfigAttrib(egl, display, config,
EGL10.EGL_DEPTH_SIZE, 0);
int s = findConfigAttrib(egl, display, config,
EGL10.EGL_STENCIL_SIZE, 0);
- if (d >= mDepthSize && s>= mStencilSize) {
- int r = findConfigAttrib(egl, display, config,
- EGL10.EGL_RED_SIZE, 0);
- int g = findConfigAttrib(egl, display, config,
- EGL10.EGL_GREEN_SIZE, 0);
- int b = findConfigAttrib(egl, display, config,
- EGL10.EGL_BLUE_SIZE, 0);
- int a = findConfigAttrib(egl, display, config,
- EGL10.EGL_ALPHA_SIZE, 0);
- int distance = Math.abs(r - mRedSize)
- + Math.abs(g - mGreenSize)
- + Math.abs(b - mBlueSize)
- + Math.abs(a - mAlphaSize);
- if (distance < closestDistance) {
- closestDistance = distance;
- closestConfig = config;
- }
- }
+
+ // We need at least mDepthSize and mStencilSize bits
+ if (d < mDepthSize || s < mStencilSize)
+ continue;
+
+ // We want an *exact* match for red/green/blue/alpha
+ int r = findConfigAttrib(egl, display, config,
+ EGL10.EGL_RED_SIZE, 0);
+ int g = findConfigAttrib(egl, display, config,
+ EGL10.EGL_GREEN_SIZE, 0);
+ int b = findConfigAttrib(egl, display, config,
+ EGL10.EGL_BLUE_SIZE, 0);
+ int a = findConfigAttrib(egl, display, config,
+ EGL10.EGL_ALPHA_SIZE, 0);
+
+ if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize)
+ return config;
}
- return closestConfig;
+ return null;
}
private int findConfigAttrib(EGL10 egl, EGLDisplay display,
@@ -293,4 +337,3 @@ class GL2JNIView extends GLSurfaceView {
}
}
}
-