应用程序的渲染方式分为两种

  1. 按需渲染: 绝大多数应用程序,比如微信/钉钉/QQ,都是这种,当有数据更新才请求重新刷新绘制界面
  2. 定频渲染:比如游戏,永远按照固定的频率进行渲染(只有这样,才能模拟出逼真的动画效果)

在android 中,上述两个场景分别用以下两个类

  1. SurfaceView(按需渲染):直接在UI线程进行渲染,效率低,适用于渲染频率低的应用场景。
  2. GLSurfaceView(定频渲染):开启一个独立的opengl线程来进行渲染(防止UI线程被阻塞),每个GLSurfaceView的实例都有一个 GLThread mGLThread 成员

无论是java/C++, opengl绘制流程都一样:

  1. 初始化 egl 参数
  2. 在一个循环中不断进行帧绘制

类的大体定义如下

public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback2
{
    private GLThread mGLThread;  //独立的opengl线程进行渲染
    private Renderer mRenderer;  //自定义的Renderer, 这个Render定义了如何进行渲染
    ........
    public void setRenderer(Renderer renderer)
    {
        .........
        mRenderer = renderer;
        mGLThread = new GLThread(mThisWeakRef);
        mGLThread.start();  //启动opengl线程
    }
    public void queueEvent(Runnable r) {
        mGLThread.queueEvent(r);
    }
    .........
}


public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCallback {
    SurfaceControl mSurfaceControl;  // 与android系统的的surfacefinger服务进行binder通讯
     public void draw(Canvas canvas){
        .....
        super.draw(canvas);
     }
}
static class GLThread extends Thread {
    @Override
    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);
        }
    }

    private void guardedRun() throws InterruptedException 
    {
        .............
        Runnable event = null;
        while(true){
             synchronized (sGLThreadManager) {
                while (true) {
                    if (mShouldExit) {
                        return;
                    }

                    //pop 一个 event
                    if (! mEventQueue.isEmpty()) {
                        event = mEventQueue.remove(0);
                        break;
                    }

                    if (event != null) {
                        event.run();    // 执行event
                        event = null;
                        continue;
                    }

                    ...........
                    // 初始化egl
                    mEglHelper.createGL();

                    ...........
                    //onSurfaceCreated
                    mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);

                    if(sizeChanged)  //如果view大小发生了变化
                    {
                        //onSurfaceChanged
                        mRenderer.onSurfaceChanged(gl, w, h);
                    }
                   
                   //绘制
                   mRenderer.onDrawFrame(gl);

                   ...........
                }
             }
        }
    }
}

自定义Render类

public class MyRender implements GLSurfaceView.Renderer {

    private int m_vbo
    private int m_textureId;
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        //初始化vbo,纹理 ,sharder 等
        Log.d(TAG, "onSurfaceCreated");
        GLES30.glClearColor(1.0f,0.0f,0.0f,1.0f);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        Log.d(TAG, "onSurfaceChanged");
        GLES30.glViewport(0,0, width, height);
    }

    //调用 native 层的opengl库进行渲染
    @Override
    public void onDrawFrame(GL10 gl) {
        GLES30.glClearColor(0.0f,0.0f,0.0f,1.0f);
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);

        GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, m_textureId);
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, m_vbo);
        ..............
    }
}

总结:GLSurfaceView 开启了独立的线程中进行opengl渲染,用Render类来定义具体如何渲染,在需要实时渲染的场景使用:比如 游戏,VR, 车载环视系统等。