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 进程上的服务端通信,进行 lock unlock 之类的操作。而只有 Layer 类返回的 ISurface 接口才能返回有内容的 ISurfaceTexture 实例,其他的 ISurface 返回的内容都是空的。 Layer 类的 ISurface 接口实际上是返回的 Layer 类中的成员变量 mSurfaceTexture ,它是一个 SurfaceTextureLayer 实例,它继承自 SurfaceTexture 类。 SurfaceTexture 类是一个非常重要的类,基本上它包括两个密不可分的部分,一个是作为服务端实现了 ISurfaceTexture 接口,与客户端通信,它包含有 32 GraphicBuffer ,当然他们都是在需要的时候才分配内存,客户端所进行的操作都是针对这个内存的, SurfaceTexture 中有对这些内存的同步和管理功能;另外一个功能就是根据客户端的画好的内存生成 OpenGL|ES image ,这个 image 最终是要交给 SurfaceFlinger Composer 混合的,SurfaceTexture的内存实际上就是一个读写队列,客户端会不断要求添加新的帧,SurfaceFlinger的主线程中会去读取这个帧。有了要显示的内容,剩下的工作就是要把它显示到屏幕上了。 SurfaceFlniger 中所有和显示相关的动作都封装在 Displayhardware 类中,这个类的实例指针是保存在 GraphicPlane 实例中,它是 SurfaceFlinger 的一个成员变量,它代表了一块屏幕,目前只有一个,实际上 SurfaceFlinger 可以支持多块屏幕。 Displayhardware 中包含一个 FramebufferNativeWindow 实例指针,它才是真正打开加载硬件设备的类,它继承自 ANativeWindow 类,它打开了两个设备,一个是 framebuffer ,一个是 gralloc framebuffer 用于写屏幕, gralloc 用于从 framebuffer 中分配内存,实际上 FramebufferNativeWindow 中的有两个 NativeBuffer ,即所谓的 front buffer back 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 研究报告中已经有详细说明;下面将分别对 handleConsoleEvent handleTransaction handlePageFlip handleRepaint postFrameBuffer 等进行说明

.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 了一个 DisplayEventThreadBase DisplayEventThreadBase 类在 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 函数退出消息等待,并把 SurfaceFlinger Signal 设置为 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
    //
module framebuffer 中获取内存,如果这个 framebuffer null ,需要进行分配
    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);
这里涉及了几个概念, nativewindow surface context display ,其中 ANativeWindow android opengl es 的接口结构,两边都在使用,在创建 Surface 的时候,就会根据 opengl es 的版本不同,创建不同的 suface 结构,并把 ANativeWindow 中关于设备的详细信息设置到这个 surface 中, surface 的很多操作都是基于 ANativeWindow 提供的函数的。 surface 显然是一个显示窗口的逻辑概念, display 代表显示设备, context 是显示的环境, makecurrent display 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 的两个成员变量 mDrawingState mCurrentState ,它们都是 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;
            }
        }
。。。
}
在同步模式中, queueBuffer buf 索引放到 mQueue 中,表示这是需要处理的 buffer ,在异步模式下,由于只需要存储最新的 buffer ,所以从 mQueue 中取出第一个 buffer 的索引,将它对应的 buffer 的状态设置为 free ,然后把新的索引放到队列中去。也就是说,在这种模式下, Queue 中只有一个最新的 buffer
updateTexImage 中,判断 mQueue 是否为空,也就是说这是一个读写队列,在 Binder 线程中通过 queueBuffer 把需要处理的 Buffer 入队列,在 SurfaceFlinger 的主线程中读取 Buffer updateTexImage 中调用了 createImage 函数,它实际上是根据读写队列中 buffer 创建了 OpenGL|ES image ,这个 image 被保存在相应的 slot 中。同时,下面两个函数把 image Tex 绑定起来
        glBindTexture(mTexTarget, mTexName);
        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
返回来再看 Layer::lockPageFlip 函数,后面的代码就是计算一个 DirtyRegion ,即要画 image 的那一部分,在 Layer 中,也有两个 State DrawingState CurrentState ,这个 State 的结构与 SurfaceFlinger State 结构不同,但是 DrawState 同样表示当前已经在屏幕上的状态, CurrentState 是当前处理的状态。

3.unlockPageFlip

lockPageFilp 类似, unlockPageFlip 也是编译 Z order layer ,然后调用 layer unlockPageFilp 函数,该函数并没有做太多的动作,主要就是根据当前 Plane tranform 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 的层信息, hwComposer prepare 函数就是用于初始化这些层信息的,默认情况下 compositionType HWC_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 的可见区域与 drityRegion clip
        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 中有详细说明
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值