1 // Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten
\r
2 // This file is part of the "Irrlicht Engine".
\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
\r
7 - changed behavior for log2 textures ( replaced multiplies by shift )
\r
10 #ifndef __S_VIDEO_2_SOFTWARE_HELPER_H_INCLUDED__
\r
11 #define __S_VIDEO_2_SOFTWARE_HELPER_H_INCLUDED__
\r
13 #include "SoftwareDriver2_compile_config.h"
\r
14 #include "irrMath.h"
\r
15 #include "irrMathFastCompat.h"
\r
16 #include "CSoftwareTexture2.h"
\r
17 #include "SMaterial.h"
\r
23 // supporting different packed pixel needs many defines...
\r
25 #ifdef SOFTWARE_DRIVER_2_32BIT
\r
26 typedef u32 tVideoSample;
\r
28 #define MASK_A 0xFF000000
\r
29 #define MASK_R 0x00FF0000
\r
30 #define MASK_G 0x0000FF00
\r
31 #define MASK_B 0x000000FF
\r
38 #define COLOR_MAX 0xFF
\r
39 #define COLOR_MAX_LOG2 8
\r
40 #define COLOR_BRIGHT_WHITE 0xFFFFFFFF
\r
42 #define VIDEO_SAMPLE_GRANULARITY 2
\r
45 typedef u16 tVideoSample;
\r
47 #define MASK_A 0x8000
\r
48 #define MASK_R 0x7C00
\r
49 #define MASK_G 0x03E0
\r
50 #define MASK_B 0x001F
\r
57 #define COLOR_MAX 0x1F
\r
58 #define COLOR_MAX_LOG2 5
\r
59 #define COLOR_BRIGHT_WHITE 0xFFFF
\r
60 #define VIDEO_SAMPLE_GRANULARITY 1
\r
67 // ----------------------- Generic ----------------------------------
\r
69 //! a more useful memset for pixel
\r
70 // (standard memset only works with 8-bit values)
\r
71 inline void memset32(void * dest, const u32 value, u32 bytesize)
\r
73 u32 * d = (u32*) dest;
\r
77 // loops unrolled to reduce the number of increments by factor ~8.
\r
78 i = bytesize >> (2 + 3);
\r
95 i = (bytesize >> 2 ) & 7;
\r
104 //! a more useful memset for pixel
\r
105 // (standard memset only works with 8-bit values)
\r
106 inline void memset16(void * dest, const u16 value, u32 bytesize)
\r
108 u16 * d = (u16*) dest;
\r
112 // loops unrolled to reduce the number of increments by factor ~8.
\r
113 i = bytesize >> (1 + 3);
\r
130 i = (bytesize >> 1 ) & 7;
\r
140 use biased loop counter
\r
141 --> 0 byte copy is forbidden
\r
143 REALINLINE void memcpy32_small ( void * dest, const void *source, u32 bytesize )
\r
145 u32 c = bytesize >> 2;
\r
149 ((u32*) dest ) [ c-1 ] = ((u32*) source) [ c-1 ];
\r
156 // integer log2 of a float ieee 754. TODO: non ieee floating point
\r
157 static inline s32 s32_log2_f32( f32 f)
\r
160 return ((x & 0x7F800000) >> 23) - 127;
\r
163 static inline s32 s32_log2_s32(u32 x)
\r
165 return s32_log2_f32( (f32) x);
\r
168 static inline s32 s32_abs(s32 x)
\r
171 return (x ^ b ) - b;
\r
175 //! conditional set based on mask and arithmetic shift
\r
176 REALINLINE u32 if_mask_a_else_b ( const u32 mask, const u32 a, const u32 b )
\r
178 return ( mask & ( a ^ b ) ) ^ b;
\r
181 // ------------------ Video---------------------------------------
\r
183 Pixel = dest * ( 1 - alpha ) + source * alpha
\r
186 REALINLINE u32 PixelBlend32 ( const u32 c2, const u32 c1, u32 alpha )
\r
188 u32 srcRB = c1 & 0x00FF00FF;
\r
189 u32 srcXG = c1 & 0x0000FF00;
\r
191 u32 dstRB = c2 & 0x00FF00FF;
\r
192 u32 dstXG = c2 & 0x0000FF00;
\r
195 u32 rb = srcRB - dstRB;
\r
196 u32 xg = srcXG - dstXG;
\r
213 Pixel = dest * ( 1 - alpha ) + source * alpha
\r
216 inline u16 PixelBlend16 ( const u16 c2, const u32 c1, const u16 alpha )
\r
218 const u16 srcRB = c1 & 0x7C1F;
\r
219 const u16 srcXG = c1 & 0x03E0;
\r
221 const u16 dstRB = c2 & 0x7C1F;
\r
222 const u16 dstXG = c2 & 0x03E0;
\r
224 u32 rb = srcRB - dstRB;
\r
225 u32 xg = srcXG - dstXG;
\r
238 return (u16)(rb | xg);
\r
242 Pixel = c0 * (c1/31). c0 Alpha retain
\r
244 inline u16 PixelMul16 ( const u16 c0, const u16 c1)
\r
246 return (u16)((( ( (c0 & 0x7C00) * (c1 & 0x7C00) ) & 0x3E000000 ) >> 15 ) |
\r
247 (( ( (c0 & 0x03E0) * (c1 & 0x03E0) ) & 0x000F8000 ) >> 10 ) |
\r
248 (( ( (c0 & 0x001F) * (c1 & 0x001F) ) & 0x000003E0 ) >> 5 ) |
\r
253 Pixel = c0 * (c1/31).
\r
255 inline u16 PixelMul16_2 ( u16 c0, u16 c1)
\r
257 return (u16)(( ( (c0 & 0x7C00) * (c1 & 0x7C00) ) & 0x3E000000 ) >> 15 |
\r
258 ( ( (c0 & 0x03E0) * (c1 & 0x03E0) ) & 0x000F8000 ) >> 10 |
\r
259 ( ( (c0 & 0x001F) * (c1 & 0x001F) ) & 0x000003E0 ) >> 5 |
\r
260 ( c0 & c1 & 0x8000));
\r
264 Pixel = c0 * (c1/255). c0 Alpha Retain
\r
266 REALINLINE u32 PixelMul32 ( const u32 c0, const u32 c1)
\r
268 return (c0 & 0xFF000000) |
\r
269 (( ( (c0 & 0x00FF0000) >> 12 ) * ( (c1 & 0x00FF0000) >> 12 ) ) & 0x00FF0000 ) |
\r
270 (( ( (c0 & 0x0000FF00) * (c1 & 0x0000FF00) ) >> 16 ) & 0x0000FF00 ) |
\r
271 (( ( (c0 & 0x000000FF) * (c1 & 0x000000FF) ) >> 8 ) & 0x000000FF);
\r
275 Pixel = c0 * (c1/255).
\r
277 REALINLINE u32 PixelMul32_2 ( const u32 c0, const u32 c1)
\r
279 return (( ( (c0 & 0xFF000000) >> 16 ) * ( (c1 & 0xFF000000) >> 16 ) ) & 0xFF000000 ) |
\r
280 (( ( (c0 & 0x00FF0000) >> 12 ) * ( (c1 & 0x00FF0000) >> 12 ) ) & 0x00FF0000 ) |
\r
281 (( ( (c0 & 0x0000FF00) * (c1 & 0x0000FF00) ) >> 16 ) & 0x0000FF00 ) |
\r
282 (( ( (c0 & 0x000000FF) * (c1 & 0x000000FF) ) >> 8 ) & 0x000000FF);
\r
286 Pixel = clamp ( c0 + c1, 0, 255 )
\r
288 REALINLINE u32 PixelAdd32 ( const u32 c2, const u32 c1)
\r
290 u32 sum = ( c2 & 0x00FFFFFF ) + ( c1 & 0x00FFFFFF );
\r
291 u32 low_bits = ( c2 ^ c1 ) & 0x00010101;
\r
292 s32 carries = ( sum - low_bits ) & 0x01010100;
\r
293 u32 modulo = sum - carries;
\r
294 u32 clamp = carries - ( carries >> 8 );
\r
295 return modulo | clamp;
\r
300 // 1 - Bit Alpha Blending
\r
301 inline u16 PixelBlend16 ( const u16 destination, const u16 source )
\r
303 if((source & 0x8000) == 0x8000)
\r
304 return source; // The source is visible, so use it.
\r
306 return destination; // The source is transparent, so use the destination.
\r
309 // 1 - Bit Alpha Blending 16Bit SIMD
\r
310 inline u32 PixelBlend16_simd ( const u32 destination, const u32 source )
\r
312 switch(source & 0x80008000)
\r
314 case 0x80008000: // Both source pixels are visible
\r
317 case 0x80000000: // Only the first source pixel is visible
\r
318 return (source & 0xFFFF0000) | (destination & 0x0000FFFF);
\r
320 case 0x00008000: // Only the second source pixel is visible.
\r
321 return (destination & 0xFFFF0000) | (source & 0x0000FFFF);
\r
323 default: // Neither source pixel is visible.
\r
324 return destination;
\r
329 // 1 - Bit Alpha Blending
\r
330 inline u16 PixelBlend16 ( const u16 c2, const u16 c1 )
\r
332 u16 mask = ((c1 & 0x8000) >> 15 ) + 0x7fff;
\r
333 return (c2 & mask ) | ( c1 & ~mask );
\r
336 // 1 - Bit Alpha Blending 16Bit SIMD
\r
337 inline u32 PixelBlend16_simd ( const u32 c2, const u32 c1 )
\r
339 u32 mask = ((c1 & 0x80008000) >> 15 ) + 0x7fff7fff;
\r
340 return (c2 & mask ) | ( c1 & ~mask );
\r
346 Pixel = dest * ( 1 - SourceAlpha ) + source * SourceAlpha (OpenGL blending)
\r
348 inline u32 PixelBlend32 ( const u32 c2, const u32 c1 )
\r
351 u32 alpha = c1 & 0xFF000000;
\r
355 if ( 0xFF000000 == alpha )
\r
362 // add highbit alpha, if ( alpha > 127 ) alpha += 1;
\r
363 alpha += ( alpha >> 7);
\r
365 u32 srcRB = c1 & 0x00FF00FF;
\r
366 u32 srcXG = c1 & 0x0000FF00;
\r
368 u32 dstRB = c2 & 0x00FF00FF;
\r
369 u32 dstXG = c2 & 0x0000FF00;
\r
372 u32 rb = srcRB - dstRB;
\r
373 u32 xg = srcXG - dstXG;
\r
386 return (c1 & 0xFF000000) | rb | xg;
\r
391 color = sourceAlpha > 0 ? source, else dest
\r
392 alpha = max(destAlpha, sourceAlpha)
\r
394 inline u16 PixelCombine16 ( const u16 c2, const u16 c1 )
\r
396 if ( video::getAlpha(c1) > 0 )
\r
404 color = dest * ( 1 - SourceAlpha ) + source * SourceAlpha,
\r
405 alpha = destAlpha * ( 1 - SourceAlpha ) + sourceAlpha
\r
407 where "1" means "full scale" (255)
\r
409 inline u32 PixelCombine32 ( const u32 c2, const u32 c1 )
\r
412 u32 alpha = c1 & 0xFF000000;
\r
416 if ( 0xFF000000 == alpha )
\r
423 // add highbit alpha, if ( alpha > 127 ) alpha += 1;
\r
424 // stretches [0;255] to [0;256] to avoid division by 255. use division 256 == shr 8
\r
425 alpha += ( alpha >> 7);
\r
427 u32 srcRB = c1 & 0x00FF00FF;
\r
428 u32 srcXG = c1 & 0x0000FF00;
\r
430 u32 dstRB = c2 & 0x00FF00FF;
\r
431 u32 dstXG = c2 & 0x0000FF00;
\r
434 u32 rb = srcRB - dstRB;
\r
435 u32 xg = srcXG - dstXG;
\r
450 u32 blendAlpha_fix8 = (sa*256 + da*(256-alpha))>>8;
\r
451 return blendAlpha_fix8 << 24 | rb | xg;
\r
456 // ------------------ Fix Point ----------------------------------
\r
458 typedef s32 tFixPoint;
\r
459 typedef u32 tFixPointu;
\r
463 #define FIX_POINT_PRE 12
\r
464 #define FIX_POINT_FRACT_MASK 0xFFF
\r
465 #define FIX_POINT_SIGNED_MASK 0xFFFFF000
\r
466 #define FIX_POINT_UNSIGNED_MASK 0x7FFFF000
\r
467 #define FIX_POINT_ONE 0x1000
\r
468 #define FIX_POINT_ZERO_DOT_FIVE 0x0800
\r
469 #define FIX_POINT_F32_MUL 4096.f
\r
474 #define FIX_POINT_PRE 10
\r
475 #define FIX_POINT_FRACT_MASK 0x3FF
\r
476 #define FIX_POINT_SIGNED_MASK 0xFFFFFC00
\r
477 #define FIX_POINT_UNSIGNED_MASK 0x7FFFFE00
\r
478 #define FIX_POINT_ONE 0x400
\r
479 #define FIX_POINT_ZERO_DOT_FIVE 0x200
\r
480 #define FIX_POINT_F32_MUL 1024.f
\r
485 #define FIX_POINT_PRE 9
\r
486 #define FIX_POINT_FRACT_MASK 0x1FF
\r
487 #define FIX_POINT_SIGNED_MASK 0xFFFFFE00
\r
488 #define FIX_POINT_UNSIGNED_MASK 0x7FFFFE00
\r
489 #define FIX_POINT_ONE 0x200
\r
490 #define FIX_POINT_ZERO_DOT_FIVE 0x100
\r
491 #define FIX_POINT_F32_MUL 512.f
\r
496 #define FIX_POINT_PRE 7
\r
497 #define FIX_POINT_FRACT_MASK 0x7F
\r
498 #define FIX_POINT_SIGNED_MASK 0xFFFFFF80
\r
499 #define FIX_POINT_UNSIGNED_MASK 0x7FFFFF80
\r
500 #define FIX_POINT_ONE 0x80
\r
501 #define FIX_POINT_ZERO_DOT_FIVE 0x40
\r
502 #define FIX_POINT_F32_MUL 128.f
\r
505 #define FIXPOINT_COLOR_MAX ( COLOR_MAX << FIX_POINT_PRE )
\r
506 #define FIX_POINT_HALF_COLOR ( (tFixPoint) ( ((f32) COLOR_MAX / 2.f * FIX_POINT_F32_MUL ) ) )
\r
510 convert signed integer to fixpoint
\r
512 inline tFixPoint s32_to_fixPoint (const s32 x)
\r
514 return x << FIX_POINT_PRE;
\r
517 inline tFixPointu u32_to_fixPoint (const u32 x)
\r
519 return x << FIX_POINT_PRE;
\r
522 inline u32 fixPointu_to_u32 (const tFixPointu x)
\r
524 return x >> FIX_POINT_PRE;
\r
529 #define fix_inverse32(x) (FIX_POINT_F32_MUL / (x))
\r
533 convert float to fixpoint
\r
534 fast convert (fistp on x86) HAS to be used..
\r
535 hints: compileflag /QIfist for msvc7. msvc 8.0 has smth different
\r
536 others should use their favourite assembler..
\r
538 static inline int f_round2(f32 f)
\r
541 return IR(f) - 0x4b400000;
\r
545 convert f32 to Fix Point.
\r
546 multiply is needed anyway, so scale mulby
\r
548 REALINLINE tFixPoint tofix0 (const f32 x, const f32 mulby = FIX_POINT_F32_MUL )
\r
550 return (tFixPoint) (x * mulby);
\r
552 #define tofix(x,y) (tFixPoint)(x * y)
\r
555 Fix Point , Fix Point Multiply
\r
557 REALINLINE tFixPointu imulFixu(const tFixPointu x, const tFixPointu y)
\r
559 return (x * y) >> (tFixPointu) FIX_POINT_PRE;
\r
563 Fix Point , Fix Point Multiply
\r
565 REALINLINE tFixPoint imulFix(const tFixPoint x, const tFixPoint y)
\r
567 return ( x * y) >> ( FIX_POINT_PRE );
\r
571 Fix Point , Fix Point Multiply x * y * 2
\r
573 REALINLINE tFixPoint imulFix2(const tFixPoint x, const tFixPoint y)
\r
575 return ( x * y) >> ( FIX_POINT_PRE -1 );
\r
582 REALINLINE tFixPoint imulFix_tex1(const tFixPoint x, const tFixPoint y)
\r
584 return ( ( (tFixPointu) x >> 2 ) * ( (tFixPointu) y >> 2 ) ) >> (tFixPointu) ( FIX_POINT_PRE + 4 );
\r
590 REALINLINE tFixPoint imulFix_tex2(const tFixPoint x, const tFixPoint y)
\r
592 return ( ( (tFixPointu) x >> 2 ) * ( (tFixPointu) y >> 2 ) ) >> (tFixPointu) ( FIX_POINT_PRE + 3 );
\r
598 REALINLINE tFixPoint imulFix_tex4(const tFixPoint x, const tFixPoint y)
\r
600 #ifdef SOFTWARE_DRIVER_2_32BIT
\r
601 return ( ( (tFixPointu) x >> 2 ) * ( (tFixPointu) y >> 2 ) ) >> (tFixPointu) ( FIX_POINT_PRE + 2 );
\r
603 return ( x * y) >> ( FIX_POINT_PRE + ( VIDEO_SAMPLE_GRANULARITY * 3 ) );
\r
608 clamp FixPoint to maxcolor in FixPoint, min(a,31)
\r
610 REALINLINE tFixPoint clampfix_maxcolor ( const tFixPoint a)
\r
612 tFixPoint c = (a - FIXPOINT_COLOR_MAX) >> 31;
\r
613 return (a & c) | ( FIXPOINT_COLOR_MAX & ~c);
\r
617 clamp FixPoint to 0 in FixPoint, max(a,0)
\r
619 REALINLINE tFixPoint clampfix_mincolor ( const tFixPoint a)
\r
621 return a - ( a & ( a >> 31 ) );
\r
624 REALINLINE tFixPoint saturateFix ( const tFixPoint a)
\r
626 return clampfix_mincolor ( clampfix_maxcolor ( a ) );
\r
630 // rount fixpoint to int
\r
631 inline s32 roundFix ( const tFixPoint x )
\r
633 return ( x + FIX_POINT_ZERO_DOT_FIVE ) >> FIX_POINT_PRE;
\r
639 inline s32 f32_to_23Bits(const f32 x)
\r
642 return IR(y) & 0x7FFFFF; // last 23 bits
\r
646 return VideoSample from fixpoint
\r
648 REALINLINE tVideoSample fix_to_color ( const tFixPoint r, const tFixPoint g, const tFixPoint b )
\r
650 return ( FIXPOINT_COLOR_MAX & FIXPOINT_COLOR_MAX) << ( SHIFT_A - FIX_POINT_PRE ) |
\r
651 ( r & FIXPOINT_COLOR_MAX) << ( SHIFT_R - FIX_POINT_PRE ) |
\r
652 ( g & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - SHIFT_G ) |
\r
653 ( b & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - SHIFT_B );
\r
658 return VideoSample from fixpoint
\r
660 REALINLINE tVideoSample fix4_to_color ( const tFixPoint a, const tFixPoint r, const tFixPoint g, const tFixPoint b )
\r
662 return ( a & (FIX_POINT_FRACT_MASK - 1 )) << ( SHIFT_A - 1 ) |
\r
663 ( r & FIXPOINT_COLOR_MAX) << ( SHIFT_R - FIX_POINT_PRE ) |
\r
664 ( g & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - SHIFT_G ) |
\r
665 ( b & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - SHIFT_B );
\r
669 return fixpoint from VideoSample granularity COLOR_MAX
\r
671 inline void color_to_fix ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 )
\r
673 (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE );
\r
674 (tFixPointu&) g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G );
\r
675 (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B );
\r
679 return fixpoint from VideoSample granularity COLOR_MAX
\r
681 inline void color_to_fix ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 )
\r
683 (tFixPointu&) a = (t00 & MASK_A) >> ( SHIFT_A - FIX_POINT_PRE );
\r
684 (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE );
\r
685 (tFixPointu&) g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G );
\r
686 (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B );
\r
690 return fixpoint from VideoSample granularity 0..FIX_POINT_ONE
\r
692 inline void color_to_fix1 ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 )
\r
694 (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R + COLOR_MAX_LOG2 - FIX_POINT_PRE );
\r
695 (tFixPointu&) g = (t00 & MASK_G) >> ( SHIFT_G + COLOR_MAX_LOG2 - FIX_POINT_PRE );
\r
696 (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - COLOR_MAX_LOG2 );
\r
700 return fixpoint from VideoSample granularity 0..FIX_POINT_ONE
\r
702 inline void color_to_fix1 ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 )
\r
704 (tFixPointu&) a = (t00 & MASK_A) >> ( SHIFT_A + COLOR_MAX_LOG2 - FIX_POINT_PRE );
\r
705 (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R + COLOR_MAX_LOG2 - FIX_POINT_PRE );
\r
706 (tFixPointu&) g = (t00 & MASK_G) >> ( SHIFT_G + COLOR_MAX_LOG2 - FIX_POINT_PRE );
\r
707 (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - COLOR_MAX_LOG2 );
\r
712 // ----- FP24 ---- floating point z-buffer
\r
723 fp24 ( const f32 f )
\r
726 v = ((u32&)y) & 0x7FFFFF; // last 23 bits
\r
729 void operator=(const f32 f )
\r
732 v = ((u32&)y) & 0x7FFFFF; // last 23 bits
\r
735 void operator+=(const fp24 &other )
\r
740 operator f32 () const
\r
750 // ------------------------ Internal Texture -----------------------------
\r
752 struct sInternalTexture
\r
760 video::CSoftwareTexture2 *Texture;
\r
766 // get video sample plain
\r
767 inline tVideoSample getTexel_plain ( const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty )
\r
771 ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;
\r
772 ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );
\r
775 return *((tVideoSample*)( (u8*) t->data + ofs ));
\r
778 // get video sample to fix
\r
779 inline void getTexel_fix ( tFixPoint &r, tFixPoint &g, tFixPoint &b,
\r
780 const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty
\r
785 ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;
\r
786 ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );
\r
790 t00 = *((tVideoSample*)( (u8*) t->data + ofs ));
\r
792 r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE);
\r
793 g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G );
\r
794 b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B );
\r
798 // get video sample to fixpoint
\r
799 REALINLINE void getTexel_fix ( tFixPoint &a,
\r
800 const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty)
\r
804 ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;
\r
805 ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );
\r
809 t00 = *((tVideoSample*)( (u8*) t->data + ofs ));
\r
811 a = (t00 & MASK_A) >> ( SHIFT_A - FIX_POINT_PRE);
\r
815 inline void getSample_texture_dither ( tFixPoint &r, tFixPoint &g, tFixPoint &b,
\r
816 const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty,
\r
817 const u32 x, const u32 y
\r
820 static const tFixPointu dithermask[] =
\r
822 0x00,0x80,0x20,0xa0,
\r
823 0xc0,0x40,0xe0,0x60,
\r
824 0x30,0xb0,0x10,0x90,
\r
825 0xf0,0x70,0xd0,0x50
\r
828 const u32 index = (y & 3 ) << 2 | (x & 3);
\r
830 const tFixPointu _ntx = (tx + dithermask [ index ] ) & t->textureXMask;
\r
831 const tFixPointu _nty = (ty + dithermask [ index ] ) & t->textureYMask;
\r
834 ofs = ( ( _nty ) >> FIX_POINT_PRE ) << t->pitchlog2;
\r
835 ofs |= ( _ntx ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );
\r
838 const tVideoSample t00 = *((tVideoSample*)( (u8*) t->data + ofs ));
\r
840 (tFixPointu &) r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE);
\r
841 (tFixPointu &) g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G );
\r
842 (tFixPointu &) b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B );
\r
847 load a sample from internal texture at position tx,ty to fixpoint
\r
849 #ifndef SOFTWARE_DRIVER_2_BILINEAR
\r
851 // get Sample linear == getSample_fixpoint
\r
853 inline void getSample_texture ( tFixPoint &r, tFixPoint &g, tFixPoint &b,
\r
854 const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty
\r
859 ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;
\r
860 ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );
\r
863 const tVideoSample t00 = *((tVideoSample*)( (u8*) t->data + ofs ));
\r
865 (tFixPointu &) r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE);
\r
866 (tFixPointu &) g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G );
\r
867 (tFixPointu &) b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B );
\r
870 inline void getSample_texture ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b,
\r
871 const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty
\r
876 ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;
\r
877 ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );
\r
880 const tVideoSample t00 = *((tVideoSample*)( (u8*) t->data + ofs ));
\r
882 (tFixPointu &)a = (t00 & MASK_A) >> ( SHIFT_A - FIX_POINT_PRE);
\r
883 (tFixPointu &)r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE);
\r
884 (tFixPointu &)g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G );
\r
885 (tFixPointu &)b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B );
\r
892 // get sample linear
\r
893 REALINLINE void getSample_linear ( tFixPointu &r, tFixPointu &g, tFixPointu &b,
\r
894 const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty
\r
899 ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;
\r
900 ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );
\r
904 t00 = *((tVideoSample*)( (u8*) t->data + ofs ));
\r
906 r = (t00 & MASK_R) >> SHIFT_R;
\r
907 g = (t00 & MASK_G) >> SHIFT_G;
\r
908 b = (t00 & MASK_B);
\r
911 // get Sample bilinear
\r
912 REALINLINE void getSample_texture ( tFixPoint &r, tFixPoint &g, tFixPoint &b,
\r
913 const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty
\r
917 tFixPointu r00,g00,b00;
\r
918 tFixPointu r01,g01,b01;
\r
919 tFixPointu r10,g10,b10;
\r
920 tFixPointu r11,g11,b11;
\r
923 getSample_linear ( r00, g00, b00, t, tx,ty );
\r
924 getSample_linear ( r10, g10, b10, t, tx + FIX_POINT_ONE,ty );
\r
925 getSample_linear ( r01, g01, b01, t, tx,ty + FIX_POINT_ONE );
\r
926 getSample_linear ( r11, g11, b11, t, tx + FIX_POINT_ONE,ty + FIX_POINT_ONE );
\r
931 o0 = ( ( (ty) & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;
\r
932 o1 = ( ( (ty+FIX_POINT_ONE) & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;
\r
933 o2 = ( (tx) & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );
\r
934 o3 = ( (tx+FIX_POINT_ONE) & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );
\r
936 t00 = *((tVideoSample*)( (u8*) t->data + (o0 | o2 ) ));
\r
937 r00 = (t00 & MASK_R) >> SHIFT_R;
\r
938 g00 = (t00 & MASK_G) >> SHIFT_G;
\r
939 b00 = (t00 & MASK_B);
\r
941 t00 = *((tVideoSample*)( (u8*) t->data + (o0 | o3 ) ));
\r
942 r10 = (t00 & MASK_R) >> SHIFT_R;
\r
943 g10 = (t00 & MASK_G) >> SHIFT_G;
\r
944 b10 = (t00 & MASK_B);
\r
946 t00 = *((tVideoSample*)( (u8*) t->data + (o1 | o2 ) ));
\r
947 r01 = (t00 & MASK_R) >> SHIFT_R;
\r
948 g01 = (t00 & MASK_G) >> SHIFT_G;
\r
949 b01 = (t00 & MASK_B);
\r
951 t00 = *((tVideoSample*)( (u8*) t->data + (o1 | o3 ) ));
\r
952 r11 = (t00 & MASK_R) >> SHIFT_R;
\r
953 g11 = (t00 & MASK_G) >> SHIFT_G;
\r
954 b11 = (t00 & MASK_B);
\r
958 const tFixPointu txFract = tx & FIX_POINT_FRACT_MASK;
\r
959 const tFixPointu txFractInv = FIX_POINT_ONE - txFract;
\r
961 const tFixPointu tyFract = ty & FIX_POINT_FRACT_MASK;
\r
962 const tFixPointu tyFractInv = FIX_POINT_ONE - tyFract;
\r
964 const tFixPointu w00 = imulFixu ( txFractInv, tyFractInv );
\r
965 const tFixPointu w10 = imulFixu ( txFract , tyFractInv );
\r
966 const tFixPointu w01 = imulFixu ( txFractInv, tyFract );
\r
967 const tFixPointu w11 = imulFixu ( txFract , tyFract );
\r
987 // get sample linear
\r
988 REALINLINE void getSample_linear ( tFixPointu &a, tFixPointu &r, tFixPointu &g, tFixPointu &b,
\r
989 const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty
\r
994 ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;
\r
995 ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );
\r
999 t00 = *((tVideoSample*)( (u8*) t->data + ofs ));
\r
1001 a = (t00 & MASK_A) >> SHIFT_A;
\r
1002 r = (t00 & MASK_R) >> SHIFT_R;
\r
1003 g = (t00 & MASK_G) >> SHIFT_G;
\r
1004 b = (t00 & MASK_B);
\r
1007 // get Sample bilinear
\r
1008 REALINLINE void getSample_texture ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b,
\r
1009 const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty
\r
1013 tFixPointu a00, r00,g00,b00;
\r
1014 tFixPointu a01, r01,g01,b01;
\r
1015 tFixPointu a10, r10,g10,b10;
\r
1016 tFixPointu a11, r11,g11,b11;
\r
1018 getSample_linear ( a00, r00, g00, b00, t, tx,ty );
\r
1019 getSample_linear ( a10, r10, g10, b10, t, tx + FIX_POINT_ONE,ty );
\r
1020 getSample_linear ( a01, r01, g01, b01, t, tx,ty + FIX_POINT_ONE );
\r
1021 getSample_linear ( a11, r11, g11, b11, t, tx + FIX_POINT_ONE,ty + FIX_POINT_ONE );
\r
1023 const tFixPointu txFract = tx & FIX_POINT_FRACT_MASK;
\r
1024 const tFixPointu txFractInv = FIX_POINT_ONE - txFract;
\r
1026 const tFixPointu tyFract = ty & FIX_POINT_FRACT_MASK;
\r
1027 const tFixPointu tyFractInv = FIX_POINT_ONE - tyFract;
\r
1029 const tFixPointu w00 = imulFixu ( txFractInv, tyFractInv );
\r
1030 const tFixPointu w10 = imulFixu ( txFract , tyFractInv );
\r
1031 const tFixPointu w01 = imulFixu ( txFractInv, tyFract );
\r
1032 const tFixPointu w11 = imulFixu ( txFract , tyFract );
\r
1034 a = (a00 * w00 ) +
\r
1039 r = (r00 * w00 ) +
\r
1044 g = (g00 * w00 ) +
\r
1049 b = (b00 * w00 ) +
\r
1059 // some 2D Defines
\r
1060 struct AbsRectangle
\r
1068 //! 2D Intersection test
\r
1069 inline bool intersect ( AbsRectangle &dest, const AbsRectangle& a, const AbsRectangle& b)
\r
1071 dest.x0 = core::s32_max( a.x0, b.x0 );
\r
1072 dest.y0 = core::s32_max( a.y0, b.y0 );
\r
1073 dest.x1 = core::s32_min( a.x1, b.x1 );
\r
1074 dest.y1 = core::s32_min( a.y1, b.y1 );
\r
1075 return dest.x0 < dest.x1 && dest.y0 < dest.y1;
\r
1078 // some 1D defines
\r
1085 // returning intersection width
\r
1086 inline s32 intervall_intersect_test( const sIntervall& a, const sIntervall& b)
\r
1088 return core::s32_min( a.end, b.end ) - core::s32_max( a.start, b.start );
\r
1092 } // end namespace irr
\r