SurfaceFlinger研究报告

本文深入探讨SurfaceFlinger的研究报告,包括其类结构综述、SurfaceFlinger进程启动、主线程初始化与运行机制,以及关键函数fb_device_open与fb_post的详细解释。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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中有详细说明
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值