您的位置:首页 > 其它

SurfaceFlinger启动过程分析(二)

2012-02-03 21:40 218 查看


SurfaceFlinger启动过程分析(二)

Daniel Wood 20110217

转载时请注明出处和作者

文章出处:http://danielwood.cublog.cn

作者:Daniel Wood

------------------------------------------------------------

上节说到SurfaceFlinger的readyToRun函数。先来看看它的代码:

(Google Android 2.2)

SurfaceFlinger.cpp
status_t SurfaceFlinger::readyToRun()
{

    LOGI( "SurfaceFlinger's main thread ready to run. "

            "Initializing graphics H/W...");

    // we only support one display currently

    int dpy = 0;

    {

        // initialize the main display

        GraphicPlane& plane(graphicPlane(dpy));

        DisplayHardware* const hw = new DisplayHardware(this, dpy);

        plane.setDisplayHardware(hw);

    }

    // create the shared control-block

    mServerHeap = new MemoryHeapBase(4096,

            MemoryHeapBase::READ_ONLY, "SurfaceFlinger
read-only heap");

    LOGE_IF(mServerHeap==0, "can't
create shared memory dealer");

    

    mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());

    LOGE_IF(mServerCblk==0, "can't
get to shared control block's address");   

    new(mServerCblk) surface_flinger_cblk_t;

    // initialize primary screen

    // (other display should be initialized in the same manner, but

    // asynchronously, as they could come and go. None of this is supported

    // yet).

    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();

    // initialize the shared control block

    mServerCblk->connected |= 1<<dpy;

    display_cblk_t* dcblk = mServerCblk->displays + dpy;

    memset(dcblk, 0, sizeof(display_cblk_t));

    dcblk->w = plane.getWidth();

    dcblk->h = plane.getHeight();

    dcblk->format = f;

    dcblk->orientation = ISurfaceComposer::eOrientationDefault;

    dcblk->xdpi = hw.getDpiX();

    dcblk->ydpi = hw.getDpiY();

    dcblk->fps = hw.getRefreshRate();

    dcblk->density = hw.getDensity();

    asm volatile ("":::"memory");

    // Initialize OpenGL|ES

    glActiveTexture(GL_TEXTURE0);

    glBindTexture(GL_TEXTURE_2D, 0);

    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

    glPixelStorei(GL_PACK_ALIGNMENT, 4); 

    glEnableClientState(GL_VERTEX_ARRAY);

    glEnable(GL_SCISSOR_TEST);

    glShadeModel(GL_FLAT);

    glDisable(GL_DITHER);

    glDisable(GL_CULL_FACE);

    const uint16_t g0 = pack565(0x0F,0x1F,0x0F);

    const uint16_t g1 = pack565(0x17,0x2f,0x17);

    const uint16_t textureData[4] = { g0, g1, g1, g0 };

    glGenTextures(1, &mWormholeTexName);

    glBindTexture(GL_TEXTURE_2D, mWormholeTexName);

    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0,

            GL_RGB, GL_UNSIGNED_SHORT_5_6_5, textureData);

    glViewport(0, 0, w, h);

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

    glOrthof(0, w, h, 0, 0, 1);

   LayerDim::initDimmer(this, w, h);

    mReadyToRunBarrier.open();

    /*

     * We're now ready to accept clients...

     */

    // start boot animation

    property_set("ctl.start", "bootanim");   

    return NO_ERROR;
}

调用readyToRun函数用于初始化整个显示系统。

 readyToRun()调用过程如下[这部分摘自网上资料]: 

(1)执行new DisplayHardware(this,dpy),通过DisplayHardware初始化Framebuffer、EGL并获取OpenGL
ES信息。 

(2)创建共享的内存控制块。 

(3)将EGL与当前屏幕绑定。 

(4)初始化共享内存控制块。 

(5)初始化OpenGL
ES。 

(6)显示开机动画。

上面的六点作为阅读代码的提纲及参考,下面对照代码进行分析:

(1)创建一个DisplayHardware,通过它的init函数去初始化Framebuffer、EGL并获取OpenGL
ES信息。 

DisplayHardware.cpp[frameworks\base\libs\surfaceflinger\displayhardware]

DisplayHardware::DisplayHardware(

        const sp<SurfaceFlinger>& flinger,

        uint32_t dpy)

    : DisplayHardwareBase(flinger, dpy)
{

    init(dpy);
}

init函数的代码狠长,我们一块一块,一句一句地分析:

void DisplayHardware::init(uint32_t dpy)
{

    mNativeWindow = new FramebufferNativeWindow();


    ...
首先亮相的是第一句(如上),new一个FramebufferNativeWindow。

FramebufferNativeWindow构造函数的代码也不少,我们去掉一些次要的代码,挑重要的关键的说:

FramebufferNativeWindow::FramebufferNativeWindow() 

    : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
{

    hw_module_t const* module;

    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {

        int stride;

        int err;

        err = framebuffer_open(module, &fbDev);

        LOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));

        

        err = gralloc_open(module, &grDev);

        LOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err));

        // bail out if we can't initialize the modules

        if (!fbDev || !grDev)

            return;        

        mUpdateOnDemand = (fbDev->setUpdateRect != 0);  
    

        // initialize the buffer FIFO

        mNumBuffers = 2;

        mNumFreeBuffers = 2;

        mBufferHead = mNumBuffers-1;

        buffers[0] = new NativeBuffer(

                fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);

        buffers[1] = new NativeBuffer(

                fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);


        

        err = grDev->alloc(grDev,

                fbDev->width, fbDev->height, fbDev->format, 

                GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride);

        LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s",fbDev->width,fbDev->height, strerror(-err));

        err = grDev->alloc(grDev,

                fbDev->width, fbDev->height, fbDev->format, 

                GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride);

        LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s",fbDev->width,fbDev->height, strerror(-err));
