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)
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
;
}
}
就这样吧,简单撸一下过程,回头再分析。