Android系統(tǒng)Surface機(jī)制的SurfaceFlinger服務(wù)對幀緩沖區(qū)(FrameBuffer)的管理分析_第1頁
Android系統(tǒng)Surface機(jī)制的SurfaceFlinger服務(wù)對幀緩沖區(qū)(FrameBuffer)的管理分析_第2頁
Android系統(tǒng)Surface機(jī)制的SurfaceFlinger服務(wù)對幀緩沖區(qū)(FrameBuffer)的管理分析_第3頁
Android系統(tǒng)Surface機(jī)制的SurfaceFlinger服務(wù)對幀緩沖區(qū)(FrameBuffer)的管理分析_第4頁
Android系統(tǒng)Surface機(jī)制的SurfaceFlinger服務(wù)對幀緩沖區(qū)(FrameBuffer)的管理分析_第5頁
已閱讀5頁,還剩19頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、Android系統(tǒng)Surface機(jī)制的SurfaceFlinger服務(wù)對幀緩沖區(qū)(Frame Buffer)的管理分析在前文中,我們分析了SurfaceFlinger服務(wù)的啟動過程。SurfaceFlinger服務(wù)在啟動的過程中,會對系統(tǒng)的硬件幀緩沖區(qū)進(jìn)行初始化。由于系統(tǒng)的硬件幀緩沖區(qū)一般只有一個(gè),并且不是誰都可以隨便訪問的,因此,它就需要由一個(gè)服務(wù)來統(tǒng)一管理。在Android系統(tǒng)中,這個(gè)服務(wù)便是SurfaceFlinger。在本文中,我們就詳細(xì)分析SurfaceFlinger服務(wù)是如何管理系統(tǒng)的硬件幀緩沖區(qū)的。 從前面 一文可以知道,SurfaceFlinger服務(wù)通過一個(gè)GraphicPl

2、ane對象來描述系統(tǒng)的顯示屏,即系統(tǒng)的硬件幀緩沖區(qū)。GraphicPlane類內(nèi)部聚合了一個(gè)DisplayHardware對象,通過這個(gè)DisplayHardware對象就可以訪問系統(tǒng)的硬件幀緩沖區(qū)。DisplayHardware類內(nèi)部又包含了一個(gè)FramebufferNativeWindow對象,這個(gè)FramebufferNativeWindow對象才是真正用來描述系統(tǒng)的硬件幀緩沖區(qū)的。FramebufferNativeWindow類的作用類似于在前面 一文中所介紹的Surface類,它是連接OpenGL庫和Android的UI系統(tǒng)的一個(gè)橋梁,OpenGL庫就是通過這個(gè)橋梁來將Android

3、系統(tǒng)的UI渲染到硬件幀緩沖區(qū)中去的。GraphicPlane、DisplayHardware和FramebufferNativeWindow這三個(gè)類的關(guān)系如圖1所示。接下來,我們就分別介紹GraphicPlane、DisplayHardware和FramebufferNativeWindow這三個(gè)類的實(shí)現(xiàn),以便可以理解SurfaceFlinger服務(wù)是如何通過它們來管理系統(tǒng)的硬件幀緩沖區(qū)的。 從前面 一文可以知道,SurfaceFlinger服務(wù)在啟動的過程中,會對系統(tǒng)的硬件幀緩沖區(qū)進(jìn)行初始化,如下所示:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片status

