/*
	Twilight Prophecy 3D/Multimedia SDK
	A multi-platform development system for virtual reality and multimedia.

	Copyright (C) 1997-2001 by Twilight 3D Finland Oy Ltd.

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

	Please read the file LICENSE.TXT for additional details.


	source:
		alpha blending

	revision history:
		Feb/02/1999 - Jukka Liimatta - initial revision
		Feb/05/2001 - Jukka Liimatta - renaissance build

	todo:
		- optimize generic c++ innerloops
*/
#include <prcore/prcore.hpp>
using namespace prcore;



//////////////////////////////////////////////////////
// modulation tables                               //
////////////////////////////////////////////////////

static int32 lut0_int[] =
{
	0x00000000, 0x01010101, 0x02020202, 0x03030303, 0x04040404, 0x05050505, 0x06060606, 0x07070707,
	0x08080808, 0x09090909, 0x0a0a0a0a, 0x0b0b0b0b, 0x0c0c0c0c, 0x0d0d0d0d, 0x0e0e0e0e, 0x0f0f0f0f,
	0x10101010, 0x11111111, 0x12121212, 0x13131313, 0x14141414, 0x15151515, 0x16161616, 0x17171717,
	0x18181818, 0x19191919, 0x1a1a1a1a, 0x1b1b1b1b, 0x1c1c1c1c, 0x1d1d1d1d, 0x1e1e1e1e, 0x1f1f1f1f,
	0x20202020, 0x21212121, 0x22222222, 0x23232323, 0x24242424, 0x25252525, 0x26262626, 0x27272727,
	0x28282828, 0x29292929, 0x2a2a2a2a, 0x2b2b2b2b, 0x2c2c2c2c, 0x2d2d2d2d, 0x2e2e2e2e, 0x2f2f2f2f,
	0x30303030, 0x31313131, 0x32323232, 0x33333333, 0x34343434, 0x35353535, 0x36363636, 0x37373737,
	0x38383838, 0x39393939, 0x3a3a3a3a, 0x3b3b3b3b, 0x3c3c3c3c, 0x3d3d3d3d, 0x3e3e3e3e, 0x3f3f3f3f,
	0x40404040, 0x41414141, 0x42424242, 0x43434343, 0x44444444, 0x45454545, 0x46464646, 0x47474747,
	0x48484848, 0x49494949, 0x4a4a4a4a, 0x4b4b4b4b, 0x4c4c4c4c, 0x4d4d4d4d, 0x4e4e4e4e, 0x4f4f4f4f,
	0x50505050, 0x51515151, 0x52525252, 0x53535353, 0x54545454, 0x55555555, 0x56565656, 0x57575757,
	0x58585858, 0x59595959, 0x5a5a5a5a, 0x5b5b5b5b, 0x5c5c5c5c, 0x5d5d5d5d, 0x5e5e5e5e, 0x5f5f5f5f,
	0x60606060, 0x61616161, 0x62626262, 0x63636363, 0x64646464, 0x65656565, 0x66666666, 0x67676767,
	0x68686868, 0x69696969, 0x6a6a6a6a, 0x6b6b6b6b, 0x6c6c6c6c, 0x6d6d6d6d, 0x6e6e6e6e, 0x6f6f6f6f,
	0x70707070, 0x71717171, 0x72727272, 0x73737373, 0x74747474, 0x75757575, 0x76767676, 0x77777777,
	0x78787878, 0x79797979, 0x7a7a7a7a, 0x7b7b7b7b, 0x7c7c7c7c, 0x7d7d7d7d, 0x7e7e7e7e, 0x7f7f7f7f,
	0x80808080, 0x81818181, 0x82828282, 0x83838383, 0x84848484, 0x85858585, 0x86868686, 0x87878787,
	0x88888888, 0x89898989, 0x8a8a8a8a, 0x8b8b8b8b, 0x8c8c8c8c, 0x8d8d8d8d, 0x8e8e8e8e, 0x8f8f8f8f,
	0x90909090, 0x91919191, 0x92929292, 0x93939393, 0x94949494, 0x95959595, 0x96969696, 0x97979797,
	0x98989898, 0x99999999, 0x9a9a9a9a, 0x9b9b9b9b, 0x9c9c9c9c, 0x9d9d9d9d, 0x9e9e9e9e, 0x9f9f9f9f,
	0xa0a0a0a0, 0xa1a1a1a1, 0xa2a2a2a2, 0xa3a3a3a3, 0xa4a4a4a4, 0xa5a5a5a5, 0xa6a6a6a6, 0xa7a7a7a7,
	0xa8a8a8a8, 0xa9a9a9a9, 0xaaaaaaaa, 0xabababab, 0xacacacac, 0xadadadad, 0xaeaeaeae, 0xafafafaf,
	0xb0b0b0b0, 0xb1b1b1b1, 0xb2b2b2b2, 0xb3b3b3b3, 0xb4b4b4b4, 0xb5b5b5b5, 0xb6b6b6b6, 0xb7b7b7b7,
	0xb8b8b8b8, 0xb9b9b9b9, 0xbabababa, 0xbbbbbbbb, 0xbcbcbcbc, 0xbdbdbdbd, 0xbebebebe, 0xbfbfbfbf,
	0xc0c0c0c0, 0xc1c1c1c1, 0xc2c2c2c2, 0xc3c3c3c3, 0xc4c4c4c4, 0xc5c5c5c5, 0xc6c6c6c6, 0xc7c7c7c7,
	0xc8c8c8c8, 0xc9c9c9c9, 0xcacacaca, 0xcbcbcbcb, 0xcccccccc, 0xcdcdcdcd, 0xcececece, 0xcfcfcfcf,
	0xd0d0d0d0, 0xd1d1d1d1, 0xd2d2d2d2, 0xd3d3d3d3, 0xd4d4d4d4, 0xd5d5d5d5, 0xd6d6d6d6, 0xd7d7d7d7,
	0xd8d8d8d8, 0xd9d9d9d9, 0xdadadada, 0xdbdbdbdb, 0xdcdcdcdc, 0xdddddddd, 0xdededede, 0xdfdfdfdf,
	0xe0e0e0e0, 0xe1e1e1e1, 0xe2e2e2e2, 0xe3e3e3e3, 0xe4e4e4e4, 0xe5e5e5e5, 0xe6e6e6e6, 0xe7e7e7e7,
	0xe8e8e8e8, 0xe9e9e9e9, 0xeaeaeaea, 0xebebebeb, 0xecececec, 0xedededed, 0xeeeeeeee, 0xefefefef,
	0xf0f0f0f0, 0xf1f1f1f1, 0xf2f2f2f2, 0xf3f3f3f3, 0xf4f4f4f4, 0xf5f5f5f5, 0xf6f6f6f6, 0xf7f7f7f7,
	0xf8f8f8f8, 0xf9f9f9f9, 0xfafafafa, 0xfbfbfbfb, 0xfcfcfcfc, 0xfdfdfdfd, 0xfefefefe, 0xffffffff,
};
static int32 lut1_int[] =
{
	0x00000000, 0x01010101, 0x02020202, 0x03030303, 0x04040404, 0x05050505, 0x06060606, 0x07070707,
	0x08080808, 0x09090909, 0x0a0a0a0a, 0x0b0b0b0b, 0x0c0c0c0c, 0x0d0d0d0d, 0x0e0e0e0e, 0x0f0f0f0f,
	0x10101010, 0x11111111, 0x12121212, 0x13131313, 0x14141414, 0x15151515, 0x16161616, 0x17171717,
	0x18181818, 0x19191919, 0x1a1a1a1a, 0x1b1b1b1b, 0x1c1c1c1c, 0x1d1d1d1d, 0x1e1e1e1e, 0x1f1f1f1f,
	0x20202020, 0x21212121, 0x22222222, 0x23232323, 0x24242424, 0x25252525, 0x26262626, 0x27272727,
	0x28282828, 0x29292929, 0x2a2a2a2a, 0x2b2b2b2b, 0x2c2c2c2c, 0x2d2d2d2d, 0x2e2e2e2e, 0x2f2f2f2f,
	0x30303030, 0x31313131, 0x32323232, 0x33333333, 0x34343434, 0x35353535, 0x36363636, 0x37373737,
	0x38383838, 0x39393939, 0x3a3a3a3a, 0x3b3b3b3b, 0x3c3c3c3c, 0x3d3d3d3d, 0x3e3e3e3e, 0x3f3f3f3f,
	0x40404040, 0x41414141, 0x42424242, 0x43434343, 0x44444444, 0x45454545, 0x46464646, 0x47474747,
	0x48484848, 0x49494949, 0x4a4a4a4a, 0x4b4b4b4b, 0x4c4c4c4c, 0x4d4d4d4d, 0x4e4e4e4e, 0x4f4f4f4f,
	0x50505050, 0x51515151, 0x52525252, 0x53535353, 0x54545454, 0x55555555, 0x56565656, 0x57575757,
	0x58585858, 0x59595959, 0x5a5a5a5a, 0x5b5b5b5b, 0x5c5c5c5c, 0x5d5d5d5d, 0x5e5e5e5e, 0x5f5f5f5f,
	0x60606060, 0x61616161, 0x62626262, 0x63636363, 0x64646464, 0x65656565, 0x66666666, 0x67676767,
	0x68686868, 0x69696969, 0x6a6a6a6a, 0x6b6b6b6b, 0x6c6c6c6c, 0x6d6d6d6d, 0x6e6e6e6e, 0x6f6f6f6f,
	0x70707070, 0x71717171, 0x72727272, 0x73737373, 0x74747474, 0x75757575, 0x76767676, 0x77777777,
	0x78787878, 0x79797979, 0x7a7a7a7a, 0x7b7b7b7b, 0x7c7c7c7c, 0x7d7d7d7d, 0x7e7e7e7e, 0x7f7f7f7f,
	0x80808080, 0x81818181, 0x82828282, 0x83838383, 0x84848484, 0x85858585, 0x86868686, 0x87878787,
	0x88888888, 0x89898989, 0x8a8a8a8a, 0x8b8b8b8b, 0x8c8c8c8c, 0x8d8d8d8d, 0x8e8e8e8e, 0x8f8f8f8f,
	0x90909090, 0x91919191, 0x92929292, 0x93939393, 0x94949494, 0x95959595, 0x96969696, 0x97979797,
	0x98989898, 0x99999999, 0x9a9a9a9a, 0x9b9b9b9b, 0x9c9c9c9c, 0x9d9d9d9d, 0x9e9e9e9e, 0x9f9f9f9f,
	0xa0a0a0a0, 0xa1a1a1a1, 0xa2a2a2a2, 0xa3a3a3a3, 0xa4a4a4a4, 0xa5a5a5a5, 0xa6a6a6a6, 0xa7a7a7a7,
	0xa8a8a8a8, 0xa9a9a9a9, 0xaaaaaaaa, 0xabababab, 0xacacacac, 0xadadadad, 0xaeaeaeae, 0xafafafaf,
	0xb0b0b0b0, 0xb1b1b1b1, 0xb2b2b2b2, 0xb3b3b3b3, 0xb4b4b4b4, 0xb5b5b5b5, 0xb6b6b6b6, 0xb7b7b7b7,
	0xb8b8b8b8, 0xb9b9b9b9, 0xbabababa, 0xbbbbbbbb, 0xbcbcbcbc, 0xbdbdbdbd, 0xbebebebe, 0xbfbfbfbf,
	0xc0c0c0c0, 0xc1c1c1c1, 0xc2c2c2c2, 0xc3c3c3c3, 0xc4c4c4c4, 0xc5c5c5c5, 0xc6c6c6c6, 0xc7c7c7c7,
	0xc8c8c8c8, 0xc9c9c9c9, 0xcacacaca, 0xcbcbcbcb, 0xcccccccc, 0xcdcdcdcd, 0xcececece, 0xcfcfcfcf,
	0xd0d0d0d0, 0xd1d1d1d1, 0xd2d2d2d2, 0xd3d3d3d3, 0xd4d4d4d4, 0xd5d5d5d5, 0xd6d6d6d6, 0xd7d7d7d7,
	0xd8d8d8d8, 0xd9d9d9d9, 0xdadadada, 0xdbdbdbdb, 0xdcdcdcdc, 0xdddddddd, 0xdededede, 0xdfdfdfdf,
	0xe0e0e0e0, 0xe1e1e1e1, 0xe2e2e2e2, 0xe3e3e3e3, 0xe4e4e4e4, 0xe5e5e5e5, 0xe6e6e6e6, 0xe7e7e7e7,
	0xe8e8e8e8, 0xe9e9e9e9, 0xeaeaeaea, 0xebebebeb, 0xecececec, 0xedededed, 0xeeeeeeee, 0xefefefef,
	0xf0f0f0f0, 0xf1f1f1f1, 0xf2f2f2f2, 0xf3f3f3f3, 0xf4f4f4f4, 0xf5f5f5f5, 0xf6f6f6f6, 0xf7f7f7f7,
	0xf8f8f8f8, 0xf9f9f9f9, 0xfafafafa, 0xfbfbfbfb, 0xfcfcfcfc, 0xfdfdfdfd, 0xfefefefe, 0xffffffff,
};