...

    } else {

        LOGE("Couldn't get gralloc module");

    }


    ...


}

  关键的代码都被我高亮了,从最后一行的else的LOGE中可以看出这里主要是获得gralloc这个模块。模块ID定义在:gralloc.h[hardware\libhardware\include\hardware]

#define GRALLOC_HARDWARE_MODULE_ID "gralloc"

ps:有时候代码中的log狠有用,可以帮助我们读懂代码,而且logcat也是我们调试代码的好东西。

    首先打开framebuffer和gralloc这两个模块

framebuffer_open和gralloc_open这两个接口在gralloc.h里面定义

static inline int framebuffer_open(const struct hw_module_t* module, 

        struct framebuffer_device_t** device) {

    return module->methods->open(module, 

            GRALLOC_HARDWARE_FB0, (struct hw_device_t**)device);
}
static inline int gralloc_open(const struct hw_module_t* module, 

        struct alloc_device_t** device) {

    return module->methods->open(module, 

            GRALLOC_HARDWARE_GPU0, (struct hw_device_t**)device);
}

两者指定的是gralloc.cpp中同一个函数gralloc_device_open,但是用的是不同的设备名,函数名和设备名分别在gralloc.cpp和gralloc.h中定义。

gralloc.h[hardware\libhardware\include\hardware]


#define GRALLOC_HARDWARE_FB0 "fb0"
#define GRALLOC_HARDWARE_GPU0 "gpu0"


gralloc.cpp[hardware\libhardware\modules\gralloc]
static struct hw_module_methods_t gralloc_module_methods = {

        open: gralloc_device_open
};

gralloc.cpp[hardware\libhardware\modules\gralloc]
int gralloc_device_open(const hw_module_t* module, const char* name,

        hw_device_t** device)
{

    int status = -EINVAL;

    if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {

        gralloc_context_t *dev;

        dev = (gralloc_context_t*)malloc(sizeof(*dev));

        /* initialize our state here */

        memset(dev, 0, sizeof(*dev));

        /* initialize the procs */

        dev->device.common.tag = HARDWARE_DEVICE_TAG;

        dev->device.common.version = 0;

        dev->device.common.module = const_cast<hw_module_t*>(module);

        dev->device.common.close = gralloc_close;

        dev->device.alloc = gralloc_alloc;

        dev->device.free = gralloc_free;

        *device = &dev->device.common;

        status = 0;

    } else {

        status = fb_device_open(module, name, device);

    }

    return status;
}

gralloc_device_open函数通过设备名字来进行相关的初始化工作。打开framebuffer则调用fb_device_open函数。fb_device_open函数定义在framebuffer.cpp中。

int fb_device_open(hw_module_t const* module, const char* name,

        hw_device_t** device)
{

    int status = -EINVAL;

    if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {

        alloc_device_t* gralloc_device;

        status = gralloc_open(module, &gralloc_device);

        if (status < 0)

            return status;

        /* initialize our state here */

        fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));

        memset(dev, 0, sizeof(*dev));

        /* initialize the procs */

        dev->device.common.tag = HARDWARE_DEVICE_TAG;

        dev->device.common.version = 0;

        dev->device.common.module = const_cast<hw_module_t*>(module);

        dev->device.common.close = fb_close;

        dev->device.setSwapInterval = fb_setSwapInterval;

        dev->device.post = fb_post;

        dev->device.setUpdateRect = 0;

        private_module_t* m = (private_module_t*)module;

        status = mapFrameBuffer(m);

        if (status >= 0) {

             ...

            *device = &dev->device.common;

        }

    }

    return status;
}

    fb_device_open函数是framebuffer.cpp里面的函数它会再次调用gralloc_open函数,调用gralloc_open并没有什么实际的用途,只是检测模块的正确性,感觉这句话没有必要,还是我哪里理解错了???因为gralloc_device这个变量在后面都没有用到啊。

哈哈,经过测试,把以下几句注释掉,然后make,烧到手机上,手机基本功能仍旧正常,看来这几句代码狠有可能是没有什么特别用处的。

alloc_device_t* gralloc_device;

status = gralloc_open(module, &gralloc_device);
if (status < 0)

   return status;

    然后调用mapFrameBuffer函数,就是将显示缓冲区映射到用户空间,这样在用户空间就可以直接对显示缓冲区进行读写操作。mapFrameBuffer函数的主体功能是在mapFrameBufferLocked函数里面完成的。

关于mapFrameBuffer函数,在下节讲解。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息