4、_t SurfaceFlinger:readyToRun() . / 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); . / initialize primary screen / (other display should b

5、e initialized in the same manner, but / asynchronously, as they could come and go. None of this is supported / yet). const GraphicPlane& plane(graphicPlane(dpy); const DisplayHardware& hw = plane.displayHardware(); . hw.makeCurrent(); . 這個(gè)函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger

6、.cpp文件中。 這個(gè)代碼段首先創(chuàng)建了一個(gè)DisplayHardware對象,用來初始化編號為0的GraphicPlane對象,接著再將這個(gè)DisplayHardware對象設(shè)置為系統(tǒng)當(dāng)前活動的DisplayHardware對象,這就相當(dāng)于是將編號為0的GraphicPlane對象所描述的顯示屏設(shè)置為系統(tǒng)當(dāng)前活動的顯示屏。 接下來,我們就首先分析編號為0的GraphicPlane對象的初始化過程,接著再分析DisplayHardware對象的創(chuàng)建過程。 編號為0的GraphicPlane對象的初始化過程主要是調(diào)用GraphicPlane類的成員函數(shù)setDisplayHardware來實(shí)現(xiàn)的,

7、如下所示:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片void GraphicPlane:setDisplayHardware(DisplayHardware *hw) mHw = hw; / initialize the display orientation transform. / its a constant that should come from the display driver. int displayOrientation = ISurfaceComposer:eOrientationDefault; char propertyPROPE

8、RTY_VALUE_MAX; if (property_get(ro.sf.hwrotation, property, NULL) 0) /displayOrientation switch (atoi(property) case 90: displayOrientation = ISurfaceComposer:eOrientation90; break; case 270: displayOrientation = ISurfaceComposer:eOrientation270; break; const float w = hw-getWidth(); const float h =

9、 hw-getHeight(); GraphicPlane:orientationToTransfrom(displayOrientation, w, h, &mDisplayTransform); if (displayOrientation & ISurfaceComposer:eOrientationSwapMask) mDisplayWidth = h; mDisplayHeight = w; else mDisplayWidth = w; mDisplayHeight = h; setOrientation(ISurfaceComposer:eOrientationDefault);

10、 這個(gè)函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp文件中。 函數(shù)首先設(shè)置顯示屏的初始大小和旋轉(zhuǎn)方向。GraphicPlane類有三個(gè)成員變量mDisplayWidth、mDisplayHeight和mDisplayTransform,前兩者的類型為float,分別用描述顯示屏的初始寬度和高度,而后者的類型為Transform,用來描述顯示屏的初始旋轉(zhuǎn)矩陣。Transform類的作用是來描述變換矩陣,以便后面在渲染UI時(shí)可以用來動態(tài)地計(jì)算顯示屏的大小和旋轉(zhuǎn)方向等。 顯示屏的初始化寬度和高度是由參數(shù)hw所描述的一

11、個(gè)DisplayHardware對象來描述的,而顯示屏的初始旋轉(zhuǎn)方向則是由名稱為“ro.sf.hwrotation”的系統(tǒng)屬性來決定的。如果沒有設(shè)置名稱為“ro.sf.hwrotation”的系統(tǒng)屬性,那么顯示屏的旋轉(zhuǎn)方向就為默認(rèn)方向,即ISurfaceComposer:eOrientationDefault。 獲得了顯示屏的初始化寬度w、高度h和旋轉(zhuǎn)方向displayOrientation之后,函數(shù)接著就調(diào)用GraphicPlane類的靜態(tài)成員函數(shù)orientationToTransfrom來將它們構(gòu)造成一個(gè)變換矩陣,并且保存在GraphicPlane類的成員變量mDisplayTransf

12、orm中。 函數(shù)接下來繼續(xù)判斷顯示屏的初始化旋轉(zhuǎn)方向是否將初始化寬度和高度值翻轉(zhuǎn)了。如果翻轉(zhuǎn)了,那么就需要相互調(diào)換GraphicPlane類的成員變量mDisplayWidth和mDisplayHeight的值,以便可以正確地反映顯示屏的初始化寬度和高度。 注意,顯示屏的初始寬度、高度和旋轉(zhuǎn)方向一經(jīng)初始化之后,就會保持不變,以后顯示屏的實(shí)際旋轉(zhuǎn)方向計(jì)算都是要在此基礎(chǔ)上進(jìn)行計(jì)算的,即要在變換矩陣mDisplayTransform的基礎(chǔ)上進(jìn)行計(jì)算。從這里還可以看出,通過設(shè)置名稱為“ro.sf.hwrotation”的系統(tǒng)屬性的值,就可以設(shè)置系統(tǒng)顯示屏的初始化旋轉(zhuǎn)方向,以便匹配實(shí)際的硬件幀緩沖區(qū)的旋

13、轉(zhuǎn)方向。 函數(shù)最后調(diào)用GraphicPlane類的成員函數(shù)setOrientation來設(shè)備顯示屏的實(shí)際度度、高度以及旋轉(zhuǎn)方向,如下所示:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片status_t GraphicPlane:setOrientation(int orientation) / If the rotation can be handled in hardware, this is where / the magic should happen. const DisplayHardware& hw(displayHardware(); const

14、float w = mDisplayWidth; const float h = mDisplayHeight; mWidth = int(w); mHeight = int(h); Transform orientationTransform; GraphicPlane:orientationToTransfrom(orientation, w, h, &orientationTransform); if (orientation & ISurfaceComposer:eOrientationSwapMask) mWidth = int(h); mHeight = int(w); mOrie

15、ntation = orientation; mGlobalTransform = mDisplayTransform * orientationTransform; return NO_ERROR; 這個(gè)函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp文件中。 參數(shù)orientation的值等于ISurfaceComposer:eOrientationDefault,即SurfaceFlinger服務(wù)在初始化系統(tǒng)顯示屏?xí)r,會將它的旋轉(zhuǎn)方向設(shè)置為默認(rèn)值,以后再根據(jù)實(shí)際情況來做調(diào)整。 GraphicPlane類有三

16、個(gè)成員變量mWidth、mHeight和mOrientation,它們的類型均為int,分別用來描述顯示屏的實(shí)際寬度、高度和旋轉(zhuǎn)方向。與成員變量mDisplayWidth、mDisplayHeight和mDisplayTransform所描述的顯示屏初始化寬度、高度和旋轉(zhuǎn)矩陣一經(jīng)初始化后就保持不變不同,mWidth、mHeight和mOrientation這三個(gè)成員變量是會動態(tài)變化的。例如,當(dāng)顯示屏由LANDSCAPE變?yōu)镻ORTRAIT模式時(shí),mWidth、mHeight和mOrientation這三個(gè)成員變量就會相應(yīng)地發(fā)生改變。 函數(shù)首先將顯示屏的實(shí)際寬度mWidth、高度mHeight和

17、旋轉(zhuǎn)方向mOrientation設(shè)置為顯示屏的初始寬度mDisplayWidth、高度mDisplayHeight以及參數(shù)orientation所描述的旋轉(zhuǎn)方向,接著再調(diào)用GraphicPlane類的靜態(tài)成員函數(shù)orientationToTransfrom來將它們構(gòu)造成一個(gè)變換矩陣orientationTransform。 函數(shù)接著判斷顯示屏的實(shí)際旋轉(zhuǎn)方向orientation是否將原來的實(shí)際寬度和高度值翻轉(zhuǎn)了。如果翻轉(zhuǎn)了,那么就需要相互調(diào)換GraphicPlane類的成員變量mWidth和mHeight的值,以便可以正確地反映顯示屏的實(shí)際寬度和高度。 函數(shù)最后將用來描述顯示屏的初始化旋轉(zhuǎn)方向

18、的變換矩陣mDisplayTransform和用來描述顯示屏的實(shí)際旋轉(zhuǎn)方向的變換矩陣orientationTransform相乘,就可以得到一個(gè)全局變換矩陣,并且保存在GraphicPlane類的成員變量mGlobalTransform中。這樣以后渲染UI時(shí),對于一個(gè)任意的點(diǎn)向量,只要將它乘以全局變換矩陣mGlobalTransform,那么就可以得到它所描述的實(shí)際位置。 至此,編號為0的GraphicPlane對象的初始化過程就完成了,以后SurfaceFlinger服務(wù)就可以調(diào)用它的成員函數(shù)displayHardware來獲得它內(nèi)部的一個(gè)DisplayHardware對象,如下所示:cpp

19、 view plain copy 在CODE上查看代碼片派生到我的代碼片const DisplayHardware& GraphicPlane:displayHardware() const return *mHw; 這個(gè)函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp文件中。 接下來,回到前面SurfaceFlinger類的成員函數(shù)readyToRun中,我們通過DisplayHardware對象的創(chuàng)建過程來分析DisplayHardware類的實(shí)現(xiàn)。 在創(chuàng)建DisplayHardware對象的過程中,會調(diào)用D

20、isplayHardware類的構(gòu)造函數(shù),如下所示:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片DisplayHardware:DisplayHardware( const sp& flinger, uint32_t dpy) : DisplayHardwareBase(flinger, dpy), mFlags(0) init(dpy); 這個(gè)函數(shù)定義在文件frameworks/base/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp中。 從這里可以看出,DisplayHardware類

21、是從DisplayHardwareBase類繼承下來的。接下來,我們首先繼續(xù)分析一個(gè)DisplayHardware對象的初始化過程,接著再分析這個(gè)DisplayHardware對象的父對象DisplayHardwareBase的初始化過程,以便可以了解DisplayHardwareBase類的實(shí)現(xiàn)。 一個(gè)DisplayHardware對象的初始化過程是通過調(diào)用DisplayHardware類的成員函數(shù)init來實(shí)現(xiàn)的。DisplayHardware類的成員函數(shù)init的實(shí)現(xiàn)比較長,我們分段來閱讀:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片void Displ

22、ayHardware:init(uint32_t dpy) mNativeWindow = new FramebufferNativeWindow(); framebuffer_device_t const * fbDev = mNativeWindow-getDevice(); mDpiX = mNativeWindow-xdpi; mDpiY = mNativeWindow-ydpi; mRefreshRate = fbDev-fps; mOverlayEngine = NULL; hw_module_t const* module; if (hw_get_module(OVERLAY_H

23、ARDWARE_MODULE_ID, &module) = 0) overlay_control_open(module, &mOverlayEngine); 這段代碼首先是創(chuàng)建了一個(gè)FramebufferNativeWindow對象,并且保存在DisplayHardware類的成員變量mNativeWindow中,用來管理硬件幀緩沖區(qū)。有了這個(gè)FramebufferNativeWindow對象之后,就可以通過它里面的一個(gè)fb設(shè)備來獲得硬件幀緩沖區(qū)的點(diǎn)密度以及刷新頻率等信息。后面我們再詳細(xì)分析FramebufferNativeWindow類的實(shí)現(xiàn)。 這段代碼接著再加載HAL層中的overlay

24、模塊,目的是要打開系統(tǒng)的overlay設(shè)備。在Android系統(tǒng)中,我們可以將overlay看作是一種特殊的Surface,一般用來顯示視頻。在這一系列文章中,我們暫時(shí)不關(guān)心overlay設(shè)備的實(shí)現(xiàn)。 我們接著往下閱讀代碼:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片EGLint w, h, dummy; EGLint numConfigs=0; EGLSurface surface; EGLContext context; / initialize EGL EGLint attribs = EGL_SURFACE_TYPE, EGL_WINDOW_BIT,

25、EGL_NONE, 0, EGL_NONE ; / debug: disable h/w rendering char propertyPROPERTY_VALUE_MAX; if (property_get(debug.sf.hw, property, NULL) 0) if (atoi(property) = 0) LOGW(H/W composition disabled); attribs2 = EGL_CONFIG_CAVEAT; attribs3 = EGL_SLOW_CONFIG; 這段代碼主要用來設(shè)置一個(gè)EGL屬性數(shù)組attribs,以便接下來可以根據(jù)這個(gè)屬性數(shù)組的值來正確的初

26、始化EGL庫。 我們接著往下閱讀代碼:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片/ 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; sta

27、tus_t err = EGLUtils:selectConfigForNativeWindow( display, attribs, mNativeWindow.get(), &config); LOGE_IF(err, couldnt find an EGLConfig matching the screen format); 這段代碼首先調(diào)用eglGetDisplay和eglInitialize函數(shù)來獲得和初始化OpengGL庫的默認(rèn)顯示屏,接著再調(diào)用EGLUtils:selectConfigForNativeWindow函數(shù)來獲得前面所創(chuàng)建的一個(gè)FramebufferNativeWin

28、dow對象所描述的系統(tǒng)主繪圖表面的配置信息,并且保存在EGLConfig對象config。有了這些配置信息之后,接下來就可以在硬件幀緩沖區(qū)上面創(chuàng)建系統(tǒng)的主繪圖表面。 我們接著往下閱讀代碼:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片EGLint r,g,b,a; eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r); eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g); eglGetConfigAttrib(display, config, EGL

29、_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; 這段代碼主要是用來獲得系統(tǒng)主繪圖表面的一些屬性,例如,四個(gè)顏色

30、分量R、G、B和A的大小,以及是否支持部分更新、是否使用慢渲染方式等。 我們接著往下閱讀代碼:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片/* * Create our main surface */ surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL); eglQuerySurface(display, surface, EGL_WIDTH, &mWidth); eglQuerySurface(display, surface, EGL_HEIGHT, &mH

31、eight); if (mFlags & PARTIAL_UPDATES) / if we have partial updates, we definitely dont 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

