Android GLSurfaceView详解

学习在Android中使用OpenGL ES,就不得不提到一个控件:GLSurfaceView

GLSurfaceView从Android 1.5(API level 3)开始加入,继承自SurfaceView,实现了SurfaceHolder.Callback2接口,拥有SurfaceView的全部特性,也有view所有的功能和属性,特别是处理事件的能力,它主要是在SurfaceView的基础上它加入了EGL的管理,并自带了一个GLThread绘制线程(EGLContext创建GL环境所在线程即为GL线程),绘制的工作直接通过OpenGL在绘制线程进行,不会阻塞主线程,绘制的结果输出到SurfaceView所提供的Surface上,这使得GLSurfaceView也拥有了OpenGlES所提供的图形处理能力,通过它定义的Render接口,使更改具体的Render的行为非常灵活性,只需要将实现了渲染函数的Renderer的实现类设置给GLSurfaceView即可。

GLSurfaceView提供了下列特性:
    1>  提供并且管理一个独立的Surface
    2>  提供并且管理一个EGL display,它能让opengl把内容渲染到上述的Surface上。
    3>  支持用户自定义渲染器(Render),通过setRenderer设置一个自定义的Renderer
    4>  让渲染器在独立的GLThread线程里运作,和UI线程分离。
    5>  支持按需渲染(on-demand)和连续渲染(continuous)两种模式。
    6>  GPU加速:GLSurfaceView的效率是SurfaceView的30倍以上,SurfaceView使用画布进行绘制,GLSurfaceView利用GPU加速提高了绘制效率。
    7>  View的绘制onDraw(Canvas canvas)使用Skia渲染引擎渲染,而GLSurfaceView的渲染器RendereronDrawFrame(GL10 gl)使用opengl绘制引擎进行渲染


2.GLSurfaceView的使用步骤

开发基于GLSurfaceView的程序,通常需要继承GLSurfaceView,并重载一些和用户输入事件有关的方法,如果你不需监听事件,也可以直接使用GLSurfaceView, 你可以使用set方法来修改默认的属性,例如setRenderer(Renderer)设置渲染器,主要的工作就是设置Renderer,其他过程,例如EGL的创建,Surface的分配以及OpenGLES的调用都被隐藏起来了,GLSurfaceView会启动一个工作线程来完成渲染,避免阻塞UI主线程,这个工作线程就是mGLThread,这个线程在应用程序setRederer的时候启动,然后不停地等待和处理事件,同时还负责开展Render工作。

第一步:创建GLSurfaceView

GLSurfaceView也是View,可以通过布局文件的方式将它加入整棵view树中,或者在java代码中创建并且添加。
在布局中,摆布好GLSurfaceView的位置.如下:
.opengl.GLSurfaceView
        android:id="@+id/glv_main"
        android:layout_width="match_parent"
        android:layout_height= "200dp"  />

在Activity中实例化,如下:
@Override
protected  void  onCreate (Bundle savedInstanceState){
    GLSurfaceView glv  = (GLSurfaceView)findViewById(R.id.glv_main);
}

第二步:初始化OpenGLES环境

GLSurfaceView默认情况下已经初始化好了OpenGLES的运行环境,不需要做额外的工作就可以使用,当然也可以更改一些默认的设置。

第三步:设置Renderer
渲染是OpenGLES的核心工作,setRenderer可以将用户自定义的一个 Renderer 加入实际的渲染流程中。
public class GLRender implements GLSurfaceView.Renderer{

    //控制旋转的角度
    private float rotate;

    @Override
    public void onSurfaceCreated(GL10 gl,  EGLConfig config) {
        //关闭抗抖动
        gl.glDisable(GL10.GL_DITHER);
        //设置系统对透视进行修正
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
        gl .glClearColor ( 0 ,  0 ,  0 ,  0 ) ;
        //设置阴影平滑模式
        gl.glShadeModel(GL10.GL_SMOOTH);
        //启动深度测试
        gl.glEnable(GL10.GL_DEPTH_TEST);
        //设置深度测试的类型
        gl.glDepthFunc(GL10.GL_LEQUAL);

    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        //设置3D视窗的大小及位置
        gl .glViewport ( 0 ,  0 , width, height) ;
        //将当前矩阵模式设为投影矩形
        gl.glMatrixMode(GL10.GL_PROJECTION);
        //初始化单位矩阵
        gl.glLoadIdentity();
        //计算透视窗口的宽度高度比
        float ratio = (float) width / height;
        //调用此方法设置透视窗口的空间大小
        gl .glFrustumf (-ratio, ratio, - 1 ,  1 ,  1 ,  10 ) ;
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        //清除屏幕缓存和深度缓存
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        //启用顶点坐标数据
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        //启用顶点颜色数据
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
        //设置当前矩阵堆栈为模型堆栈
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        //------绘制第一个图形-----
        //重置当前的模型视图矩阵
        gl.glLoadIdentity();
        gl.glTranslatef(0.95f, -0.8f, -1.5f); //1⃣
        //设置顶点位置数据
        gl .glVertexPointer ( 3 , GL10 .GL _FLOAT,  0 , PointData .floatBufferUtil (PointData .triangleData )) ;
        //设置顶点颜色数据
        gl .glColorPointer ( 4 , GL10 .GL _FIXED,  0 , PointData .intBufferUtil (PointData .triangleColor )) ;
        //根据顶点数据绘制平面图形
        gl .glDrawArrays (GL10 .GL _TRIANGLES,  0 ,  3 ) ;

        //-----绘制第二个图形-----
        //重置当前的模型视图矩阵
        gl.glLoadIdentity();
        gl .glTranslatef ( 0.95 f,  0.8 f, - 1.5 f) ;
        //设置顶点位置数据
        gl .glVertexPointer ( 3 , GL10 .GL _FLOAT,  0 , PointData .floatBufferUtil (PointData .rectData )) ;
        //设置顶点颜色数据
        gl .glColorPointer ( 4 , GL10 .GL _FIXED,  0 , PointData .intBufferUtil (PointData .rectColor )) ;
        //更具顶点数据绘制平面图形
        gl .glDrawArrays (GL10 .GL _TRIANGLE_STRIP,  0 ,  4 ) ;

        //-----绘制第三个图形----
        //重置当前的模型视图矩阵
        gl.glLoadIdentity();
        gl .glTranslatef (- 0.95 f,  0.8 f, - 1.5 f) ;
        //设置顶点位置数据
        gl .glVertexPointer ( 3 , GL10 .GL _FLOAT,  0 , PointData .floatBufferUtil (PointData .rectData 2)) ;
        //根据顶点数据绘制平面图形
        gl .glDrawArrays (GL10 .GL _TRIANGLE_STRIP,  0 ,  4 ) ;

        //-----绘制第四个图形-----
        //重置当前的模型视图矩阵
        gl.glLoadIdentity();
        gl.glTranslatef(-0.95f, -0.8f, -1.5f);
        //设置使用纯色填充 **需要注意: 使用纯色填充需要禁用顶点颜色数组
        gl .glColor 4f( 1.0 f,  0.2 f,  0.2 f,  0.0 f) ;
        gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
        //设置顶点位置数据
        gl .glVertexPointer ( 3 , GL10 .GL _FLOAT,  0 , PointData .floatBufferUtil (PointData .pentacle )) ;
        //根据顶点数据绘制图形
        gl .glDrawArrays (GL10 .GL _TRIANGLE_STRIP,  0 ,  5 ) ;

        //----绘制第五个图形---
        //重置当前的模型视图矩阵
        gl.glLoadIdentity();
        gl .glTranslatef ( 0 f,  0 f, - 1.5 f) ;
        gl .glRotatef (rotate,  0 f,  0.2 f,  0 f) ;
        //设置顶点位置数据
        gl .glVertexPointer ( 3 , GL10 .GL _FLOAT,  0 , PointData .floatBufferUtil (TDPointData .taperVertices )) ;
        //启用顶点颜色组
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
        //设置顶点颜色数据
        gl .glColorPointer ( 4 , GL10 .GL _FIXED,  0 , PointData .intBufferUtil (TDPointData .taperColors )) ;
        //按taperFacetsBuffer指定的面绘制三角形
        ByteBuffer byteBuffer = PointData.byteBufferUtil(TDPointData.taperFacets);
        gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, byteBuffer.remaining(), GL10.GL_UNSIGNED_BYTE, byteBuffer);


