rgb24轉rgb555/rgb565優化

 真彩色轉成高彩色的快速算法  
   
  --------------------------------------------------------------------------------  
   
  --------------------------------------------------------------------------------  
   
  這裏我不談減低色彩深度時,   採用抖動減少誤差的方法.   因爲本文將着力於找到儘可能快的算法   (雖然最快的方法一定存在,   但我們只能去接近它,   而無法達到,   因爲優化是無至盡的,   而且隨着   CPU   而變化)實時轉化   24bit   (或32bit)   的真彩色位圖到16bit(15bit)的高彩色.    
   
  爲什麼要實時轉換顏色深度?    
   
  通常,   2D   遊戲中的位圖,   無論在外存中按什麼顏色深度存放,   加栽後都被轉換成了需要的顏色深度.   我們不太注意顏色深度轉換說需要的時間.    
   
  但是,   現在不同了.   雲風未來的計劃中,   最重要的一項是製作一個超級   2D   引擎.   將支持   Voxel   物體和實時光線處理這樣的特性,   而且在光線處理中,   32   級的光線亮度級別也遠遠不夠,   所以,   未來的   2D   遊戲的發展趨勢應該是採用真彩色,   至少是在內部運算時使用.   在某些場合下,   我們可能需要做   15/16bit   高彩色的輸出,   所以有必要找到更快的方法實時處理.    
   
  下面,   我們對此做一些探討,   雖然顯卡可以支持   15   或   16   bit   色中的一種,   但這裏全部用   16bit   色舉例:    
   
  先來看看   C   版本:    
   
  red=(truecolor>>8)&0xf800;  
  green=(truecolor>>5)&0x7e0;  
  blue=(truecolor>>3)&0x1f;  
  hicolor=red|green|blue;  
   
  這樣當然是相當慢的,   所以我們還是要藉助彙編.   而彙編能極大的優化它:    
  lodsd ;RRRRRRRR   GGGGGGGG   BBBBBBBB  
  shr   eax,3 ;000RRRRR   RRRGGGGG   GGGBBBBB  
  shl   al,2 ;000RRRRR   RRRGGGGG   GBBBBBxx  
  shl   ax,3 ;000RRRRR   GGGGGGBBB   BBxxxxx  
  dec   esi  
  shr   eax,5 ;00000000   RRRRRGGG   GGGBBBBB  
  stosw  
   
  是不是精簡了很多?   但不幸的是,   雖然看起來很簡潔,   但由於大量使用部分寄存器,   對流水線的衝擊很大.   代碼幾乎把流水線的效率減到了最低.   優化方案很多,   我們可以在一次循環裏處理兩個點,   分別使用   eax   和   ebx,   然後交錯那些代碼;   又或者將上面代碼的後半部分改爲查表,   相信都能提高速度.   但是下面我還想提出另一種方案,   採用   MMX   指令級:    
  mm7=F800F800F800F800  
  mm6=FC00FC00FC00FC00  
  ------------------------------  
  punpcklbw   mm0,[red+edx]  
  ;mm0=RRRRRRRR   00000000   RRRRRRRR   00000000   RRRRRRRR   00000000   RRRRRRRR   00000000    
  punpcklbw   mm1,[green+edx]  
  ;mm1=GGGGGGGG   00000000   GGGGGGGG   00000000   GGGGGGGG   00000000   GGGGGGGG   00000000    
  punpcklbw   mm2,[blue+edx]  
  ;mm2=BBBBBBBB   00000000   BBBBBBBB   00000000   BBBBBBBB   00000000   BBBBBBBB   00000000    
  pand   mm0,mm7  
  ;mm0=RRRRR000   00000000   RRRRR000   00000000   RRRRR000   00000000   RRRRR000   00000000    
  pand   mm1,mm6  
  ;mm1=GGGGGG00   00000000   GGGGGG00   00000000   GGGGGG00   00000000   GGGGGG00   00000000    
  psrlw   mm2,11  
  ;mm2=00000000   000BBBBB   00000000   000BBBBB   00000000   000BBBBB   00000000   000BBBBB    
  psrlw   mm1,5  
  ;mm1=00000GGG   GGG00000   00000GGG   GGG00000   00000GGG   GGG00000   00000GGG   GGG00000    
  por   mm0,mm2  
  por   mm0,mm1  
  ;mm0=RRRRRGGG   GGGBBBBB   RRRRRGGG   GGGBBBBB   RRRRRGGG   GGGBBBBB   RRRRRGGG   GGGBBBBB  
  movq   [dis+edx*2],mm0  
  add   edx,4  
   
  我們對   MMX   的運用是針對它的並行運算,   直接從   RGB888   格式利用並行處理變成   RGB565   似乎不可能,   但是,   如果我們將   RGB   三個色素分開存放,   就將其變爲了可能.   可以同時讀入   4   個色素,   並行處理,   然後合併,   這樣便在一個循環內處理了   4   個點.   考慮到   CACHE   的效率,   最好不要將   RGB   三塊內存分的太開.   我的建議是,   位圖的每一行分成三個部分,   即爲   Red   段,   Green   段   和   Blue   段.    
  上面的方法都是可以繼續優化的,   本文旨在啓發朋友們的靈感,   找出更好的方法.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章