现在的位置: 首页 > 综合 > 正文

SurfaceFlinger启动过程分析(二)

2013年09月11日 ⁄ 综合 ⁄ 共 6663字 ⁄ 字号 评论关闭

转载时请注明出处和作者
文章出处: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->= plane.getWidth();
    dcblk->= 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初始化FramebufferEGL并获取OpenGL
ES
信息。 

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

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

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

5)初始化OpenGL
ES
 

6)显示开机动画。

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

(1)创建一个DisplayHardware,通过它的init函数去初始化FramebufferEGL并获取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_opengralloc_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中定义。


抱歉!评论已关闭.