        //绘制结束
        gl.glFinish();
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        //旋转角度+1
        rotate +=  1 ;
    }
}

@Override
protected  void  onCreate (Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_glsurface);
    glv = (GLSurfaceView)findViewById(R.id.glv_opengl);
    GLRender render =  new  GLRender();
    glv.setRenderer(render);
}

第四步:设置RenderingMode

GLSurfaceView 在onAttachedToWindow后就启动了一个无线循环的 GLThread 线程, GLSurfaceView默认采用的是 RENDERMODE_CONTINUOUSLY 连续渲染的方式, 刷新的帧率是60FPS,16ms就重绘一次, 可以通过 mGLView.setRenderMode()更改其渲染方式为 RENDERMODE_WHEN_DIRTY,表示被动渲染,在 surfaceCreate的时候会绘制一次,之后 只有在调用requestRender或者onResume等方法 主动请求重绘 时才会进行渲染, 如果你的界面不需要频繁的刷新最好使用 RENDERMODE_WHEN_DIRTY ,这样可以降低CPU和GPU的活动

第五步:状态处理

使用GLSurfaceView需要注意程序的生命周期, Activity及Fragment 会有暂停和恢复等状态,GLSurfaceView也需根据这些状态来做相应的处理, GLSurfaceView具有onResume和onPause两个同Activity及Fragment中的生命周期同名的方法,在Activity或者Fragment中的onResume和onPause方法中,需要主动调用GLSurfaceView的实例的这两个方法 ,这样能使OpenGLES的内部线程做出正确的判断,从而保证应用程序的稳定性。

第六部:事件处理
为了处理事件,一般都是继承GLSurfaceView类并重载它的事件方法,但是由于GLSurfaceView是多线程的,渲染器在独立的渲染线程里,你应该使用Java的跨线程机制跟渲染器通讯,GLSurfaceView提供的queueEvent(Runnable)方法就是一种相对简单的操作,queueEvent()方法被安全地用于在UI线程和渲染线程之间进行交流通信
public void queueEvent(Runnable r) {
    mGLThread.queueEvent(r);
}

这里直接调用 GLThread的 queueEvent(Runnable r)方法 GLThread的 mEventQueue 队列中添加 Runnable 
     public void queueEvent(Runnable r) {  
      
         synchronized(sGLThreadManager) {  
             mEventQueue.add(r);  
             sGLThreadManager.notifyAll();  
         }  
       
     }  

GLThread的guardenRun()方法中有如下代码:
  1. if (! mEventQueue.isEmpty()) {  
  2.     event = mEventQueue.remove(0);  
  3.     break;  
  4. }  
  5.                   
  6. ...  
  7.                   
  8. if (event != null) {  
  9.     event.run();  
  10.     event = null;  
  11.     continue;  
  12. }  
一般事件的使用如下:
  1. class MyGLSurfaceView extends GLSurfaceView {    
  2.     private MyRenderer mMyRenderer;    
  3.     
  4.     public boolean onKeyDown(int keyCode, KeyEvent event) {    
  5.     
  6.        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {    
  7.            queueEvent(new Runnable() {    
  8.               // 这个方法会在渲染线程里被调用    
  9.               public void run() {    
  10.                     mMyRenderer.handleDpadCenter();    
  11.            }});    
  12.            return true;    
  13.        }    
  14.     
  15.        return super.onKeyDown(keyCode, event);    
  16.    }    

  17.    public boolean onTouchEvent(final MotionEvent event) {
  18.             queueEvent(new Runnable(){
  19.                public void run() {
  20.                 mRenderer.setColor(event.getX() / getWidth(),
  21.                         event.getY() / getHeight(), 1.0f);
  22.             }});
  23.             return true;
  24.          }    
  25. }    
