~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/CBlit.h

  • Committer: Mantas Kriaučiūnas
  • Date: 2011-07-18 13:06:25 UTC
  • Revision ID: mantas@akl.lt-20110718130625-c5pvifp61e7kj1ol
Included whole irrlicht SVN libraries to work around launchpad recipe issue with quilt, see https://answers.launchpad.net/launchpad/+question/165193

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C) 2002-2011 Nikolaus Gebhardt / Thomas Alten
 
2
// This file is part of the "Irrlicht Engine".
 
3
// For conditions of distribution and use, see copyright notice in irrlicht.h
 
4
 
 
5
#ifndef _C_BLIT_H_INCLUDED_
 
6
#define _C_BLIT_H_INCLUDED_
 
7
 
 
8
#include "SoftwareDriver2_helper.h"
 
9
 
 
10
namespace 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
 
 
49
inline 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
 
 
74
static int ClipLine(const AbsRectangle &clipping,
 
75
                        core::position2d<s32> &p0,
 
76
                        core::position2d<s32> &p1,
 
77
                        const core::position2d<s32>& p0_in,
 
78
                        const core::position2d<s32>& p1_in)
 
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
*/
 
160
inline 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
*/
 
172
static 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
*/
 
181
static 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
*/
 
191
inline 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
*/
 
211
static 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
        while ( run )
 
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
        }
 
270
 
 
271
        t->unlock();
 
272
}
 
273
 
 
274
 
 
275
/*
 
276
*/
 
277
static 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
        while ( run )
 
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
        }
 
337
 
 
338
        t->unlock();
 
339
}
 
340
 
 
341
/*
 
342
*/
 
343
static 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
        while ( run )
 
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
        }
 
402
 
 
403
        t->unlock();
 
404
}
 
405
 
 
406
/*
 
407
*/
 
408
static 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
        while ( run )
 
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
        }
 
469
 
 
470
        t->unlock();
 
471
}
 
472
 
 
473
 
 
474
/*!
 
475
*/
 
476
static 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
*/
 
518
static 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
*/
 
564
static 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
*/
 
609
static 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
 
 
649
static 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
*/
 
699
static 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
 
 
742
static 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
*/
 
790
static 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
*/
 
845
static 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
*/
 
886
static 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
*/
 
909
static 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
*/
 
927
static void executeBlit_Color_16_to_16( const SBlitJob * job )
 
928
{
 
929
        u16 *dst = (u16*) job->dst;
 
930
 
 
931
        u16 c0 = video::A8R8G8B8toA1R5G5B5( job->argb );
 
932
        u32 c = c0 | c0 << 16;
 
933
 
 
934
        if ( 0 == (job->srcPitch & 3 ) )
 
935
        {
 
936
                for ( s32 dy = 0; dy != job->height; ++dy )
 
937
                {
 
938
                        memset32( dst, c, job->srcPitch );
 
939
                        dst = (u16*) ( (u8*) (dst) + job->dstPitch );
 
940
                }
 
941
        }
 
942
        else
 
943
        {
 
944
                s32 dx = job->width - 1;
 
945
 
 
946
                for ( s32 dy = 0; dy != job->height; ++dy )
 
947
                {
 
948
                        memset32( dst, c, job->srcPitch );
 
949
                        dst[dx] = c0;
 
950
                        dst = (u16*) ( (u8*) (dst) + job->dstPitch );
 
951
                }
 
952
 
 
953
        }
 
954
}
 
955
 
 
956
/*!
 
957
*/
 
958
static void executeBlit_Color_32_to_32( const SBlitJob * job )
 
959
{
 
960
        u32 *dst = (u32*) job->dst;
 
961
 
 
962
        for ( s32 dy = 0; dy != job->height; ++dy )
 
963
        {
 
964
                memset32( dst, job->argb, job->srcPitch );
 
965
                dst = (u32*) ( (u8*) (dst) + job->dstPitch );
 
966
        }
 
967
}
 
968
 
 
969
/*!
 
970
*/
 
