转载时请表明原文出处(http://blog.sina.com.cn/wyw1976)及作者邮箱(wyw1976@gmail.com)
刚刚说了gfx core 及gfx driver 的初始化,有必要趁热打铁看看gfx硬件加速的工作流程。
我们先看一下用户是如何调DirectFB来画线的,一般流程如下:
· DirectFBInit( &argc, &argv );
· DirectFBCreate(&dfb);
· dfb->CreateSurface(dfb, &sdsc, &primary);
· primary->DrawLine(primary, 0, 0, 100, 200);
上面的代码就是创建一个surface并在其上画一条从(0,0)到(100,200)的斜线。
我们可以沿着上述流程看看系统是如何一步步的调到硬件的呢?
1. DirectFBCreate在dfb_core_create完成各个core的初始化后,会调用IDirectFB_Construct设置DirectFB的总接口:IDirectFB。 IDirectFB也就是上面DirectFBCreate返回的那个参数,DFB所有的其他接口那么是这个总接口直接创建,要么是它的子孙创建的。在DFB中,接口实际上是用C语言实现的一个类,里面有私有数据,还有函数等。设置总接口的任务之一是设置它的函数指针。
其中有一个函数指针是:thiz->CreateSurface = IDirectFB_CreateSurface;
2. 当用户调用dfb->CreateSurface 时,实际调到的是IDirectFB_CreateSurface,而它又会创建surface这个对象并调用IDirectFBSurface_Construct完成surface接口中各个函数指针的赋值工作,其中有一个函数指针是: thiz->DrawLine = IDirectFBSurface_DrawLine。
3. 当用户调用primary->DrawLine,实际调到的是 IDirectFBSurface_DrawLine
IDirectFBSurface_DrawLine会调用dfb_gfxcard_drawlines(),而它首先会调用dfb_gfxcard_state_check看看系统是否支持硬件加速,如果card->funcs.CheckState等于NULL, 则表示不支持或不用硬件加速这直接返回,调用软件实现, 这个我们在《DirectFB 源码解读之初始化-9》讲过 。
4. 如果通过了dfb_gfxcard_state_check的检查,则继续调用dfb_gfxcard_state_acquire,设置下面硬件寄存器的状态和值,包括颜色、目标地址、源地址等等(通过card->funcs.SetState)。
5. 在第3步和第4步都成功后,就可以调用真正的作图函数,如card->funcs.DrawLine了,根据《DirectFB 源码解读之初始化-9》我们知道,这个函数指向的就是gfx driver中的作图函数,即硬件加速。例如,对于ATI128,它指向的就是ati128DrawLine()【gfxdrivers/ati128/Ati128.c】
至此我们完成了整个graphics driver中的硬件加速的画图流程。我们虽以DrawLine为例,但实际上所有其他的画图流程完全类似。唯一有区别的是:操作不同,涉及的寄存器不同。例如对于画线,需要设置画线的颜色;而对于blit操作,需要知道src surface 的地址等。
刚刚说了gfx core 及gfx driver 的初始化,有必要趁热打铁看看gfx硬件加速的工作流程。
我们先看一下用户是如何调DirectFB来画线的,一般流程如下:
· DirectFBInit( &argc, &argv );
· DirectFBCreate(&dfb);
· dfb->CreateSurface(dfb, &sdsc, &primary);
· primary->DrawLine(primary, 0, 0, 100, 200);
上面的代码就是创建一个surface并在其上画一条从(0,0)到(100,200)的斜线。
我们可以沿着上述流程看看系统是如何一步步的调到硬件的呢?
1. DirectFBCreate在dfb_core_create完成各个core的初始化后,会调用IDirectFB_Construct设置DirectFB的总接口:IDirectFB。 IDirectFB也就是上面DirectFBCreate返回的那个参数,DFB所有的其他接口那么是这个总接口直接创建,要么是它的子孙创建的。在DFB中,接口实际上是用C语言实现的一个类,里面有私有数据,还有函数等。设置总接口的任务之一是设置它的函数指针。
其中有一个函数指针是:thiz->CreateSurface = IDirectFB_CreateSurface;
2. 当用户调用dfb->CreateSurface 时,实际调到的是IDirectFB_CreateSurface,而它又会创建surface这个对象并调用IDirectFBSurface_Construct完成surface接口中各个函数指针的赋值工作,其中有一个函数指针是: thiz->DrawLine = IDirectFBSurface_DrawLine。
3. 当用户调用primary->DrawLine,实际调到的是 IDirectFBSurface_DrawLine
IDirectFBSurface_DrawLine会调用dfb_gfxcard_drawlines(),而它首先会调用dfb_gfxcard_state_check看看系统是否支持硬件加速,如果card->funcs.CheckState等于NULL, 则表示不支持或不用硬件加速这直接返回,调用软件实现, 这个我们在《DirectFB 源码解读之初始化-9》讲过 。
4. 如果通过了dfb_gfxcard_state_check的检查,则继续调用dfb_gfxcard_state_acquire,设置下面硬件寄存器的状态和值,包括颜色、目标地址、源地址等等(通过card->funcs.SetState)。
5. 在第3步和第4步都成功后,就可以调用真正的作图函数,如card->funcs.DrawLine了,根据《DirectFB 源码解读之初始化-9》我们知道,这个函数指向的就是gfx driver中的作图函数,即硬件加速。例如,对于ATI128,它指向的就是ati128DrawLine()【gfxdrivers/ati128/Ati128.c】
至此我们完成了整个graphics driver中的硬件加速的画图流程。我们虽以DrawLine为例,但实际上所有其他的画图流程完全类似。唯一有区别的是:操作不同,涉及的寄存器不同。例如对于画线,需要设置画线的颜色;而对于blit操作,需要知道src surface 的地址等。