如果在UI线程里调用渲染器的方法,因为UI事件和渲染绘制是在不同的线程里,会收到“call to OpenGL ES API with no current context”的警告,典型的案例就是在键盘或触摸事件方法里直接调用opengl es的API。

GLSurfaceView源码分析
GLSurfaceView中对于GL环境的操作,除queueEvent是将事件放入队列中然后到GL线程中执行外, 其他方法基本都是在主线程中修改某个状态值(某个属性属性),然后调用 sGLThreadManager.notifyAll() 取消GL线程的等待, 在GL线程中根据属性的状态值作不同的操作,并在操作后反馈给主线程,当然有的方法也不需要反馈。
相关类图如下,GLSurfaceView中的EglHelper和GLThread分别实现了上面提到的管理EGL环境和渲染线程的工作,GLSurfaceView的使用者需要实现Renderer接口。

渲染的整体步骤如下:

  • 获取EGLDisplay对象,初始化与EGLDisplay 之间的连接
  • 获取EGLConfig对象
  • 创建EGLContext 实例
  • 创建EGLSurface实例
  • 连接EGLContext和EGLSurface.
  • 是否需要重新申请EGLSurface,如果尺寸发生了变化,此时createEGLSurface为true
  • 是否需要申请GLObject,此时createGLinterface为true
  • 是否需要生成EGLContext,此时createEGLContext为true
  • 尺寸是否变化,sizeChanged为true,此时需要通知观察者
  • 一切准备好之后,使用GL指令绘制图形,调用view.mRenderer.onDrawFrame进行真正的渲染
  • 最后通过swap把渲染结果显示到屏幕
  • 断开并释放与EGLSurface关联的EGLContext对象
  • 删除EGLSurface对象
  • 删除EGLContext对象
  • 终止与EGLDisplay之间的连接
Android GLSurfaceView详解_第1张图片
public  class  GLSurfaceView  extends  SurfaceView  implements  SurfaceHolder . Callback2  {

     public  final  static  int  RENDERMODE_WHEN_DIRTY =  0 ;//按需渲染模式
     public  final  static  int  RENDERMODE_CONTINUOUSLY =  1 ;//连续渲染模式

    private static final   GLThreadManager   sGLThreadManager   =   new   GLThreadManager() ;

    private final   WeakReference   mThisWeakRef   new   WeakReference( this ) ;
    private   GLThread   mGLThread ;
    private   Renderer   mRenderer ;
    private boolean   mDetached ;
    private   EGLConfigChooser   mEGLConfigChooser ;
    private   EGLContextFactory   mEGLContextFactory ;
    private   EGLWindowSurfaceFactory   mEGLWindowSurfaceFactory ;
    private int   mDebugFlags ;
    private int   mEGLContextClientVersion ;
    private boolean   mPreserveEGLContextOnPause ;

     public  GLSurfaceView (Context context) {
         super (context);
        init();
    }

     public  GLSurfaceView (Context context, AttributeSet attrs) {
         super (context, attrs);
        init();
    }

     //调试用的
     public  void  setDebugFlags ( int  debugFlags);
     public  int  getDebugFlags ();

     //设置暂停的时候是否保持EglContext
     public  void  setPreserveEGLContextOnPause ( boolean  preserveOnPause);
     public  boolean  getPreserveEGLContextOnPause ();

     //设置渲染器,这个非常重要,渲染工作就依靠渲染器了
     //调用此方法会开启一个新的线程,即GL线程
     public  void  setRenderer (Renderer renderer) {
        checkRenderThreadState();//检查渲染线程是否已经创建了,如果已经创建了就抛出异常
         if  (mEGLConfigChooser ==  null ) {
            mEGLConfigChooser =  new  SimpleEGLConfigChooser( true );//默认的设置EglConfig的方法
        }
         if  (mEGLContextFactory ==  null ) {
            mEGLContextFactory =  new  DefaultContextFactory();//默认的EGLContext工厂
        }
         if  (mEGLWindowSurfaceFactory ==  null ) {
            mEGLWindowSurfaceFactory =  new  DefaultWindowSurfaceFactory();//默认的EGLSurface工厂
        }
        mRenderer = renderer;
        mGLThread =  new  GLThread(mThisWeakRef);
        mGLThread.start();
    }

     //设置EGLContext工厂,不设置就用默认的
     public  void  setEGLContextFactory (EGLContextFactory factory){
    checkRenderThreadState() ;
     mEGLContextFactory   = factory ;
    }

     //设置EGLSurface工厂,不设置就用默认的
     public  void  setEGLWindowSurfaceFactory (EGLWindowSurfaceFactory factory){
    checkRenderThreadState() ;
       mEGLWindowSurfaceFactory   = factory ;
    }
     //设置EglConfig,一般颜色深度等等,利用此方法设置。不设置就用默认的
     public  void  setEGLConfigChooser (EGLConfigChooser configChooser){
    checkRenderThreadState() ;
     mEGLConfigChooser   = configChooser ;
    }

     //内部调用setEGLConfigChooser
     public  void  setEGLConfigChooser ( boolean  needDepth){
    setEGLConfigChooser( new   SimpleEGLConfigChooser(needDepth)) ;
    }

     //内部调用setEGLConfigChooser
     public  void  setEGLConfigChooser ( int  redSize,  int  greenSize,  int  blueSize,
             int  alphaSize,  int  depthSize,  int  stencilSize){
    setEGLConfigChooser( new   ComponentSizeChooser(redSize ,   greenSize ,
blueSize ,   alphaSize ,   depthSize ,   stencilSize)) ;
    }

     //设置EGLContextVersion,比如2,即OpenGLES2.0
     public  void  setEGLContextClientVersion ( int  version){
     checkRenderThreadState() ;
       mEGLContextClientVersion   = version ;
    }

     //设置渲染方式,有RENDERMODE_CONTINUOUSLY表示不断渲染
     //以及RENDERMODE_WHEN_DIRTY表示在需要的时候才会渲染
     //渲染的时候调用requestRender必须在setRenderer后
     public  void  setRenderMode ( int  renderMode){
     mGLThread .setRenderMode(renderMode) ;
    }

