Android4.2.2 SurfaceFlinger启动流程详解(二)

本文均属自己阅读源码的点滴总结,转账请注明出处谢谢。

欢迎和大家交流。qq:1037701636 email:gzzaigcn2012@gmail.com

Android源码版本Version:4.2.2; 硬件平台 全志A31

 

接着上文的SF启动流程,这里单独拎出来分析SurfaceFlinger::readyToRun()函数。里面的知识点比较多,只能和大家分享自己所知道的,共同交流学习。

status_t SurfaceFlinger::readyToRun()
{
    ALOGI(  "SurfaceFlinger's main thread ready to run. "
            "Initializing graphics H/W...");

    // initialize EGL for the default display
    mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglInitialize(mEGLDisplay, NULL, NULL);//EGL的初始化

    // Initialize the H/W composer object.  There may or may not be an
    // actual hardware composer underneath.
    mHwc = new HWComposer(this,
            *static_cast<HWComposer::EventHandler *>(this));//新建一个软硬件合成器HWComposer

    // initialize the config and context
    EGLint format = mHwc->getVisualID();
    mEGLConfig  = selectEGLConfig(mEGLDisplay, format);//配置EGL的参数
    mEGLContext = createGLContext(mEGLDisplay, mEGLConfig);//初始化上下文内容

    LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
            "couldn't create EGLContext");

    // initialize our non-virtual displays
    for (size_t i=0 ; i<DisplayDevice::NUM_DISPLAY_TYPES ; i++) {//DisplayDevice::NUM_DISPLAY_TYPES = 2
        DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);//0:HWC_DISPLAY_PRIMARY,1:HWC_DISPLAY_EXTERNAL
        mDefaultDisplays[i] = new BBinder();
        wp<IBinder> token = mDefaultDisplays[i];

        // set-up the displays that are already connected
        if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
            // All non-virtual displays are currently considered secure.
            bool isSecure = mHwc->isSecure(i);
            mCurrentState.displays.add(token, DisplayDeviceState(type));
            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i);
            sp<SurfaceTextureClient> stc = new SurfaceTextureClient(
                        static_cast< sp<ISurfaceTexture> >(fbs->getBufferQueue()));
            sp<DisplayDevice> hw = new DisplayDevice(this,
                    type, isSecure, token, stc, fbs, mEGLConfig);//新的显示设备
            if (i > DisplayDevice::DISPLAY_PRIMARY) {//HDMI,i= 1
                // FIXME: currently we don't get blank/unblank requests
                // for displays other than the main display, so we always
                // assume a connected display is unblanked.
                ALOGD("marking display %d as acquired/unblanked", i);
                hw->acquireScreen();
            }
            mDisplays.add(token, hw);//将准备好的显示硬件维护在mDefaultDisplays[i]中
        }
    }

    //  we need a GL context current in a few places, when initializing
    //  OpenGL ES (see below), or creating a layer,
    //  or when a texture is (asynchronously) destroyed, and for that
    //  we need a valid surface, so it's convenient to use the main display
    //  for that.
    sp<const DisplayDevice> hw(getDefaultDisplayDevice());

    //  initialize OpenGL ES
    DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
    initializeGL(mEGLDisplay);

    // start the EventThread
    mEventThread = new EventThread(this);//新建一个事件线程用于创建event的消息,处理VSYC同步事件
    mEventQueue.setEventThread(mEventThread);

    // initialize our drawing state
    mDrawingState = mCurrentState;


    // We're now ready to accept clients...
    mReadyToRunBarrier.open();

    // set initial conditions (e.g. unblank default device)
    initializeDisplays();

    // start boot animation
    startBootAnim();//开启动画属性

    return NO_ERROR;
}

int32_t SurfaceFlinger::allocateHwcDisplayId(DisplayDevice::DisplayType type) {
    return (uint32_t(type) < DisplayDevice::NUM_DISPLAY_TYPES) ?
            type : mHwc->allocateDisplayId();
}

在进入线程循环前,之所以执行他,因为SF正在运行前还有许多的工作要做,从下面几个点开始分析:

step1: new HWComposer()

