SurfaceFlinger 分析 一

原创 2016年06月01日 16:44:54

SurfaceFlinger 

 

1. SurfaceFlinger启动流程

 

SurfaceFlinger 线程启动是由kenerl加载init.rc文件后执行system/bin文件夹下的可执行文件: surfaceflinger, 启动main函数:

先见时序图:

 

 

启动main函数后创建自己的线程并限定binder线程最大为4初始话后加入线程池:

    ProcessState::self()->setThreadPoolMaxThreadCount(4); // 设置最大线程数
    sp<ProcessState> ps(ProcessState::self());
    ps->startThreadPool();


 

初始化的第一部分:

Main函数调用surface flingerinit函数EGL, RenderEngine 等初始化:

    mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); 
    eglInitialize(mEGLDisplay, NULL, NULL); // EGL 的初始化动作
    sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true, "app"); // 虚拟化Vsync App UI部分
    mEventThread = new EventThread(vsyncSrc);
    sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, sfVsyncPhaseOffsetNs, true, "sf"); // 虚拟化Vsync SF合成部分
    mSFEventThread = new EventThread(sfVsyncSrc);
    mEventQueue.setEventThread(mSFEventThread); 
    // Initialize the H/W composer object.  There may or may not be an
    // actual hardware composer underneath.
    mHwc = DisplayUtils::getInstance()->getHWCInstance(this,  *static_cast<HWComposer::EventHandler *>(this));  // 初始化hardwarecomposer
    // get a RenderEngine for the given display / config (can't fail)
    mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());
    // retrieve the EGL context that was selected/created
    mEGLContext = mRenderEngine->getEGLContext();
    LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,  "couldn't create EGLContext");



(1) . EGL的初始就不说了有意思的是 google 实例了两个不同的VsyncSource : vsyncSrc 与 sfvsyncSrc 一个是app uivsync另一个是surfaceflinger合成的vsync, 他们只是将hardware层传过来的vsync虚拟化了.

他们根据sfVsyncPhaseOffsetNs 与 vsyncPhaseOffsetNs 两个相对偏移量将

 app UI绘制 与 SF合成区分

 

其中Phase Offset 1, 2 的值可以改变这样做的目的是避免了因同时唤醒app UI 渲染和SF合成是造成对CPU资源的抢占.

 

(2) . 接下来启动上述EventThread. 

EventThread的构造函数只是初始化一些数据重要的是它的onFirstRef函数(使用强指针时就会触发onFirstRef函数 )

 
void EventThread::onFirstRef() {
    run("EventThread", PRIORITY_URGENT_DISPLAY+PRIORITY_MORE_FAVORABLE);
}

Run 启动threadloop: 其中一个重要的函数: waitForEvent, 

 

( 3 ) . HWcomposer初始化:

 

HWComposer::HWComposer(
       const sp<SurfaceFlinger>& flinger, EventHandler& handler)
    : mFlinger(flinger),mFbDev(0),  mHwc(0),  mNumDisplays(1),
    mCBContext(new cb_context), mEventHandler(handler), mDebugForceFakeVSync(false)
{
    ...  ...
 
    // Note: some devices may insist that the FB HAL be opened before HWC.
    int fberr = loadFbHalModule();  // 加载准备framebuffer hal模块, 最终加载gralloc.XX.so动态库
    loadHwcModule();   // 加载准备硬件加速模块 最终会加载各平台对应的hwcomposer.XX.so动态库
 
    ... ...
    if (needVSyncThread) {
        // we don't have VSYNC support, we need to fake it
        mVSyncThread = new VSyncThread(*this);  // Vsync周期控制
    }
}

HWcomposer 的初始化其中两个很重要的工作就是加载FB HAL与 Hwc 模块它们为数据在硬件合成方面做准备工作

 

( 4 ) . 根据EGL display与 像素格式创建RenderEngine, 并获取当前EGLContext

 

