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

歡迎訪問 生活随笔!

生活随笔

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

Android

Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析(10)...

發(fā)布時間:2025/7/14 Android 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析(10)... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

??? ? ? 7. 圖形緩沖區(qū)的注銷過程

?? ? ? 圖形緩沖區(qū)使用完成之后,就需要從當(dāng)前進(jìn)程中注銷。前面提到,注銷圖形緩沖區(qū)是由Gralloc模塊中的函數(shù)gralloc_unregister_buffer來實現(xiàn)的,這個函數(shù)實現(xiàn)在文件hardware/libhardware/modules/gralloc/mapper.cpp中,如下所示:
  • int?gralloc_unregister_buffer(gralloc_module_t?const*?module,??
  • ????????buffer_handle_t?handle)??
  • {??
  • ????if?(private_handle_t::validate(handle)?<?0)??
  • ????????return?-EINVAL;??
  • ??
  • ????//?never?unmap?buffers?that?were?created?in?this?process??
  • ????private_handle_t*?hnd?=?(private_handle_t*)handle;??
  • ????if?(hnd->pid?!=?getpid())?{??
  • ????????if?(hnd->base)?{??
  • ????????????gralloc_unmap(module,?handle);??
  • ????????}??
  • ????}??
  • ????return?0;??
  • }??
  • ?? ? ? ?這個函數(shù)同樣是首先調(diào)用private_handle_t類的靜態(tài)成員函數(shù)validate來驗證參數(shù)handle指向的一塊圖形緩沖區(qū)的確是由Gralloc模塊分配的,接著再將將參數(shù)handle指向的一塊圖形緩沖區(qū)轉(zhuǎn)換為一個private_handle_t結(jié)構(gòu)體hnd來訪問。 ?? ? ? ?一塊圖形緩沖區(qū)只有被注冊過,即被Gralloc模塊中的函數(shù)gralloc_register_buffer注冊過,才需要注銷,而由函數(shù)gralloc_register_buffer注冊的圖形緩沖區(qū)都不是由當(dāng)前進(jìn)程分配的,因此,當(dāng)前進(jìn)程在注銷一個圖形緩沖區(qū)的時候,會檢查要注銷的圖形緩沖區(qū)是否是由自己分配的。如果是由自己分配的話,那么它什么也不做就返回了。 ?? ? ? ?假設(shè)要注銷的圖形緩沖區(qū)hnd不是由當(dāng)前進(jìn)程分配的,那么接下來就會調(diào)用另外一個函數(shù)galloc_unmap來注銷圖形緩沖區(qū)hnd。 ?? ? ? ?函數(shù)galloc_unmap也是實現(xiàn)在文件hardware/libhardware/modules/gralloc/mapper.cpp中,如下所示:
  • static?int?gralloc_unmap(gralloc_module_t?const*?module,??
  • ????????buffer_handle_t?handle)??
  • {??
  • ????private_handle_t*?hnd?=?(private_handle_t*)handle;??
  • ????if?(!(hnd->flags?&?private_handle_t::PRIV_FLAGS_FRAMEBUFFER))?{??
  • ????????void*?base?=?(void*)hnd->base;??
  • ????????size_t?size?=?hnd->size;??
  • ????????//LOGD("unmapping?from?%p,?size=%d",?base,?size);??
  • ????????if?(munmap(base,?size)?<?0)?{??
  • ????????????LOGE("Could?not?unmap?%s",?strerror(errno));??
  • ????????}??
  • ????}??
  • ????hnd->base?=?0;??
  • ????return?0;??
  • }??
  • ?? ? ? ?這個函數(shù)的實現(xiàn)與前面所分析的函數(shù)gralloc_map的實現(xiàn)是類似的,只不過它執(zhí)行的是相反的操作,即將解除一個指定的圖形緩沖區(qū)在當(dāng)前進(jìn)程的地址空間中的映射,從而完成對這個圖形緩沖區(qū)的注銷工作。 ?? ? ? ?這樣,圖形緩沖區(qū)的注銷過程就分析完成了,接下來我們再繼續(xù)分析一個圖形緩沖區(qū)是如何被渲染到系統(tǒng)幀緩沖區(qū)去的,即它的內(nèi)容是如何繪制在設(shè)備顯示屏中的。 ?? ? ? ?8. 圖形緩沖區(qū)的渲染過程 ?? ? ? ?用戶空間的應(yīng)用程序?qū)嬅鎯?nèi)容寫入到圖形緩沖區(qū)中去之后,還需要將圖形緩沖區(qū)渲染到系統(tǒng)幀緩沖區(qū)中去,這樣才可以把畫面繪制到設(shè)備顯示屏中去。前面提到,渲染圖形緩沖區(qū)是由Gralloc模塊中的函數(shù)fb_post來實現(xiàn)的,這個函數(shù)實現(xiàn)在文件hardware/libhardware/modules/gralloc/framebuffer.cpp中,如下所示:
  • static?int?fb_post(struct?framebuffer_device_t*?dev,?buffer_handle_t?buffer)??
  • {??
  • ????if?(private_handle_t::validate(buffer)?<?0)??
  • ????????return?-EINVAL;??
  • ??
  • ????fb_context_t*?ctx?=?(fb_context_t*)dev;??
  • ??
  • ????private_handle_t?const*?hnd?=?reinterpret_cast<private_handle_t?const*>(buffer);??
  • ????private_module_t*?m?=?reinterpret_cast<private_module_t*>(??
  • ????????????dev->common.module);??
  • ??
  • ????if?(hnd->flags?&?private_handle_t::PRIV_FLAGS_FRAMEBUFFER)?{??
  • ????????const?size_t?offset?=?hnd->base?-?m->framebuffer->base;??
  • ????????m->info.activate?=?FB_ACTIVATE_VBL;??
  • ????????m->info.yoffset?=?offset?/?m->finfo.line_length;??
  • ????????if?(ioctl(m->framebuffer->fd,?FBIOPUT_VSCREENINFO,?&m->info)?==?-1)?{??
  • ????????????LOGE("FBIOPUT_VSCREENINFO?failed");??
  • ????????????m->base.unlock(&m->base,?buffer);??
  • ????????????return?-errno;??
  • ????????}??
  • ????????m->currentBuffer?=?buffer;??
  • ??
  • ????}?else?{??
  • ????????//?If?we?can't?do?the?page_flip,?just?copy?the?buffer?to?the?front???
  • ????????//?FIXME:?use?copybit?HAL?instead?of?memcpy??
  • ??
  • ????????void*?fb_vaddr;??
  • ????????void*?buffer_vaddr;??
  • ??
  • ????????m->base.lock(&m->base,?m->framebuffer,??
  • ????????????????GRALLOC_USAGE_SW_WRITE_RARELY,??
  • ????????????????0,?0,?m->info.xres,?m->info.yres,??
  • ????????????????&fb_vaddr);??
  • ??
  • ????????m->base.lock(&m->base,?buffer,??
  • ????????????????GRALLOC_USAGE_SW_READ_RARELY,??
  • ????????????????0,?0,?m->info.xres,?m->info.yres,??
  • ????????????????&buffer_vaddr);??
  • ??
  • ????????memcpy(fb_vaddr,?buffer_vaddr,?m->finfo.line_length?*?m->info.yres);??
  • ??
  • ????????m->base.unlock(&m->base,?buffer);??
  • ????????m->base.unlock(&m->base,?m->framebuffer);??
  • ????}??
  • ??
  • ????return?0;??
  • }??
  • ?? ? ? ?參數(shù)buffer用來描述要渲染的圖形緩沖區(qū),它指向的必須要是一個private_handle_t結(jié)構(gòu)體,這是通過調(diào)用private_handle_t類的靜態(tài)成員函數(shù)validate來驗證的。驗證通過之后,就可以將參數(shù)buffer所描述的一個buffer_handle_t結(jié)構(gòu)體轉(zhuǎn)換成一個private_handle_t結(jié)構(gòu)體hnd。 ?? ? ? ?參數(shù)dev用來描述在Gralloc模塊中的一個fb設(shè)備。從前面第3部分的內(nèi)容可以知道,在打開fb設(shè)備的時候,Gralloc模塊返回給調(diào)用者的實際上是一個fb_context_t結(jié)構(gòu)體,因此,這里就可以將參數(shù)dev所描述的一個framebuffer_device_t結(jié)構(gòu)體轉(zhuǎn)換成一個fb_context_t結(jié)構(gòu)體ctx。 ?? ? ? ?參數(shù)dev的成員變量common指向了一個hw_device_t結(jié)構(gòu)體,這個結(jié)構(gòu)體的成員變量module指向了一個Gralloc模塊。從前面第1部分的內(nèi)容可以知道,一個Gralloc模塊是使用一個private_module_t結(jié)構(gòu)體來描述的,因此,我們可以將dev->common.moudle轉(zhuǎn)換成一個private_module_t結(jié)構(gòu)體m。 ?? ? ? ?由于private_handle_t結(jié)構(gòu)體hnd所描述的圖形緩沖區(qū)可能是在系統(tǒng)幀緩沖區(qū)分配的,也有可能是內(nèi)存中分配的,因此,我們分兩種情況來討論圖形緩沖區(qū)渲染過程。 ?? ? ? ?當(dāng)private_handle_t結(jié)構(gòu)體hnd所描述的圖形緩沖區(qū)是在系統(tǒng)幀緩沖區(qū)中分配的時候,即這個圖形緩沖區(qū)的標(biāo)志值flags的PRIV_FLAGS_FRAMEBUFFER位等于1的時候,我們是不需要將圖形緩沖區(qū)的內(nèi)容拷貝到系統(tǒng)幀緩沖區(qū)去的,因為我們將內(nèi)容寫入到圖形緩沖區(qū)的時候,已經(jīng)相當(dāng)于是將內(nèi)容寫入到了系統(tǒng)幀緩沖區(qū)中去了。雖然在這種情況下,我們不需要將圖形緩沖區(qū)的內(nèi)容拷貝到系統(tǒng)幀緩沖區(qū)去,但是我們需要告訴系統(tǒng)幀緩沖區(qū)設(shè)備將要渲染的圖形緩沖區(qū)作為系統(tǒng)當(dāng)前的輸出圖形緩沖區(qū),這樣才可以將要渲染的圖形緩沖區(qū)的內(nèi)容繪制到設(shè)備顯示屏來。例如,假設(shè)系統(tǒng)幀緩沖區(qū)有2個圖形緩沖區(qū),當(dāng)前是以第1個圖形緩沖區(qū)作為輸出圖形緩沖區(qū)的,這時候如果我們需要渲染第2個圖形緩沖區(qū),那么就必須告訴系統(tǒng)幀繪沖區(qū)設(shè)備,將第2個圖形緩沖區(qū)作為輸出圖形緩沖區(qū)。 ?? ? ? 設(shè)置系統(tǒng)幀緩沖區(qū)的當(dāng)前輸出圖形緩沖區(qū)是通過IO控制命令FBIOPUT_VSCREENINFO來進(jìn)行的。IO控制命令FBIOPUT_VSCREENINFO需要一個fb_var_screeninfo結(jié)構(gòu)體作為參數(shù)。從前面第3部分的內(nèi)容可以知道,private_module_t結(jié)構(gòu)體m的成員變量info正好保存在我們所需要的這個fb_var_screeninfo結(jié)構(gòu)體。有了個m->info這個fb_var_screeninfo結(jié)構(gòu)體之后,我們只需要設(shè)置好它的成員變量yoffset的值(不用設(shè)置成員變量xoffset的值是因為所有的圖形緩沖區(qū)的寬度是相等的),就可以將要渲染的圖形緩沖區(qū)設(shè)置為系統(tǒng)幀緩沖區(qū)的當(dāng)前輸出圖形緩沖區(qū)。fb_var_screeninfo結(jié)構(gòu)體的成員變量yoffset保存的是當(dāng)前輸出圖形緩沖區(qū)在整個系統(tǒng)幀緩沖區(qū)的縱向偏移量,即Y偏移量。我們只需要將要渲染的圖形緩沖區(qū)的開始地址hnd->base的值減去系統(tǒng)幀緩沖區(qū)的基地址m->framebuffer->base的值,再除以圖形緩沖區(qū)一行所占據(jù)的字節(jié)數(shù)m->finfo.line_length,就可以得到所需要的Y偏移量。 ?? ? ? ?在執(zhí)行IO控制命令FBIOPUT_VSCREENINFO之前,還會將作為參數(shù)的fb_var_screeninfo結(jié)構(gòu)體的成員變量activate的值設(shè)置FB_ACTIVATE_VBL,表示要等到下一個垂直同步事件出現(xiàn)時,再將當(dāng)前要渲染的圖形緩沖區(qū)的內(nèi)容繪制出來。這樣做的目的是避免出現(xiàn)屏幕閃爍,即避免前后兩個圖形緩沖區(qū)的內(nèi)容各有一部分同時出現(xiàn)屏幕中。 ?? ? ? ?成功地執(zhí)行完成IO控制命令FBIOPUT_VSCREENINFO之后,函數(shù)還會將當(dāng)前被渲染的圖形緩沖區(qū)保存在private_module_t結(jié)構(gòu)體m的成員變量currentBuffer中,以便可以記錄當(dāng)前被渲染的圖形緩沖區(qū)是哪一個。 ?? ? ? ?當(dāng)private_handle_t結(jié)構(gòu)體hnd所描述的圖形緩沖區(qū)是在內(nèi)存中分配的時候,即這個圖形緩沖區(qū)的標(biāo)志值flags的PRIV_FLAGS_FRAMEBUFFER位等于0的時候,我們就需要將它的內(nèi)容拷貝到系統(tǒng)幀緩沖區(qū)中去了。這個拷貝的工作是通過調(diào)用函數(shù)memcpy來完成的。在拷貝之前,我們需要三個參數(shù)。第一個參數(shù)是要渲染的圖形緩沖區(qū)的起址地址,這個地址保存在參數(shù)buffer所指向的一個private_handle_t結(jié)構(gòu)體中。第二個參數(shù)是要系統(tǒng)幀緩沖區(qū)的基地址,這個地址保存在private_module_t結(jié)構(gòu)體m的成員變量framebuffer所指向的一個private_handle_t結(jié)構(gòu)體中。第三個參數(shù)是要拷貝的內(nèi)容的大小,這個大小就剛好是一個屏幕像素所占據(jù)的內(nèi)存的大小。屏幕高度由m->info.yres來描述,而一行屏幕像素所占用的字節(jié)數(shù)由m->finfo.line_length來描述,將這兩者相乘,就可以得到一個屏幕像素所占據(jù)的內(nèi)存的大小。 ?? ? ? ?在將一塊內(nèi)存緩沖區(qū)的內(nèi)容拷貝到系統(tǒng)幀緩沖區(qū)中去之前,需要對這兩塊緩沖區(qū)進(jìn)行鎖定,以保證在拷貝的過程中,這兩塊緩沖區(qū)的內(nèi)容不會被修改。這個鎖定的工作是由Gralloc模塊中的函數(shù)gralloc_lock來實現(xiàn)的。從前面第1部分的內(nèi)容可以知道,Gralloc模塊中的函數(shù)gralloc_lock的地址正好就保存在private_module_t結(jié)構(gòu)體m的成員變量base所描述的一個gralloc_module_t結(jié)構(gòu)體的成員函數(shù)lock中。 ?? ? ? ?在調(diào)用函數(shù)gralloc_lock來鎖定一塊緩沖區(qū)之后,還可以通過最后一個輸出參數(shù)來獲得被鎖定的緩沖區(qū)的開始地址,因此,通過調(diào)用函數(shù)gralloc_lock來鎖定要渲染的圖形緩沖區(qū)以及系統(tǒng)幀緩沖區(qū),就可以得到前面所需要的第一個和第二個參數(shù)。 ?? ? ? ?將要渲染的圖形緩沖區(qū)的內(nèi)容拷貝到系統(tǒng)幀緩沖區(qū)之后,就可以解除前面對它們的鎖定了,這個解鎖的工作是由Gralloc模塊中的函數(shù)gralloc_unlock來實現(xiàn)的。從前面第1部分的內(nèi)容可以知道,Gralloc模塊中的函數(shù)gralloc_unlock的地址正好就保存在private_module_t結(jié)構(gòu)體m的成員變量base所描述的一個gralloc_module_t結(jié)構(gòu)體的成員函數(shù)unlock中。 ?? ? ? ?這樣,一個圖形緩沖區(qū)的渲染過程就分析完成了。

    總結(jié)

    以上是生活随笔為你收集整理的Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析(10)...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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