//////////////////////////////////////////////////////
// macros                                          //
////////////////////////////////////////////////////

static inline Color32 InvColor(const Color32& p)
{
	return -p;
}

static inline Color32 Alpha0(const Color32& p)
{
	return lut0_int[p.a];
}

static inline Color32 InvAlpha0(const Color32& p)
{
	return lut0_int[p.a^0xff];
}

static inline Color32 Alpha1(const Color32& p)
{
	return lut1_int[p.a];
}

static inline Color32 InvAlpha1(const Color32& p)
{
	return lut1_int[p.a^0xff];
}


//////////////////////////////////////////////////////
// innerloops                                      //
////////////////////////////////////////////////////

static void Blend_Zero_Zero(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	memset(dest,0,sizeof(Color32)*count);
}

static void Blend_Zero_One(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	memcpy(dest,sr1,sizeof(Color32)*count);
}

static void Blend_Zero_SrcColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		*dest++ = *sr1++ * *sr0++;
	} while ( --count );
}

static void Blend_Zero_SrcInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		*dest++ = *sr1++ * InvColor(*sr0++);
	} while ( --count );
}

static void Blend_Zero_SrcAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		*dest++ = *sr1++ * Alpha0(*sr0++);
	} while ( --count );
}

static void Blend_Zero_SrcInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		*dest++ = *sr1++ * InvAlpha0(*sr0++);
	} while ( --count );
}

