1. 从 SurfaceFlinger::readyToRun 开始 (SurfaceFlinger.cpp)
class SurfaceFlinger : 中包含下面obj
GraphicPlane mGraphicPlanes[1];
UML 里称之为组合或者包容
GraphicPlane& plane(graphicPlane(dpy)); 返回mGraphicPlanes的引用
DisplayHardware* const hw = new DisplayHardware(this, dpy);
初始化1个DisplayHardware
因为每一个graphicPlane对象都对应一个DisplayHardware
下面把他们组合起来
plane.setDisplayHardware(hw);
关于这几个类之间的关系图:
到这里SurfaceFlinger组合了GraphicPlane,然后GraphicPlane 组合了
DisplayHardware,并且DisplayHardware 已经在 new DisplayHardware
完成了init,与framebuffer 的关联,具体做了什么呢?
继续看DisplayHardware
2. new DisplayHardware
class DisplayHardware 构造时传入SurfaceFlinger引用
以及它的父类 DisplayHardwareBase 的成员wp mFlinger;
DisplayHardware 到 SurfaceFlinger 的联系也建立了
其他dpy=0,mFlags=0到自己的类成员,开始执行init前
给自己提个问题,虽然感觉这个成员使用SurfaceFlinger的弱引用
满合适的,但讲不出为什么的道理???
void DisplayHardware::init(uint32_t dpy)一开始就又new了这样1个类:
class FramebufferNativeWindow :
public EGLNativeBase
LightRefBase>
这个类的注释如下:
* This implements the (main) framebuffer management. This class is used
* mostly by SurfaceFlinger, but also by command line GL application.
* In fact this is an implementation of ANativeWindow on top of
* the framebuffer.
*
* Currently it is pretty simple, it manages only two buffers (the front
* and back buffer).
很直接说明了FramebufferNativeWindow 与 framebuffer 以及SurfaceFlinger
之间的关系
SurfaceFlinger操作的是对framebuffer又做了1次封装的FramebufferNativeWindow类
3. new FramebufferNativeWindow (FramebufferNativeWindow.cpp)
从构造函数看起:
FramebufferNativeWindow::FramebufferNativeWindow()
: BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
a. 首先获得 gralloc hardware module
b. 执行 framebuffer_open(module, &fbDev);
来获得struct framebuffer_device_t
它调用下面gralloc module的open函数:
module->methods->open(module,
GRALLOC_HARDWARE_FB0, (struct hw_device_t**)device);
gralloc hardware module 的open定义如下
static struct hw_module_methods_t gralloc_module_methods = {
open: gralloc_device_open
};
对于GRALLOC_HARDWARE_FB0,gralloc_device_open执行下面函数
fb_device_open(module, name, device); 调用
gralloc_open(module, &gralloc_device);
实际对应到
module->methods->open(module,
GRALLOC_HARDWARE_GPU0, (struct hw_device_t**)device);
就是 gralloc_device_open的GRALLOC_HARDWARE_GPU0部分
主要做了下面工作:
分配下面结构:
struct gralloc_context_t {
alloc_device_t device;
/* our private data here */
};
并对 alloc_device_t device设置alloc 函数为gralloc_alloc
free 函数为gralloc_free
这样在获得 struct framebuffer_device_t * 前
我们已经获得了 alloc_device_t* gralloc_device;
注意galloc module的其他几个方法:
registerBuffer: gralloc_register_buffer,
unregisterBuffer: gralloc_unregister_buffer,
lock: gralloc_lock,
unlock: gralloc_unlock,
这些都是以后buffer管理要用到的
接下来继续 framebuffer_device_t device;
部分的open操作如下:
分配结构
struct fb_context_t {
framebuffer_device_t device;
};
setSwapInterval = fb_setSwapInterval;
post = fb_post;
其中fb_setSwapInterval 是设置切换framebuffer的间隔,现在还没实现
fb_post 很重要,将显示内容传到硬件缓冲区,根据其中if else 可以看出有
两种方法
1. 从新设置framebuffer 硬件缓冲的开始地址
const size_t offset = hnd->base - m->framebuffer->base;
m->info.activate = FB_ACTIVATE_VBL;
m->info.yoffset = offset / m->finfo.line_length;
ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info)
2. memcpy 到 framebuffer硬件缓冲
回到fb_device_open 接下来call mapFrameBuffer->mapFrameBufferLocked
最重要的framebuff mmap 就在这里面,下面看下具体的:
* 打开/dev/fb0 获得fd
* ioctl 获得struct fb_fix_screeninfo,fb_var_screeninfo
* 支持page flip的 NUM_BUFFERS,计算fb_var_screeninfo的yres_virtual
然后ioctl再写入,再读更新后的fb_var_screeninfo
* 根据module->framebuffer = new private_handle_t
* mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
获得frame buffer 物理地址对应的虚拟地址,并把vaddr 赋给
module->framebuffer->base
到这里framebuffer关键参数base, size都有了,通过module->framebuffer
就可以访问到
c. 继续 FramebufferNativeWindow 构造的gralloc_open(module, &grDev);
不明白为什么前面fb_device_open调用gralloc_open的意义???
这里可以获得alloc_device_t* 到 FramebufferNativeWindow 成员grDev
d. new 两个class NativeBuffer : public EGLNativeBase<
android_native_buffer_t,
NativeBuffer,
LightRefBase >
到 FramebufferNativeWindow的成员 sp buffers[2];
e. grDev->alloc 前面的sp buffers[2];
gralloc_alloc -> gralloc_alloc_framebuffer
-> gralloc_alloc_framebuffer_locked
没有真的分配内存,只是关联到我们前面获得的module->framebuffer->base
private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size,
private_handle_t::PRIV_FLAGS_FRAMEBUFFER);
// find a free slot
for (uint32_t i=0 ; i if ((bufferMask & (1LU< m->bufferMask |= (1LU< break;
}
vaddr += bufferSize;
}
hnd->base = vaddr;
hnd->offset = vaddr - intptr_t(m->framebuffer->base);
*pHandle = hnd;
返回一个关联framebuffer 地址的 buffer_handle_t*
其中根据GRALLOC_USAGE_HW_FB判断,如果不支持 pageflip 需要另外分配2个buffer
在ashmem 中
f. 将 framebuffer_device_t* fbDev中的参数设置到ANativeWindow
以后 FramebufferNativeWindow 可以访问到这些参数
const_cast(ANativeWindow::flags) = fbDev->flags;
const_cast(ANativeWindow::xdpi) = fbDev->xdpi;
const_cast(ANativeWindow::ydpi) = fbDev->ydpi;
const_cast(ANativeWindow::minSwapInterval) =
fbDev->minSwapInterval;
const_cast(ANativeWindow::maxSwapInterval) =
fbDev->maxSwapInterval;
g. 设置ANativeWindow 相关操作
ANativeWindow::setSwapInterval = setSwapInterval;
ANativeWindow::dequeueBuffer = dequeueBuffer;
ANativeWindow::lockBuffer = lockBuffer;
ANativeWindow::queueBuffer = queueBuffer;
ANativeWindow::query = query;
ANativeWindow::perform = perform;
dequeueBuffer 用来获得一个buffer 进行后台输出
,queueBuffer 将已经绘制好的buffer ,切到硬件缓冲区
fb->post(fb, handle);
到这里 FramebufferNativeWindow 有了我们需要的一切必要元素
framebuffer_device_t* fbDev;
alloc_device_t* grDev;
sp buffers[2];
sp front;
int32_t mNumBuffers=2;
int32_t mNumFreeBuffers;
int32_t mBufferHead=1;
int32_t mCurrentBufferIndex;
bool mUpdateOnDemand;
module ,dev 关联图:
4. 回到 DisplayHardware::init
接下来打开overlay,如果vendor 没有提供,那么就是overlay.default.so
if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
overlay_control_open(module, &mOverlayEngine);
}
就是通过overlay_device_open 函数执行OVERLAY_HARDWARE_CONTROL命令
来分配如下overlay control 结构:
struct overlay_control_context_t {
struct overlay_control_device_t device;
/* our private state goes below here */
};
然后设置createOverlay,setPosition等函数
再接下来就是OPENGL 的初始化部分:
先判断debug.sf.hw 属性如果不等于0 ,那么就表示使用agl(软件gl)
/system/lib/egl # ls
libEGL_POWERVR_SGX530_125.so => HW
libGLES_android.so => SW
egl.cfg
libGLESv1_CM_POWERVR_SGX530_125.so => HW
libGLESv2_POWERVR_SGX530_125.so => HW
static egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
中的 gEGLImpl[IMPL_HARDWARE] 用于存放从HW lib 中获得的API
struct egl_connection_t
{
inline egl_connection_t() : dso(0) { }
void * dso;
/*GLESvq1_CM api 放到 gEGLImpl[].hooks[GLESv1_INDEX]->gl
GLESv2 api 放到 gEGLImpl[].hooks[GLESv2_INDEX]->gl
opengl\libs\egl_entries.in
*/
gl_hooks_t * hooks[2];
EGLint major;
EGLint minor;
egl_t egl; /* 其中EGL api */
};
struct egl_t {
#include "EGL/egl_entries.in"
};
egl_entries.in 中放的就是entry list
比如:
EGL_ENTRY(EGLDisplay, eglGetDisplay, NativeDisplayType)
根据定义
#define EGL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__);
得到:
EGLDisplay (* eglGetDisplay)( NativeDisplayType)
libs/egl/loader.cpp 用来加载这些函数指针
eglGetDisplay-> egl_init_drivers->
egl_init_drivers_locked ->
-> cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx);
-> dso = load_driver("EGL", tag, cnx, EGL);
hnd = new driver_t(dso);
// TODO: make this more automated
hnd->set( load_driver("GLESv1_CM", tag, cnx, GLESv1_CM), GLESv1_CM );
hnd->set( load_driver("GLESv2", tag, cnx, GLESv2), GLESv2 );
EGL,和GLES都提供给系统使用,EGL是访问GLES的接口
获得API后使用EGL 的 eglGetConfigs 函数去获得hw,sw的config
if (cnx->egl.eglGetConfigs(
dp->disp[i].dpy, dp->disp[i].config, n,
&dp->disp[i].numConfigs))
根据窗口选择config :
selectConfigForNativeWindow
通过eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
创建main surface,其中mNativeWindow就是diplayhardware init中new的
FramebufferNativeWindow
通过 eglCreateContext 创建OpenGL ES context
最后
// Unbind the context from this thread
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
opengl init 基本结束
DisplayHardware 的如下成员都获得了相应的结果
EGLDisplay mDisplay;
EGLSurface mSurface;
EGLContext mContext;
EGLConfig mConfig;
最重要的就是 EGLSurface mSurface;
以后所有的SurfaceFlinger进程中使用EGL的所有的操作目的地都是它
5. 回到 SurfaceFlinger::readyToRun
接下来分配控制块,(和display相关的control block)
// create the shared control-block
mServerHeap = new MemoryHeapBase(4096,
MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap");
然后如注释initialize primary screen
const GraphicPlane& plane(graphicPlane(dpy));
const DisplayHardware& hw = plane.displayHardware();
const uint32_t w = hw.getWidth();
const uint32_t h = hw.getHeight();
const uint32_t f = hw.getFormat();
hw.makeCurrent();
获得surfacefling 成员mGraphicPlanes[0] 的引用,
并用该引用获得与该GraphicPlane类对象 对应的 DisplayHardware的类对象的引用
最后通过EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
EGLSurface read, EGLContext ctx)
将上面unbind 的进行context 和 mSurface 进行重新bind
// initialize the shared control block
这个共享控制块是4K
结构如下:
//管理系统中所有的显示屏
struct surface_flinger_cblk_t // 4KB max
{
/* 每一个bit表示一个显示屏 ,上面定义最大4个*/
uint8_t connected;
uint8_t reserved[3];
uint32_t pad[7];
display_cblk_t displays[SharedBufferStack::NUM_DISPLAY_MAX];
};
接下来继续 Initialize OpenGL|ES
好象是视口等设置,不是很懂,有时间可以看下 opengl方面的东西来了解
最后开启动画显示
// start boot animation
property_set("ctl.start", "bootanim");
结束