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 #if defined(SOFTWARE_DRIVER_2_32BIT)
\r
26 typedef u32 tVideoSample;
\r
27 typedef u32 tStencilSample;
\r
29 #define MASK_A 0xFF000000
\r
30 #define MASK_R 0x00FF0000
\r
31 #define MASK_G 0x0000FF00
\r
32 #define MASK_B 0x000000FF
\r
34 #define SHIFT_A (unsigned)24
\r
35 #define SHIFT_R (unsigned)16
\r
36 #define SHIFT_G (unsigned)8
\r
37 #define SHIFT_B (unsigned)0
\r
39 #define COLOR_MAX 0xFF
\r
40 #define COLOR_MAX_LOG2 8
\r
41 #define COLOR_BRIGHT_WHITE 0xFFFFFFFF
\r
43 #define SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY (unsigned)2
\r
44 #define SOFTWARE_DRIVER_2_RENDERTARGET_GRANULARITY (unsigned)2
\r
46 typedef u16 tVideoSample;
\r
47 typedef u8 tStencilSample;
\r
49 #define MASK_A 0x8000
\r
50 #define MASK_R 0x7C00
\r
51 #define MASK_G 0x03E0
\r
52 #define MASK_B 0x001F
\r
54 #define SHIFT_A (unsigned)15
\r
55 #define SHIFT_R (unsigned)10
\r
56 #define SHIFT_G (unsigned)5
\r
57 #define SHIFT_B (unsigned)0
\r
59 #define COLOR_MAX 0x1F
\r
60 #define COLOR_MAX_LOG2 5
\r
61 #define COLOR_BRIGHT_WHITE 0xFFFF
\r
62 #define SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY (unsigned)1
\r
63 #define SOFTWARE_DRIVER_2_RENDERTARGET_GRANULARITY (unsigned)1
\r
70 // ----------------------- Generic ----------------------------------
\r
71 //! align_next - align to next upper 2^n
\r
72 #define align_next(num,to) (((num) + (to-1)) & (~(to-1)))
\r
74 //! a more useful memset for pixel. dest must be aligned at least to 4 byte
\r
75 // (standard memset only works with 8-bit values)
\r
76 inline void memset32(void * dest, const u32 value, size_t bytesize)
\r
78 u32 * d = (u32*) dest;
\r
82 // loops unrolled to reduce the number of increments by factor ~8.
\r
83 i = bytesize >> (2 + 3);
\r
100 i = (bytesize >> 2 ) & 7;
\r
109 //! a more useful memset for pixel. dest must be aligned at least to 2 byte
\r
110 // (standard memset only works with 8-bit values)
\r
111 inline void memset16(void * dest, const u16 value, size_t bytesize)
\r
113 u16 * d = (u16*) dest;
\r
117 // loops unrolled to reduce the number of increments by factor ~8.
\r
118 i = bytesize >> (1 + 3);
\r
135 i = (bytesize >> 1 ) & 7;
\r
144 //! memset interleaved
\r
145 inline void memset32_interlaced(void* dest, const u32 value, size_t pitch,u32 height,const interlaced_control Interlaced)
\r
147 if (Interlaced.bypass) return memset32(dest, value, pitch * height);
\r
149 u8* dst = (u8*)dest;
\r
150 interlace_scanline_data line;
\r
151 for (line.y = 0; line.y < height; line.y += SOFTWARE_DRIVER_2_STEP_Y)
\r
153 interlace_scanline_enabled memset32(dst, value, pitch);
\r
158 // byte-align structures
\r
159 #include "irrpack.h"
\r
161 //IEEE Standard for Floating - Point Arithmetic(IEEE 754)
\r
165 struct { unsigned int frac:23; unsigned exp:8; unsigned int sign:1; } fields;
\r
166 struct { unsigned int frac_exp:31; } abs;
\r
167 } ieee754 PACK_STRUCT;
\r
169 // Default alignment
\r
170 #include "irrunpack.h"
\r
173 #define ieee754_zero_dot_5 0x3f000000
\r
174 #define ieee754_one 0x3f800000
\r
175 #define ieee754_two 0x40000000
\r
178 // integer log2 of a float ieee 754. [not used anymore]
\r
179 static inline s32 s32_log2_f32( f32 f)
\r
181 //u32 x = IR ( f ); return ((x & 0x7F800000) >> 23) - 127;
\r
184 return _log2.fields.exp ? _log2.fields.exp - 127 : 10000000; /*denormal very high number*/
\r
188 // integer log2 of an integer. returning 0 as denormal
\r
189 static inline s32 s32_log2_s32(u32 in)
\r
198 //return s32_log2_f32( (f32) x);
\r
199 //ieee754 _log2;_log2.f = (f32) in; return _log2.fields.exp - 127;
\r
203 static inline s32 s32_abs(s32 x)
\r
206 return (x ^ b ) - b;
\r
210 //! conditional set based on mask and arithmetic shift
\r
211 REALINLINE u32 if_mask_a_else_b ( const u32 mask, const u32 a, const u32 b )
\r
213 return ( mask & ( a ^ b ) ) ^ b;
\r
217 // ------------------ Video---------------------------------------
\r
219 Pixel = dest * ( 1 - alpha ) + source * alpha
\r
222 REALINLINE u32 PixelBlend32 ( const u32 c2, const u32 c1, const u32 alpha )
\r
224 u32 srcRB = c1 & 0x00FF00FF;
\r
225 u32 srcXG = c1 & 0x0000FF00;
\r
227 u32 dstRB = c2 & 0x00FF00FF;
\r
228 u32 dstXG = c2 & 0x0000FF00;
\r
231 u32 rb = srcRB - dstRB;
\r
232 u32 xg = srcXG - dstXG;
\r
249 Pixel = dest * ( 1 - alpha ) + source * alpha
\r
252 inline u16 PixelBlend16 ( const u16 c2, const u16 c1, const u16 alpha )
\r
254 const u16 srcRB = c1 & 0x7C1F;
\r
255 const u16 srcXG = c1 & 0x03E0;
\r
257 const u16 dstRB = c2 & 0x7C1F;
\r
258 const u16 dstXG = c2 & 0x03E0;
\r
260 u32 rb = srcRB - dstRB;
\r
261 u32 xg = srcXG - dstXG;
\r
274 return (u16)(rb | xg);
\r
278 Pixel = c0 * (c1/31). c0 Alpha retain
\r
280 inline u16 PixelMul16 ( const u16 c0, const u16 c1)
\r
282 return (u16)((( ( (c0 & 0x7C00) * (c1 & 0x7C00) ) & 0x3E000000 ) >> 15 ) |
\r
283 (( ( (c0 & 0x03E0) * (c1 & 0x03E0) ) & 0x000F8000 ) >> 10 ) |
\r
284 (( ( (c0 & 0x001F) * (c1 & 0x001F) ) & 0x000003E0 ) >> 5 ) |
\r
289 Pixel = c0 * (c1/31).
\r
291 inline u16 PixelMul16_2 ( u16 c0, u16 c1)
\r
293 return (u16)(( ( (c0 & 0x7C00) * (c1 & 0x7C00) ) & 0x3E000000 ) >> 15 |
\r
294 ( ( (c0 & 0x03E0) * (c1 & 0x03E0) ) & 0x000F8000 ) >> 10 |
\r
295 ( ( (c0 & 0x001F) * (c1 & 0x001F) ) & 0x000003E0 ) >> 5 |
\r
296 ( c0 & c1 & 0x8000));
\r
300 Pixel = c0 * (c1/255). c0 Alpha Retain
\r
302 REALINLINE u32 PixelMul32 ( const u32 c0, const u32 c1)
\r
304 return (c0 & 0xFF000000) |
\r
305 (( ( (c0 & 0x00FF0000) >> 12 ) * ( (c1 & 0x00FF0000) >> 12 ) ) & 0x00FF0000 ) |
\r
306 (( ( (c0 & 0x0000FF00) * (c1 & 0x0000FF00) ) >> 16 ) & 0x0000FF00 ) |
\r
307 (( ( (c0 & 0x000000FF) * (c1 & 0x000000FF) ) >> 8 ) & 0x000000FF);
\r
311 Pixel = c0 * (c1/255).
\r
313 REALINLINE u32 PixelMul32_2 ( const u32 c0, const u32 c1)
\r
315 return (( ( (c0 & 0xFF000000) >> 16 ) * ( (c1 & 0xFF000000) >> 16 ) ) & 0xFF000000 ) |
\r
316 (( ( (c0 & 0x00FF0000) >> 12 ) * ( (c1 & 0x00FF0000) >> 12 ) ) & 0x00FF0000 ) |
\r
317 (( ( (c0 & 0x0000FF00) * (c1 & 0x0000FF00) ) >> 16 ) & 0x0000FF00 ) |
\r
318 (( ( (c0 & 0x000000FF) * (c1 & 0x000000FF) ) >> 8 ) & 0x000000FF);
\r
322 Pixel = clamp ( c0 + c1, 0, 255 )
\r
324 REALINLINE u32 PixelAdd32 ( const u32 c2, const u32 c1)
\r
326 u32 sum = ( c2 & 0x00FFFFFF ) + ( c1 & 0x00FFFFFF );
\r
327 u32 low_bits = ( c2 ^ c1 ) & 0x00010101;
\r
328 s32 carries = ( sum - low_bits ) & 0x01010100;
\r
329 u32 modulo = sum - carries;
\r
330 u32 clamp = carries - ( carries >> 8 );
\r
331 return modulo | clamp;
\r
336 // 1 - Bit Alpha Blending
\r
337 inline u16 PixelBlend16 ( const u16 destination, const u16 source )
\r
339 if((source & 0x8000) == 0x8000)
\r
340 return source; // The source is visible, so use it.
\r
342 return destination; // The source is transparent, so use the destination.
\r
345 // 1 - Bit Alpha Blending 16Bit SIMD
\r
346 inline u32 PixelBlend16_simd ( const u32 destination, const u32 source )
\r
348 switch(source & 0x80008000)
\r
350 case 0x80008000: // Both source pixels are visible
\r
353 case 0x80000000: // Only the first source pixel is visible
\r
354 return (source & 0xFFFF0000) | (destination & 0x0000FFFF);
\r
356 case 0x00008000: // Only the second source pixel is visible.
\r
357 return (destination & 0xFFFF0000) | (source & 0x0000FFFF);
\r
359 default: // Neither source pixel is visible.
\r
360 return destination;
\r
365 // 1 - Bit Alpha Blending
\r
366 inline u16 PixelBlend16 ( const u16 c2, const u16 c1 )
\r
368 u16 mask = ((c1 & 0x8000) >> 15 ) + 0x7fff;
\r
369 return (c2 & mask ) | ( c1 & ~mask );
\r
372 // 1 - Bit Alpha Blending 16Bit SIMD
\r
373 inline u32 PixelBlend16_simd ( const u32 c2, const u32 c1 )
\r
375 u32 mask = ((c1 & 0x80008000) >> 15 ) + 0x7fff7fff;
\r
376 return (c2 & mask ) | ( c1 & ~mask );
\r
382 Pixel = dest * ( 1 - SourceAlpha ) + source * SourceAlpha (OpenGL blending)
\r
384 inline u32 PixelBlend32 ( const u32 c2, const u32 c1 )
\r
387 u32 alpha = c1 & 0xFF000000;
\r
391 if ( 0xFF000000 == alpha )
\r
398 // add highbit alpha, if ( alpha > 127 ) alpha += 1;
\r
399 alpha += ( alpha >> 7);
\r
401 u32 srcRB = c1 & 0x00FF00FF;
\r
402 u32 srcXG = c1 & 0x0000FF00;
\r
404 u32 dstRB = c2 & 0x00FF00FF;
\r
405 u32 dstXG = c2 & 0x0000FF00;
\r
408 u32 rb = srcRB - dstRB;
\r
409 u32 xg = srcXG - dstXG;
\r
422 return (c1 & 0xFF000000) | rb | xg;
\r
427 // ------------------ Fix Point ----------------------------------
\r
429 #if defined(ENV64BIT)
\r
430 typedef s32 tFixPoint;
\r
431 typedef u32 tFixPointu;
\r
433 typedef s32 tFixPoint;
\r
434 typedef u32 tFixPointu;
\r
437 // Fix Point 12 (overflow on s32)
\r
439 #define FIX_POINT_PRE 12
\r
440 #define FIX_POINT_FRACT_MASK 0xFFF
\r
441 #define FIX_POINT_UNSIGNED_MASK 0x7FFFF000
\r
442 #define FIX_POINT_ONE 0x1000
\r
443 #define FIX_POINT_ZERO_DOT_FIVE 0x0800
\r
444 #define FIX_POINT_F32_MUL 4096.f
\r
447 // Fix Point 11 (overflow on s32)
\r
449 #define FIX_POINT_PRE 11
\r
450 #define FIX_POINT_FRACT_MASK 0x7FF
\r
451 #define FIX_POINT_UNSIGNED_MASK 0xFFFFF800
\r
452 #define FIX_POINT_ONE 0x800
\r
453 #define FIX_POINT_ZERO_DOT_FIVE 0x400
\r
454 #define FIX_POINT_F32_MUL 2048.f
\r
459 #define FIX_POINT_PRE 10
\r
460 #define FIX_POINT_FRACT_MASK 0x000003FF
\r
461 #define FIX_POINT_UNSIGNED_MASK 0x7FFFFE00
\r
462 #define FIX_POINT_ONE 0x00000400
\r
463 #define FIX_POINT_ZERO_DOT_FIVE 0x00000200
\r
464 #define FIX_POINT_F32_MUL 1024.f
\r
469 #define FIX_POINT_PRE 9
\r
470 #define FIX_POINT_FRACT_MASK 0x1FF
\r
471 #define FIX_POINT_UNSIGNED_MASK 0x7FFFFE00
\r
472 #define FIX_POINT_ONE 0x200
\r
473 #define FIX_POINT_ZERO_DOT_FIVE 0x100
\r
474 #define FIX_POINT_F32_MUL 512.f
\r
479 #define FIX_POINT_PRE 7
\r
480 #define FIX_POINT_FRACT_MASK 0x7F
\r
481 #define FIX_POINT_UNSIGNED_MASK 0x7FFFFF80
\r
482 #define FIX_POINT_ONE 0x80
\r
483 #define FIX_POINT_ZERO_DOT_FIVE 0x40
\r
484 #define FIX_POINT_F32_MUL 128.f
\r
487 #define FIXPOINT_COLOR_MAX ( COLOR_MAX << FIX_POINT_PRE )
\r
489 #if FIX_POINT_PRE == 10 && COLOR_MAX == 255
\r
490 #define FIX_POINT_HALF_COLOR 0x1FE00
\r
491 #define FIX_POINT_COLOR_ERROR 4
\r
492 #elif FIX_POINT_PRE == 12 && COLOR_MAX == 255
\r
493 #define FIX_POINT_HALF_COLOR 0x7F800
\r
494 #define FIX_POINT_COLOR_ERROR 16
\r
495 #elif FIX_POINT_PRE == 10 && COLOR_MAX == 31
\r
496 #define FIX_POINT_HALF_COLOR 0x3E00
\r
497 #define FIX_POINT_COLOR_ERROR 32
\r
499 #define FIX_POINT_HALF_COLOR ( (tFixPoint) ( ((f32) COLOR_MAX / 2.f * FIX_POINT_F32_MUL ) ) )
\r
500 #define FIX_POINT_COLOR_ERROR (1<<(FIX_POINT_PRE-COLOR_MAX_LOG2))
\r
505 convert signed integer to fixpoint
\r
507 inline tFixPoint s32_to_fixPoint (const s32 x)
\r
509 return x << FIX_POINT_PRE;
\r
513 inline tFixPointu u32_to_fixPoint (const u32 x)
\r
515 return x << FIX_POINT_PRE;
\r
519 inline u32 fixPointu_to_u32 (const tFixPointu x)
\r
521 return (u32)(x >> FIX_POINT_PRE);
\r
526 #define fix_inverse32(x) (FIX_POINT_F32_MUL / (x))
\r
527 #define fix_inverse32_color(x) ((FIX_POINT_F32_MUL*COLOR_MAX) / (x))
\r
531 convert float to fixpoint
\r
532 fast convert (fistp on x86) HAS to be used..
\r
533 hints: compileflag /QIfist for msvc7. msvc 8.0 has smth different
\r
534 others should use their favourite assembler..
\r
537 static inline int f_round2(f32 f)
\r
540 return IR(f) - 0x4b400000;
\r
545 convert f32 to Fix Point.
\r
546 multiply is needed anyway, so scale mulby
\r
549 REALINLINE tFixPoint tofix0 (const f32 x, const f32 mulby = FIX_POINT_F32_MUL )
\r
551 return (tFixPoint) (x * mulby);
\r
554 #define tofix(x,y) (tFixPoint)(x * y)
\r
558 Fix Point , Fix Point Multiply
\r
561 REALINLINE tFixPointu imulFixu(const tFixPointu x, const tFixPointu y)
\r
563 return (x * y) >> (tFixPointu) FIX_POINT_PRE;
\r
566 #define imulFixu(x,y) (((x) * (y)) >> (tFixPointu) FIX_POINT_PRE)
\r
570 Fix Point , Fix Point Multiply
\r
572 REALINLINE tFixPoint imulFix(const tFixPoint x, const tFixPoint y)
\r
574 return (x * y) >> FIX_POINT_PRE;
\r
577 #define imulFix_simple(x,y) ((x*y)>>FIX_POINT_PRE)
\r
581 Fix Point , Fix Point Multiply x * y * 2
\r
583 REALINLINE tFixPoint imulFix2(const tFixPoint x, const tFixPoint y)
\r
585 return ( x * y) >> ( FIX_POINT_PRE -1 );
\r
590 Multiply x * y * 1 FIXPOINT_COLOR_MAX
\r
592 REALINLINE tFixPoint imulFix_tex1(const tFixPoint x, const tFixPoint y)
\r
594 #if SOFTWARE_DRIVER_2_TEXTURE_COLOR_FORMAT == ECF_A8R8G8B8
\r
595 return (((tFixPointu)x >> 2)*(((tFixPointu)y + FIX_POINT_ONE) >> 2)) >> (tFixPointu) (FIX_POINT_PRE + 4);
\r
597 return (x * (y+ FIX_POINT_ONE)) >> (FIX_POINT_PRE + 5);
\r
604 REALINLINE tFixPoint imulFix_tex2(const tFixPoint x, const tFixPoint y)
\r
606 return ( ( (tFixPointu) x >> 2 ) * ( (tFixPointu) y >> 2 ) ) >> (tFixPointu) ( FIX_POINT_PRE + 3 );
\r
610 Multiply x * y * 4 clamp
\r
613 REALINLINE tFixPoint imulFix_tex4(const tFixPoint x, const tFixPoint y)
\r
615 #if SOFTWARE_DRIVER_2_TEXTURE_COLOR_FORMAT == ECF_A8R8G8B8
\r
616 tFixPoint a = (((tFixPointu)x >> 2)*(((tFixPointu)y + FIX_POINT_ONE) >> 2)) >> (tFixPointu)(FIX_POINT_PRE + 2);
\r
618 tFixPoint a = (x * (y + FIX_POINT_ONE)) >> (FIX_POINT_PRE + 3);
\r
620 tFixPoint mask = (a - FIXPOINT_COLOR_MAX) >> 31;
\r
621 return (a & mask) | (FIXPOINT_COLOR_MAX & ~mask);
\r
626 clamp FixPoint to maxcolor in FixPoint, min(a,COLOR_MAX)
\r
628 REALINLINE tFixPoint clampfix_maxcolor ( const tFixPoint a)
\r
630 tFixPoint c = (a - FIXPOINT_COLOR_MAX) >> 31;
\r
631 return (a & c) | ( FIXPOINT_COLOR_MAX & ~c);
\r
636 clamp FixPoint to 0 in FixPoint, max(a,0)
\r
638 REALINLINE tFixPoint clampfix_mincolor ( const tFixPoint a)
\r
640 return a - ( a & ( a >> 31 ) );
\r
643 REALINLINE tFixPoint saturateFix ( const tFixPoint a)
\r
645 return clampfix_mincolor ( clampfix_maxcolor ( a ) );
\r
650 // rount fixpoint to int
\r
651 inline s32 roundFix ( const tFixPoint x )
\r
653 return (s32)(( x + FIX_POINT_ZERO_DOT_FIVE ) >> FIX_POINT_PRE);
\r
659 inline s32 f32_to_23Bits(const f32 x)
\r
662 return IR(y) & 0x7FFFFF; // last 23 bits
\r
667 fixpoint in [0..Fixpoint_color] to VideoSample xrgb
\r
669 REALINLINE tVideoSample fix_to_sample ( const tFixPoint r, const tFixPoint g, const tFixPoint b )
\r
671 return ( FIXPOINT_COLOR_MAX & FIXPOINT_COLOR_MAX) << ( SHIFT_A - FIX_POINT_PRE ) |
\r
672 ( r & FIXPOINT_COLOR_MAX) << ( SHIFT_R - FIX_POINT_PRE ) |
\r
673 ( g & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - SHIFT_G ) |
\r
674 ( b & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - SHIFT_B );
\r
679 fixpoint to VideoSample argb
\r
681 rgb in [0;255] colormax
\r
683 REALINLINE tVideoSample fix4_to_sample ( const tFixPoint a, const tFixPoint r, const tFixPoint g, const tFixPoint b )
\r
685 return ( a & (FIX_POINT_FRACT_MASK - 1 )) << ( SHIFT_A - 1 ) |
\r
686 ( r & FIXPOINT_COLOR_MAX) << ( SHIFT_R - FIX_POINT_PRE ) |
\r
687 ( g & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - SHIFT_G ) |
\r
688 ( b & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - SHIFT_B );
\r
692 return fixpoint from VideoSample granularity FIXPOINT_COLOR_MAX
\r
694 inline void color_to_fix ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 )
\r
696 (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE );
\r
697 (tFixPointu&) g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G );
\r
698 (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B );
\r
702 return fixpoint from VideoSample granularity FIXPOINT_COLOR_MAX
\r
704 inline void color_to_fix ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 )
\r
706 (tFixPointu&) a = (t00 & MASK_A) >> ( SHIFT_A - FIX_POINT_PRE );
\r
707 (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE );
\r
708 (tFixPointu&) g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G );
\r
709 (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B );
\r
713 return fixpoint from VideoSample granularity 0..FIX_POINT_ONE
\r
715 inline void color_to_fix1 ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 )
\r
717 (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R + COLOR_MAX_LOG2 - FIX_POINT_PRE );
\r
718 (tFixPointu&) g = (t00 & MASK_G) >> ( SHIFT_G + COLOR_MAX_LOG2 - FIX_POINT_PRE );
\r
719 (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - COLOR_MAX_LOG2 );
\r
721 //0..255 -> 0..256 | c += c >= 0.5 ? 1 : 0
\r
722 r += (r & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0;
\r
723 g += (g & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0;
\r
724 b += (b & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0;
\r
728 return fixpoint from VideoSample granularity 0..FIX_POINT_ONE
\r
730 inline void color_to_fix1 ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 )
\r
732 (tFixPointu&) a = (t00 & MASK_A) >> ( SHIFT_A + COLOR_MAX_LOG2 - FIX_POINT_PRE );
\r
733 (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R + COLOR_MAX_LOG2 - FIX_POINT_PRE );
\r
734 (tFixPointu&) g = (t00 & MASK_G) >> ( SHIFT_G + COLOR_MAX_LOG2 - FIX_POINT_PRE );
\r
735 (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - COLOR_MAX_LOG2 );
\r
737 //0..255 -> 0..256 | c += c >= 0.5 ? 1 : 0
\r
738 a += (a & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0;
\r
739 r += (r & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0;
\r
740 g += (g & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0;
\r
741 b += (b & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0;
\r
746 return fixpoint from VideoSample granularity FIXPOINT_COLOR_MAX
\r
748 inline void color_to_fix(tFixPoint c[4], const tVideoSample t00)
\r
750 c[0] = (t00 & MASK_A) >> (SHIFT_A - FIX_POINT_PRE);
\r
751 c[1] = (t00 & MASK_R) >> (SHIFT_R - FIX_POINT_PRE);
\r
752 c[2] = (t00 & MASK_G) << (FIX_POINT_PRE - SHIFT_G);
\r
753 c[3] = (t00 & MASK_B) << (FIX_POINT_PRE - SHIFT_B);
\r
757 return fixpoint from VideoSample granularity 0..FIX_POINT_ONE
\r
759 inline void color_to_fix1(tFixPoint c[4], const tVideoSample t00)
\r
761 c[0] = (t00 & MASK_A) >> (SHIFT_A + COLOR_MAX_LOG2 - FIX_POINT_PRE);
\r
762 c[1] = (t00 & MASK_R) >> (SHIFT_R + COLOR_MAX_LOG2 - FIX_POINT_PRE);
\r
763 c[2] = (t00 & MASK_G) >> (SHIFT_G + COLOR_MAX_LOG2 - FIX_POINT_PRE);
\r
764 c[3] = (t00 & MASK_B) << (FIX_POINT_PRE - COLOR_MAX_LOG2);
\r
766 //0..255 -> 0..256 | c += c >= 0.5 ? 1 : 0
\r
767 c[0] += (c[0] & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0;
\r
768 c[1] += (c[1] & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0;
\r
769 c[2] += (c[2] & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0;
\r
770 c[3] += (c[3] & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0;
\r
776 //! ----- FP24 1.23 fix point z-buffer
\r
787 fp24 ( const f32 f )
\r
790 v = ((u32&)y) & 0x7FFFFF; // last 23 bits
\r
793 void operator=(const f32 f )
\r
796 v = ((u32&)y) & 0x7FFFFF; // last 23 bits
\r
799 void operator+=(const fp24 &other )
\r
804 operator f32 () const
\r
814 // ------------------------ Internal Texture -----------------------------
\r
816 struct sInternalTexture
\r
819 void* data; //tVideoSample* Texture->lock(miplevel)
\r
820 size_t textureXMask;
\r
821 size_t textureYMask;
\r
825 video::CSoftwareTexture2 *Texture;
\r
826 s32 lodFactor; // magnify/minify
\r
831 // get video sample plain
\r
832 static inline tVideoSample getTexel_plain ( const sInternalTexture* t, const tFixPointu tx, const tFixPointu ty )
\r
836 ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;
\r
837 ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY );
\r
840 return *((tVideoSample*)( (u8*) t->data + ofs ));
\r
843 // get video sample to fix
\r
844 inline void getTexel_fix ( tFixPoint &r, tFixPoint &g, tFixPoint &b,
\r
845 const sInternalTexture* t, const tFixPointu tx, const tFixPointu ty
\r
850 ofs = ( ((ty + FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;
\r
851 ofs |= ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask ) >> ( FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY );
\r
855 t00 = *((tVideoSample*)( (u8*) t->data + ofs ));
\r
857 r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE);
\r
858 g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G );
\r
859 b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B );
\r
863 // get video sample to fixpoint colormax
\r
864 inline void getTexel_fix(tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b,
\r
865 const sInternalTexture* t, const tFixPointu tx, const tFixPointu ty
\r
870 ofs = (((ty+ FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2;
\r
871 ofs |= ((tx+ FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY);
\r
875 t00 = *((tVideoSample*)((u8*)t->data + ofs));
\r
877 a = (t00 & MASK_A) >> (SHIFT_A - FIX_POINT_PRE);
\r
878 r = (t00 & MASK_R) >> (SHIFT_R - FIX_POINT_PRE);
\r
879 g = (t00 & MASK_G) << (FIX_POINT_PRE - SHIFT_G);
\r
880 b = (t00 & MASK_B) << (FIX_POINT_PRE - SHIFT_B);
\r
885 // get video sample to fixpoint
\r
886 static REALINLINE void getTexel_fix ( tFixPoint &a,
\r
887 const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty)
\r
891 ofs = ( ((ty + FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;
\r
892 ofs |= ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask ) >> ( FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY );
\r
896 t00 = *((tVideoSample*)( (u8*) t->data + ofs ));
\r
898 a = (t00 & MASK_A) >> ( SHIFT_A - FIX_POINT_PRE);
\r
903 load a sample from internal texture at position tx,ty to fixpoint
\r
905 #if defined(SOFTWARE_DRIVER_2_BILINEAR)
\r
908 // texture2D in fixpoint color range bilinear
\r
909 static REALINLINE void getSample_texture(tFixPoint &r, tFixPoint &g, tFixPoint &b,
\r
910 const sInternalTexture* burning_restrict t, const tFixPointu tx, const tFixPointu ty
\r
914 if (t->lodFactor > 0)
\r
918 ofs = (((ty + FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2;
\r
919 ofs += ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY);
\r
923 t00 = *((tVideoSample*)((u8*)t->data + ofs));
\r
925 r = (t00 & MASK_R) >> (SHIFT_R - FIX_POINT_PRE);
\r
926 g = (t00 & MASK_G) << (FIX_POINT_PRE - SHIFT_G);
\r
927 b = (t00 & MASK_B) << (FIX_POINT_PRE - SHIFT_B);
\r
932 tFixPointu r00, g00, b00;
\r
933 tFixPointu r01, g01, b01;
\r
934 tFixPointu r10, g10, b10;
\r
935 tFixPointu r11, g11, b11;
\r
937 size_t o0, o1, o2, o3;
\r
940 //wraps positive (ignoring negative)
\r
941 o0 = (((ty)& t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2;
\r
942 o1 = (((ty + FIX_POINT_ONE) & t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2;
\r
943 o2 = ((tx)& t->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY);
\r
944 o3 = ((tx + FIX_POINT_ONE) & t->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY);
\r
946 t00 = *((tVideoSample*)((u8*)t->data + (o0 + o2)));
\r
947 r00 = (t00 & MASK_R) >> SHIFT_R;
\r
948 g00 = (t00 & MASK_G) >> SHIFT_G;
\r
949 b00 = (t00 & MASK_B);
\r
951 t00 = *((tVideoSample*)((u8*)t->data + (o0 + o3)));
\r
952 r10 = (t00 & MASK_R) >> SHIFT_R;
\r
953 g10 = (t00 & MASK_G) >> SHIFT_G;
\r
954 b10 = (t00 & MASK_B);
\r
956 t00 = *((tVideoSample*)((u8*)t->data + (o1 + o2)));
\r
957 r01 = (t00 & MASK_R) >> SHIFT_R;
\r
958 g01 = (t00 & MASK_G) >> SHIFT_G;
\r
959 b01 = (t00 & MASK_B);
\r
961 t00 = *((tVideoSample*)((u8*)t->data + (o1 + o3)));
\r
962 r11 = (t00 & MASK_R) >> SHIFT_R;
\r
963 g11 = (t00 & MASK_G) >> SHIFT_G;
\r
964 b11 = (t00 & MASK_B);
\r
967 tFixPointu fracx = tx & FIX_POINT_FRACT_MASK;
\r
968 tFixPointu fracy = ty & FIX_POINT_FRACT_MASK;
\r
972 w[0] = imulFixu(FIX_POINT_ONE - fracx, FIX_POINT_ONE - fracy);
\r
973 w[1] = imulFixu(FIX_POINT_ONE - fracx, fracy);
\r
974 w[2] = imulFixu(fracx, FIX_POINT_ONE - fracy);
\r
975 w[3] = imulFixu(fracx, fracy);
\r
996 // texture2D in fixpoint color range bilinear
\r
997 static REALINLINE void getSample_texture(tFixPoint &r, tFixPoint &g, tFixPoint &b,
\r
998 const sInternalTexture* burning_restrict tex, const tFixPointu tx, const tFixPointu ty
\r
1002 if (tex->lodFactor > 1)
\r
1004 //nearest neighbor
\r
1006 ofs = (((ty + FIX_POINT_ZERO_DOT_FIVE) & tex->textureYMask) >> FIX_POINT_PRE) << tex->pitchlog2;
\r
1007 ofs += ((tx + FIX_POINT_ZERO_DOT_FIVE) & tex->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY);
\r
1010 t00 = *((tVideoSample*)((u8*)tex->data + ofs));
\r
1012 r = (t00 & MASK_R) >> (SHIFT_R - FIX_POINT_PRE);
\r
1013 g = (t00 & MASK_G) << (FIX_POINT_PRE - SHIFT_G);
\r
1014 b = (t00 & MASK_B) << (FIX_POINT_PRE - SHIFT_B);
\r
1021 tFixPointu fracx = tx & FIX_POINT_FRACT_MASK;
\r
1022 tFixPointu fracy = ty & FIX_POINT_FRACT_MASK;
\r
1023 w[0] = imulFixu(FIX_POINT_ONE - fracx, FIX_POINT_ONE - fracy);
\r
1024 w[1] = imulFixu(fracx, FIX_POINT_ONE - fracy);
\r
1025 w[2] = imulFixu(FIX_POINT_ONE - fracx, fracy);
\r
1026 w[3] = imulFixu(fracx, fracy);
\r
1029 //wraps positive (ignoring negative)
\r
1030 tVideoSample t[4];
\r
1032 size_t o0, o1, o2, o3;
\r
1033 o0 = (((ty) & tex->textureYMask) >> FIX_POINT_PRE) << tex->pitchlog2;
\r
1034 o1 = (((ty + FIX_POINT_ONE) & tex->textureYMask) >> FIX_POINT_PRE) << tex->pitchlog2;
\r
1035 o2 = ((tx)& tex->textureXMask) >> (unsigned)(FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY);
\r
1036 o3 = ((tx + FIX_POINT_ONE) & tex->textureXMask) >> (unsigned)(FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY);
\r
1038 t[0] = *((tVideoSample*)((u8*)tex->data + (o0 + o2)));
\r
1039 t[1] = *((tVideoSample*)((u8*)tex->data + (o0 + o3)));
\r
1040 t[2] = *((tVideoSample*)((u8*)tex->data + (o1 + o2)));
\r
1041 t[3] = *((tVideoSample*)((u8*)tex->data + (o1 + o3)));
\r
1044 r = (((t[0] & MASK_R) >> SHIFT_R) * w[0]) +
\r
1045 (((t[1] & MASK_R) >> SHIFT_R) * w[1]) +
\r
1046 (((t[2] & MASK_R) >> SHIFT_R) * w[2]) +
\r
1047 (((t[3] & MASK_R) >> SHIFT_R) * w[3]);
\r
1049 g = (((t[0] & MASK_G) >> SHIFT_G) * w[0]) +
\r
1050 (((t[1] & MASK_G) >> SHIFT_G) * w[1]) +
\r
1051 (((t[2] & MASK_G) >> SHIFT_G) * w[2]) +
\r
1052 (((t[3] & MASK_G) >> SHIFT_G) * w[3]);
\r
1054 b = ((t[0] & MASK_B) * w[0]) +
\r
1055 ((t[1] & MASK_B) * w[1]) +
\r
1056 ((t[2] & MASK_B) * w[2]) +
\r
1057 ((t[3] & MASK_B) * w[3]);
\r
1062 // get Sample bilinear
\r
1063 static REALINLINE void getSample_texture(tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b,
\r
1064 const sInternalTexture* burning_restrict tex, const tFixPointu tx, const tFixPointu ty
\r
1068 tFixPointu a00, r00, g00, b00;
\r
1069 tFixPointu a01, r01, g01, b01;
\r
1070 tFixPointu a10, r10, g10, b10;
\r
1071 tFixPointu a11, r11, g11, b11;
\r
1073 size_t o0, o1, o2, o3;
\r
1076 o0 = (((ty)& tex->textureYMask) >> FIX_POINT_PRE) << tex->pitchlog2;
\r
1077 o1 = (((ty + FIX_POINT_ONE) & tex->textureYMask) >> FIX_POINT_PRE) << tex->pitchlog2;
\r
1078 o2 = ((tx)& tex->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY);
\r
1079 o3 = ((tx + FIX_POINT_ONE) & tex->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY);
\r
1081 t00 = *((tVideoSample*)((u8*)tex->data + (o0 + o2)));
\r
1082 a00 = (t00 & MASK_A) >> SHIFT_A;
\r
1083 r00 = (t00 & MASK_R) >> SHIFT_R;
\r
1084 g00 = (t00 & MASK_G) >> SHIFT_G;
\r
1085 b00 = (t00 & MASK_B);
\r
1087 t00 = *((tVideoSample*)((u8*)tex->data + (o0 + o3)));
\r
1088 a10 = (t00 & MASK_A) >> SHIFT_A;
\r
1089 r10 = (t00 & MASK_R) >> SHIFT_R;
\r
1090 g10 = (t00 & MASK_G) >> SHIFT_G;
\r
1091 b10 = (t00 & MASK_B);
\r
1093 t00 = *((tVideoSample*)((u8*)tex->data + (o1 + o2)));
\r
1094 a01 = (t00 & MASK_A) >> SHIFT_A;
\r
1095 r01 = (t00 & MASK_R) >> SHIFT_R;
\r
1096 g01 = (t00 & MASK_G) >> SHIFT_G;
\r
1097 b01 = (t00 & MASK_B);
\r
1099 t00 = *((tVideoSample*)((u8*)tex->data + (o1 + o3)));
\r
1100 a11 = (t00 & MASK_A) >> SHIFT_A;
\r
1101 r11 = (t00 & MASK_R) >> SHIFT_R;
\r
1102 g11 = (t00 & MASK_G) >> SHIFT_G;
\r
1103 b11 = (t00 & MASK_B);
\r
1105 const tFixPointu txFract = tx & FIX_POINT_FRACT_MASK;
\r
1106 const tFixPointu txFractInv = FIX_POINT_ONE - txFract;
\r
1108 const tFixPointu tyFract = ty & FIX_POINT_FRACT_MASK;
\r
1109 const tFixPointu tyFractInv = FIX_POINT_ONE - tyFract;
\r
1111 const tFixPointu w00 = imulFixu(txFractInv, tyFractInv);
\r
1112 const tFixPointu w10 = imulFixu(txFract, tyFractInv);
\r
1113 const tFixPointu w01 = imulFixu(txFractInv, tyFract);
\r
1114 const tFixPointu w11 = imulFixu(txFract, tyFract);
\r
1121 fix_alpha_color_max(a);
\r
1140 #else // SOFTWARE_DRIVER_2_BILINEAR
\r
1142 // get Sample linear == getSample_fixpoint
\r
1144 static REALINLINE void getSample_texture(tFixPoint &r, tFixPoint &g, tFixPoint &b,
\r
1145 const sInternalTexture* burning_restrict t, const tFixPointu tx, const tFixPointu ty
\r
1149 ofs = (((ty + FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2;
\r
1150 ofs += ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY);
\r
1153 const tVideoSample t00 = *((tVideoSample*)((u8*)t->data + ofs));
\r
1155 (tFixPointu &)r = (t00 & MASK_R) >> (SHIFT_R - FIX_POINT_PRE);
\r
1156 (tFixPointu &)g = (t00 & MASK_G) << (FIX_POINT_PRE - SHIFT_G);
\r
1157 (tFixPointu &)b = (t00 & MASK_B) << (FIX_POINT_PRE - SHIFT_B);
\r
1160 static REALINLINE void getSample_texture(tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b,
\r
1161 const sInternalTexture* burning_restrict t, const tFixPointu tx, const tFixPointu ty
\r
1165 ofs = (((ty + FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2;
\r
1166 ofs += ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask) >> (FIX_POINT_PRE - SOFTWARE_DRIVER_2_TEXTURE_GRANULARITY);
\r
1169 const tVideoSample t00 = *((tVideoSample*)((u8*)t->data + ofs));
\r
1171 (tFixPointu &)a = (t00 & MASK_A) >> (SHIFT_A - FIX_POINT_PRE);
\r
1172 fix_alpha_color_max(a);
\r
1173 (tFixPointu &)r = (t00 & MASK_R) >> (SHIFT_R - FIX_POINT_PRE);
\r
1174 (tFixPointu &)g = (t00 & MASK_G) << (FIX_POINT_PRE - SHIFT_G);
\r
1175 (tFixPointu &)b = (t00 & MASK_B) << (FIX_POINT_PRE - SHIFT_B);
\r
1179 #endif // SOFTWARE_DRIVER_2_BILINEAR
\r
1182 // 2D Region closed [x0;x1]
\r
1183 struct AbsRectangle
\r
1191 //! 2D Intersection test
\r
1192 inline bool intersect ( AbsRectangle &dest, const AbsRectangle& a, const AbsRectangle& b)
\r
1194 dest.x0 = core::s32_max( a.x0, b.x0 );
\r
1195 dest.y0 = core::s32_max( a.y0, b.y0 );
\r
1196 dest.x1 = core::s32_min( a.x1, b.x1 );
\r
1197 dest.y1 = core::s32_min( a.y1, b.y1 );
\r
1198 return dest.x0 < dest.x1 && dest.y0 < dest.y1;
\r
1202 // some 1D defines
\r
1209 // returning intersection width
\r
1210 inline s32 intervall_intersect_test( const sIntervall& a, const sIntervall& b)
\r
1212 return core::s32_min( a.end, b.end ) - core::s32_max( a.start, b.start );
\r
1218 static inline void tiny_strncpy(char* to, const char* from, const size_t count)
\r
1220 for (size_t r = 0; r < count && (*to = *from) != '\0'; ++from, ++to, ++r);
\r
1224 #define tiny_strcpy(a, b) tiny_strncpy(a,b,sizeof(a)-1)
\r
1227 // tiny_isequal = !strncmp(a,b,sizeof(a)-1)
\r
1228 static inline int tiny_isequal(const char *s1, const char *s2, size_t n)
\r
1231 if (*s1 != *s2++) return 0;
\r
1234 } while (--n != 0);
\r
1238 #define tiny_istoken(a, b) tiny_isequal(a,b,sizeof(a)-1) != 0
\r
1241 } // end namespace irr
\r