當(dāng)繪制的時(shí)候,是如何顯示到屏幕的?

Android Skia iOS CoreGraphics Windows GDI/DX3D/DX2D Linux Cario AGG 等等都是大家常用的渲染器(Path Render, 這里的渲染器特指最終會(huì)通過算法做像素染色. 而不是不是Web前端提到的渲染, 兩者之間存在著本質(zhì)的差異),這些渲染器把程序提交的渲染Command(例如:DrawLine DrawArcTo..)最后轉(zhuǎn)化成了光柵圖,然后提交給硬件上屏就OK了.

那么實(shí)際上就是生成一張位圖而已?
可以這么理解, 操作系統(tǒng)或者程序就是不停的構(gòu)建當(dāng)前界面的位圖,在另一篇里面我介紹了硬件加速構(gòu)建UI的原理.

1. 打印機(jī)-曾經(jīng)的顯示器

計(jì)算機(jī)剛剛出現(xiàn)的時(shí)候沒有好用的輸出設(shè)備,最常用的是打印機(jī),對(duì)的你沒有聽錯(cuò)。打印機(jī)是曾經(jīng)的顯示設(shè)備,每次程序運(yùn)行結(jié)束后會(huì)通過打印機(jī)把結(jié)果打印出來。用過打印機(jī)的同學(xué)可能沒有注意到一個(gè)事實(shí):打印機(jī)是獨(dú)占設(shè)備(所謂獨(dú)占設(shè)備指的是在同一個(gè)時(shí)刻只能由一個(gè)程序持有該設(shè)備,其他程序只能等待直到能夠獲取到)。

后面終于可以用顯示器來實(shí)時(shí)顯示計(jì)算的繪圖結(jié)果了,極大解決顯示的成本。但是在早期的顯示系統(tǒng)架構(gòu)下顯示器也是獨(dú)占設(shè)備(和打印機(jī)一樣),也就是一個(gè)時(shí)刻只能由一個(gè)程序往顯示器輸出結(jié)果(是不是很傻@@@!)。隨著操作系統(tǒng)的發(fā)展,尤其是分時(shí)多任務(wù)(通過CPU切割時(shí)間片來實(shí)現(xiàn)的多任務(wù),也就是多線程的技術(shù))系統(tǒng)的發(fā)展。需要多個(gè)程序同時(shí)往屏幕輸出圖像(試想一下如果現(xiàn)在的顯示器還是獨(dú)占設(shè)計(jì),那么你在用chrome上網(wǎng)的時(shí)候沒有版本聊QQ了,寫Office的時(shí)候也不能切換到網(wǎng)易云音樂聽一段了),同時(shí)顯示多個(gè)程序的輸出可以極大的提升顯示器的利用率,也能極大的提升用戶的使用效率。

2. 如何讓多個(gè)程序同時(shí)繪制到屏幕上去

所以上面已經(jīng)闡述了,對(duì)于硬件驅(qū)動(dòng)測我們能做的就是提交給他那張渲染好的位圖,基本這個(gè)方式動(dòng)不了。所以我們在操作系統(tǒng)測這邊動(dòng)動(dòng)奶子~ 額 腦子哦!

首先從操作系統(tǒng)測接管了對(duì)顯示設(shè)備的控制,也就是顯示器交給了操作系統(tǒng)獨(dú)占,當(dāng)然這個(gè)時(shí)候有其他程序需要獨(dú)占顯示器有不太可能(現(xiàn)在也提供了獨(dú)占的方式,主要提供給游戲使用。獨(dú)占的好處是可以更快速的和硬件通訊,數(shù)據(jù)可以快速發(fā)送到屏幕上面并顯示給用戶)。

當(dāng)程序需要向屏幕繪制內(nèi)容的時(shí)候,首先向系統(tǒng)申請(qǐng)一個(gè)窗口然后系統(tǒng)會(huì)給這個(gè)窗口分配一塊RAM存儲(chǔ)空間(可以是內(nèi)存也可以是顯存),這個(gè)存儲(chǔ)空間可以看做是一個(gè)RGBA的二維數(shù)組(也就是一張位圖)。這樣程序只要把繪制的內(nèi)容繪制到這塊存儲(chǔ)空間上面去就好。那么當(dāng)有多個(gè)程序(進(jìn)程)同時(shí)需要繪制的話,那么系統(tǒng)這個(gè)時(shí)候其實(shí)就已經(jīng)分配了多個(gè)窗口。那么操作系統(tǒng)只要定時(shí)統(tǒng)計(jì)所有窗口的位圖,然后按照窗口的上下層疊順序通過AlphaBlend合并在一張位圖上,然后操作系統(tǒng)把這張合成后的位圖提交給顯示器顯示就好了。