static void Blend_Zero_DestColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = c1 * c1;
	} while ( --count );
}

static void Blend_Zero_DestInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = c1 * InvColor(c1);
	} while ( --count );
}

static void Blend_Zero_DestAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = c1 * Alpha1(c1);
	} while ( --count );
}

static void Blend_Zero_DestInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = c1 * InvAlpha1(c1);
	} while ( --count );
}

static void Blend_One_Zero(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	memcpy(dest,sr0,sizeof(Color32)*count);
}

static void Blend_One_One(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		*dest++ = *sr0++ + *sr1++;
	} while ( --count );
}

static void Blend_One_SrcColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = c0 + (*sr1++ * c0);
	} while ( --count );
}

static void Blend_One_SrcInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = c0 + (*sr1++ * InvColor(c0));
	} while ( --count );
}

static void Blend_One_SrcAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = c0 + (*sr1++ * Alpha0(c0));
	} while ( --count );
}

static void Blend_One_SrcInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = c0 + (*sr1++ * InvAlpha0(c0));
	} while ( --count );
}

static void Blend_One_DestColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = *sr0++ + (c1 * c1);
	} while ( --count );
}

static void Blend_One_DestInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = *sr0++ + (c1 * InvColor(c1));
	} while ( --count );
}