在这里冒昧的称其为硬件合成器,从他的实现来看,可以看出他是和底层驱动走的最近的地方,因为涉及到了Gralloc模块(即所谓的Framebffer,主要用于图形的最终显示。

构造函数如下:

HWComposer::HWComposer(
        const sp<SurfaceFlinger>& flinger,
        EventHandler& handler)
    : mFlinger(flinger),
      mFbDev(0), mHwc(0), mNumDisplays(1),
      mCBContext(new cb_context),
      mEventHandler(handler),
      mVSyncCount(0), mDebugForceFakeVSync(false)
{
    for (size_t i =0 ; i<MAX_DISPLAYS ; i++) {
        mLists[i] = 0;
        mFrame[i].left = 0;
        mFrame[i].top = 0;
        mFrame[i].right = -1;
        mFrame[i].bottom = -1;
    }

    char value[PROPERTY_VALUE_MAX];
    property_get("debug.sf.no_hw_vsync", value, "0");
    mDebugForceFakeVSync = atoi(value);

    bool needVSyncThread = true;

    // Note: some devices may insist that the FB HAL be opened before HWC.
    loadFbHalModule();//加载framerbuffer模块gralloc
    loadHwcModule();//加载HWComposer模块
......
{//如果支持硬件hw
        ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
              (hwcApiVersion(mHwc) >> 24) & 0xff,
              (hwcApiVersion(mHwc) >> 16) & 0xff);//1.1版本
        if (mHwc->registerProcs) {
            mCBContext->hwc = this;
            mCBContext->procs.invalidate = &hook_invalidate;
            mCBContext->procs.vsync = &hook_vsync;//相关hwc的回调函数初始化
            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
                mCBContext->procs.hotplug = &hook_hotplug;
            else
                mCBContext->procs.hotplug = NULL;
            memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
            mHwc->registerProcs(mHwc, &mCBContext->procs);//向HAL注册回调函数
        }

        // don't need a vsync thread if we have a hardware composer
        needVSyncThread = false;//有硬件合成器就不需要软件的Vsync同步
        // always turn vsync off when we start
        eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);

        // the number of displays we actually have depends on the
        // hw composer version
        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
            // 1.2 adds support for virtual displays
            mNumDisplays = MAX_DISPLAYS;//1.2支持虚拟屏
        } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
            // 1.1 adds support for multiple displays
            mNumDisplays = HWC_NUM_DISPLAY_TYPES;//1.1支持2个屏
        } else {
            mNumDisplays = 1;
        }
    }
}

两个重要的成员函数loadFbHalModule和loadHwcModule

void HWComposer::loadFbHalModule()
{
    hw_module_t const* module;

    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) != 0) {//GRALLOC_HARDWARE_MODULE_ID = "Gralloc"
        ALOGE("%s module not found", GRALLOC_HARDWARE_MODULE_ID);
        return;
    }

    int err = framebuffer_open(module, &mFbDev);//gralloc内部的fb0模块
    if (err) {
        ALOGE("framebuffer_open failed (%s)", strerror(-err));
        return;
    }
}

根据博文Android中的HAL相关库搜索机制和原理学习可知最终会获取对应的framebuffer和hardware composer模块。

另外通过mHwc->registerProcs(mHwc, &mCBContext->procs);//向HAL注册对应的回调函数,供底层事件的回调调用。

 

step2: 对显示屏的初始化

mDisplayData[HWC_DISPLAY_PRIMARY]维护主要的显示屏,由下面的枚举类型来负责

enum {
    HWC_DISPLAY_PRIMARY     = 0,
    HWC_DISPLAY_EXTERNAL    = 1,    // HDMI, DP, etc.
    HWC_NUM_DISPLAY_TYPES
};

显示屏的相关信息提取与维护有函数HWComposer::queryDisplayProperties来完成:

status_t HWComposer::queryDisplayProperties(int disp) {

    LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));

    // use zero as default value for unspecified attributes
    int32_t values[NUM_DISPLAY_ATTRIBUTES - 1];
    memset(values, 0, sizeof(values));

    uint32_t config;
    size_t numConfigs = 1;
    status_t err = mHwc->getDisplayConfigs(mHwc, disp, &config, &numConfigs);//得到显示器的配置
    if (err != NO_ERROR) {
        // this can happen if an unpluggable display is not connected
        mDisplayData[disp].connected = false;
        return err;
    }

    err = mHwc->getDisplayAttributes(mHwc, disp, config, DISPLAY_ATTRIBUTES, values);//获取显示属性
......
}

 

