Android OpenGL ES 相关的包主要定义在
其中GLSurfaceView 为android.opengl 包中核心类:
使用过Java ME ,JSR 239 开发过OpenGL ES可以看到 Android 包javax.microedition.khronos.egl ,javax.microedition.khronos.opengles 和JSR239 基本一致,因此理论上不使用android.opengl 包中的类也可以开发Android上OpenGL ES应用,但此时就需要自己使用EGL来管理Display,Context, Surfaces 的创建,释放,捆绑,可以参见Android OpenGL ES 开发教程(5):关于EGL 。
使用EGL 实现GLSurfaceView一个可能的实现如下:
- class GLSurfaceView extends SurfaceView
- implements SurfaceHolder.Callback, Runnable {
- public GLSurfaceView(Context context) {
- super(context);
- mHolder = getHolder();
- mHolder.addCallback(this);
- mHolder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
- }
- public void setRenderer(Renderer renderer) {
- mRenderer = renderer;
- }
- public void surfaceCreated(SurfaceHolder holder) {
- }
- public void surfaceDestroyed(SurfaceHolder holder) {
- running = false;
- try {
- thread.join();
- } catch (InterruptedException e) {
- }
- thread = null;
- }
- public void surfaceChanged(SurfaceHolder holder,
- int format, int w, int h) {
- synchronized(this){
- mWidth = w;
- mHeight = h;
- thread = new Thread(this);
- thread.start();
- }
- }
- public interface Renderer {
- void EGLCreate(SurfaceHolder holder);
- void EGLDestroy();
- int Initialize(int width, int height);
- void DrawScene(int width, int height);
- }
- public void run() {
- synchronized(this) {
- mRenderer.EGLCreate(mHolder);
- mRenderer.Initialize(mWidth, mHeight);
- running=true;
- while (running) {
- mRenderer.DrawScene(mWidth, mHeight);
- }
- mRenderer.EGLDestroy();
- }
- }
- private SurfaceHolder mHolder;
- private Thread thread;
- private boolean running;
- private Renderer mRenderer;
- private int mWidth;
- private int mHeight;
- }
- class GLRenderer implements GLSurfaceView.Renderer {
- public GLRenderer() {
- }
- public int Initialize(int width, int height){
- gl.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
- return 1;
- }
- public void DrawScene(int width, int height){
- gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
- egl.eglSwapBuffers(eglDisplay, eglSurface);
- }
- public void EGLCreate(SurfaceHolder holder){
- int[] num_config = new int[1];
- EGLConfig[] configs = new EGLConfig[1];
- int[] configSpec = {
- EGL10.EGL_RED_SIZE, 8,
- EGL10.EGL_GREEN_SIZE, 8,
- EGL10.EGL_BLUE_SIZE, 8,
- EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
- EGL10.EGL_NONE
- };
- this.egl = (EGL10) EGLContext.getEGL();
- eglDisplay = this.egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
- this.egl.eglInitialize(eglDisplay, null);
- this.egl.eglChooseConfig(eglDisplay, configSpec,
- configs, 1, num_config);
- eglConfig = configs[0];
- eglContext = this.egl.eglCreateContext(eglDisplay, eglConfig,
- EGL10.EGL_NO_CONTEXT, null);
- eglSurface = this.egl.eglCreateWindowSurface(eglDisplay,
- eglConfig, holder, null);
- this.egl.eglMakeCurrent(eglDisplay, eglSurface,
- eglSurface, eglContext);
- gl = (GL10)eglContext.getGL();
- }
- public void EGLDestroy(){
- if (eglSurface != null) {
- egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE,
- EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
- egl.eglDestroySurface(eglDisplay, eglSurface);
- eglSurface = null;
- }
- if (eglContext != null) {
- egl.eglDestroyContext(eglDisplay, eglContext);
- eglContext = null;
- }
- if (eglDisplay != null) {
- egl.eglTerminate(eglDisplay);
- eglDisplay = null;
- }
- }
- private EGL10 egl;
- private GL10 gl;
- private EGLDisplay eglDisplay;
- private EGLConfig eglConfig;
- private EGLContext eglContext;
- private EGLSurface eglSurface;
- }
可以看到需要派生SurfaceView ,并手工创建,销毁Display,Context ,工作繁琐。
使用GLSurfaceView 内部提供了上面类似的实现,对于大部分应用只需调用一个方法来设置OpenGLView用到的GLSurfaceView.Renderer.
- public void setRenderer(GLSurfaceView.Renderer renderer)
GLSurfaceView.Renderer定义了一个统一图形绘制的接口,它定义了如下三个接口函数:
- // Called when the surface is created or recreated.
- public void onSurfaceCreated(GL10 gl, EGLConfig config)
- // Called to draw the current frame.
- public void onDrawFrame(GL10 gl)
- // Called when the surface changed size.
- public void onSurfaceChanged(GL10 gl, int width, int height)
如果有需要,也可以通过函数来修改GLSurfaceView一些缺省设置:
GLSurfaceView 缺省创建为RGB_565 颜色格式的Surface ,如果需要支持透明度,可以调用getHolder().setFormat(PixelFormat.TRANSLUCENT).
GLSurfaceView 的渲染模式有两种,一种是连续不断的更新屏幕,另一种为on-demand ,只有在调用requestRender() 在更新屏幕。 缺省为RENDERMODE_CONTINUOUSLY 持续刷新屏幕。