接上一篇: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渲染上下文信息