・MMXで半透明(2) : アセンブラ 編 (99/5/18)

前回 C でα合成を試したら平均 8 回/秒 しか計算出来ませんでした。 ならばアセンブラで高速化しよう、という訳で今回は アセンブラを使ってα合成をしてみます。

さてアセンブラで合成の部分を素直に書けば下の様なソースになります。前回の ソースの VOID AlphaBlending() 関数を置き換えて下さい。WinMain() やプロシージャ等の関数は同じ物を使います(したがって今回は それらのソースは載せません)。 やっていること自体は C 版と全く同じなのですがメモリへのアクセスが かなり減りますので C よりは速くなることが予想できます (もっとも最近はキャッシュがあるのであまり変わらないような気もしますが)。

// α合成 アセンブラ版  
//
// コピー先 = コピー元1 * α + コピー元1 * (1-α)
//
VOID AlphaBlending(LPBYTE lpDest, // コピー先
                   LPBYTE lpSrc1,    // コピー元1
		   LPBYTE lpSrc2,    // コピー元2
		   DWORD dwLength,   // コピーする長さ
		   WORD wAlpha){     // α値

     DWORD dwAlpha = (DWORD)wAlpha;
     DWORD dwAlpha2 = (256 - dwAlpha);

_asm{

     mov eax,dwLength  // eax = カウンタ
     mov ebx,lpDest  // ebx = コピー先アドレス
     mov edi,lpSrc1  // ecx = コピー元1 アドレス
     mov esi,lpSrc2  // edx = コピー元2 アドレス
     xor ecx,ecx  // ecx 初期化
     xor edx,edx  // edx 初期化

LOOP1:
        // データ読み込み
	mov cl,byte ptr [edi]
	mov dl,byte ptr [esi]

	// 掛け算
	imul ecx,dwAlpha
	imul edx,dwAlpha2

	// 足して 256 で割って転送
	add ecx,edx
	shr ecx,8
	shr edx,8
	mov byte ptr [ebx],cl

	inc ebx
	inc edi
	inc esi
	dec eax
	jne LOOP1
    }
}
さて結果ですが、MMX ペンティアム 150 で 460x320 のビットマップ 2 枚を混合させる計算速度は平均 11 回/秒でした。ありゃ、まだ 高橋名人の連打よりも遅い(^^; もちろん上のソースは全く最適化 していないので最適化を行えばもう少し速くなると思いますが、 それでも高橋名人は越えられないでしょう。

結局、アセンブラを使っても計算でリアルタイムにα合成をさせるのは 無理そうです。やはり MMX を使わない場合は従来通り(メモリは食いますが )変換値を入れたテーブルをあらかじめ用意しておくしかないようです。

(第3回 MMX編(その 1)に続く)