971
static void executeBlit_ColorAlpha_16_to_16( const SBlitJob * job )
 
972
{
 
973
        u16 *dst = (u16*) job->dst;
 
974
 
 
975
        const u16 alpha = extractAlpha( job->argb ) >> 3;
 
976
        if ( 0 == alpha )
 
977
                return;
 
978
        const u32 src = video::A8R8G8B8toA1R5G5B5( job->argb );
 
979
 
 
980
        for ( s32 dy = 0; dy != job->height; ++dy )
 
981
        {
 
982
                for ( s32 dx = 0; dx != job->width; ++dx )
 
983
                {
 
984
                        dst[dx] = 0x8000 | PixelBlend16( dst[dx], src, alpha );
 
985
                }
 
986
                dst = (u16*) ( (u8*) (dst) + job->dstPitch );
 
987
        }
 
988
}
 
989
 
 
990
/*!
 
991
*/
 
992
static void executeBlit_ColorAlpha_32_to_32( const SBlitJob * job )
 
993
{
 
994
        u32 *dst = (u32*) job->dst;
 
995
 
 
996
        const u32 alpha = extractAlpha( job->argb );
 
997
        const u32 src = job->argb;
 
998
 
 
999
        for ( s32 dy = 0; dy != job->height; ++dy )
 
1000
        {
 
1001
                for ( s32 dx = 0; dx != job->width; ++dx )
 
1002
                {
 
1003
                        dst[dx] = (job->argb & 0xFF000000 ) | PixelBlend32( dst[dx], src, alpha );
 
1004
                }
 
1005
                dst = (u32*) ( (u8*) (dst) + job->dstPitch );
 
1006
        }
 
1007
}
 
1008
 
 
1009
// Blitter Operation
 
1010
enum eBlitter
 
1011
{
 
1012
        BLITTER_INVALID = 0,
 
1013
        BLITTER_COLOR,
 
1014
        BLITTER_COLOR_ALPHA,
 
1015
        BLITTER_TEXTURE,
 
1016
        BLITTER_TEXTURE_ALPHA_BLEND,
 
1017
        BLITTER_TEXTURE_ALPHA_COLOR_BLEND
 
1018
};
 
1019
 
 
1020
typedef void (*tExecuteBlit) ( const SBlitJob * job );
 
1021
 
 
1022
 
 
1023
/*!
 
1024
*/
 
1025
struct blitterTable
 
1026
{
 
1027
        eBlitter operation;
 
1028
        s32 destFormat;
 
1029
        s32 sourceFormat;
 
1030
        tExecuteBlit func;
 
1031
};
 
1032
 
 
1033
static const blitterTable blitTable[] =
 
1034
{
 
1035
        { BLITTER_TEXTURE, -2, -2, executeBlit_TextureCopy_x_to_x },
 
1036
        { BLITTER_TEXTURE, video::ECF_A1R5G5B5, video::ECF_A8R8G8B8, executeBlit_TextureCopy_32_to_16 },
 
1037
        { BLITTER_TEXTURE, video::ECF_A1R5G5B5, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_16 },
 
1038
        { BLITTER_TEXTURE, video::ECF_A8R8G8B8, video::ECF_A1R5G5B5, executeBlit_TextureCopy_16_to_32 },
 
1039
        { BLITTER_TEXTURE, video::ECF_A8R8G8B8, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_32 },
 
1040
        { BLITTER_TEXTURE, video::ECF_R8G8B8, video::ECF_A1R5G5B5, executeBlit_TextureCopy_16_to_24 },
 
1041
        { BLITTER_TEXTURE, video::ECF_R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureCopy_32_to_24 },
 
1042
        { BLITTER_TEXTURE_ALPHA_BLEND, video::ECF_A1R5G5B5, video::ECF_A1R5G5B5, executeBlit_TextureBlend_16_to_16 },
 
1043
        { BLITTER_TEXTURE_ALPHA_BLEND, video::ECF_A8R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureBlend_32_to_32 },
 
1044
        { BLITTER_TEXTURE_ALPHA_COLOR_BLEND, video::ECF_A1R5G5B5, video::ECF_A1R5G5B5, executeBlit_TextureBlendColor_16_to_16 },
 
1045
        { BLITTER_TEXTURE_ALPHA_COLOR_BLEND, video::ECF_A8R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureBlendColor_32_to_32 },
 
1046
        { BLITTER_COLOR, video::ECF_A1R5G5B5, -1, executeBlit_Color_16_to_16 },
 
1047
        { BLITTER_COLOR, video::ECF_A8R8G8B8, -1, executeBlit_Color_32_to_32 },
 
1048
        { BLITTER_COLOR_ALPHA, video::ECF_A1R5G5B5, -1, executeBlit_ColorAlpha_16_to_16 },
 
1049
        { BLITTER_COLOR_ALPHA, video::ECF_A8R8G8B8, -1, executeBlit_ColorAlpha_32_to_32 },
 
1050
        { BLITTER_INVALID, -1, -1, 0 }
 
1051
};
 