static void Blend_One_DestAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = *sr0++ + (c1 * Alpha1(c1));
	} while ( --count );
}

static void Blend_One_DestInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = *sr0++ + (c1 * InvAlpha1(c1));
	} while ( --count );
}

static void Blend_SrcColor_Zero(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = c0 * c0;
	} while ( --count );
}

static void Blend_SrcColor_One(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = (c0 * c0) + *sr1++;
	} while ( --count );
}

static void Blend_SrcColor_SrcColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = (c0 * c0) + (*sr1++ * c0);
	} while ( --count );
}

static void Blend_SrcColor_SrcInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = (c0 * c0) + (*sr1++ * InvColor(c0));
	} while ( --count );
}

static void Blend_SrcColor_SrcAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = (c0 * c0) + (*sr1++ * Alpha0(c0));
	} while ( --count );
}

static void Blend_SrcColor_SrcInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = (c0 * c0) + (*sr1++ * InvAlpha0(c0));
	} while ( --count );
}

static void Blend_SrcColor_DestColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * c0) + (c1 * c1);
	} while ( --count );
}

static void Blend_SrcColor_DestInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * c0) + (c1 * InvColor(c1));
	} while ( --count );
}

static void Blend_SrcColor_DestAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * c0) + (c1 * Alpha1(c1));
	} while ( --count );
}

static void Blend_SrcColor_DestInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * c0) + (c1 * InvAlpha1(c1));
	} while ( --count );
}

static void Blend_SrcInvColor_Zero(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = c0 * InvColor(c0);
	} while ( --count );
}

static void Blend_SrcInvColor_One(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = (c0 * InvColor(c0)) + *sr1++;
	} while ( --count );
}

static void Blend_SrcInvColor_SrcColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = (c0 * InvColor(c0)) + (*sr1++ * c0);
	} while ( --count );
}

static void Blend_SrcInvColor_SrcInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = (c0 * InvColor(c0)) + (*sr1++ * InvColor(c0));
	} while ( --count );
}

static void Blend_SrcInvColor_SrcAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = (c0 * InvColor(c0)) + (*sr1++ * Alpha0(c0));
	} while ( --count );
}

static void Blend_SrcInvColor_SrcInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = (c0 * InvColor(c0)) + (*sr1++ * InvAlpha0(c0));
	} while ( --count );
}

static void Blend_SrcInvColor_DestColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * InvColor(c0)) + (c1 * c1);
	} while ( --count );
}

static void Blend_SrcInvColor_DestInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * InvColor(c0)) + (c1 * InvColor(c1));
	} while ( --count );
}

static void Blend_SrcInvColor_DestAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * InvColor(c0)) + (c1 * Alpha1(c1));
	} while ( --count );
}

static void Blend_SrcInvColor_DestInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * InvColor(c0)) + (c1 * InvAlpha1(c1));
	} while ( --count );
}

