display: mesa: eglapi接口:bind/query api

接上一篇:display: mesa: eglapi接口:getdisplay&initialize_maze的专栏-CSDN博客

eglBindAPI

eglBindAPI:设置当前要绑定的API,api可取参数为EGL_OPENGL_API, EGL_OPENGL_ES_API和EGL_OPENVG_API。1.2及以上的版本支持OpenVG和OpenGLES,1.4及以上版本才支持OpenGL。默认值是ES,可以通过eglQueryAPI来查询。

/**
 * Specify the client API to use for subsequent calls including:
 *  eglCreateContext()
 *  eglGetCurrentContext()
 *  eglGetCurrentDisplay()
 *  eglGetCurrentSurface()
 *  eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
 *  eglWaitClient()
 *  eglWaitNative()
 * See section 3.7 "Rendering Context" in the EGL specification for details.
 */
EGLBoolean EGLAPIENTRY
eglBindAPI(EGLenum api)
{
    _EGLThreadInfo *t;
    
    t = _eglGetCurrentThread();
       _EGLThreadInfo *t = _eglCheckedGetTSD();
       if (!t) {
          t = _eglCreateThreadInfo();
          _eglSetTSD(t);
       }
       return t;
...
    t->CurrentAPI = api; //实际操作也就这一步。
}



################## _EGLThreadInfo结构体
/**
 * Per-thread info
 */
struct _egl_thread_info
{
   EGLint LastError;
   _EGLContext *CurrentContext;
   EGLenum CurrentAPI;
   EGLLabelKHR Label;

   /**
    * The name of the EGL function that's being called at the moment. This is
    * used to report the function name to the EGL_KHR_debug callback.
    */
   const char *CurrentFuncName;
   EGLLabelKHR CurrentObjectLabel;
};

eglQueryAPI

eglQueryAPI:查询当前的渲染API,返回调用线程中EGL使用的当前渲染API的值. 这个值通过eglBindAPI设置. 

/**
 * Return the last value set with eglBindAPI().
 */
EGLenum EGLAPIENTRY
eglQueryAPI(void)
{
   _EGLThreadInfo *t = _eglGetCurrentThread();
   EGLenum ret;

   /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
   ret = t->CurrentAPI;

   RETURN_EGL_SUCCESS(NULL, ret);
}

 bind和query都是围绕_EGLThreadInfo操作。可以看到里面存放了_EGLContext这一重要内容!

eglGetConfigs

eglGetConfigs:返回一个list,包含指定display可用的所有EGL frame buffer配置。 

EGLBoolean EGLAPIENTRY
eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
              EGLint config_size, EGLint *num_config)
{
   ret = _eglGetConfigs(disp, configs, config_size, num_config);
       通过数组元素disp->Configs,将disp->Configs内容写入configs
       *num_config = _eglFlattenArray(disp->Configs, (void *) configs, sizeof(configs[0]), config_size, _eglFlattenConfig);
}

eglChooseConfig

eglChooseConfig:返回符合指定属性的EGL帧缓冲的配置list,可设置的参数很多。 

EGLBoolean EGLAPIENTRY
eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs,
                EGLint config_size, EGLint *num_config)
{
   ret = _eglChooseConfig(disp, attrib_list, configs, config_size, num_config);
       _eglParseConfigAttribList(&criteria, disp, attrib_list); //通过client给过来的egl attr筛选出对应的符合这些attr的egl能提供的attr集合。
       return _eglFilterConfigArray(disp->Configs, configs, config_size, num_configs, _eglFallbackMatch, _eglFallbackCompare,(void *) &criteria);
}

eglGetConfigAttrib

eglGetConfigAttrib:返回EGL dpy对应的配置属性的值。

EGLBoolean EGLAPIENTRY
eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
                   EGLint attribute, EGLint *value)
返回dpy的config数组中attribute的值,value
{
   ret = _eglGetConfigAttrib(disp, conf, attribute, value);
       ...
       *value = _eglGetConfigKey(conf, attribute);//Return the value for a given key.
}

可以看到EGLDisplay和EGLConfig是绑定的。

eglCreateContext

eglCreateContext:创建一个EGL rendering context,返回的是EGLContext

EGLContext EGLAPIENTRY
eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
                 const EGLint *attrib_list)