image

3. 雙緩沖和三緩沖

上面多窗口的架構(gòu)確實(shí)能解決多進(jìn)程渲染到屏幕的問題,通過系統(tǒng)定時(shí)合并 多窗口分別渲染的方式解決。就按Android系統(tǒng)來說,這個(gè)窗口就叫做Surface而合并Surface的系統(tǒng)程序就叫做SurfaceFlinger。其他的操作系統(tǒng)以此類推。

但是存在一個(gè)問題:多窗口的RAM數(shù)據(jù)空間在被系統(tǒng)合并的時(shí)候,對(duì)應(yīng)渲染的程序不能操作這塊RAM數(shù)據(jù)(你想啊,如果系統(tǒng)正在把當(dāng)前這幀合并到屏幕上去,合并不是瞬時(shí)完成的啊,需要一定的時(shí)間啊。你的程序恰好在這個(gè)時(shí)間也在操作這幀的數(shù)據(jù)就會(huì)出現(xiàn)上下兩幀錯(cuò)位的情況)。這樣影響了軟件渲染的性能,畢竟不能真正的并行處理。當(dāng)系統(tǒng)在合并上屏的時(shí)候,程序如果需要繪制只能等待了,那么如何解決這個(gè)問題?

答案:程序在系統(tǒng)申請(qǐng)窗口系統(tǒng)可以分配2塊一模一樣的RAM空間,每塊RAM存儲(chǔ)空間都可以獨(dú)立存儲(chǔ)程序渲染的位圖。一塊位圖叫做前景圖另一塊叫后景圖。程序每次只能繪制到前景圖,當(dāng)程序繪制完當(dāng)前這幀的時(shí)候就會(huì)通知系統(tǒng)交換前后景圖(系統(tǒng)內(nèi)核只是交換了一下指針,成本非常低)。操作系統(tǒng)定期把后景圖合并上屏幕,通過這種雙緩沖的方式就可以讓系統(tǒng)合并上屏軟件繪制并行處理,互相之間基本不影響。

總結(jié):系統(tǒng)自己持有了一張用來合并結(jié)果的位圖,每個(gè)程序在分配窗口的時(shí)候其實(shí)有2張位圖數(shù)據(jù)空間。這樣整個(gè)渲染系統(tǒng)基本上是由3張位圖數(shù)據(jù)共同作用。單純從軟件測來說叫雙緩沖。整個(gè)架構(gòu)體系又叫做三緩沖。

4. 多緩沖在操作系統(tǒng)的各種使用場景

操作系統(tǒng)利用多緩沖的方式把顯示設(shè)備獨(dú)占設(shè)備改變到了共享設(shè)備。讓多個(gè)進(jìn)程可以同時(shí)渲染到顯示器上面,大大增強(qiáng)了顯示器這種外接設(shè)備使用效率。那么這類技巧還用在哪里?

答案: 硬盤,聲卡,網(wǎng)卡 等等都采用了類似的方案。

比如聲卡:傳統(tǒng)聲卡早期只支持一路聲音數(shù)據(jù)的播發(fā),也就是同一時(shí)刻只能播發(fā)一個(gè)程序的一個(gè)聲音(大白話)。現(xiàn)在的顯卡已經(jīng)支持有效多路(比如聲卡的接口支持同時(shí)輸入3路聲音的數(shù)據(jù))。但是有的時(shí)候我們的系統(tǒng)采用還是多緩沖的方式來解決這個(gè)問題。每個(gè)程序當(dāng)需要播發(fā)聲音的時(shí)候,就把聲音的數(shù)據(jù)(PCM編碼的聲音數(shù)據(jù))提交給系統(tǒng)。系統(tǒng)利用混音算法(顏色用的Alpha融合,聲音用的是混合算法)把多路混合成一路。得到這一路的數(shù)據(jù)后再丟給聲卡播發(fā)就好了(這類算法只要CPU的運(yùn)算性能足夠,理論可以同時(shí)播發(fā)任意路。當(dāng)你在看電影順帶聊著QQ,系統(tǒng)時(shí)不時(shí)還給點(diǎn)提醒聲音等等,就都可以同時(shí)播發(fā)了)。

image

那還有一點(diǎn)需要討論,屏幕在接受到系統(tǒng)的顯示位圖后,是如何顯示到屏幕的?

5. 屏幕刷新和VSYNC垂直同步型號(hào)