static void Blend_SrcAlpha_Zero(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = c0 * Alpha0(c0);
	} while ( --count );
}

static void Blend_SrcAlpha_One(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = (c0 * Alpha0(c0)) + *sr1++;
	} while ( --count );
}

static void Blend_SrcAlpha_SrcColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = (c0 * Alpha0(c0)) + (*sr1++ * c0);
	} while ( --count );
}

static void Blend_SrcAlpha_SrcInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = (c0 * Alpha0(c0)) + (*sr1++ * InvColor(c0));
	} while ( --count );
}

static void Blend_SrcAlpha_SrcAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& a0 = Alpha0(c0);
		*dest++ = (c0 * a0) + (*sr1++ * a0);
	} while ( --count );
}

static void Blend_SrcAlpha_SrcInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& a0 = Alpha0(c0);
		*dest++ = (c0 * a0) + (*sr1++ * InvColor(a0));
	} while ( --count );
}

static void Blend_SrcAlpha_DestColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * Alpha0(c0)) + (c1 * c1);
	} while ( --count );
}

static void Blend_SrcAlpha_DestInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * Alpha0(c0)) + (c1 * InvColor(c1));
	} while ( --count );
}

static void Blend_SrcAlpha_DestAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * Alpha0(c0)) + (c1 * Alpha1(c1));
	} while ( --count );
}

static void Blend_SrcAlpha_DestInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * Alpha0(c0)) + (c1 * InvAlpha1(c1));
	} while ( --count );
}

static void Blend_SrcInvAlpha_Zero(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = c0 * InvAlpha0(c0);
	} while ( --count );
}

static void Blend_SrcInvAlpha_One(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = (c0 * InvAlpha0(c0)) + *sr1++;
	} while ( --count );
}

static void Blend_SrcInvAlpha_SrcColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = (c0 * InvAlpha0(c0)) + (*sr1++ * c0);
	} while ( --count );
}

static void Blend_SrcInvAlpha_SrcInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		*dest++ = (c0 * InvAlpha0(c0)) + (*sr1++ * InvColor(c0));
	} while ( --count );
}

static void Blend_SrcInvAlpha_SrcAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& a0 = Alpha0(c0);
		*dest++ = (c0 * InvColor(a0)) + (*sr1++ * a0);
	} while ( --count );
}

static void Blend_SrcInvAlpha_SrcInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& ia0 = InvAlpha0(c0);
		*dest++ = (c0 * ia0) + (*sr1++ * ia0);
	} while ( --count );
}

static void Blend_SrcInvAlpha_DestColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * InvAlpha0(c0)) + (c1 * c1);
	} while ( --count );
}

static void Blend_SrcInvAlpha_DestInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * InvAlpha0(c0)) + (c1 * InvColor(c1));
	} while ( --count );
}

static void Blend_SrcInvAlpha_DestAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * InvAlpha0(c0)) + (c1 * Alpha1(c1));
	} while ( --count );
}

static void Blend_SrcInvAlpha_DestInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * InvAlpha0(c0)) + (c1 * InvAlpha1(c1));
	} while ( --count );
}

static void Blend_DestColor_Zero(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		*dest++ = *sr0++ * *sr1++;
	} while ( --count );
}

static void Blend_DestColor_One(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = (*sr0++ * c1) + c1;
	} while ( --count );
}

static void Blend_DestColor_SrcColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * c1) + (c1 * c0);
	} while ( --count );
}

static void Blend_DestColor_SrcInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * c1) + (c1 * InvColor(c0));
	} while ( --count );
}

static void Blend_DestColor_SrcAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * c1) + (c1 * Alpha0(c0));
	} while ( --count );
}

static void Blend_DestColor_SrcInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * c1) + (c1 * InvAlpha0(c0));
	} while ( --count );
}

static void Blend_DestColor_DestColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = (*sr0++ * c1) + (c1 * c1);
	} while ( --count );
}

static void Blend_DestColor_DestInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = (*sr0++ * c1) + (c1 * InvColor(c1));
	} while ( --count );
}

static void Blend_DestColor_DestAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = (*sr0++ * c1) + (c1 * Alpha1(c1));
	} while ( --count );
}

static void Blend_DestColor_DestInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = (*sr0++ * c1) + (c1 * InvAlpha1(c1));
	} while ( --count );
}

static void Blend_DestInvColor_Zero(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		*dest++ = *sr0++ * InvColor(*sr1++);
	} while ( --count );
}

static void Blend_DestInvColor_One(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = (*sr0++ * InvColor(c1)) + c1;
	} while ( --count );
}

static void Blend_DestInvColor_SrcColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * InvColor(c1)) + (c1 * c0);
	} while ( --count );
}