接下来看初始化的第二部分:

   // initialize our non-virtual displays
    for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
        DisplayDevice::DisplayType type((DisplayDevice::DisplayType)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 = true;
            createBuiltinDisplayLocked(type);
            wp<IBinder> token = mBuiltinDisplays[i];
 
            sp<IGraphicBufferProducer> producer;
            sp<IGraphicBufferConsumer> consumer;
            BufferQueue::createBufferQueue(&producer, &consumer,
                    new GraphicBufferAlloc());
 
            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
                    consumer);
            int32_t hwcId = allocateHwcDisplayId(type);
            sp<DisplayDevice> hw = new DisplayDevice(this,
                    type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
                    fbs, producer,
                    mRenderEngine->getEGLConfig());
            if (i > DisplayDevice::DISPLAY_PRIMARY) {
                // 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 %zu as acquired/unblanked", i);
                hw->setPowerMode(HWC_POWER_MODE_NORMAL);
            }
            // When a non-virtual display device is added at boot time,
            // update the active config by querying HWC otherwise the
            // default config (config 0) will be used.
            int activeConfig = mHwc->getActiveConfig(hwcId);
            if (activeConfig >= 0) {
                hw->setActiveConfig(activeConfig);
            }
            mDisplays.add(token, hw);
        }
    }

( 1 ) . 初始化BufferQueue, 这个Queue是生产者IGraphicBufferProducer 与 消费者IGraphicBufferConsumer 的关键桥梁

( 2 ) . 创建一个FramebufferSurface

( 3 ) . 初始化各个DisplayDevice, 每个显示设备都会封装为一个DisplayDevice, HDMI等 

DisplayDevice::DisplayDevice(
        const sp<SurfaceFlinger>& flinger,
        DisplayType type,
        int32_t hwcId,
        int format,
        bool isSecure,
        const wp<IBinder>& displayToken,
        const sp<DisplaySurface>& displaySurface,
        const sp<IGraphicBufferProducer>& producer,
        EGLConfig config)
    : lastCompositionHadVisibleLayers(false),
      mFlinger(flinger),
      mType(type), mHwcDisplayId(hwcId),
      mDisplayToken(displayToken),
      mDisplaySurface(displaySurface),
      mDisplay(EGL_NO_DISPLAY),
      mSurface(EGL_NO_SURFACE),
      mDisplayWidth(), mDisplayHeight(), mFormat(),
      mFlags(),
      mPageFlipCount(),
      mIsSecure(isSecure),
      mSecureLayerVisible(false),
      mLayerStack(NO_LAYER_STACK),
      mOrientation(),
      mPowerMode(HWC_POWER_MODE_OFF),
      mActiveConfig(0)
{
    Surface* surface;
    mNativeWindow = surface = new Surface(producer, false);  // 创建一个surface
    ANativeWindow* const window = mNativeWindow.get(); // 获取一个本地窗口
    char property[PROPERTY_VALUE_MAX];
 
    /*
     * Create our display's surface
     */
 
    EGLSurface eglSurface;
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (config == EGL_NO_CONFIG) {
        config = RenderEngine::chooseEglConfig(display, format);
    }
    eglSurface = eglCreateWindowSurface(display, config, window, NULL);
    eglQuerySurface(display, eglSurface, EGL_WIDTH,  &mDisplayWidth);
    eglQuerySurface(display, eglSurface, EGL_HEIGHT, &mDisplayHeight);
 
    // Make sure that composition can never be stalled by a virtual display
    // consumer that isn't processing buffers fast enough. We have to do this
    // in two places:
    // * Here, in case the display is composed entirely by HWC.
    // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
    //   window's swap interval in eglMakeCurrent, so they'll override the
    //   interval we set here.
    if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
        window->setSwapInterval(window, 0);
 
    mConfig = config;
    mDisplay = display;
    mSurface = eglSurface;
    mFormat  = format;
    mPageFlipCount = 0;
    mViewport.makeInvalid();
    mFrame.makeInvalid();
 
    // virtual displays are always considered enabled
    mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ?
                  HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
 
    // Name the display.  The name will be replaced shortly if the display
    // was created with createDisplay().
    switch (mType) {
        case DISPLAY_PRIMARY:
            mDisplayName = "Built-in Screen";
            break;
        case DISPLAY_EXTERNAL:
            mDisplayName = "HDMI Screen";
            break;
        default:
            mDisplayName = "Virtual Screen";    // e.g. Overlay #n
            break;
    }
 
    mPanelInverseMounted = false;
    // Check if panel is inverse mounted (contents show up HV flipped)
    property_get("persist.panel.inversemounted", property, "0");
    mPanelInverseMounted = !!atoi(property);
 
    // initialize the display orientation transform.
    setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
 
#ifdef NUM_FRAMEBUFFER_SURFACE_BUFFERS
    surface->allocateBuffers();
#endif
}


