306 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			306 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten
 | |
| // This file is part of the "Irrlicht Engine".
 | |
| // For conditions of distribution and use, see copyright notice in irrlicht.h
 | |
| 
 | |
| /*
 | |
| 	History:
 | |
| 	- changed behavior for log2 textures ( replaced multiplies by shift )
 | |
| */
 | |
| 
 | |
| #ifndef __S_VIDEO_2_SOFTWARE_HELPER_H_INCLUDED__
 | |
| #define __S_VIDEO_2_SOFTWARE_HELPER_H_INCLUDED__
 | |
| 
 | |
| #include "irrMath.h"
 | |
| #include "SMaterial.h"
 | |
| 
 | |
| #ifndef REALINLINE
 | |
| #ifdef _MSC_VER
 | |
| #define REALINLINE __forceinline
 | |
| #else
 | |
| #define REALINLINE inline
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| 
 | |
| namespace irr
 | |
| {
 | |
| 
 | |
| // ----------------------- Generic ----------------------------------
 | |
| //! align_next - align to next upper 2^n
 | |
| #define align_next(num,to) (((num) + (to-1)) & (~(to-1)))
 | |
| 
 | |
| //! a more useful memset for pixel. dest must be aligned at least to 4 byte
 | |
| // (standard memset only works with 8-bit values)
 | |
| inline void memset32(void * dest, const u32 value, size_t bytesize)
 | |
| {
 | |
| 	u32 * d = (u32*) dest;
 | |
| 
 | |
| 	size_t i;
 | |
| 
 | |
| 	// loops unrolled to reduce the number of increments by factor ~8.
 | |
| 	i = bytesize >> (2 + 3);
 | |
| 	while (i)
 | |
| 	{
 | |
| 		d[0] = value;
 | |
| 		d[1] = value;
 | |
| 		d[2] = value;
 | |
| 		d[3] = value;
 | |
| 
 | |
| 		d[4] = value;
 | |
| 		d[5] = value;
 | |
| 		d[6] = value;
 | |
| 		d[7] = value;
 | |
| 
 | |
| 		d += 8;
 | |
| 		i -= 1;
 | |
| 	}
 | |
| 
 | |
| 	i = (bytesize >> 2 ) & 7;
 | |
| 	while (i)
 | |
| 	{
 | |
| 		d[0] = value;
 | |
| 		d += 1;
 | |
| 		i -= 1;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| //! a more useful memset for pixel. dest must be aligned at least to 2 byte
 | |
| // (standard memset only works with 8-bit values)
 | |
| inline void memset16(void * dest, const u16 value, size_t bytesize)
 | |
| {
 | |
| 	u16 * d = (u16*) dest;
 | |
| 
 | |
| 	size_t i;
 | |
| 
 | |
| 	// loops unrolled to reduce the number of increments by factor ~8.
 | |
| 	i = bytesize >> (1 + 3);
 | |
| 	while (i)
 | |
| 	{
 | |
| 		d[0] = value;
 | |
| 		d[1] = value;
 | |
| 		d[2] = value;
 | |
| 		d[3] = value;
 | |
| 
 | |
| 		d[4] = value;
 | |
| 		d[5] = value;
 | |
| 		d[6] = value;
 | |
| 		d[7] = value;
 | |
| 
 | |
| 		d += 8;
 | |
| 		--i;
 | |
| 	}
 | |
| 
 | |
| 	i = (bytesize >> 1 ) & 7;
 | |
| 	while (i)
 | |
| 	{
 | |
| 		d[0] = value;
 | |
| 		++d;
 | |
| 		--i;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // integer log2 of an integer. returning 0 as denormal
 | |
| static inline s32 s32_log2_s32(u32 in)
 | |
| {
 | |
| 	s32 ret = 0;
 | |
| 	while (in > 1)
 | |
| 	{
 | |
| 		in >>= 1;
 | |
| 		ret++;
 | |
| 	}
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| // ------------------ Video---------------------------------------
 | |
| /*!
 | |
| 	Pixel = dest * ( 1 - alpha ) + source * alpha
 | |
| 	alpha [0;256]
 | |
| */
 | |
| REALINLINE u32 PixelBlend32 ( const u32 c2, const u32 c1, const u32 alpha )
 | |
| {
 | |
| 	u32 srcRB = c1 & 0x00FF00FF;
 | |
| 	u32 srcXG = c1 & 0x0000FF00;
 | |
| 
 | |
| 	u32 dstRB = c2 & 0x00FF00FF;
 | |
| 	u32 dstXG = c2 & 0x0000FF00;
 | |
| 
 | |
| 
 | |
| 	u32 rb = srcRB - dstRB;
 | |
| 	u32 xg = srcXG - dstXG;
 | |
| 
 | |
| 	rb *= alpha;
 | |
| 	xg *= alpha;
 | |
| 	rb >>= 8;
 | |
| 	xg >>= 8;
 | |
| 
 | |
| 	rb += dstRB;
 | |
| 	xg += dstXG;
 | |
| 
 | |
| 	rb &= 0x00FF00FF;
 | |
| 	xg &= 0x0000FF00;
 | |
| 
 | |
| 	return rb | xg;
 | |
| }
 | |
| 
 | |
| /*!
 | |
| 	Pixel = dest * ( 1 - alpha ) + source * alpha
 | |
| 	alpha [0;32]
 | |
| */
 | |
| inline u16 PixelBlend16 ( const u16 c2, const u16 c1, const u16 alpha )
 | |
| {
 | |
| 	const u16 srcRB = c1 & 0x7C1F;
 | |
| 	const u16 srcXG = c1 & 0x03E0;
 | |
| 
 | |
| 	const u16 dstRB = c2 & 0x7C1F;
 | |
| 	const u16 dstXG = c2 & 0x03E0;
 | |
| 
 | |
| 	u32 rb = srcRB - dstRB;
 | |
| 	u32 xg = srcXG - dstXG;
 | |
| 
 | |
| 	rb *= alpha;
 | |
| 	xg *= alpha;
 | |
| 	rb >>= 5;
 | |
| 	xg >>= 5;
 | |
| 
 | |
| 	rb += dstRB;
 | |
| 	xg += dstXG;
 | |
| 
 | |
| 	rb &= 0x7C1F;
 | |
| 	xg &= 0x03E0;
 | |
| 
 | |
| 	return (u16)(rb | xg);
 | |
| }
 | |
| 
 | |
| /*
 | |
| 	Pixel = c0 * (c1/31). c0 Alpha retain
 | |
| */
 | |
| inline u16 PixelMul16 ( const u16 c0, const u16 c1)
 | |
| {
 | |
| 	return (u16)((( ( (c0 & 0x7C00) * (c1 & 0x7C00) ) & 0x3E000000 ) >> 15 ) |
 | |
| 			(( ( (c0 & 0x03E0) * (c1 & 0x03E0) ) & 0x000F8000 ) >> 10 ) |
 | |
| 			(( ( (c0 & 0x001F) * (c1 & 0x001F) ) & 0x000003E0 ) >> 5 ) |
 | |
| 			(c0 & 0x8000));
 | |
| }
 | |
| 
 | |
| /*
 | |
| 	Pixel = c0 * (c1/31).
 | |
| */
 | |
| inline u16 PixelMul16_2 ( u16 c0, u16 c1)
 | |
| {
 | |
| 	return	(u16)(( ( (c0 & 0x7C00) * (c1 & 0x7C00) ) & 0x3E000000 ) >> 15 |
 | |
| 			( ( (c0 & 0x03E0) * (c1 & 0x03E0) ) & 0x000F8000 ) >> 10 |
 | |
| 			( ( (c0 & 0x001F) * (c1 & 0x001F) ) & 0x000003E0 ) >> 5  |
 | |
| 			( c0 & c1 & 0x8000));
 | |
| }
 | |
| 
 | |
| /*
 | |
| 	Pixel = c0 * (c1/255). c0 Alpha Retain
 | |
| */
 | |
| REALINLINE u32 PixelMul32 ( const u32 c0, const u32 c1)
 | |
| {
 | |
| 	return	(c0 & 0xFF000000) |
 | |
| 			(( ( (c0 & 0x00FF0000) >> 12 ) * ( (c1 & 0x00FF0000) >> 12 ) ) & 0x00FF0000 ) |
 | |
| 			(( ( (c0 & 0x0000FF00) * (c1 & 0x0000FF00) ) >> 16 ) & 0x0000FF00 ) |
 | |
| 			(( ( (c0 & 0x000000FF) * (c1 & 0x000000FF) ) >> 8  ) & 0x000000FF);
 | |
| }
 | |
| 
 | |
| /*
 | |
| 	Pixel = c0 * (c1/255).
 | |
| */
 | |
| REALINLINE u32 PixelMul32_2 ( const u32 c0, const u32 c1)
 | |
| {
 | |
| 	return	(( ( (c0 & 0xFF000000) >> 16 ) * ( (c1 & 0xFF000000) >> 16 ) ) & 0xFF000000 ) |
 | |
| 			(( ( (c0 & 0x00FF0000) >> 12 ) * ( (c1 & 0x00FF0000) >> 12 ) ) & 0x00FF0000 ) |
 | |
| 			(( ( (c0 & 0x0000FF00) * (c1 & 0x0000FF00) ) >> 16 ) & 0x0000FF00 ) |
 | |
| 			(( ( (c0 & 0x000000FF) * (c1 & 0x000000FF) ) >> 8  ) & 0x000000FF);
 | |
| }
 | |
| 
 | |
| /*
 | |
| 	Pixel = clamp ( c0 + c1, 0, 255 )
 | |
| */
 | |
| REALINLINE u32 PixelAdd32 ( const u32 c2, const u32 c1)
 | |
| {
 | |
| 	u32 sum = ( c2 & 0x00FFFFFF )  + ( c1 & 0x00FFFFFF );
 | |
| 	u32 low_bits = ( c2 ^ c1 ) & 0x00010101;
 | |
| 	s32 carries  = ( sum - low_bits ) & 0x01010100;
 | |
| 	u32 modulo = sum - carries;
 | |
| 	u32 clamp = carries - ( carries >> 8 );
 | |
| 	return modulo | clamp;
 | |
| }
 | |
| 
 | |
| // 1 - Bit Alpha Blending
 | |
| inline u16 PixelBlend16 ( const u16 c2, const u16 c1 )
 | |
| {
 | |
| 	u16 mask = ((c1 & 0x8000) >> 15 ) + 0x7fff;
 | |
| 	return (c2 & mask ) | ( c1 & ~mask );
 | |
| }
 | |
| /*!
 | |
| 	Pixel = dest * ( 1 - SourceAlpha ) + source * SourceAlpha (OpenGL blending)
 | |
| */
 | |
| inline u32 PixelBlend32 ( const u32 c2, const u32 c1 )
 | |
| {
 | |
| 	// alpha test
 | |
| 	u32 alpha = c1 & 0xFF000000;
 | |
| 
 | |
| 	if ( 0 == alpha )
 | |
| 		return c2;
 | |
| 	if ( 0xFF000000 == alpha )
 | |
| 	{
 | |
| 		return c1;
 | |
| 	}
 | |
| 
 | |
| 	alpha >>= 24;
 | |
| 
 | |
| 	// add highbit alpha, if ( alpha > 127 ) alpha += 1;
 | |
| 	alpha += ( alpha >> 7);
 | |
| 
 | |
| 	u32 srcRB = c1 & 0x00FF00FF;
 | |
| 	u32 srcXG = c1 & 0x0000FF00;
 | |
| 
 | |
| 	u32 dstRB = c2 & 0x00FF00FF;
 | |
| 	u32 dstXG = c2 & 0x0000FF00;
 | |
| 
 | |
| 
 | |
| 	u32 rb = srcRB - dstRB;
 | |
| 	u32 xg = srcXG - dstXG;
 | |
| 
 | |
| 	rb *= alpha;
 | |
| 	xg *= alpha;
 | |
| 	rb >>= 8;
 | |
| 	xg >>= 8;
 | |
| 
 | |
| 	rb += dstRB;
 | |
| 	xg += dstXG;
 | |
| 
 | |
| 	rb &= 0x00FF00FF;
 | |
| 	xg &= 0x0000FF00;
 | |
| 
 | |
| 	return (c1 & 0xFF000000) | rb | xg;
 | |
| }
 | |
| 
 | |
| 
 | |
| // 2D Region closed [x0;x1]
 | |
| struct AbsRectangle
 | |
| {
 | |
| 	s32 x0;
 | |
| 	s32 y0;
 | |
| 	s32 x1;
 | |
| 	s32 y1;
 | |
| };
 | |
| 
 | |
| //! 2D Intersection test
 | |
| inline bool intersect ( AbsRectangle &dest, const AbsRectangle& a, const AbsRectangle& b)
 | |
| {
 | |
| 	dest.x0 = core::s32_max( a.x0, b.x0 );
 | |
| 	dest.y0 = core::s32_max( a.y0, b.y0 );
 | |
| 	dest.x1 = core::s32_min( a.x1, b.x1 );
 | |
| 	dest.y1 = core::s32_min( a.y1, b.y1 );
 | |
| 	return dest.x0 < dest.x1 && dest.y0 < dest.y1;
 | |
| }
 | |
| 
 | |
| 
 | |
| } // end namespace irr
 | |
| 
 | |
| #endif
 | |
| 
 |