static void Blend_DestInvColor_SrcInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * InvColor(c1)) + (c1 * InvColor(c0));
	} while ( --count );
}

static void Blend_DestInvColor_SrcAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * InvColor(c1)) + (c1 * Alpha0(c0));
	} while ( --count );
}

static void Blend_DestInvColor_SrcInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * InvColor(c1)) + (c1 * InvAlpha0(c0));
	} while ( --count );
}

static void Blend_DestInvColor_DestColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = (*sr0++ * InvColor(c1)) + (c1 * c1);
	} while ( --count );
}

static void Blend_DestInvColor_DestInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		const Color32& i1 = InvColor(c1);
		*dest++ = (*sr0++ * i1) + (c1 * i1);
	} while ( --count );
}

static void Blend_DestInvColor_DestAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = (*sr0++ * InvColor(c1)) + (c1 * Alpha1(c1));
	} while ( --count );
}

static void Blend_DestInvColor_DestInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = (*sr0++ * InvColor(c1)) + (c1 * InvAlpha1(c1));
	} while ( --count );
}

static void Blend_DestAlpha_Zero(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		*dest++ = *sr0++ * Alpha1(*sr1++);
	} while ( --count );
}

static void Blend_DestAlpha_One(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = (*sr0++ * Alpha1(c1)) + c1;
	} while ( --count );
}

static void Blend_DestAlpha_SrcColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * Alpha1(c1)) + (c1 * c0);
	} while ( --count );
}

static void Blend_DestAlpha_SrcInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * Alpha1(c1)) + (c1 * InvColor(c0));
	} while ( --count );
}

static void Blend_DestAlpha_SrcAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * Alpha1(c1)) + (c1 * Alpha0(c0));
	} while ( --count );
}

static void Blend_DestAlpha_SrcInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * Alpha1(c1)) + (c1 * InvAlpha0(c0));
	} while ( --count );
}

static void Blend_DestAlpha_DestColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = (*sr0++ * Alpha1(c1)) + (c1 * c1);
	} while ( --count );
}

static void Blend_DestAlpha_DestInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = (*sr0++ * Alpha1(c1)) + (c1 * InvColor(c1));
	} while ( --count );
}

static void Blend_DestAlpha_DestAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		const Color32& a1 = Alpha1(c1);
		*dest++ = (*sr0++ * a1) + (c1 * a1);
	} while ( --count );
}

static void Blend_DestAlpha_DestInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		const Color32& a1 = Alpha1(c1);
		*dest++ = (*sr0++ * a1) + (c1 * InvColor(a1));
	} while ( --count );
}

static void Blend_DestInvAlpha_Zero(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		*dest++ = *sr0++ * InvAlpha1(*sr1++);
	} while ( --count );
}

static void Blend_DestInvAlpha_One(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = (*sr0++ * InvAlpha1(c1)) + c1;
	} while ( --count );
}

static void Blend_DestInvAlpha_SrcColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * InvAlpha1(c1)) + (c1 * c0);
	} while ( --count );
}

static void Blend_DestInvAlpha_SrcInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * InvAlpha1(c1)) + (c1 * InvColor(c0));
	} while ( --count );
}

static void Blend_DestInvAlpha_SrcAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * InvAlpha1(c1)) + (c1 * Alpha0(c0));
	} while ( --count );
}

static void Blend_DestInvAlpha_SrcInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c0 = *sr0++;
		const Color32& c1 = *sr1++;
		*dest++ = (c0 * InvAlpha1(c1)) + (c1 * InvAlpha0(c0));
	} while ( --count );
}

static void Blend_DestInvAlpha_DestColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = (*sr0++ * InvAlpha1(c1)) + (c1 * c1);
	} while ( --count );
}

static void Blend_DestInvAlpha_DestInvColor(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		*dest++ = (*sr0++ * InvAlpha1(c1)) + (c1 * InvColor(c1));
	} while ( --count );
}

static void Blend_DestInvAlpha_DestAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		const Color32& a1 = Alpha1(c1);
		*dest++ = (*sr0++ * InvColor(a1)) + (c1 * a1);
	} while ( --count );
}

static void Blend_DestInvAlpha_DestInvAlpha(Color32* dest, const Color32* sr0, const Color32* sr1, int count)
{
	do
	{
		const Color32& c1 = *sr1++;
		const Color32& ia1 = InvAlpha1(c1);
		*dest++ = (*sr0++ * ia1) + (c1 * ia1);
	} while ( --count );
}


//////////////////////////////////////////////////////
// C++ implementation table                        //
////////////////////////////////////////////////////

typedef void (*BlendFunc)(Color32*, const Color32*, const Color32*, int);