step3:进一步初始化SF端需要的surface信息

  // initialize our non-virtual displays
    for (size_t i=0 ; i<DisplayDevice::NUM_DISPLAY_TYPES ; i++) {//DisplayDevice::NUM_DISPLAY_TYPES = 2
        DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);//0:HWC_DISPLAY_PRIMARY,1:HWC_DISPLAY_EXTERNAL
        mDefaultDisplays[i] = new BBinder();
        wp<IBinder> token = mDefaultDisplays[i];

        // set-up the displays that are already connected
        if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
            // All non-virtual displays are currently considered secure.
            bool isSecure = mHwc->isSecure(i);
            mCurrentState.displays.add(token, DisplayDeviceState(type));
            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i);
            sp<SurfaceTextureClient> stc = new SurfaceTextureClient(
                        static_cast< sp<ISurfaceTexture> >(fbs->getBufferQueue()));
            sp<DisplayDevice> hw = new DisplayDevice(this,
                    type, isSecure, token, stc, fbs, mEGLConfig);//新的显示设备
            if (i > DisplayDevice::DISPLAY_PRIMARY) {//HDMI,i= 1
                // FIXME: currently we don't get blank/unblank requests
                // for displays other than the main display, so we always
                // assume a connected display is unblanked.
                ALOGD("marking display %d as acquired/unblanked", i);
                hw->acquireScreen();
            }
            mDisplays.add(token, hw);//将准备好的显示硬件维护在mDefaultDisplays[i]中
        }
    }

这里分别new了FramebufferSurface和SurfaceTextureClient,下面对其进行分析

FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp) :
    ConsumerBase(new BufferQueue(true, new GraphicBufferAlloc())),
    mDisplayType(disp),
    mCurrentBufferSlot(-1),
    mCurrentBuffer(0),
    mHwc(hwc)
{
    mName = "FramebufferSurface";
    mBufferQueue->setConsumerName(mName);
    mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
                                       GRALLOC_USAGE_HW_RENDER |
                                       GRALLOC_USAGE_HW_COMPOSER);
    mBufferQueue->setDefaultBufferFormat(mHwc.getFormat(disp));
    mBufferQueue->setDefaultBufferSize(mHwc.getWidth(disp),  mHwc.getHeight(disp));
    mBufferQueue->setSynchronousMode(true);
    mBufferQueue->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
}

OK,这里又进入了FramebufferSurface的构造函数,该类继承ConsumerBase类,对该构造函数分为以下几个部分来分析。

a. new GraphicBufferAlloc(),新建一个图形缓存分配器类

b. new BufferQueue() 新建缓存队列类, 如下:

BufferQueue::BufferQueue(bool allowSynchronousMode,
        const sp<IGraphicBufferAlloc>& allocator) 
{
if (allocator == NULL) {
        sp<ISurfaceComposer> composer(ComposerService::getComposerService());
        mGraphicBufferAlloc = composer->createGraphicBufferAlloc();//创建GraphicBuffer
        if (mGraphicBufferAlloc == 0) {
            ST_LOGE("createGraphicBufferAlloc() failed in BufferQueue()");
        }
    } else {
        mGraphicBufferAlloc = allocator;
    }
}

新建的图像缓存分配器保存在BufferQueue队列当中。

c. new ConsumerBase类

ConsumerBase::ConsumerBase(const sp<BufferQueue>& bufferQueue) :
        mAbandoned(false),
        mBufferQueue(bufferQueue) {
    // Choose a name using the PID and a process-unique ID.
    mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());

    // Note that we can't create an sp<...>(this) in a ctor that will not keep a
    // reference once the ctor ends, as that would cause the refcount of 'this'
    // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
    // that's what we create.
    wp<BufferQueue::ConsumerListener> listener;
    sp<BufferQueue::ConsumerListener> proxy;
    listener = static_cast<BufferQueue::ConsumerListener*>(this);
    proxy = new BufferQueue::ProxyConsumerListener(listener);//新建一个监听代理

    status_t err = mBufferQueue->consumerConnect(proxy);//创建一个ConsumerListener代理
    if (err != NO_ERROR) {
        CB_LOGE("SurfaceTexture: error connecting to BufferQueue: %s (%d)",
                strerror(-err), err);
    } else {
        mBufferQueue->setConsumerName(mName);
    }
}

新建的ConsumerBase类,内部主要完成了创建一个BufferQueue的代理监听,同时将当前的mBufferQueue与监听连接在一起,具体如何使用后续会分析到。

status_t BufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener) {
...
    mConsumerListener = consumerListener;

    return OK;
}

 

step4,最终集成新建一个DisplayDevice

            sp<DisplayDevice> hw = new DisplayDevice(this,
                    type, isSecure, token, stc, fbs, mEGLConfig);//新的显示设备

 


step5.在SurfaceFlinger内接下去的内容将会在后续进行进一步分析。





  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值