螢幕撕裂及掉幀原因與解決方案

2020-07-14     segmentfault官方

原標題:螢幕撕裂及掉幀原因與解決方案

作者:Daniel_Coder來源:SegmentFault 思否

1. 什麼是螢幕撕裂

還記得以前的顯示器中常常出現上下兩半螢幕顯示錯位的情況,比如下面的圖:

圖中可知,上半部分和下半部分顯示的完全是不同的畫面,這就是螢幕撕裂。

那麼為什麼會出現這種情況呢?是什麼原因造成了螢幕撕裂呢?首先我們先了解一下光柵掃描顯示系統結構。

2. 光柵掃描顯示系統結構

什麼時候光柵掃描呢?它是指我們顯示器的電子束從螢幕的左上角開始橫向向右一行一行逐行掃描。類似於印表機列印文檔。如下圖:

圖像是由像素矩陣組成的,顯示一個圖像的時間和圖像的複雜度毫無關係,而是顯示整個光柵所需要的時間。

2.1 簡單的光柵掃描顯示系統

當要顯示圖片的時候,首先CPU先對圖片進行數據處理,然後將處理後的數據存儲在內存中,再由顯示控制器通過系統總線讀取數據進行顯示,此時並沒有獨立的顯卡。

2.2 常用的光柵掃描顯示系統

此時我們在內存中單獨開闢了一個圖片數據的存儲區域(幀緩存),如下圖:

此時雖然有了獨立的存儲空間,但是沒有本質上的改變,顯示控制器還是通過系統總線讀取圖片數據,對系統總線仍有較大的壓力。隨後更高級一點的顯示系統變出來了。

2.3 高級的光柵掃描顯示系統

上面這種系統結構是我們現在計算機常用的顯示系統結構,此時已經有了獨立的顯卡,在現實圖片的時候,CPU解碼處理完後,數據將被顯示處理器拷貝到顯存中,後期再操作的時候不會占用內存空間,也不依賴系統總線。

3. 螢幕撕裂原因

在顯示一張圖片的時候,其流程為:GPU進⾏渲染—>幀緩存區⾥ —>顯示控制器—>讀取幀緩存區信息(位圖) —> 數模轉化(數位訊號處—>模 擬型號) —>(逐⾏掃描)顯示。

正常的情況下,顯示器完全顯示完一幀後,幀緩存區更新一幀,這樣便不會有撕裂問題,但事實並非如此。

當顯卡輸出幀的速度比顯示器快,顯示器的處理速度跟不上顯卡,在顯示器處理顯卡丟過來的第1幀的時候,第2幀就又到了(幀緩存區已更新),導致同一個畫面同時出現1、2兩幀,撕裂就產生了。

4. 雙緩存區及垂直同步信號Vsync

為了解決撕裂,蘋果引入了: 垂直同步Vsync + 雙緩存區 DoubleBuffering。

(1)垂直同步Vsync:當螢幕掃描完成後,便會發出同步信號,顯示控制器切換幀緩存區。

(2)雙緩存區 DoubleBuffering :就是GPU開闢了兩個幀緩存區(暫叫A、B緩存區)。

執行流程:

當CPU/GPU處理完數據後,將圖片數據放入A幀緩存區,然後顯示控制器讀取A幀緩存區,並在螢幕上掃描,當掃描結束後,發出同步信號,顯示控制器切換到B幀緩存區並讀取數據掃描顯示,一次類推,不斷的切換取數據顯示,此時螢幕撕裂的問題便解決了。

5. 掉幀

當採用垂直同步信號和雙緩存區後,仍有一種情況無法避免,那邊是掉幀,所謂的掉幀,並不是某一幀丟失了,沒有渲染,而是重複渲染同一幀數據。

為什麼會出現這種情況呢?

如果按照1秒60幀算的話,每幀渲染的時間為16.7ms(1s/60 ≈16.7ms),當CPU/GPU處理圖⽚數據速度大於了16.7ms,那麼在同步信號來的時候,便拿不到幀緩存區數據,這個時候顯示控制器只能顯示同一幀的數據。

為了減少掉幀,便引入了三級緩存區,三級緩存區是為了充分利用CPU/GPU的空餘時間,開闢ABC三個幀緩存區,A顯示螢幕, B也渲染好,C再從GPU拿取渲染數據,當螢幕緩存區和幀緩存區都弄好了,然後視頻控制器再指向幀緩存區的另外一個,再顯示,這樣交替,達到減少掉幀的情況,這樣做就比二級緩存區多了一個確認的操作。

掉幀問題,我們只能是減少掉幀,即使用三級緩存區,也不一定能絕對的避免掉幀。

文章來源: https://twgreatdaily.com/zh-mo/ufMpTHMBfGB4SiUwgA1I.html

Flutter 知識點

2020-08-10