static BlendFunc FuncTableCPP[] =
{
	Blend_Zero_Zero,
	Blend_Zero_One,
	Blend_Zero_SrcColor,
	Blend_Zero_SrcInvColor,
	Blend_Zero_SrcAlpha,
	Blend_Zero_SrcInvAlpha,
	Blend_Zero_DestColor,
	Blend_Zero_DestInvColor,
	Blend_Zero_DestAlpha,
	Blend_Zero_DestInvAlpha,
	Blend_One_Zero,
	Blend_One_One,
	Blend_One_SrcColor,
	Blend_One_SrcInvColor,
	Blend_One_SrcAlpha,
	Blend_One_SrcInvAlpha,
	Blend_One_DestColor,
	Blend_One_DestInvColor,
	Blend_One_DestAlpha,
	Blend_One_DestInvAlpha,
	Blend_SrcColor_Zero,
	Blend_SrcColor_One,
	Blend_SrcColor_SrcColor,
	Blend_SrcColor_SrcInvColor,
	Blend_SrcColor_SrcAlpha,
	Blend_SrcColor_SrcInvAlpha,
	Blend_SrcColor_DestColor,
	Blend_SrcColor_DestInvColor,
	Blend_SrcColor_DestAlpha,
	Blend_SrcColor_DestInvAlpha,
	Blend_SrcInvColor_Zero,
	Blend_SrcInvColor_One,
	Blend_SrcInvColor_SrcColor,
	Blend_SrcInvColor_SrcInvColor,
	Blend_SrcInvColor_SrcAlpha,
	Blend_SrcInvColor_SrcInvAlpha,
	Blend_SrcInvColor_DestColor,
	Blend_SrcInvColor_DestInvColor,
	Blend_SrcInvColor_DestAlpha,
	Blend_SrcInvColor_DestInvAlpha,
	Blend_SrcAlpha_Zero,
	Blend_SrcAlpha_One,
	Blend_SrcAlpha_SrcColor,
	Blend_SrcAlpha_SrcInvColor,
	Blend_SrcAlpha_SrcAlpha,
	Blend_SrcAlpha_SrcInvAlpha,
	Blend_SrcAlpha_DestColor,
	Blend_SrcAlpha_DestInvColor,
	Blend_SrcAlpha_DestAlpha,
	Blend_SrcAlpha_DestInvAlpha,
	Blend_SrcInvAlpha_Zero,
	Blend_SrcInvAlpha_One,
	Blend_SrcInvAlpha_SrcColor,
	Blend_SrcInvAlpha_SrcInvColor,
	Blend_SrcInvAlpha_SrcAlpha,
	Blend_SrcInvAlpha_SrcInvAlpha,
	Blend_SrcInvAlpha_DestColor,
	Blend_SrcInvAlpha_DestInvColor,
	Blend_SrcInvAlpha_DestAlpha,
	Blend_SrcInvAlpha_DestInvAlpha,
	Blend_DestColor_Zero,
	Blend_DestColor_One,
	Blend_DestColor_SrcColor,
	Blend_DestColor_SrcInvColor,
	Blend_DestColor_SrcAlpha,
	Blend_DestColor_SrcInvAlpha,
	Blend_DestColor_DestColor,
	Blend_DestColor_DestInvColor,
	Blend_DestColor_DestAlpha,
	Blend_DestColor_DestInvAlpha,
	Blend_DestInvColor_Zero,
	Blend_DestInvColor_One,
	Blend_DestInvColor_SrcColor,
	Blend_DestInvColor_SrcInvColor,
	Blend_DestInvColor_SrcAlpha,
	Blend_DestInvColor_SrcInvAlpha,
	Blend_DestInvColor_DestColor,
	Blend_DestInvColor_DestInvColor,
	Blend_DestInvColor_DestAlpha,
	Blend_DestInvColor_DestInvAlpha,
	Blend_DestAlpha_Zero,
	Blend_DestAlpha_One,
	Blend_DestAlpha_SrcColor,
	Blend_DestAlpha_SrcInvColor,
	Blend_DestAlpha_SrcAlpha,
	Blend_DestAlpha_SrcInvAlpha,
	Blend_DestAlpha_DestColor,
	Blend_DestAlpha_DestInvColor,
	Blend_DestAlpha_DestAlpha,
	Blend_DestAlpha_DestInvAlpha,
	Blend_DestInvAlpha_Zero,
	Blend_DestInvAlpha_One,
	Blend_DestInvAlpha_SrcColor,
	Blend_DestInvAlpha_SrcInvColor,
	Blend_DestInvAlpha_SrcAlpha,
	Blend_DestInvAlpha_SrcInvAlpha,
	Blend_DestInvAlpha_DestColor,
	Blend_DestInvAlpha_DestInvColor,
	Blend_DestInvAlpha_DestAlpha,
	Blend_DestInvAlpha_DestInvAlpha,
};


