简单撸一下EGL

egl复杂构造opengl的工作环境
void egl_demo() 
{   
  EGLDisplay display = eglGetDisplay ( EGL_DEFAULT_DISPLAY );
    eglInitialize ( display , 0, 0);

  EGLConfig  config;
    eglChooseConfig ( display , attribs , & config , 1, & numConfigs );  

  EGLSurface  surface = eglCreateWindowSurface ( display , config , ANativeWindow  , NULL );
  EGLContext  context = eglCreateContext ( display , config , NULL , NULL );
  eglMakeCurrent ( display , surface , surface , context )

  while(true){
    //opengl绘制
    glxx();
    
    eglSwapBuffers ( display , surface );
  }

  eglDestroyContext ( display , context );
  eglDestroySurface ( display , surface );
  eglTerminate ( display );
}

    1. 动态加载opengles实现so
     eglGetDisplay(EGLNativeDisplayType display)
        egl_init_drivers
          egl_init_drivers_locked(未加载gl等模块,则加载,否则直接跳出)      
            Loader.open(egl_connection_t
)                    
                  load_driver(根据规则加载选定的so文件,把一段函数指针进行初始化)
          egl_display_t :: getFromNativeDisplay ( display )调用上面初始化的函数指针初始化display ,   cnx -> egl . eglGetDisplay)                           
             egl_display_t. getDisplay
   
 
     egl_init_drivers_locked()
     { // dynamically load our EGL implementation
    egl_connection_t * cnx = & gEGLImpl ;
    if ( cnx -> dso == 0) {
        //opengl的一堆函数指针,未初始化
        cnx -> hooks [ egl_connection_t :: GLESv1_INDEX ] = & gHooks [ egl_connection_t :: GLESv1_INDEX ];
        cnx -> hooks [ egl_connection_t :: GLESv2_INDEX ] = & gHooks [ egl_connection_t :: GLESv2_INDEX ];
        //
        cnx -> dso = loader . open ( cnx );
    }
 }

void * Loader :: load_driver ( const char * kind ,
        egl_connection_t * cnx , uint32_t mask )
{
          const char * const driver_absolute_path 找到so的路径;
    void * dso = dlopen ( driver_absolute_path , RTLD_NOW | RTLD_LOCAL );
    if ( mask & EGL ) {
        getProcAddress = ( getProcAddressType ) dlsym ( dso , ”eglGetProcAddress” );
         cnx -> egl ; 填充egl数组中的指针
    }

    if ( mask & GLESv1_CM ) {//填充v1指针
        cnx -> hooks [ egl_connection_t :: GLESv1_INDEX ]-> gl ,
    }

    if ( mask & GLESv2 ) { //填充v2指针
        cnx -> hooks [ egl_connection_t :: GLESv2_INDEX ]-> gl ,
    }
    return dso ;
}


EGLDisplay egl_display_t :: getDisplay ( EGLNativeDisplayType display ) {
    egl_connection_t * const cnx = & gEGLImpl ;
    if ( cnx -> dso && disp . dpy == EGL_NO_DISPLAY ) {//如果没有初始化过则初始化一下
        EGLDisplay dpy = cnx -> egl . eglGetDisplay ( display );
        disp.dpy = dpy;
        if ( dpy == EGL_NO_DISPLAY ) {
            loader . close ( cnx -> dso );
            cnx -> dso = NULL ;
        }
    }

    //返回的索引做一下映射,
    return EGLDisplay ( uintptr_t ( display ) + 1U);
}


   2.初始化egl,并获取版本号     
      EGLBoolean eglInitialize ( EGLDisplay dpy , EGLint * major , EGLint * minor ) (通过dpy找到 egl_display_t )
         egl_display_t :: initialize ( EGLint * major , EGLint * minor)
                cnx->egl . eglInitialize(底层的so导出的函数egl)

   3.选择最佳的配置      
     EGLBoolean eglChooseConfig ( EGLDisplay dpy , const EGLint * attrib_list , EGLConfig * configs , EGLint config_size , EGLint * num_config )
    {    // 通过dpy找到 egl_display_t
          const egl_display_ptr dp = validate_display ( dpy );
         //调用底层获取配置 dpy是底层创建的
          cnx->egl . eglChooseConfig ( dp->disp .dpy , attrib_list , configs , config_size , num_config );
    }

   4.本地窗口创建一个gl用的surface     
EGLSurface eglCreateWindowSurface EGLDisplay dpy , EGLConfig config , NativeWindowType window , const EGLint * attrib_list )
{
    // 通过dpy找到 egl_display_t
    egl_display_ptr dp = validate_display_connection ( dpy , cnx );
    //设置本地窗口的刷新间隔
     ANativeWindow * anw = reinterpret_cast < ANativeWindow *>( window );
    anw -> setSwapInterval ( anw , 1);
    //本地窗口创建surface
    EGLSurface surface = cnx -> egl . eglCreateWindowSurface ( iDpy , config , window , attrib_list );
}

