這篇文章主要介紹Windows Phone中XAML的渲染處理過程,你能夠根據下文中所提到的內容來優化現有的XAML頁面,來提升頁面渲染的性能。緩存
XAML的渲染包括如下兩個階段:app
1. 光柵化(Rasterization) 光柵化是將圖形的表現形式從以基於矢量(vector-based)的圖形(好比:線、文字和矩形)轉換成基於像素(pixel-based)的圖形,從而能夠使圖像直接顯示在屏幕上的處理過程。這個轉換過程要先在內存中先爲位圖分配一個緩衝區,而後將以矢量圖形一個像素一個像素的轉換成位圖,並完成蒙板和梯度值的計算。這個光柵化的過程徹底是由CPU來處理的。ide
2. 組合(Composition) 在每個UIElement都被光柵化以後渲染器按照原始元素Z軸的順序講各個緩衝區上的位圖層疊到彼此之上。這個處理將各個位圖組合到了一塊兒,因此渲染器要負責處理元素的透明度和任何轉換(如:大小和位置),最終將位圖展現在設備的屏幕上。組合處理CPU或者GPU來完成。性能
下面這張圖經過將兩個UI Element展現在屏幕上,說明了光柵化和組合階段的過程,其中一個具備不透明蒙板。優化
渲染的過程是很是複雜的,由於屏幕上的圖形都是由UI Element的集合組合在一塊兒的,而不少UI Element又是由其餘UI Element組合的。在內部,XAML使用一種全部元素均可見和渲染的層次結構的視覺樹(visual tree)。好比要呈現一個普通的屏幕圖形, XAML經過光柵化及組合可視化樹中的元素,以減小必須分配的內存緩衝區的數量。這個處理過程將盡量的將元素覆蓋到現有的緩衝區中。開發人員能夠經過緩衝組合,以指定特定的UI元素如何被分組和由GPU組成。適當的緩存能夠顯着提升用戶界面的幀速率。動畫
若是UI Element是可動的,它將浪費一些處理器的時間,直到動畫結束才進行光柵化處理。此外,即便元素只移動了其中一小部分,也須要對整個UI Element進行從新組合。爲了優化渲染過程,XAML自動推遲了某些元素的組合過程,從而是元素的組合步驟能夠迅速的經過GPU來完成。使用GPU來加速渲染過程一般被稱爲硬件加速。若是您的設備沒有GPU或因其餘緣由不能硬體加速,XAML採用圖形設備接口(GDI )以較低的渲染速度來經過Z軸的順序一像素一像素繪製UI。this
在XAML中有兩個主要的線程:UI線程和Compositor線程。爲了建立響應及時的應用,瞭解這兩個線程是很是重要的。
spa
1. UI Thread線程
UI線程負責如下任務:
3d
爲了使您的應用程序儘量靈活響應,必須儘可能保持UI線程的輕量和空閒。
2. Compositor Thread
組合線程是一個超輕量級的線程,它爲GPU簡單的組合元素的紋理,它處理GPU上的被定義爲Storyboards類型或者基礎紋理的繪製類型的動畫。這些動畫類型包括:
注意,任何使用了不透明蒙板,非矩形剪切或者大小改變的動畫的對象大於2,048 x 2,048像素,它們將在UI線程上光柵化。
爲了說明前面的概念,請參閱以下圖所示的界面。屏幕上的地球圖像製做成動畫,繞着屏幕剩餘邊界。雖然這個屏幕顯示了一個很是簡單的用戶界面,它包括全部上面列出的關鍵構建模塊來講明渲染過程.
這個圖像是由下面這個XAML用戶控件構成的。
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="HelloWorld.MainPage" Width="300" Height="200"> <Grid x:Name="LayoutRoot"> <Grid x:Name="_Background" Background="{StaticResource BlueWashBrush}"> <Image x:Name="_LightHexes" Source="Assets/Hexes.png" Stretch="Fill"/> <Image x:Name="_DarkHexes" Source="Assets/BlackHexes.png" Stretch="Fill"> <Image.OpacityMask> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Offset="0"/> <GradientStop Color="#C0FFFFFF" Offset="0.6"/> </LinearGradientBrush> </Image.OpacityMask> </Image> </Grid> <Rectangle x:Name="_Border" Fill="#FF969696" Stroke="White" Margin="0,10,90,10" RadiusX="10" RadiusY="10" HorizontalAlignment="Center" Width="180" Opacity="0.5"/> <TextBlock x:Name="_Label" HorizontalAlignment="Center" Margin="0,0,90,15" VerticalAlignment="Bottom" FontFamily="Verdana" FontSize="21.333" Text="Hello World" TextWrapping="Wrap" FontWeight="Bold"/> <Button x:Name="_Button" HorizontalAlignment="Right" Margin="0,0,8,8" VerticalAlignment="Bottom" Width="75" Content="Close" FontFamily="Verdana" FontSize="16"/> <Image x:Name="_Globe" Height="138" HorizontalAlignment="Center" Margin="0,20,90,0" VerticalAlignment="Top" Width="138" Source="Assets/Globe138x138.png" Stretch="Fill" RenderTransformOrigin="0.5,0.5" CacheMode="BitmapCache"> <Image.RenderTransform> <TransformGroup> <ScaleTransform/> <SkewTransform/> <RotateTransform/> <TranslateTransform/> </TransformGroup> </Image.RenderTransform> </Image> </Grid> </UserControl>
下圖展現了上面代碼的樹形結構。
XAML的渲染過程執行如下步驟來呈現上圖所示的可視化樹:
注意,在渲染器執行的過程當中遵循如下規則:
在動畫過程當中,只有_Globe元素在畫面上移動,沒有其餘任何元素的變化。XAML沒有必要逐幀來執行全部光柵化和組合的步驟。最優行爲是保存已經完成的每幀動畫步驟的結果,經過保存的步驟來組合_Globe。 在前面的代碼塊22行提到CacheMode屬性來明確地告訴渲染器單獨對待_Globe元素,以產生緩存的效果。
在XAML中緩存是自動的,不必再設置CacheMode屬性。注意,分離緩存的對象和元素分組是緩存和提升動畫速度成功的關鍵。