初始化第三部分:

    // make the GLContext current so that we can create textures when creating Layers
    // (which may happens before we render something)
    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
 
    mEventControlThread = new EventControlThread(this);
    mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
 
    // set a fake vsync period if there is no HWComposer
    if (mHwc->initCheck() != NO_ERROR) {
        mPrimaryDispSync.setPeriod(16666667);
    }
 
    // initialize our drawing state
    mDrawingState = mCurrentState;
 
    // set initial conditions (e.g. unblank default device)
    initializeDisplays();  // 设置初始的layer数据
 
    // start boot animation
    startBootAnim();  // 开机动画设置


SurfaceFlinger init完成之后会执行它的run函数使之进入死循环,去等待vsync信号: waitForEvent()


总结:

至此SurfaceFlinger的初始话工作完成但这才是开始, androidsurface系统值得我们去深究去探索.

Android6.0 显示系统(五) SurfaceFlinger服务

SurfaceFlinger是一个独立的进程,我们来看下init.rc关于SurfaceFlinger的代码,我们可以看到SurfaceFlinger是属于core服务的。 service surfa...
  • kc58236582
  • kc58236582
  • 2016年10月10日 10:57
  • 6603

SurfaceFlinger简介

1. SurfaceFlinger背景知识         SurfaceFlinger 是一个独立的Service, 它接收所有Window的Surface作为输入,根据ZOrder, 透明度,大小...
  • wlwl0071986
  • wlwl0071986
  • 2016年03月22日 14:53
  • 1955

Android应用程序与SurfaceFlinger服务的关系概述和学习计划

SurfaceFlinger服务负责绘制Android应用程序的UI,它的实现相当复杂,要从正面分析它的实现不是一件容易的事。既然不能从正面分析,我们就想办法从侧面分析。说到底,无论SurfaceFl...
  • Luoshengyang
  • Luoshengyang
  • 2012年08月13日 00:56
  • 100299

Android SurfaceFlinger之SurfaceFlinger启动过程

Android SurfaceFlinger之SurfaceFlinger启动过程
  • ztguang
  • ztguang
  • 2017年03月22日 09:52
  • 479

DisplayManagerService 上层到surfaceflinger流程分析

DisplayManagerService 的启动是在systemserver中;// Display manager is needed to provide display metrics bef...
  • u010865783
  • u010865783
  • 2017年01月19日 15:35
  • 1911

Android6.0 显示系统(二) SurfaceFlinger创建Surface

接上篇博客分析到SurfaceComposerClient中调用createSurface函数会最后调用到SurfaceFlinger的Client的createSurface函数。 我们来看下这个函...
  • kc58236582
  • kc58236582
  • 2016年09月27日 15:17
  • 2654

【Android】Android SurfaceFlinger之OpenGL ES

1、OpenGL ES在Android系统中,直接面向终端用户的便是GUI,可以说任何一款产品的UI都是至关重要的,是用户可以实实在在感受到的东西,是最直观的、最易被感知的东西。SurfaceFlin...
  • iEearth
  • iEearth
  • 2017年01月25日 15:24
  • 1737

SurfaceFlinger详解

最近再看SurfaceFlinger的相关东西,看到网上一篇文章十分优秀,转载过来,以做参考学习...
  • yangrendong
  • yangrendong
  • 2014年08月11日 16:35
  • 6689

SurfaceFlinger中图像合成流程

android中图像的显示是通过HWComposer合成的,(不支持硬件composer的不考虑,现在基本都支持)。 硬件支持合成就是你输入多路视频,图像信号,出来一路合成好的数据。 硬件合成只支持...
  • u014409795
  • u014409795
  • 2016年05月09日 17:20
  • 807

App的启动过程(8)surfaceflinger的启动

接下来就是怎样把BufferQueue中数据,也就是GraphicBuffer中的数据显示到屏幕上,这就是surfaceflinger做的事情。          先说surfaceflinger的...
  • lin20044140410
  • lin20044140410
  • 2017年06月01日 17:37
  • 503
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:SurfaceFlinger 分析 一
举报原因:
原因补充:

(最多只允许输入30个字)