The exact commands to make this commit were: git reset --hard origin/master find -type f | # list all regular files grep -E '\.(h|cpp|fsh|vsh|mm)|LICENSE$' | # filter for text files xargs -n 1 -P $(nproc) sed -i 's:\s*$::' # for each file, trim trailing whitespace including the CR git commit -a
		
			
				
	
	
		
			1060 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1060 lines
		
	
	
		
			26 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
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include "SoftwareDriver2_helper.h"
 | |
| 
 | |
| namespace irr
 | |
| {
 | |
| 
 | |
| //! f18 - fixpoint 14.18 limit to 16k Textures
 | |
| #define CBLIT_USE_FIXPOINT18
 | |
| 
 | |
| #if defined(CBLIT_USE_FIXPOINT18)
 | |
| 	typedef int f18;
 | |
| 	#define f18_one 262144
 | |
| 	#define f18_zero 0
 | |
| 	#define f32_to_f18(x)((f18)floorf(((x) * 262144.f) + 0.f))
 | |
| 	#define f32_to_f32(x)(x)
 | |
| 	#define f18_floor(x) ((x)>>18)
 | |
| 	#define f18_round(x) ((x+131.072)>>18)
 | |
| #else
 | |
| 	typedef float f18;
 | |
| 	#define f18_one 1.f
 | |
| 	#define f18_zero_dot_five 0.5f
 | |
| 	#define f18_zero 0.f
 | |
| 	#define f32_to_f18(x)(x)
 | |
| 	#define f32_to_f32(x)(x)
 | |
| 	#define f18_floor(x) ((int)(x))
 | |
| 	#define f18_round(x) ((int)(x+0.5f))
 | |
| #endif
 | |
| 
 | |
| 	struct SBlitJob
 | |
| 	{
 | |
| 		AbsRectangle Dest;
 | |
| 		AbsRectangle Source;
 | |
| 
 | |
| 		u32 argb;
 | |
| 
 | |
| 		const void* src;
 | |
| 		void* dst;
 | |
| 
 | |
| 		u32 width;		//draw size
 | |
| 		u32 height;
 | |
| 
 | |
| 		u32 srcPixelMul; //pixel byte size
 | |
| 		u32 dstPixelMul;
 | |
| 
 | |
| 		int srcPitch;	//scanline byte size. allow negative for mirror
 | |
| 		u32 dstPitch;
 | |
| 
 | |
| 		bool stretch;
 | |
| 		f32 x_stretch;
 | |
| 		f32 y_stretch;
 | |
| 	};
 | |
| 
 | |
| 	// Bitfields Cohen Sutherland
 | |
| 	enum eClipCode
 | |
| 	{
 | |
| 		CLIPCODE_EMPTY	=	0,
 | |
| 		CLIPCODE_BOTTOM	=	1,
 | |
| 		CLIPCODE_TOP	=	2,
 | |
| 		CLIPCODE_LEFT	=	4,
 | |
| 		CLIPCODE_RIGHT	=	8
 | |
| 	};
 | |
| 
 | |
| inline u32 GetClipCode( const AbsRectangle &r, const core::position2d<s32> &p )
 | |
| {
 | |
| 	u32 code = CLIPCODE_EMPTY;
 | |
| 
 | |
| 	if ( p.X < r.x0 )
 | |
| 		code = CLIPCODE_LEFT;
 | |
| 	else
 | |
| 	if ( p.X > r.x1 )
 | |
| 		code = CLIPCODE_RIGHT;
 | |
| 
 | |
| 	if ( p.Y < r.y0 )
 | |
| 		code |= CLIPCODE_TOP;
 | |
| 	else
 | |
| 	if ( p.Y > r.y1 )
 | |
| 		code |= CLIPCODE_BOTTOM;
 | |
| 
 | |
| 	return code;
 | |
| }
 | |
| 
 | |
| /*
 | |
| */
 | |
| inline void GetClip(AbsRectangle &clipping, video::IImage * t)
 | |
| {
 | |
| 	clipping.x0 = 0;
 | |
| 	clipping.y0 = 0;
 | |
| 	clipping.x1 = t->getDimension().Width - 1;
 | |
| 	clipping.y1 = t->getDimension().Height - 1;
 | |
| }
 | |
| 
 | |
| /*
 | |
| 	return alpha in [0;256] Granularity from 32-Bit ARGB
 | |
| 	add highbit alpha ( alpha > 127 ? + 1 )
 | |
| */
 | |
| static inline u32 extractAlpha(const u32 c)
 | |
| {
 | |
| 	return ( c >> 24 ) + ( c >> 31 );
 | |
| }
 | |
| 
 | |
| /*
 | |
| 	return alpha in [0;255] Granularity and 32-Bit ARGB
 | |
| 	add highbit alpha ( alpha > 127 ? + 1 )
 | |
| */
 | |
| static inline u32 packAlpha(const u32 c)
 | |
| {
 | |
| 	return (c > 127 ? c - 1 : c) << 24;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*!
 | |
| 	Scale Color by (1/value)
 | |
| 	value 0 - 256 ( alpha )
 | |
| */
 | |
| inline u32 PixelLerp32(const u32 source, const u32 value)
 | |
| {
 | |
| 	u32 srcRB = source & 0x00FF00FF;
 | |
| 	u32 srcXG = (source & 0xFF00FF00) >> 8;
 | |
| 
 | |
| 	srcRB *= value;
 | |
| 	srcXG *= value;
 | |
| 
 | |
| 	srcRB >>= 8;
 | |
| 	//srcXG >>= 8;
 | |
| 
 | |
| 	srcXG &= 0xFF00FF00;
 | |
| 	srcRB &= 0x00FF00FF;
 | |
| 
 | |
| 	return srcRB | srcXG;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*!
 | |
| */
 | |
| static void executeBlit_TextureCopy_x_to_x( const SBlitJob * job )
 | |
| {
 | |
| 	if (job->stretch)
 | |
| 	{
 | |
| 		const f18 wscale = f32_to_f18(job->x_stretch);
 | |
| 		const f18 hscale = f32_to_f18(job->y_stretch);
 | |
| 
 | |
| 		f18 src_y = f18_zero;
 | |
| 
 | |
| 		if (job->srcPixelMul == 4)
 | |
| 		{
 | |
| 			const u32 *src = (u32*)(job->src);
 | |
| 			u32 *dst = (u32*)(job->dst);
 | |
| 
 | |
| 			for (u32 dy = 0; dy < job->height; ++dy, src_y += hscale)
 | |
| 			{
 | |
| 				src = (u32*)((u8*)(job->src) + job->srcPitch*f18_floor(src_y));
 | |
| 
 | |
| 				f18 src_x = f18_zero;
 | |
| 				for (u32 dx = 0; dx < job->width; ++dx, src_x += wscale)
 | |
| 				{
 | |
| 					dst[dx] = src[f18_floor(src_x)];
 | |
| 				}
 | |
| 				dst = (u32*)((u8*)(dst)+job->dstPitch);
 | |
| 			}
 | |
| 		}
 | |
| 		else if (job->srcPixelMul == 2)
 | |
| 		{
 | |
| 			const u16 *src = (u16*)(job->src);
 | |
| 			u16* dst = (u16*)(job->dst);
 | |
| 
 | |
| 			for (u32 dy = 0; dy < job->height; ++dy, src_y += hscale)
 | |
| 			{
 | |
| 				src = (u16*)((u8*)(job->src) + job->srcPitch*f18_floor(src_y));
 | |
| 
 | |
| 				f18 src_x = f18_zero;
 | |
| 				for (u32 dx = 0; dx < job->width; ++dx, src_x += wscale)
 | |
| 				{
 | |
| 					dst[dx] = src[f18_floor(src_x)];
 | |
| 				}
 | |
| 				dst = (u16*)((u8*)(dst)+job->dstPitch);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		const size_t widthPitch = job->width * job->dstPixelMul;
 | |
| 		const void *src = (void*) job->src;
 | |
| 		void *dst = (void*) job->dst;
 | |
| 
 | |
| 		for ( u32 dy = 0; dy < job->height; ++dy )
 | |
| 		{
 | |
| 			memcpy( dst, src, widthPitch);
 | |
| 
 | |
| 			src = (void*) ( (u8*) (src) + job->srcPitch );
 | |
| 			dst = (void*) ( (u8*) (dst) + job->dstPitch );
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*!
 | |
| */
 | |
| static void executeBlit_TextureCopy_32_to_16( const SBlitJob * job )
 | |
| {
 | |
| 	const u32 w = job->width;
 | |
| 	const u32 h = job->height;
 | |
| 	const u32 *src = static_cast<const u32*>(job->src);
 | |
| 	u16 *dst = static_cast<u16*>(job->dst);
 | |
| 
 | |
| 	if (job->stretch)
 | |
| 	{
 | |
| 		const float wscale = job->x_stretch;
 | |
| 		const float hscale = job->y_stretch;
 | |
| 
 | |
| 		for ( u32 dy = 0; dy < h; ++dy )
 | |
| 		{
 | |
| 			const u32 src_y = (u32)(dy*hscale);
 | |
| 			src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y );
 | |
| 
 | |
| 			for ( u32 dx = 0; dx < w; ++dx )
 | |
| 			{
 | |
| 				const u32 src_x = (u32)(dx*wscale);
 | |
| 				//16 bit Blitter depends on pre-multiplied color
 | |
| 				const u32 s = PixelLerp32( src[src_x] | 0xFF000000, extractAlpha( src[src_x] ) );
 | |
| 				dst[dx] = video::A8R8G8B8toA1R5G5B5( s );
 | |
| 			}
 | |
| 			dst = (u16*) ( (u8*) (dst) + job->dstPitch );
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		for ( u32 dy = 0; dy != h; ++dy )
 | |
| 		{
 | |
| 			for ( u32 dx = 0; dx != w; ++dx )
 | |
| 			{
 | |
| 				//16 bit Blitter depends on pre-multiplied color
 | |
| 				const u32 s = PixelLerp32( src[dx] | 0xFF000000, extractAlpha( src[dx] ) );
 | |
| 				dst[dx] = video::A8R8G8B8toA1R5G5B5( s );
 | |
| 			}
 | |
| 
 | |
| 			src = (u32*) ( (u8*) (src) + job->srcPitch );
 | |
| 			dst = (u16*) ( (u8*) (dst) + job->dstPitch );
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*!
 | |
| */
 | |
| static void executeBlit_TextureCopy_24_to_16( const SBlitJob * job )
 | |
| {
 | |
| 	const u32 w = job->width;
 | |
| 	const u32 h = job->height;
 | |
| 	const u8 *src = static_cast<const u8*>(job->src);
 | |
| 	u16 *dst = static_cast<u16*>(job->dst);
 | |
| 
 | |
| 	if (job->stretch)
 | |
| 	{
 | |
| 		const float wscale = job->x_stretch * 3.f;
 | |
| 		const float hscale = job->y_stretch;
 | |
| 
 | |
| 		for ( u32 dy = 0; dy < h; ++dy )
 | |
| 		{
 | |
| 			const u32 src_y = (u32)(dy*hscale);
 | |
| 			src = (u8*)(job->src) + job->srcPitch*src_y;
 | |
| 
 | |
| 			for ( u32 dx = 0; dx < w; ++dx )
 | |
| 			{
 | |
| 				const u8* src_x = src+(u32)(dx*wscale);
 | |
| 				dst[dx] = video::RGBA16(src_x[0], src_x[1], src_x[2]);
 | |
| 			}
 | |
| 			dst = (u16*) ( (u8*) (dst) + job->dstPitch );
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		for ( u32 dy = 0; dy != h; ++dy )
 | |
| 		{
 | |
| 			const u8* s = src;
 | |
| 			for ( u32 dx = 0; dx != w; ++dx )
 | |
| 			{
 | |
| 				dst[dx] = video::RGBA16(s[0], s[1], s[2]);
 | |
| 				s += 3;
 | |
| 			}
 | |
| 
 | |
| 			src = src+job->srcPitch;
 | |
| 			dst = (u16*) ( (u8*) (dst) + job->dstPitch );
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| /*!
 | |
| */
 | |
| static void executeBlit_TextureCopy_16_to_32( const SBlitJob * job )
 | |
| {
 | |
| 	const u32 w = job->width;
 | |
| 	const u32 h = job->height;
 | |
| 	const u16 *src = static_cast<const u16*>(job->src);
 | |
| 	u32 *dst = static_cast<u32*>(job->dst);
 | |
| 
 | |
| 	if (job->stretch)
 | |
| 	{
 | |
| 		const float wscale = job->x_stretch;
 | |
| 		const float hscale = job->y_stretch;
 | |
| 
 | |
| 		for ( u32 dy = 0; dy < h; ++dy )
 | |
| 		{
 | |
| 			const u32 src_y = (u32)(dy*hscale);
 | |
| 			src = (u16*) ( (u8*) (job->src) + job->srcPitch*src_y );
 | |
| 
 | |
| 			for ( u32 dx = 0; dx < w; ++dx )
 | |
| 			{
 | |
| 				const u32 src_x = (u32)(dx*wscale);
 | |
| 				dst[dx] = video::A1R5G5B5toA8R8G8B8(src[src_x]);
 | |
| 			}
 | |
| 			dst = (u32*) ( (u8*) (dst) + job->dstPitch );
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		for ( u32 dy = 0; dy != h; ++dy )
 | |
| 		{
 | |
| 			for ( u32 dx = 0; dx != w; ++dx )
 | |
| 			{
 | |
| 				dst[dx] = video::A1R5G5B5toA8R8G8B8( src[dx] );
 | |
| 			}
 | |
| 
 | |
| 			src = (u16*) ( (u8*) (src) + job->srcPitch );
 | |
| 			dst = (u32*) ( (u8*) (dst) + job->dstPitch );
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void executeBlit_TextureCopy_16_to_24( const SBlitJob * job )
 | |
| {
 | |
| 	const u32 w = job->width;
 | |
| 	const u32 h = job->height;
 | |
| 	const u16 *src = static_cast<const u16*>(job->src);
 | |
| 	u8 *dst = static_cast<u8*>(job->dst);
 | |
| 
 | |
| 	if (job->stretch)
 | |
| 	{
 | |
| 		const float wscale = job->x_stretch;
 | |
| 		const float hscale = job->y_stretch;
 | |
| 
 | |
| 		for ( u32 dy = 0; dy < h; ++dy )
 | |
| 		{
 | |
| 			const u32 src_y = (u32)(dy*hscale);
 | |
| 			src = (u16*) ( (u8*) (job->src) + job->srcPitch*src_y );
 | |
| 
 | |
| 			for ( u32 dx = 0; dx < w; ++dx )
 | |
| 			{
 | |
| 				const u32 src_x = (u32)(dx*wscale);
 | |
| 				u32 color = video::A1R5G5B5toA8R8G8B8(src[src_x]);
 | |
| 				u8 * writeTo = &dst[dx * 3];
 | |
| 				*writeTo++ = (color >> 16)& 0xFF;
 | |
| 				*writeTo++ = (color >> 8) & 0xFF;
 | |
| 				*writeTo++ = color & 0xFF;
 | |
| 			}
 | |
| 			dst += job->dstPitch;
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		for ( u32 dy = 0; dy != h; ++dy )
 | |
| 		{
 | |
| 			for ( u32 dx = 0; dx != w; ++dx )
 | |
| 			{
 | |
| 				u32 color = video::A1R5G5B5toA8R8G8B8(src[dx]);
 | |
| 				u8 * writeTo = &dst[dx * 3];
 | |
| 				*writeTo++ = (color >> 16)& 0xFF;
 | |
| 				*writeTo++ = (color >> 8) & 0xFF;
 | |
| 				*writeTo++ = color & 0xFF;
 | |
| 			}
 | |
| 
 | |
| 			src = (u16*) ( (u8*) (src) + job->srcPitch );
 | |
| 			dst += job->dstPitch;
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*!
 | |
| */
 | |
| static void executeBlit_TextureCopy_24_to_32( const SBlitJob * job )
 | |
| {
 | |
| 	const u32 w = job->width;
 | |
| 	const u32 h = job->height;
 | |
| 	const u8 *src = static_cast<const u8*>(job->src);
 | |
| 	u32 *dst = static_cast<u32*>(job->dst);
 | |
| 
 | |
| 	if (job->stretch)
 | |
| 	{
 | |
| 		const float wscale = job->x_stretch * 3.f;
 | |
| 		const float hscale = job->y_stretch;
 | |
| 
 | |
| 		for ( u32 dy = 0; dy < h; ++dy )
 | |
| 		{
 | |
| 			const u32 src_y = (u32)(dy*hscale);
 | |
| 			src = (const u8*)job->src+(job->srcPitch*src_y);
 | |
| 
 | |
| 			for ( u32 dx = 0; dx < w; ++dx )
 | |
| 			{
 | |
| 				const u8* s = src+(u32)(dx*wscale);
 | |
| 				dst[dx] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2];
 | |
| 			}
 | |
| 			dst = (u32*) ( (u8*) (dst) + job->dstPitch );
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		for ( u32 dy = 0; dy < job->height; ++dy )
 | |
| 		{
 | |
| 			const u8* s = src;
 | |
| 
 | |
| 			for ( u32 dx = 0; dx < job->width; ++dx )
 | |
| 			{
 | |
| 				dst[dx] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2];
 | |
| 				s += 3;
 | |
| 			}
 | |
| 
 | |
| 			src = src + job->srcPitch;
 | |
| 			dst = (u32*) ( (u8*) (dst) + job->dstPitch );
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void executeBlit_TextureCopy_32_to_24( const SBlitJob * job )
 | |
| {
 | |
| 	const u32 w = job->width;
 | |
| 	const u32 h = job->height;
 | |
| 	const u32 *src = static_cast<const u32*>(job->src);
 | |
| 	u8 *dst = static_cast<u8*>(job->dst);
 | |
| 
 | |
| 	if (job->stretch)
 | |
| 	{
 | |
| 		const float wscale = job->x_stretch;
 | |
| 		const float hscale = job->y_stretch;
 | |
| 
 | |
| 		for ( u32 dy = 0; dy < h; ++dy )
 | |
| 		{
 | |
| 			const u32 src_y = (u32)(dy*hscale);
 | |
| 			src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y);
 | |
| 
 | |
| 			for ( u32 dx = 0; dx < w; ++dx )
 | |
| 			{
 | |
| 				const u32 src_x = src[(u32)(dx*wscale)];
 | |
| 				u8 * writeTo = &dst[dx * 3];
 | |
| 				*writeTo++ = (src_x >> 16)& 0xFF;
 | |
| 				*writeTo++ = (src_x >> 8) & 0xFF;
 | |
| 				*writeTo++ = src_x & 0xFF;
 | |
| 			}
 | |
| 			dst += job->dstPitch;
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		for ( u32 dy = 0; dy != h; ++dy )
 | |
| 		{
 | |
| 			for ( u32 dx = 0; dx != w; ++dx )
 | |
| 			{
 | |
| 				u8 * writeTo = &dst[dx * 3];
 | |
| 				*writeTo++ = (src[dx] >> 16)& 0xFF;
 | |
| 				*writeTo++ = (src[dx] >> 8) & 0xFF;
 | |
| 				*writeTo++ = src[dx] & 0xFF;
 | |
| 			}
 | |
| 
 | |
| 			src = (u32*) ( (u8*) (src) + job->srcPitch );
 | |
| 			dst += job->dstPitch;
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*!
 | |
| */
 | |
| static void executeBlit_TextureBlend_16_to_16( const SBlitJob * job )
 | |
| {
 | |
| 	const f18 wscale = f32_to_f18(job->x_stretch);
 | |
| 	const f18 hscale = f32_to_f18(job->y_stretch);
 | |
| 
 | |
| 	f18 src_y = f18_zero;
 | |
| 	u16 *dst = (u16*)job->dst;
 | |
| 
 | |
| 	for (u32 dy = 0; dy < job->height; ++dy, src_y += hscale)
 | |
| 	{
 | |
| 		const u16* src = (u16*)((u8*)(job->src) + job->srcPitch*f18_floor(src_y));
 | |
| 		f18 src_x = f18_zero;
 | |
| 		for (u32 dx = 0; dx < job->width; ++dx, src_x += wscale)
 | |
| 		{
 | |
| 			dst[dx] = PixelBlend16(dst[dx], src[f18_floor(src_x)]);
 | |
| 		}
 | |
| 		dst = (u16*)((u8*)(dst)+job->dstPitch);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*!
 | |
| */
 | |
| static void executeBlit_TextureBlend_32_to_32( const SBlitJob * job )
 | |
| {
 | |
| 	const f18 wscale = f32_to_f18(job->x_stretch);
 | |
| 	const f18 hscale = f32_to_f18(job->y_stretch);
 | |
| 
 | |
| 	f18 src_y = f18_zero;
 | |
| 	u32 *dst = (u32*)job->dst;
 | |
| 	for (u32 dy = 0; dy < job->height; ++dy, src_y += hscale)
 | |
| 	{
 | |
| 		const u32* src = (u32*)((u8*)(job->src) + job->srcPitch*f18_floor(src_y));
 | |
| 
 | |
| 		f18 src_x = f18_zero;
 | |
| 		for (u32 dx = 0; dx < job->width; ++dx, src_x += wscale)
 | |
| 		{
 | |
| 			dst[dx] = PixelBlend32(dst[dx], src[f18_floor(src_x)]);
 | |
| 		}
 | |
| 		dst = (u32*)((u8*)(dst)+job->dstPitch);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*!
 | |
| */
 | |
| static void executeBlit_TextureBlendColor_16_to_16( const SBlitJob * job )
 | |
| {
 | |
| 	const u16 blend = video::A8R8G8B8toA1R5G5B5(job->argb);
 | |
| 
 | |
| 	const f18 wscale = f32_to_f18(job->x_stretch);
 | |
| 	const f18 hscale = f32_to_f18(job->y_stretch);
 | |
| 
 | |
| 	f18 src_y = f18_zero;
 | |
| 	u16 *dst = (u16*)job->dst;
 | |
| 	for (u32 dy = 0; dy < job->height; ++dy, src_y += hscale)
 | |
| 	{
 | |
| 		const u16* src = (u16*)((u8*)(job->src) + job->srcPitch*f18_floor(src_y));
 | |
| 		f18 src_x = f18_zero;
 | |
| 		for (u32 dx = 0; dx < job->width; ++dx, src_x += wscale)
 | |
| 		{
 | |
| 			u16 c0 = src[f18_floor(src_x)];
 | |
| 			if (0 == (c0 & 0x8000))
 | |
| 				continue;
 | |
| 
 | |
| 			dst[dx] = PixelMul16_2(c0, blend);
 | |
| 		}
 | |
| 		dst = (u16*)((u8*)(dst)+job->dstPitch);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| /*!
 | |
| */
 | |
| static void executeBlit_TextureBlendColor_32_to_32( const SBlitJob * job )
 | |
| {
 | |
| 	const f18 wscale = f32_to_f18(job->x_stretch);
 | |
| 	const f18 hscale = f32_to_f18(job->y_stretch);
 | |
| 
 | |
| 	u32* dst = (u32*)job->dst;
 | |
| 	f18 src_y = f18_zero;
 | |
| 	for (u32 dy = 0; dy < job->height; ++dy, src_y += hscale)
 | |
| 	{
 | |
| 		const u32* src = (u32*)((u8*)(job->src) + job->srcPitch*f18_floor(src_y));
 | |
| 
 | |
| 		f18 src_x = f18_zero;
 | |
| 		for (u32 dx = 0; dx < job->width; ++dx, src_x += wscale)
 | |
| 		{
 | |
| 			dst[dx] = PixelBlend32(dst[dx], PixelMul32_2(src[f18_floor(src_x)], job->argb));
 | |
| 		}
 | |
| 		dst = (u32*)((u8*)(dst)+job->dstPitch);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*!
 | |
| */
 | |
| static void executeBlit_Color_16_to_16( const SBlitJob * job )
 | |
| {
 | |
| 	const u16 c = video::A8R8G8B8toA1R5G5B5(job->argb);
 | |
| 	u16 *dst = (u16*) job->dst;
 | |
| 
 | |
| 	for ( u32 dy = 0; dy < job->height; ++dy )
 | |
| 	{
 | |
| 		memset16(dst, c, job->srcPitch);
 | |
| 		dst = (u16*) ( (u8*) (dst) + job->dstPitch );
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*!
 | |
| */
 | |
| static void executeBlit_Color_32_to_32( const SBlitJob * job )
 | |
| {
 | |
| 	u32 *dst = (u32*) job->dst;
 | |
| 
 | |
| 	for ( u32 dy = 0; dy < job->height; ++dy )
 | |
| 	{
 | |
| 		memset32( dst, job->argb, job->srcPitch );
 | |
| 		dst = (u32*) ( (u8*) (dst) + job->dstPitch );
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*!
 | |
| */
 | |
| static void executeBlit_ColorAlpha_16_to_16( const SBlitJob * job )
 | |
| {
 | |
| 	u16 *dst = (u16*) job->dst;
 | |
| 
 | |
| 	const u16 alpha = extractAlpha( job->argb ) >> 3;
 | |
| 	if ( 0 == alpha )
 | |
| 		return;
 | |
| 	const u32 src = video::A8R8G8B8toA1R5G5B5( job->argb );
 | |
| 
 | |
| 	for ( u32 dy = 0; dy != job->height; ++dy )
 | |
| 	{
 | |
| 		for ( u32 dx = 0; dx != job->width; ++dx )
 | |
| 		{
 | |
| 			dst[dx] = PixelBlend16( dst[dx], src, alpha );
 | |
| 		}
 | |
| 		dst = (u16*) ( (u8*) (dst) + job->dstPitch );
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*!
 | |
| */
 | |
| static void executeBlit_ColorAlpha_32_to_32( const SBlitJob * job )
 | |
| {
 | |
| 	const u32 alpha = extractAlpha( job->argb );
 | |
| 	if (0 == alpha)
 | |
| 		return;
 | |
| 
 | |
| 	u32 *dst = (u32*)job->dst;
 | |
| 	for ( u32 dy = 0; dy < job->height; ++dy )
 | |
| 	{
 | |
| 		for ( u32 dx = 0; dx < job->width; ++dx )
 | |
| 		{
 | |
| 			dst[dx] = PixelBlend32( dst[dx], job->argb, alpha );
 | |
| 		}
 | |
| 		dst = (u32*) ( (u8*) (dst) + job->dstPitch );
 | |
| 	}
 | |
| 
 | |
| }
 | |
| 
 | |
| /*!
 | |
| 	Pixel =>
 | |
| 			color = sourceAlpha > 0 ? source, else dest
 | |
| 			alpha = max(destAlpha, sourceAlpha)
 | |
| */
 | |
| inline u16 PixelCombine16(const u16 c2, const u16 c1)
 | |
| {
 | |
| 	if (video::getAlpha(c1) > 0)
 | |
| 		return c1;
 | |
| 	else
 | |
| 		return c2;
 | |
| }
 | |
| 
 | |
| /*!
 | |
| 	Combine alpha channels (increases alpha / reduces transparency)
 | |
| */
 | |
| static void executeBlit_TextureCombineColor_16_to_16( const SBlitJob * job )
 | |
| {
 | |
| 	const u32 w = job->width * 2;
 | |
| 	const u32 h = job->height * 2;
 | |
| 	u16* src = (u16*) job->src;
 | |
| 	u16* dst = (u16*) job->dst;
 | |
| 
 | |
| 	const u16 jobColor = video::A8R8G8B8toA1R5G5B5( job->argb );
 | |
| 
 | |
| 	/*
 | |
| 		Stretch not supported.
 | |
| 	*/
 | |
| 	for ( u32 dy = 0; dy != h; dy++ )
 | |
| 	{
 | |
| 		for ( u32 dx = 0; dx != w; dx++ )
 | |
| 		{
 | |
| 			const u16 src_x = src[dx];
 | |
| 			const u16 dst_x = dst[dx];
 | |
| 			dst[dx] = PixelCombine16( dst_x, PixelMul16_2( src_x, jobColor ) );
 | |
| 		}
 | |
| 		src = (u16*) ( (u8*) (src) + job->srcPitch );
 | |
| 		dst = (u16*) ( (u8*) (dst) + job->dstPitch );
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*!
 | |
| 	Combine alpha channels (increases alpha / reduces transparency)
 | |
| */
 | |
| static void executeBlit_TextureCombineColor_16_to_24( const SBlitJob * job )
 | |
| {
 | |
| 	const u32 w = job->width;
 | |
| 	const u32 h = job->height;
 | |
| 	const u16 *src = static_cast<const u16*>(job->src);
 | |
| 	u8 *dst = static_cast<u8*>(job->dst);
 | |
| 
 | |
| 	const u16 jobColor = video::A8R8G8B8toA1R5G5B5( job->argb );
 | |
| 
 | |
| 	if (job->stretch)
 | |
| 	{
 | |
| 		const float wscale = job->x_stretch;
 | |
| 		const float hscale = job->y_stretch;
 | |
| 
 | |
| 		for ( u32 dy = 0; dy < h; ++dy )
 | |
| 		{
 | |
| 			const u32 src_y = (u32)(dy*hscale);
 | |
| 			src = (u16*) ( (u8*) (job->src) + job->srcPitch*src_y );
 | |
| 
 | |
| 			for ( u32 dx = 0; dx < w; ++dx )
 | |
| 			{
 | |
| 				const u32 src_x = (u32)(dx*wscale);
 | |
| 				u32 color = PixelMul16_2( video::A1R5G5B5toA8R8G8B8(src[src_x]), jobColor);
 | |
| 				u8 * writeTo = &dst[dx * 3];
 | |
| 				if ( video::getAlpha(src[src_x]) > 0 ) // only overlay if source has visible alpha (alpha == 1)
 | |
| 				{
 | |
| 					*writeTo++ = (color >> 16)& 0xFF;
 | |
| 					*writeTo++ = (color >> 8) & 0xFF;
 | |
| 					*writeTo++ = color & 0xFF;
 | |
| 				}
 | |
| 			}
 | |
| 			dst += job->dstPitch;
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		for ( u32 dy = 0; dy != h; ++dy )
 | |
| 		{
 | |
| 			for ( u32 dx = 0; dx != w; ++dx )
 | |
| 			{
 | |
| 				u32 color = PixelMul16_2( video::A1R5G5B5toA8R8G8B8(src[dx]), jobColor);
 | |
| 				u8 * writeTo = &dst[dx * 3];
 | |
| 				if ( video::getAlpha(src[dx]) > 0 ) // only overlay if source has visible alpha (alpha == 1)
 | |
| 				{
 | |
| 					*writeTo++ = (color >> 16)& 0xFF;
 | |
| 					*writeTo++ = (color >> 8) & 0xFF;
 | |
| 					*writeTo++ = color & 0xFF;
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			src = (u16*) ( (u8*) (src) + job->srcPitch );
 | |
| 			dst += job->dstPitch;
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*!
 | |
| 	Pixel =>
 | |
| 			color = dest * ( 1 - SourceAlpha ) + source * SourceAlpha,
 | |
| 			alpha = destAlpha * ( 1 - SourceAlpha ) + sourceAlpha
 | |
| 
 | |
| 	where "1" means "full scale" (255)
 | |
| */
 | |
| inline u32 PixelCombine32(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;
 | |
| 	// stretches [0;255] to [0;256] to avoid division by 255. use division 256 == shr 8
 | |
| 	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;
 | |
| 
 | |
| 	u32 sa = c1 >> 24;
 | |
| 	u32 da = c2 >> 24;
 | |
| 	u32 blendAlpha_fix8 = (sa * 256 + da * (256 - alpha)) >> 8;
 | |
| 	return blendAlpha_fix8 << 24 | rb | xg;
 | |
| }
 | |
| 
 | |
| /*!
 | |
| 	Combine alpha channels (increases alpha / reduces transparency)
 | |
| 	Destination alpha is treated as full 255
 | |
| */
 | |
| static void executeBlit_TextureCombineColor_32_to_24( const SBlitJob * job )
 | |
| {
 | |
| 	const u32 w = job->width;
 | |
| 	const u32 h = job->height;
 | |
| 	const u32 *src = static_cast<const u32*>(job->src);
 | |
| 	u8 *dst = static_cast<u8*>(job->dst);
 | |
| 
 | |
| 	if (job->stretch)
 | |
| 	{
 | |
| 		const float wscale = job->x_stretch;
 | |
| 		const float hscale = job->y_stretch;
 | |
| 
 | |
| 		for ( u32 dy = 0; dy < h; ++dy )
 | |
| 		{
 | |
| 			const u32 src_y = (u32)(dy*hscale);
 | |
| 			src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y);
 | |
| 
 | |
| 			for ( u32 dx = 0; dx < w; ++dx )
 | |
| 			{
 | |
| 				const u32 src_x = src[(u32)(dx*wscale)];
 | |
| 				u8* writeTo = &dst[dx * 3];
 | |
| 				const u32 dst_x = 0xFF000000 | writeTo[0] << 16 | writeTo[1] << 8 | writeTo[2];
 | |
| 				const u32 combo = PixelCombine32( dst_x, PixelMul32_2( src_x, job->argb ) );
 | |
| 				*writeTo++ = (combo >> 16) & 0xFF;
 | |
| 				*writeTo++ = (combo >> 8) & 0xFF;
 | |
| 				*writeTo++ = combo & 0xFF;
 | |
| 			}
 | |
| 			dst += job->dstPitch;
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		for ( u32 dy = 0; dy != h; ++dy )
 | |
| 		{
 | |
| 			for ( u32 dx = 0; dx != w; ++dx )
 | |
| 			{
 | |
| 				u8* writeTo = &dst[dx * 3];
 | |
| 				const u32 dst_x = 0xFF000000 | writeTo[0] << 16 | writeTo[1] << 8 | writeTo[2];
 | |
| 				const u32 combo = PixelCombine32( dst_x, PixelMul32_2( src[dx], job->argb ) );
 | |
| 				*writeTo++ = (combo >> 16) & 0xFF;
 | |
| 				*writeTo++ = (combo >> 8) & 0xFF;
 | |
| 				*writeTo++ = combo & 0xFF;
 | |
| 			}
 | |
| 
 | |
| 			src = (u32*) ( (u8*) (src) + job->srcPitch );
 | |
| 			dst += job->dstPitch;
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*!
 | |
| 	Combine alpha channels (increases alpha / reduces transparency)
 | |
| */
 | |
| static void executeBlit_TextureCombineColor_32_to_32( const SBlitJob * job )
 | |
| {
 | |
| 	u32 *src = (u32*) job->src;
 | |
| 	u32 *dst = (u32*) job->dst;
 | |
| 
 | |
| 	for ( u32 dy = 0; dy != job->height; ++dy )
 | |
| 	{
 | |
| 		for (u32 dx = 0; dx != job->width; ++dx )
 | |
| 		{
 | |
| 			dst[dx] = PixelCombine32( dst[dx], PixelMul32_2( src[dx], job->argb ) );
 | |
| 		}
 | |
| 		src = (u32*) ( (u8*) (src) + job->srcPitch );
 | |
| 		dst = (u32*) ( (u8*) (dst) + job->dstPitch );
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Blitter Operation
 | |
| enum eBlitter
 | |
| {
 | |
| 	BLITTER_INVALID = 0,
 | |
| 	BLITTER_COLOR,
 | |
| 	BLITTER_COLOR_ALPHA,
 | |
| 	BLITTER_TEXTURE,
 | |
| 	BLITTER_TEXTURE_ALPHA_BLEND,
 | |
| 	BLITTER_TEXTURE_ALPHA_COLOR_BLEND,
 | |
| 	BLITTER_TEXTURE_COMBINE_ALPHA,
 | |
| };
 | |
| 
 | |
| typedef void (*tExecuteBlit) ( const SBlitJob * job );
 | |
| 
 | |
| 
 | |
| /*!
 | |
| */
 | |
| struct blitterTable
 | |
| {
 | |
| 	eBlitter operation;
 | |
| 	s32 destFormat;
 | |
| 	s32 sourceFormat;
 | |
| 	tExecuteBlit func;
 | |
| };
 | |
| 
 | |
| static const blitterTable blitTable[] =
 | |
| {
 | |
| 	{ BLITTER_TEXTURE, -2, -2, executeBlit_TextureCopy_x_to_x },
 | |
| 	{ BLITTER_TEXTURE, video::ECF_A1R5G5B5, video::ECF_A8R8G8B8, executeBlit_TextureCopy_32_to_16 },
 | |
| 	{ BLITTER_TEXTURE, video::ECF_A1R5G5B5, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_16 },
 | |
| 	{ BLITTER_TEXTURE, video::ECF_A8R8G8B8, video::ECF_A1R5G5B5, executeBlit_TextureCopy_16_to_32 },
 | |
| 	{ BLITTER_TEXTURE, video::ECF_A8R8G8B8, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_32 },
 | |
| 	{ BLITTER_TEXTURE, video::ECF_R8G8B8, video::ECF_A1R5G5B5, executeBlit_TextureCopy_16_to_24 },
 | |
| 	{ BLITTER_TEXTURE, video::ECF_R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureCopy_32_to_24 },
 | |
| 	{ BLITTER_TEXTURE_ALPHA_BLEND, video::ECF_A1R5G5B5, video::ECF_A1R5G5B5, executeBlit_TextureBlend_16_to_16 },
 | |
| 	{ BLITTER_TEXTURE_ALPHA_BLEND, video::ECF_A8R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureBlend_32_to_32 },
 | |
| 	{ BLITTER_TEXTURE_ALPHA_COLOR_BLEND, video::ECF_A1R5G5B5, video::ECF_A1R5G5B5, executeBlit_TextureBlendColor_16_to_16 },
 | |
| 	{ BLITTER_TEXTURE_ALPHA_COLOR_BLEND, video::ECF_A8R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureBlendColor_32_to_32 },
 | |
| 	{ BLITTER_COLOR, video::ECF_A1R5G5B5, -1, executeBlit_Color_16_to_16 },
 | |
| 	{ BLITTER_COLOR, video::ECF_A8R8G8B8, -1, executeBlit_Color_32_to_32 },
 | |
| 	{ BLITTER_COLOR_ALPHA, video::ECF_A1R5G5B5, -1, executeBlit_ColorAlpha_16_to_16 },
 | |
| 	{ BLITTER_COLOR_ALPHA, video::ECF_A8R8G8B8, -1, executeBlit_ColorAlpha_32_to_32 },
 | |
| 	{ BLITTER_TEXTURE_COMBINE_ALPHA, video::ECF_A8R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureCombineColor_32_to_32 },
 | |
| 	{ BLITTER_TEXTURE_COMBINE_ALPHA, video::ECF_A8R8G8B8, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_32 },
 | |
| 	{ BLITTER_TEXTURE_COMBINE_ALPHA, video::ECF_R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureCombineColor_32_to_24 },
 | |
| 	{ BLITTER_TEXTURE_COMBINE_ALPHA, video::ECF_R8G8B8, video::ECF_R8G8B8, executeBlit_TextureCopy_x_to_x },
 | |
| 	{ BLITTER_TEXTURE_COMBINE_ALPHA, video::ECF_A1R5G5B5, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_16 },
 | |
| 	{ BLITTER_TEXTURE_COMBINE_ALPHA, video::ECF_A1R5G5B5, video::ECF_A1R5G5B5, executeBlit_TextureCombineColor_16_to_16 },
 | |
| 	{ BLITTER_TEXTURE_COMBINE_ALPHA, video::ECF_A1R5G5B5, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_16 },
 | |
| 	{ BLITTER_TEXTURE_COMBINE_ALPHA, video::ECF_R8G8B8, video::ECF_A1R5G5B5, executeBlit_TextureCombineColor_16_to_24 },
 | |
| 	{ BLITTER_INVALID, -1, -1, 0 }
 | |
| };
 | |
| 
 | |
| 
 | |
| static inline tExecuteBlit getBlitter2( eBlitter operation,const video::IImage * dest,const video::IImage * source )
 | |
| {
 | |
| 	video::ECOLOR_FORMAT sourceFormat = (video::ECOLOR_FORMAT) ( source ? source->getColorFormat() : -1 );
 | |
| 	video::ECOLOR_FORMAT destFormat = (video::ECOLOR_FORMAT) ( dest ? dest->getColorFormat() : -1 );
 | |
| 
 | |
| 	const blitterTable * b = blitTable;
 | |
| 
 | |
| 	while ( b->operation != BLITTER_INVALID )
 | |
| 	{
 | |
| 		if ( b->operation == operation )
 | |
| 		{
 | |
| 			if (( b->destFormat == -1 || b->destFormat == destFormat ) &&
 | |
| 				( b->sourceFormat == -1 || b->sourceFormat == sourceFormat ) )
 | |
| 					return b->func;
 | |
| 			else
 | |
| 			if ( b->destFormat == -2 && ( sourceFormat == destFormat ) )
 | |
| 					return b->func;
 | |
| 		}
 | |
| 		b += 1;
 | |
| 	}
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| // bounce clipping to texture
 | |
| inline void setClip(AbsRectangle &out, const core::rect<s32> *clip,
 | |
| 	const video::IImage* tex, s32 passnative, const core::dimension2d<u32>* tex_org)
 | |
| {
 | |
| 	if (0 == tex)
 | |
| 	{
 | |
| 		if (clip && passnative)
 | |
| 		{
 | |
| 			out.x0 = clip->UpperLeftCorner.X;
 | |
| 			out.x1 = clip->LowerRightCorner.X;
 | |
| 			out.y0 = clip->UpperLeftCorner.Y;
 | |
| 			out.y1 = clip->LowerRightCorner.Y;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			out.x0 = 0;
 | |
| 			out.x1 = 0;
 | |
| 			out.y0 = 0;
 | |
| 			out.y1 = 0;
 | |
| 		}
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	const s32 w = tex->getDimension().Width;
 | |
| 	const s32 h = tex->getDimension().Height;
 | |
| 
 | |
| 	//driver could have changed texture size.
 | |
| 	if (clip && tex_org && ((u32)w != tex_org->Width || (u32)h != tex_org->Height))
 | |
| 	{
 | |
| 		out.x0 = core::s32_clamp((clip->UpperLeftCorner.X*w) / tex_org->Width, 0, w - 1);
 | |
| 		out.x1 = core::s32_clamp((clip->LowerRightCorner.X*w) / tex_org->Width, out.x0, w);
 | |
| 		out.y0 = core::s32_clamp((clip->UpperLeftCorner.Y*h) / tex_org->Height, 0, h - 1);
 | |
| 		out.y1 = core::s32_clamp((clip->LowerRightCorner.Y*h) / tex_org->Height, out.y0, h);
 | |
| 	}
 | |
| 	else if (clip)
 | |
| 	{
 | |
| 		//y-1 to prevent starting on illegal memory (not ideal!).
 | |
| 		out.x0 = core::s32_clamp(clip->UpperLeftCorner.X, 0, w - 1);
 | |
| 		out.x1 = core::s32_clamp(clip->LowerRightCorner.X, passnative ? 0 : out.x0, w);
 | |
| 		out.y0 = core::s32_clamp(clip->UpperLeftCorner.Y, 0, h - 1);
 | |
| 		out.y1 = core::s32_clamp(clip->LowerRightCorner.Y, passnative ? 0 : out.y0, h);
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		out.x0 = 0;
 | |
| 		out.y0 = 0;
 | |
| 		out.x1 = w;
 | |
| 		out.y1 = h;
 | |
| 	}
 | |
| 
 | |
| }
 | |
| 
 | |
| /*!
 | |
| 	a generic 2D Blitter
 | |
| */
 | |
| static s32 Blit(eBlitter operation,
 | |
| 		video::IImage * dest,
 | |
| 		const core::rect<s32> *destClipping,
 | |
| 		const core::position2d<s32> *destPos,
 | |
| 		video::IImage * const source,
 | |
| 		const core::rect<s32> *sourceClipping,
 | |
| 		u32 argb)
 | |
| {
 | |
| 	tExecuteBlit blitter = getBlitter2( operation, dest, source );
 | |
| 	if ( 0 == blitter )
 | |
| 	{
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	// Clipping
 | |
| 	AbsRectangle sourceClip;
 | |
| 	AbsRectangle destClip;
 | |
| 	AbsRectangle v;
 | |
| 
 | |
| 	SBlitJob job;
 | |
| 
 | |
| 	setClip ( sourceClip, sourceClipping, source, 1,0 );
 | |
| 	setClip ( destClip, destClipping, dest, 0,0 );
 | |
| 
 | |
| 	v.x0 = destPos ? destPos->X : 0;
 | |
| 	v.y0 = destPos ? destPos->Y : 0;
 | |
| 	v.x1 = v.x0 + ( sourceClip.x1 - sourceClip.x0 );
 | |
| 	v.y1 = v.y0 + ( sourceClip.y1 - sourceClip.y0 );
 | |
| 
 | |
| 	if ( !intersect( job.Dest, destClip, v ) )
 | |
| 		return 0;
 | |
| 
 | |
| 	job.width = job.Dest.x1 - job.Dest.x0;
 | |
| 	job.height = job.Dest.y1 - job.Dest.y0;
 | |
| 
 | |
| 	job.Source.x0 = sourceClip.x0 + ( job.Dest.x0 - v.x0 );
 | |
| 	job.Source.x1 = job.Source.x0 + job.width;
 | |
| 	job.Source.y0 = sourceClip.y0 + ( job.Dest.y0 - v.y0 );
 | |
| 	job.Source.y1 = job.Source.y0 + job.height;
 | |
| 
 | |
| 	job.argb = argb;
 | |
| 
 | |
| 	job.stretch = false;
 | |
| 	job.x_stretch = 1.f;
 | |
| 	job.y_stretch = 1.f;
 | |
| 
 | |
| 	if ( source )
 | |
| 	{
 | |
| 		job.srcPitch = source->getPitch();
 | |
| 		job.srcPixelMul = source->getBytesPerPixel();
 | |
| 		job.src = (void*) ( (u8*) source->getData() + ( job.Source.y0 * job.srcPitch ) + ( job.Source.x0 * job.srcPixelMul ) );
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		// use srcPitch for color operation on dest
 | |
| 		job.srcPitch = job.width * dest->getBytesPerPixel();
 | |
| 	}
 | |
| 
 | |
| 	job.dstPitch = dest->getPitch();
 | |
| 	job.dstPixelMul = dest->getBytesPerPixel();
 | |
| 	job.dst = (void*) ( (u8*) dest->getData() + ( job.Dest.y0 * job.dstPitch ) + ( job.Dest.x0 * job.dstPixelMul ) );
 | |
| 
 | |
| 	blitter( &job );
 | |
| 
 | |
| 	return 1;
 | |
| }
 | |
| 
 | |
| }
 |