1
// Copyright (C) 2002-2011 Nikolaus Gebhardt / Thomas Alten
2
// This file is part of the "Irrlicht Engine".
3
// For conditions of distribution and use, see copyright notice in irrlicht.h
5
#ifndef _C_BLIT_H_INCLUDED_
6
#define _C_BLIT_H_INCLUDED_
8
#include "SoftwareDriver2_helper.h"
36
SBlitJob() : stretch(false) {}
39
// Bitfields Cohen Sutherland
49
inline u32 GetClipCode( const AbsRectangle &r, const core::position2d<s32> &p )
51
u32 code = CLIPCODE_EMPTY;
57
code = CLIPCODE_RIGHT;
63
code |= CLIPCODE_BOTTOM;
70
Cohen Sutherland clipping
74
static int ClipLine(const AbsRectangle &clipping,
75
core::position2d<s32> &p0,
76
core::position2d<s32> &p1,
77
const core::position2d<s32>& p0_in,
78
const core::position2d<s32>& p1_in)
87
code0 = GetClipCode( clipping, p0 );
88
code1 = GetClipCode( clipping, p1 );
91
while ( code0 | code1 )
111
if ( (code & CLIPCODE_BOTTOM) == CLIPCODE_BOTTOM )
113
// clip bottom viewport
115
x = p0.X + ( p1.X - p0.X ) * ( y - p0.Y ) / ( p1.Y - p0.Y );
118
if ( (code & CLIPCODE_TOP) == CLIPCODE_TOP )
122
x = p0.X + ( p1.X - p0.X ) * ( y - p0.Y ) / ( p1.Y - p0.Y );
125
if ( (code & CLIPCODE_RIGHT) == CLIPCODE_RIGHT )
127
// clip right viewport
129
y = p0.Y + ( p1.Y - p0.Y ) * ( x - p0.X ) / ( p1.X - p0.X );
132
if ( (code & CLIPCODE_LEFT) == CLIPCODE_LEFT )
134
// clip left viewport
136
y = p0.Y + ( p1.Y - p0.Y ) * ( x - p0.X ) / ( p1.X - p0.X );
141
// modify first point
144
code0 = GetClipCode( clipping, p0 );
148
// modify second point
151
code1 = GetClipCode( clipping, p1 );
160
inline void GetClip(AbsRectangle &clipping, video::IImage * t)
164
clipping.x1 = t->getDimension().Width - 1;
165
clipping.y1 = t->getDimension().Height - 1;
169
return alpha in [0;256] Granularity from 32-Bit ARGB
170
add highbit alpha ( alpha > 127 ? + 1 )
172
static inline u32 extractAlpha(const u32 c)
174
return ( c >> 24 ) + ( c >> 31 );
178
return alpha in [0;255] Granularity and 32-Bit ARGB
179
add highbit alpha ( alpha > 127 ? + 1 )
181
static inline u32 packAlpha(const u32 c)
183
return (c > 127 ? c - 1 : c) << 24;
188
Scale Color by (1/value)
189
value 0 - 256 ( alpha )
191
inline u32 PixelLerp32(const u32 source, const u32 value)
193
u32 srcRB = source & 0x00FF00FF;
194
u32 srcXG = (source & 0xFF00FF00) >> 8;
205
return srcRB | srcXG;
211
static void RenderLine32_Decal(video::IImage *t,
212
const core::position2d<s32> &p0,
213
const core::position2d<s32> &p1,
216
s32 dx = p1.X - p0.X;
217
s32 dy = p1.Y - p0.Y;
225
s32 yInc = (s32) t->getPitch();
240
dst = (u32*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 2 ) );
261
dst = (u32*) ( (u8*) dst + xInc ); // x += xInc
265
dst = (u32*) ( (u8*) dst + yInc ); // y += yInc
277
static void RenderLine32_Blend(video::IImage *t,
278
const core::position2d<s32> &p0,
279
const core::position2d<s32> &p1,
282
s32 dx = p1.X - p0.X;
283
s32 dy = p1.Y - p0.Y;
291
s32 yInc = (s32) t->getPitch();
306
dst = (u32*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 2 ) );
323
const u32 packA = packAlpha ( alpha );
326
*dst = packA | PixelBlend32( *dst, argb, alpha );
328
dst = (u32*) ( (u8*) dst + xInc ); // x += xInc
332
dst = (u32*) ( (u8*) dst + yInc ); // y += yInc
343
static void RenderLine16_Decal(video::IImage *t,
344
const core::position2d<s32> &p0,
345
const core::position2d<s32> &p1,
348
s32 dx = p1.X - p0.X;
349
s32 dy = p1.Y - p0.Y;
357
s32 yInc = (s32) t->getPitch();
372
dst = (u16*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 1 ) );
393
dst = (u16*) ( (u8*) dst + xInc ); // x += xInc
397
dst = (u16*) ( (u8*) dst + yInc ); // y += yInc
408
static void RenderLine16_Blend(video::IImage *t,
409
const core::position2d<s32> &p0,
410
const core::position2d<s32> &p1,
414
s32 dx = p1.X - p0.X;
415
s32 dy = p1.Y - p0.Y;
423
s32 yInc = (s32) t->getPitch();
438
dst = (u16*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 1 ) );
455
const u16 packA = alpha ? 0x8000 : 0;
458
*dst = packA | PixelBlend16( *dst, argb, alpha );
460
dst = (u16*) ( (u8*) dst + xInc ); // x += xInc
464
dst = (u16*) ( (u8*) dst + yInc ); // y += yInc
476
static void executeBlit_TextureCopy_x_to_x( const SBlitJob * job )
478
const u32 w = job->width;
479
const u32 h = job->height;
482
const u32 *src = static_cast<const u32*>(job->src);
483
u32 *dst = static_cast<u32*>(job->dst);
484
const float wscale = 1.f/job->x_stretch;
485
const float hscale = 1.f/job->y_stretch;
487
for ( u32 dy = 0; dy < h; ++dy )
489
const u32 src_y = (u32)(dy*hscale);
490
src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y );
492
for ( u32 dx = 0; dx < w; ++dx )
494
const u32 src_x = (u32)(dx*wscale);
495
dst[dx] = src[src_x];
497
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
502
const u32 widthPitch = job->width * job->dstPixelMul;
503
const void *src = (void*) job->src;
504
void *dst = (void*) job->dst;
506
for ( u32 dy = 0; dy != h; ++dy )
508
memcpy( dst, src, widthPitch );
510
src = (void*) ( (u8*) (src) + job->srcPitch );
511
dst = (void*) ( (u8*) (dst) + job->dstPitch );
518
static void executeBlit_TextureCopy_32_to_16( const SBlitJob * job )
520
const u32 w = job->width;
521
const u32 h = job->height;
522
const u32 *src = static_cast<const u32*>(job->src);
523
u16 *dst = static_cast<u16*>(job->dst);
527
const float wscale = 1.f/job->x_stretch;
528
const float hscale = 1.f/job->y_stretch;
530
for ( u32 dy = 0; dy < h; ++dy )
532
const u32 src_y = (u32)(dy*hscale);
533
src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y );
535
for ( u32 dx = 0; dx < w; ++dx )
537
const u32 src_x = (u32)(dx*wscale);
538
//16 bit Blitter depends on pre-multiplied color
539
const u32 s = PixelLerp32( src[src_x] | 0xFF000000, extractAlpha( src[src_x] ) );
540
dst[dx] = video::A8R8G8B8toA1R5G5B5( s );
542
dst = (u16*) ( (u8*) (dst) + job->dstPitch );
547
for ( u32 dy = 0; dy != h; ++dy )
549
for ( u32 dx = 0; dx != w; ++dx )
551
//16 bit Blitter depends on pre-multiplied color
552
const u32 s = PixelLerp32( src[dx] | 0xFF000000, extractAlpha( src[dx] ) );
553
dst[dx] = video::A8R8G8B8toA1R5G5B5( s );
556
src = (u32*) ( (u8*) (src) + job->srcPitch );
557
dst = (u16*) ( (u8*) (dst) + job->dstPitch );
564
static void executeBlit_TextureCopy_24_to_16( const SBlitJob * job )
566
const u32 w = job->width;
567
const u32 h = job->height;
568
const u8 *src = static_cast<const u8*>(job->src);
569
u16 *dst = static_cast<u16*>(job->dst);
573
const float wscale = 3.f/job->x_stretch;
574
const float hscale = 1.f/job->y_stretch;
576
for ( u32 dy = 0; dy < h; ++dy )
578
const u32 src_y = (u32)(dy*hscale);
579
src = (u8*)(job->src) + job->srcPitch*src_y;
581
for ( u32 dx = 0; dx < w; ++dx )
583
const u8* src_x = src+(u32)(dx*wscale);
584
dst[dx] = video::RGBA16(src_x[0], src_x[1], src_x[2]);
586
dst = (u16*) ( (u8*) (dst) + job->dstPitch );
591
for ( u32 dy = 0; dy != h; ++dy )
594
for ( u32 dx = 0; dx != w; ++dx )
596
dst[dx] = video::RGBA16(s[0], s[1], s[2]);
600
src = src+job->srcPitch;
601
dst = (u16*) ( (u8*) (dst) + job->dstPitch );
609
static void executeBlit_TextureCopy_16_to_32( const SBlitJob * job )
611
const u32 w = job->width;
612
const u32 h = job->height;
613
const u16 *src = static_cast<const u16*>(job->src);
614
u32 *dst = static_cast<u32*>(job->dst);
618
const float wscale = 1.f/job->x_stretch;
619
const float hscale = 1.f/job->y_stretch;
621
for ( u32 dy = 0; dy < h; ++dy )
623
const u32 src_y = (u32)(dy*hscale);
624
src = (u16*) ( (u8*) (job->src) + job->srcPitch*src_y );
626
for ( u32 dx = 0; dx < w; ++dx )
628
const u32 src_x = (u32)(dx*wscale);
629
dst[dx] = video::A1R5G5B5toA8R8G8B8(src[src_x]);
631
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
636
for ( u32 dy = 0; dy != h; ++dy )
638
for ( u32 dx = 0; dx != w; ++dx )
640
dst[dx] = video::A1R5G5B5toA8R8G8B8( src[dx] );
643
src = (u16*) ( (u8*) (src) + job->srcPitch );
644
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
649
static void executeBlit_TextureCopy_16_to_24( const SBlitJob * job )
651
const u32 w = job->width;
652
const u32 h = job->height;
653
const u16 *src = static_cast<const u16*>(job->src);
654
u8 *dst = static_cast<u8*>(job->dst);
658
const float wscale = 1.f/job->x_stretch;
659
const float hscale = 1.f/job->y_stretch;
661
for ( u32 dy = 0; dy < h; ++dy )
663
const u32 src_y = (u32)(dy*hscale);
664
src = (u16*) ( (u8*) (job->src) + job->srcPitch*src_y );
666
for ( u32 dx = 0; dx < w; ++dx )
668
const u32 src_x = (u32)(dx*wscale);
669
u32 color = video::A1R5G5B5toA8R8G8B8(src[src_x]);
670
u8 * writeTo = &dst[dx * 3];
671
*writeTo++ = (color >> 16)& 0xFF;
672
*writeTo++ = (color >> 8) & 0xFF;
673
*writeTo++ = color & 0xFF;
675
dst += job->dstPitch;
680
for ( u32 dy = 0; dy != h; ++dy )
682
for ( u32 dx = 0; dx != w; ++dx )
684
u32 color = video::A1R5G5B5toA8R8G8B8(src[dx]);
685
u8 * writeTo = &dst[dx * 3];
686
*writeTo++ = (color >> 16)& 0xFF;
687
*writeTo++ = (color >> 8) & 0xFF;
688
*writeTo++ = color & 0xFF;
691
src = (u16*) ( (u8*) (src) + job->srcPitch );
692
dst += job->dstPitch;
699
static void executeBlit_TextureCopy_24_to_32( const SBlitJob * job )
701
const u32 w = job->width;
702
const u32 h = job->height;
703
const u8 *src = static_cast<const u8*>(job->src);
704
u32 *dst = static_cast<u32*>(job->dst);
708
const float wscale = 3.f/job->x_stretch;
709
const float hscale = 1.f/job->y_stretch;
711
for ( u32 dy = 0; dy < h; ++dy )
713
const u32 src_y = (u32)(dy*hscale);
714
src = (const u8*)job->src+(job->srcPitch*src_y);
716
for ( u32 dx = 0; dx < w; ++dx )
718
const u8* s = src+(u32)(dx*wscale);
719
dst[dx] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2];
721
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
726
for ( s32 dy = 0; dy != job->height; ++dy )
730
for ( s32 dx = 0; dx != job->width; ++dx )
732
dst[dx] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2];
736
src = src + job->srcPitch;
737
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
742
static void executeBlit_TextureCopy_32_to_24( const SBlitJob * job )
744
const u32 w = job->width;
745
const u32 h = job->height;
746
const u32 *src = static_cast<const u32*>(job->src);
747
u8 *dst = static_cast<u8*>(job->dst);
751
const float wscale = 1.f/job->x_stretch;
752
const float hscale = 1.f/job->y_stretch;
754
for ( u32 dy = 0; dy < h; ++dy )
756
const u32 src_y = (u32)(dy*hscale);
757
src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y);
759
for ( u32 dx = 0; dx < w; ++dx )
761
const u32 src_x = src[(u32)(dx*wscale)];
762
u8 * writeTo = &dst[dx * 3];
763
*writeTo++ = (src_x >> 16)& 0xFF;
764
*writeTo++ = (src_x >> 8) & 0xFF;
765
*writeTo++ = src_x & 0xFF;
767
dst += job->dstPitch;
772
for ( u32 dy = 0; dy != h; ++dy )
774
for ( u32 dx = 0; dx != w; ++dx )
776
u8 * writeTo = &dst[dx * 3];
777
*writeTo++ = (src[dx] >> 16)& 0xFF;
778
*writeTo++ = (src[dx] >> 8) & 0xFF;
779
*writeTo++ = src[dx] & 0xFF;
782
src = (u32*) ( (u8*) (src) + job->srcPitch );
783
dst += job->dstPitch;
790
static void executeBlit_TextureBlend_16_to_16( const SBlitJob * job )
792
const u32 w = job->width;
793
const u32 h = job->height;
794
const u32 rdx = w>>1;
796
const u32 *src = (u32*) job->src;
797
u32 *dst = (u32*) job->dst;
801
const float wscale = 1.f/job->x_stretch;
802
const float hscale = 1.f/job->y_stretch;
803
const u32 off = core::if_c_a_else_b(w&1, (u32)((w-1)*wscale), 0);
804
for ( u32 dy = 0; dy < h; ++dy )
806
const u32 src_y = (u32)(dy*hscale);
807
src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y );
809
for ( u32 dx = 0; dx < rdx; ++dx )
811
const u32 src_x = (u32)(dx*wscale);
812
dst[dx] = PixelBlend16_simd( dst[dx], src[src_x] );
816
((u16*) dst)[off] = PixelBlend16( ((u16*) dst)[off], ((u16*) src)[off] );
819
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
824
const u32 off = core::if_c_a_else_b(w&1, w-1, 0);
825
for (u32 dy = 0; dy != h; ++dy )
827
for (u32 dx = 0; dx != rdx; ++dx )
829
dst[dx] = PixelBlend16_simd( dst[dx], src[dx] );
834
((u16*) dst)[off] = PixelBlend16( ((u16*) dst)[off], ((u16*) src)[off] );
837
src = (u32*) ( (u8*) (src) + job->srcPitch );
838
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
845
static void executeBlit_TextureBlend_32_to_32( const SBlitJob * job )
847
const u32 w = job->width;
848
const u32 h = job->height;
849
const u32 *src = (u32*) job->src;
850
u32 *dst = (u32*) job->dst;
854
const float wscale = 1.f/job->x_stretch;
855
const float hscale = 1.f/job->y_stretch;
856
for ( u32 dy = 0; dy < h; ++dy )
858
const u32 src_y = (u32)(dy*hscale);
859
src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y );
861
for ( u32 dx = 0; dx < w; ++dx )
863
const u32 src_x = (u32)(dx*wscale);
864
dst[dx] = PixelBlend32( dst[dx], src[src_x] );
867
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
872
for ( u32 dy = 0; dy != h; ++dy )
874
for ( u32 dx = 0; dx != w; ++dx )
876
dst[dx] = PixelBlend32( dst[dx], src[dx] );
878
src = (u32*) ( (u8*) (src) + job->srcPitch );
879
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
886
static void executeBlit_TextureBlendColor_16_to_16( const SBlitJob * job )
888
u16 *src = (u16*) job->src;
889
u16 *dst = (u16*) job->dst;
891
u16 blend = video::A8R8G8B8toA1R5G5B5 ( job->argb );
892
for ( s32 dy = 0; dy != job->height; ++dy )
894
for ( s32 dx = 0; dx != job->width; ++dx )
896
if ( 0 == (src[dx] & 0x8000) )
899
dst[dx] = PixelMul16_2( src[dx], blend );
901
src = (u16*) ( (u8*) (src) + job->srcPitch );
902
dst = (u16*) ( (u8*) (dst) + job->dstPitch );
909
static void executeBlit_TextureBlendColor_32_to_32( const SBlitJob * job )
911
u32 *src = (u32*) job->src;
912
u32 *dst = (u32*) job->dst;
914
for ( s32 dy = 0; dy != job->height; ++dy )
916
for ( s32 dx = 0; dx != job->width; ++dx )
918
dst[dx] = PixelBlend32( dst[dx], PixelMul32_2( src[dx], job->argb ) );
920
src = (u32*) ( (u8*) (src) + job->srcPitch );
921
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
927
static void executeBlit_Color_16_to_16( const SBlitJob * job )
929
u16 *dst = (u16*) job->dst;
931
u16 c0 = video::A8R8G8B8toA1R5G5B5( job->argb );
932
u32 c = c0 | c0 << 16;
934
if ( 0 == (job->srcPitch & 3 ) )
936
for ( s32 dy = 0; dy != job->height; ++dy )
938
memset32( dst, c, job->srcPitch );
939
dst = (u16*) ( (u8*) (dst) + job->dstPitch );
944
s32 dx = job->width - 1;
946
for ( s32 dy = 0; dy != job->height; ++dy )
948
memset32( dst, c, job->srcPitch );
950
dst = (u16*) ( (u8*) (dst) + job->dstPitch );
958
static void executeBlit_Color_32_to_32( const SBlitJob * job )
960
u32 *dst = (u32*) job->dst;
962
for ( s32 dy = 0; dy != job->height; ++dy )
964
memset32( dst, job->argb, job->srcPitch );
965
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
971
static void executeBlit_ColorAlpha_16_to_16( const SBlitJob * job )
973
u16 *dst = (u16*) job->dst;
975
const u16 alpha = extractAlpha( job->argb ) >> 3;
978
const u32 src = video::A8R8G8B8toA1R5G5B5( job->argb );
980
for ( s32 dy = 0; dy != job->height; ++dy )
982
for ( s32 dx = 0; dx != job->width; ++dx )
984
dst[dx] = 0x8000 | PixelBlend16( dst[dx], src, alpha );
986
dst = (u16*) ( (u8*) (dst) + job->dstPitch );
992
static void executeBlit_ColorAlpha_32_to_32( const SBlitJob * job )
994
u32 *dst = (u32*) job->dst;
996
const u32 alpha = extractAlpha( job->argb );
997
const u32 src = job->argb;
999
for ( s32 dy = 0; dy != job->height; ++dy )
1001
for ( s32 dx = 0; dx != job->width; ++dx )
1003
dst[dx] = (job->argb & 0xFF000000 ) | PixelBlend32( dst[dx], src, alpha );
1005
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
1009
// Blitter Operation
1012
BLITTER_INVALID = 0,
1014
BLITTER_COLOR_ALPHA,
1016
BLITTER_TEXTURE_ALPHA_BLEND,
1017
BLITTER_TEXTURE_ALPHA_COLOR_BLEND
1020
typedef void (*tExecuteBlit) ( const SBlitJob * job );
1033
static const blitterTable blitTable[] =
1035
{ BLITTER_TEXTURE, -2, -2, executeBlit_TextureCopy_x_to_x },
1036
{ BLITTER_TEXTURE, video::ECF_A1R5G5B5, video::ECF_A8R8G8B8, executeBlit_TextureCopy_32_to_16 },
1037
{ BLITTER_TEXTURE, video::ECF_A1R5G5B5, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_16 },
1038
{ BLITTER_TEXTURE, video::ECF_A8R8G8B8, video::ECF_A1R5G5B5, executeBlit_TextureCopy_16_to_32 },
1039
{ BLITTER_TEXTURE, video::ECF_A8R8G8B8, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_32 },
1040
{ BLITTER_TEXTURE, video::ECF_R8G8B8, video::ECF_A1R5G5B5, executeBlit_TextureCopy_16_to_24 },
1041
{ BLITTER_TEXTURE, video::ECF_R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureCopy_32_to_24 },
1042
{ BLITTER_TEXTURE_ALPHA_BLEND, video::ECF_A1R5G5B5, video::ECF_A1R5G5B5, executeBlit_TextureBlend_16_to_16 },
1043
{ BLITTER_TEXTURE_ALPHA_BLEND, video::ECF_A8R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureBlend_32_to_32 },
1044
{ BLITTER_TEXTURE_ALPHA_COLOR_BLEND, video::ECF_A1R5G5B5, video::ECF_A1R5G5B5, executeBlit_TextureBlendColor_16_to_16 },
1045
{ BLITTER_TEXTURE_ALPHA_COLOR_BLEND, video::ECF_A8R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureBlendColor_32_to_32 },
1046
{ BLITTER_COLOR, video::ECF_A1R5G5B5, -1, executeBlit_Color_16_to_16 },
1047
{ BLITTER_COLOR, video::ECF_A8R8G8B8, -1, executeBlit_Color_32_to_32 },
1048
{ BLITTER_COLOR_ALPHA, video::ECF_A1R5G5B5, -1, executeBlit_ColorAlpha_16_to_16 },
1049
{ BLITTER_COLOR_ALPHA, video::ECF_A8R8G8B8, -1, executeBlit_ColorAlpha_32_to_32 },
1050
{ BLITTER_INVALID, -1, -1, 0 }
1054
static inline tExecuteBlit getBlitter2( eBlitter operation,const video::IImage * dest,const video::IImage * source )
1056
video::ECOLOR_FORMAT sourceFormat = (video::ECOLOR_FORMAT) ( source ? source->getColorFormat() : -1 );
1057
video::ECOLOR_FORMAT destFormat = (video::ECOLOR_FORMAT) ( dest ? dest->getColorFormat() : -1 );
1059
const blitterTable * b = blitTable;
1061
while ( b->operation != BLITTER_INVALID )
1063
if ( b->operation == operation )
1065
if (( b->destFormat == -1 || b->destFormat == destFormat ) &&
1066
( b->sourceFormat == -1 || b->sourceFormat == sourceFormat ) )
1069
if ( b->destFormat == -2 && ( sourceFormat == destFormat ) )
1078
// bounce clipping to texture
1079
inline void setClip ( AbsRectangle &out, const core::rect<s32> *clip,
1080
const video::IImage * tex, s32 passnative )
1082
if ( clip && 0 == tex && passnative )
1084
out.x0 = clip->UpperLeftCorner.X;
1085
out.x1 = clip->LowerRightCorner.X;
1086
out.y0 = clip->UpperLeftCorner.Y;
1087
out.y1 = clip->LowerRightCorner.Y;
1091
const s32 w = tex ? tex->getDimension().Width : 0;
1092
const s32 h = tex ? tex->getDimension().Height : 0;
1095
out.x0 = core::s32_clamp ( clip->UpperLeftCorner.X, 0, w );
1096
out.x1 = core::s32_clamp ( clip->LowerRightCorner.X, out.x0, w );
1097
out.y0 = core::s32_clamp ( clip->UpperLeftCorner.Y, 0, h );
1098
out.y1 = core::s32_clamp ( clip->LowerRightCorner.Y, out.y0, h );
1111
a generic 2D Blitter
1113
static s32 Blit(eBlitter operation,
1114
video::IImage * dest,
1115
const core::rect<s32> *destClipping,
1116
const core::position2d<s32> *destPos,
1117
video::IImage * const source,
1118
const core::rect<s32> *sourceClipping,
1121
tExecuteBlit blitter = getBlitter2( operation, dest, source );
1128
AbsRectangle sourceClip;
1129
AbsRectangle destClip;
1134
setClip ( sourceClip, sourceClipping, source, 1 );
1135
setClip ( destClip, destClipping, dest, 0 );
1137
v.x0 = destPos ? destPos->X : 0;
1138
v.y0 = destPos ? destPos->Y : 0;
1139
v.x1 = v.x0 + ( sourceClip.x1 - sourceClip.x0 );
1140
v.y1 = v.y0 + ( sourceClip.y1 - sourceClip.y0 );
1142
if ( !intersect( job.Dest, destClip, v ) )
1145
job.width = job.Dest.x1 - job.Dest.x0;
1146
job.height = job.Dest.y1 - job.Dest.y0;
1148
job.Source.x0 = sourceClip.x0 + ( job.Dest.x0 - v.x0 );
1149
job.Source.x1 = job.Source.x0 + job.width;
1150
job.Source.y0 = sourceClip.y0 + ( job.Dest.y0 - v.y0 );
1151
job.Source.y1 = job.Source.y0 + job.height;
1157
job.srcPitch = source->getPitch();
1158
job.srcPixelMul = source->getBytesPerPixel();
1159
job.src = (void*) ( (u8*) source->lock() + ( job.Source.y0 * job.srcPitch ) + ( job.Source.x0 * job.srcPixelMul ) );
1163
// use srcPitch for color operation on dest
1164
job.srcPitch = job.width * dest->getBytesPerPixel();
1167
job.dstPitch = dest->getPitch();
1168
job.dstPixelMul = dest->getBytesPerPixel();
1169
job.dst = (void*) ( (u8*) dest->lock() + ( job.Dest.y0 * job.dstPitch ) + ( job.Dest.x0 * job.dstPixelMul ) );
1182
static s32 StretchBlit(eBlitter operation,
1183
video::IImage* dest, const core::rect<s32> *destRect,
1184
const core::rect<s32> *srcRect, video::IImage* const source,
1187
tExecuteBlit blitter = getBlitter2( operation, dest, source );
1196
setClip ( job.Source, srcRect, source, 1 );
1197
setClip ( job.Dest, destRect, dest, 0 );
1199
job.width = job.Dest.x1-job.Dest.x0;
1200
job.height = job.Dest.y1-job.Dest.y0;
1204
// use original dest size, despite any clipping
1205
job.x_stretch = (float)destRect->getWidth() / (float)(job.Source.x1-job.Source.x0);
1206
job.y_stretch = (float)destRect->getHeight() / (float)(job.Source.y1-job.Source.y0);
1207
job.stretch = (job.x_stretch != 1.f) || (job.y_stretch != 1.f);
1211
job.srcPitch = source->getPitch();
1212
job.srcPixelMul = source->getBytesPerPixel();
1213
job.src = (void*) ( (u8*) source->lock() + ( job.Source.y0 * job.srcPitch ) + ( job.Source.x0 * job.srcPixelMul ) );
1217
// use srcPitch for color operation on dest
1218
job.srcPitch = job.width * dest->getBytesPerPixel();
1221
job.dstPitch = dest->getPitch();
1222
job.dstPixelMul = dest->getBytesPerPixel();
1223
job.dst = (void*) ( (u8*) dest->lock() + ( job.Dest.y0 * job.dstPitch ) + ( job.Dest.x0 * job.dstPixelMul ) );
1237
// Methods for Software drivers
1238
//! draws a rectangle
1239
static void drawRectangle(video::IImage* img, const core::rect<s32>& rect, const video::SColor &color)
1241
Blit(color.getAlpha() == 0xFF ? BLITTER_COLOR : BLITTER_COLOR_ALPHA,
1242
img, 0, &rect.UpperLeftCorner, 0, &rect, color.color);
1246
//! draws a line from to with color
1247
static void drawLine(video::IImage* img, const core::position2d<s32>& from,
1248
const core::position2d<s32>& to, const video::SColor &color)
1253
core::position2d<s32> p[2];
1254
if (ClipLine( clip, p[0], p[1], from, to))
1256
u32 alpha = extractAlpha(color.color);
1258
switch(img->getColorFormat())
1260
case video::ECF_A1R5G5B5:
1263
RenderLine16_Decal(img, p[0], p[1], video::A8R8G8B8toA1R5G5B5(color.color));
1267
RenderLine16_Blend(img, p[0], p[1], video::A8R8G8B8toA1R5G5B5(color.color), alpha >> 3);
1270
case video::ECF_A8R8G8B8:
1273
RenderLine32_Decal(img, p[0], p[1], color.color);
1277
RenderLine32_Blend(img, p[0], p[1], color.color, alpha);