这是我参加8月更文挑战的次日.GLSurfaceView是Android端使用OpenGL es绘图的重要组件,若是咱们理解了它的源码,咱们就能更加深刻的理解OpenGL es.git
咱们平时在使用GLSurfaceView时,最主要用到的两个方法就是setEGLContextClientVersion和setRenderer,前者是设置OpenGL es的版本,主要的绘制工做都是在第二个方法里实现的,因此咱们主要看一下setRenderer方法.github
public void setRenderer(Renderer renderer) {
checkRenderThreadState();
if (mEGLConfigChooser == null) {
mEGLConfigChooser = new SimpleEGLConfigChooser(true);
}
if (mEGLContextFactory == null) {
mEGLContextFactory = new DefaultContextFactory();
}
if (mEGLWindowSurfaceFactory == null) {
mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();
}
mRenderer = renderer;
mGLThread = new GLThread(mThisWeakRef);
mGLThread.start();
}
复制代码
这个方法比较简短,主要涉及到了三个对象,分别是:mEGLConfigChooser,mEGLContextFactory,mEGLWindowSurfaceFactory.markdown
mEGLConfigChooser是用于在EGLHelper中的start方法(下文会提到)生成EGLConfig对象以及指定OpenGL颜色和深度.app
mEGLContextFactory也是用在EGLHelper的start方法中生成EGLContext,提供EGLContext的建立和销毁的方法.oop
mEGLWindowSurfaceFactory用于在EGLHelper的createSurface方法中生成EGLSurface,一样提供了EGLSurface的建立和销毁方法.this
EGLDisplay是表明实际显示设备的类,EGLSurface是用于存储图像信息的类.基于这两个类GLSurfaceView才能实现双缓冲机制.spa
setRenderer方法最后生成了一个GLThread对象而且启动了该对象,咱们进入这个类能够看见这是它集成了Thread,因此咱们就着重看它的run方法.3d
public void run() {
setName("GLThread " + getId());
if (LOG_THREADS) {
Log.i("GLThread", "starting tid=" + getId());
}
try {
guardedRun();
} catch (InterruptedException e) {
// fall thru and exit normally
} finally {
sGLThreadManager.threadExiting(this);
}
}
复制代码
其中最主要的也就是guardedRun()方法,这个方法比较长,就关注一些主要的代码就好.code
private void guardedRun() throws InterruptedException{
mEGLHlper = new EglHelper(mGLSurfaceViewWeakRef);
//...省略一堆变量的定义
while(true) {
//...省略一堆条件判断
if (readyToDraw()){ //准备好开始渲染
mEglHelper.start();
}
if (createGLInterface) {
gl = (GL10) mEglHelper.createGL();
}
if (createEglContext) {
GLSurfaceView view = mGLSurfaceViewWeakRef.get();
view.mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
}
if (sizeChanged) {
GLSurfaceView view = mGLSurfaceViewWeakRef.get();
view.mRenderer.onSurfaceChanged(gl, w, h);
}
{
GLSurfaceView view = mGLSurfaceViewWeakRef.get();
view.mRenderer.onDrawFrame(gl);
}
int swapError = mEglHelper.swap();
}
}
复制代码
能够看见咱们平时在自定义Renderer的时候实现的三个方法都是在这里调用的,除了这一点咱们还须要关注的是mEGLHelper这个对象,从上面这些代码咱们能够看见mEGLHelper的使用是贯穿整个GLSurfaceView的,因此咱们还须要看看mEGLHelper的代码orm
public void start(){
mEgl = (EGL10) EGLContext.getEGL();
mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
mEgl.eglInitialize(mEglDisplay, version)
GLSurfaceView view = mGLSurfaceViewWeakRef.get();
mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig)
}
复制代码
在start的方法中进行了一些初始化操做,实例化了EGL,EGLConfig和EGLContext,初始化了EGL,还生成了EGLDisplay.
public boolean createSurface() {
GLSurfaceView view = mGLSurfaceViewWeakRef.get();
mEglSurface = view.mEGLWindowSurfaceFactory.createWindowSurface(mEgl,
mEglDisplay, mEglConfig, view.getHolder());
}
复制代码
createSurface方法用于建立EGLSurface对象.
GL createGL() {
GL gl = mEglContext.getGL();
GLSurfaceView view = mGLSurfaceViewWeakRef.get();
if (view != null) {
if (view.mGLWrapper != null) {
gl = view.mGLWrapper.wrap(gl);
}
}
return gl;
}
复制代码
createGL主要用于建立GL对象,GL对象在自定义Render实现的三个方法的参数里都有用到.
public int swap() {
if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
return mEgl.eglGetError();
}
return EGL10.EGL_SUCCESS;
}
复制代码
swap方法调用了native方法来交换EGLDisplay和EGLSurface的数据.
通过以上分析,咱们就能指定GLSurface建立渲染的大部分流程,经过模仿这些代码咱们就能够使用自定义载体来进行OpenGL的渲染,好比说TextureView等等.下面这张图就是GLSurface建立渲染过程当中涉及到的主要的类和方法: