SurfaceFlinger研究報告

SurfaceFlinger研究報告

SurfaceFlinger研究報告                                                                                                                                       1
一.綜述與SurfaceFlinger的類結構                                                                                                         2
二.SurfaceFlinger進程                                                                                                                                 3
1.進程的啓動                                                                                                                                      3
2.SurfaceFlinger主線程的啓動                                                                                                       4
3.SurfaceFlinger主線程的初始化                                                                                                  4
4.SurfaceFlinger主線程的運行                                                                                                       4
三.DisplayHardware類                                                                                                                                6
1.DisplayHardware的創建                                                                                                               6
2.DisplayEventThread                                                                                                                        7
3.DisplayHardware的初始化                                                                                                           9
FramebufferNativeWindow                                                                                                   14
fb_device_open                                                                                                                        15
mapFrameBufferLocked                                                                                                         17
gralloc_alloc_framebuffer_locked                                                                                       20
DisplayHardware::init                                                                                                             22
4.DisplayHardware::flip                                                                                                                   22
四.handlePageFlip函數                                                                                                                             24
1.State                                                                                                                                                 25
2.lockPageFlip                                                                                                                                    25
<1>mQueuedFrames                                                                                                               28
<2>more frames                                                                                                                       29
<3>SurfaceTexture::updateTexImage                                                                               29
3.unlockPageFlip                                                                                                                                32
4.handleRepaint                                                                                                                                32
<1>setupHardwareComposer                                                                                               32
<2>composeSurfaces                                                                                                              33
5.postFramebuffer                                                                                                                            34
6.handleTransaction                                                                                                                         35

.綜述與SurfaceFlinger 的類結構

C:\DOCUME~1\BXSUN~1.VIA\LOCALS~1\Temp\enhtmlclip\Image.png
總體來說, SurfaceFlinger的作用是爲客戶進程上的 view提供繪畫內存,並把這些 View經過compose 之後,顯示在屏幕上。上圖顯示了在 SurfaceFlinger進程中使用到的各種類及其關係。我們從 ISurface說起,來詳細介紹這個類圖中的各個類。 SurfaceFlinger進程在收到客戶進程創建 ISurface的請求後,首先是根據需求創建 LayerBaseClient,然後由這個LayerBaseClient創建 ISurface,當然各種不同的LayerBaseClient創建的 ISurface也是不同的,ISurface的功能就是獲取 ISurfaceTexture,客戶進程通過這個接口與 SurfaceFlinger進程上的服務端通信,進行 lockunlock 之類的操作。而只有 Layer類返回的ISurface 接口才能返回有內容的 ISurfaceTexture實例,其他的ISurface返回的內容都是空的。 Layer類的ISurface 接口實際上是返回的 Layer類中的成員變量mSurfaceTexture,它是一個 SurfaceTextureLayer實例,它繼承自SurfaceTexture類。 SurfaceTexture類是一個非常重要的類,基本上它包括兩個密不可分的部分,一個是作爲服務端實現了 ISurfaceTexture接口,與客戶端通信,它包含有 32GraphicBuffer ,當然他們都是在需要的時候才分配內存,客戶端所進行的操作都是針對這個內存的, SurfaceTexture中有對這些內存的同步和管理功能;另外一個功能就是根據客戶端的畫好的內存生成 OpenGL|ES image,這個image 最終是要交給 SurfaceFlingerComposer 混合的,SurfaceTexture的內存實際上就是一個讀寫隊列,客戶端會不斷要求添加新的幀,SurfaceFlinger的主線程中會去讀取這個幀。有了要顯示的內容,剩下的工作就是要把它顯示到屏幕上了。 SurfaceFlniger中所有和顯示相關的動作都封裝在 Displayhardware類中,這個類的實例指針是保存在 GraphicPlane實例中,它是SurfaceFlinger的一個成員變量,它代表了一塊屏幕,目前只有一個,實際上 SurfaceFlinger可以支持多塊屏幕。Displayhardware中包含一個 FramebufferNativeWindow實例指針,它纔是真正打開加載硬件設備的類,它繼承自 ANativeWindow類,它打開了兩個設備,一個是 framebuffer,一個是gralloc framebuffer用於寫屏幕, gralloc用於從framebuffer 中分配內存,實際上 FramebufferNativeWindow中的有兩個NativeBuffer ,即所謂的 front bufferback buffer ,它們的內存就是從 framebuffer中分配的。至此,我們對 SurfaceFlinger中各個類有了大概的瞭解,下面詳細說明 SurfaceFlinger是如何把客戶進程的UI顯示到屏幕上的。

.SurfaceFlinger進程

1.進程的啓動

init.rc中,啓動了 surfaceflinger服務,
service surfaceflinger /system/bin/surfaceflinger
這個可執行文件是在 frameworks/base/cmds/surfaceflinger/main_surfaceflinger.cpp 編譯出來的,該文件的內容非常簡單,如下所示:
int main(int argc, char** argv) {
    SurfaceFlinger::publishAndJoinThreadPool();
    return 0;
}
我們來看 SurfaceFlinger類的定義
frameworks/base/services/surfaceflinger/SurfaceFlinger.h
class SurfaceFlinger :
        public BinderService<SurfaceFlinger>,
        public BnSurfaceComposer,
        public IBinder::DeathRecipient,
        protected Thread
在它的基類 BinderService類中,定義了publishAndJoinThreadPool函數,它是一個模板類,該函數定義如下:
static void publishAndJoinThreadPool() {
        sp<ProcessState> proc(ProcessState::self());
        sp<IServiceManager> sm(defaultServiceManager());
        sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
    }
這與我們在前面分析 Binder的時候,添加服務的過程是相同的,同時,我們看到 SurfaceFlinger類也從是BnSurfaceComposer 繼承的, BnSurfaceComposer是在frameworks/base/include/surfaceflinger/ISurfaceComposer.h 定義的,它從 BnInterface<ISurfaceComposer>繼承而來,也就是說SurfaceFlinger ISurfaceComposer接口的服務器端類

2.SurfaceFlinger主線程的啓動

從前面創建 SurfaceFlinger服務的時候,我們知道SufaceFlinger的類繼承結構, SurfaceFlinger繼承自Thread ,看下面的代碼
void SurfaceFlinger::onFirstRef()
{
    run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);

    // Wait for the main thread to be done with its initialization
    mReadyToRunBarrier.wait();
}
我們從這裏可以看到,它調用了 Thread.run函數,該函數會啓動一個新的線程, readToRun是該線程的初始化函數,在線程中將運行 threadLoop函數,mReadyToRunBarrier.wait(); 是爲了等待線程啓動起來,也就是說,在 init進程啓動 SurfaceFlinger服務進程之後,創建 SurfaceFlinger實例,並在該實例第一次得到引用的時候,會啓動一個新的線程,這個線程就是 調用的就是SurfaceFlinger.threadLoop 函數。

3.SurfaceFlinger主線程的初始化

SurfaceFlinger::readToRun 函數主要用於線程的初始化,其中最關鍵的是調用了 DisplayHardware::makeCurrent,該函數把當前線程與OpenGL|ES Context綁定起來,後面的繪畫都是在這個 context中進行的。

4.SurfaceFlinger主線程的運行

bool SurfaceFlinger::threadLoop()
{
    waitForEvent();

    // check for transactions
    if (UNLIKELY(mConsoleSignals)) {
        handleConsoleEvents();
    }

    // if we're in a global transaction, don't do anything.
    const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
    uint32_t transactionFlags = peekTransactionFlags(mask);
    if (UNLIKELY(transactionFlags)) {
        handleTransaction(transactionFlags);
    }

    // post surfaces (if needed)
    handlePageFlip();

    if (mDirtyRegion.isEmpty()) {
        // nothing new to do.
        return true;
    }

    if (UNLIKELY(mHwWorkListDirty)) {
        // build the h/w work list
        handleWorkList();
    }

    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    if (LIKELY(hw.canDraw())) {
        // repaint the framebuffer (if needed)

        const int index = hw.getCurrentBufferIndex();
        GraphicLog& logger(GraphicLog::getInstance());

        logger.log(GraphicLog::SF_REPAINT, index);
        handleRepaint();

        // inform the h/w that we're done compositing
        logger.log(GraphicLog::SF_COMPOSITION_COMPLETE, index);
        hw.compositionComplete();

        logger.log(GraphicLog::SF_SWAP_BUFFERS, index);
        postFramebuffer();

        logger.log(GraphicLog::SF_REPAINT_DONE, index);
    } else {
        // pretend we did the post
        hw.compositionComplete();
        usleep(16667); // 60 fps period
    }
    return true;
}
waitForEvent
函數在 Surface研究報告中已經有詳細說明;下面將分別對 handleConsoleEventhandleTransaction handlePageFlip handleRepaintpostFrameBuffer 等進行說明

.DisplayHardware

SurfaceFlinger所有重要的工作都在threadLoop函數中進行。在分析 threadLoop函數中的其他函數之前,我們需要先分析 DisplayHardware類。

1.DisplayHardware的創建

而在 SurfaceFlinger::readyToRun中,new DisplayHardware, 並設置給 GraphicPlane
virtual void onFirstRef() {
            run("DisplayEventThread", PRIORITY_URGENT_DISPLAY);
        }
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);
    }
。。。。。。
}

2.DisplayEventThread

DisplayHardware派生自DisplayHardwareBase ,其類圖如下:
C:\DOCUME~1\BXSUN~1.VIA\LOCALS~1\Temp\enhtmlclip\Image(1).png

DisplayHardware在構造函數中new了一個 DisplayEventThreadBaseDisplayEventThreadBase 類在onFirstRef的時候會啓動自己
run("DisplayEventThread",PRIORITY_URGENT_DISPLAY);
bool DisplayHardwareBase::DisplayEventThread::threadLoop()
{
    int err = 0;
    char buf;
    int fd;

    fd = open(kSleepFileName, O_RDONLY, 0);
    do {
      err = read(fd, &buf, 1);
    } while (err < 0 && errno == EINTR);
    close(fd);
    LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno));
    if (err >= 0) {
        sp<SurfaceFlinger> flinger = mFlinger.promote();
        LOGD("About to give-up screen, flinger = %p", flinger.get());
        if (flinger != 0) {
            mBarrier.close();
            flinger->screenReleased(0);
                     ----->android_atomic_or(eConsoleReleased, &mConsoleSignals);
                     ----->mEventQueue.invalidate();
                                       ----->mCondition.signal();//
這會使得 MessageQueue::waitMessage函數退出等待
            mBarrier.wait();//
等待
        }
    }
    fd = open(kWakeFileName, O_RDONLY, 0);
    do {
      err = read(fd, &buf, 1);
    } while (err < 0 && errno == EINTR);
    close(fd);
    LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_WAKE failed (%s)", strerror(errno));
    if (err >= 0) {
        sp<SurfaceFlinger> flinger = mFlinger.promote();
        LOGD("Screen about to return, flinger = %p", flinger.get());
        if (flinger != 0)
            flinger->screenAcquired(0);
                   ----->android_atomic_or(eConsoleAcquired, &mConsoleSignals);
                   ----->mEventQueue.invalidate();
                                       ----->mCondition.signal();//
這會使得 MessageQueue::waitMessage函數退出等待
    }
    return true;
}
對應的在 SurfaceFlinger::threadLoop
------>handleConsoleEvents
void SurfaceFlinger::handleConsoleEvents()
{
    // something to do with the console
    const DisplayHardware& hw = graphicPlane(0).displayHardware();

    int what = android_atomic_and(0, &mConsoleSignals);
    if (what & eConsoleAcquired) {
        hw.acquireScreen();
                ----->mScreenAcquired = true;
        // this is a temporary work-around, eventually this should be called
        // by the power-manager
        SurfaceFlinger::turnElectronBeamOn(mElectronBeamAnimationMode);
    }

    if (what & eConsoleReleased) {
        if (hw.isScreenAcquired()) {
                    ----->return mScreenAcquired;
            hw.releaseScreen();
                    ----->mBarrier.open();
                    ----->mScreenAcquired = false;
        }
    }

    mDirtyRegion.set(hw.bounds());
}
SurfaceFlinger是在初始化函數readToRun的時候創建了 DisplayHardware實例,在構造該實例的過程中,該實例又啓動了新的線程 DisplayEventThread,該線程與SurfaceFlinger 主線程之間,交替切換運行。 DisplayEventThread線程首先讀取kSleepFileName文件,並讀取一個字節的內容,然後通知 SurfaceFlinger釋放屏幕,SurfaceFlinger->screenReleased 函數將使得 SurfaceFlinger::threadLoop中的waitForEvent 函數退出消息等待,並把 SurfaceFlingerSignal 設置爲eConsoleReleased,然後 DisplayEventThread線程調用mBarrier.wait() 進入等待狀態。 SurfaceFlinger::threadLoop函數從waitForEvent 退出後,進入 handleConsoleEvents函數,檢測到eConsoleReleased信號,由於默認情況下, DisplayHardware中的mScreenAcquired true,將會執行 hw.releaseScreen(),也就是說,DisplayEventThread線程將會被激活,但是由於它的優先級與 SurfaceFilinger的主線程的優先級是一樣的,所以不會搶佔主線程運行。這樣看來,這兩個線程不斷的交替運行, mScreenAcquired不斷的被設置爲true false,那麼它的作用是什麼呢?在 threadLoop函數裏,使用DisplayHardware::canDraw來判斷是否進行畫的動作,這個 canDraw就是返回mScreenAcquired ,這樣看來,通過 DisplayEventThread線程主要是讓主線程的消息隊列處理能定期退出,交給 DispayHardware來畫屏幕。

3.DisplayHardware的初始化

void DisplayHardware::init(uint32_t dpy)
{
    mNativeWindow = new FramebufferNativeWindow();------<1>------
    framebuffer_device_t const * fbDev = mNativeWindow->getDevice();
    if (!fbDev) {
        LOGE("Display subsystem failed to initialize. check logs. exiting...");
        exit(0);
    }

    int format;
    ANativeWindow const * const window = mNativeWindow.get();
    window->query(window, NATIVE_WINDOW_FORMAT, &format);
    mDpiX = mNativeWindow->xdpi;
    mDpiY = mNativeWindow->ydpi;
    mRefreshRate = fbDev->fps;

    EGLint w, h, dummy;
    EGLint numConfigs=0;
    EGLSurface surface;
    EGLContext context;
    EGLBoolean result;
    status_t err;

    // initialize EGL
    EGLint attribs[] = {
            EGL_SURFACE_TYPE,       EGL_WINDOW_BIT,
            EGL_NONE,               0,
            EGL_NONE
    };

    // debug: disable h/w rendering
    char property[PROPERTY_VALUE_MAX];
    if (property_get("debug.sf.hw", property, NULL) > 0) {
        if (atoi(property) == 0) {
            LOGW("H/W composition disabled");
            attribs[2] = EGL_CONFIG_CAVEAT;
            attribs[3] = EGL_SLOW_CONFIG;
        }
    }

    // TODO: all the extensions below should be queried through
    // eglGetProcAddress().

    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglInitialize(display, NULL, NULL);
    eglGetConfigs(display, NULL, 0, &numConfigs);

    EGLConfig config = NULL;
    err = selectConfigForPixelFormat(display, attribs, format, &config);
    LOGE_IF(err, "couldn't find an EGLConfig matching the screen format");
    
    EGLint r,g,b,a;
    eglGetConfigAttrib(display, config, EGL_RED_SIZE,   &r);
    eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
    eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,  &b);
    eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);

    if (mNativeWindow->isUpdateOnDemand()) {
        mFlags |= PARTIAL_UPDATES;
    }
    
    if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
        if (dummy == EGL_SLOW_CONFIG)
            mFlags |= SLOW_CONFIG;
    }

    /*
     * Create our main surface
     */

    surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
    eglQuerySurface(display, surface, EGL_WIDTH,  &mWidth);
    eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);

    if (mFlags & PARTIAL_UPDATES) {
        // if we have partial updates, we definitely don't need to
        // preserve the backbuffer, which may be costly.
        eglSurfaceAttrib(display, surface,
                EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
    }

    if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
        if (dummy == EGL_BUFFER_PRESERVED) {
            mFlags |= BUFFER_PRESERVED;
        }
    }
    
    /* Read density from build-specific ro.sf.lcd_density property
     * except if it is overridden by qemu.sf.lcd_density.
     */
    if (property_get("qemu.sf.lcd_density", property, NULL) <= 0) {
        if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
            LOGW("ro.sf.lcd_density not defined, using 160 dpi by default.");
            strcpy(property, "160");
        }
    } else {
        /* for the emulator case, reset the dpi values too */
        mDpiX = mDpiY = atoi(property);
    }
    mDensity = atoi(property) * (1.0f/160.0f);


    /*
     * Create our OpenGL ES context
     */
    

    EGLint contextAttributes[] = {
#ifdef EGL_IMG_context_priority
#ifdef HAS_CONTEXT_PRIORITY
#warning "using EGL_IMG_context_priority"
        EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG,
#endif
#endif
        EGL_NONE, EGL_NONE
    };
    context = eglCreateContext(display, config, NULL, contextAttributes);

    mDisplay = display;
    mConfig  = config;
    mSurface = surface;
    mContext = context;
    mFormat  = fbDev->format;
    mPageFlipCount = 0;

    /*
     * Gather OpenGL ES extensions
     */

    result = eglMakeCurrent(display, surface, surface, context);
    if (!result) {
        LOGE("Couldn't create a working GLES context. check logs. exiting...");
        exit(0);
    }

    GLExtensions& extensions(GLExtensions::getInstance());
    extensions.initWithGLStrings(
            glGetString(GL_VENDOR),
            glGetString(GL_RENDERER),
            glGetString(GL_VERSION),
            glGetString(GL_EXTENSIONS),
            eglQueryString(display, EGL_VENDOR),
            eglQueryString(display, EGL_VERSION),
            eglQueryString(display, EGL_EXTENSIONS));

    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);


#ifdef EGL_ANDROID_swap_rectangle
    if (extensions.hasExtension("EGL_ANDROID_swap_rectangle")) {
        if (eglSetSwapRectangleANDROID(display, surface,
                0, 0, mWidth, mHeight) == EGL_TRUE) {
            // This could fail if this extension is not supported by this
            // specific surface (of config)
            mFlags |= SWAP_RECTANGLE;
        }
    }
    // when we have the choice between PARTIAL_UPDATES and SWAP_RECTANGLE
    // choose PARTIAL_UPDATES, which should be more efficient
    if (mFlags & PARTIAL_UPDATES)
        mFlags &= ~SWAP_RECTANGLE;
#endif

    LOGI("EGL informations:");
    LOGI("# of configs : %d", numConfigs);
    LOGI("vendor    : %s", extensions.getEglVendor());
    LOGI("version   : %s", extensions.getEglVersion());
    LOGI("extensions: %s", extensions.getEglExtension());
    LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
    LOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);

    LOGI("OpenGL informations:");
    LOGI("vendor    : %s", extensions.getVendor());
    LOGI("renderer  : %s", extensions.getRenderer());
    LOGI("version   : %s", extensions.getVersion());
    LOGI("extensions: %s", extensions.getExtension());
    LOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize);
    LOGI("GL_MAX_VIEWPORT_DIMS = %d x %d", mMaxViewportDims[0], mMaxViewportDims[1]);
    LOGI("flags = %08x", mFlags);

    // Unbind the context from this thread
    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);


    // initialize the H/W composer
    mHwc = new HWComposer(mFlinger);
    if (mHwc->initCheck() == NO_ERROR) {
        mHwc->setFrameBuffer(mDisplay, mSurface);
    }
}
代碼分析如下:

FramebufferNativeWindow

class FramebufferNativeWindow
    : public EGLNativeBase<
        ANativeWindow,
        FramebufferNativeWindow,
        LightRefBase<FramebufferNativeWindow> >
FramebufferNativeWindow
繼承自 ANativeWindow,其構造函數如下:
FramebufferNativeWindow::FramebufferNativeWindow()
    : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
{
    hw_module_t const* module;
    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {//
得到gralloc 模塊
        int stride;
        int err;
        int i;
        err = framebuffer_open(module, &fbDev);//
從模塊中得到fb設備
        LOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));
        
        err = gralloc_open(module, &grDev);//
從模塊中得到gpu0設備,前面已經分析過
        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 = NUM_FRAME_BUFFERS;
        mNumFreeBuffers = NUM_FRAME_BUFFERS;
        mBufferHead = mNumBuffers-1;

        //
創建兩個 native buffer
        for (i = 0; i < mNumBuffers; i++)
        {
                buffers[i] = new NativeBuffer(
                        fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
        }

        //
native buffer分配內存,由於使用了GRALLOC_USAGE_HW_FB,所以是從 framebuffer中分配的,而不是從asmem中分配的
        for (i = 0; i < mNumBuffers; i++)
        {
                err = grDev->alloc(grDev,
                        fbDev->width, fbDev->height, fbDev->format,
                        GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride);

                LOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s",
                        i, fbDev->width, fbDev->height, strerror(-err));

                if (err)
                {
                        mNumBuffers = i;
                        mNumFreeBuffers = i;
                        mBufferHead = mNumBuffers-1;
                        break;
                }
        }

        const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;
        const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
        const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
        const_cast<int&>(ANativeWindow::minSwapInterval) =
            fbDev->minSwapInterval;
        const_cast<int&>(ANativeWindow::maxSwapInterval) =
            fbDev->maxSwapInterval;
    } else {
        LOGE("Couldn't get gralloc module");
    }

    ANativeWindow::setSwapInterval = setSwapInterval;
    ANativeWindow::dequeueBuffer = dequeueBuffer;
    ANativeWindow::lockBuffer = lockBuffer;
    ANativeWindow::queueBuffer = queueBuffer;
    ANativeWindow::query = query;
    ANativeWindow::perform = perform;
}
先來看 framebuffer_open函數,它定義於hardware/libhardware/include/hardware/fb.h,它實際調用了hardware/libhardware/modules/gralloc/framebuffer.cpp文件中的fb_device_open 函數

fb_device_open

int fb_device_open(hw_module_t const* module, const char* name,
        hw_device_t** device)
{
    int status = -EINVAL;
    if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {
        alloc_device_t* gralloc_device;
        status = gralloc_open(module, &gralloc_device);
        if (status < 0)
            return status;

        /* initialize our state here */
        fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
        memset(dev, 0, sizeof(*dev));

        /* initialize the procs */
        dev->device.common.tag = HARDWARE_DEVICE_TAG;
        dev->device.common.version = 0;
        dev->device.common.module = const_cast<hw_module_t*>(module);
        dev->device.common.close = fb_close;
        dev->device.setSwapInterval = fb_setSwapInterval;
        dev->device.post            = fb_post;
        dev->device.setUpdateRect = 0;

        private_module_t* m = (private_module_t*)module;
        status = mapFrameBuffer(m);
        if (status >= 0) {
            int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
            int format = (m->info.bits_per_pixel == 32)
                         ? HAL_PIXEL_FORMAT_RGBX_8888
                         : HAL_PIXEL_FORMAT_RGB_565;
            const_cast<uint32_t&>(dev->device.flags) = 0;
            const_cast<uint32_t&>(dev->device.width) = m->info.xres;
            const_cast<uint32_t&>(dev->device.height) = m->info.yres;
            const_cast<int&>(dev->device.stride) = stride;
            const_cast<int&>(dev->device.format) = format;
            const_cast<float&>(dev->device.xdpi) = m->xdpi;
            const_cast<float&>(dev->device.ydpi) = m->ydpi;
            const_cast<float&>(dev->device.fps) = m->fps;
            const_cast<int&>(dev->device.minSwapInterval) = 1;
            const_cast<int&>(dev->device.maxSwapInterval) = 1;
            *device = &dev->device.common;
        }
    }
    return status;
}
這個函數中最終要的是調用了 mapFrameBuffer函數,它有調用了mapFrameBufferLocked

mapFrameBufferLocked

int mapFrameBufferLocked(struct private_module_t* module)
{
    // already initialized...
    if (module->framebuffer) {
        return 0;
    }
    //
這裏是 graphic設備的兩個可能的路徑
    char const * const device_template[] = {
            "/dev/graphics/fb%u",
            "/dev/fb%u",
            0 };

    int fd = -1;
    int i=0;
    char name[64];

     //
這裏從設備得到 fd
    while ((fd==-1) && device_template[i]) {
        snprintf(name, 64, device_template[i], 0);
        fd = open(name, O_RDWR, 0);
        i++;
    }
    if (fd < 0)
        return -errno;

    struct fb_fix_screeninfo finfo;
    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
        return -errno;

    struct fb_var_screeninfo info;
    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
        return -errno;

    info.reserved[0] = 0;
    info.reserved[1] = 0;
    info.reserved[2] = 0;
    info.xoffset = 0;
    info.yoffset = 0;
    info.activate = FB_ACTIVATE_NOW;

    /*
     * Request NUM_BUFFERS screens (at lest 2 for page flipping)
     */
    //yres_virtual
y軸的虛擬值,如果我們是 page flipping,那麼虛擬高度就是實際高度的兩倍, yres是實際高度
    info.yres_virtual = info.yres * NUM_BUFFERS;


    uint32_t flags = PAGE_FLIP;
    //
把虛擬高度設置給設備
    if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) {
        info.yres_virtual = info.yres;
        flags &= ~PAGE_FLIP;
        LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");
    }

    if (info.yres_virtual < info.yres * 2) {
        // we need at least 2 for page-flipping
        info.yres_virtual = info.yres;
        flags &= ~PAGE_FLIP;
        LOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
                info.yres_virtual, info.yres*2);
    }

    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
        return -errno;

    uint64_t  refreshQuotient =
    (
            uint64_t( info.upper_margin + info.lower_margin + info.yres )
            * ( info.left_margin  + info.right_margin + info.xres )
            * info.pixclock
    );

    /* Beware, info.pixclock might be 0 under emulation, so avoid a
     * division-by-0 here (SIGFPE on ARM) */
    int refreshRate = refreshQuotient > 0 ? (int)(1000000000000000LLU / refreshQuotient) : 0;

    if (refreshRate == 0) {
        // bleagh, bad info from the driver
        refreshRate = 60*1000;  // 60 Hz
    }

    if (int(info.width) <= 0 || int(info.height) <= 0) {
        // the driver doesn't return that information
        // default to 160 dpi
        info.width  = ((info.xres * 25.4f)/160.0f + 0.5f);
        info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
    }
    //info.width
info.height是設備的寬度和高度,他們是以 mm爲單位的,infor.xres info.yres也是設備的寬度和高度,不過他們是以像素爲單位的, 1inch=25.4mm
    float xdpi = (info.xres * 25.4f) / info.width;
    float ydpi = (info.yres * 25.4f) / info.height;
    float fps  = refreshRate / 1000.0f;//fps
是每秒的幀數

    LOGI(   "using (fd=%d)\n"
            "id           = %s\n"
            "xres         = %d px\n"
            "yres         = %d px\n"
            "xres_virtual = %d px\n"
            "yres_virtual = %d px\n"
            "bpp          = %d\n"
            "r            = %2u:%u\n"
            "g            = %2u:%u\n"
            "b            = %2u:%u\n",
            fd,
            finfo.id,
            info.xres,
            info.yres,
            info.xres_virtual,
            info.yres_virtual,
            info.bits_per_pixel,
            info.red.offset, info.red.length,
            info.green.offset, info.green.length,
            info.blue.offset, info.blue.length
    );

    LOGI(   "width        = %d mm (%f dpi)\n"
            "height       = %d mm (%f dpi)\n"
            "refresh rate = %.2f Hz\n",
            info.width,  xdpi,
            info.height, ydpi,
            fps
    );


    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
        return -errno;

    if (finfo.smem_len <= 0)
        return -errno;


    module->flags = flags;
    module->info = info;
    module->finfo = finfo;
    module->xdpi = xdpi;
    module->ydpi = ydpi;
    module->fps = fps;

    /*
     * map the framebuffer
     */

    int err;
    size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual);
    module->framebuffer = new private_handle_t(dup(fd), fbSize, 0);

    module->numBuffers = info.yres_virtual / info.yres;
    module->bufferMask = 0;

    void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if (vaddr == MAP_FAILED) {
        LOGE("Error mapping the framebuffer (%s)", strerror(errno));
        return -errno;
    }
    module->framebuffer->base = intptr_t(vaddr);
    memset(vaddr, 0, fbSize);
    return 0;
}
fb_device_open
在調用該函數之後,得到了顯示設備的詳細信息,並存儲在 fb_context_t結構中返回,同時顯示設備文件被映射到內存中,並創建了 frambuffer,這個frambuffer handle存儲在 module中。

gralloc_alloc_framebuffer_locked

FramebufferNativeWindow構造函數中,同樣打開了 GPU0設備,並從設備分配內存給 NativeuBuffer,這個分配過程不同於上面從 ashmem中分配的過程,它使用了 GRALLOC_USAGE_HW_FB usage。其分配過程如下:
static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev,
        size_t size, int usage, buffer_handle_t* pHandle)
{
    private_module_t* m = reinterpret_cast<private_module_t*>(
            dev->common.module);

    // allocate the framebuffer
    //
moduleframebuffer 中獲取內存,如果這個 framebuffernull ,需要進行分配
    if (m->framebuffer == NULL) {
        // initialize the framebuffer, the framebuffer is mapped once
        // and forever.
        int err = mapFrameBufferLocked(m);
        if (err < 0) {
            return err;
        }
    }

    const uint32_t bufferMask = m->bufferMask;//buffermask
是用來表示當前有哪些緩衝區得到使用
    const uint32_t numBuffers = m->numBuffers;//
當前使用了幾個緩衝區,目前爲 2
    const size_t bufferSize = m->finfo.line_length * m->info.yres;//
注意這裏使用的是yres,也就是算出一個屏幕使用的內存大小
    if (numBuffers == 1) {
        // If we have only one buffer, we never use page-flipping. Instead,
        // we return a regular buffer which will be memcpy'ed to the main
        // screen when post is called.
        int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;
        return gralloc_alloc_buffer(dev, bufferSize, newUsage, pHandle);
    }

    if (bufferMask >= ((1LU<<numBuffers)-1)) {
        // We ran out of buffers.
        return -ENOMEM;
    }

    // create a "fake" handles for it
    intptr_t vaddr = intptr_t(m->framebuffer->base);
    private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size,
            private_handle_t::PRIV_FLAGS_FRAMEBUFFER);

    // find a free slot
    //
mask中找到一個空前的位置,並根據序號算出這個 buffer的起始地址
    for (uint32_t i=0 ; i<numBuffers ; i++) {
        if ((bufferMask & (1LU<<i)) == 0) {
            m->bufferMask |= (1LU<<i);
            break;
        }
        vaddr += bufferSize;
    }
    
    hnd->base = vaddr;
    hnd->offset = vaddr - intptr_t(m->framebuffer->base);//offset
表示與原始地址的位移
    *pHandle = hnd;

    return 0;
}
這樣,我們就爲 NatvieBuffer分配了一塊內存。綜上所述, DisplayHardware::init的調用流程如下:

DisplayHardware::init

----->new FramebufferNativeWindow
                ----->framebuffer_open
                              ----->fb_device_open(hw_module_t const* module, const char* name,hw_device_t** device)
                                          ----->mapFrameBuffer
                                                       ----->mapFrameBufferLocked(struct private_module_t* module)
               ----->gralloc_open
----->gralloc_alloc_framebuffer
               ----->gralloc_alloc_framebuffer_locked(alloc_device_t* dev,size_t size, int usage, buffer_handle_t* pHandle)
----->EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
----->surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
----->context = eglCreateContext(display, config, NULL, contextAttributes);
----->result = eglMakeCurrent(display, surface, surface, context);
----->eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
這裏涉及了幾個概念, nativewindowsurface context display,其中ANativeWindow android opengl es的接口結構,兩邊都在使用,在創建 Surface的時候,就會根據opengl es的版本不同,創建不同的 suface結構,並把ANativeWindow 中關於設備的詳細信息設置到這個 surface中,surface 的很多操作都是基於 ANativeWindow提供的函數的。surface顯然是一個顯示窗口的邏輯概念, display代表顯示設備,context是顯示的環境, makecurrentdisplay surface context聯繫到一起,並把context bind到當前的進程。

4.DisplayHardware::flip

它調用了 eglSwapBuffers
frameworks/base/opengl/libagl2/src/egl.cpp
eglSwapBuffers
----->egl_surface_t::swapBuffers
----->previousBuffer = buffer;
----->nativeWindow->queueBuffer(nativeWindow, buffer);
                ----->FramebufferNativeWindow::queueBuffer
                                  ----->fp_post(hardware/libhardware/modules/gralloc/framebuffer.cpp)
----->nativeWindow->dequeueBuffer(nativeWindow, &buffer)
----->egl_surface_t::bindDrawSurface
                   ----->gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &buffer);
從這些調用流程就可以看出, swapbuffer就是把當前的buffer,記錄爲 previousBuffer,然後把buffer 放回nativewindow,這裏其實有一個 post buffer的過程,最後從nativewindow中重新出隊列一個 buffer,然後把這個buffer設置給 opengl,作爲新的drawsurface buffer ,其中fb_post的代碼如下:
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
{
    if (private_handle_t::validate(buffer) < 0)
        return -EINVAL;

    fb_context_t* ctx = (fb_context_t*)dev;

    private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer);
    private_module_t* m = reinterpret_cast<private_module_t*>(
            dev->common.module);

    if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
        const size_t offset = hnd->base - m->framebuffer->base;
        m->info.activate = FB_ACTIVATE_VBL;
        m->info.yoffset = offset / m->finfo.line_length;
        if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
            LOGE("FBIOPUT_VSCREENINFO failed");
            m->base.unlock(&m->base, buffer);
            return -errno;
        }
        m->currentBuffer = buffer;
        
    } else {
        // If we can't do the page_flip, just copy the buffer to the front
        // FIXME: use copybit HAL instead of memcpy
        
        void* fb_vaddr;
        void* buffer_vaddr;
        
        m->base.lock(&m->base, m->framebuffer,
                GRALLOC_USAGE_SW_WRITE_RARELY,
                0, 0, m->info.xres, m->info.yres,
                &fb_vaddr);

        m->base.lock(&m->base, buffer,
                GRALLOC_USAGE_SW_READ_RARELY,
                0, 0, m->info.xres, m->info.yres,
                &buffer_vaddr);

        memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres);
        
        m->base.unlock(&m->base, buffer);
        m->base.unlock(&m->base, m->framebuffer);
    }
    
    return 0;
}
由於我們在 alloc buffer的時候,在函數gralloc_alloc_framebuffer_locked
private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size,
            private_handle_t::PRIV_FLAGS_FRAMEBUFFER);
所以,上面這段代碼走的是 ioctl的流程,這個ioctl相信是讓屏幕顯示相應位置的內容。

.handlePageFlip函數

該函數主要是進行 Buffer flip的,即把畫好的buffer swap到屏幕上
void SurfaceFlinger::handlePageFlip()
{
    bool visibleRegions = mVisibleRegionsDirty;
    const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
    visibleRegions |= lockPageFlip(currentLayers);

        const DisplayHardware& hw = graphicPlane(0).displayHardware();
        const Region screenRegion(hw.bounds());
        if (visibleRegions) {
            Region opaqueRegion;
            computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);

            /*
             *  rebuild the visible layer list
             */
            const size_t count = currentLayers.size();
            mVisibleLayersSortedByZ.clear();
            mVisibleLayersSortedByZ.setCapacity(count);
            for (size_t i=0 ; i<count ; i++) {
                if (!currentLayers[i]->visibleRegionScreen.isEmpty())
                    mVisibleLayersSortedByZ.add(currentLayers[i]);
            }

            mWormholeRegion = screenRegion.subtract(opaqueRegion);
            mVisibleRegionsDirty = false;
            invalidateHwcGeometry();
        }

    unlockPageFlip(currentLayers);

    mDirtyRegion.orSelf(getAndClearInvalidateRegion());
    mDirtyRegion.andSelf(screenRegion);
}

1.State

在分析 handlePageFlip之前,需要說清楚SurfaceFlinger的兩個成員變量 mDrawingStatemCurrentState ,它們都是 State類型的變量,State定義如下:
struct State {
        State() {
            orientation = ISurfaceComposer::eOrientationDefault;
            freezeDisplay = 0;
        }
        LayerVector     layersSortedByZ;
        uint8_t         orientation;
        uint8_t         orientationFlags;
        uint8_t         freezeDisplay;
    };
 
其中 LayerVector是一個有序的Vector,其中存取的都是 LayerBase實例指針,排序的標準是 LayerBase類的z order
mDrawingState
表示當前畫在屏幕上的 State,而mCurrentState 則表示當前正在處理的 State,也就是說mDrawingState previous State。由於在執行 handlePageFlip之前,已經執行了handleTransaction函數,其中的 commitTransaction函數中已經把mCurrentState賦值給 mDrawingState,所以在handlePageFlip 中,mDrawingState已經是最新的要顯示的 State

2.lockPageFlip

這個函數本身比較簡單,就是遍歷 mDrawingState中的LayerVector 中的LayerBase,然後調用這個實例的 lockPageFlip,所以關鍵是看這些實例的 lockPageFlip
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
    if (mQueuedFrames > 0) {-----<1>-----
        // Capture the old state of the layer for comparisons later
        const bool oldOpacity = isOpaque();
        sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;

        // signal another event if we have more frames pending
        if (android_atomic_dec(&mQueuedFrames) > 1) {-----<2>-----
            mFlinger->signalEvent();
        }

        if (mSurfaceTexture->updateTexImage() < NO_ERROR) {-----<3>-----
            // something happened!
            recomputeVisibleRegions = true;
            return;
        }

        // update the active buffer
        mActiveBuffer = mSurfaceTexture->getCurrentBuffer();

        const Rect crop(mSurfaceTexture->getCurrentCrop());
        const uint32_t transform(mSurfaceTexture->getCurrentTransform());
        const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
        if ((crop != mCurrentCrop) ||
            (transform != mCurrentTransform) ||
            (scalingMode != mCurrentScalingMode))
        {
            mCurrentCrop = crop;
            mCurrentTransform = transform;
            mCurrentScalingMode = scalingMode;
            mFlinger->invalidateHwcGeometry();
        }

        GLfloat textureMatrix[16];
        mSurfaceTexture->getTransformMatrix(textureMatrix);
        if (memcmp(textureMatrix, mTextureMatrix, sizeof(textureMatrix))) {
            memcpy(mTextureMatrix, textureMatrix, sizeof(textureMatrix));
            mFlinger->invalidateHwcGeometry();
        }

        uint32_t bufWidth  = mActiveBuffer->getWidth();
        uint32_t bufHeight = mActiveBuffer->getHeight();
        if (oldActiveBuffer != NULL) {
            if (bufWidth != uint32_t(oldActiveBuffer->width) ||
                bufHeight != uint32_t(oldActiveBuffer->height)) {
                mFlinger->invalidateHwcGeometry();
            }
        }

        mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
        if (oldOpacity != isOpaque()) {
            recomputeVisibleRegions = true;
        }

        glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        // update the layer size and release freeze-lock
        const Layer::State& front(drawingState());

        // FIXME: mPostedDirtyRegion = dirty & bounds
        mPostedDirtyRegion.set(front.w, front.h);

        if ((front.w != front.requested_w) ||
            (front.h != front.requested_h))
        {
            // check that we received a buffer of the right size
            // (Take the buffer's orientation into account)
            if (mCurrentTransform & Transform::ROT_90) {
                swap(bufWidth, bufHeight);
            }

            if (isFixedSize() ||
                    (bufWidth == front.requested_w &&
                    bufHeight == front.requested_h))
            {
                // Here we pretend the transaction happened by updating the
                // current and drawing states. Drawing state is only accessed
                // in this thread, no need to have it locked
                Layer::State& editDraw(mDrawingState);
                editDraw.w = editDraw.requested_w;
                editDraw.h = editDraw.requested_h;

                // We also need to update the current state so that we don't
                // end-up doing too much work during the next transaction.
                // NOTE: We actually don't need hold the transaction lock here
                // because State::w and State::h are only accessed from
                // this thread
                Layer::State& editTemp(currentState());
                editTemp.w = editDraw.w;
                editTemp.h = editDraw.h;

                // recompute visible region
                recomputeVisibleRegions = true;

                // we now have the correct size, unfreeze the screen
                mFreezeLock.clear();
            }

            LOGD_IF(DEBUG_RESIZE,
                    "lockPageFlip : "
                    "       (layer=%p), buffer (%ux%u, tr=%02x), "
                    "requested (%dx%d)",
                    this,
                    bufWidth, bufHeight, mCurrentTransform,
                    front.requested_w, front.requested_h);
        }
    }
}

<1>mQueuedFrames

首先說 mQueuedFrames這個成員變量,在lock的時候要求它大於 0,這個變量在初始化的時候等於 0,在onFrameQueued 函數中加一
void Layer::onFrameQueued() {
    android_atomic_inc(&mQueuedFrames);
    mFlinger->signalEvent();//
該函數將使得消息隊列返回一個 invalidate消息給SurfaceFlinger
}
這個onFrameQueued函數是註冊給 Layer中的SurfaceTexture ,在有Frame的時候通知 layer
void Layer::onFirstRef()
{
    LayerBaseClient::onFirstRef();

    struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {
        FrameQueuedListener(Layer* layer) : mLayer(layer) { }
    private:
        wp<Layer> mLayer;
        virtual void onFrameAvailable() {
            sp<Layer> that(mLayer.promote());
            if (that != 0) {
                that->onFrameQueued();
            }
        }
    };
    mSurfaceTexture = new SurfaceTextureLayer(mTextureName, this);
    mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
    mSurfaceTexture->setSynchronousMode(true);
    mSurfaceTexture->setBufferCountServer(2);
}
SurfaceTexture::queueBuffer中,有新的Buffer加入到隊列中時候,調用 listener回調,通知Layer 有新的Frame了,這時 Layer中的mQueueFrames 將加一,同時還會退出消息處理, threadLoop有機會處理這個frame。有個特別需要注意的是,爲什麼使用android_atomic_inc來給mQueuedFrames加一,這是因爲這個Layer::onFrameQueued是被SurfaceTexture 調用的,這個 SurfaceTexture實例是Binder 的服務器端,它在響應客戶端請求,想自己的隊列中添加frame的時候,實際上是運行在SurfaceFlinger進程的Binder線程中被調用,與 SurfaceFling的主線程不在同一個線程。

<2>more frames

如果有多待處理的幀,需要再次退出消息處理給後面的代碼機會處理。

<3>SurfaceTexture::updateTexImage

調用 SurfaceTexture::updateTexImage可以說是該函數最重要的代碼了
status_t SurfaceTexture::updateTexImage() {
    ST_LOGV("SurfaceTexture::updateTexImage");
    Mutex::Autolock lock(mMutex);

    if (mAbandoned) {
        ST_LOGE("calling updateTexImage() on an abandoned SurfaceTexture");
        return NO_INIT;
    }

    // In asynchronous mode the list is guaranteed to be one buffer
    // deep, while in synchronous mode we use the oldest buffer.
    if (!mQueue.empty()) {
        Fifo::iterator front(mQueue.begin());
        int buf = *front;

        // Update the GL texture object.
        EGLImageKHR image = mSlots[buf].mEglImage;
        if (image == EGL_NO_IMAGE_KHR) {
            EGLDisplay dpy = eglGetCurrentDisplay();
            if (mSlots[buf].mGraphicBuffer == 0) {
                ST_LOGE("buffer at slot %d is null", buf);
                return BAD_VALUE;
            }
            image = createImage(dpy, mSlots[buf].mGraphicBuffer);
            mSlots[buf].mEglImage = image;
            mSlots[buf].mEglDisplay = dpy;
            if (image == EGL_NO_IMAGE_KHR) {
                // NOTE: if dpy was invalid, createImage() is guaranteed to
                // fail. so we'd end up here.
                return -EINVAL;
            }
        }

        GLint error;
        while ((error = glGetError()) != GL_NO_ERROR) {
            ST_LOGW("updateTexImage: clearing GL error: %#04x", error);
        }

        glBindTexture(mTexTarget, mTexName);
        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);

        bool failed = false;
        while ((error = glGetError()) != GL_NO_ERROR) {
            ST_LOGE("error binding external texture image %p (slot %d): %#04x",
                    image, buf, error);
            failed = true;
        }
        if (failed) {
            return -EINVAL;
        }

        if (mCurrentTexture != INVALID_BUFFER_SLOT) {
            // The current buffer becomes FREE if it was still in the queued
            // state. If it has already been given to the client
            // (synchronous mode), then it stays in DEQUEUED state.
            if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED)
                mSlots[mCurrentTexture].mBufferState = BufferSlot::FREE;
        }

        // Update the SurfaceTexture state.
        mCurrentTexture = buf;
        mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
        mCurrentCrop = mSlots[buf].mCrop;
        mCurrentTransform = mSlots[buf].mTransform;
        mCurrentScalingMode = mSlots[buf].mScalingMode;
        mCurrentTimestamp = mSlots[buf].mTimestamp;
        computeCurrentTransformMatrix();

        // Now that we've passed the point at which failures can happen,
        // it's safe to remove the buffer from the front of the queue.
        mQueue.erase(front);
        mDequeueCondition.signal();
    } else {
        // We always bind the texture even if we don't update its contents.
        glBindTexture(mTexTarget, mTexName);
    }

    return OK;
}
先說一下這個函數中的 mQueue,這個變量是Vector<int>類型,在 SurfaceTexture::queueBuffer函數中
status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp,
        uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
。。。
        if (mSynchronousMode) {
            // In synchronous mode we queue all buffers in a FIFO.
            mQueue.push_back(buf);

            // Synchronous mode always signals that an additional frame should
            // be consumed.
            listener = mFrameAvailableListener;
        } else {
            // In asynchronous mode we only keep the most recent buffer.
            if (mQueue.empty()) {
                mQueue.push_back(buf);

                // Asynchronous mode only signals that a frame should be
                // consumed if no previous frame was pending. If a frame were
                // pending then the consumer would have already been notified.
                listener = mFrameAvailableListener;
            } else {
                Fifo::iterator front(mQueue.begin());
                // buffer currently queued is freed
                mSlots[*front].mBufferState = BufferSlot::FREE;
                // and we record the new buffer index in the queued list
                *front = buf;
            }
        }
