BREW での高速アルファブレンド

id:melpon:20060419 で書いた、

d = (tbl[ alpha | ((s >>  6) & 0x03e0) | ((d >> 11)         ) ] << 11) | // R
    (tbl[ alpha | ((s >>  1) & 0x03e0) | ((d >>  6) & 0x001f) ] <<  6) | // G
    (tbl[ alpha | ((s <<  5) & 0x03e0) | ((d      ) & 0x001f) ] <<  0);  // B

この線形補間テーブルを用いたアルファブレンドより高速にブレンドする方法を思いつきました。

uint32 AlphaBlend( uint32 src , uint32 dst , uint32 alpha ){
    switch( alpha ){
    case 0:
        return dst;
    case 1:
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 2:
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 3:
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 4:
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 5:
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 6:
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 7:
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 8:
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 9:
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 10:
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 11:
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 12:
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 13:
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 14:
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 15:
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 16:
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 17:
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 18:
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 19:
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 20:
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 21:
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 22:
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 23:
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 24:
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 25:
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 26:
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 27:
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 28:
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 29:
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        src = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 30:
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 31:
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        dst = (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
        return (src & dst) + (((src ^ dst) & 0xf7de) >> 1);
    case 32:
        return src;
    }
    return 0;
}

software packed 演算で (src + dst) / 2 を繰り返しています。
これだけだと速いかどうかは微妙ですけど、まだまだ最適化できそう。