SurfaceFlinger analysis

SurfaceFlinger

1. SurfaceFlingerStart Process

SurfaceFlinger Thread is started by< span style="font-family:Times New Roman">kenerl after loading the init.rc file ,Executesystem/binExecutable files under the folder:surfaceflinger,Startmainfunction:

See the timing chart:

Start mainCreate your own thread after function, /span>and limitedbinderThe maximum number of threads is4pcs,Join the thread pool after the initial words :

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

 < /p>

The first part of initialization:

Mainfunction Callsurface flingerinitfunction, YesEGL, RenderEngineWait for initialization:

 mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(mEGLDisplay, NULL, NULL); // EGL initialization action sp vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true, "app"); // Virtualized Vsync App UI part mEventThread = new EventThread(vsyncSrc); sp sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, sfVsyncPhaseOffsetNs, true, "sf"); // Virtualized Vsync SF synthesis part mSFEventThread = new EventThread(sfVsyncSrc); mEventQueue.setEventThread(mSFEventThread); // Initialize the H/W composer object. There may or may n ot be an // actual hardware composer underneath. mHwc = DisplayUtils::getInstance()->getHWCInstance(this, *static_cast(this)); // initialize 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) . EGLI won’t talk about it at the beginning,The interesting thing is google Two different examplesVsyncSource: vsyncSrcandsfvsyncSrc span>One ​​isapp uivsyncthe other issurfaceflinger compositevsync,They just passed hardware layer by layer vsync virtualized.

They are based onsfVsyncPhaseOffsetNs andvsyncPhaseOffsetNs strong>The two relative offsets will

app UIdrawing and SFComposition distinction

where Phase Offset 1, 2 The value of can be changed, The purpose of this is to avoid waking up at the same timeapp UIrendering andSFcompositing is causing the wrong< /span>CPUResource preemption.

(2). Next start the aboveEventThread.

The constructor of EventThread just initializes some data< span style="font-family:Times New Roman">,重What I want is itsonFirstReffunction(When using strong pointers, < /span>will triggeronFirstRef function )

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

RunStartthreadloop:One ​​of the important functions: waitForEvent,

( 3 ) HWcomposerinitialization:

HWComposer::HWComposer( const sp& 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(); // Load preparation framebuffer hal module, and finally load the gralloc.XX.so dynamic library loadHwcModule(); // The hardware acceleration module will finally load the corresponding hwcomposer.XX.so dynamic library for each platform... if (needVSyncThread) {/ / we don't have VSYNC support, we need to fake it mVSyncThread = new VSyncThread(*this); // Vsync cycle control}}

HWcomposer Two of the most important tasks for the initialization of FB are loadingFB HALand Hwcmodule,They prepare data for hardware synthesis

( 4). According to EGL displayand pixel format creationRenderEngine,and get the currentEGLContext

Next look at the second part of initialization:< /h4>

 // initialize our non-virtual displays for (size_t i=0; iisConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {// All non-virtual displays are currently considered secure. bool isSecure = true; createBuilti nDisplayLocked(type); wp token = mBuiltinDisplays[i]; sp producer; sp consumer; BufferQueue::createBufferQueue(&producer, &consumer, new GraphicBufferAlloc()); sp fbs = new FramebufferSurface(*mHwc, i, consumer); int32_t hwcId = allocateHwcDisplayId(type); sp 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). initializationBufferQueue,this< span style="font-family:Times New Roman">Queueis the key bridge between producerIGraphicBufferProducer and consumer IGraphicBufferConsumer,

( 2). Create oneFramebufferSurface

( 3). Initialize eachDisplayD evice, Each display device will be packaged as oneDisplayDevice,such asHDMIetc< /p>

DisplayDevice::DisplayDevice( const sp& flinger, DisplayType type, int32_t hwcId, int format, bool isSecure, const wp& displayToken, const sp& displaySurface, const sp& 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(), m PageFlipCount(), mIsSecure(isSecure), mSecureLayerVisible(false), mLayerStack(NO_LAYER_STACK), mOrientation(), mPowerMode(HWC_POWER_MODE_OFF), mActiveConfig(0)( Surface* surface; mNativeWindow = surface = new Surface(producer, false); / / Create a surface ANativeWindow* const window = mNativeWindow.get(); // Get a local window 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, &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 // i n 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"; b reak; default: mDisplayName = "Virtual Screen"; // eg 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} 


The third part of initialization:

 // make the GLContext current so that we can create textures when creating Layers // (which may happen 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 (eg unblank default device) initializeDisplays(); // set initial layer data // start boot animation startBootAnim(); // boot animation settings

After SurfaceFlinger initafter completion, will implement itrunFunction,make it into an endless loop, Go and waitvsyncSignal:waitForEvent()

Summary:

So farSurfaceFlinger span>’s initial speech work completed,But this is the beginning, androidof surfaceThe system is worthy of our investigation,Go to explore.

Leave a Comment

Your email address will not be published.