limited minimize support
[sdl_omap.git] / src / video / SDL_blit_1.c
CommitLineData
e14743d1 1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#include "SDL_video.h"
25#include "SDL_blit.h"
26#include "SDL_sysvideo.h"
27#include "SDL_endian.h"
28
29/* Functions to blit from 8-bit surfaces to other surfaces */
30
31static void Blit1to1(SDL_BlitInfo *info)
32{
33#ifndef USE_DUFFS_LOOP
34 int c;
35#endif
36 int width, height;
37 Uint8 *src, *map, *dst;
38 int srcskip, dstskip;
39
40 /* Set up some basic variables */
41 width = info->d_width;
42 height = info->d_height;
43 src = info->s_pixels;
44 srcskip = info->s_skip;
45 dst = info->d_pixels;
46 dstskip = info->d_skip;
47 map = info->table;
48
49 while ( height-- ) {
50#ifdef USE_DUFFS_LOOP
51 DUFFS_LOOP(
52 {
53 *dst = map[*src];
54 }
55 dst++;
56 src++;
57 , width);
58#else
59 for ( c=width; c; --c ) {
60 *dst = map[*src];
61 dst++;
62 src++;
63 }
64#endif
65 src += srcskip;
66 dst += dstskip;
67 }
68}
69/* This is now endian dependent */
70#if ( SDL_BYTEORDER == SDL_LIL_ENDIAN )
71#define HI 1
72#define LO 0
73#else /* ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) */
74#define HI 0
75#define LO 1
76#endif
77static void Blit1to2(SDL_BlitInfo *info)
78{
79#ifndef USE_DUFFS_LOOP
80 int c;
81#endif
82 int width, height;
83 Uint8 *src, *dst;
84 Uint16 *map;
85 int srcskip, dstskip;
86
87 /* Set up some basic variables */
88 width = info->d_width;
89 height = info->d_height;
90 src = info->s_pixels;
91 srcskip = info->s_skip;
92 dst = info->d_pixels;
93 dstskip = info->d_skip;
94 map = (Uint16 *)info->table;
95
96#ifdef USE_DUFFS_LOOP
97 while ( height-- ) {
98 DUFFS_LOOP(
99 {
100 *(Uint16 *)dst = map[*src++];
101 dst += 2;
102 },
103 width);
104 src += srcskip;
105 dst += dstskip;
106 }
107#else
108 /* Memory align at 4-byte boundary, if necessary */
109 if ( (long)dst & 0x03 ) {
110 /* Don't do anything if width is 0 */
111 if ( width == 0 ) {
112 return;
113 }
114 --width;
115
116 while ( height-- ) {
117 /* Perform copy alignment */
118 *(Uint16 *)dst = map[*src++];
119 dst += 2;
120
121 /* Copy in 4 pixel chunks */
122 for ( c=width/4; c; --c ) {
123 *(Uint32 *)dst =
124 (map[src[HI]]<<16)|(map[src[LO]]);
125 src += 2;
126 dst += 4;
127 *(Uint32 *)dst =
128 (map[src[HI]]<<16)|(map[src[LO]]);
129 src += 2;
130 dst += 4;
131 }
132 /* Get any leftovers */
133 switch (width & 3) {
134 case 3:
135 *(Uint16 *)dst = map[*src++];
136 dst += 2;
137 case 2:
138 *(Uint32 *)dst =
139 (map[src[HI]]<<16)|(map[src[LO]]);
140 src += 2;
141 dst += 4;
142 break;
143 case 1:
144 *(Uint16 *)dst = map[*src++];
145 dst += 2;
146 break;
147 }
148 src += srcskip;
149 dst += dstskip;
150 }
151 } else {
152 while ( height-- ) {
153 /* Copy in 4 pixel chunks */
154 for ( c=width/4; c; --c ) {
155 *(Uint32 *)dst =
156 (map[src[HI]]<<16)|(map[src[LO]]);
157 src += 2;
158 dst += 4;
159 *(Uint32 *)dst =
160 (map[src[HI]]<<16)|(map[src[LO]]);
161 src += 2;
162 dst += 4;
163 }
164 /* Get any leftovers */
165 switch (width & 3) {
166 case 3:
167 *(Uint16 *)dst = map[*src++];
168 dst += 2;
169 case 2:
170 *(Uint32 *)dst =
171 (map[src[HI]]<<16)|(map[src[LO]]);
172 src += 2;
173 dst += 4;
174 break;
175 case 1:
176 *(Uint16 *)dst = map[*src++];
177 dst += 2;
178 break;
179 }
180 src += srcskip;
181 dst += dstskip;
182 }
183 }
184#endif /* USE_DUFFS_LOOP */
185}
186static void Blit1to3(SDL_BlitInfo *info)
187{
188#ifndef USE_DUFFS_LOOP
189 int c;
190#endif
191 int o;
192 int width, height;
193 Uint8 *src, *map, *dst;
194 int srcskip, dstskip;
195
196 /* Set up some basic variables */
197 width = info->d_width;
198 height = info->d_height;
199 src = info->s_pixels;
200 srcskip = info->s_skip;
201 dst = info->d_pixels;
202 dstskip = info->d_skip;
203 map = info->table;
204
205 while ( height-- ) {
206#ifdef USE_DUFFS_LOOP
207 DUFFS_LOOP(
208 {
209 o = *src * 4;
210 dst[0] = map[o++];
211 dst[1] = map[o++];
212 dst[2] = map[o++];
213 }
214 src++;
215 dst += 3;
216 , width);
217#else
218 for ( c=width; c; --c ) {
219 o = *src * 4;
220 dst[0] = map[o++];
221 dst[1] = map[o++];
222 dst[2] = map[o++];
223 src++;
224 dst += 3;
225 }
226#endif /* USE_DUFFS_LOOP */
227 src += srcskip;
228 dst += dstskip;
229 }
230}
231static void Blit1to4(SDL_BlitInfo *info)
232{
233#ifndef USE_DUFFS_LOOP
234 int c;
235#endif
236 int width, height;
237 Uint8 *src;
238 Uint32 *map, *dst;
239 int srcskip, dstskip;
240
241 /* Set up some basic variables */
242 width = info->d_width;
243 height = info->d_height;
244 src = info->s_pixels;
245 srcskip = info->s_skip;
246 dst = (Uint32 *)info->d_pixels;
247 dstskip = info->d_skip/4;
248 map = (Uint32 *)info->table;
249
250 while ( height-- ) {
251#ifdef USE_DUFFS_LOOP
252 DUFFS_LOOP(
253 *dst++ = map[*src++];
254 , width);
255#else
256 for ( c=width/4; c; --c ) {
257 *dst++ = map[*src++];
258 *dst++ = map[*src++];
259 *dst++ = map[*src++];
260 *dst++ = map[*src++];
261 }
262 switch ( width & 3 ) {
263 case 3:
264 *dst++ = map[*src++];
265 case 2:
266 *dst++ = map[*src++];
267 case 1:
268 *dst++ = map[*src++];
269 }
270#endif /* USE_DUFFS_LOOP */
271 src += srcskip;
272 dst += dstskip;
273 }
274}
275
276static void Blit1to1Key(SDL_BlitInfo *info)
277{
278 int width = info->d_width;
279 int height = info->d_height;
280 Uint8 *src = info->s_pixels;
281 int srcskip = info->s_skip;
282 Uint8 *dst = info->d_pixels;
283 int dstskip = info->d_skip;
284 Uint8 *palmap = info->table;
285 Uint32 ckey = info->src->colorkey;
286
287 if ( palmap ) {
288 while ( height-- ) {
289 DUFFS_LOOP(
290 {
291 if ( *src != ckey ) {
292 *dst = palmap[*src];
293 }
294 dst++;
295 src++;
296 },
297 width);
298 src += srcskip;
299 dst += dstskip;
300 }
301 } else {
302 while ( height-- ) {
303 DUFFS_LOOP(
304 {
305 if ( *src != ckey ) {
306 *dst = *src;
307 }
308 dst++;
309 src++;
310 },
311 width);
312 src += srcskip;
313 dst += dstskip;
314 }
315 }
316}
317
318static void Blit1to2Key(SDL_BlitInfo *info)
319{
320 int width = info->d_width;
321 int height = info->d_height;
322 Uint8 *src = info->s_pixels;
323 int srcskip = info->s_skip;
324 Uint16 *dstp = (Uint16 *)info->d_pixels;
325 int dstskip = info->d_skip;
326 Uint16 *palmap = (Uint16 *)info->table;
327 Uint32 ckey = info->src->colorkey;
328
329 /* Set up some basic variables */
330 dstskip /= 2;
331
332 while ( height-- ) {
333 DUFFS_LOOP(
334 {
335 if ( *src != ckey ) {
336 *dstp=palmap[*src];
337 }
338 src++;
339 dstp++;
340 },
341 width);
342 src += srcskip;
343 dstp += dstskip;
344 }
345}
346
347static void Blit1to3Key(SDL_BlitInfo *info)
348{
349 int width = info->d_width;
350 int height = info->d_height;
351 Uint8 *src = info->s_pixels;
352 int srcskip = info->s_skip;
353 Uint8 *dst = info->d_pixels;
354 int dstskip = info->d_skip;
355 Uint8 *palmap = info->table;
356 Uint32 ckey = info->src->colorkey;
357 int o;
358
359 while ( height-- ) {
360 DUFFS_LOOP(
361 {
362 if ( *src != ckey ) {
363 o = *src * 4;
364 dst[0] = palmap[o++];
365 dst[1] = palmap[o++];
366 dst[2] = palmap[o++];
367 }
368 src++;
369 dst += 3;
370 },
371 width);
372 src += srcskip;
373 dst += dstskip;
374 }
375}
376
377static void Blit1to4Key(SDL_BlitInfo *info)
378{
379 int width = info->d_width;
380 int height = info->d_height;
381 Uint8 *src = info->s_pixels;
382 int srcskip = info->s_skip;
383 Uint32 *dstp = (Uint32 *)info->d_pixels;
384 int dstskip = info->d_skip;
385 Uint32 *palmap = (Uint32 *)info->table;
386 Uint32 ckey = info->src->colorkey;
387
388 /* Set up some basic variables */
389 dstskip /= 4;
390
391 while ( height-- ) {
392 DUFFS_LOOP(
393 {
394 if ( *src != ckey ) {
395 *dstp = palmap[*src];
396 }
397 src++;
398 dstp++;
399 },
400 width);
401 src += srcskip;
402 dstp += dstskip;
403 }
404}
405
406static void Blit1toNAlpha(SDL_BlitInfo *info)
407{
408 int width = info->d_width;
409 int height = info->d_height;
410 Uint8 *src = info->s_pixels;
411 int srcskip = info->s_skip;
412 Uint8 *dst = info->d_pixels;
413 int dstskip = info->d_skip;
414 SDL_PixelFormat *dstfmt = info->dst;
415 const SDL_Color *srcpal = info->src->palette->colors;
416 int dstbpp;
417 const int A = info->src->alpha;
418
419 /* Set up some basic variables */
420 dstbpp = dstfmt->BytesPerPixel;
421
422 while ( height-- ) {
423 int sR, sG, sB;
424 int dR, dG, dB;
425 DUFFS_LOOP4(
426 {
427 Uint32 pixel;
428 sR = srcpal[*src].r;
429 sG = srcpal[*src].g;
430 sB = srcpal[*src].b;
431 DISEMBLE_RGB(dst, dstbpp, dstfmt,
432 pixel, dR, dG, dB);
433 ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
434 ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB);
435 src++;
436 dst += dstbpp;
437 },
438 width);
439 src += srcskip;
440 dst += dstskip;
441 }
442}
443
444static void Blit1toNAlphaKey(SDL_BlitInfo *info)
445{
446 int width = info->d_width;
447 int height = info->d_height;
448 Uint8 *src = info->s_pixels;
449 int srcskip = info->s_skip;
450 Uint8 *dst = info->d_pixels;
451 int dstskip = info->d_skip;
452 SDL_PixelFormat *srcfmt = info->src;
453 SDL_PixelFormat *dstfmt = info->dst;
454 const SDL_Color *srcpal = info->src->palette->colors;
455 Uint32 ckey = srcfmt->colorkey;
456 int dstbpp;
457 const int A = srcfmt->alpha;
458
459 /* Set up some basic variables */
460 dstbpp = dstfmt->BytesPerPixel;
461
462 while ( height-- ) {
463 int sR, sG, sB;
464 int dR, dG, dB;
465 DUFFS_LOOP(
466 {
467 if ( *src != ckey ) {
468 Uint32 pixel;
469 sR = srcpal[*src].r;
470 sG = srcpal[*src].g;
471 sB = srcpal[*src].b;
472 DISEMBLE_RGB(dst, dstbpp, dstfmt,
473 pixel, dR, dG, dB);
474 ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
475 ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB);
476 }
477 src++;
478 dst += dstbpp;
479 },
480 width);
481 src += srcskip;
482 dst += dstskip;
483 }
484}
485
486static SDL_loblit one_blit[] = {
487 NULL, Blit1to1, Blit1to2, Blit1to3, Blit1to4
488};
489
490static SDL_loblit one_blitkey[] = {
491 NULL, Blit1to1Key, Blit1to2Key, Blit1to3Key, Blit1to4Key
492};
493
494SDL_loblit SDL_CalculateBlit1(SDL_Surface *surface, int blit_index)
495{
496 int which;
497 SDL_PixelFormat *dstfmt;
498
499 dstfmt = surface->map->dst->format;
500 if ( dstfmt->BitsPerPixel < 8 ) {
501 which = 0;
502 } else {
503 which = dstfmt->BytesPerPixel;
504 }
505 switch(blit_index) {
506 case 0: /* copy */
507 return one_blit[which];
508
509 case 1: /* colorkey */
510 return one_blitkey[which];
511
512 case 2: /* alpha */
513 /* Supporting 8bpp->8bpp alpha is doable but requires lots of
514 tables which consume space and takes time to precompute,
515 so is better left to the user */
516 return which >= 2 ? Blit1toNAlpha : NULL;
517
518 case 3: /* alpha + colorkey */
519 return which >= 2 ? Blit1toNAlphaKey : NULL;
520
521 }
522 return NULL;
523}