Android 5.1 源码学习之SurfaceFlinger的启动(一)

来源:互联网 发布:小偶的软件 编辑:程序博客网 时间:2024/06/06 14:18

SurfaceFlinger在Android中负责绘制应用程序的UI,是一个系统service,本文将从源码来描述SurfaceFlinger的启动过程,看看它是怎么启动,并做了什么。


首先,SurfaceFlinger的源码位于frameworks/native/services/surfaceflinger下面,编译出来是一个Android的可执行程序,在手机的文件系统中位于system/bin下面。


启动它的代码是在init.rc中,也就是说它是init进程通过解析init.rc来启动的。init.rc(位于system/core/rootdir下面)中代码如下:


service surfaceflinger /system/bin/surfaceflinger    class core    user system    group graphics drmrpc    onrestart restart zygote


被init进程启动后就会进入它的入口main()函数开始执行。他的入口main()函数定义在frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp中,main()函数源码如下:

int main(int, char**) {    // When SF is launched in its own process, limit the number of    // binder threads to 4.    ProcessState::self()->setThreadPoolMaxThreadCount(4);    // start the thread pool    sp<ProcessState> ps(ProcessState::self());    ps->startThreadPool();    // instantiate surfaceflinger    sp<SurfaceFlinger> flinger = new SurfaceFlinger();#if defined(HAVE_PTHREADS)    setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);#endif    set_sched_policy(0, SP_FOREGROUND);    // initialize before clients can connect    flinger->init();    // publish surface flinger    sp<IServiceManager> sm(defaultServiceManager());    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);    // run in this thread    flinger->run();    return 0;}

这里首先设置SurfaceFlinger的线程池的最大线程数为4,然后启动线程池。

接着通过sp<SurfaceFlinger> flinger = new SurfaceFlinger();创建一个强指针的SurfaceFlinger对象。SurfaceFlinger的构造函数在SurfaceFlinger.cpp中:

SurfaceFlinger::SurfaceFlinger()    :   BnSurfaceComposer(),        mTransactionFlags(0),        mTransactionPending(false),        mAnimTransactionPending(false),        mLayersRemoved(false),        mRepaintEverything(0),        mRenderEngine(NULL),        mBootTime(systemTime()),        mVisibleRegionsDirty(false),        mHwWorkListDirty(false),        mAnimCompositionPending(false),        mDebugRegion(0),        mDebugDDMS(0),        mDebugDisableHWC(0),        mDebugDisableTransformHint(0),        mDebugInSwapBuffers(0),        mLastSwapBufferTime(0),        mDebugInTransaction(0),        mLastTransactionTime(0),        mBootFinished(false),        mPrimaryHWVsyncEnabled(false),        mHWVsyncAvailable(false),        mDaltonize(false),        mHasColorMatrix(false){    ALOGI("SurfaceFlinger is starting");    // debugging stuff...    char value[PROPERTY_VALUE_MAX];    property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");    mGpuToCpuSupported = !atoi(value);    property_get("debug.sf.showupdates", value, "0");    mDebugRegion = atoi(value);    property_get("debug.sf.ddms", value, "0");    mDebugDDMS = atoi(value);    if (mDebugDDMS) {        if (!startDdmConnection()) {            // start failed, and DDMS debugging not enabled            mDebugDDMS = 0;        }    }    ALOGI_IF(mDebugRegion, "showupdates enabled");    ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");}

构造函数就是对SurfaceFlinger的类成员变量赋初值。

然后setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);就是设置线程调度的优先级;

接着调用SurfaceFlinger的init函数进行一些初始化工作,具体初始化内容下面分析。由于SurfaceFlinger继承自BnSurfaceComposer,而BnSurfaceComposer向上最终继承自RefBase,SurfaceFlinger实现了RefBase的onFirstRef()方法,所以当第一次引用SurfaceFlinger对象的时候onFirstRef()方法会自动被调用。onFirstRef()方法内容如下:

void SurfaceFlinger::onFirstRef(){    mEventQueue.init(this);}

它里面初始化一个消息队列MessageQueue来接收消息,这个init的实现在frameworks/native/services/surfaceflinger/MessageQueue.cpp,代码如下:

void MessageQueue::init(const sp<SurfaceFlinger>& flinger){    mFlinger = flinger;    mLooper = new Looper(true);    mHandler = new Handler(*this);}

这里主要是将创建的SurfaceFlinger对象的引用传给mEventQueue的指针变量sp<SurfaceFlinger> mFlinger,然后创建Handler接收消息。在这个文件中实现了handleMessage()的接口,如下:

void MessageQueue::Handler::handleMessage(const Message& message) {    switch (message.what) {        case INVALIDATE:            android_atomic_and(~eventMaskInvalidate, &mEventMask);            mQueue.mFlinger->onMessageReceived(message.what);            break;        case REFRESH:            android_atomic_and(~eventMaskRefresh, &mEventMask);            mQueue.mFlinger->onMessageReceived(message.what);            break;        case TRANSACTION:            android_atomic_and(~eventMaskTransaction, &mEventMask);            mQueue.mFlinger->onMessageReceived(message.what);            break;    }}

可以看出,接收到消息后会把消息通过SurfaceFlinger对象的引用进一步发送给SurfaceFlinger服务。然后在SurfaceFlinger中的onMessageReceived()方法就会接受这些消息并正真的进行处理,如下:

void SurfaceFlinger::onMessageReceived(int32_t what) {    ATRACE_CALL();    switch (what) {        case MessageQueue::TRANSACTION: {            handleMessageTransaction();            break;        }        case MessageQueue::INVALIDATE: {            bool refreshNeeded = handleMessageTransaction();            refreshNeeded |= handleMessageInvalidate();            refreshNeeded |= mRepaintEverything;            if (refreshNeeded) {                // Signal a refresh if a transaction modified the window state,                // a new buffer was latched, or if HWC has requested a full                // repaint                signalRefresh();            }            break;        }        case MessageQueue::REFRESH: {            handleMessageRefresh();            break;        }    }}

现在说到了main_surfaceflinger.cppflinger->init();这里,具体init的实现下面细说,接着说main_surfaceflinger.cpp中的剩下几行代码。

由于SurfaceFlinger也是一个系统服务,所以需要ServiceManager进行统一管理,所以这里(sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);)SurfaceFlinger会把自己加到ServiceManager的管理列表中,让ServiceManager对自己进行管理。

最后SurfaceFlinger其实就是一个线程,所以直接调用它的run接口跑起来。

现在来看SurfaceFlinger.cpp中init函数的具体实现:

void SurfaceFlinger::init() {    ALOGI(  "SurfaceFlinger's main thread ready to run. "            "Initializing graphics H/W...");    status_t err;    Mutex::Autolock _l(mStateLock);    // initialize EGL for the default display    mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);    eglInitialize(mEGLDisplay, NULL, NULL);    // Initialize the H/W composer object.  There may or may not be an    // actual hardware composer underneath.    mHwc = new HWComposer(this,            *static_cast<HWComposer::EventHandler *>(this));    // get a RenderEngine for the given display / config (can't fail)    mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());    // retrieve the EGL context that was selected/created    mEGLContext = mRenderEngine->getEGLContext();    LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,            "couldn't create EGLContext");    // initialize our non-virtual displays    for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {        DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);        // set-up the displays that are already connected        if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {            // All non-virtual displays are currently considered secure.            bool isSecure = true;            createBuiltinDisplayLocked(type);            wp<IBinder> token = mBuiltinDisplays[i];            sp<IGraphicBufferProducer> producer;            sp<IGraphicBufferConsumer> consumer;            BufferQueue::createBufferQueue(&producer, &consumer,                    new GraphicBufferAlloc());            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,                    consumer);            int32_t hwcId = allocateHwcDisplayId(type);            sp<DisplayDevice> hw = new DisplayDevice(this,                    type, hwcId, mHwc->getFormat(hwcId), isSecure, token,                    fbs, producer,                    mRenderEngine->getEGLConfig());            if (i > DisplayDevice::DISPLAY_PRIMARY) {                // FIXME: currently we don't get blank/unblank requests                // for displays other than the main display, so we always                // assume a connected display is unblanked.                ALOGD("marking display %zu as acquired/unblanked", i);                hw->setPowerMode(HWC_POWER_MODE_NORMAL);            }            mDisplays.add(token, hw);        }    }    // make the GLContext current so that we can create textures when creating Layers    // (which may happens before we render something)    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);    // start the EventThread    sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,            vsyncPhaseOffsetNs, true, "app");    mEventThread = new EventThread(vsyncSrc);    sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,            sfVsyncPhaseOffsetNs, true, "sf");    mSFEventThread = new EventThread(sfVsyncSrc);    mEventQueue.setEventThread(mSFEventThread);    mEventControlThread = new EventControlThread(this);    mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);    // set a fake vsync period if there is no HWComposer    if (mHwc->initCheck() != NO_ERROR) {        mPrimaryDispSync.setPeriod(16666667);    }    // initialize our drawing state    mDrawingState = mCurrentState;    // set initial conditions (e.g. unblank default device)    initializeDisplays();    // start boot animation    startBootAnim();}

init函数里就是SurfaceFlinger初始化的地方,接下来一步步分析具体过程。

1、为默认的显示设备初始化EGL

代码如下:

<pre name="code" class="cpp">mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);eglInitialize(mEGLDisplay, NULL, NULL);

首先调用eglGetDisplay(EGL_DEFAULT_DISPLAY);获得默认的display设备。我们看下这个方法的实现:

EGLDisplay eglGetDisplay(EGLNativeDisplayType display){    clearError();    uintptr_t index = reinterpret_cast<uintptr_t>(display);    if (index >= NUM_DISPLAYS) {        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);    }    if (egl_init_drivers() == EGL_FALSE) {        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);    }    EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);    return dpy;}

这个方法的实现位于frameworks\native\opengl\libs\egl\eglApi.cpp中,首先会调用egl_init_drivers()方法初始化egl动态库,具体实现如下:

EGLBoolean egl_init_drivers() {    EGLBoolean res;    pthread_mutex_lock(&sInitDriverMutex);    res = egl_init_drivers_locked();    pthread_mutex_unlock(&sInitDriverMutex);    return res;}
这里使用线程锁保证访问的安全性,实际的实现在egl_init_drivers_locked();这个方法中。这个方法实现如下:

tatic EGLBoolean egl_init_drivers_locked() {    if (sEarlyInitState) {        // initialized by static ctor. should be set here.        return EGL_FALSE;    }    // get our driver loader    Loader& loader(Loader::getInstance());    // dynamically load our EGL implementation    egl_connection_t* cnx = &gEGLImpl;    if (cnx->dso == 0) {        cnx->hooks[egl_connection_t::GLESv1_INDEX] =                &gHooks[egl_connection_t::GLESv1_INDEX];        cnx->hooks[egl_connection_t::GLESv2_INDEX] =                &gHooks[egl_connection_t::GLESv2_INDEX];        cnx->dso = loader.open(cnx);    }    return cnx->dso ? EGL_TRUE : EGL_FALSE;}

首先通过调用pthread_once,也就是sEarlyInitState保证只初始化一次。接下来拿到Loader的实例,这个类主要是用来加载我们的EGL的库。这里定义一个egl_connection_t的指针cnx指向全局变量gEGLImpl,并且将cnx的hooks指向gHooks,最后通过loader实例对象的open函数打开EGL动态库,因此最后从EGL库中加载的接口函数指针都保存到了变量gEGLImpl和gHooks中了。这里的open函数的具体实现如下:

void* Loader::open(egl_connection_t* cnx){    void* dso;    driver_t* hnd = 0;    //首先加载GLES库    dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2);    if (dso) {        hnd = new driver_t(dso);    } else {        // Always load EGL first        dso = load_driver("EGL", cnx, EGL);        if (dso) {            hnd = new driver_t(dso);            hnd->set( load_driver("GLESv1_CM", cnx, GLESv1_CM), GLESv1_CM );            hnd->set( load_driver("GLESv2",    cnx, GLESv2),    GLESv2 );        }    }    LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation");#if defined(__LP64__)    cnx->libEgl   = load_wrapper("/system/lib64/libEGL.so");    cnx->libGles2 = load_wrapper("/system/lib64/libGLESv2.so");    cnx->libGles1 = load_wrapper("/system/lib64/libGLESv1_CM.so");#else    cnx->libEgl   = load_wrapper("/system/lib/libEGL.so");    cnx->libGles2 = load_wrapper("/system/lib/libGLESv2.so");    cnx->libGles1 = load_wrapper("/system/lib/libGLESv1_CM.so");#endif    LOG_ALWAYS_FATAL_IF(!cnx->libEgl,            "couldn't load system EGL wrapper libraries");    LOG_ALWAYS_FATAL_IF(!cnx->libGles2 || !cnx->libGles1,            "couldn't load system OpenGL ES wrapper libraries");    return (void*)hnd;}

这里就是通过load_driver的接口去加载EGL的实现,首先通过dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2);去拿GLES的库,通常的实现也就是这个相关的库,位于/system/lib/egl/下面。

void *Loader::load_driver(const char* kind,        egl_connection_t* cnx, uint32_t mask){    class MatchFile {    public:        static String8 find(const char* kind) {            String8 result;            String8 pattern;            pattern.appendFormat("lib%s", kind);            const char* const searchPaths[] = {#if defined(__LP64__)                    "/vendor/lib64/egl",                    "/system/lib64/egl"#else                    "/vendor/lib/egl",                    "/system/lib/egl"#endif            };            // first, we search for the exact name of the GLES userspace            // driver in both locations.            // i.e.:            //      libGLES.so, or:            //      libEGL.so, libGLESv1_CM.so, libGLESv2.so            for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {                if (find(result, pattern, searchPaths[i], true)) {                    return result;                }            }            // for compatibility with the old "egl.cfg" naming convention            // we look for files that match:            //      libGLES_*.so, or:            //      libEGL_*.so, libGLESv1_CM_*.so, libGLESv2_*.so            pattern.append("_");            for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {                if (find(result, pattern, searchPaths[i], false)) {                    return result;                }            }            // we didn't find the driver. gah.            result.clear();            return result;        }    private:        static bool find(String8& result,                const String8& pattern, const char* const search, bool exact) {            // in the emulator case, we just return the hardcoded name            // of the software renderer.            if (checkGlesEmulationStatus() == 0) {                ALOGD("Emulator without GPU support detected. "                      "Fallback to software renderer.");#if defined(__LP64__)                result.setTo("/system/lib64/egl/libGLES_android.so");#else                result.setTo("/system/lib/egl/libGLES_android.so");#endif                return true;            }            if (exact) {                String8 absolutePath;                absolutePath.appendFormat("%s/%s.so", search, pattern.string());                if (!access(absolutePath.string(), R_OK)) {                    result = absolutePath;                    return true;                }                return false;            }            DIR* d = opendir(search);            if (d != NULL) {                struct dirent cur;                struct dirent* e;                while (readdir_r(d, &cur, &e) == 0 && e) {                    if (e->d_type == DT_DIR) {                        continue;                    }                    if (!strcmp(e->d_name, "libGLES_android.so")) {                        // always skip the software renderer                        continue;                    }                    if (strstr(e->d_name, pattern.string()) == e->d_name) {                        if (!strcmp(e->d_name + strlen(e->d_name) - 3, ".so")) {                            result.clear();                            result.appendFormat("%s/%s", search, e->d_name);                            closedir(d);                            return true;                        }                    }                }                closedir(d);            }            return false;        }    };    //这里的到刚才加载的动态库的绝对路径    String8 absolutePath = MatchFile::find(kind);    if (absolutePath.isEmpty()) {        // this happens often, we don't want to log an error        return 0;    }    const char* const driver_absolute_path = absolutePath.string();    //根据获得动态库的绝对路径通过dlopen函数打开刚才的库,将地址指针赋给dso    void* dso = dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);    if (dso == 0) {        const char* err = dlerror();        ALOGE("load_driver(%s): %s", driver_absolute_path, err?err:"unknown");        return 0;    }    ALOGD("loaded %s", driver_absolute_path);    //下面通过刚才打开的库的指针获得getProcAddress,然后在通过getProcAddress拿到定义的EGL的接口函数的入口地址,并保存在全局变量传递过来的cnx中,这个cnx指向的就是全局变量gEGLImpl    if (mask & EGL) {        getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");        ALOGE_IF(!getProcAddress,                "can't find eglGetProcAddress() in %s", driver_absolute_path);        egl_t* egl = &cnx->egl;        __eglMustCastToProperFunctionPointerType* curr =            (__eglMustCastToProperFunctionPointerType*)egl;        char const * const * api = egl_names;        while (*api) {            char const * name = *api;            __eglMustCastToProperFunctionPointerType f =                (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);            if (f == NULL) {                // couldn't find the entry-point, use eglGetProcAddress()                f = getProcAddress(name);                if (f == NULL) {                    f = (__eglMustCastToProperFunctionPointerType)0;                }            }            *curr++ = f;            api++;        }    }    if (mask & GLESv1_CM) {        init_api(dso, gl_names,            (__eglMustCastToProperFunctionPointerType*)                &cnx->hooks[egl_connection_t::GLESv1_INDEX]->gl,            getProcAddress);    }    if (mask & GLESv2) {      init_api(dso, gl_names,            (__eglMustCastToProperFunctionPointerType*)                &cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl,            getProcAddress);    }    return dso;}

根据不同的设备不同的实现会加载不同的库,本文所用的设备实现为libGLES_mali.so,位于/system/lib/egl/下。如上面的代码注释中的所描述的,拿到libGLES_mali.so并通过dlopen打开然后拿到EGL接口函数的入口地址,保存在全局变量gEGLImpl中供后面调用。这里EGL接口函数的定义就是代码中egl_names这个数组中,这个数组的定义如下:

<pre name="code" class="cpp">char const * const gl_names[] = {    #include "../entries.in"    NULL};

而这个entries.in就在frameworks/native/opengl/libs下面,其内容如下:

GL_ENTRY(void, glActiveShaderProgram, GLuint pipeline, GLuint program)GL_ENTRY(void, glActiveShaderProgramEXT, GLuint pipeline, GLuint program)GL_ENTRY(void, glActiveTexture, GLenum texture)GL_ENTRY(void, glAlphaFunc, GLenum func, GLfloat ref)GL_ENTRY(void, glAlphaFuncQCOM, GLenum func, GLclampf ref)GL_ENTRY(void, glAlphaFuncx, GLenum func, GLfixed ref)GL_ENTRY(void, glAlphaFuncxOES, GLenum func, GLfixed ref)GL_ENTRY(void, glAttachShader, GLuint program, GLuint shader)GL_ENTRY(void, glBeginPerfMonitorAMD, GLuint monitor)GL_ENTRY(void, glBeginPerfQueryINTEL, GLuint queryHandle)GL_ENTRY(void, glBeginQuery, GLenum target, GLuint id)GL_ENTRY(void, glBeginQueryEXT, GLenum target, GLuint id)GL_ENTRY(void, glBeginTransformFeedback, GLenum primitiveMode)GL_ENTRY(void, glBindAttribLocation, GLuint program, GLuint index, const GLchar * name)GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer)GL_ENTRY(void, glBindBufferBase, GLenum target, GLuint index, GLuint buffer)GL_ENTRY(void, glBindBufferRange, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)GL_ENTRY(void, glBindFramebuffer, GLenum target, GLuint framebuffer)GL_ENTRY(void, glBindFramebufferOES, GLenum target, GLuint framebuffer)GL_ENTRY(void, glBindImageTexture, GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format)GL_ENTRY(void, glBindProgramPipeline, GLuint pipeline)GL_ENTRY(void, glBindProgramPipelineEXT, GLuint pipeline)GL_ENTRY(void, glBindRenderbuffer, GLenum target, GLuint renderbuffer)GL_ENTRY(void, glBindRenderbufferOES, GLenum target, GLuint renderbuffer)GL_ENTRY(void, glBindSampler, GLuint unit, GLuint sampler)GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture)GL_ENTRY(void, glBindTransformFeedback, GLenum target, GLuint id)GL_ENTRY(void, glBindVertexArray, GLuint array)GL_ENTRY(void, glBindVertexArrayOES, GLuint array)GL_ENTRY(void, glBindVertexBuffer, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride)GL_ENTRY(void, glBlendBarrierKHR, void)GL_ENTRY(void, glBlendBarrierNV, void)GL_ENTRY(void, glBlendColor, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)GL_ENTRY(void, glBlendEquation, GLenum mode)GL_ENTRY(void, glBlendEquationOES, GLenum mode)GL_ENTRY(void, glBlendEquationSeparate, GLenum modeRGB, GLenum modeAlpha)GL_ENTRY(void, glBlendEquationSeparateOES, GLenum modeRGB, GLenum modeAlpha)GL_ENTRY(void, glBlendEquationSeparateiEXT, GLuint buf, GLenum modeRGB, GLenum modeAlpha)GL_ENTRY(void, glBlendEquationiEXT, GLuint buf, GLenum mode)GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)GL_ENTRY(void, glBlendFuncSeparate, GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha)GL_ENTRY(void, glBlendFuncSeparateOES, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)GL_ENTRY(void, glBlendFuncSeparateiEXT, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)

里面就是EGL接口的定义。

到这里我们其实只是将我们EGL库加载起来,也就是我们回到上面已经提到的eglGetDisplay函数的egl_init_drivers这里:

EGLDisplay eglGetDisplay(EGLNativeDisplayType display){    clearError();    uintptr_t index = reinterpret_cast<uintptr_t>(display);    if (index >= NUM_DISPLAYS) {        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);    }    if (<strong>egl_init_drivers()</strong> == EGL_FALSE) {        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);    }    EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);    return dpy;}


而eglGetDisplay这个函数的最终目的是拿到display设备。这个就是最后一句实现的,通过getFromNativeDisplay方法获得display设备。具体实现如下:

EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp) {    if (uintptr_t(disp) >= NUM_DISPLAYS)        return NULL;    return sDisplay[uintptr_t(disp)].getDisplay(disp);}

接着调用getDisplay方法:

EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {    Mutex::Autolock _l(lock);    // get our driver loader    Loader& loader(Loader::getInstance());    egl_connection_t* const cnx = &gEGLImpl;    if (cnx->dso && disp.dpy == EGL_NO_DISPLAY) {        EGLDisplay dpy = cnx->egl.eglGetDisplay(display);        disp.dpy = dpy;        if (dpy == EGL_NO_DISPLAY) {            loader.close(cnx->dso);            cnx->dso = NULL;        }    }    return EGLDisplay(uintptr_t(display) + 1U);}

这里最终返回EGLDisplay一样display设备类型的变量,值为1;

这样我们再回到SurfaceFlinger.cpp中的init方法中,就走完了mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);这一步,拿到了EGLDisplay实现。接下来调用eglInitialize(mEGLDisplay, NULL, NULL);这里主要设置一下已经拿到的设备的一些状态信息,并保存在全局变量gEGLImpl中。这样我们就为默认的display设备初始化完成了EGL实现。


先到这里,下篇接着分析。

0 0