简单撸一下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,EGLContext 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 ;
    }
}


就这样吧,简单撸一下过程,回头再分析。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值