学习在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之间的连接

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)

更多相关文章

  1. SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
  2. android 7.0 有关wifi热点设置信息
  3. 二、Toolbar
  4. 弹出对话框--------android Toast 五种情形(无按钮)
  5. Android(安卓)TextView部分文字实现点击事件
  6. Android自屏幕底部滑出更多面板的实现
  7. Android回音噪音处理Demo
  8. 关于 android:windowSoftInputMode 的设置
  9. Android(安卓)Manager之MediaRecorder(音视频录制)

随机推荐

  1. vue+cordova移动端Android开发环境配置
  2. Android OpenGL ES 分析与实践
  3. 在Eclips中更改Android工程中包的名字
  4. Android 下载apk提示更新以及解决Android
  5. Android OpenGLES 实现结构
  6. Spring for android实现客户端与服务器的
  7. Android(安卓)Studio创建项目Error:Serve
  8. android中的主题(theme)的定义
  9. Android 常用代码整理:Android 常用弹窗整
  10. Android 的source (需安装 git repo)