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
This commit is contained in:
@@ -32,5 +32,6 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
<uses-feature android:glEsVersion="0x00020000"/>
|
||||
<uses-sdk android:minSdkVersion="5"/>
|
||||
</manifest>
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user