diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CBlit.h | 1273 |
1 files changed, 1273 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CBlit.h b/libraries/irrlicht-1.8/source/Irrlicht/CBlit.h new file mode 100644 index 0000000..a8572e9 --- /dev/null +++ b/libraries/irrlicht-1.8/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 | |||
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 | 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 | */ | ||
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 | 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 | */ | ||
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 | 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 | */ | ||
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 | 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 | */ | ||
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 | 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 | */ | ||
941 | static 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 | */ | ||
954 | static 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 | */ | ||
975 | static 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 | ||
993 | enum 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 | |||
1003 | typedef void (*tExecuteBlit) ( const SBlitJob * job ); | ||
1004 | |||
1005 | |||
1006 | /*! | ||
1007 | */ | ||
1008 | struct blitterTable | ||
1009 | { | ||
1010 | eBlitter operation; | ||
1011 | s32 destFormat; | ||
1012 | s32 sourceFormat; | ||
1013 | tExecuteBlit func; | ||
1014 | }; | ||
1015 | |||
1016 | static 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 | |||
1037 | static 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 | ||
1062 | inline 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 | */ | ||
1096 | static 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 | |||
1165 | static 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 | ||
1222 | static 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 | ||
1230 | static 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 | |||