1052
 
 
1053
 
 
1054
static inline tExecuteBlit getBlitter2( eBlitter operation,const video::IImage * dest,const video::IImage * source )
 
1055
{
 
1056
        video::ECOLOR_FORMAT sourceFormat = (video::ECOLOR_FORMAT) ( source ? source->getColorFormat() : -1 );
 
1057
        video::ECOLOR_FORMAT destFormat = (video::ECOLOR_FORMAT) ( dest ? dest->getColorFormat() : -1 );
 
1058
 
 
1059
        const blitterTable * b = blitTable;
 
1060
 
 
1061
        while ( b->operation != BLITTER_INVALID )
 
1062
        {
 
1063
                if ( b->operation == operation )
 
1064
                {
 
1065
                        if (( b->destFormat == -1 || b->destFormat == destFormat ) &&
 
1066
                                ( b->sourceFormat == -1 || b->sourceFormat == sourceFormat ) )
 
1067
                                        return b->func;
 
1068
                        else
 
1069
                        if ( b->destFormat == -2 && ( sourceFormat == destFormat ) )
 
1070
                                        return b->func;
 
1071
                }
 
1072
                b += 1;
 
1073
        }
 
1074
        return 0;
 
1075
}
 
1076
 
 
1077
 
 
1078
// bounce clipping to texture
 
1079
inline void setClip ( AbsRectangle &out, const core::rect<s32> *clip,
 
1080
                                         const video::IImage * tex, s32 passnative )
 
1081
{
 
1082
        if ( clip && 0 == tex && passnative )
 
1083
        {
 
1084
                out.x0 = clip->UpperLeftCorner.X;
 
1085
                out.x1 = clip->LowerRightCorner.X;
 
1086
                out.y0 = clip->UpperLeftCorner.Y;
 
1087
                out.y1 = clip->LowerRightCorner.Y;
 
1088
                return;
 
1089
        }
 
1090
 
 
1091
        const s32 w = tex ? tex->getDimension().Width : 0;
 
1092
        const s32 h = tex ? tex->getDimension().Height : 0;
 
1093
        if ( clip )
 
1094
        {
 
1095
                out.x0 = core::s32_clamp ( clip->UpperLeftCorner.X, 0, w );
 
1096
                out.x1 = core::s32_clamp ( clip->LowerRightCorner.X, out.x0, w );
 
1097
                out.y0 = core::s32_clamp ( clip->UpperLeftCorner.Y, 0, h );
 
1098
                out.y1 = core::s32_clamp ( clip->LowerRightCorner.Y, out.y0, h );
 
1099
        }
 
1100
        else
 
1101
        {
 
1102
                out.x0 = 0;
 
1103
                out.y0 = 0;
 
1104
                out.x1 = w;
 
1105
                out.y1 = h;
 
1106
        }
 
1107
 
 
1108
}
 
1109
 
 
1110
/*!
 
1111
        a generic 2D Blitter
 
1112
*/
 