创建一个新的egl渲染context,dpy是egl display 连接对象; config指定render上下文可用的帧缓冲区的配置;share_context 共享数据,具体不清楚; attrib_list指定context参数。
{
    _EGLDisplay *disp = _eglLockDisplay(dpy);
    _EGLConfig *conf = _eglLookupConfig(config, disp);
    _EGLContext *share = _eglLookupContext(share_list, disp);
    _EGLContext *context;
    EGLContext ret;
    ...
    context = disp->Driver->CreateContext(disp, conf, share, attrib_list);
        dri2_create_context(disp,conf,share,attrib_list) //egl_dri2.c

            通过user传递的context_attribs,传递的eglconfig_attribs,初始化EGLContext
            _eglInitContext(&dri2_ctx->base, disp, conf, attrib_list) //initialize the given _EGLContext object to defaults and/or the values in the attrib_list. 
            // And since we only support GL and GLES, this is the only place where 
the bound API matters at all. We look up the current API from the current thread, 
and stash that in the context we're initializing. Our caller is responsible for 
determining whether that's an API it supports.因为我们只支持GL和GLES,这里是绑定的API唯一起作用的地方,从当前线程查找当前API是什么,将他赋给初始化的context中。
                ...
                ctx 结构体赋值
                ...
                _eglParseContextAttribList(ctx, disp, attrib_list);//解析app传过来的context_attribs并做出对应的处理。
                api_bit = _eglCetContextAPIBit(ctx);
            ...
            dri2_fill_context_attribs(dri2_ctx, dri2_dpy, ctx_attribs, &num_attribs) //填充ctx_attribs
            ...
            不一定是下面这个实现,具体看不同的实现。主要是在initial那边挂钩的。有可能是dri2_dpy->image_driver/dri2_dpy->dri2/dri2_dpy->swrast
            dri2_ctx->dri_context = dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen,
                                                 api,
                                                 dri_config,
                                                 shared,
                                                 num_attribs / 2,
                                                 ctx_attribs,
                                                 & error,
                                                 dri2_ctx);
                driCreateContextAttribs(screen, api, dri_config, shared, num_attribs, attribs, error, data); //dri_util.c
                    ...
                    struct __DriverContextConfig ctx_config;
                    ...
                    填充ctx_config
                    ...
                    screen->driver->CreateContext(mesa_api, modes, context, &ctx_config, error, shareCtx)
                        dri_create_context(mesa_api, visual, cPriv, ctx_config, error, sharedContextPrivate); //dri_context.c
                            struct st_context_attribs attribs;
                            ...        
                            填充attribs 结构体
                            ...
                            dri_fill_st_visual(&attribs.visual, screen. visual);
                            ctx->st = stapi->create_context(stapi, &screen->base, &attribs, &ctx_err, st_share); //对应st_mananger.c里面
                                st_api_create_context(stapi, smapi, attribs, error, shared_stctxi);
                                    _mesa_initialize(attribs->options.mesa_extension_override);
                                    ...
                                    pipe = smapi->screen->context_create(smapi->screen, NULL, ctx_flags);
                                    st_visual_to_context_mode(&attribs->visual, &mode);
            dri2_create_context_attribs_error(error);
                

            return &dri2_ctx->base;

    return ret;
}

eglDestroyContext

EGLBoolean EGLAPIENTRY
eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
{ 
    _EGLDisplay *disp = _eglLockDisplay(dpy);
    _EGLContext *context = _eglLookupContext(ctx, disp);
...
    _eglUnlinkContext(context);
        _eglUnlinkResource(&ctx->Resource, _EGL_RESOURCE_CONTEXT);//从res的_egl_display中的ResourceLists这个双向链表里面拿出index为type的那一个。即拿掉res->Display->ResourceList[type];
    ret = disp->Driver->DestroyContext(disp, context);
        dri2_destroy_context(disp, context); //egl_dri2.c
            struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
            struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
            if (_eglPutContext(ctx)) { //减少context的引用计数,ctx->Resource->RefCount --
                dri2_dpy->core->destroyContext(dri2_ctx->dri_context);
                    driDestroyContext(pcp);
                        if(pcp){
                            pcp->driScreenPriv->driver->DestroyContext(pcp);
                                dri_destroy_context(pcp);
                                    hud_destroy(ctx->hud, ctx->st->cso_context);
                                    pp_free(ctx->pp);
                                    ctx->st->flush(ctx->st, 0, NULL, NULL, NULL);
                                    ctx->st->destroy(ctx->st);
                                    free(ctx);                                
                            free(pcp);
                        }
                free(dri2_ctx);
            }
}


eglQueryContext

EGLBoolean EGLAPIENTRY
eglQueryContext(EGLDisplay dpy, EGLContext ctx,
                EGLint attribute, EGLint *value)
{
   _EGLDisplay *disp = _eglLockDisplay(dpy);
   _EGLContext *context = _eglLookupContext(ctx, disp);
...
   ret = _eglQueryContext(context, attribute, value);
       switch (attribute) {
           case xxx:
               *value = context->xxx;
       }
...
}
通过传入的 attribute,把 context 相关内容输出。


返回EGL渲染上下文信息

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值