日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

android surfaceflinger研究----显示系统

發(fā)布時(shí)間:2025/3/15 windows 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android surfaceflinger研究----显示系统 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? 這周抽空研究了一下SurfaceFlinger,發(fā)現(xiàn)真正復(fù)雜的并不是SurfaceFlinger本身,而是Android的display顯示系統(tǒng),網(wǎng)上關(guān)于這部分的介紹有不少,本不打算寫的,但是發(fā)現(xiàn)還是記錄一下研究代碼的過(guò)程比較好,一是能夠幫助自己理清思路,另一個(gè)原因就是以后當(dāng)這塊內(nèi)容忘記的時(shí)候,能快速的通過(guò)這個(gè)記錄撿起來(lái)。

? ? 一. ?android顯示系統(tǒng)的建立

我們看SurfaceFlinger的定義就知道,它其實(shí)是一個(gè)Thread, 因此SurfaceFlinger的初始化工作就理所當(dāng)然的放在了SurfaceFlinger線程中,詳見readyToRun()@SurfaceFlinger.cpp

? ??SurfaceFlinger對(duì)于顯示的管理是通過(guò)一個(gè)或多個(gè)GraphicPlane對(duì)象(目前android只實(shí)現(xiàn)了一個(gè))來(lái)管理的,

@SurfaceFlinger.h