32、(dummy = EGL_BUFFER_PRESERVED) mFlags |= BUFFER_PRESERVED; 這段代碼首先調(diào)用函數(shù)eglCreateWindowSurface來創(chuàng)建系統(tǒng)的主繪圖表面。系統(tǒng)的主繪圖表面是直接在硬件幀緩沖區(qū)上創(chuàng)建的,用來渲染系統(tǒng)的UI,即負(fù)責(zé)合成和渲染所有應(yīng)用程序的UI。 這段代碼接著還獲得系統(tǒng)的主繪圖表面的寬度和高度,分別保存在并且保存在DisplayHardware類的成員變量mWidth和mHeight中。 這段代碼最后還判斷硬件幀緩沖區(qū)是否支持部分更新。如果支持的話,就會在調(diào)用函數(shù)eglSwapBuffers來渲染系統(tǒng)的UI時(shí),不保留后端圖形緩沖區(qū)的

33、內(nèi)容,因?yàn)楸A羰怯写鷥r(jià)的。如果不支持的話,那么就會就會調(diào)用函數(shù)eglQuerySurface來檢查在調(diào)用函數(shù)eglSwapBuffers來渲染系統(tǒng)的UI時(shí)是否需要保留后端圖形緩沖區(qū)的內(nèi)容。如果需要的話,那么就會將DisplayHardware類的成員變量mFlags的BUFFER_PRESERVED位設(shè)置為1。在保留后端圖形緩沖區(qū)的內(nèi)容的情況下,系統(tǒng)就可以支持僅僅渲染那些需要更新的臟區(qū)域,這些區(qū)域可以是不規(guī)則的。然而,實(shí)現(xiàn)不規(guī)則區(qū)域部分更新功能是有代價(jià)的,因?yàn)槊看卧阡秩綰I時(shí),都要將后端圖形緩沖區(qū)的內(nèi)容拷貝回那些不在那些需要更新的區(qū)域中去,這會導(dǎo)致性能低下。因此,系統(tǒng)一般都不支持不規(guī)則區(qū)域部分