     public  int  getRenderMode (){
     return   mGLThread .getRenderMode() ;
    }

     //主动请求渲染
     public  void  requestRender (){
       mGLThread .requestRender() ;
    }


     public  void  surfaceCreated (SurfaceHolder holder){
     mGLThread .surfaceCreated() ;
    }

     public  void  surfaceDestroyed (SurfaceHolder holder){
       mGLThread .surfaceDestroyed() ;
    }

     public  void  surfaceChanged (SurfaceHolder holder,  int  format,  int  w,  int  h){
     mGLThread .onWindowResize(w ,   h) ;
    }

     @Override
     public  void  surfaceRedrawNeeded (SurfaceHolder holder) {
         if  (mGLThread !=  null ) {
            mGLThread.requestRenderAndWait();
        }
    }

     //生命周期,一般在Activity、Fragment的onPause中调用
     public  void  onPause (){
       mGLThread .onPause() ;
    }

     //生命周期,一般在Activity、Fragment的onResume中调用
     public  void  onResume (){
       mGLThread .onResume() ;
    }

     //向GL线程发送一个任务
     public  void  queueEvent (Runnable r){
     mGLThread .queueEvent(r) ;
    }

     //附加到Window上时被调用,外部不可调用
     protected  void  onAttachedToWindow (){
     super .onAttachedToWindow() ;
     if   ( mDetached   && ( mRenderer   !=   null )) {
     int   renderMode =   RENDERMODE_CONTINUOUSLY ;
    if   ( mGLThread   !=   null ) {
    renderMode =   mGLThread .getRenderMode() ;
     }
     mGLThread   =   new   GLThread( mThisWeakRef ) ;
    if   (renderMode !=   RENDERMODE_CONTINUOUSLY ) {
     mGLThread .setRenderMode(renderMode) ;
     }
     mGLThread .start() ;
     }
     mDetached   =   false;
    }

      //从Window上被移除时调用,外部不可调用
     protected  void  onDetachedFromWindow (){
     if   ( mGLThread   !=   null ) {
     mGLThread .requestExitAndWait() ;
     }
     mDetached   =   true;
    super .onDetachedFromWindow() ;
    }

     //渲染器接口
     public  interface  Renderer  {

         //Surface被创建时被调用,通常在此进行渲染的初始化
         void  onSurfaceCreated(GL10 gl, EGLConfig config);

         //Surface大小被改变时被调用
         void  onSurfaceChanged(GL10 gl,  int  width,  int  height);

         //执行渲染时被调用,以完成用户渲染工作
         void  onDrawFrame(GL10 gl);

    }

     //非常重要的一个EGL帮助类,GL环境的建立依靠此类
     private  static  class  EglHelper  {
         public  EglHelper (WeakReference glSurfaceViewWeakRef) {
            mGLSurfaceViewWeakRef = glSurfaceViewWeakRef;
        }

         //EGL的初始化,可以参考此方法
         public  void  start () {
           
             /*
             * Get an EGL instance
             */
            mEgl = (EGL10) EGLContext.getEGL();

             /*
             * Get to the default display.
             */
            mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);

             if  (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
                 throw  new  RuntimeException( "eglGetDisplay failed" );
            }

             /*
             * We can now initialize EGL for that display
             */
             int [] version =  new  int [ 2 ];
             if (!mEgl.eglInitialize(mEglDisplay, version)) {
                 throw  new  RuntimeException( "eglInitialize failed" );
            }
            GLSurfaceView view = mGLSurfaceViewWeakRef.get();
             if  (view ==  null ) {
                mEglConfig =  null ;
                mEglContext =  null ;
            }  else  {
                mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);