[cpp]?view plaincopy
  • GraphicPlane????????????????mGraphicPlanes[1];??
  • ? ? 其實(shí),GraphicPlane類只是一個(gè)wrapper層,目的是當(dāng)android支持多個(gè)顯示系統(tǒng)時(shí),通過(guò)該類來(lái)管里各自的圖形系統(tǒng),顯示系統(tǒng)真正的初始化工作是通過(guò)DisplayHardware類來(lái)初始化底層圖形系統(tǒng)的管理與顯示的。真正的圖形顯示系統(tǒng)的初始化在init()@DisplayHardware.cpp 目前,android支持一個(gè)圖形系統(tǒng),這個(gè)圖形系統(tǒng)是全局的,surfaceflinger可以訪問(wèn),其他不通過(guò)surfaceflinger進(jìn)行圖形處理的application也可以對(duì)其進(jìn)行操作。


    ? ? 1. FrameBuffer的建立

    ? ??framebuffer,確切的是說(shuō)是linux下的framebuffer,,它是linux圖形顯示系統(tǒng)中一個(gè)與圖形硬件無(wú)關(guān)的抽象層,user完全不用考慮我們的硬件設(shè)備,而僅僅使用framebuffer就可以實(shí)現(xiàn)對(duì)屏幕的操作。

    ? ? android的framebuffer并沒(méi)有被SurfaceFlinger直接使用,而是在framebuffer外做了一層包裝,這個(gè)包裝就是FramebufferNativeWindow,我們來(lái)看一下FramebufferNativeWindow的創(chuàng)建過(guò)程。

    ? ?我們的framebuffer是由一個(gè)設(shè)備符fbDev來(lái)表示的,它是FramebufferNativeWindow的一個(gè)成員,我們來(lái)分析一下對(duì)fbDev的處理過(guò)程。

    ? ? 1.1. fbDev設(shè)備符

    ? ? 1.1.1?gralloc library

    ? ? 在這之前,先介紹一下gralloc library,它的形態(tài)如grallocBOARDPLATFORM.so,?BOARDPLATFORM可以從屬性ro.board.platform中獲得,這篇文章中我們以Qualcomm?msmx7x30為例,也就是gralloc.msm7x30.so中,它的源路徑在hardware/msm7k/libgralloc-qsd8k。

    ? ? framebuffer的初始化需要通過(guò)HAL?gralloc.msm7x30.so 來(lái)完成與底層硬件驅(qū)動(dòng)的適配,但是gralloc library并不是平臺(tái)無(wú)關(guān)的,不同的vendor可能會(huì)實(shí)現(xiàn)自己的gralloc library,因此為了保證在創(chuàng)建framebuffer時(shí)能夠平臺(tái)無(wú)關(guān),android只能是動(dòng)態(tài)的判斷并使用當(dāng)前的gralloc library,android通過(guò)從gralloc library中再抽象出一個(gè)hw_module_t結(jié)構(gòu)來(lái)供使用,它為framebuffer的初始化提供了需要的gralloc.msm7x30.so業(yè)務(wù)。因此通過(guò)這個(gè)hw_module_t結(jié)構(gòu)我們就不需要知道當(dāng)前系統(tǒng)使用的到底是哪個(gè)gralloc library。按規(guī)定,所有g(shù)ralloc library中的這個(gè)結(jié)構(gòu)體被命名為HAL_MODULE_INFO_SYM(HMI)。當(dāng)前分析的系統(tǒng)中,HAL_MODULE_INFO_SYM在hardware/msm7k/libgralloc-qsd8k/galloc.cpp。

    ? ? 1.1.2?打開fbDev設(shè)備符? ??

    ? ? 下面看如何打開?打開fbDev設(shè)備符。通過(guò)HAL_MODULE_INFO_SYM提供的gralloc.msm7x30.so的接口我們調(diào)用到了fb_device_open()@hardware/msm7k/libgralloc-qsd8kframebuffer.cpp。


    [cpp]?view plaincopy
  • int?fb_device_open(hw_module_t?const*?module,?const?char*?name,??
  • ????????hw_device_t**?device)??
  • {??
  • ????int?status?=?-EINVAL;??
  • ????if?(!strcmp(name,?GRALLOC_HARDWARE_FB0))?{??
  • ????????alloc_device_t*?gralloc_device;??
  • ????????status?=?gralloc_open(module,?&gralloc_device);??
  • ??
  • ????????/*?initialize?our?state?here?*/??
  • ????????fb_context_t?*dev?=?(fb_context_t*)malloc(sizeof(*dev));??
  • ????????memset(dev,?0,?sizeof(*dev));??
  • ??
  • ????????/*?initialize?the?procs?*/??
  • ????????dev->device.common.tag?=?HARDWARE_DEVICE_TAG;??
  • ??
  • ????????private_module_t*?m?=?(private_module_t*)module;??
  • ????????status?=?mapFrameBuffer(m);??
  • ??
  • }??

  • 在這個(gè)函數(shù)中,主要為fbDev設(shè)備符指定一個(gè)fb_context_t實(shí)例,并通過(guò)函數(shù)mapFrameBuffer()對(duì)設(shè)備節(jié)點(diǎn)/dev/graphics/fb0進(jìn)行操作,操作的目的有:

    1.獲得屏幕設(shè)備的信息,并將屏幕信息保存在HAL_MODULE_INFO_SYM(上面代碼中的module)中。

    ?2. 向/dev/graphics/fb0請(qǐng)求page flip模式,page flip模式需要至少2個(gè)屏幕大小的buffer,page flip模式在后面介紹。目前android系統(tǒng)中設(shè)置為2個(gè)屏幕大小的buffer。當(dāng)然屏幕設(shè)備可能不支持page flip模式。

    mapFrameBufferLocked()@hardware/msm7k/libgralloc-qsd8k/framebuffer.cpp

    [cpp]?view plaincopy
  • /*?
  • ?*?Request?NUM_BUFFERS?screens?(at?lest?2?for?page?flipping)?
  • ?*/??
  • info.yres_virtual?=?info.yres?*?NUM_BUFFERS;??
  • ??
  • ??
  • uint32_t?flags?=?PAGE_FLIP;??
  • if?(ioctl(fd,?FBIOPUT_VSCREENINFO,?&info)?==?-1)?{??
  • ????info.yres_virtual?=?info.yres;??
  • ????flags?&=?~PAGE_FLIP;??
  • ????LOGW("FBIOPUT_VSCREENINFO?failed,?page?flipping?not?supported");??
  • }??


  • 3. 映射屏幕設(shè)備緩存區(qū)給fbDev設(shè)備符。

    mapFrameBufferLocked()@hardware/msm7k/libgralloc-qsd8k/framebuffer.cpp

    [cpp]?view plaincopy
  • /*?
  • ?*?map?the?framebuffer?
  • ?*/??
  • ??
  • int?err;??
  • size_t?fbSize?=?roundUpToPageSize(finfo.line_length?*?info.yres_virtual);??
  • module->framebuffer?=?new?private_handle_t(dup(fd),?fbSize,??
  • ????????private_handle_t::PRIV_FLAGS_USES_PMEM);??
  • ??
  • module->numBuffers?=?info.yres_virtual?/?info.yres;??
  • module->bufferMask?=?0;??
  • ??
  • void*?vaddr?=?mmap(0,?fbSize,?PROT_READ|PROT_WRITE,?MAP_SHARED,?fd,?0);??
  • if?(vaddr?==?MAP_FAILED)?{??
  • ????LOGE("Error?mapping?the?framebuffer?(%s)",?strerror(errno));??
  • ????return?-errno;??
  • }??
  • module->framebuffer->base?=?intptr_t(vaddr);??
  • memset(vaddr,?0,?fbSize);??


  • 1.2 grDev設(shè)備符

    在為framebuffer,也就是FramebufferNativeWindow申請(qǐng)內(nèi)存之前,我們還要介紹一個(gè)概念,就是grDev設(shè)備符。它雖然也叫設(shè)備符,但是它和具體的設(shè)備沒(méi)有直接關(guān)系,我們看它的類型就是知道了alloc_device_t,沒(méi)錯(cuò),grDev設(shè)備符就是為了FramebufferNativeWindow管理內(nèi)存使用的。為FramebufferNativeWindow提供了申請(qǐng)/釋放內(nèi)存的接口。


    ? ? 1.3 FramebufferNativeWindow內(nèi)存管理

    FramebufferNativeWindow維護(hù)了2個(gè)buffer,? [cpp]?view plaincopy
  • sp<NativeBuffer>?buffers[2];??

  • ? ? 1.3.1 屏幕設(shè)備支持page filp模式

    目前的android系統(tǒng)默認(rèn)要求屏幕設(shè)備給系統(tǒng)映射2個(gè)屏幕大小的緩存區(qū),以便支持page flip模式,如果屏幕設(shè)備支持page flip模式,那么FramebufferNativeWindow中buffers將分別指向一個(gè)屏幕大小的屏幕設(shè)備緩存區(qū)。 [cpp]?view plaincopy
  • //?create?a?"fake"?handles?for?it??
  • intptr_t?vaddr?=?intptr_t(m->framebuffer->base);??
  • private_handle_t*?hnd?=?new?private_handle_t(dup(m->framebuffer->fd),?size,??
  • ?????????????????????????????????????????????private_handle_t::PRIV_FLAGS_USES_PMEM?|??
  • ?????????????????????????????????????????????private_handle_t::PRIV_FLAGS_FRAMEBUFFER);??
  • ??
  • //?find?a?free?slot??
  • for?(uint32_t?i=0?;?i<numBuffers?;?i++)?{??
  • ????if?((bufferMask?&?(1LU<<i))?==?0)?{??
  • ????????m->bufferMask?|=?(1LU<<i);??
  • ????????break;??
  • ????}??
  • ????vaddr?+=?bufferSize;??
  • }??
  • ??
  • hnd->base?=?vaddr;??
  • hnd->offset?=?vaddr?-?intptr_t(m->framebuffer->base);??
  • *pHandle?=?hnd;??

  • ? ? 1.3.2 屏幕設(shè)備不支持page flip模式

    mapFrameBufferLocked()@hardware/msm7k/libgralloc-qsd8k/framebuffer.cpp中可以得知,如果屏幕設(shè)備不支持page flip模式,那么numBuffer值將為1而不是2,那么映射過(guò)來(lái)的屏幕緩存區(qū)將只有一個(gè)屏幕大小,不夠支持page flip模式,那么此時(shí)將不使用這一個(gè)屏幕大小的屏幕緩存區(qū),而改為去dev/pmem設(shè)備去申請(qǐng)。

    gralloc_alloc_framebuffer_locked()@hardware/msm7k/libgralloc-qsd8k/gpu.cpp

    [cpp]?view plaincopy
  • ????const?uint32_t?bufferMask?=?m->bufferMask;??
  • ????const?uint32_t?numBuffers?=?m->numBuffers;??
  • ????const?size_t?bufferSize?=?m->finfo.line_length?*?m->info.yres;??
  • ????if?(numBuffers?==?1)?{??
  • ????????//?If?we?have?only?one?buffer,?we?never?use?page-flipping.?Instead,??
  • ????????//?we?return?a?regular?buffer?which?will?be?memcpy'ed?to?the?main??
  • ????????//?screen?when?post?is?called.??
  • ????????int?newUsage?=?(usage?&?~GRALLOC_USAGE_HW_FB)?|?GRALLOC_USAGE_HW_2D;??
  • ????????return?gralloc_alloc_buffer(bufferSize,?newUsage,?pHandle);??
  • ????}??

  • ? ? 2. 打開Overlay

    同選擇gralloc library相似,根據(jù)屬性值來(lái)選擇何時(shí)的overlay庫(kù),如果vendor廠商沒(méi)有提供overlay庫(kù)的話,那么系統(tǒng)將使用默認(rèn)的overlay庫(kù)overlay.default.so。同樣的我們獲得overlay庫(kù)的HAL_MODULE_INFO_SYM結(jié)構(gòu)體,作為系統(tǒng)調(diào)用overlay的接口。
    [cpp]?view plaincopy
  • if?(hw_get_module(OVERLAY_HARDWARE_MODULE_ID,?&module)?==?0)?{??
  • ????overlay_control_open(module,?&mOverlayEngine);??
  • }??


  • ? ? 3. 選擇OpenGL ES library(也即軟/硬件加速)

    OpenGL (Open Graphics Library)[3] is a standard specification defining a cross-language, cross-platform API for writing applications that produce 2D and 3D computer graphics. The interface consists of over 250 different function calls which can be used to draw complex three-dimensional scenes from simple primitives. OpenGL was developed by Silicon Graphics Inc. (SGI) in 1992[4] and is widely used in CAD, virtual reality, scientific visualization, information visualization, flight simulation, and video games. OpenGL is managed by the non-profit technology consortium Khronos Group.。 android是默認(rèn)支持OpenGL ES軟件加速的,library為libGLES_android,源碼路徑為frameworks\base\opengl\libagl;如果手機(jī)設(shè)備支持硬件加速的話,那么復(fù)雜的圖像處理工作將交由GPU去處理,那么效率將大大提高。但是如果系統(tǒng)真的存在硬件加速,它是如何選擇何時(shí)用軟件加速?何時(shí)用硬件加速的呢? 如何查看是否有GPU來(lái)實(shí)現(xiàn)硬件加速,很容易查看/system/lib/egl/egl.cfg文件內(nèi)容 [java]?view plaincopy
  • 0?0?android??
  • 0?1?adreno200??
  • ? ? 因此只要我們的移動(dòng)設(shè)備芯片集成了GPU,并提供了對(duì)應(yīng)的GL圖形庫(kù),那么我們就可以在我們的工程中device目錄下的egl.cfg文件中加入類似上面的配置,那么我們的系統(tǒng)就會(huì)支持硬件加速。 如adreno200 GPU提供的GL圖形庫(kù):
    [cpp]?view plaincopy
  • libGLESv1_CM_adreno200.so??
  • libGLESv2_adreno200.so??
  • libEGL_adreno200.so??
  • ? ? 那么假如我們的系統(tǒng)中軟硬件加速都支持了,那么我們從代碼來(lái)看能不能讓用戶自由的選擇加速類型,我們帶著問(wèn)題來(lái)研究一下代碼。

    ? ?3.1?OpenGL初始化

    在調(diào)用不管是軟件加速的還是硬件加速的OpenGL api之前,我們都需要把軟硬兩種模式的各自的OpenGL api提取出來(lái),抽象出一個(gè)interface來(lái)供系統(tǒng)使用,這個(gè)過(guò)程我稱之為OpenGL初始化過(guò)程。 軟硬兩種模式的OpenGL api被分別指定到了一個(gè)全局?jǐn)?shù)組的對(duì)應(yīng)位置。
    frameworks/base/opengl/libs/EGL/egl.cpp
    [cpp]?view plaincopy
  • static?egl_connection_t?gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];??
  • [cpp]?view plaincopy
  • enum?{??
  • ????IMPL_HARDWARE?=?0,??
  • ????IMPL_SOFTWARE,??
  • ????IMPL_NUM_IMPLEMENTATIONS??
  • };??

  • gEGLImpl[IMPL_HARDWARE]中保存著硬件圖形設(shè)備的OpenGL api地址,從 [cpp]?view plaincopy
  • libGLESv1_CM_adreno200.so??
  • libGLESv2_adreno200.so??
  • libEGL_adreno200.so??
  • 這3個(gè)庫(kù)中獲得;gEGLImpl[IMPL_SOFTWARE]中保存著軟件的OpenGL api地址,從libGLES_android.so中獲取。
    這部分代碼在egl_init_drivers_locked()@frameworks/base/opengl/libs/EGL/egl.cpp

    3.2 EGL和GLES api

    在OpenGL的初始化過(guò)程中,OpenGL提供了兩套api,分別稱為EGL和GLES。android在OPENGL初始化過(guò)程中,會(huì)將兩種不同的接口分開管理,從下面代碼中我們可以看到EGL和GLES api地址被存儲(chǔ)到了不同的位置。 @frameworks\base\opengl\libs\EGL\Loader.h
    [cpp]?view plaincopy
  • enum?{??
  • ????EGL?????????=?0x01,??
  • ????GLESv1_CM???=?0x02,??
  • ????GLESv2??????=?0x04??
  • };??
  • load_driver()@frameworks\base\opengl\libs\EGL\Loader.cpp
    上面枚舉的EGL表示ELG api;GLESvq1_CM表示OpenGL ES 1.0的api;GLESv2表示OpenGL ES 2.0的api。 EGL api地址最終被存儲(chǔ)在gEGLImpl[].egl中; GLESvq1_CM api地址最終被存儲(chǔ)在gEGLImpl[].hooks[GLESv1_INDEX]->gl中; GLESv2 api地址最終被存儲(chǔ)在gEGLImpl[].hooks[GLESv2_INDEX]->gl中;

    3.2.1 EGL api EGL is an interface between Khronos rendering APIs such as OpenGL ES or OpenVG and the underlying native platform window system. It handles graphics context management, surface/buffer binding, and rendering synchronization and enables high-performance, accelerated, mixed-mode 2D and 3D rendering using other Khronos APIs. 上面引用了官方的定義,可以看出,EGL是系統(tǒng)和OPENGL ES之間的接口,它的聲明在文件frameworks\base\opengl\libs\EGL\egl_entries.in。

    3.2.2 GLES GLES才是真正的OpenGL ES的api,它的聲明我們可以在frameworks\base\opengl\libs\entries.in找到。目前的android系統(tǒng)不但將EGL提供給系統(tǒng)使用,同時(shí)將GLES也提供給了系統(tǒng)使用,這個(gè)我們可以在最開始的顯示系統(tǒng)的結(jié)構(gòu)圖中可以看到,surfacefliger和framework的opengl模塊均可以訪問(wèn)EGL和GLES接口。

    3.3 OpenGL config

    每個(gè)OpenGL庫(kù)都根據(jù)不同的像素格式(pixel format)提供了一系統(tǒng)的config,android根據(jù)framebuffer中設(shè)置的像素格式來(lái)選擇合適的config,android根據(jù)中各config中的屬性信息來(lái)創(chuàng)建main surface和openGL上下文。

    3.3.1 系統(tǒng)默認(rèn)pixel format

    當(dāng)前的代碼分析是基于gingerbread的,在mapFrameBufferLocked()@hardware/msm7k/libgralloc-qsd8k/framebuffer.cpp中我們可以找到framebuffer的pixel format的類型 [cpp]?view plaincopy
  • ???if(info.bits_per_pixel?==?32)?{??
  • /*?
  • *?Explicitly?request?RGBA_8888?
  • */??
  • ??
  • /*?Note:?the?GL?driver?does?not?have?a?r=8?g=8?b=8?a=0?config,?so?if?we?do?
  • *?not?use?the?MDP?for?composition?(i.e.?hw?composition?==?0),?ask?for?
  • *?RGBA?instead?of?RGBX.?*/??
  • if?(property_get("debug.sf.hw",?property,?NULL)?>?0?&&?atoi(property)?==?0)??
  • ????module->fbFormat?=?HAL_PIXEL_FORMAT_RGBX_8888;??
  • else?if(property_get("debug.composition.type",?property,?NULL)?>?0?&&?(strncmp(property,?"mdp",?3)?==?0))??
  • ????module->fbFormat?=?HAL_PIXEL_FORMAT_RGBX_8888;??
  • else??
  • ????module->fbFormat?=?HAL_PIXEL_FORMAT_RGBA_8888;??
  • ???}?else?{??
  • /*?
  • *?Explicitly?request?5/6/5?
  • */??
  • module->fbFormat?=?HAL_PIXEL_FORMAT_RGB_565;??
  • ???}??

  • 目前的移動(dòng)設(shè)備都是真彩色,所以這里我們認(rèn)為我們的屏幕設(shè)備支持的是HAL_PIXEL_FORMAT_RGBA_8888。

    ? ??

    3.3.2 config初始化

    所有的OpenGL庫(kù)提供的config,同樣需要將軟硬兩種模式的各自的OpenGL config提取出來(lái)供系統(tǒng)使用,如同OpenGL api地址一樣。OpenGL config提取出來(lái)后保存在另外一個(gè)全局變量 [cpp]?view plaincopy
  • static?egl_display_t?gDisplay[NUM_DISPLAYS];??
  • [cpp]?view plaincopy
  • //??EGLDisplay?are?global,?not?attached?to?a?given?thread??
  • const?unsigned?int?NUM_DISPLAYS?=?1;??
  • 中,不同于gEGLImpl分開保存軟硬件api,所有的config,不論軟硬件的,均保存在gDisplay[0],因?yàn)樗械腸onfig是以屏幕區(qū)分的,同一塊屏幕應(yīng)該保存同一份config信息。
    在提取出的openGL的config時(shí),會(huì)保存到gDisplay[0].config中,在這兒有一個(gè)很tricky的實(shí)現(xiàn),它保證了硬件加速器的優(yōu)先使用!
    [cpp]?view plaincopy
  • <strong>??</strong>??????//?sort?our?configurations?so?we?can?do?binary-searches??
  • ????????qsort(??dp->configs,??
  • ????????????????dp->numTotalConfigs,??
  • ????????????????sizeof(egl_config_t),?cmp_configs);<strong>??
  • </strong>??
  • 最終,上述代碼會(huì)將gDisplay[0].config中的配置按照先硬件的,后軟件的規(guī)則做一個(gè)總體的排序。

    代碼在eglInitialize()@frameworks/base/opengl/libs/EGL/egl.cpp

    3.3.3 config選擇

    上文說(shuō)到,android會(huì)根據(jù)framebuffer的pixel format信息來(lái)獲取對(duì)應(yīng)的config,這個(gè)過(guò)程只選擇一個(gè)合適的config,選到為止。

    3.3.3.1 滿足屬性要求

    并不是所有的config都可以被選擇,首先這個(gè)config的屬性需要滿足 init()@DisplayHardware.cpp
    [cpp]?view plaincopy
  • //?initialize?EGL??
  • EGLint?attribs[]?=?{??
  • ????????EGL_SURFACE_TYPE,???EGL_WINDOW_BIT,??
  • ????????EGL_NONE,???????????0,??
  • ????????EGL_NONE??
  • };??
  • 3.3.3.2 滿足RGBA要求

    在pixelflinger中,為系統(tǒng)提供了各個(gè)pixel format的基本信息,RGBA值,字節(jié)數(shù)/pixel,位數(shù)/pixel。 system/core/libpixelflinger/format.cpp
    [cpp]?view plaincopy
  • static?GGLFormat?const?gPixelFormatInfos[]?=??
  • {???//??????????Alpha????Red?????Green???Blue??
  • ????{??0,??0,?{{?0,?0,???0,?0,???0,?0,???0,?0?}},????????0?},???//?PIXEL_FORMAT_NONE??
  • ????{??4,?32,?{{32,24,???8,?0,??16,?8,??24,16?}},?GGL_RGBA?},???//?PIXEL_FORMAT_RGBA_8888??
  • android會(huì)根據(jù)pixelflinger的pixel format信息,去和openGL的config比較,得到想要的config。
    selectConfigForPixelFormat()@frameworks/base/libs/ui/EGLUtils.cpp
    [cpp]?view plaincopy
  • EGLConfig*?const?configs?=?(EGLConfig*)malloc(sizeof(EGLConfig)*numConfigs);??
  • if?(eglChooseConfig(dpy,?attrs,?configs,?numConfigs,?&n)?==?EGL_FALSE)?{??
  • ????free(configs);??
  • ????return?BAD_VALUE;??
  • }??
  • ??
  • const?int?fbSzA?=?fbFormatInfo.getSize(PixelFormatInfo::INDEX_ALPHA);??
  • const?int?fbSzR?=?fbFormatInfo.getSize(PixelFormatInfo::INDEX_RED);??
  • const?int?fbSzG?=?fbFormatInfo.getSize(PixelFormatInfo::INDEX_GREEN);??
  • const?int?fbSzB?=?fbFormatInfo.getSize(PixelFormatInfo::INDEX_BLUE);???
  • ??
  • int?i;??
  • EGLConfig?config?=?NULL;??
  • for?(i=0?;?i<n?;?i++)?{??
  • ????EGLint?r,g,b,a;??
  • ????EGLConfig?curr?=?configs[i];??
  • ????eglGetConfigAttrib(dpy,?curr,?EGL_RED_SIZE,???&r);??
  • ????eglGetConfigAttrib(dpy,?curr,?EGL_GREEN_SIZE,?&g);??
  • ????eglGetConfigAttrib(dpy,?curr,?EGL_BLUE_SIZE,??&b);??
  • ????eglGetConfigAttrib(dpy,?curr,?EGL_ALPHA_SIZE,?&a);??
  • ????if?(fbSzA?<=?a?&&?fbSzR?<=?r?&&?fbSzG?<=?g?&&?fbSzB??<=?b)?{??
  • ????????config?=?curr;??
  • ????????break;??
  • ????}??
  • }??

  • ? ? 4. 創(chuàng)建main surface

    要讓OpenGL進(jìn)行圖形處理,那么需要在OpenGL中創(chuàng)建一個(gè)openGL surface。代碼在eglCreateWindowSurface()@frameworks/base/opengl/libs/EGL/egl.cpp 調(diào)用當(dāng)前的config所處的openGL庫(kù)的api來(lái)創(chuàng)建surface。通過(guò)validate_display_config()方法來(lái)獲取當(dāng)前config的openGL api。 創(chuàng)建的surface會(huì)和FramebufferNativeWindow關(guān)聯(lián)到一起。

    ? ? 5. 創(chuàng)建?OpenGL ES 上下文

    ? ??An?OpenGL context?represents many things. A context stores all of the state associated with this instance of OpenGL. It represents the (potentially visible)?default framebufferthat rendering commands will draw to when not drawing to a?framebuffer object. Think of a context as an object that holds all of OpenGL; when a context is destroyed, OpenGL is destroyed.

    ? ?http://www.opengl.org/wiki/OpenGL_context

    ?具體的創(chuàng)建過(guò)程專業(yè)術(shù)語(yǔ)太多,也沒(méi)有仔細(xì)研究不再介紹。

    ? ? 6. 綁定context和surface

    有了surface,有了FramebufferNativeWindow,有了context,基本上與圖形系統(tǒng)相關(guān)的概念都有了,下一步就是把這幾個(gè)概念關(guān)聯(lián)起來(lái),在創(chuàng)建surface時(shí)已經(jīng)將surface和FramebufferNativeWindow關(guān)聯(lián)了起來(lái)。 eglMakeCurrent()@frameworks/base/opengl/libs/EGL/egl.cpp

    6.1 多線程支持

    OpenGL 提供了多線程的支持,有以下2點(diǎn)的支持: 1. 一個(gè)Context只能被一個(gè)線程使用,不能存在多個(gè)線程使用同一個(gè)context。因此在多線層操作中使用到了TLS技術(shù),即Thread-local storage,來(lái)保證context被唯一使用。 makeCurrent()@frameworks/base/opengl/libs/libagl/egl.cpp
    [cpp]?view plaincopy
  • ????ogles_context_t*?current?=?(ogles_context_t*)getGlThreadSpecific();??
  • ????if?(gl)?{??
  • ????????egl_context_t*?c?=?egl_context_t::context(gl);??
  • ????????if?(c->flags?&?egl_context_t::IS_CURRENT)?{??
  • ????????????if?(current?!=?gl)?{??
  • ????????????????//?it?is?an?error?to?set?a?context?current,?if?it's?already??
  • ????????????????//?current?to?another?thread??
  • ????????????????return?-1;??
  • ????????????}??
  • ????????}?else?{??
  • ????????????if?(current)?{??
  • ????????????????//?mark?the?current?context?as?not?current,?and?flush??
  • ????????????????glFlush();??
  • ????????????????egl_context_t::context(current)->flags?&=?~egl_context_t::IS_CURRENT;??
  • ????????????}??
  • ????????}??
  • ????????if?(!(c->flags?&?egl_context_t::IS_CURRENT))?{??
  • ????????????//?The?context?is?not?current,?make?it?current!??
  • ????????????setGlThreadSpecific(gl);??
  • ????????????c->flags?|=?egl_context_t::IS_CURRENT;??
  • ????????}??
  • 2. 在同一進(jìn)程中,對(duì)于不同的線程對(duì)OpenGL庫(kù)的訪問(wèn),可能使用的GLES api version不同,同樣可以使用TLS技術(shù)來(lái)保證多線程過(guò)程中,不同線程調(diào)用各自的GLES api。 前面我們介紹過(guò)GLES api地址被存放在gEGLImpl[].hooks[VERSION]->gl中,因此為保證多線程支持,android將gEGLImpl[].hooks[VERSION]保存到了TLS中,這樣就實(shí)現(xiàn)了不同線程各自調(diào)用各自版本的GLES api。 eglMakeCurrent()@frameworks/base/opengl/libs/EGL/egl.cpp
    [cpp]?view plaincopy
  • //?cur_c?has?to?be?valid?here?(but?could?be?terminated)??
  • if?(ctx?!=?EGL_NO_CONTEXT)?{??
  • ????setGlThreadSpecific(c->cnx->hooks[c->version]);??
  • ????setContext(ctx);??
  • ????_c.acquire();??
  • }?else?{??
  • ????setGlThreadSpecific(&gHooksNoContext);??
  • ????setContext(EGL_NO_CONTEXT);??
  • }??

  • 盡管openGL 實(shí)現(xiàn)了多線程的支持,目前我從代碼中別沒(méi)有找到多線程的使用。

    6.2 設(shè)置surface和context之間的關(guān)系

    由于vendor廠商提供的GPU的GLES庫(kù)是不可見的,因此以libGLES_android.so軟件加速為例來(lái)說(shuō)明這個(gè)過(guò)程。 contex中保存著兩個(gè)surface,read和draw,多少情況下這兩個(gè)surface為同一個(gè)surface。 設(shè)置FramebufferNativeWindow中Buffers[2]之一為surface的數(shù)據(jù)區(qū), 通過(guò)connect()和bindDrawSurface()。最終的形態(tài)如下圖所示:


    在init()@DisplayHardware.cpp中,在綁定surface和context之后,馬上在當(dāng)前線程中unbind了context,通過(guò) [cpp]?view plaincopy
  • //?Unbind?the?context?from?this?thread??
  • eglMakeCurrent(display,?EGL_NO_SURFACE,?EGL_NO_SURFACE,?EGL_NO_CONTEXT);??
  • 這么做的目的應(yīng)該是支持多display系統(tǒng)中的特殊處理,目的是當(dāng)系統(tǒng)有多個(gè)display系統(tǒng)的話,那么surfaceflinger就會(huì)去定義多個(gè)DisplayHardware對(duì)象,那么為了保證下一個(gè)DisplayHardware對(duì)象的創(chuàng)建不受影響,在當(dāng)前的DisplayHardware創(chuàng)建完成后,將context從當(dāng)前的進(jìn)程中unbind掉。 不過(guò)沒(méi)關(guān)系,在所有的DisplayHardware創(chuàng)建完成之后,surfaceflinger會(huì)重新bind 主Display系統(tǒng)的context和surface。 readyToRun()@SurfaceFlinger.cpp
    [cpp]?view plaincopy
  • //?initialize?primary?screen??
  • //?(other?display?should?be?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();??
  • const?uint32_t?w?=?hw.getWidth();??
  • const?uint32_t?h?=?hw.getHeight();??
  • const?uint32_t?f?=?hw.getFormat();??
  • hw.makeCurrent();??



  • 下圖為這個(gè)圖形系統(tǒng)的類圖結(jié)構(gòu)。



    原文地址:?http://blog.csdn.net/windskier/article/details/7030732

    總結(jié)

    以上是生活随笔為你收集整理的android surfaceflinger研究----显示系统的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 香港三级日本三级韩国三级 | 四虎影院免费视频 | 欧美草比视频 | 久久人精品 | 亚洲香蕉av | 欧美bbbbb性bbbbb视频 | 亚洲资源av| 欧美日韩精品一区二区三区蜜桃 | 91偷拍精品一区二区三区 | 欧洲美女与动交zozzo | 中文字幕精品亚洲 | 欧美大片免费 | 日韩国产欧美在线视频 | 1区2区3区视频 | 人妻在线日韩免费视频 | 国产精品第一国产精品 | 最近中文字幕在线中文高清版 | 艳母免费在线观看 | 自拍偷拍日韩精品 | 毛片视频网站 | 高h校园不许穿内裤h调教 | 法国空姐在线观看免费 | 中文无码精品一区二区三区 | 嫩模被强到高潮呻吟不断 | 欧美vieox另类极品 | 欧美人与性动交a欧美精品 日韩免费高清视频 | 久久综合九色综合网站 | 男男gay羞辱feet贱奴vk | 国产精品mm| 久久精品国产亚洲AV黑人 | www.日韩 | 久久无码人妻精品一区二区三区 | 亚洲乱轮视频 | 91av小视频| av午夜激情 | 日韩精品免费一区二区三区 | 91av福利视频 | 久久久精品一区二区涩爱 | 久久国产中文字幕 | 95国产精品 | 超碰狠狠 | 丰满少妇一区二区三区 | 日本中文字幕有码 | 亚洲在线一区二区三区 | 外国毛片 | 黄瓜视频在线播放 | 色窝窝无码一区二区三区 | 国产毛片一区二区三区va在线 | julia一区二区中文久久97 | 亚洲情趣 | 日韩av综合网 | 亚洲狼人在线 | a视频免费 | 97午夜 | 国产极品美女高潮无套在线观看 | 日日不卡av| 夜夜草视频 | 亚洲AV无码乱码国产精品牛牛 | 亚洲一区二区三区高清视频 | 免费又黄又爽又色的视频 | 国产高清自拍av | 一个色综合久久 | 黄色变态网站 | 欧美黑人精品 | 国产噜噜噜噜噜久久久久久久久 | 五月婷婷开心网 | 青青草在线观看视频 | 天天天天天天天干 | 特黄特色免费视频 | 深夜天堂 | 动漫美女无遮挡免费 | 182tv午夜| 中国成熟妇女毛茸茸 | 欧美肥老妇视频 | 国产男女猛烈无遮挡免费视频动漫 | 在线观看aa | 国产精品扒开腿做爽爽爽视频 | 精品一区二区三区免费看 | 国产精品一区在线 | 日韩在线 中文字幕 | wwwwww日本| 国产一级二级三级在线观看 | 久久综合九色综合网站 | 91pao| 欧美亚洲在线 | 国产精彩视频一区 | 一级片免费观看 | 东京热加勒比无码少妇 | 精品国产一区二区三区四区精华 | 九九在线观看免费高清版 | 日韩中文在线字幕 | 18禁裸男晨勃露j毛免费观看 | 91一起草 | 一及黄色大片 | 先锋av资源 | 国产人妻黑人一区二区三区 | 91亚洲在线 | 久久99精品久久久久久噜噜 | 91在线色 |