前一些時候看到CSDN上一篇文章介紹FlashPlayer的渲染效能是HTML 5的數倍文章,回想起幾年來對Adobe的FlashPlayer研究,想從理論上探究一下為什麼會有這樣的結果,同時也解釋一下針對傳統硬體加速(非GPU方案)為什麼Adobe的FlashPlayer會被批評的原因;
早年在一家IC設計公司為一個低端平台(具有硬體3D加速)作官方的FlashPlayer的硬體加速,幾個月下來,硬體渲染引擎做好了,但最後的結果非常出人意料----- 改用硬體加速後的效能居然比軟體渲染的要差;為了解釋其中的原因,我們還是先從Adobe的FlashPlayer軟體渲染演算法原理上入手;
事實上,FlashPlayer的2D渲染引擎使用的是最常見的掃描線演算法(Scanline演算法),及簡單的講,是以虛擬顯示設備(對於考慮抗鋸齒的情況下,虛擬顯示設備大於實際顯示設備,如4 x 4抗鋸齒,虛擬顯示設備的縱向是實際顯示設備的4倍)每條掃描線計算和向量圖形的各邊(Edge)的交點,並根據不同的填充法則填充兩個交點間的水平線;這樣隨著掃描線自上而下逐條計算完成後,在虛擬顯示設備中即完成了一幅完整圖形的構成,然後,再根據超採樣算法,將虛擬顯示設備上的圖形輸出到實際顯示設備上,這樣,在實際顯示設備上即得到一幅完美的無鋸齒的圖形;以一定的速率重複以上動作,及可以得到連續的動畫;FlashPlayer通過解析流式的swf文件,並且以指定的速度更新畫面完成動畫的播放,因此,我們已經有些簡單的結論:
l 向量運算是一個工程浩大的計算;這也解釋了為什麼FlashPlayer在多數平台上存在的效能問題;非常遺憾的是,目前即時2D向量圖形播放軟體似乎只有FlashPlayer,所以這個黑鍋是沒辦法了;
l 為什麼高畫質的顯示效能要較低畫質的差很多;因為在高畫質下,FlashPlayer是使用的4 x 4的超採樣抗鋸齒,及表示透過掃描線計算交點的計算量是低畫質的4倍;
(關於2D向量圖形顯示,參考我之前的資源:http://download.csdn. net/source/5773340)
在實際的2D向量引擎中,問題往往更為複雜,在考慮Cap和Join後,實際即使是一根很簡單的折線或Bezier曲線都是由很多的曲線構成的(如圖折線的兩個端點---- Cap):
這樣可以理解為什麼現在為止鮮有可以和Adobe FlashPlayer相抗衡的實時2D矢量顯示程序了,這是不是有些矛盾:為什麼Adobe的FlashPlayer會一枝獨秀呢?以上只是關於2D向量圖形顯示的原理性解釋,其他2D向量顯示引擎,如OpenVG(gingkoVG)、agg等使用的是完全相同的原理,Adobe的FlashPlayer相對通用的2D向量顯示引擎一定有他自己特殊的定義,仔細閱讀Adobe關於FlashPlayer的官方技術檔(swf_file_format_spec_v10),我們很快就發現了兩處很有趣的說明:
l FlashPlayer只支援2階的貝塞爾曲線(Quadratic Bezier),而不支援類似PostScript和OpenVG等傳統2D向量引擎所使用的3階貝塞爾曲線(Cubic Bezier);
相對2階Beizer曲線,3階貝塞爾曲線單獨一條在計算交點是增加的計算量似乎不大:多了幾次乘法運算;但在多數CPU體系中乘除法運算所消耗的時間會大於加減法,尤其在非常大的運算量下,其累積的差異就更大了;
l 在Adobe的官方文件中明確註明FlashPlayer不支援點劃線(Dash)
為什麼不支援Dash呢?事實上在向量圖形顯示中,除了曲線和掃描線交點的計算外,最困難的是計算曲線的長度,Dash的顯示必須依賴事先的曲線長度的計算;在實現gingkoVG時,不包含Dash功能的曲線顯示其顯示效能是使用Dash的4倍;
l 僅此而已嗎?並不是,不過即使以上的約束,其顯示效能已經「被提升」了數倍。在Adobe的FlashPlayer中,針對渲染同時使用了其他的一些最佳化演算法,當然這些最佳化演算法作為通用最佳化技術在多數2D向量引擎中也會被使用;(參考:http://download.csdn.net/source /1998019)
非常遺憾的是多數2D向量引擎因為需要考慮通用性,都會支援3階貝塞爾曲線和點劃線,甚至是圓弧(OpenVG),這樣從演算法層面我們不難理解為什麼那些使用標準2D渲染引擎(如gnash使用了agg)的開源FlashPlayer無法和Adobe的FlashPlayer的執行效能相比較了----- 因為FlashPlayer的2D渲染引擎是針對Flash播放的實時性的需要量身定做的;當然,Adobe的FlashPlayer除了這些外,在程式的最佳化上有很多高明之處,這些不是我們這裡需要討論的;
事情似乎就此可以告一段落了,但隨著對FlashPlayer的深入研究,我們發現了一些更深入的問題----- 及Adobe的FlashPlayer被廣為批評的硬體加速性能差的原因;在不考慮針對特殊GPU的硬體加速,我們只考慮標準硬體加速方式(OpenGL ES/OpenVG)來解釋這個問題;Adobe的FlashPlayer在誕生時,那時還沒有通用的2D向量顯示標準(如OpenVG),其針對軟體渲染的2D向量圖形顯示可謂是亮點,在經過十幾年的發展和優化,Adobe的2D軟體向量渲染引擎可謂已經發展到盡善盡美了,這也可以解釋為什麼自FlashPlayer 4到FlashPlayer 8其渲染引擎一直沒有太大的變化,也可以解釋為什麼Adobe FlashPlayer軟體渲染的效能甚至會好於使用低階硬體加速的效能了;但,成也蕭何敗也蕭何,過於完美的標準和演算法阻礙了使用標準硬體加速的可能(針對特殊GPU的硬體加速,因為其靈活性不在我們的考慮中),我們繼續仔細研究Adobe的官方文件,我們注意到,關於填充法則FlashPlayer相對傳統的2D向量引擎有不同之處:傳統的2D向量引擎(如OpenVG/gingkoVG)有兩種填充法則:奇偶填充法則(Even-odd fill rule)和非零填充法則(Non-zero fill rule),而Adobe的FlashPlayer又增加了邊填充法則( Edge-edge fill rule),及多數2D向量引擎針對每個Shape/Object使用單一的著色方式(RColor),而在邊邊填充法則中,一條邊根據左右不同可以分別擁有兩種不同的著色方式( color1/color2),當然Adobe這樣做的原因是增加了軟體渲染的靈活性,如在兩個Shape相交時對於相交部分允許使用不同的著色方式,如圖:
遺憾的是這樣在使用標準當圖形加速引擎時(OpenVG/OpenGL)會為我們帶來困惑:即針對一個Shape我們可能會有不同的著色方式,這似乎是有悖於多數2D向量引擎;儘管針對邊邊填充法則我們可以視作是兩個不同奇偶填充法則,但考慮到針對每條邊因此可能隨時變化的填充法則,具有單一Color的Shape的重新確認並非那麼容易,尤其對於由曲線構成的Shape。不過這個問題相對2D向量圖形渲染並不是很麻煩,但我們因此可以發現針對現在多數傳統2D向量引擎,Adobe FlashPlayer似乎並不「友善」 ----- 程式設計師必須小心編寫一個中間層來解決這些問題,這並非是Adobe的錯誤:在FlashPlayer誕生時這些2D向量顯示標準(OpenVG)還沒有出現; 只是非常可惜的是Adobe的FlashPlayer並非開源程式(Adobe FlashPlayer的AVM2已經開源),因此,我們必須耐心等待Adobe為我們去做這些,除非我們不准備使用官方的FlashPlayer;
(我們自己使用OpenVG的FlashPlayer)