aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/source/Irrlicht/CBlit.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/CBlit.h')
-rw-r--r--src/others/irrlicht-1.8.1/source/Irrlicht/CBlit.h1273
1 files changed, 1273 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/CBlit.h b/src/others/irrlicht-1.8.1/source/Irrlicht/CBlit.h
new file mode 100644
index 0000000..a8572e9
--- /dev/null
+++ b/src/others/irrlicht-1.8.1/source/Irrlicht/CBlit.h
@@ -0,0 +1,1273 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten
2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h
4
5#ifndef _C_BLIT_H_INCLUDED_
6#define _C_BLIT_H_INCLUDED_
7
8#include "SoftwareDriver2_helper.h"
9
10namespace irr
11{
12
13 struct SBlitJob
14 {
15 AbsRectangle Dest;
16 AbsRectangle Source;
17
18 u32 argb;
19
20 void * src;
21 void * dst;
22
23 s32 width;
24 s32 height;
25
26 u32 srcPitch;
27 u32 dstPitch;
28
29 u32 srcPixelMul;
30 u32 dstPixelMul;
31
32 bool stretch;
33 float x_stretch;
34 float y_stretch;
35
36 SBlitJob() : stretch(false) {}
37 };
38
39 // Bitfields Cohen Sutherland
40 enum eClipCode
41 {
42 CLIPCODE_EMPTY = 0,
43 CLIPCODE_BOTTOM = 1,
44 CLIPCODE_TOP = 2,
45 CLIPCODE_LEFT = 4,
46 CLIPCODE_RIGHT = 8
47 };
48
49inline u32 GetClipCode( const AbsRectangle &r, const core::position2d<s32> &p )
50{
51 u32 code = CLIPCODE_EMPTY;
52
53 if ( p.X < r.x0 )
54 code = CLIPCODE_LEFT;
55 else
56 if ( p.X > r.x1 )
57 code = CLIPCODE_RIGHT;
58
59 if ( p.Y < r.y0 )
60 code |= CLIPCODE_TOP;
61 else
62 if ( p.Y > r.y1 )
63 code |= CLIPCODE_BOTTOM;
64
65 return code;
66}
67
68
69/*!
70 Cohen Sutherland clipping
71 @return: 1 if valid
72*/
73
74static int ClipLine(const AbsRectangle &clipping,
75 core::position2d<s32> &p0,
76 core::position2d<s32> &p1,
77 const core::position2d<s32>& p0_in,
78 const core::position2d<s32>& p1_in)
79{
80 u32 code0;
81 u32 code1;
82 u32 code;
83
84 p0 = p0_in;
85 p1 = p1_in;
86
87 code0 = GetClipCode( clipping, p0 );
88 code1 = GetClipCode( clipping, p1 );
89
90 // trivial accepted
91 while ( code0 | code1 )
92 {
93 s32 x=0;
94 s32 y=0;
95
96 // trivial reject
97 if ( code0 & code1 )
98 return 0;
99
100 if ( code0 )
101 {
102 // clip first point
103 code = code0;
104 }
105 else
106 {
107 // clip last point
108 code = code1;
109 }
110
111 if ( (code & CLIPCODE_BOTTOM) == CLIPCODE_BOTTOM )
112 {
113 // clip bottom viewport
114 y = clipping.y1;
115 x = p0.X + ( p1.X - p0.X ) * ( y - p0.Y ) / ( p1.Y - p0.Y );
116 }
117 else
118 if ( (code & CLIPCODE_TOP) == CLIPCODE_TOP )
119 {
120 // clip to viewport
121 y = clipping.y0;
122 x = p0.X + ( p1.X - p0.X ) * ( y - p0.Y ) / ( p1.Y - p0.Y );
123 }
124 else
125 if ( (code & CLIPCODE_RIGHT) == CLIPCODE_RIGHT )
126 {
127 // clip right viewport
128 x = clipping.x1;
129 y = p0.Y + ( p1.Y - p0.Y ) * ( x - p0.X ) / ( p1.X - p0.X );
130 }
131 else
132 if ( (code & CLIPCODE_LEFT) == CLIPCODE_LEFT )
133 {
134 // clip left viewport
135 x = clipping.x0;
136 y = p0.Y + ( p1.Y - p0.Y ) * ( x - p0.X ) / ( p1.X - p0.X );
137 }
138
139 if ( code == code0 )
140 {
141 // modify first point
142 p0.X = x;
143 p0.Y = y;
144 code0 = GetClipCode( clipping, p0 );
145 }
146 else
147 {
148 // modify second point
149 p1.X = x;
150 p1.Y = y;
151 code1 = GetClipCode( clipping, p1 );
152 }
153 }
154
155 return 1;
156}
157
158/*
159*/
160inline void GetClip(AbsRectangle &clipping, video::IImage * t)
161{
162 clipping.x0 = 0;
163 clipping.y0 = 0;
164 clipping.x1 = t->getDimension().Width - 1;
165 clipping.y1 = t->getDimension().Height - 1;
166}
167
168/*
169 return alpha in [0;256] Granularity from 32-Bit ARGB
170 add highbit alpha ( alpha > 127 ? + 1 )
171*/
172static inline u32 extractAlpha(const u32 c)
173{
174 return ( c >> 24 ) + ( c >> 31 );
175}
176
177/*
178 return alpha in [0;255] Granularity and 32-Bit ARGB
179 add highbit alpha ( alpha > 127 ? + 1 )
180*/
181static inline u32 packAlpha(const u32 c)
182{
183 return (c > 127 ? c - 1 : c) << 24;
184}
185
186
187/*!
188 Scale Color by (1/value)
189 value 0 - 256 ( alpha )
190*/
191inline u32 PixelLerp32(const u32 source, const u32 value)
192{
193 u32 srcRB = source & 0x00FF00FF;
194 u32 srcXG = (source & 0xFF00FF00) >> 8;
195
196 srcRB *= value;
197 srcXG *= value;
198
199 srcRB >>= 8;
200 //srcXG >>= 8;
201
202 srcXG &= 0xFF00FF00;
203 srcRB &= 0x00FF00FF;
204
205 return srcRB | srcXG;
206}
207
208
209/*
210*/
211static void RenderLine32_Decal(video::IImage *t,
212 const core::position2d<s32> &p0,
213 const core::position2d<s32> &p1,
214 u32 argb )
215{
216 s32 dx = p1.X - p0.X;
217 s32 dy = p1.Y - p0.Y;
218
219 s32 c;
220 s32 m;
221 s32 d = 0;
222 s32 run;
223
224 s32 xInc = 4;
225 s32 yInc = (s32) t->getPitch();
226
227 if ( dx < 0 )
228 {
229 xInc = -xInc;
230 dx = -dx;
231 }
232
233 if ( dy < 0 )
234 {
235 yInc = -yInc;
236 dy = -dy;
237 }
238
239 u32 *dst;
240 dst = (u32*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 2 ) );
241
242 if ( dy > dx )
243 {
244 s32 tmp;
245 tmp = dx;
246 dx = dy;
247 dy = tmp;
248 tmp = xInc;
249 xInc = yInc;
250 yInc = tmp;
251 }
252
253 c = dx << 1;
254 m = dy << 1;
255
256 run = dx;
257 do
258 {
259 *dst = argb;
260
261 dst = (u32*) ( (u8*) dst + xInc ); // x += xInc
262 d += m;
263 if ( d > dx )
264 {
265 dst = (u32*) ( (u8*) dst + yInc ); // y += yInc
266 d -= c;
267 }
268 run -= 1;
269 } while (run>=0);
270
271 t->unlock();
272}
273
274
275/*
276*/
277static void RenderLine32_Blend(video::IImage *t,
278 const core::position2d<s32> &p0,
279 const core::position2d<s32> &p1,
280 u32 argb, u32 alpha)
281{
282 s32 dx = p1.X - p0.X;
283 s32 dy = p1.Y - p0.Y;
284
285 s32 c;
286 s32 m;
287 s32 d = 0;
288 s32 run;
289
290 s32 xInc = 4;
291 s32 yInc = (s32) t->getPitch();
292
293 if ( dx < 0 )
294 {
295 xInc = -xInc;
296 dx = -dx;
297 }
298
299 if ( dy < 0 )
300 {
301 yInc = -yInc;
302 dy = -dy;
303 }
304
305 u32 *dst;
306 dst = (u32*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 2 ) );
307
308 if ( dy > dx )
309 {
310 s32 tmp;
311 tmp = dx;
312 dx = dy;
313 dy = tmp;
314 tmp = xInc;
315 xInc = yInc;
316 yInc = tmp;
317 }
318
319 c = dx << 1;
320 m = dy << 1;
321
322 run = dx;
323 const u32 packA = packAlpha ( alpha );
324 do
325 {
326 *dst = packA | PixelBlend32( *dst, argb, alpha );
327
328 dst = (u32*) ( (u8*) dst + xInc ); // x += xInc
329 d += m;
330 if ( d > dx )
331 {
332 dst = (u32*) ( (u8*) dst + yInc ); // y += yInc
333 d -= c;
334 }
335 run -= 1;
336 } while (run>=0);
337
338 t->unlock();
339}
340
341/*
342*/
343static void RenderLine16_Decal(video::IImage *t,
344 const core::position2d<s32> &p0,
345 const core::position2d<s32> &p1,
346 u32 argb )
347{
348 s32 dx = p1.X - p0.X;
349 s32 dy = p1.Y - p0.Y;
350
351 s32 c;
352 s32 m;
353 s32 d = 0;
354 s32 run;
355
356 s32 xInc = 2;
357 s32 yInc = (s32) t->getPitch();
358
359 if ( dx < 0 )
360 {
361 xInc = -xInc;
362 dx = -dx;
363 }
364
365 if ( dy < 0 )
366 {
367 yInc = -yInc;
368 dy = -dy;
369 }
370
371 u16 *dst;
372 dst = (u16*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 1 ) );
373
374 if ( dy > dx )
375 {
376 s32 tmp;
377 tmp = dx;
378 dx = dy;
379 dy = tmp;
380 tmp = xInc;
381 xInc = yInc;
382 yInc = tmp;
383 }
384
385 c = dx << 1;
386 m = dy << 1;
387
388 run = dx;
389 do
390 {
391 *dst = (u16)argb;
392
393 dst = (u16*) ( (u8*) dst + xInc ); // x += xInc
394 d += m;
395 if ( d > dx )
396 {
397 dst = (u16*) ( (u8*) dst + yInc ); // y += yInc
398 d -= c;
399 }
400 run -= 1;
401 } while (run>=0);
402
403 t->unlock();
404}
405
406/*
407*/
408static void RenderLine16_Blend(video::IImage *t,
409 const core::position2d<s32> &p0,
410 const core::position2d<s32> &p1,
411 u16 argb,
412 u16 alpha)
413{
414 s32 dx = p1.X - p0.X;
415 s32 dy = p1.Y - p0.Y;
416
417 s32 c;
418 s32 m;
419 s32 d = 0;
420 s32 run;
421
422 s32 xInc = 2;
423 s32 yInc = (s32) t->getPitch();
424
425 if ( dx < 0 )
426 {
427 xInc = -xInc;
428 dx = -dx;
429 }
430
431 if ( dy < 0 )
432 {
433 yInc = -yInc;
434 dy = -dy;
435 }
436
437 u16 *dst;
438 dst = (u16*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 1 ) );
439
440 if ( dy > dx )
441 {
442 s32 tmp;
443 tmp = dx;
444 dx = dy;
445 dy = tmp;
446 tmp = xInc;
447 xInc = yInc;
448 yInc = tmp;
449 }
450
451 c = dx << 1;
452 m = dy << 1;
453
454 run = dx;
455 const u16 packA = alpha ? 0x8000 : 0;
456 do
457 {
458 *dst = packA | PixelBlend16( *dst, argb, alpha );
459
460 dst = (u16*) ( (u8*) dst + xInc ); // x += xInc
461 d += m;
462 if ( d > dx )
463 {
464 dst = (u16*) ( (u8*) dst + yInc ); // y += yInc
465 d -= c;
466 }
467 run -= 1;
468 } while (run>=0);
469
470 t->unlock();
471}
472
473
474/*!
475*/
476static void executeBlit_TextureCopy_x_to_x( const SBlitJob * job )
477{
478 const u32 w = job->width;
479 const u32 h = job->height;
480 if (job->stretch)
481 {
482 const u32 *src = static_cast<const u32*>(job->src);
483 u32 *dst = static_cast<u32*>(job->dst);
484 const float wscale = 1.f/job->x_stretch;
485 const float hscale = 1.f/job->y_stretch;
486
487 for ( u32 dy = 0; dy < h; ++dy )
488 {
489 const u32 src_y = (u32)(dy*hscale);
490 src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y );
491
492 for ( u32 dx = 0; dx < w; ++dx )
493 {
494 const u32 src_x = (u32)(dx*wscale);
495 dst[dx] = src[src_x];
496 }
497 dst = (u32*) ( (u8*) (dst) + job->dstPitch );
498 }
499 }
500 else
501 {
502 const u32 widthPitch = job->width * job->dstPixelMul;
503 const void *src = (void*) job->src;
504 void *dst = (void*) job->dst;
505
506 for ( u32 dy = 0; dy != h; ++dy )
507 {
508 memcpy( dst, src, widthPitch );
509
510 src = (void*) ( (u8*) (src) + job->srcPitch );
511 dst = (void*) ( (u8*) (dst) + job->dstPitch );
512 }
513 }
514}
515
516/*!
517*/
518static void executeBlit_TextureCopy_32_to_16( const SBlitJob * job )
519{
520 const u32 w = job->width;
521 const u32 h = job->height;
522 const u32 *src = static_cast<const u32*>(job->src);
523 u16 *dst = static_cast<u16*>(job->dst);
524
525 if (job->stretch)
526 {
527 const float wscale = 1.f/job->x_stretch;
528 const float hscale = 1.f/job->y_stretch;
529
530 for ( u32 dy = 0; dy < h; ++dy )
531 {
532 const u32 src_y = (u32)(dy*hscale);
533 src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y );
534
535 for ( u32 dx = 0; dx < w; ++dx )
536 {
537 const u32 src_x = (u32)(dx*wscale);
538 //16 bit Blitter depends on pre-multiplied color
539 const u32 s = PixelLerp32( src[src_x] | 0xFF000000, extractAlpha( src[src_x] ) );
540 dst[dx] = video::A8R8G8B8toA1R5G5B5( s );
541 }
542 dst = (u16*) ( (u8*) (dst) + job->dstPitch );
543 }
544 }
545 else
546 {
547 for ( u32 dy = 0; dy != h; ++dy )
548 {
549 for ( u32 dx = 0; dx != w; ++dx )
550 {
551 //16 bit Blitter depends on pre-multiplied color
552 const u32 s = PixelLerp32( src[dx] | 0xFF000000, extractAlpha( src[dx] ) );
553 dst[dx] = video::A8R8G8B8toA1R5G5B5( s );
554 }
555
556 src = (u32*) ( (u8*) (src) + job->srcPitch );
557 dst = (u16*) ( (u8*) (dst) + job->dstPitch );
558 }
559 }
560}
561
562/*!
563*/
564static void executeBlit_TextureCopy_24_to_16( const SBlitJob * job )
565{
566 const u32 w = job->width;
567 const u32 h = job->height;
568 const u8 *src = static_cast<const u8*>(job->src);
569 u16 *dst = static_cast<u16*>(job->dst);
570
571 if (job->stretch)
572 {
573 const float wscale = 3.f/job->x_stretch;
574 const float hscale = 1.f/job->y_stretch;
575
576 for ( u32 dy = 0; dy < h; ++dy )
577 {
578 const u32 src_y = (u32)(dy*hscale);
579 src = (u8*)(job->src) + job->srcPitch*src_y;
580
581 for ( u32 dx = 0; dx < w; ++dx )
582 {
583 const u8* src_x = src+(u32)(dx*wscale);
584 dst[dx] = video::RGBA16(src_x[0], src_x[1], src_x[2]);
585 }
586 dst = (u16*) ( (u8*) (dst) + job->dstPitch );
587 }
588 }
589 else
590 {
591 for ( u32 dy = 0; dy != h; ++dy )
592 {
593 const u8* s = src;
594 for ( u32 dx = 0; dx != w; ++dx )
595 {
596 dst[dx] = video::RGBA16(s[0], s[1], s[2]);
597 s += 3;
598 }
599
600 src = src+job->srcPitch;
601 dst = (u16*) ( (u8*) (dst) + job->dstPitch );
602 }
603 }
604}
605
606
607/*!
608*/
609static void executeBlit_TextureCopy_16_to_32( const SBlitJob * job )
610{
611 const u32 w = job->width;
612 const u32 h = job->height;
613 const u16 *src = static_cast<const u16*>(job->src);
614 u32 *dst = static_cast<u32*>(job->dst);
615
616 if (job->stretch)
617 {
618 const float wscale = 1.f/job->x_stretch;
619 const float hscale = 1.f/job->y_stretch;
620
621 for ( u32 dy = 0; dy < h; ++dy )
622 {
623 const u32 src_y = (u32)(dy*hscale);
624 src = (u16*) ( (u8*) (job->src) + job->srcPitch*src_y );
625
626 for ( u32 dx = 0; dx < w; ++dx )
627 {
628 const u32 src_x = (u32)(dx*wscale);
629 dst[dx] = video::A1R5G5B5toA8R8G8B8(src[src_x]);
630 }
631 dst = (u32*) ( (u8*) (dst) + job->dstPitch );
632 }
633 }
634 else
635 {
636 for ( u32 dy = 0; dy != h; ++dy )
637 {
638 for ( u32 dx = 0; dx != w; ++dx )
639 {
640 dst[dx] = video::A1R5G5B5toA8R8G8B8( src[dx] );
641 }
642
643 src = (u16*) ( (u8*) (src) + job->srcPitch );
644 dst = (u32*) ( (u8*) (dst) + job->dstPitch );
645 }
646 }
647}
648
649static void executeBlit_TextureCopy_16_to_24( const SBlitJob * job )
650{
651 const u32 w = job->width;
652 const u32 h = job->height;
653 const u16 *src = static_cast<const u16*>(job->src);
654 u8 *dst = static_cast<u8*>(job->dst);
655
656 if (job->stretch)
657 {
658 const float wscale = 1.f/job->x_stretch;
659 const float hscale = 1.f/job->y_stretch;
660
661 for ( u32 dy = 0; dy < h; ++dy )
662 {
663 const u32 src_y = (u32)(dy*hscale);
664 src = (u16*) ( (u8*) (job->src) + job->srcPitch*src_y );
665
666 for ( u32 dx = 0; dx < w; ++dx )
667 {
668 const u32 src_x = (u32)(dx*wscale);
669 u32 color = video::A1R5G5B5toA8R8G8B8(src[src_x]);
670 u8 * writeTo = &dst[dx * 3];
671 *writeTo++ = (color >> 16)& 0xFF;
672 *writeTo++ = (color >> 8) & 0xFF;
673 *writeTo++ = color & 0xFF;
674 }
675 dst += job->dstPitch;
676 }
677 }
678 else
679 {
680 for ( u32 dy = 0; dy != h; ++dy )
681 {
682 for ( u32 dx = 0; dx != w; ++dx )
683 {
684 u32 color = video::A1R5G5B5toA8R8G8B8(src[dx]);
685 u8 * writeTo = &dst[dx * 3];
686 *writeTo++ = (color >> 16)& 0xFF;
687 *writeTo++ = (color >> 8) & 0xFF;
688 *writeTo++ = color & 0xFF;
689 }
690
691 src = (u16*) ( (u8*) (src) + job->srcPitch );
692 dst += job->dstPitch;
693 }
694 }
695}
696
697/*!
698*/
699static void executeBlit_TextureCopy_24_to_32( const SBlitJob * job )
700{
701 const u32 w = job->width;
702 const u32 h = job->height;
703 const u8 *src = static_cast<const u8*>(job->src);
704 u32 *dst = static_cast<u32*>(job->dst);
705
706 if (job->stretch)
707 {
708 const float wscale = 3.f/job->x_stretch;
709 const float hscale = 1.f/job->y_stretch;
710
711 for ( u32 dy = 0; dy < h; ++dy )
712 {
713 const u32 src_y = (u32)(dy*hscale);
714 src = (const u8*)job->src+(job->srcPitch*src_y);
715
716 for ( u32 dx = 0; dx < w; ++dx )
717 {
718 const u8* s = src+(u32)(dx*wscale);
719 dst[dx] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2];
720 }
721 dst = (u32*) ( (u8*) (dst) + job->dstPitch );
722 }
723 }
724 else
725 {
726 for ( s32 dy = 0; dy != job->height; ++dy )
727 {
728 const u8* s = src;
729
730 for ( s32 dx = 0; dx != job->width; ++dx )
731 {
732 dst[dx] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2];
733 s += 3;
734 }
735
736 src = src + job->srcPitch;
737 dst = (u32*) ( (u8*) (dst) + job->dstPitch );
738 }
739 }
740}
741
742static void executeBlit_TextureCopy_32_to_24( const SBlitJob * job )
743{
744 const u32 w = job->width;
745 const u32 h = job->height;
746 const u32 *src = static_cast<const u32*>(job->src);
747 u8 *dst = static_cast<u8*>(job->dst);
748
749 if (job->stretch)
750 {
751 const float wscale = 1.f/job->x_stretch;
752 const float hscale = 1.f/job->y_stretch;
753
754 for ( u32 dy = 0; dy < h; ++dy )
755 {
756 const u32 src_y = (u32)(dy*hscale);
757 src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y);
758
759 for ( u32 dx = 0; dx < w; ++dx )
760 {
761 const u32 src_x = src[(u32)(dx*wscale)];
762 u8 * writeTo = &dst[dx * 3];
763 *writeTo++ = (src_x >> 16)& 0xFF;
764 *writeTo++ = (src_x >> 8) & 0xFF;
765 *writeTo++ = src_x & 0xFF;
766 }
767 dst += job->dstPitch;
768 }
769 }
770 else
771 {
772 for ( u32 dy = 0; dy != h; ++dy )
773 {
774 for ( u32 dx = 0; dx != w; ++dx )
775 {
776 u8 * writeTo = &dst[dx * 3];
777 *writeTo++ = (src[dx] >> 16)& 0xFF;
778 *writeTo++ = (src[dx] >> 8) & 0xFF;
779 *writeTo++ = src[dx] & 0xFF;
780 }
781
782 src = (u32*) ( (u8*) (src) + job->srcPitch );
783 dst += job->dstPitch;
784 }
785 }
786}
787
788/*!
789*/
790static void executeBlit_TextureBlend_16_to_16( const SBlitJob * job )
791{
792 const u32 w = job->width;
793 const u32 h = job->height;
794 const u32 rdx = w>>1;
795
796 const u32 *src = (u32*) job->src;
797 u32 *dst = (u32*) job->dst;
798
799 if (job->stretch)
800 {
801 const float wscale = 1.f/job->x_stretch;
802 const float hscale = 1.f/job->y_stretch;
803 const u32 off = core::if_c_a_else_b(w&1, (u32)((w-1)*wscale), 0);
804 for ( u32 dy = 0; dy < h; ++dy )
805 {
806 const u32 src_y = (u32)(dy*hscale);
807 src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y );
808
809 for ( u32 dx = 0; dx < rdx; ++dx )
810 {
811 const u32 src_x = (u32)(dx*wscale);
812 dst[dx] = PixelBlend16_simd( dst[dx], src[src_x] );
813 }
814 if ( off )
815 {
816 ((u16*) dst)[off] = PixelBlend16( ((u16*) dst)[off], ((u16*) src)[off] );
817 }
818
819 dst = (u32*) ( (u8*) (dst) + job->dstPitch );
820 }
821 }
822 else
823 {
824 const u32 off = core::if_c_a_else_b(w&1, w-1, 0);
825 for (u32 dy = 0; dy != h; ++dy )
826 {
827 for (u32 dx = 0; dx != rdx; ++dx )
828 {
829 dst[dx] = PixelBlend16_simd( dst[dx], src[dx] );
830 }
831
832 if ( off )
833 {
834 ((u16*) dst)[off] = PixelBlend16( ((u16*) dst)[off], ((u16*) src)[off] );
835 }
836
837 src = (u32*) ( (u8*) (src) + job->srcPitch );
838 dst = (u32*) ( (u8*) (dst) + job->dstPitch );
839 }
840 }
841}
842
843/*!
844*/
845static void executeBlit_TextureBlend_32_to_32( const SBlitJob * job )
846{
847 const u32 w = job->width;
848 const u32 h = job->height;
849 const u32 *src = (u32*) job->src;
850 u32 *dst = (u32*) job->dst;
851
852 if (job->stretch)
853 {
854 const float wscale = 1.f/job->x_stretch;
855 const float hscale = 1.f/job->y_stretch;
856 for ( u32 dy = 0; dy < h; ++dy )
857 {
858 const u32 src_y = (u32)(dy*hscale);
859 src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y );
860
861 for ( u32 dx = 0; dx < w; ++dx )
862 {
863 const u32 src_x = (u32)(dx*wscale);
864 dst[dx] = PixelBlend32( dst[dx], src[src_x] );
865 }
866
867 dst = (u32*) ( (u8*) (dst) + job->dstPitch );
868 }
869 }
870 else
871 {
872 for ( u32 dy = 0; dy != h; ++dy )
873 {
874 for ( u32 dx = 0; dx != w; ++dx )
875 {
876 dst[dx] = PixelBlend32( dst[dx], src[dx] );
877 }
878 src = (u32*) ( (u8*) (src) + job->srcPitch );
879 dst = (u32*) ( (u8*) (dst) + job->dstPitch );
880 }
881 }
882}
883
884/*!
885*/
886static void executeBlit_TextureBlendColor_16_to_16( const SBlitJob * job )
887{
888 u16 *src = (u16*) job->src;
889 u16 *dst = (u16*) job->dst;
890
891 u16 blend = video::A8R8G8B8toA1R5G5B5 ( job->argb );
892 for ( s32 dy = 0; dy != job->height; ++dy )
893 {
894 for ( s32 dx = 0; dx != job->width; ++dx )
895 {
896 if ( 0 == (src[dx] & 0x8000) )
897 continue;
898
899 dst[dx] = PixelMul16_2( src[dx], blend );
900 }
901 src = (u16*) ( (u8*) (src) + job->srcPitch );
902 dst = (u16*) ( (u8*) (dst) + job->dstPitch );
903 }
904}
905
906
907/*!
908*/
909static void executeBlit_TextureBlendColor_32_to_32( const SBlitJob * job )
910{
911 u32 *src = (u32*) job->src;
912 u32 *dst = (u32*) job->dst;
913
914 for ( s32 dy = 0; dy != job->height; ++dy )
915 {
916 for ( s32 dx = 0; dx != job->width; ++dx )
917 {
918 dst[dx] = PixelBlend32( dst[dx], PixelMul32_2( src[dx], job->argb ) );
919 }
920 src = (u32*) ( (u8*) (src) + job->srcPitch );
921 dst = (u32*) ( (u8*) (dst) + job->dstPitch );
922 }
923}
924
925/*!
926*/
927static void executeBlit_Color_16_to_16( const SBlitJob * job )
928{
929 const u16 c = video::A8R8G8B8toA1R5G5B5(job->argb);
930 u16 *dst = (u16*) job->dst;
931
932 for ( s32 dy = 0; dy != job->height; ++dy )
933 {
934 memset16(dst, c, job->srcPitch);
935 dst = (u16*) ( (u8*) (dst) + job->dstPitch );
936 }
937}
938
939/*!
940*/
941static void executeBlit_Color_32_to_32( const SBlitJob * job )
942{
943 u32 *dst = (u32*) job->dst;
944
945 for ( s32 dy = 0; dy != job->height; ++dy )
946 {
947 memset32( dst, job->argb, job->srcPitch );
948 dst = (u32*) ( (u8*) (dst) + job->dstPitch );
949 }
950}
951
952/*!
953*/
954static void executeBlit_ColorAlpha_16_to_16( const SBlitJob * job )
955{
956 u16 *dst = (u16*) job->dst;
957
958 const u16 alpha = extractAlpha( job->argb ) >> 3;
959 if ( 0 == alpha )
960 return;
961 const u32 src = video::A8R8G8B8toA1R5G5B5( job->argb );
962
963 for ( s32 dy = 0; dy != job->height; ++dy )
964 {
965 for ( s32 dx = 0; dx != job->width; ++dx )
966 {
967 dst[dx] = 0x8000 | PixelBlend16( dst[dx], src, alpha );
968 }
969 dst = (u16*) ( (u8*) (dst) + job->dstPitch );
970 }
971}
972
973/*!
974*/
975static void executeBlit_ColorAlpha_32_to_32( const SBlitJob * job )
976{
977 u32 *dst = (u32*) job->dst;
978
979 const u32 alpha = extractAlpha( job->argb );
980 const u32 src = job->argb;
981
982 for ( s32 dy = 0; dy != job->height; ++dy )
983 {
984 for ( s32 dx = 0; dx != job->width; ++dx )
985 {
986 dst[dx] = (job->argb & 0xFF000000 ) | PixelBlend32( dst[dx], src, alpha );
987 }
988 dst = (u32*) ( (u8*) (dst) + job->dstPitch );
989 }
990}
991
992// Blitter Operation
993enum eBlitter
994{
995 BLITTER_INVALID = 0,
996 BLITTER_COLOR,
997 BLITTER_COLOR_ALPHA,
998 BLITTER_TEXTURE,
999 BLITTER_TEXTURE_ALPHA_BLEND,
1000 BLITTER_TEXTURE_ALPHA_COLOR_BLEND
1001};
1002
1003typedef void (*tExecuteBlit) ( const SBlitJob * job );
1004
1005
1006/*!
1007*/
1008struct blitterTable
1009{
1010 eBlitter operation;
1011 s32 destFormat;
1012 s32 sourceFormat;
1013 tExecuteBlit func;
1014};
1015
1016static const blitterTable blitTable[] =
1017{
1018 { BLITTER_TEXTURE, -2, -2, executeBlit_TextureCopy_x_to_x },
1019 { BLITTER_TEXTURE, video::ECF_A1R5G5B5, video::ECF_A8R8G8B8, executeBlit_TextureCopy_32_to_16 },
1020 { BLITTER_TEXTURE, video::ECF_A1R5G5B5, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_16 },
1021 { BLITTER_TEXTURE, video::ECF_A8R8G8B8, video::ECF_A1R5G5B5, executeBlit_TextureCopy_16_to_32 },
1022 { BLITTER_TEXTURE, video::ECF_A8R8G8B8, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_32 },
1023 { BLITTER_TEXTURE, video::ECF_R8G8B8, video::ECF_A1R5G5B5, executeBlit_TextureCopy_16_to_24 },
1024 { BLITTER_TEXTURE, video::ECF_R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureCopy_32_to_24 },
1025 { BLITTER_TEXTURE_ALPHA_BLEND, video::ECF_A1R5G5B5, video::ECF_A1R5G5B5, executeBlit_TextureBlend_16_to_16 },
1026 { BLITTER_TEXTURE_ALPHA_BLEND, video::ECF_A8R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureBlend_32_to_32 },
1027 { BLITTER_TEXTURE_ALPHA_COLOR_BLEND, video::ECF_A1R5G5B5, video::ECF_A1R5G5B5, executeBlit_TextureBlendColor_16_to_16 },
1028 { BLITTER_TEXTURE_ALPHA_COLOR_BLEND, video::ECF_A8R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureBlendColor_32_to_32 },
1029 { BLITTER_COLOR, video::ECF_A1R5G5B5, -1, executeBlit_Color_16_to_16 },
1030 { BLITTER_COLOR, video::ECF_A8R8G8B8, -1, executeBlit_Color_32_to_32 },
1031 { BLITTER_COLOR_ALPHA, video::ECF_A1R5G5B5, -1, executeBlit_ColorAlpha_16_to_16 },
1032 { BLITTER_COLOR_ALPHA, video::ECF_A8R8G8B8, -1, executeBlit_ColorAlpha_32_to_32 },
1033 { BLITTER_INVALID, -1, -1, 0 }
1034};
1035
1036
1037static inline tExecuteBlit getBlitter2( eBlitter operation,const video::IImage * dest,const video::IImage * source )
1038{
1039 video::ECOLOR_FORMAT sourceFormat = (video::ECOLOR_FORMAT) ( source ? source->getColorFormat() : -1 );
1040 video::ECOLOR_FORMAT destFormat = (video::ECOLOR_FORMAT) ( dest ? dest->getColorFormat() : -1 );
1041
1042 const blitterTable * b = blitTable;
1043
1044 while ( b->operation != BLITTER_INVALID )
1045 {
1046 if ( b->operation == operation )
1047 {
1048 if (( b->destFormat == -1 || b->destFormat == destFormat ) &&
1049 ( b->sourceFormat == -1 || b->sourceFormat == sourceFormat ) )
1050 return b->func;
1051 else
1052 if ( b->destFormat == -2 && ( sourceFormat == destFormat ) )
1053 return b->func;
1054 }
1055 b += 1;
1056 }
1057 return 0;
1058}
1059
1060
1061// bounce clipping to texture
1062inline void setClip ( AbsRectangle &out, const core::rect<s32> *clip,
1063 const video::IImage * tex, s32 passnative )
1064{
1065 if ( clip && 0 == tex && passnative )
1066 {
1067 out.x0 = clip->UpperLeftCorner.X;
1068 out.x1 = clip->LowerRightCorner.X;
1069 out.y0 = clip->UpperLeftCorner.Y;
1070 out.y1 = clip->LowerRightCorner.Y;
1071 return;
1072 }
1073
1074 const s32 w = tex ? tex->getDimension().Width : 0;
1075 const s32 h = tex ? tex->getDimension().Height : 0;
1076 if ( clip )
1077 {
1078 out.x0 = core::s32_clamp ( clip->UpperLeftCorner.X, 0, w );
1079 out.x1 = core::s32_clamp ( clip->LowerRightCorner.X, out.x0, w );
1080 out.y0 = core::s32_clamp ( clip->UpperLeftCorner.Y, 0, h );
1081 out.y1 = core::s32_clamp ( clip->LowerRightCorner.Y, out.y0, h );
1082 }
1083 else
1084 {
1085 out.x0 = 0;
1086 out.y0 = 0;
1087 out.x1 = w;
1088 out.y1 = h;
1089 }
1090
1091}
1092
1093/*!
1094 a generic 2D Blitter
1095*/
1096static s32 Blit(eBlitter operation,
1097 video::IImage * dest,
1098 const core::rect<s32> *destClipping,
1099 const core::position2d<s32> *destPos,
1100 video::IImage * const source,
1101 const core::rect<s32> *sourceClipping,
1102 u32 argb)
1103{
1104 tExecuteBlit blitter = getBlitter2( operation, dest, source );
1105 if ( 0 == blitter )
1106 {
1107 return 0;
1108 }
1109
1110 // Clipping
1111 AbsRectangle sourceClip;
1112 AbsRectangle destClip;
1113 AbsRectangle v;
1114
1115 SBlitJob job;
1116
1117 setClip ( sourceClip, sourceClipping, source, 1 );
1118 setClip ( destClip, destClipping, dest, 0 );
1119
1120 v.x0 = destPos ? destPos->X : 0;
1121 v.y0 = destPos ? destPos->Y : 0;
1122 v.x1 = v.x0 + ( sourceClip.x1 - sourceClip.x0 );
1123 v.y1 = v.y0 + ( sourceClip.y1 - sourceClip.y0 );
1124
1125 if ( !intersect( job.Dest, destClip, v ) )
1126 return 0;
1127
1128 job.width = job.Dest.x1 - job.Dest.x0;
1129 job.height = job.Dest.y1 - job.Dest.y0;
1130
1131 job.Source.x0 = sourceClip.x0 + ( job.Dest.x0 - v.x0 );
1132 job.Source.x1 = job.Source.x0 + job.width;
1133 job.Source.y0 = sourceClip.y0 + ( job.Dest.y0 - v.y0 );
1134 job.Source.y1 = job.Source.y0 + job.height;
1135
1136 job.argb = argb;
1137
1138 if ( source )
1139 {
1140 job.srcPitch = source->getPitch();
1141 job.srcPixelMul = source->getBytesPerPixel();
1142 job.src = (void*) ( (u8*) source->lock() + ( job.Source.y0 * job.srcPitch ) + ( job.Source.x0 * job.srcPixelMul ) );
1143 }
1144 else
1145 {
1146 // use srcPitch for color operation on dest
1147 job.srcPitch = job.width * dest->getBytesPerPixel();
1148 }
1149
1150 job.dstPitch = dest->getPitch();
1151 job.dstPixelMul = dest->getBytesPerPixel();
1152 job.dst = (void*) ( (u8*) dest->lock() + ( job.Dest.y0 * job.dstPitch ) + ( job.Dest.x0 * job.dstPixelMul ) );
1153
1154 blitter( &job );
1155
1156 if ( source )
1157 source->unlock();
1158
1159 if ( dest )
1160 dest->unlock();
1161
1162 return 1;
1163}
1164
1165static s32 StretchBlit(eBlitter operation,
1166 video::IImage* dest, const core::rect<s32> *destRect,
1167 const core::rect<s32> *srcRect, video::IImage* const source,
1168 u32 argb)
1169{
1170 tExecuteBlit blitter = getBlitter2( operation, dest, source );
1171 if ( 0 == blitter )
1172 {
1173 return 0;
1174 }
1175
1176 SBlitJob job;
1177
1178 // Clipping
1179 setClip ( job.Source, srcRect, source, 1 );
1180 setClip ( job.Dest, destRect, dest, 0 );
1181
1182 job.width = job.Dest.x1-job.Dest.x0;
1183 job.height = job.Dest.y1-job.Dest.y0;
1184
1185 job.argb = argb;
1186
1187 // use original dest size, despite any clipping
1188 job.x_stretch = (float)destRect->getWidth() / (float)(job.Source.x1-job.Source.x0);
1189 job.y_stretch = (float)destRect->getHeight() / (float)(job.Source.y1-job.Source.y0);
1190 job.stretch = (job.x_stretch != 1.f) || (job.y_stretch != 1.f);
1191
1192 if ( source )
1193 {
1194 job.srcPitch = source->getPitch();
1195 job.srcPixelMul = source->getBytesPerPixel();
1196 job.src = (void*) ( (u8*) source->lock() + ( job.Source.y0 * job.srcPitch ) + ( job.Source.x0 * job.srcPixelMul ) );
1197 }
1198 else
1199 {
1200 // use srcPitch for color operation on dest
1201 job.srcPitch = job.width * dest->getBytesPerPixel();
1202 }
1203
1204 job.dstPitch = dest->getPitch();
1205 job.dstPixelMul = dest->getBytesPerPixel();
1206 job.dst = (void*) ( (u8*) dest->lock() + ( job.Dest.y0 * job.dstPitch ) + ( job.Dest.x0 * job.dstPixelMul ) );
1207
1208 blitter( &job );
1209
1210 if ( source )
1211 source->unlock();
1212
1213 if ( dest )
1214 dest->unlock();
1215
1216 return 1;
1217}
1218
1219
1220// Methods for Software drivers
1221//! draws a rectangle
1222static void drawRectangle(video::IImage* img, const core::rect<s32>& rect, const video::SColor &color)
1223{
1224 Blit(color.getAlpha() == 0xFF ? BLITTER_COLOR : BLITTER_COLOR_ALPHA,
1225 img, 0, &rect.UpperLeftCorner, 0, &rect, color.color);
1226}
1227
1228
1229//! draws a line from to with color
1230static void drawLine(video::IImage* img, const core::position2d<s32>& from,
1231 const core::position2d<s32>& to, const video::SColor &color)
1232{
1233 AbsRectangle clip;
1234 GetClip(clip, img);
1235
1236 core::position2d<s32> p[2];
1237 if (ClipLine( clip, p[0], p[1], from, to))
1238 {
1239 u32 alpha = extractAlpha(color.color);
1240
1241 switch(img->getColorFormat())
1242 {
1243 case video::ECF_A1R5G5B5:
1244 if (alpha == 256)
1245 {
1246 RenderLine16_Decal(img, p[0], p[1], video::A8R8G8B8toA1R5G5B5(color.color));
1247 }
1248 else
1249 {
1250 RenderLine16_Blend(img, p[0], p[1], video::A8R8G8B8toA1R5G5B5(color.color), alpha >> 3);
1251 }
1252 break;
1253 case video::ECF_A8R8G8B8:
1254 if (alpha == 256)
1255 {
1256 RenderLine32_Decal(img, p[0], p[1], color.color);
1257 }
1258 else
1259 {
1260 RenderLine32_Blend(img, p[0], p[1], color.color, alpha);
1261 }
1262 break;
1263 default:
1264 break;
1265 }
1266 }
1267}
1268
1269
1270}
1271
1272#endif
1273