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.cpp中flinger->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;}
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实现。
先到这里,下篇接着分析。
- Android 5.1 源码学习之SurfaceFlinger的启动(一)
- Android SurfaceFlinger 学习之路(四)----SurfaceFlinger服务的启动与连接过程
- 【Android】Android SurfaceFlinger之SurfaceFlinger启动过程
- Android SurfaceFlinger之SurfaceFlinger启动过程
- Android SurfaceFlinger服务启动过程源码分析
- 浅谈Android之SurfaceFlinger相关介绍(一)
- Android SurfaceFlinger 学习之路(二)----SurfaceFlinger概述
- Android SurfaceFlinger 学习之路(六)----SurfaceFlinger创建Surface
- android从init到开机动画启动关闭流程一简易图(surfaceflinger启动的位置)
- android从init到开机动画启动关闭流程一简易图(surfaceflinger启动的位置)
- SurfaceFlinger启动过程分析(一)
- SurfaceFlinger启动过程分析(一)
- SurfaceFlinger启动过程分析(一)
- SurfaceFlinger启动过程分析(一)
- Android显示系统之SurfaceFlinger(一)
- Android显示系统之SurfaceFlinger(一)
- Android显示系统之SurfaceFlinger(一)
- Android显示系统之SurfaceFlinger(一)
- 关于STM32的IAP在线升级的整理
- Hadoop的简单控制台log分析
- Nim教程翻译(三)
- 多线程还是多进程的选择及区别
- jQuery.extend 函数详解
- Android 5.1 源码学习之SurfaceFlinger的启动(一)
- SIEMENS SIMATIC S7-200 PLC 开发环境配置。
- 成长,随遇而安
- Android动态添加控件约束位置
- gdb调试命令
- Xcode在真机调试的时候出现"The identity used to sign the executable is no longer valid"
- 解决EXT.NET年月日期弹出框数据被遮盖的问题
- 我对CSS vertical-align的一些理解与认识(一)
- Mysql主从备份实现master-slave