                 /*
                * Create an EGL context. We want to do this as rarely as we can, because an
                * EGL context is a somewhat heavy object.
                */
                mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);
            }
             if  (mEglContext ==  null  || mEglContext == EGL10.EGL_NO_CONTEXT) {
                mEglContext =  null ;
                throwEglException("createContext");
            }
             if  (LOG_EGL) {
                Log.w( "EglHelper" ,  "createContext "  + mEglContext +  " tid="  + Thread.currentThread().getId());
            }

            mEglSurface =  null ;
        }

         //创建EGLSurface,使GL的渲染,能够渲染到用户指定的Surface
         //默认的Surface就是SurfaceHolder的Surface
         public  boolean  createSurface () {
             
             /*
             * Check preconditions.
             */
             if  (mEgl ==  null ) {
                 throw  new  RuntimeException( "egl not initialized" );
            }
             if  (mEglDisplay ==  null ) {
                 throw  new  RuntimeException( "eglDisplay not initialized" );
            }
             if  (mEglConfig ==  null ) {
                 throw  new  RuntimeException( "mEglConfig not initialized" );
            }

             /*
             *  The window size has changed, so we need to create a new
             *  surface.
             */
            destroySurfaceImp();

             /*
             * Create an EGL surface we can render into.
             */
            GLSurfaceView view = mGLSurfaceViewWeakRef.get();
             if  (view !=  null ) {
                mEglSurface = view.mEGLWindowSurfaceFactory.createWindowSurface(mEgl,
                        mEglDisplay, mEglConfig, view.getHolder());
            }  else  {
                mEglSurface =  null ;
            }

             if  (mEglSurface ==  null  || mEglSurface == EGL10.EGL_NO_SURFACE) {
                 int  error = mEgl.eglGetError();
                 if  (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
                    Log.e( "EglHelper" ,  "createWindowSurface returned EGL_BAD_NATIVE_WINDOW." );
                }
                 return  false ;
            }

             /*
             * Before we can issue GL commands, we need to make sure
             * the context is current and bound to a surface.
             */
             if  (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
                 /*
                 * Could not make the context current, probably because the underlying
                 * SurfaceView surface has been destroyed.
                 */
                logEglErrorAsWarning( "EGLHelper" ,  "eglMakeCurrent" , mEgl.eglGetError());
                 return  false ;
            }

             return  true ;
        }

         //通过EGL得到GL,然后用户设置了Wrapper的话会给得到的GL做个包装
         //同时也会解析一下用户的Debug意图,看看要不要debug
        GL createGL(){

        GL gl = mEglContext.getGL();
         GLSurfaceView view =   mGLSurfaceViewWeakRef .get() ;
        if   (view !=   null ) {
         if   (view.mGLWrapper !=   null ) {
        gl = view.mGLWrapper.wrap(gl) ;
         }

         if   ((view.mDebugFlags & ( DEBUG_CHECK_GL_ERROR   |   DEBUG_LOG_GL_CALLS )) !=   0 ) {
         int   configFlags =   0 ;
          Writer log =   null;
        if   ((view.mDebugFlags &   DEBUG_CHECK_GL_ERROR ) !=   0 ) {
        configFlags |= GLDebugHelper. CONFIG_CHECK_GL_ERROR ;
         }
         if   ((view.mDebugFlags &   DEBUG_LOG_GL_CALLS ) !=   0 ) {
        log =   new   LogWriter() ;
         }
        gl = GLDebugHelper. wrap (gl ,   configFlags ,   log) ;
         }
        }
          return   gl ;
        }

         //绘制完成之后,调用此方法,将绘制的内容输出到前台,让用户可以看到
         public  int  swap (){
         if   (!   mEgl .eglSwapBuffers( mEglDisplay ,   mEglSurface )) {
         return   mEgl .eglGetError() ;
         }
         return   EGL10. EGL_SUCCESS ;
        }

         //销毁Surface的方法,具体实现在destroySurfaceImp方法中       
        public void destroySurface() {  
            destroySurfaceImp() ;
        }

        private void   destroySurfaceImp () {
            if   ( mEglSurface   !=   null   &&   mEglSurface   != EGL10. EGL_NO_SURFACE ) {
                mEgl .eglMakeCurrent( mEglDisplay ,   EGL10. EGL_NO_SURFACE ,
                EGL10. EGL_NO_SURFACE ,
                EGL10. EGL_NO_CONTEXT ) ;
                GLSurfaceView view =   mGLSurfaceViewWeakRef .get() ;
                if   (view !=   null ) {
                    view.mEGLWindowSurfaceFactory.destroySurface( mEgl ,   mEglDisplay ,   mEglSurface ) ;
                }
                mEglSurface   =   null;
            }
        }
        //销毁GL环境
        public void   finish () {
            if   ( mEglContext   !=   null ) {
                GLSurfaceView view =   mGLSurfaceViewWeakRef .get() ;
                if   (view !=   null ) {
                    view.mEGLContextFactory.destroyContext( mEgl ,   mEglDisplay ,   mEglContext ) ;
                }
                mEglContext   =   null;
            }
            if   ( mEglDisplay   !=   null ) {
                mEgl .eglTerminate( mEglDisplay ) ;
                mEglDisplay   =   null;
            }
        }
    }
