通常情况下我们使用GLSurfaceview来实现opengl渲染.GLSurfaceview实现上是对SurfaceView和EGL的封装.为了从本质上理解渲染流程,使用EGL和SurfaceView来写一个Demo.
首先要封装一个EGLHelper用来操作EGL.下面代码的详细解释请参考参考资料3. EGLHelper.java代码如下:
public class EglHelper {
EGL10 mEgl;
EGLDisplay mEglDisplay;
EGLSurface mEglSurface;
EGLConfig mEglConfig;
EGLContext mEglContext;
public EglHelper(){}
public void start(int[] configSpec)
{
mEgl = (EGL10) EGLContext.getEGL();
mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
int[] version = new int[2];
mEgl.eglInitialize(mEglDisplay, version);
EGLConfig[] configs = new EGLConfig[1];
int[] num_config = new int[1];
mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1,
num_config);
mEglConfig = configs[0];
mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig,
EGL10.EGL_NO_CONTEXT, null);
mEglSurface = null;
}
public GL createSurface(SurfaceHolder holder) {
if (mEglSurface != null) {
mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
}
mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay,
mEglConfig, holder, null);
mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
mEglContext);
GL gl = mEglContext.getGL();
return gl;
}
public boolean swap() {
mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST;
}
public void finish() {
if (mEglSurface != null) {
mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_CONTEXT);
mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
mEglSurface = null;
}
if (mEglContext != null) {
mEgl.eglDestroyContext(mEglDisplay, mEglContext);
mEglContext = null;
}
if (mEglDisplay != null) {
mEgl.eglTerminate(mEglDisplay);
mEglDisplay = null;
}
}
}
需要写一个类继承SurfaceView.要在SurfaceView的surfaceCreated和surfaceChanged执行之后再进行opengl的相关操作.代码如下:
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
public SurfaceHolder mHolder;
private int w, h;
private Context context;
public MySurfaceView(Context context) {
super(context);
this.context = context;
init();
}
public MySurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mHolder = getHolder();
mHolder.addCallback(this);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
EglHelper eglHelper = new EglHelper();
int[] configSpec = {
EGL10.EGL_DEPTH_SIZE, 0,
EGL10.EGL_NONE
};
eglHelper.start(configSpec);
GL10 gl = (GL10) eglHelper.createSurface(mHolder);
gl.glClearColor(1f, 0f, 0f, 0f);
gl.glViewport(0, 0, w, h);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
eglHelper.swap();
}
public void surfaceCreated(SurfaceHolder holder) {
}
public void surfaceDestroyed(SurfaceHolder holder) {
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
this.w = w;
this.h = h;
}
}
整个程序源代码: https://github.com/zhouyang209117/AndroidTutorial/tree/master/OpenGL/EGLHelloWorld
参考资料
- Sayed Y, Hashimi, Satya Komatineni. Pro Android. Apress. pp325-362. 2009.
- (美)Kevin Brothaler著, 刘力平,苏统华译. OpenGL ES应用开发实践指南 android卷. 机械工业出版社. pp1-26. 2014.
- Aaftab Munshi, Dan Ginsburg, Dave Shreiner. OpenGL ES 2.0 Programming Guide. addison wesley. pp35-56