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

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

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

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

3、系統(tǒng)的UI渲染到硬件幀緩沖區(qū)中去的。GraphicPlane、DisplayHardware和FramebufferNativeWindow這三個類的關系如圖1所示。接下來,我們就分別介紹GraphicPlane、DisplayHardware和FramebufferNativeWindow這三個類的實現,以便可以理解SurfaceFlinger服務是如何通過它們來管理系統(tǒng)的硬件幀緩沖區(qū)的。 從前面 一文可以知道,SurfaceFlinger服務在啟動的過程中,會對系統(tǒng)的硬件幀緩沖區(qū)進行初始化,如下所示: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(); . 這個函數定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger

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

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

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

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

13、轉方向。 函數最后調用GraphicPlane類的成員函數setOrientation來設備顯示屏的實際度度、高度以及旋轉方向,如下所示: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; 這個函數定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp文件中。 參數orientation的值等于ISurfaceComposer:eOrientationDefault,即SurfaceFlinger服務在初始化系統(tǒng)顯示屏時,會將它的旋轉方向設置為默認值,以后再根據實際情況來做調整。 GraphicPlane類有三

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

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

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

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

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

21、是從DisplayHardwareBase類繼承下來的。接下來,我們首先繼續(xù)分析一個DisplayHardware對象的初始化過程,接著再分析這個DisplayHardware對象的父對象DisplayHardwareBase的初始化過程,以便可以了解DisplayHardwareBase類的實現。 一個DisplayHardware對象的初始化過程是通過調用DisplayHardware類的成員函數init來實現的。DisplayHardware類的成員函數init的實現比較長,我們分段來閱讀: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)建了一個FramebufferNativeWindow對象,并且保存在DisplayHardware類的成員變量mNativeWindow中,用來管理硬件幀緩沖區(qū)。有了這個FramebufferNativeWindow對象之后,就可以通過它里面的一個fb設備來獲得硬件幀緩沖區(qū)的點密度以及刷新頻率等信息。后面我們再詳細分析FramebufferNativeWindow類的實現。 這段代碼接著再加載HAL層中的overlay

24、模塊,目的是要打開系統(tǒng)的overlay設備。在Android系統(tǒng)中,我們可以將overlay看作是一種特殊的Surface,一般用來顯示視頻。在這一系列文章中,我們暫時不關心overlay設備的實現。 我們接著往下閱讀代碼: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; 這段代碼主要用來設置一個EGL屬性數組attribs,以便接下來可以根據這個屬性數組的值來正確的初

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); 這段代碼首先調用eglGetDisplay和eglInitialize函數來獲得和初始化OpengGL庫的默認顯示屏,接著再調用EGLUtils:selectConfigForNativeWindow函數來獲得前面所創(chuàng)建的一個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)主繪圖表面的一些屬性,例如,四個顏色

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

33、內容,因為保留是有代價的。如果不支持的話,那么就會就會調用函數eglQuerySurface來檢查在調用函數eglSwapBuffers來渲染系統(tǒng)的UI時是否需要保留后端圖形緩沖區(qū)的內容。如果需要的話,那么就會將DisplayHardware類的成員變量mFlags的BUFFER_PRESERVED位設置為1。在保留后端圖形緩沖區(qū)的內容的情況下,系統(tǒng)就可以支持僅僅渲染那些需要更新的臟區(qū)域,這些區(qū)域可以是不規(guī)則的。然而,實現不規(guī)則區(qū)域部分更新功能是有代價的,因為每次在渲染UI時,都要將后端圖形緩沖區(qū)的內容拷貝回那些不在那些需要更新的區(qū)域中去,這會導致性能低下。因此,系統(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; 這段代碼主要是調用函數eglCreateContext來創(chuàng)建系統(tǒng)的主繪圖表面的上下文。有了這個上下文之后,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擴展屬性。如果支持的話,那么每次在調

39、用函數eglSwapBuffers來渲染UI時,都會使用軟件的方式來支持部分更新區(qū)域功能,即:先得到不在新臟區(qū)域里面的那部分舊臟區(qū)域的內容,然后再將得到的這部分舊臟區(qū)域的內容拷貝回到要渲染的新圖形緩沖區(qū)中去,這要求每次在渲染UI時,都要將被渲染的圖形緩沖區(qū)以及對應的臟區(qū)域保存下來。注意,如果系統(tǒng)的主繪圖表面同時支持EGL_ANDROID_swap_rectangle擴展屬性以及部分更新屬性,那么將會優(yōu)先使用部分更新屬性,因為后者是直接在硬件上支持部分更新,因而性能會更好。 我們接著往下閱讀最后一段代碼: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); 這段代碼首先調用日志接口LOGI來顯示系統(tǒng)的主繪圖表面的屬性信息,接著最調用函數eglMakeCurrent來取消 設置OpenGL庫在當前線程的繪圖表面以及繪圖上下文。 從這里就可以看出,一個DisplayHardware對象

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

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

45、dware/DisplayHardware.cpp中。 DisplayHardware類的成員函數makeCurrent的實現很簡單,它只是通過調用函數eglMakeCurrent來將前面已經創(chuàng)建好的繪圖表面以及繪圖上下文設置為當前線程的繪圖表面以及繪圖上下文,即設置為SurfaceFlinger服務的UI渲染線程的繪圖表面以及繪圖上下文。 系統(tǒng)的硬件幀緩沖區(qū)在初始化完成之后,SurfaceFlinger服務以后就可以調用用來描述它的一個DisplayHardware對象的成員函數flip來在它上面渲染系統(tǒng)的UI了,這個成員函數的實現如下所示: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); 這個函數定義在文件frameworks/base/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp中。 這個函數主要就是調用OpenGL庫中的函數eglSwapBuffers來將系統(tǒng)的UI渲染到系統(tǒng)的主繪圖表面上去的,即渲染到系統(tǒng)的硬件幀緩沖區(qū)上去的。在渲染之前,函數會首先判斷系統(tǒng)的主繪圖表面是否支持EGL_ANDROID_swap_rectangle擴展屬性和部分更新屬性。如果支持EGL_ANDROID_swap_rectangle擴展屬性,即DisplayHardware類的成員變量mFlags的SWAP_RECTANGLE位等于1,那么就需要調用函數eglSetSwapRectangleANDROID來設置要渲染的區(qū)域,以便在渲染UI時,可以通過軟件的方式來支持部分更新。如果硬件幀緩沖區(qū)直接支持部分更新屬性,即DisplayHardware類的成員變量mFlags的PARTIAL_UPDATES位等于1,那么就需要調用DisplayHardware類的成員變量mN

溫馨提示

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

評論

0/150

提交評論