----------------------------------------------------------------------------------------------
     //GL线程,此类中存在的方法在GLSurfaceView中都有同名的, 都是提供给GLSurfaceView作为真正的实现调用
     static  class GLThread extends Thread {

    GLSurfaceView中对于GL环境的操作,除queueEvent是将事件放入队列中然后到GL线程中执行外,
    其他方法基本都是在主线程中修改某个状态值(下面的某个属性属性),然后调用sGLThreadManager.notifyAll()取消GL线程的等待,
    在GL线程中根据属性的状态值作不同的操作,并在操作后反馈给主线程,当然有的方法也不需要反馈。
         
        private boolean mShouldExit;
        private boolean   mExited ;
        private boolean   mRequestPaused ;
        private boolean   mPaused ;
        private boolean   mHasSurface ;
        private boolean   mSurfaceIsBad ;
        private boolean   mWaitingForSurface ;
        private boolean   mHaveEglContext ;
        private boolean   mHaveEglSurface ;
        private boolean   mFinishedCreatingEglSurface ;
        private boolean   mShouldReleaseEglContext ;
        private int   mWidth ;
        private int   mHeight ;
        private int   mRenderMode ;
        private boolean   mRequestRender ;
        private boolean   mWantRenderNotification ;
        private boolean   mRenderComplete ;
        private   ArrayList   mEventQueue   =   new   ArrayList() ;
        private boolean   mSizeChanged   =   true;

        // End of member variables protected by the sGLThreadManager monitor.
        private   EglHelper   mEglHelper ;

        private   WeakReference   mGLSurfaceViewWeakRef ;

        GLThread (WeakReference glSurfaceViewWeakRef) {
         super () ;
           mWidth   =   0 ;
         mHeight   =   0 ;
         mRequestRender   =   true;//开始需要刷新一次
         mRenderMode   =   RENDERMODE_CONTINUOUSLY ;//默认的渲染模式
         mWantRenderNotification   =   false;
         mGLSurfaceViewWeakRef   = glSurfaceViewWeakRef ;
        }

        
        @Override
        public void   run () {
        setName( "GLThread "   + getId()) ;
         try   {
        guardedRun() ;//处理所有渲染逻辑

         }   catch   (InterruptedException e) {
      
         }   finally   {
         sGLThreadManager .threadExiting( this ) ;
         }
        }

        

         //销毁EglSurface
         private  void  stopEglSurfaceLocked (){
         if   ( mHaveEglSurface ) {
         mHaveEglSurface   =   false;
         mEglHelper .destroySurface() ;
         }
        }

         //销毁EglContext
         private  void  stopEglContextLocked (){
         if   ( mHaveEglContext ) {
         mEglHelper .finish() ;
         mHaveEglContext   =   false;
         sGLThreadManager .releaseEglContextLocked( this ) ;
         }
        }

         // GLSurfaceView的核心就在这个方法里面, GL线程 渲染的主要逻辑 都在这个方法里面,这个方法比较复杂     
        第一步:判断事件队列是否为空,如果有事件需要处理,则直接跳出内循环去处理事件,否则依然在内循环运行
        第二步:1.判断是否需要释放EGLSurface,
                        2.判断是否丢失了Surface,mHasSurface表示当前有没有可用的Surface,mWaitingForSurface表示是否在申请Surface的过程中,
                        3.是否需要放弃EGLContext
        第三步:经过以上的判断之后,程序进入图形渲染前的准备工作,也就是readyToDraw之间的代码
        第四步:一旦程序执行到这里也就是跳出了内循环,有两种可能,第一是EventQueue中有需要处理的事件,第二是需要执行渲染工作
       private  void  guardedRun ()  throws  InterruptedException {
            mEglHelper =  new  EglHelper(mGLSurfaceViewWeakRef);//初始化EglHelper
            mHaveEglContext =  false ;
            mHaveEglSurface =  false ;
            mWantRenderNotification =  false ;

                     try  {
                GL10 gl =  null ;
                 boolean  createEglContext =  false ;
                         boolean  createEglSurface =  false ;
                         boolean  createGlInterface =  false ;
                 boolean  lostEglContext =  false ;
                         boolean  sizeChanged =  false ;
                         boolean  wantRenderNotification =  false ;
                 boolean  doRenderNotification =  false ;
                 boolean  askedToReleaseEglContext =  false ;
                         int  w =  0 ;
                         int  h =  0 ;
               Runnable event =  null ;

                 while  ( true ) {
                         synchronized  (sGLThreadManager) {
                         while  ( true ) {//死循环,除非主动跳出
                                 //外部请求退出GL线程
                             if  (mShouldExit) {
                                 return ;
                            }

                             /*外部请求在GL线程中处理的事件没有处理完时,就优先处理这些事件*/
                                     if  (! mEventQueue.isEmpty()) {
                                event = mEventQueue.remove( 0 );
                                          break ;
                            }

                                     //暂停和恢复状态变化时,onResume和onPause状态变化
                                     boolean  pausing =  false ;
                                     if  (mPaused != mRequestPaused) {
                                pausing = mRequestPaused;
                                mPaused = mRequestPaused;
                                         /*GLSurfaceView的onPause和onResume都会用wait方法等待GL线程的响应,这时候主线程阻塞。
                                    此处调用notifyAll通知onPause和onResume,放弃主线程的阻塞。
                                    GLSurfaceView中其他很多方法也存在wait方法,基本与此类似
                                */
                                sGLThreadManager.notifyAll();
                            }

                                     // 需要释放EglContext时候执行的工作
                                     if  (mShouldReleaseEglContext) {
                        
                                stopEglSurfaceLocked();
                                stopEglContextLocked();
                                mShouldReleaseEglContext =  false ;
                                askedToReleaseEglContext =  true ;
                            }

                                     // EglContext丢失时,销毁EglSurface和EglContext
                                     if  (lostEglContext) {
                                stopEglSurfaceLocked();
                                stopEglContextLocked();
                                lostEglContext =  false ;
                            }

                                     // 如果 acitivity 已经暂停, 接收了暂停信号,而且当前EglSurface存在时,销毁EglSurface
                                     if  (pausing && mHaveEglSurface) {
                                stopEglSurfaceLocked();
                            }

                                 /*接收了暂停信号,而且当前EglContext存在时,根据用户设置,来决定是否销毁EglContext*/
                                 if  (pausing && mHaveEglContext) {
                                GLSurfaceView view = mGLSurfaceViewWeakRef.get();
                                 boolean  preserveEglContextOnPause = view ==  null  ?  false  : view.mPreserveEGLContextOnPause;
                                         if  (!preserveEglContextOnPause) {
                                    stopEglContextLocked();
                                }
                          }

                                 /*Surface不存在而且当前并没有在等待Surface*/
                                 if  ((! mHasSurface) && (! mWaitingForSurface)) {
                                 if  (mHaveEglSurface) {
                                stopEglSurfaceLocked();
                            }
                            mWaitingForSurface =  true ;
                            mSurfaceIsBad =  false ;
                            sGLThreadManager.notifyAll();
                        }

                         // Surface存在,而且在等待Surface
                             if  (mHasSurface && mWaitingForSurface) {
                        
                            mWaitingForSurface =  false ;
                            sGLThreadManager.notifyAll();
                        }

                             if  (doRenderNotification) {
                       
                            mWantRenderNotification =  false ;
                            doRenderNotification =  false ;
                            mRenderComplete =  true ;
                            sGLThreadManager.notifyAll();
                        }

                        // 判断当前环境准备好了渲染执行,否则进入下一轮等待及判断
                            判断两个关键因素:EGLContext和EGLSurface是否存在并有效,如果没有EGLContext,就需要获取一个,
                            如果当前有EGLSurface但尺寸发生了变化,那么就需要销毁他并重新申请Surface。
                            可以渲染图形的条件是:
                            1.程序当前不处于pause状态, 2.已经成功获得Surface, 3.有合适的尺寸, 4.处于自动持续渲染状态或用户发起了渲染请求
                         if  (readyToDraw()) {

                             // 没有EglContext就需要借助EglHelper来创建EglContext
                             if  (! mHaveEglContext) {
                             if  (askedToReleaseEglContext) {
                                askedToReleaseEglContext =  false ;
                            }  else  {
                                 try  {
                                    mEglHelper.start();
                                }  catch  (RuntimeException t) {
                                    sGLThreadManager.releaseEglContextLocked( this );
                                     throw  t;
                                }
                                mHaveEglContext =  true ;
                                createEglContext =  true ;

                                sGLThreadManager.notifyAll();
                            }
                        }

                         /*有了EglContext,但是没有EglSurface,就需要设置一些状态,以便后续操作*/
                         if  (mHaveEglContext && !mHaveEglSurface) {
                            mHaveEglSurface =  true ;
                            createEglSurface =  true ;
                            createGlInterface =  true ;
                            sizeChanged =  true ;
                        }

                         /*有eglSurface时,需要判断是否需要执行surface sizechange*/
                         if  (mHaveEglSurface) {
                             if  (mSizeChanged) {
                                sizeChanged =  true ;
                                w = mWidth;
                                h = mHeight;
                                mWantRenderNotification =  true ;
                               
                                 // Destroy and recreate the EGL surface.
                                createEglSurface =  true ;

                                mSizeChanged =  false ;
                            }
                            mRequestRender =  false ;
                            sGLThreadManager.notifyAll();
                             if  (mWantRenderNotification) {
                                wantRenderNotification =  true ;
                            }
                             //注意此处break,跳出等待的循环
                             break ;
                        }
                    }

                     // By design, this is the only place in a GLThread thread where we wait().
                    sGLThreadManager.wait();
                }
            }

             /*外部请求在GL线程中处理的事件没有处理完时,就优先处理这些事件*/
             if  (event !=  null ) {
                event.run();
                event =  null ;
                 continue ;
            }

             //后续就是根据上面的判断设置,来执行相应的操作
             if  (createEglSurface) {//EglSurface需要被创建
                 //创建EglSurface
                 if  (mEglHelper.createSurface()) {      
                     synchronized (sGLThreadManager) {
                        mFinishedCreatingEglSurface =  true ;
                        sGLThreadManager.notifyAll();
                    }
                }  else  {
                     synchronized (sGLThreadManager) {
                        mFinishedCreatingEglSurface =  true ;
                        mSurfaceIsBad =  true ;
                        sGLThreadManager.notifyAll();
                    }
                     continue ;
                }
                createEglSurface =  false ;
            }

             if  (createGlInterface) {
                gl = (GL10) mEglHelper.createGL();

                createGlInterface =  false ;
            }

             if  (createEglContext) {

                GLSurfaceView view = mGLSurfaceViewWeakRef.get();
                 if  (view !=  null ) {
                     try  {
                        Trace.traceBegin(Trace.TRACE_TAG_VIEW,  "onSurfaceCreated" );
                         //调用GLSurfaceView设置的renderer的onSurfceCreated方法
                        view.mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
                    }  finally  {
                        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
                    }
                }
                createEglContext =  false ;
            }

             //surface大小被改变
             if  (sizeChanged) {
                GLSurfaceView view = mGLSurfaceViewWeakRef.get();
                 if  (view !=  null ) {
                     try  {
                        Trace.traceBegin(Trace.TRACE_TAG_VIEW,  "onSurfaceChanged" );
                        view.mRenderer.onSurfaceChanged(gl, w, h);//通知应用程序尺寸发生了变化
                    }  finally  {
                        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
                    }
                }
                sizeChanged =  false ;
            }

             //每帧绘制
            {
                GLSurfaceView view = mGLSurfaceViewWeakRef.get();
                 if  (view !=  null ) {
                     try  {
                        Trace.traceBegin(Trace.TRACE_TAG_VIEW,  "onDrawFrame" );
                        view.mRenderer.onDrawFrame(gl);//调用应用程序的Renderer渲染
                    }  finally  {
                        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
                    }
                }
            }
            //提交绘制结果,通过swap把渲染结果显示到屏幕上
             int  swapError = mEglHelper.swap();
             switch  (swapError) {
                 case  EGL10.EGL_SUCCESS:
                     break ;
                 case  EGL11.EGL_CONTEXT_LOST:
                    lostEglContext =  true ;
                     break ;
                 default :
                    EglHelper.logEglErrorAsWarning( "GLThread" ,  "eglSwapBuffers" , swapError);

                     synchronized (sGLThreadManager) {
                        mSurfaceIsBad =  true ;
                        sGLThreadManager.notifyAll();
                    }
                     break ;
            }

             if  (wantRenderNotification) {
                doRenderNotification =  true ;
                wantRenderNotification =  false ;
            }
        }

    }  finally  {
             /*
             * clean-up everything...
             */
         synchronized  (sGLThreadManager) {
            stopEglSurfaceLocked();
            stopEglContextLocked();
        }
    }

}

         public  boolean  ableToDraw () {
             return  mHaveEglContext && mHaveEglSurface && readyToDraw();
        }

         private  boolean  readyToDraw () {
             return  (!mPaused) && mHasSurface && (!mSurfaceIsBad)
                && (mWidth >  0 ) && (mHeight >  0 )
                && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY));
        }

         //设置渲染方法,见GLSurfaceView的setRenderMode
         public  void  setRenderMode ( int  renderMode){
         if   ( !(( RENDERMODE_WHEN_DIRTY   <= renderMode) && (renderMode <=   RENDERMODE_CONTINUOUSLY )) ) {
         throw new   IllegalArgumentException( "renderMode" ) ;
         }
         synchronized ( sGLThreadManager ) {
         mRenderMode   = renderMode ;
         sGLThreadManager .notifyAll() ;
         }
        }

         public  int  getRenderMode (){
         synchronized ( sGLThreadManager ) {
         return   mRenderMode ;
         }
        }

         //请求一次渲染
         public  void  requestRender (){
         synchronized ( sGLThreadManager ) {
         mRequestRender   =   true;
         sGLThreadManager .notifyAll() ;
         }
        }

         //请求一次渲染,并等待渲染完成
         public  void  requestRenderAndWait (){
         synchronized ( sGLThreadManager ) {
         if   (Thread. currentThread () ==   this ) {
           return;
         }

           mWantRenderNotification   =   true;
         mRequestRender   =   true;
         mRenderComplete   =   false;

         sGLThreadManager .notifyAll() ;

        while   (! mExited   && ! mPaused   && ! mRenderComplete   && ableToDraw()) {
         try   {
         sGLThreadManager .wait() ;
         }   catch   (InterruptedException ex) {
        Thread. currentThread ().interrupt() ;
         }
        }

         }
        }
         //创建Surface
         public  void  surfaceCreated (){
         synchronized ( sGLThreadManager ) {
         mHasSurface   =   true;
         mFinishedCreatingEglSurface   =   false;
         sGLThreadManager .notifyAll() ;
        while   ( mWaitingForSurface
     && ! mFinishedCreatingEglSurface
       && ! mExited ) {
         try   {
     sGLThreadManager .wait() ;
         }   catch   (InterruptedException e) {
        Thread. currentThread ().interrupt() ;
         }
         }
        }
        }

         //销毁Surface
         public  void  surfaceDestroyed (){
         synchronized ( sGLThreadManager ) {
         mHasSurface   =   false;
         sGLThreadManager .notifyAll() ;
         while ((! mWaitingForSurface ) && (! mExited )) {
         try   {
         sGLThreadManager .wait() ;
         }   catch   (InterruptedException e) {
        Thread. currentThread ().interrupt() ;
         }
        }
        }
        }

         public  void  onPause (){
         synchronized   ( sGLThreadManager ) {
         mRequestPaused   =   true;
         sGLThreadManager .notifyAll() ;
        while   ((!   mExited ) && (!   mPaused )) {
         try   {
         sGLThreadManager .wait() ;
         }   catch   (InterruptedException ex) {
        Thread. currentThread ().interrupt() ;
         }
        }
        }
        }
         public  void  onResume (){
         synchronized   ( sGLThreadManager ) {
         mRequestPaused   =   false;
         mRequestRender   =   true;
         mRenderComplete   =   false;
         sGLThreadManager .notifyAll() ;
        while   ((!   mExited ) &&   mPaused   && (! mRenderComplete )) {
         try   {
         sGLThreadManager .wait() ;
         }   catch   (InterruptedException ex) {
        Thread. currentThread ().interrupt() ;
         }
        }
        }
        }

         //Surface的大小被改变时调用
         public  void  onWindowResize ( int  w,  int  h){
         synchronized   ( sGLThreadManager ) {
         mWidth   = w ;
           mHeight   = h ;
         mSizeChanged   =   true;
         mRequestRender   =   true;
         mRenderComplete   =   false;

         if   (Thread. currentThread () ==   this ) {
         return;
         }

         sGLThreadManager .notifyAll() ;

         while   (!   mExited   && ! mPaused   && ! mRenderComplete
     && ableToDraw()) {
         try   {
         sGLThreadManager .wait() ;
         }   catch   (InterruptedException ex) {
        Thread. currentThread ().interrupt() ;
         }
        }
         }
        }

         //请求退出渲染线程,并等待退出
         public  void  requestExitAndWait (){
         synchronized ( sGLThreadManager ) {
         mShouldExit   =   true;
         sGLThreadManager .notifyAll() ;
        while   (!   mExited ) {
         try   {
         sGLThreadManager .wait() ;
         }   catch   (InterruptedException ex) {
        Thread. currentThread ().interrupt() ;
         }
        }
        }
        }

         //请求回收EglContext
         public  void  requestReleaseEglContextLocked (){
         mShouldReleaseEglContext   =   true;
         sGLThreadManager .notifyAll() ;
        }

         //向GL线程发送一个任务
         public  void  queueEvent (Runnable r){
         if   (r ==   null ) {
         throw new   IllegalArgumentException( "r must not be null" ) ;
         }
         synchronized ( sGLThreadManager ) {
         mEventQueue .add(r) ;
         sGLThreadManager .notifyAll() ;
         }
        }

    }


     //很多方法都会调用此方法,会检查mGLThread不为null, 即保证调用此方法的方法,必须在setRenderer之前调用
     private  void  checkRenderThreadState (){
     if   ( mGLThread   !=   null ) {
     throw new   IllegalStateException(
"setRenderer has already been called for this instance." ) ;
     }
    }

     //主要就是用来做同步用的,利用Object的wait和notifyAll
     private  static  class  GLThreadManager  {

            public synchronized void  threadExiting(GLThread thread) {
                thread. mExited =  true;
                notifyAll() ;
            }

            public void  releaseEglContextLocked(GLThread thread) {
                notifyAll() ;
            }
    }

}




