]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/SoftwareDriver2_helper.h
01e2f4f73b5e2233433a3e53cac0147f49123a59
[irrlicht.git] / source / Irrlicht / SoftwareDriver2_helper.h
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
4 \r
5 /*\r
6         History:\r
7         - changed behavior for log2 textures ( replaced multiplies by shift )\r
8 */\r
9 \r
10 #ifndef __S_VIDEO_2_SOFTWARE_HELPER_H_INCLUDED__\r
11 #define __S_VIDEO_2_SOFTWARE_HELPER_H_INCLUDED__\r
12 \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
18 \r
19 \r
20 namespace irr\r
21 {\r
22 \r
23 // supporting different packed pixel needs many defines...\r
24 \r
25 #ifdef SOFTWARE_DRIVER_2_32BIT\r
26         typedef u32     tVideoSample;\r
27 \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
32 \r
33         #define SHIFT_A 24\r
34         #define SHIFT_R 16\r
35         #define SHIFT_G 8\r
36         #define SHIFT_B 0\r
37 \r
38         #define COLOR_MAX                                       0xFF\r
39         #define COLOR_MAX_LOG2                          8\r
40         #define COLOR_BRIGHT_WHITE                      0xFFFFFFFF\r
41 \r
42         #define VIDEO_SAMPLE_GRANULARITY        2\r
43 \r
44 #else\r
45         typedef u16     tVideoSample;\r
46 \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
51 \r
52         #define SHIFT_A 15\r
53         #define SHIFT_R 10\r
54         #define SHIFT_G 5\r
55         #define SHIFT_B 0\r
56 \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
61 \r
62 #endif\r
63 \r
64 \r
65 \r
66 \r
67 // ----------------------- Generic ----------------------------------\r
68 \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
72 {\r
73         u32 * d = (u32*) dest;\r
74 \r
75         u32 i;\r
76 \r
77         // loops unrolled to reduce the number of increments by factor ~8.\r
78         i = bytesize >> (2 + 3);\r
79         while (i)\r
80         {\r
81                 d[0] = value;\r
82                 d[1] = value;\r
83                 d[2] = value;\r
84                 d[3] = value;\r
85 \r
86                 d[4] = value;\r
87                 d[5] = value;\r
88                 d[6] = value;\r
89                 d[7] = value;\r
90 \r
91                 d += 8;\r
92                 i -= 1;\r
93         }\r
94 \r
95         i = (bytesize >> 2 ) & 7;\r
96         while (i)\r
97         {\r
98                 d[0] = value;\r
99                 d += 1;\r
100                 i -= 1;\r
101         }\r
102 }\r
103 \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
107 {\r
108         u16 * d = (u16*) dest;\r
109 \r
110         u32 i;\r
111 \r
112         // loops unrolled to reduce the number of increments by factor ~8.\r
113         i = bytesize >> (1 + 3);\r
114         while (i)\r
115         {\r
116                 d[0] = value;\r
117                 d[1] = value;\r
118                 d[2] = value;\r
119                 d[3] = value;\r
120 \r
121                 d[4] = value;\r
122                 d[5] = value;\r
123                 d[6] = value;\r
124                 d[7] = value;\r
125 \r
126                 d += 8;\r
127                 --i;\r
128         }\r
129 \r
130         i = (bytesize >> 1 ) & 7;\r
131         while (i)\r
132         {\r
133                 d[0] = value;\r
134                 ++d;\r
135                 --i;\r
136         }\r
137 }\r
138 \r
139 /*\r
140         use biased loop counter\r
141         --> 0 byte copy is forbidden\r
142 */\r
143 REALINLINE void memcpy32_small ( void * dest, const void *source, u32 bytesize )\r
144 {\r
145         u32 c = bytesize >> 2;\r
146 \r
147         do\r
148         {\r
149                 ((u32*) dest ) [ c-1 ] = ((u32*) source) [ c-1 ];\r
150         } while ( --c );\r
151 \r
152 }\r
153 \r
154 \r
155 \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
158 {\r
159         u32 x = IR ( f );\r
160         return ((x & 0x7F800000) >> 23) - 127;\r
161 }\r
162 \r
163 static inline s32 s32_log2_s32(u32 x)\r
164 {\r
165         return s32_log2_f32( (f32) x);\r
166 }\r
167 \r
168 static inline s32 s32_abs(s32 x)\r
169 {\r
170         s32 b = x >> 31;\r
171         return (x ^ b ) - b;\r
172 }\r
173 \r
174 \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
177 {\r
178         return ( mask & ( a ^ b ) ) ^ b;\r
179 }\r
180 \r
181 // ------------------ Video---------------------------------------\r
182 /*!\r
183         Pixel = dest * ( 1 - alpha ) + source * alpha\r
184         alpha [0;256]\r
185 */\r
186 REALINLINE u32 PixelBlend32 ( const u32 c2, const u32 c1, u32 alpha )\r
187 {\r
188         u32 srcRB = c1 & 0x00FF00FF;\r
189         u32 srcXG = c1 & 0x0000FF00;\r
190 \r
191         u32 dstRB = c2 & 0x00FF00FF;\r
192         u32 dstXG = c2 & 0x0000FF00;\r
193 \r
194 \r
195         u32 rb = srcRB - dstRB;\r
196         u32 xg = srcXG - dstXG;\r
197 \r
198         rb *= alpha;\r
199         xg *= alpha;\r
200         rb >>= 8;\r
201         xg >>= 8;\r
202 \r
203         rb += dstRB;\r
204         xg += dstXG;\r
205 \r
206         rb &= 0x00FF00FF;\r
207         xg &= 0x0000FF00;\r
208 \r
209         return rb | xg;\r
210 }\r
211 \r
212 /*!\r
213         Pixel = dest * ( 1 - alpha ) + source * alpha\r
214         alpha [0;32]\r
215 */\r
216 inline u16 PixelBlend16 ( const u16 c2, const u32 c1, const u16 alpha )\r
217 {\r
218         const u16 srcRB = c1 & 0x7C1F;\r
219         const u16 srcXG = c1 & 0x03E0;\r
220 \r
221         const u16 dstRB = c2 & 0x7C1F;\r
222         const u16 dstXG = c2 & 0x03E0;\r
223 \r
224         u32 rb = srcRB - dstRB;\r
225         u32 xg = srcXG - dstXG;\r
226 \r
227         rb *= alpha;\r
228         xg *= alpha;\r
229         rb >>= 5;\r
230         xg >>= 5;\r
231 \r
232         rb += dstRB;\r
233         xg += dstXG;\r
234 \r
235         rb &= 0x7C1F;\r
236         xg &= 0x03E0;\r
237 \r
238         return (u16)(rb | xg);\r
239 }\r
240 \r
241 /*\r
242         Pixel = c0 * (c1/31). c0 Alpha retain\r
243 */\r
244 inline u16 PixelMul16 ( const u16 c0, const u16 c1)\r
245 {\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
249                         (c0 & 0x8000));\r
250 }\r
251 \r
252 /*\r
253         Pixel = c0 * (c1/31).\r
254 */\r
255 inline u16 PixelMul16_2 ( u16 c0, u16 c1)\r
256 {\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
261 }\r
262 \r
263 /*\r
264         Pixel = c0 * (c1/255). c0 Alpha Retain\r
265 */\r
266 REALINLINE u32 PixelMul32 ( const u32 c0, const u32 c1)\r
267 {\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
272 }\r
273 \r
274 /*\r
275         Pixel = c0 * (c1/255).\r
276 */\r
277 REALINLINE u32 PixelMul32_2 ( const u32 c0, const u32 c1)\r
278 {\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
283 }\r
284 \r
285 /*\r
286         Pixel = clamp ( c0 + c1, 0, 255 )\r
287 */\r
288 REALINLINE u32 PixelAdd32 ( const u32 c2, const u32 c1)\r
289 {\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
296 }\r
297 \r
298 #if 0\r
299 \r
300 // 1 - Bit Alpha Blending\r
301 inline u16 PixelBlend16 ( const u16 destination, const u16 source )\r
302 {\r
303         if((source & 0x8000) == 0x8000)\r
304                 return source; // The source is visible, so use it.\r
305         else\r
306                 return destination; // The source is transparent, so use the destination.\r
307 }\r
308 \r
309 // 1 - Bit Alpha Blending 16Bit SIMD\r
310 inline u32 PixelBlend16_simd ( const u32 destination, const u32 source )\r
311 {\r
312         switch(source & 0x80008000)\r
313         {\r
314                 case 0x80008000: // Both source pixels are visible\r
315                         return source;\r
316 \r
317                 case 0x80000000: // Only the first source pixel is visible\r
318                         return (source & 0xFFFF0000) | (destination & 0x0000FFFF);\r
319 \r
320                 case 0x00008000: // Only the second source pixel is visible.\r
321                         return (destination & 0xFFFF0000) | (source & 0x0000FFFF);\r
322 \r
323                 default: // Neither source pixel is visible.\r
324                         return destination;\r
325         }\r
326 }\r
327 #else\r
328 \r
329 // 1 - Bit Alpha Blending\r
330 inline u16 PixelBlend16 ( const u16 c2, const u16 c1 )\r
331 {\r
332         u16 mask = ((c1 & 0x8000) >> 15 ) + 0x7fff;\r
333         return (c2 & mask ) | ( c1 & ~mask );\r
334 }\r
335 \r
336 // 1 - Bit Alpha Blending 16Bit SIMD\r
337 inline u32 PixelBlend16_simd ( const u32 c2, const u32 c1 )\r
338 {\r
339         u32 mask = ((c1 & 0x80008000) >> 15 ) + 0x7fff7fff;\r
340         return (c2 & mask ) | ( c1 & ~mask );\r
341 }\r
342 \r
343 #endif\r
344 \r
345 /*!\r
346         Pixel = dest * ( 1 - SourceAlpha ) + source * SourceAlpha (OpenGL blending)\r
347 */\r
348 inline u32 PixelBlend32 ( const u32 c2, const u32 c1 )\r
349 {\r
350         // alpha test\r
351         u32 alpha = c1 & 0xFF000000;\r
352 \r
353         if ( 0 == alpha )\r
354                 return c2;\r
355         if ( 0xFF000000 == alpha )\r
356         {\r
357                 return c1;\r
358         }\r
359 \r
360         alpha >>= 24;\r
361 \r
362         // add highbit alpha, if ( alpha > 127 ) alpha += 1;\r
363         alpha += ( alpha >> 7);\r
364 \r
365         u32 srcRB = c1 & 0x00FF00FF;\r
366         u32 srcXG = c1 & 0x0000FF00;\r
367 \r
368         u32 dstRB = c2 & 0x00FF00FF;\r
369         u32 dstXG = c2 & 0x0000FF00;\r
370 \r
371 \r
372         u32 rb = srcRB - dstRB;\r
373         u32 xg = srcXG - dstXG;\r
374 \r
375         rb *= alpha;\r
376         xg *= alpha;\r
377         rb >>= 8;\r
378         xg >>= 8;\r
379 \r
380         rb += dstRB;\r
381         xg += dstXG;\r
382 \r
383         rb &= 0x00FF00FF;\r
384         xg &= 0x0000FF00;\r
385 \r
386         return (c1 & 0xFF000000) | rb | xg;\r
387 }\r
388 \r
389 /*!\r
390         Pixel =>\r
391                         color = sourceAlpha > 0 ? source, else dest\r
392                         alpha = max(destAlpha, sourceAlpha)\r
393 */\r
394 inline u16 PixelCombine16 ( const u16 c2, const u16 c1 )\r
395 {\r
396         if ( video::getAlpha(c1) > 0 )\r
397                 return c1;\r
398         else\r
399                 return c2;\r
400 }\r
401 \r
402 /*!\r
403         Pixel =>\r
404                         color = dest * ( 1 - SourceAlpha ) + source * SourceAlpha,\r
405                         alpha = destAlpha * ( 1 - SourceAlpha ) + sourceAlpha\r
406 \r
407         where "1" means "full scale" (255)\r
408 */\r
409 inline u32 PixelCombine32 ( const u32 c2, const u32 c1 )\r
410 {\r
411         // alpha test\r
412         u32 alpha = c1 & 0xFF000000;\r
413 \r
414         if ( 0 == alpha )\r
415                 return c2;\r
416         if ( 0xFF000000 == alpha )\r
417         {\r
418                 return c1;\r
419         }\r
420 \r
421         alpha >>= 24;\r
422 \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
426 \r
427         u32 srcRB = c1 & 0x00FF00FF;\r
428         u32 srcXG = c1 & 0x0000FF00;\r
429 \r
430         u32 dstRB = c2 & 0x00FF00FF;\r
431         u32 dstXG = c2 & 0x0000FF00;\r
432 \r
433 \r
434         u32 rb = srcRB - dstRB;\r
435         u32 xg = srcXG - dstXG;\r
436 \r
437         rb *= alpha;\r
438         xg *= alpha;\r
439         rb >>= 8;\r
440         xg >>= 8;\r
441 \r
442         rb += dstRB;\r
443         xg += dstXG;\r
444 \r
445         rb &= 0x00FF00FF;\r
446         xg &= 0x0000FF00;\r
447 \r
448         u32 sa = c1 >> 24;\r
449         u32 da = c2 >> 24;\r
450         u32 blendAlpha_fix8 = (sa*256 + da*(256-alpha))>>8;\r
451         return blendAlpha_fix8 << 24 | rb | xg;\r
452 }\r
453 \r
454 \r
455 \r
456 // ------------------ Fix Point ----------------------------------\r
457 \r
458 typedef s32 tFixPoint;\r
459 typedef u32 tFixPointu;\r
460 \r
461 // Fix Point 12\r
462 #if 0\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
470 #endif\r
471 \r
472 // Fix Point 10\r
473 #if 1\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
481 #endif\r
482 \r
483 // Fix Point 9\r
484 #if 0\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
492 #endif\r
493 \r
494 // Fix Point 7\r
495 #if 0\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
503 #endif\r
504 \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
507 \r
508 \r
509 /*\r
510         convert signed integer to fixpoint\r
511 */\r
512 inline tFixPoint s32_to_fixPoint (const s32 x)\r
513 {\r
514         return x << FIX_POINT_PRE;\r
515 }\r
516 \r
517 inline tFixPointu u32_to_fixPoint (const u32 x)\r
518 {\r
519         return x << FIX_POINT_PRE;\r
520 }\r
521 \r
522 inline u32 fixPointu_to_u32 (const tFixPointu x)\r
523 {\r
524         return x >> FIX_POINT_PRE;\r
525 }\r
526 \r
527 \r
528 // 1/x * FIX_POINT\r
529 #define fix_inverse32(x) (FIX_POINT_F32_MUL / (x))\r
530 \r
531 \r
532 /*\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
537 */\r
538 static inline int f_round2(f32 f)\r
539 {\r
540         f += (3<<22);\r
541         return IR(f) - 0x4b400000;\r
542 }\r
543 \r
544 /*\r
545         convert f32 to Fix Point.\r
546         multiply is needed anyway, so scale mulby\r
547 */\r
548 REALINLINE tFixPoint tofix0 (const f32 x, const f32 mulby = FIX_POINT_F32_MUL )\r
549 {\r
550         return (tFixPoint) (x * mulby);\r
551 }\r
552 #define tofix(x,y) (tFixPoint)(x * y)\r
553 \r
554 /*\r
555         Fix Point , Fix Point Multiply\r
556 */\r
557 REALINLINE tFixPointu imulFixu(const tFixPointu x, const tFixPointu y)\r
558 {\r
559         return (x * y) >> (tFixPointu) FIX_POINT_PRE;\r
560 }\r
561 \r
562 /*\r
563         Fix Point , Fix Point Multiply\r
564 */\r
565 REALINLINE tFixPoint imulFix(const tFixPoint x, const tFixPoint y)\r
566 {\r
567         return ( x * y) >> ( FIX_POINT_PRE );\r
568 }\r
569 \r
570 /*\r
571         Fix Point , Fix Point Multiply x * y * 2\r
572 */\r
573 REALINLINE tFixPoint imulFix2(const tFixPoint x, const tFixPoint y)\r
574 {\r
575         return ( x * y) >> ( FIX_POINT_PRE -1 );\r
576 }\r
577 \r
578 \r
579 /*\r
580         Multiply x * y * 1\r
581 */\r
582 REALINLINE tFixPoint imulFix_tex1(const tFixPoint x, const tFixPoint y)\r
583 {\r
584         return ( ( (tFixPointu) x >> 2 ) * ( (tFixPointu) y >> 2 ) ) >> (tFixPointu) ( FIX_POINT_PRE + 4 );\r
585 }\r
586 \r
587 /*\r
588         Multiply x * y * 2\r
589 */\r
590 REALINLINE tFixPoint imulFix_tex2(const tFixPoint x, const tFixPoint y)\r
591 {\r
592         return ( ( (tFixPointu) x >> 2 ) * ( (tFixPointu) y >> 2 ) ) >> (tFixPointu) ( FIX_POINT_PRE + 3 );\r
593 }\r
594 \r
595 /*\r
596         Multiply x * y * 4\r
597 */\r
598 REALINLINE tFixPoint imulFix_tex4(const tFixPoint x, const tFixPoint y)\r
599 {\r
600 #ifdef SOFTWARE_DRIVER_2_32BIT\r
601         return ( ( (tFixPointu) x >> 2 ) * ( (tFixPointu) y >> 2 ) ) >> (tFixPointu) ( FIX_POINT_PRE + 2 );\r
602 #else\r
603         return ( x * y) >> ( FIX_POINT_PRE + ( VIDEO_SAMPLE_GRANULARITY * 3 ) );\r
604 #endif\r
605 }\r
606 \r
607 /*!\r
608         clamp FixPoint to maxcolor in FixPoint, min(a,31)\r
609 */\r
610 REALINLINE tFixPoint clampfix_maxcolor ( const tFixPoint a)\r
611 {\r
612         tFixPoint c = (a - FIXPOINT_COLOR_MAX) >> 31;\r
613         return (a & c) | ( FIXPOINT_COLOR_MAX & ~c);\r
614 }\r
615 \r
616 /*!\r
617         clamp FixPoint to 0 in FixPoint, max(a,0)\r
618 */\r
619 REALINLINE tFixPoint clampfix_mincolor ( const tFixPoint a)\r
620 {\r
621         return a - ( a & ( a >> 31 ) );\r
622 }\r
623 \r
624 REALINLINE tFixPoint saturateFix ( const tFixPoint a)\r
625 {\r
626         return clampfix_mincolor ( clampfix_maxcolor ( a ) );\r
627 }\r
628 \r
629 \r
630 // rount fixpoint to int\r
631 inline s32 roundFix ( const tFixPoint x )\r
632 {\r
633         return ( x + FIX_POINT_ZERO_DOT_FIVE ) >> FIX_POINT_PRE;\r
634 }\r
635 \r
636 \r
637 \r
638 // x in [0;1[\r
639 inline s32 f32_to_23Bits(const f32 x)\r
640 {\r
641         f32 y = x + 1.f;\r
642         return IR(y) & 0x7FFFFF;        // last 23 bits\r
643 }\r
644 \r
645 /*!\r
646         return VideoSample from fixpoint\r
647 */\r
648 REALINLINE tVideoSample fix_to_color ( const tFixPoint r, const tFixPoint g, const tFixPoint b )\r
649 {\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
654 }\r
655 \r
656 \r
657 /*!\r
658         return VideoSample from fixpoint\r
659 */\r
660 REALINLINE tVideoSample fix4_to_color ( const tFixPoint a, const tFixPoint r, const tFixPoint g, const tFixPoint b )\r
661 {\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
666 }\r
667 \r
668 /*!\r
669         return fixpoint from VideoSample granularity COLOR_MAX\r
670 */\r
671 inline void color_to_fix ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 )\r
672 {\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
676 }\r
677 \r
678 /*!\r
679         return fixpoint from VideoSample granularity COLOR_MAX\r
680 */\r
681 inline void color_to_fix ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 )\r
682 {\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
687 }\r
688 \r
689 /*!\r
690         return fixpoint from VideoSample granularity 0..FIX_POINT_ONE\r
691 */\r
692 inline void color_to_fix1 ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 )\r
693 {\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
697 }\r
698 \r
699 /*!\r
700         return fixpoint from VideoSample granularity 0..FIX_POINT_ONE\r
701 */\r
702 inline void color_to_fix1 ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 )\r
703 {\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
708 }\r
709 \r
710 \r
711 \r
712 // ----- FP24 ---- floating point z-buffer\r
713 \r
714 #if 1\r
715 typedef f32 fp24;\r
716 #else\r
717 struct fp24\r
718 {\r
719         u32 v;\r
720 \r
721         fp24() {}\r
722 \r
723         fp24 ( const f32 f )\r
724         {\r
725                 f32 y = f + 1.f;\r
726                 v = ((u32&)y) & 0x7FFFFF;       // last 23 bits\r
727         }\r
728 \r
729         void operator=(const f32 f )\r
730         {\r
731         f32 y = f + 1.f;\r
732                 v = ((u32&)y) & 0x7FFFFF;       // last 23 bits\r
733                 }\r
734 \r
735         void operator+=(const fp24 &other )\r
736         {\r
737                 v += other.v;\r
738         }\r
739 \r
740         operator f32 () const\r
741         {\r
742                 f32 r = FR ( v );\r
743                 return r + 1.f;\r
744         }\r
745 \r
746 };\r
747 #endif\r
748 \r
749 \r
750 // ------------------------ Internal Texture -----------------------------\r
751 \r
752 struct sInternalTexture\r
753 {\r
754         u32 textureXMask;\r
755         u32 textureYMask;\r
756 \r
757         u32 pitchlog2;\r
758         void *data;\r
759 \r
760         video::CSoftwareTexture2 *Texture;\r
761         s32 lodLevel;\r
762 };\r
763 \r
764 \r
765 \r
766 // get video sample plain\r
767 inline tVideoSample getTexel_plain ( const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty )\r
768 {\r
769         u32 ofs;\r
770 \r
771         ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;\r
772         ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );\r
773 \r
774         // texel\r
775         return *((tVideoSample*)( (u8*) t->data + ofs ));\r
776 }\r
777 \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
781                                                                 )\r
782 {\r
783         u32 ofs;\r
784 \r
785         ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;\r
786         ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );\r
787 \r
788         // texel\r
789         tVideoSample t00;\r
790         t00 = *((tVideoSample*)( (u8*) t->data + ofs ));\r
791 \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
795 \r
796 }\r
797 \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
801 {\r
802         u32 ofs;\r
803 \r
804         ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;\r
805         ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );\r
806 \r
807         // texel\r
808         tVideoSample t00;\r
809         t00 = *((tVideoSample*)( (u8*) t->data + ofs ));\r
810 \r
811         a = (t00 & MASK_A) >> ( SHIFT_A - FIX_POINT_PRE);\r
812 }\r
813 \r
814 \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
818                                                                 )\r
819 {\r
820         static const tFixPointu dithermask[] =\r
821         {\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
826         };\r
827 \r
828         const u32 index = (y & 3 ) << 2 | (x & 3);\r
829 \r
830         const tFixPointu _ntx = (tx + dithermask [ index ] ) & t->textureXMask;\r
831         const tFixPointu _nty = (ty + dithermask [ index ] ) & t->textureYMask;\r
832 \r
833         u32 ofs;\r
834         ofs = ( ( _nty ) >> FIX_POINT_PRE ) << t->pitchlog2;\r
835         ofs |= ( _ntx ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );\r
836 \r
837         // texel\r
838         const tVideoSample t00 = *((tVideoSample*)( (u8*) t->data + ofs ));\r
839 \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
843 \r
844 }\r
845 \r
846 /*\r
847         load a sample from internal texture at position tx,ty to fixpoint\r
848 */\r
849 #ifndef SOFTWARE_DRIVER_2_BILINEAR\r
850 \r
851 // get Sample linear == getSample_fixpoint\r
852 \r
853 inline void getSample_texture ( tFixPoint &r, tFixPoint &g, tFixPoint &b,\r
854                                                 const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty\r
855                                                                 )\r
856 {\r
857         u32 ofs;\r
858 \r
859         ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;\r
860         ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );\r
861 \r
862         // texel\r
863         const tVideoSample t00 = *((tVideoSample*)( (u8*) t->data + ofs ));\r
864 \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
868 }\r
869 \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
872                                                                 )\r
873 {\r
874         u32 ofs;\r
875 \r
876         ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;\r
877         ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );\r
878 \r
879         // texel\r
880         const tVideoSample t00 = *((tVideoSample*)( (u8*) t->data + ofs ));\r
881 \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
886 }\r
887 \r
888 \r
889 #else\r
890 \r
891 \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
895                                                                 )\r
896 {\r
897         u32 ofs;\r
898 \r
899         ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;\r
900         ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );\r
901 \r
902         // texel\r
903         tVideoSample t00;\r
904         t00 = *((tVideoSample*)( (u8*) t->data + ofs ));\r
905 \r
906         r =     (t00 & MASK_R) >> SHIFT_R;\r
907         g =     (t00 & MASK_G) >> SHIFT_G;\r
908         b =     (t00 & MASK_B);\r
909 }\r
910 \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
914                                                                 )\r
915 {\r
916 \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
921 \r
922 #if 0\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
927 #else\r
928         u32 o0, o1,o2,o3;\r
929         tVideoSample t00;\r
930 \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
935 \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
940 \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
945 \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
950 \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
955 \r
956 #endif\r
957 \r
958         const tFixPointu txFract = tx & FIX_POINT_FRACT_MASK;\r
959         const tFixPointu txFractInv = FIX_POINT_ONE - txFract;\r
960 \r
961         const tFixPointu tyFract = ty & FIX_POINT_FRACT_MASK;\r
962         const tFixPointu tyFractInv = FIX_POINT_ONE - tyFract;\r
963 \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
968 \r
969         r =             (r00 * w00 ) +\r
970                         (r01 * w01 ) +\r
971                         (r10 * w10 ) +\r
972                         (r11 * w11 );\r
973 \r
974         g =             (g00 * w00 ) +\r
975                         (g01 * w01 ) +\r
976                         (g10 * w10 ) +\r
977                         (g11 * w11 );\r
978 \r
979         b =             (b00 * w00 ) +\r
980                         (b01 * w01 ) +\r
981                         (b10 * w10 ) +\r
982                         (b11 * w11 );\r
983 \r
984 }\r
985 \r
986 \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
990                                                                 )\r
991 {\r
992         u32 ofs;\r
993 \r
994         ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2;\r
995         ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY );\r
996 \r
997         // texel\r
998         tVideoSample t00;\r
999         t00 = *((tVideoSample*)( (u8*) t->data + ofs ));\r
1000 \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
1005 }\r
1006 \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
1010                                                                 )\r
1011 {\r
1012 \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
1017 \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
1022 \r
1023         const tFixPointu txFract = tx & FIX_POINT_FRACT_MASK;\r
1024         const tFixPointu txFractInv = FIX_POINT_ONE - txFract;\r
1025 \r
1026         const tFixPointu tyFract = ty & FIX_POINT_FRACT_MASK;\r
1027         const tFixPointu tyFractInv = FIX_POINT_ONE - tyFract;\r
1028 \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
1033 \r
1034         a =             (a00 * w00 ) +\r
1035                         (a01 * w01 ) +\r
1036                         (a10 * w10 ) +\r
1037                         (a11 * w11 );\r
1038 \r
1039         r =             (r00 * w00 ) +\r
1040                         (r01 * w01 ) +\r
1041                         (r10 * w10 ) +\r
1042                         (r11 * w11 );\r
1043 \r
1044         g =             (g00 * w00 ) +\r
1045                         (g01 * w01 ) +\r
1046                         (g10 * w10 ) +\r
1047                         (g11 * w11 );\r
1048 \r
1049         b =             (b00 * w00 ) +\r
1050                         (b01 * w01 ) +\r
1051                         (b10 * w10 ) +\r
1052                         (b11 * w11 );\r
1053 \r
1054 }\r
1055 \r
1056 \r
1057 #endif\r
1058 \r
1059 // some 2D Defines\r
1060 struct AbsRectangle\r
1061 {\r
1062         s32 x0;\r
1063         s32 y0;\r
1064         s32 x1;\r
1065         s32 y1;\r
1066 };\r
1067 \r
1068 //! 2D Intersection test\r
1069 inline bool intersect ( AbsRectangle &dest, const AbsRectangle& a, const AbsRectangle& b)\r
1070 {\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
1076 }\r
1077 \r
1078 // some 1D defines\r
1079 struct sIntervall\r
1080 {\r
1081         s32 start;\r
1082         s32 end;\r
1083 };\r
1084 \r
1085 // returning intersection width\r
1086 inline s32 intervall_intersect_test( const sIntervall& a, const sIntervall& b)\r
1087 {\r
1088         return core::s32_min( a.end, b.end ) - core::s32_max( a.start, b.start );\r
1089 }\r
1090 \r
1091 \r
1092 } // end namespace irr\r
1093 \r
1094 #endif\r
1095 \r