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>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
|
<uses-feature android:glEsVersion="0x00020000"/>
|
||||||
<uses-sdk android:minSdkVersion="5"/>
|
<uses-sdk android:minSdkVersion="5"/>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ package com.android.gl2jni;
|
|||||||
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.PixelFormat;
|
||||||
import android.opengl.GLSurfaceView;
|
import android.opengl.GLSurfaceView;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -46,16 +47,26 @@ import javax.microedition.khronos.egl.EGLDisplay;
|
|||||||
import javax.microedition.khronos.opengles.GL10;
|
import javax.microedition.khronos.opengles.GL10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of SurfaceView that uses the dedicated surface for
|
* A simple GLSurfaceView sub-class that demonstrate how to perform
|
||||||
* displaying an OpenGL animation. This allows the animation to run in a
|
* OpenGL ES 2.0 rendering into a GL Surface. Note the following important
|
||||||
* separate thread, without requiring that it be driven by the update mechanism
|
* details:
|
||||||
* of the view hierarchy.
|
|
||||||
*
|
*
|
||||||
* The application-specific rendering code is delegated to a GLView.Renderer
|
* - The class must use a custom context factory to enable 2.0 rendering.
|
||||||
* instance.
|
* 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 {
|
class GL2JNIView extends GLSurfaceView {
|
||||||
private static String TAG = "GL2JNIView";
|
private static String TAG = "GL2JNIView";
|
||||||
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
public GL2JNIView(Context context) {
|
public GL2JNIView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@@ -68,10 +79,31 @@ class GL2JNIView extends GLSurfaceView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void init(boolean translucent, int depth, int stencil) {
|
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());
|
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 ?
|
setEGLConfigChooser( translucent ?
|
||||||
new ConfigChooser(8,8,8,8, depth, stencil) :
|
new ConfigChooser(8, 8, 8, 8, depth, stencil) :
|
||||||
new ConfigChooser(5,6,5,0, depth, stencil));
|
new ConfigChooser(5, 6, 5, 0, depth, stencil) );
|
||||||
|
|
||||||
|
/* Set the renderer responsible for frame rendering */
|
||||||
setRenderer(new Renderer());
|
setRenderer(new Renderer());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,15 +131,6 @@ class GL2JNIView extends GLSurfaceView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
|
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) {
|
public ConfigChooser(int r, int g, int b, int a, int depth, int stencil) {
|
||||||
mRedSize = r;
|
mRedSize = r;
|
||||||
@@ -118,8 +141,24 @@ class GL2JNIView extends GLSurfaceView {
|
|||||||
mStencilSize = stencil;
|
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) {
|
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
|
||||||
|
|
||||||
|
/* Get the number of minimally matching EGL configurations
|
||||||
|
*/
|
||||||
int[] num_config = new int[1];
|
int[] num_config = new int[1];
|
||||||
egl.eglChooseConfig(display, s_configAttribs2, null, 0, num_config);
|
egl.eglChooseConfig(display, s_configAttribs2, null, 0, num_config);
|
||||||
|
|
||||||
@@ -128,22 +167,33 @@ class GL2JNIView extends GLSurfaceView {
|
|||||||
if (numConfigs <= 0) {
|
if (numConfigs <= 0) {
|
||||||
throw new IllegalArgumentException("No configs match configSpec");
|
throw new IllegalArgumentException("No configs match configSpec");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocate then read the array of minimally matching EGL configs
|
||||||
|
*/
|
||||||
EGLConfig[] configs = new EGLConfig[numConfigs];
|
EGLConfig[] configs = new EGLConfig[numConfigs];
|
||||||
egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config);
|
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);
|
return chooseConfig(egl, display, configs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
|
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
|
||||||
EGLConfig[] configs) {
|
EGLConfig[] configs) {
|
||||||
EGLConfig closestConfig = null;
|
|
||||||
int closestDistance = 1000;
|
|
||||||
for(EGLConfig config : configs) {
|
for(EGLConfig config : configs) {
|
||||||
int d = findConfigAttrib(egl, display, config,
|
int d = findConfigAttrib(egl, display, config,
|
||||||
EGL10.EGL_DEPTH_SIZE, 0);
|
EGL10.EGL_DEPTH_SIZE, 0);
|
||||||
int s = findConfigAttrib(egl, display, config,
|
int s = findConfigAttrib(egl, display, config,
|
||||||
EGL10.EGL_STENCIL_SIZE, 0);
|
EGL10.EGL_STENCIL_SIZE, 0);
|
||||||
if (d >= mDepthSize && s>= mStencilSize) {
|
|
||||||
|
// 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,
|
int r = findConfigAttrib(egl, display, config,
|
||||||
EGL10.EGL_RED_SIZE, 0);
|
EGL10.EGL_RED_SIZE, 0);
|
||||||
int g = findConfigAttrib(egl, display, config,
|
int g = findConfigAttrib(egl, display, config,
|
||||||
@@ -152,17 +202,11 @@ class GL2JNIView extends GLSurfaceView {
|
|||||||
EGL10.EGL_BLUE_SIZE, 0);
|
EGL10.EGL_BLUE_SIZE, 0);
|
||||||
int a = findConfigAttrib(egl, display, config,
|
int a = findConfigAttrib(egl, display, config,
|
||||||
EGL10.EGL_ALPHA_SIZE, 0);
|
EGL10.EGL_ALPHA_SIZE, 0);
|
||||||
int distance = Math.abs(r - mRedSize)
|
|
||||||
+ Math.abs(g - mGreenSize)
|
if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize)
|
||||||
+ Math.abs(b - mBlueSize)
|
return config;
|
||||||
+ Math.abs(a - mAlphaSize);
|
|
||||||
if (distance < closestDistance) {
|
|
||||||
closestDistance = distance;
|
|
||||||
closestConfig = config;
|
|
||||||
}
|
}
|
||||||
}
|
return null;
|
||||||
}
|
|
||||||
return closestConfig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int findConfigAttrib(EGL10 egl, EGLDisplay display,
|
private int findConfigAttrib(EGL10 egl, EGLDisplay display,
|
||||||
@@ -293,4 +337,3 @@ class GL2JNIView extends GLSurfaceView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user