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 持續刷新屏幕。