。。。
}
在同步模式中, queueBufferbuf 索引放到 mQueue中,表示這是需要處理的 buffer,在異步模式下,由於只需要存儲最新的 buffer,所以從mQueue 中取出第一個 buffer的索引,將它對應的buffer的狀態設置爲 free,然後把新的索引放到隊列中去。也就是說,在這種模式下, Queue中只有一個最新的buffer
updateTexImage中,判斷 mQueue是否爲空,也就是說這是一個讀寫隊列,在 Binder線程中通過queueBuffer 把需要處理的 Buffer入隊列,在SurfaceFlinger 的主線程中讀取 BufferupdateTexImage 中調用了 createImage函數,它實際上是根據讀寫隊列中 buffer創建了OpenGL|ES image,這個 image被保存在相應的slot中。同時,下面兩個函數把 imageTex 綁定起來
        glBindTexture(mTexTarget, mTexName);
        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
返回來再看 Layer::lockPageFlip函數,後面的代碼就是計算一個 DirtyRegion,即要畫image 的那一部分,在 Layer中,也有兩個State DrawingStateCurrentState ,這個State的結構與 SurfaceFlingerState 結構不同,但是 DrawState同樣表示當前已經在屏幕上的狀態, CurrentState是當前處理的狀態。

3.unlockPageFlip

lockPageFilp類似, unlockPageFlip也是編譯Z order layer ,然後調用 layerunlockPageFilp 函數,該函數並沒有做太多的動作,主要就是根據當前 Planetranform dirtyRegion做一些座標變換

4.handleRepaint

lockPageFlip實際上是讓每個Layer計算出他們的 image,這個函數則是負責把這些 image混合之後畫到back framebuffer上,該函數主要有兩個重要的函數

<1>setupHardwareComposer

這裏用到了 DisplayHardware中我們沒有涉及到的一部分內容, hwcomposer,這是個硬件模塊,用於做圖像混合,即 HWComposer類,它在構造函數中加載了 hwcomposer模塊,並打開了該設備,得到 hwc_composer_device_t設備,該設備在做comoser的時候使用到了一個重要的結構 hwc_layer_list_t
typedef struct hwc_layer_list {
    uint32_t flags;
    size_t numHwLayers;
    hwc_layer_t hwLayers[0];
} hwc_layer_list_t;
其中hwd_layer_t的結構如下:
typedef struct hwc_layer {
    /*
     * initially set to HWC_FRAMEBUFFER, indicates the layer will
     * be drawn into the framebuffer using OpenGL ES.
     * The HWC can toggle this value to HWC_OVERLAY, to indicate
     * it will handle the layer.
     */
    int32_t compositionType;
    uint32_t hints;
    uint32_t flags;

    /* handle of buffer to compose. this handle is guaranteed to have been
     * allocated with gralloc */
    buffer_handle_t handle;
    uint32_t transform;
    int32_t blending;
    /* area of the source to consider, the origin is the top-left corner of
     * the buffer */
    hwc_rect_t sourceCrop;
    /* where to composite the sourceCrop onto the display. The sourceCrop
     * is scaled using linear filtering to the displayFrame. The origin is the
     * top-left corner of the screen.
     */
    hwc_rect_t displayFrame;
    /* visible region in screen space. The origin is the
     * top-left corner of the screen.
     * The visible region INCLUDES areas overlapped by a translucent layer.
     */
    hwc_region_t visibleRegionScreen;
} hwc_layer_t;
顯然, hw_layer_list_t結構中包含了需要進行composer的層信息, hwComposerprepare 函數就是用於初始化這些層信息的,默認情況下 compositionTypeHWC_FRAMEBUFFER 表示使用 OpenGL|ES,硬件設備可以修改它的值爲 HWC_OVERLAY,表示由硬件來處理layer HWComposer類的prepare 方法就是用來初始化 list結構的
setupHardwareComposer
函數中比較重要的兩點,
for (size_t i=0 ; i<count ; i++) {
        const sp<LayerBase>& layer(layers[i]);
        layer->setPerFrameData(&cur[i]);
    }
這裏的 Layer::setPerFrameData函數把Layer 中的handle,即 asm的內存,設置給hwComposer中對應的 hwc_layer_t中的handle
另外,調用了 hwc.prepare函數,用於初始化list結構中的其他部分。經過這兩部分設置之後,就可以使用 hwComposer進行compose

<2>composeSurfaces

void SurfaceFlinger::composeSurfaces(const Region& dirty)
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    HWComposer& hwc(hw.getHwComposer());

    const size_t fbLayerCount = hwc.getLayerCount(HWC_FRAMEBUFFER);
    if (UNLIKELY(fbLayerCount && !mWormholeRegion.isEmpty())) {
        // should never happen unless the window manager has a bug
        // draw something...
        drawWormhole();
    }

    /*
     * and then, render the layers targeted at the framebuffer
     */
    hwc_layer_t* const cur(hwc.getLayers());
    const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
    size_t count = layers.size();
    for (size_t i=0 ; i<count ; i++) {
        if (cur && (cur[i].compositionType != HWC_FRAMEBUFFER)) {
            continue;
        }
        const sp<LayerBase>& layer(layers[i]);
        const Region clip(dirty.intersect(layer->visibleRegionScreen));//
這裏計算Layer 的可見區域與 drityRegionclip
        if (!clip.isEmpty()) {
            layer->draw(clip);//
在這個clip draw layer
        }
    }
}
該函數相對也比較簡單,關鍵還是 LayerBase::draw函數,它實際上調用了Layer::onDraw函數,這個函數實際上是調用了衆多的 openGL|ES的函數來實現draw的功能,畫到 framebuffer上。這裏不做過多的說明。在 handleRepaint函數完成之後,接着調用了 DisplayHardware::compositionComplete函數,這個函數調用了frameBufferDevice compositionComlete函數,目的就是爲了通知 openGL或者硬件composition 操作結束。

5.postFramebuffer

該函數調用了 DisplayHardware::flp函數,
void DisplayHardware::flip(const Region& dirty) const
{
    checkGLErrors();

    EGLDisplay dpy = mDisplay;
    EGLSurface surface = mSurface;

#ifdef EGL_ANDROID_swap_rectangle    
    if (mFlags & SWAP_RECTANGLE) {
        const Region newDirty(dirty.intersect(bounds()));
        const Rect b(newDirty.getBounds());
        eglSetSwapRectangleANDROID(dpy, surface,
                b.left, b.top, b.width(), b.height());
    } 
#endif
    
    if (mFlags & PARTIAL_UPDATES) {
        mNativeWindow->setUpdateRectangle(dirty.getBounds());
    }
    
    mPageFlipCount++;

    if (mHwc->initCheck() == NO_ERROR) {
        mHwc->commit();//
如果hwComposer 已經初始化就調用它的 commit函數把內容畫到屏幕上去
    } else {
        eglSwapBuffers(dpy, surface);//
openGL|ES 使用framebuffer把內容寫到屏幕設備上去, eglSwapBuffer在前面已經分析過
    }
    checkEGLErrors("eglSwapBuffers");

    // for debugging
    //glClearColor(1,0,0,0);
    //glClear(GL_COLOR_BUFFER_BIT);
}

6.handleTransaction

這一部分在 Surface中有詳細說明
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章