//////////////////////////////////////////////////////
// X86-MMX implementation table                    //
////////////////////////////////////////////////////

#ifdef PRCORE_X86_SIMD

extern "C"
{
	extern int64	mmx_mult0;
	extern int64	mmx_mult1;
	extern int*		mmx_alpha;
};
static BlendFunc* FuncTableMMX = (BlendFunc*)&mmx_alpha;

#endif // PRCORE_X86_SIMD


//////////////////////////////////////////////////////
// setup                                           //
////////////////////////////////////////////////////

static BlendFunc* InnerTable = NULL;
static BlendFunc BlendFuncPtr = NULL;


static inline int AlphaFuncOffset(AlphaFunc af0, AlphaFunc af1)
{
	return af0 * 10 + af1;
}


static void InitializeInner()
{
	// already initialized?
	if ( InnerTable )
		return;

	// default: generic c++ innerloops
	InnerTable = FuncTableCPP;


	#ifdef PRCORE_X86_SIMD

	// use MMX innerloops if possible
	if ( IsMMX() ) 
		InnerTable = FuncTableMMX;

	// to defeat the egcs/gcc warnings
	uint32* a = (uint32*)&mmx_mult0;
	uint32* b = (uint32*)&mmx_mult1;
	a[0] = 0x00ff; a[1] = 0x00ff;
	b[0] = 0x00ff; b[1] = 0x00ff;

	#endif // PRCORE_X86_SIMD


	// default alphafunc
	BlendFuncPtr = InnerTable[ AlphaFuncOffset(ONE,ZERO) ];
}


//////////////////////////////////////////////////////
// interface                                       //
////////////////////////////////////////////////////

void prcore::SetConstantAlpha(uint8 mult0, uint8 mult1)
{
	if ( !InnerTable )
		InitializeInner();

	if ( InnerTable == FuncTableCPP )
	{
		Color32* array0 = (Color32*)lut0_int;
		Color32* array1 = (Color32*)lut1_int;
		for ( int i=0; i<256; i++ )
		{
			uint32 scale0 = (i*mult0) >> 8;
			array0->b = scale0;
			array0->g = scale0;
			array0->r = scale0;
			array0->a = scale0;
			array0++;

			uint32 scale1 = (i*mult1) >> 8;
			array1->b = scale1;
			array1->g = scale1;
			array1->r = scale1;
			array1->a = scale1;
			array1++;
		}
	}
	else
	{
#ifdef PRCORE_X86_SIMD
		int64 a0 = (int64)mult0;
		int64 a1 = (int64)mult1;
		mmx_mult0 = (a0<<48) | (a0<<32) | (a0<<16) | a0;
		mmx_mult1 = (a1<<48) | (a1<<32) | (a1<<16) | a1;
#endif // PRCORE_X86_SIMD
	}
}


void prcore::SetAlphaFunc(AlphaFunc func0, AlphaFunc func1)
{
	if ( !InnerTable )
		InitializeInner();

	BlendFuncPtr = InnerTable[ AlphaFuncOffset(func0,func1) ];
}


void prcore::AlphaBlend(uint32* dest, uint32* source0, uint32* source1, int count)
{
	if ( !InnerTable )
		InitializeInner();

	BlendFuncPtr(
		(Color32*)dest,
		(Color32*)source0,
		(Color32*)source1,
		count );
}


void prcore::AlphaBlend(int x, int y, Surface& dest, const Surface& source)
{
	// assert
	assert( dest.GetImage() );
	assert( source.GetImage() );

	if ( dest.GetFormat().GetBits() != 32 ) return;
	if ( source.GetFormat().GetBits() != 32 ) return;

	if ( !InnerTable )
		InitializeInner();

	// clip
	Rect rect;
	if ( !rect.Intersect(
		dest.GetRect(),
		Rect(x,y,source.GetWidth(),source.GetHeight()) ))
		return;

	int sx = rect.x - x;
	int sy = rect.y - y;

	// setup surfaces
	int bpp0 = dest.GetFormat().GetBytes();
	int bpp1 = source.GetFormat().GetBytes();
	int pitch0 = dest.GetPitch();
	int pitch1 = source.GetPitch();
	uint8* image0 = dest.GetImage() + rect.y * pitch0 + rect.x * bpp0;
	uint8* image1 = source.GetImage() + sy * pitch1 + sx * bpp1;

	// alphablend
	for ( int i=0; i<rect.height; i++ )
	{
		BlendFuncPtr(
			(Color32*)image0,
			(Color32*)image1,
			(Color32*)image0,
			rect.width );

		image0 += pitch0;
		image1 += pitch1;
	}
}
