简单撸一下EGL

来源:互联网 发布:印象笔记是什么软件 编辑:程序博客网 时间:2024/05/06 02:35
egl复杂构造opengl的工作环境
void egl_demo() 
{  
 EGLDisplaydisplay=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(EGLNativeDisplayTypedisplay)
       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(constchar*kind,
       egl_connection_t*cnx,uint32_tmask)
{
         constchar*constdriver_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,
    }
   returndso;
}


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

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


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

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

   4.本地窗口创建一个gl用的surface    
EGLSurfaceeglCreateWindowSurfaceEGLDisplaydpy,EGLConfigconfig,NativeWindowTypewindow,constEGLint*attrib_list)
{
   //通过dpy找到egl_display_t
   egl_display_ptrdp=validate_display_connection(dpy,cnx);
    //设置本地窗口的刷新间隔
    ANativeWindow*anw=reinterpret_cast<ANativeWindow*>(window);
   anw->setSwapInterval(anw, 1);
    //本地窗口创建surface
   EGLSurfacesurface=cnx->egl.eglCreateWindowSurface(iDpy,config,window,attrib_list);
}

5.创建上下文,保存gl的一些状态 
EGLContexteglCreateContext(EGLDisplaydpy,EGLConfigconfig,EGLContextshare_list,constEGLint*attrib_list)
{
    //通过dpy找到egl_display_t
   constegl_display_ptrdp=validate_display_connection(dpy,cnx);

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

6.设置绘制表面,
EGLBooleaneglMakeCurrentEGLDisplaydpy,EGLSurfacedraw,EGLSurfaceread,EGLContextctx)
{
        //通过dpy找到egl_display_t
        egl_display_ptrdp=validate_display(dpy);
        // 设置到egl_display_ptr中
        EGLBooleanresult=dp->makeCurrent(c,cur_c,draw,read,ctx,impl_draw,impl_read,impl_ctx);
      }

EGLBooleanegl_display_t::makeCurrent(egl_context_t*c,egl_context_t*cur_c,
       EGLSurfacedraw,EGLSurfaceread,EGLContextctx,
       EGLSurfaceimpl_draw,EGLSurfaceimpl_read,EGLContextimpl_ctx)
{ 
       //底层egl库
           result=c->cnx->egl.eglMakeCurrent(
                   disp.dpy,impl_draw,impl_read,impl_ctx);
            //context中保存一些变量
           c->onMakeCurrent(draw,read);
      }

     7.交换后台缓冲区,绘制
       EGLBooleaneglSwapBuffers(EGLDisplaydpy,EGLSurfacedraw)
      {
             constegl_display_ptrdp=validate_display(dpy);              
              egl_surface_tconst*consts=get_surface(draw);
             returns->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,跟上面过程一样的
EGLBooleaneglDestroySurface(EGLDisplaydpy,EGLSurfacesurface)
{
         constegl_display_ptrdp=validate_display(dpy);
   SurfaceRef_s(dp.get(),surface);
    //egl底层释放
   egl_surface_t*consts=get_surface(surface);
   EGLBooleanresult=s->cnx->egl.eglDestroySurface(dp->disp.dpy,s->surface);
   //释放这一层保存的
    _s.terminate();

   returnresult;
}
   

     10.结束 ,还是释放display,没有卸载so
EGLBooleaneglTerminate(EGLDisplaydpy)
{
   egl_display_ptrdp=get_display(dpy);
   EGLBooleanres=dp->terminate();
   returnres;
}

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

      //如果最后一个,
   EGLBooleanres=EGL_FALSE;
   egl_connection_t*constcnx= &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_tcount=objects.size();
   for(size_ti=0 ;i<count;i++) {
       egl_object_t*o=objects.itemAt(i);
       o->destroy(); //这个调用了下面egl_object_t.destroy 会delete的
    }
   objects.clear();
   refs--;
}

看一下terminate,都用它了
classegl_surface_t:publicegl_object_t

classegl_context_t:publicegl_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() {
}

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

voidegl_object_t::destroy() {
   if(decRef() == 1) {//删除,当egl_display_t.terminate 会调用destroy
       deletethis;
    }
}


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