EGLHelper
readyToDraw后调用了 EGLHelper. start方法初始化,然后跳出readyToDraw后调用了 EGLHelper. createSurface方法创建一个 EglSurface,
最后绘制完成以后 通过 EGLHelper. swap把渲染结果显示到屏幕上。

第一步: EGLHelper. start()方法初始化EGLHelper的内容
public void start() {
    mEgl = (EGL10) EGLContext.getEGL();//获取一个EGL实例
        //获取一个EGLDisplay
    mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);

       //初始化EGL并返回版本号
    if(!mEgl.eglInitialize(mEglDisplay, version)) {
    }
    GLSurfaceView view = mGLSurfaceViewWeakRef.get();
        //选取一个配置
    mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
        //创建EGLContext
    mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);
    mEglSurface = null;
}

第二步:如果需要创建 EglSurface,调用 mEglHelper.createSurface()方法
public boolean createSurface() {
    if (LOG_EGL) {
        Log.w("EglHelper", "createSurface()  tid=" + Thread.currentThread().getId());
    }
    /*
     * Check preconditions.
     */
    if (mEgl == null) {
        throw new RuntimeException("egl not initialized");
    }
    if (mEglDisplay == null) {
        throw new RuntimeException("eglDisplay not initialized");
    }
    if (mEglConfig == null) {
        throw new RuntimeException("mEglConfig not initialized");
    }
    GLSurfaceView view = mGLSurfaceViewWeakRef.get();
   
    mEglSurface = view.mEGLWindowSurfaceFactory.createWindowSurface(mEgl,
                mEglDisplay, mEglConfig, view.getHolder());

    return true;
}

private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory {

    public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display,
            EGLConfig config, Object nativeWindow) {
        EGLSurface result = null;
        result = egl.eglCreateWindowSurface(display, config, nativeWindow, null);
        return result;
}

}

第三步:提交绘制结果,通过mEglHelper.swap()把渲染结果显示到屏幕上
public int swap() {
     if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
          return mEgl.eglGetError();
     }
     return EGL10.EGL_SUCCESS;
}

总结GLSurfaceView使用EGL的流程如下:
1.生成一个EGL实例
mEgl = (EGL10) EGLContext.getEGL();
2.获取一个EGL Display  
mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
3.初始化EGL并返回版本号
if(!mEgl.eglInitialize(mEglDisplay, version)) {}
4.选取一个配置
mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
5.创建一个EGLContext
mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);
6.创建EGLSurface
egl.eglCreateWindowSurface(display, config, nativeWindow, null);
7.通过swap将渲染内容显示到屏幕
mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)

你可能感兴趣的:(android开发,组内讲座)