1113
static s32 Blit(eBlitter operation,
 
1114
                video::IImage * dest,
 
1115
                const core::rect<s32> *destClipping,
 
1116
                const core::position2d<s32> *destPos,
 
1117
                video::IImage * const source,
 
1118
                const core::rect<s32> *sourceClipping,
 
1119
                u32 argb)
 
1120
{
 
1121
        tExecuteBlit blitter = getBlitter2( operation, dest, source );
 
1122
        if ( 0 == blitter )
 
1123
        {
 
1124
                return 0;
 
1125
        }
 
1126
 
 
1127
        // Clipping
 
1128
        AbsRectangle sourceClip;
 
1129
        AbsRectangle destClip;
 
1130
        AbsRectangle v;
 
1131
 
 
1132
        SBlitJob job;
 
1133
 
 
1134
        setClip ( sourceClip, sourceClipping, source, 1 );
 
1135
        setClip ( destClip, destClipping, dest, 0 );
 
1136
 
 
1137
        v.x0 = destPos ? destPos->X : 0;
 
1138
        v.y0 = destPos ? destPos->Y : 0;
 
1139
        v.x1 = v.x0 + ( sourceClip.x1 - sourceClip.x0 );
 
1140
        v.y1 = v.y0 + ( sourceClip.y1 - sourceClip.y0 );
 
1141
 
 
1142
        if ( !intersect( job.Dest, destClip, v ) )
 
1143
                return 0;
 
1144
 
 
1145
        job.width = job.Dest.x1 - job.Dest.x0;
 
1146
        job.height = job.Dest.y1 - job.Dest.y0;
 
1147
 
 
1148
        job.Source.x0 = sourceClip.x0 + ( job.Dest.x0 - v.x0 );
 
1149
        job.Source.x1 = job.Source.x0 + job.width;
 
1150
        job.Source.y0 = sourceClip.y0 + ( job.Dest.y0 - v.y0 );
 
1151
        job.Source.y1 = job.Source.y0 + job.height;
 
1152
 
 
1153
        job.argb = argb;
 
1154
 
 
1155
        if ( source )
 
1156
        {
 
1157
                job.srcPitch = source->getPitch();
 
1158
                job.srcPixelMul = source->getBytesPerPixel();
 
1159
                job.src = (void*) ( (u8*) source->lock() + ( job.Source.y0 * job.srcPitch ) + ( job.Source.x0 * job.srcPixelMul ) );
 
1160
        }
 
1161
        else
 
1162
        {
 
1163
                // use srcPitch for color operation on dest
 
1164
                job.srcPitch = job.width * dest->getBytesPerPixel();
 
1165
        }
 
1166
 
 
1167
        job.dstPitch = dest->getPitch();
 
1168
        job.dstPixelMul = dest->getBytesPerPixel();
 
1169
        job.dst = (void*) ( (u8*) dest->lock() + ( job.Dest.y0 * job.dstPitch ) + ( job.Dest.x0 * job.dstPixelMul ) );
 
1170
 
 
1171
        blitter( &job );
 
1172
 
 
1173
        if ( source )
 
1174
                source->unlock();
 
1175
 
 
1176
        if ( dest )
 
1177
                dest->unlock();
 
1178
 
 
1179
        return 1;
 
1180
}
 
1181
 
 
1182
static s32 StretchBlit(eBlitter operation,
 
1183
                video::IImage* dest, const core::rect<s32> *destRect,
 
1184
                const core::rect<s32> *srcRect, video::IImage* const source,
 
1185
                u32 argb)
 
