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

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实现。


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值