前些時候看到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相交時對於相交部分允許使用不同的著色方式,