am 0dce2dd2: Extend GLSurfaceView to make it easy to create an OpenGL ES 2.0 context
Merge commit '0dce2dd26699e4dbfba8b8c5ea01f7fd03369e02' into eclair-mr2-plus-aosp * commit '0dce2dd26699e4dbfba8b8c5ea01f7fd03369e02': Extend GLSurfaceView to make it easy to create an OpenGL ES 2.0 context
This commit is contained in:
@@ -372,6 +372,39 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
||||
setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize,
|
||||
blueSize, alphaSize, depthSize, stencilSize));
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform the default EGLContextFactory and default EGLConfigChooser
|
||||
* which EGLContext client version to pick.
|
||||
* <p>Use this method to create an OpenGL ES 2.0-compatible context.
|
||||
* Example:
|
||||
* <pre class="prettyprint">
|
||||
* public MyView(Context context) {
|
||||
* super(context);
|
||||
* setEGLContextClientVersion(2); // Pick an OpenGL ES 2.0 context.
|
||||
* setRenderer(new MyRenderer());
|
||||
* }
|
||||
* </pre>
|
||||
* <p>Note: Activities which require OpenGL ES 2.0 should indicate this by
|
||||
* setting @lt;uses-feature android:glEsVersion="0x00020000" /> in the activity's
|
||||
* AndroidManifest.xml file.
|
||||
* <p>If this method is called, it must be called before {@link #setRenderer(Renderer)}
|
||||
* is called.
|
||||
* <p>This method only affects the behavior of the default EGLContexFactory and the
|
||||
* default EGLConfigChooser. If
|
||||
* {@link #setEGLContextFactory(EGLContextFactory)} has been called, then the supplied
|
||||
* EGLContextFactory is responsible for creating an OpenGL ES 2.0-compatible context.
|
||||
* If
|
||||
* {@link #setEGLConfigChooser(EGLConfigChooser)} has been called, then the supplied
|
||||
* EGLConfigChooser is responsible for choosing an OpenGL ES 2.0-compatible config.
|
||||
* @param version The EGLContext client version to choose. Use 2 for OpenGL ES 2.0
|
||||
* @hide
|
||||
*/
|
||||
public void setEGLContextClientVersion(int version) {
|
||||
checkRenderThreadState();
|
||||
mEGLContextClientVersion = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the rendering mode. When renderMode is
|
||||
* RENDERMODE_CONTINUOUSLY, the renderer is called
|
||||
@@ -623,10 +656,15 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
||||
void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context);
|
||||
}
|
||||
|
||||
private static class DefaultContextFactory implements EGLContextFactory {
|
||||
private class DefaultContextFactory implements EGLContextFactory {
|
||||
private int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
||||
|
||||
public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) {
|
||||
return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, null);
|
||||
int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, mEGLContextClientVersion,
|
||||
EGL10.EGL_NONE };
|
||||
|
||||
return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT,
|
||||
mEGLContextClientVersion != 0 ? attrib_list : null);
|
||||
}
|
||||
|
||||
public void destroyContext(EGL10 egl, EGLDisplay display,
|
||||
@@ -680,11 +718,12 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
||||
EGLConfig chooseConfig(EGL10 egl, EGLDisplay display);
|
||||
}
|
||||
|
||||
private static abstract class BaseConfigChooser
|
||||
private abstract class BaseConfigChooser
|
||||
implements EGLConfigChooser {
|
||||
public BaseConfigChooser(int[] configSpec) {
|
||||
mConfigSpec = configSpec;
|
||||
mConfigSpec = filterConfigSpec(configSpec);
|
||||
}
|
||||
|
||||
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
|
||||
int[] num_config = new int[1];
|
||||
if (!egl.eglChooseConfig(display, mConfigSpec, null, 0,
|
||||
@@ -715,9 +754,25 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
||||
EGLConfig[] configs);
|
||||
|
||||
protected int[] mConfigSpec;
|
||||
|
||||
private int[] filterConfigSpec(int[] configSpec) {
|
||||
if (mEGLContextClientVersion != 2) {
|
||||
return configSpec;
|
||||
}
|
||||
/* We know none of the subclasses define EGL_RENDERABLE_TYPE.
|
||||
* And we know the configSpec is well formed.
|
||||
*/
|
||||
int len = configSpec.length;
|
||||
int[] newConfigSpec = new int[len + 2];
|
||||
System.arraycopy(configSpec, 0, newConfigSpec, 0, len-1);
|
||||
newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE;
|
||||
newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */
|
||||
newConfigSpec[len+1] = EGL10.EGL_NONE;
|
||||
return newConfigSpec;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ComponentSizeChooser extends BaseConfigChooser {
|
||||
private class ComponentSizeChooser extends BaseConfigChooser {
|
||||
public ComponentSizeChooser(int redSize, int greenSize, int blueSize,
|
||||
int alphaSize, int depthSize, int stencilSize) {
|
||||
super(new int[] {
|
||||
@@ -793,7 +848,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
||||
* RGB565 as possible, with or without a depth buffer.
|
||||
*
|
||||
*/
|
||||
private static class SimpleEGLConfigChooser extends ComponentSizeChooser {
|
||||
private class SimpleEGLConfigChooser extends ComponentSizeChooser {
|
||||
public SimpleEGLConfigChooser(boolean withDepthBuffer) {
|
||||
super(4, 4, 4, 0, withDepthBuffer ? 16 : 0, 0);
|
||||
// Adjust target values. This way we'll accept a 4444 or
|
||||
@@ -1401,4 +1456,5 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
||||
private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory;
|
||||
private GLWrapper mGLWrapper;
|
||||
private int mDebugFlags;
|
||||
private int mEGLContextClientVersion;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.gl2java">
|
||||
<uses-feature android:glEsVersion="0x00020000" />
|
||||
<application
|
||||
android:label="@string/gl2java_activity">
|
||||
<activity android:name="GL2JavaActivity"
|
||||
|
||||
@@ -49,226 +49,10 @@ class GL2JavaView extends GLSurfaceView {
|
||||
|
||||
public GL2JavaView(Context context) {
|
||||
super(context);
|
||||
init(false, 0, 0);
|
||||
}
|
||||
|
||||
public GL2JavaView(Context context, boolean translucent, int depth, int stencil) {
|
||||
super(context);
|
||||
init(translucent, depth, stencil);
|
||||
}
|
||||
|
||||
private void init(boolean translucent, int depth, int stencil) {
|
||||
setEGLContextFactory(new ContextFactory());
|
||||
setEGLConfigChooser( translucent ?
|
||||
new ConfigChooser(8,8,8,8, depth, stencil) :
|
||||
new ConfigChooser(5,6,5,0, depth, stencil));
|
||||
setEGLContextClientVersion(2);
|
||||
setRenderer(new Renderer());
|
||||
}
|
||||
|
||||
private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
|
||||
private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
||||
public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
|
||||
Log.w(TAG, "creating OpenGL ES 2.0 context");
|
||||
checkEglError("Before eglCreateContext", egl);
|
||||
int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
|
||||
EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
|
||||
checkEglError("After eglCreateContext", egl);
|
||||
return context;
|
||||
}
|
||||
|
||||
public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
|
||||
egl.eglDestroyContext(display, context);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkEglError(String prompt, EGL10 egl) {
|
||||
int error;
|
||||
while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
|
||||
Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
mGreenSize = g;
|
||||
mBlueSize = b;
|
||||
mAlphaSize = a;
|
||||
mDepthSize = depth;
|
||||
mStencilSize = stencil;
|
||||
}
|
||||
|
||||
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
|
||||
|
||||
int[] num_config = new int[1];
|
||||
egl.eglChooseConfig(display, s_configAttribs2, null, 0, num_config);
|
||||
|
||||
int numConfigs = num_config[0];
|
||||
|
||||
if (numConfigs <= 0) {
|
||||
throw new IllegalArgumentException("No configs match configSpec");
|
||||
}
|
||||
EGLConfig[] configs = new EGLConfig[numConfigs];
|
||||
egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config);
|
||||
// printConfigs(egl, display, configs);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return closestConfig;
|
||||
}
|
||||
|
||||
private int findConfigAttrib(EGL10 egl, EGLDisplay display,
|
||||
EGLConfig config, int attribute, int defaultValue) {
|
||||
|
||||
if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
|
||||
return mValue[0];
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private void printConfigs(EGL10 egl, EGLDisplay display,
|
||||
EGLConfig[] configs) {
|
||||
int numConfigs = configs.length;
|
||||
Log.w(TAG, String.format("%d configurations", numConfigs));
|
||||
for (int i = 0; i < numConfigs; i++) {
|
||||
Log.w(TAG, String.format("Configuration %d:\n", i));
|
||||
printConfig(egl, display, configs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void printConfig(EGL10 egl, EGLDisplay display,
|
||||
EGLConfig config) {
|
||||
int[] attributes = {
|
||||
EGL10.EGL_BUFFER_SIZE,
|
||||
EGL10.EGL_ALPHA_SIZE,
|
||||
EGL10.EGL_BLUE_SIZE,
|
||||
EGL10.EGL_GREEN_SIZE,
|
||||
EGL10.EGL_RED_SIZE,
|
||||
EGL10.EGL_DEPTH_SIZE,
|
||||
EGL10.EGL_STENCIL_SIZE,
|
||||
EGL10.EGL_CONFIG_CAVEAT,
|
||||
EGL10.EGL_CONFIG_ID,
|
||||
EGL10.EGL_LEVEL,
|
||||
EGL10.EGL_MAX_PBUFFER_HEIGHT,
|
||||
EGL10.EGL_MAX_PBUFFER_PIXELS,
|
||||
EGL10.EGL_MAX_PBUFFER_WIDTH,
|
||||
EGL10.EGL_NATIVE_RENDERABLE,
|
||||
EGL10.EGL_NATIVE_VISUAL_ID,
|
||||
EGL10.EGL_NATIVE_VISUAL_TYPE,
|
||||
0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
|
||||
EGL10.EGL_SAMPLES,
|
||||
EGL10.EGL_SAMPLE_BUFFERS,
|
||||
EGL10.EGL_SURFACE_TYPE,
|
||||
EGL10.EGL_TRANSPARENT_TYPE,
|
||||
EGL10.EGL_TRANSPARENT_RED_VALUE,
|
||||
EGL10.EGL_TRANSPARENT_GREEN_VALUE,
|
||||
EGL10.EGL_TRANSPARENT_BLUE_VALUE,
|
||||
0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB,
|
||||
0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA,
|
||||
0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL,
|
||||
0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL,
|
||||
EGL10.EGL_LUMINANCE_SIZE,
|
||||
EGL10.EGL_ALPHA_MASK_SIZE,
|
||||
EGL10.EGL_COLOR_BUFFER_TYPE,
|
||||
EGL10.EGL_RENDERABLE_TYPE,
|
||||
0x3042 // EGL10.EGL_CONFORMANT
|
||||
};
|
||||
String[] names = {
|
||||
"EGL_BUFFER_SIZE",
|
||||
"EGL_ALPHA_SIZE",
|
||||
"EGL_BLUE_SIZE",
|
||||
"EGL_GREEN_SIZE",
|
||||
"EGL_RED_SIZE",
|
||||
"EGL_DEPTH_SIZE",
|
||||
"EGL_STENCIL_SIZE",
|
||||
"EGL_CONFIG_CAVEAT",
|
||||
"EGL_CONFIG_ID",
|
||||
"EGL_LEVEL",
|
||||
"EGL_MAX_PBUFFER_HEIGHT",
|
||||
"EGL_MAX_PBUFFER_PIXELS",
|
||||
"EGL_MAX_PBUFFER_WIDTH",
|
||||
"EGL_NATIVE_RENDERABLE",
|
||||
"EGL_NATIVE_VISUAL_ID",
|
||||
"EGL_NATIVE_VISUAL_TYPE",
|
||||
"EGL_PRESERVED_RESOURCES",
|
||||
"EGL_SAMPLES",
|
||||
"EGL_SAMPLE_BUFFERS",
|
||||
"EGL_SURFACE_TYPE",
|
||||
"EGL_TRANSPARENT_TYPE",
|
||||
"EGL_TRANSPARENT_RED_VALUE",
|
||||
"EGL_TRANSPARENT_GREEN_VALUE",
|
||||
"EGL_TRANSPARENT_BLUE_VALUE",
|
||||
"EGL_BIND_TO_TEXTURE_RGB",
|
||||
"EGL_BIND_TO_TEXTURE_RGBA",
|
||||
"EGL_MIN_SWAP_INTERVAL",
|
||||
"EGL_MAX_SWAP_INTERVAL",
|
||||
"EGL_LUMINANCE_SIZE",
|
||||
"EGL_ALPHA_MASK_SIZE",
|
||||
"EGL_COLOR_BUFFER_TYPE",
|
||||
"EGL_RENDERABLE_TYPE",
|
||||
"EGL_CONFORMANT"
|
||||
};
|
||||
int[] value = new int[1];
|
||||
for (int i = 0; i < attributes.length; i++) {
|
||||
int attribute = attributes[i];
|
||||
String name = names[i];
|
||||
if ( egl.eglGetConfigAttrib(display, config, attribute, value)) {
|
||||
Log.w(TAG, String.format(" %s: %d\n", name, value[0]));
|
||||
} else {
|
||||
// Log.w(TAG, String.format(" %s: failed\n", name));
|
||||
while (egl.eglGetError() != EGL10.EGL_SUCCESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Subclasses can adjust these values:
|
||||
protected int mRedSize;
|
||||
protected int mGreenSize;
|
||||
protected int mBlueSize;
|
||||
protected int mAlphaSize;
|
||||
protected int mDepthSize;
|
||||
protected int mStencilSize;
|
||||
private int[] mValue = new int[1];
|
||||
}
|
||||
|
||||
private static class Renderer implements GLSurfaceView.Renderer {
|
||||
|
||||
public Renderer() {
|
||||
|
||||
Reference in New Issue
Block a user