5.创建上下文,保存gl的一些状态 
EGLContext eglCreateContext ( EGLDisplay dpy , EGLConfig config ,E GLContext share_list , const EGLint * attrib_list )
{
    // 通过dpy找到 egl_display_t
    const egl_display_ptr dp = validate_display_connection ( dpy , cnx );

    EGLContext context = cnx -> egl . eglCreateContext ( dp -> disp . dpy , config , share_list , attrib_list );
    //创建一个内部结构保存状态    
    egl_context_t * c = new egl_context_t ( dpy , context , config , cnx , version );   
}

6.设置绘制表面,
EGLBoolean eglMakeCurrent EGLDisplay dpy , EGLSurface draw , EGLSurface read , EGLContext ctx )
{
        // 通过dpy找到 egl_display_t
         egl_display_ptr dp = validate_display ( dpy );
        // 设置到 egl_display_ptr中
        EGLBoolean result = dp -> makeCurrent ( c , cur_c , draw , read , ctx , impl_draw , impl_read , impl_ctx );
      }

EGLBoolean egl_display_t :: makeCurrent ( egl_context_t * c , egl_context_t * cur_c ,
        EGLSurface draw , EGLSurface read , EGLContext ctx ,
        EGLSurface impl_draw , EGLSurface impl_read , EGLContext impl_ctx )
{  
       //底层egl库
            result = c -> cnx -> egl . eglMakeCurrent (
                    disp . dpy , impl_draw , impl_read , impl_ctx );
            //context中保存一些变量
            c -> onMakeCurrent ( draw , read );
      }

      7.交换后台缓冲区,绘制
       EGLBoolean eglSwapBuffers ( EGLDisplay dpy , EGLSurface draw )
      {
              const egl_display_ptr dp = validate_display ( dpy );               
              egl_surface_t const * const s = get_surface ( draw );
              return s -> cnx ->egl . eglSwapBuffers ( dp -> disp . dpy , s -> surface );
      }

      8.释放context
EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
{
    const egl_display_ptr dp = validate_display(dpy);
    ContextRef _c(dp.get(), ctx);
    egl_context_t * const c = get_context(ctx);
    //egl底层释放
    EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
   //释放这一层保存的
    _c->teminate
}

9.释放surface,跟上面过程一样的
EGLBoolean eglDestroySurface ( EGLDisplay dpy , EGLSurface surface )
{
          const egl_display_ptr dp = validate_display ( dpy );
    SurfaceRef _s ( dp . get (), surface );
    //egl底层释放
    egl_surface_t * const s = get_surface ( surface );
    EGLBoolean result = s-> cnx->egl . eglDestroySurface ( dp -> disp . dpy , s -> surface );
   //释放这一层保存的
     _s . terminate ();

    return result ;
}
   

     10.结束 ,还是释放display,没有卸载so
EGLBoolean eglTerminate ( EGLDisplay dpy )
{
    egl_display_ptr dp = get_display ( dpy );
    EGLBoolean res = dp -> terminate ();
    return res ;
}

egl_display_t保存在一个全局变量中,保存了一些状态
这个的terminate还和上面8,9的不一样
EGLBoolean egl_display_t :: terminate () {  
   //减小引用计数
    if ( refs > 1) {
        refs –;
        return EGL_TRUE ;
    }

      //如果最后一个,
    EGLBoolean res = EGL_FALSE ;
    egl_connection_t * const cnx = & gEGLImpl ;
    if ( cnx -> dso && disp . state == egl_display_t :: INITIALIZED ) {
        cnx ->egl. eglTerminate ( disp . dpy ) //更改状态
        disp . state = egl_display_t :: TERMINATED ;
        res = EGL_TRUE ;
    }

    //清空内部保存的content,surface等变量,
    size_t count = objects . size ();
    for ( size_t i =0 ; i < count ; i ++) {
        egl_object_t * o = objects . itemAt ( i );
        o->destroy (); //这个调用了下面 egl_object_t.destroy 会delete的
    }
    objects . clear ();
    refs –;
}

看一下 terminate,都用它了
class egl_surface_t : public egl_object_t

class egl_context_t : public egl_object_t

egl_object_t :: egl_object_t ( egl_display_t * disp ) :
    display ( disp ), count (1) {
    //display  就是全局的 egl_display_t,addobject就是添加到了数组中
    display -> addObject ( this );
}

egl_object_t ::~ egl_object_t () {
}

void egl_object_t :: terminate () {
        //数组中移除
    display -> removeObject ( this );
    if ( decRef () == 1) { //没有delete
 
    }
}

void egl_object_t :: destroy () {
    if ( decRef () == 1) {//删除,当 egl_display_t. terminate 会调用destroy
        delete this ;
    }
}


就这样吧,简单撸一下过程,回头再分析。

猜你喜欢

转载自blog.csdn.net/baidu_37503452/article/details/80800822