GLSurface源码小探 | 8月更文挑战

1.背景介绍

这是我参加8月更文挑战的次日.GLSurfaceView是Android端使用OpenGL es绘图的重要组件,若是咱们理解了它的源码,咱们就能更加深刻的理解OpenGL es.git

2.代码分析

2.1.入口

咱们平时在使用GLSurfaceView时,最主要用到的两个方法就是setEGLContextClientVersionsetRenderer,前者是设置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也是用在EGLHelperstart方法中生成EGLContext,提供EGLContext的建立和销毁的方法.oop

mEGLWindowSurfaceFactory用于在EGLHelpercreateSurface方法中生成EGLSurface,一样提供了EGLSurface的建立和销毁方法.this

EGLDisplay是表明实际显示设备的类,EGLSurface是用于存储图像信息的类.基于这两个类GLSurfaceView才能实现双缓冲机制.spa

2.2.GLThread的分析

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

2.3.EGLHelper

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,EGLConfigEGLContext,初始化了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的数据.

3.总结

通过以上分析,咱们就能指定GLSurface建立渲染的大部分流程,经过模仿这些代码咱们就能够使用自定义载体来进行OpenGL的渲染,好比说TextureView等等.下面这张图就是GLSurface建立渲染过程当中涉及到的主要的类和方法: GLSurface渲染

4.参考资料

音视频开发之旅(十) GLSurfaceView源码解析&EGL环境

相关文章
相关标签/搜索