Gecko Layer 除錯工具: LayerDump & LayerScope
在 Firefox 的 Rendering Pipeline 中,一路從 Layout 到 Layer tree,在 Layer tree 中的每一個 Layer 會依序的畫到螢幕上,所以通常畫面出現問題後(ex. 某個畫面下面剛好少了一個 pixel ),我們會先從 Layer 開始下手從下到上去檢查到底是那一個環節出了問題。
不過 Layer 這麼複雜,有什麼好用的工具可以幫助我們快速的檢查每一個 Layer 的屬性呢?這次就來介紹兩個好用的工具:LayerDump 和 LayerScope。
LayerDump
嚴格來說這個並不算是工具的一種,只是在程式碼中已經寫好了一段程式可以快速的把我們目前的Layer tree把他印出來,使用的方式如下:
- 要先將 Firefox OS 編成 debug build,只需將 b2g 目錄下的 .userconfig 檔案裡加入一行
export B2G_DEBUG=1
- 在 gfx/layers/ipc/CompositorParent.cpp 內,找到
static bool gDumpCompositorTree = false
將 gDumpCompositorTree 改成 true - Dump 這個 function 的第二個參數可以在 log 中加上一個 prefix,建議加入會比較好 debug 喔!
- 改完的code差異如下
#ifdef MOZ_DUMP_PAINTING - static bool gDumpCompositorTree = false; + static bool gDumpCompositorTree = true; if (gDumpCompositorTree) { printf_stderr("Painting --- compositing layer tree:\n"); - mLayerManager->Dump(); + mLayerManager->Dump(nullptr, "DumpTest"); } #endif
- 請把 gecko 重編後就會出現囉
- 因為上面我們有加入 prefix,因此只要打入 adb logcat | grep “DumpTest” 就可以輕鬆的把 Layer 資訊抓出來囉!!
一起來看看有那些資訊吧!從下面的範例來看,至少有
- Layer 的型態
- Layer 間的階層關係
- Layer 的空間資訊,大小、位置等等
LayerManager (0x4802c980) ContainerLayerComposite (0x44a8b800) [shadow-visible=< (x=0, y=0, w=480, h=800); >] [visible=< (x=0, y=0, w=480, h=800); >] [opaqueContent] [metrics={ viewport=(x=0.000000, y=0.000000, w=320.000000, h=533.333313) viewportScroll=(x=0.000000, y=0.000000) displayport=(x=0.000000, y=0.000000, w=0.000000, h=0.000000) scrollId=0 }] ThebesLayerComposite (0x45651000) [shadow-clip=(x=0, y=0, w=0, h=0)] [clip=(x=0, y=0, w=0, h=0)] [not visible] ColorLayerComposite (0x45651600) [not visible] [opaqueContent] [color=rgba(0, 0, 0, 1)] ContainerLayerComposite (0x45622c00) [shadow-clip=(x=0, y=0, w=480, h=800)] [shadow-visible=< (x=0, y=0, w=480, h=800); >] [clip=(x=0, y=0, w=480, h=800)] [visible=< (x=0, y=0, w=480, h=800); >] [opaqueContent] ThebesLayerComposite (0x45651200) [shadow-visible=< (x=0, y=0, w=480, h=800); >] [visible=< (x=0, y=0, w=480, h=800); >] [opaqueContent] [valid=< (x=0, y=0, w=480, h=800); >] DeprecatedContentHostDoubleBuffered (0x456d8630) [buffer-rect=(x=0, y=0, w=480, h=800)] [buffer-rotation=(x=0, y=0)] GrallocDeprecatedTextureHostOGL (0x442e10c0) [size=(width=480, height=800)] [format=FORMAT_B8G8R8X8] [flags=TEXTURE_USE_NEAREST_FILTER] GrallocDeprecatedTextureHostOGL (0x442e1300) [size=(width=480, height=800)] [format=FORMAT_B8G8R8X8] [flags=TEXTURE_USE_NEAREST_FILTER] CanvasLayerComposite (0x46132200) [shadow-clip=(x=0, y=0, w=480, h=800)] [shadow-transform=[ 1 0; 0 1; 0 664.75; ]] [shadow-visible=< (x=0, y=0, w=480, h=120); >] [clip=(x=0, y=0, w=480, h=800)] [transform=[ 1 0; 0 1; 0 664.75; ]] [visible=< (x=0, y=0, w=480, h=120); >] ImageHost (0x461b0280) [picture-rect=(x=0, y=0, w=0, h=0)] MemoryTextureHost (0x47061830) [size=(width=0, height=0)] [format=FORMAT_B8G8R8A8] [flags=] ThebesLayerComposite (0x47042a00) [shadow-visible=< (x=382, y=702, w=46, h=8); (x=57, y=710, w=36, h=30); (x=382, y=710, w=46, h=30); (x=382, y=740, w=46, h=8); >] [visible=< (x=382, y=702, w=46, h=8); (x=57, y=710, w=36, h=30); (x=382, y=710, w=46, h=30); (x=382, y=740, w=46, h=8); >] [valid=< (x=382, y=702, w=46, h=8); (x=57, y=710, w=36, h=30); (x=382, y=710, w=46, h=30); (x=382, y=740, w=46, h=8); >] DeprecatedContentHostDoubleBuffered (0x483eeeb0) [buffer-rect=(x=57, y=702, w=371, h=46)] [buffer-rotation=(x=0, y=0)] GrallocDeprecatedTextureHostOGL (0x461d9940) [size=(width=371, height=46)] [format=FORMAT_B8G8R8A8] [flags=TEXTURE_USE_NEAREST_FILTER] GrallocDeprecatedTextureHostOGL (0x461d98c0) [size=(width=0, height=0)] [format=FORMAT_UNKNOWN] [flags=TEXTURE_USE_NEAREST_FILTER]
LayerScope
雖然 LayerDump 簡單好用,但是我們卻看不到每一個 Layer 的內容,這時候就可以使用另一個工具 – LayerScope,它的原理是透過 WebSocket 連接Device上的Socket 來接收資料,用途是顯示出每個畫在畫面上的 Layer 的內容,截圖如下:
使用的方式如下:
- 這個功能是最近才新加入的功能,所以請確定已經抓到最新版的 gecko 程式碼喔。另一個簡單可以分辨的方式是可以直接去檢查gfx/layers/LayerScope.cpp 這個檔案有沒有存在,有才表示可以使用 LayerScope。
- 在 b2g 目錄下,打 ./edit-prefs.sh 並且加入以下二個 prefs
user_pref("gfx.layerscope.enabled", true); user_pref("network.gonk.manage-offline-status", false);
- 請打以下指令
adb forward tcp:23456 tcp:23456
- 請下載 websockify,下載後請打以下指令
python websockify.py localhost:23457 localhost:23456
- 打開工具的網址,在其中的網址列打入
ws://localhost:23457
並按下 Connect 即可
結論
二個工具目前各有各的優點,LayerDump 資訊豐富且設定簡單,LayerScope 可得到 Layer 的內容可以容易的用肉眼看出一些潛在的問題,建議在做 Debugging 的時候二個搭配一起用,更能事半功倍!