34、更新功能。 我們接著往下閱讀代碼:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片/* 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) format; mPageF

35、lipCount = 0; 這段代碼主要是調(diào)用函數(shù)eglCreateContext來創(chuàng)建系統(tǒng)的主繪圖表面的上下文。有了這個(gè)上下文之后,OpenGL庫就能夠在前面所創(chuàng)建的系統(tǒng)主繪圖表面上渲染系統(tǒng)的UI了。 我們接著往下閱讀代碼:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片 /* * Gather OpenGL ES extensions */ eglMakeCurrent(display, surface, surface, context); GLExtensions& extensions(GLExtensions:getInstance(); extens

36、ions.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); glG

37、etIntegerv(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 s

38、urface (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 這段代碼主要用來檢查系統(tǒng)的主繪圖表面是否支持EGL_ANDROID_swap_rectangle擴(kuò)展屬性。如果支持的話,那么每次在調(diào)

39、用函數(shù)eglSwapBuffers來渲染UI時(shí),都會使用軟件的方式來支持部分更新區(qū)域功能,即:先得到不在新臟區(qū)域里面的那部分舊臟區(qū)域的內(nèi)容,然后再將得到的這部分舊臟區(qū)域的內(nèi)容拷貝回到要渲染的新圖形緩沖區(qū)中去,這要求每次在渲染UI時(shí),都要將被渲染的圖形緩沖區(qū)以及對應(yīng)的臟區(qū)域保存下來。注意,如果系統(tǒng)的主繪圖表面同時(shí)支持EGL_ANDROID_swap_rectangle擴(kuò)展屬性以及部分更新屬性,那么將會優(yōu)先使用部分更新屬性,因?yàn)楹笳呤侵苯釉谟布现С植糠指拢蚨阅軙谩?我們接著往下閱讀最后一段代碼:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片LOGI(EG

40、L 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-

41、%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

42、(GL_MAX_VIEWPORT_DIMS = %d, mMaxViewportDims); LOGI(flags = %08x, mFlags); / Unbind the context from this thread eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 這段代碼首先調(diào)用日志接口LOGI來顯示系統(tǒng)的主繪圖表面的屬性信息,接著最調(diào)用函數(shù)eglMakeCurrent來取消 設(shè)置OpenGL庫在當(dāng)前線程的繪圖表面以及繪圖上下文。 從這里就可以看出,一個(gè)DisplayHardware對象

43、在初始化完成之后,它還不能直接用來渲染系統(tǒng)的UI,因?yàn)樗跏蓟牡睦L圖表面以及繪圖上下文并沒有作為當(dāng)前線程的繪圖表面以及繪圖上下文。這是由于SurfaceFlinger服務(wù)可以同時(shí)支持多個(gè)DisplayHardware對象,即同時(shí)支持多個(gè)顯示屏造成的。 從前面SurfaceFlinger類的成員函數(shù)readyToRun可以知道,當(dāng)前正在初始化的DisplayHardware對象的編號為0,并且它是在SurfaceFlinger服務(wù)的UI渲染線程中創(chuàng)建的,為了可以將它設(shè)置系統(tǒng)的主顯示屏,即主繪圖表面,SurfaceFlinger類的成員函數(shù)readyToRun接下來還會調(diào)用它的成員函數(shù)make

44、Current來將它所里面的繪圖表面以及繪圖上下文設(shè)置為SurfaceFlinger服務(wù)的UI渲染線程的繪圖表面以及繪圖上下文。 DisplayHardware類的成員函數(shù)makeCurrent的實(shí)現(xiàn)如下所示:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片void DisplayHardware:makeCurrent() const eglMakeCurrent(mDisplay, mSurface, mSurface, mContext); 這個(gè)函數(shù)定義在文件frameworks/base/services/surfaceflinger/DisplayHar

45、dware/DisplayHardware.cpp中。 DisplayHardware類的成員函數(shù)makeCurrent的實(shí)現(xiàn)很簡單,它只是通過調(diào)用函數(shù)eglMakeCurrent來將前面已經(jīng)創(chuàng)建好的繪圖表面以及繪圖上下文設(shè)置為當(dāng)前線程的繪圖表面以及繪圖上下文,即設(shè)置為SurfaceFlinger服務(wù)的UI渲染線程的繪圖表面以及繪圖上下文。 系統(tǒng)的硬件幀緩沖區(qū)在初始化完成之后,SurfaceFlinger服務(wù)以后就可以調(diào)用用來描述它的一個(gè)DisplayHardware對象的成員函數(shù)flip來在它上面渲染系統(tǒng)的UI了,這個(gè)成員函數(shù)的實(shí)現(xiàn)如下所示:cpp view plain copy 在CODE

46、上查看代碼片派生到我的代碼片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(ersect(bounds(); const Rect b(newDirty.getBounds(); eglSetSwapRe

47、ctangleANDROID(dpy, surface, b.left, b.top, b.width(), b.height(); #endif if (mFlags & PARTIAL_UPDATES) mNativeWindow-setUpdateRectangle(dirty.getBounds(); mPageFlipCount+; eglSwapBuffers(dpy, surface); checkEGLErrors(eglSwapBuffers); / for debugging /glClearColor(1,0,0,0); /glClear(GL_COLOR_BUFFER_

48、BIT); 這個(gè)函數(shù)定義在文件frameworks/base/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp中。 這個(gè)函數(shù)主要就是調(diào)用OpenGL庫中的函數(shù)eglSwapBuffers來將系統(tǒng)的UI渲染到系統(tǒng)的主繪圖表面上去的,即渲染到系統(tǒng)的硬件幀緩沖區(qū)上去的。在渲染之前,函數(shù)會首先判斷系統(tǒng)的主繪圖表面是否支持EGL_ANDROID_swap_rectangle擴(kuò)展屬性和部分更新屬性。如果支持EGL_ANDROID_swap_rectangle擴(kuò)展屬性,即DisplayHardware類的成員變量mFlags的SWAP_RECTANGLE位等于1,那么就需要調(diào)用函數(shù)eglSetSwapRectangleANDROID來設(shè)置要渲染的區(qū)域,以便在渲染UI時(shí),可以通過軟件的方式來支持部分更新。如果硬件幀緩沖區(qū)直接支持部分更新屬性,即DisplayHardware類的成員變量mFlags的PARTIAL_UPDATES位等于1,那么就需要調(diào)用DisplayHardware類的成員變量mN

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論