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環境

相關文章
相關標籤/搜索