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

来源:互联网 发布:芯片和单片机的区别 编辑:程序博客网 时间:2024/06/11 04:29

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

欢迎和大家交流。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内接下去的内容将会在后续进行进一步分析。





0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小孩头敲了个包怎么办 四个月不吃奶怎么办啊 4个月宝宝不吃奶粉怎么办 3个月婴儿不喝奶怎么办 地图舌加裂纹舌怎么办 3个月宝宝厌食怎么办 宝宝不吃奶吃手怎么办 三个月的宝宝光吃手不吃奶怎么办 九个月宝宝积热怎么办 前门牙露神经了怎么办 7岁宝宝吐舌头怎么办 连续液精几个月了怎么办 接吻时对方伸舌头我要怎么办 亲嘴不想让对方伸舌头怎么办 喝醉酒想吐吐不出来怎么办 凉了胃怎么办喝什么药 生宝宝后屁股扁了怎么办 屁股又宽又扁怎么办 烫伤一年多色差没有恢复怎么办 上古卷轴5不能动怎么办 上古卷轴ol卡死怎么办 小妹妹这么骚长大了怎么办 同事借钱忘了还怎么办 怀了二胎想离婚怎么办 如果闺蜜疏远了怎么办 考上博士但是硕士要延期怎么办 硕士延期也不能毕业怎么办 硕士论文工作量太少被延期了怎么办 竞彩足球比赛延期中断怎么办? 竞彩足球输了怎么办 讯飞语音不兼容百度怎么办 虎牙直播不兼容语音怎么办 为什么手机打开游戏就死机怎么办 2007cad打开时时死机怎么办 手机qq总是无响应怎么办 英雄联盟登录服务器未响应怎么办 苹果7p照相死机怎么办 小米手机qq打不开怎么办啊 电脑qq老是闪退怎么办 微信摄像卡住了怎么办 电脑打开应用程序没反应怎么办