屏幕也是采用掃描線的算法來實(shí)現(xiàn)對(duì)屏幕顯示像素的刷新。比如常見的橫向掃描屏幕,屏幕就按照位圖的像素的數(shù)據(jù)從左到右,從上到下依次設(shè)置屏幕顏色的亮度。每一幀從第一個(gè)像素處理完到最后一個(gè)像素處理完成成為一幀刷新。那么刷新一幀需要多少時(shí)間?這個(gè)從顯示器出廠就定死了。比如常規(guī)的顯示器都是60HZ刷新率的(也就是一秒可以刷新60張),也有用于游戲的80HZ144HZ的屏幕。

按照60HZ的刷新頻率來說,一幀數(shù)據(jù)從第一個(gè)像素到最后一個(gè)像素需要 1000ms/60 = 16ms的時(shí)間。如果屏幕刷新到一半的時(shí)候,系統(tǒng)提交了新的一幀數(shù)據(jù)。那么就會(huì)出現(xiàn)當(dāng)前屏幕顯示的,已經(jīng)刷新的一半內(nèi)容是上一幀的,后面的部分繪制下一幀的數(shù)據(jù),這樣的現(xiàn)象被叫做幀撕裂,甚至?xí)霈F(xiàn)屏幕閃爍。

那么系統(tǒng)如何在屏幕一幀完全刷新完成后才提交下一幀的數(shù)據(jù)?這就要說到垂直同步了。顯示器在刷新完一幀的時(shí)候回向系統(tǒng)提交一個(gè)叫VSYNC的信號(hào),系統(tǒng)受到這個(gè)硬件信號(hào)后才提交數(shù)據(jù)。同樣操作系統(tǒng)也模擬了類似這個(gè)信號(hào)功能的軟信號(hào),用來告知軟件渲染算法,減少不必要的多余的渲染(比如屏幕只有60HZ,那么我的軟件性能很好每秒可以渲染120幀,那么多出來的60幀就被丟棄了,這樣就導(dǎo)致了性能的浪費(fèi))。

6. 運(yùn)動(dòng)模糊

image

最后: 我們來探討下運(yùn)動(dòng)模糊具體是什么?不知道大家關(guān)注過這個(gè)問題么?電視機(jī)的28HZ大家就覺得很流暢,但是游戲60HZ了還是覺得有卡頓。這個(gè)問題主要原因就是存在于 運(yùn)動(dòng)模糊的原因。電視機(jī)的界面基本全是靠攝像機(jī)拍攝的結(jié)果,大家可以挨幀分析下攝像機(jī)拍攝的影片。你會(huì)發(fā)現(xiàn)其中有很多的幀是模擬的。這種運(yùn)動(dòng)模糊是由于攝像機(jī)的CCD芯片需要曝光時(shí)間導(dǎo)致的。也正是這種現(xiàn)象,讓人腦在看到這類視頻的時(shí)候回覺得非常流暢。但是游戲的每一幀都是程序生成的,每一幀都是精確的不存在這種運(yùn)動(dòng)模糊效果。所以游戲即使刷新頻率到60HZ大家也覺得沒有電視來的流暢。目前有些游戲通過渲染前后2幀的插值來模擬這種運(yùn)動(dòng)模糊,當(dāng)游戲里面有大場景的轉(zhuǎn)動(dòng)的時(shí)候效果會(huì)比傳統(tǒng)游戲更加流暢(當(dāng)然大家都在60HZ滿幀渲染的情況下的)。

總結(jié)下: 額~ 沒啥總結(jié)的,那就這樣吧!
</br></br>
版權(quán)所有,如有轉(zhuǎn)載請(qǐng)聯(lián)系我本人http://www.breakerror.com/archives/68-i.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 繪制像素到屏幕上 answer-huang22 Mar 2014 分享文章 一個(gè)像素是如何繪制到屏幕上去的?有很多...
    阿貍旅途T恤閱讀 1,756評(píng)論 0 7
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 30,194評(píng)論 8 265
  • Smarty
    layjoy閱讀 172評(píng)論 0 1
  • 就在不久前,我們學(xué)校五年級(jí)段開展了有趣生動(dòng),真實(shí)的職業(yè)體驗(yàn)。聽到這個(gè)振奮人心的消息,大家都免不了一陣愉悅的心?情,...
    等多久打開閱讀 651評(píng)論 0 0
  • 紙醉金迷的世界 包裹著他的心 拋向那宇宙黑洞 恍恍惚惚 恍恍惚惚 快活的軀體呀 去救救你的心 他被你喜愛的一切 砸...
    琳泳閱讀 274評(píng)論 0 2

友情鏈接更多精彩內(nèi)容