1186
{
 
1187
        tExecuteBlit blitter = getBlitter2( operation, dest, source );
 
1188
        if ( 0 == blitter )
 
1189
        {
 
1190
                return 0;
 
1191
        }
 
1192
 
 
1193
        SBlitJob job;
 
1194
 
 
1195
        // Clipping
 
1196
        setClip ( job.Source, srcRect, source, 1 );
 
1197
        setClip ( job.Dest, destRect, dest, 0 );
 
1198
 
 
1199
        job.width = job.Dest.x1-job.Dest.x0;
 
1200
        job.height = job.Dest.y1-job.Dest.y0;
 
1201
 
 
1202
        job.argb = argb;
 
1203
 
 
1204
        // use original dest size, despite any clipping
 
1205
        job.x_stretch = (float)destRect->getWidth() / (float)(job.Source.x1-job.Source.x0);
 
1206
        job.y_stretch = (float)destRect->getHeight() / (float)(job.Source.y1-job.Source.y0);
 
1207
        job.stretch = (job.x_stretch != 1.f) || (job.y_stretch != 1.f);
 
1208
 
 
1209
        if ( source )
 
1210
        {
 
1211
                job.srcPitch = source->getPitch();
 
1212
                job.srcPixelMul = source->getBytesPerPixel();
 
1213
                job.src = (void*) ( (u8*) source->lock() + ( job.Source.y0 * job.srcPitch ) + ( job.Source.x0 * job.srcPixelMul ) );
 
1214
        }
 
1215
        else
 
1216
        {
 
1217
                // use srcPitch for color operation on dest
 
1218
                job.srcPitch = job.width * dest->getBytesPerPixel();
 
1219
        }
 
1220
 
 
1221
        job.dstPitch = dest->getPitch();
 
1222
        job.dstPixelMul = dest->getBytesPerPixel();
 
1223
        job.dst = (void*) ( (u8*) dest->lock() + ( job.Dest.y0 * job.dstPitch ) + ( job.Dest.x0 * job.dstPixelMul ) );
 
1224
 
 
1225
        blitter( &job );
 
1226
 
 
1227
        if ( source )
 
1228
                source->unlock();
 
1229
 
 
1230
        if ( dest )
 
1231
                dest->unlock();
 
1232
 
 
1233
        return 1;
 
1234
}
 
1235
 
 
1236
 
 
1237
// Methods for Software drivers
 
1238
//! draws a rectangle
 
1239
static void drawRectangle(video::IImage* img, const core::rect<s32>& rect, const video::SColor &color)
 
1240
{
 
1241
        Blit(color.getAlpha() == 0xFF ? BLITTER_COLOR : BLITTER_COLOR_ALPHA,
 
1242
                        img, 0, &rect.UpperLeftCorner, 0, &rect, color.color);
 
1243
}
 
1244
 
 
1245
 
 
1246
//! draws a line from to with color
 
1247
static void drawLine(video::IImage* img, const core::position2d<s32>& from,
 
1248
                                         const core::position2d<s32>& to, const video::SColor &color)
 
1249
{
 
1250
        AbsRectangle clip;
 
1251
        GetClip(clip, img);
 
1252
 
 
1253
        core::position2d<s32> p[2];
 
1254
        if (ClipLine( clip, p[0], p[1], from, to))
 
1255
        {
 
1256
                u32 alpha = extractAlpha(color.color);
 
1257
 
 
1258
                switch(img->getColorFormat())
 
1259
                {
 
1260
                case video::ECF_A1R5G5B5:
 
1261
                                if (alpha == 256)
 
1262
                                {
 
1263
                                        RenderLine16_Decal(img, p[0], p[1], video::A8R8G8B8toA1R5G5B5(color.color));
 
1264
                                }
 
1265
                                else
 
1266
                                {
 
1267
                                        RenderLine16_Blend(img, p[0], p[1], video::A8R8G8B8toA1R5G5B5(color.color), alpha >> 3);
 
1268
                                }
 
1269
                                break;
 
1270
                case video::ECF_A8R8G8B8:
 
1271
                                if (alpha == 256)
 
1272
                                {
 
1273
                                        RenderLine32_Decal(img, p[0], p[1], color.color);
 
1274
                                }
 
1275
                                else
 
1276
                                {
 
1277
                                        RenderLine32_Blend(img, p[0], p[1], color.color, alpha);
 
1278
                                }
 
1279
                                break;
 
1280
                default:
 
1281
                                break;
 
1282
                }
 
1283
        }
 
1284
}
 
1285
 
 
1286
 
 
1287
}
 
1288
 
 
1289
#endif
 
1290