SDL_blit_1.c (12710B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../SDL_internal.h" 22 23#include "SDL_video.h" 24#include "SDL_blit.h" 25#include "SDL_sysvideo.h" 26#include "SDL_endian.h" 27 28/* Functions to blit from 8-bit surfaces to other surfaces */ 29 30static void 31Blit1to1(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->dst_w; 42 height = info->dst_h; 43 src = info->src; 44 srcskip = info->src_skip; 45 dst = info->dst; 46 dstskip = info->dst_skip; 47 map = info->table; 48 49 while (height--) { 50#ifdef USE_DUFFS_LOOP 51 /* *INDENT-OFF* */ 52 DUFFS_LOOP( 53 { 54 *dst = map[*src]; 55 } 56 dst++; 57 src++; 58 , width); 59 /* *INDENT-ON* */ 60#else 61 for (c = width; c; --c) { 62 *dst = map[*src]; 63 dst++; 64 src++; 65 } 66#endif 67 src += srcskip; 68 dst += dstskip; 69 } 70} 71 72/* This is now endian dependent */ 73#if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) 74#define HI 1 75#define LO 0 76#else /* ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) */ 77#define HI 0 78#define LO 1 79#endif 80static void 81Blit1to2(SDL_BlitInfo * info) 82{ 83#ifndef USE_DUFFS_LOOP 84 int c; 85#endif 86 int width, height; 87 Uint8 *src, *dst; 88 Uint16 *map; 89 int srcskip, dstskip; 90 91 /* Set up some basic variables */ 92 width = info->dst_w; 93 height = info->dst_h; 94 src = info->src; 95 srcskip = info->src_skip; 96 dst = info->dst; 97 dstskip = info->dst_skip; 98 map = (Uint16 *) info->table; 99 100#ifdef USE_DUFFS_LOOP 101 while (height--) { 102 /* *INDENT-OFF* */ 103 DUFFS_LOOP( 104 { 105 *(Uint16 *)dst = map[*src++]; 106 dst += 2; 107 }, 108 width); 109 /* *INDENT-ON* */ 110 src += srcskip; 111 dst += dstskip; 112 } 113#else 114 /* Memory align at 4-byte boundary, if necessary */ 115 if ((long) dst & 0x03) { 116 /* Don't do anything if width is 0 */ 117 if (width == 0) { 118 return; 119 } 120 --width; 121 122 while (height--) { 123 /* Perform copy alignment */ 124 *(Uint16 *) dst = map[*src++]; 125 dst += 2; 126 127 /* Copy in 4 pixel chunks */ 128 for (c = width / 4; c; --c) { 129 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]); 130 src += 2; 131 dst += 4; 132 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]); 133 src += 2; 134 dst += 4; 135 } 136 /* Get any leftovers */ 137 switch (width & 3) { 138 case 3: 139 *(Uint16 *) dst = map[*src++]; 140 dst += 2; 141 case 2: 142 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]); 143 src += 2; 144 dst += 4; 145 break; 146 case 1: 147 *(Uint16 *) dst = map[*src++]; 148 dst += 2; 149 break; 150 } 151 src += srcskip; 152 dst += dstskip; 153 } 154 } else { 155 while (height--) { 156 /* Copy in 4 pixel chunks */ 157 for (c = width / 4; c; --c) { 158 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]); 159 src += 2; 160 dst += 4; 161 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]); 162 src += 2; 163 dst += 4; 164 } 165 /* Get any leftovers */ 166 switch (width & 3) { 167 case 3: 168 *(Uint16 *) dst = map[*src++]; 169 dst += 2; 170 case 2: 171 *(Uint32 *) dst = (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} 186 187static void 188Blit1to3(SDL_BlitInfo * info) 189{ 190#ifndef USE_DUFFS_LOOP 191 int c; 192#endif 193 int o; 194 int width, height; 195 Uint8 *src, *map, *dst; 196 int srcskip, dstskip; 197 198 /* Set up some basic variables */ 199 width = info->dst_w; 200 height = info->dst_h; 201 src = info->src; 202 srcskip = info->src_skip; 203 dst = info->dst; 204 dstskip = info->dst_skip; 205 map = info->table; 206 207 while (height--) { 208#ifdef USE_DUFFS_LOOP 209 /* *INDENT-OFF* */ 210 DUFFS_LOOP( 211 { 212 o = *src * 4; 213 dst[0] = map[o++]; 214 dst[1] = map[o++]; 215 dst[2] = map[o++]; 216 } 217 src++; 218 dst += 3; 219 , width); 220 /* *INDENT-ON* */ 221#else 222 for (c = width; c; --c) { 223 o = *src * 4; 224 dst[0] = map[o++]; 225 dst[1] = map[o++]; 226 dst[2] = map[o++]; 227 src++; 228 dst += 3; 229 } 230#endif /* USE_DUFFS_LOOP */ 231 src += srcskip; 232 dst += dstskip; 233 } 234} 235 236static void 237Blit1to4(SDL_BlitInfo * info) 238{ 239#ifndef USE_DUFFS_LOOP 240 int c; 241#endif 242 int width, height; 243 Uint8 *src; 244 Uint32 *map, *dst; 245 int srcskip, dstskip; 246 247 /* Set up some basic variables */ 248 width = info->dst_w; 249 height = info->dst_h; 250 src = info->src; 251 srcskip = info->src_skip; 252 dst = (Uint32 *) info->dst; 253 dstskip = info->dst_skip / 4; 254 map = (Uint32 *) info->table; 255 256 while (height--) { 257#ifdef USE_DUFFS_LOOP 258 /* *INDENT-OFF* */ 259 DUFFS_LOOP( 260 *dst++ = map[*src++]; 261 , width); 262 /* *INDENT-ON* */ 263#else 264 for (c = width / 4; c; --c) { 265 *dst++ = map[*src++]; 266 *dst++ = map[*src++]; 267 *dst++ = map[*src++]; 268 *dst++ = map[*src++]; 269 } 270 switch (width & 3) { 271 case 3: 272 *dst++ = map[*src++]; 273 case 2: 274 *dst++ = map[*src++]; 275 case 1: 276 *dst++ = map[*src++]; 277 } 278#endif /* USE_DUFFS_LOOP */ 279 src += srcskip; 280 dst += dstskip; 281 } 282} 283 284static void 285Blit1to1Key(SDL_BlitInfo * info) 286{ 287 int width = info->dst_w; 288 int height = info->dst_h; 289 Uint8 *src = info->src; 290 int srcskip = info->src_skip; 291 Uint8 *dst = info->dst; 292 int dstskip = info->dst_skip; 293 Uint8 *palmap = info->table; 294 Uint32 ckey = info->colorkey; 295 296 if (palmap) { 297 while (height--) { 298 /* *INDENT-OFF* */ 299 DUFFS_LOOP( 300 { 301 if ( *src != ckey ) { 302 *dst = palmap[*src]; 303 } 304 dst++; 305 src++; 306 }, 307 width); 308 /* *INDENT-ON* */ 309 src += srcskip; 310 dst += dstskip; 311 } 312 } else { 313 while (height--) { 314 /* *INDENT-OFF* */ 315 DUFFS_LOOP( 316 { 317 if ( *src != ckey ) { 318 *dst = *src; 319 } 320 dst++; 321 src++; 322 }, 323 width); 324 /* *INDENT-ON* */ 325 src += srcskip; 326 dst += dstskip; 327 } 328 } 329} 330 331static void 332Blit1to2Key(SDL_BlitInfo * info) 333{ 334 int width = info->dst_w; 335 int height = info->dst_h; 336 Uint8 *src = info->src; 337 int srcskip = info->src_skip; 338 Uint16 *dstp = (Uint16 *) info->dst; 339 int dstskip = info->dst_skip; 340 Uint16 *palmap = (Uint16 *) info->table; 341 Uint32 ckey = info->colorkey; 342 343 /* Set up some basic variables */ 344 dstskip /= 2; 345 346 while (height--) { 347 /* *INDENT-OFF* */ 348 DUFFS_LOOP( 349 { 350 if ( *src != ckey ) { 351 *dstp=palmap[*src]; 352 } 353 src++; 354 dstp++; 355 }, 356 width); 357 /* *INDENT-ON* */ 358 src += srcskip; 359 dstp += dstskip; 360 } 361} 362 363static void 364Blit1to3Key(SDL_BlitInfo * info) 365{ 366 int width = info->dst_w; 367 int height = info->dst_h; 368 Uint8 *src = info->src; 369 int srcskip = info->src_skip; 370 Uint8 *dst = info->dst; 371 int dstskip = info->dst_skip; 372 Uint8 *palmap = info->table; 373 Uint32 ckey = info->colorkey; 374 int o; 375 376 while (height--) { 377 /* *INDENT-OFF* */ 378 DUFFS_LOOP( 379 { 380 if ( *src != ckey ) { 381 o = *src * 4; 382 dst[0] = palmap[o++]; 383 dst[1] = palmap[o++]; 384 dst[2] = palmap[o++]; 385 } 386 src++; 387 dst += 3; 388 }, 389 width); 390 /* *INDENT-ON* */ 391 src += srcskip; 392 dst += dstskip; 393 } 394} 395 396static void 397Blit1to4Key(SDL_BlitInfo * info) 398{ 399 int width = info->dst_w; 400 int height = info->dst_h; 401 Uint8 *src = info->src; 402 int srcskip = info->src_skip; 403 Uint32 *dstp = (Uint32 *) info->dst; 404 int dstskip = info->dst_skip; 405 Uint32 *palmap = (Uint32 *) info->table; 406 Uint32 ckey = info->colorkey; 407 408 /* Set up some basic variables */ 409 dstskip /= 4; 410 411 while (height--) { 412 /* *INDENT-OFF* */ 413 DUFFS_LOOP( 414 { 415 if ( *src != ckey ) { 416 *dstp = palmap[*src]; 417 } 418 src++; 419 dstp++; 420 }, 421 width); 422 /* *INDENT-ON* */ 423 src += srcskip; 424 dstp += dstskip; 425 } 426} 427 428static void 429Blit1toNAlpha(SDL_BlitInfo * info) 430{ 431 int width = info->dst_w; 432 int height = info->dst_h; 433 Uint8 *src = info->src; 434 int srcskip = info->src_skip; 435 Uint8 *dst = info->dst; 436 int dstskip = info->dst_skip; 437 SDL_PixelFormat *dstfmt = info->dst_fmt; 438 const SDL_Color *srcpal = info->src_fmt->palette->colors; 439 int dstbpp; 440 Uint32 pixel; 441 unsigned sR, sG, sB; 442 unsigned dR, dG, dB, dA; 443 const unsigned A = info->a; 444 445 /* Set up some basic variables */ 446 dstbpp = dstfmt->BytesPerPixel; 447 448 while (height--) { 449 /* *INDENT-OFF* */ 450 DUFFS_LOOP4( 451 { 452 sR = srcpal[*src].r; 453 sG = srcpal[*src].g; 454 sB = srcpal[*src].b; 455 DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA); 456 ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA); 457 ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); 458 src++; 459 dst += dstbpp; 460 }, 461 width); 462 /* *INDENT-ON* */ 463 src += srcskip; 464 dst += dstskip; 465 } 466} 467 468static void 469Blit1toNAlphaKey(SDL_BlitInfo * info) 470{ 471 int width = info->dst_w; 472 int height = info->dst_h; 473 Uint8 *src = info->src; 474 int srcskip = info->src_skip; 475 Uint8 *dst = info->dst; 476 int dstskip = info->dst_skip; 477 SDL_PixelFormat *dstfmt = info->dst_fmt; 478 const SDL_Color *srcpal = info->src_fmt->palette->colors; 479 Uint32 ckey = info->colorkey; 480 int dstbpp; 481 Uint32 pixel; 482 unsigned sR, sG, sB; 483 unsigned dR, dG, dB, dA; 484 const unsigned A = info->a; 485 486 /* Set up some basic variables */ 487 dstbpp = dstfmt->BytesPerPixel; 488 489 while (height--) { 490 /* *INDENT-OFF* */ 491 DUFFS_LOOP( 492 { 493 if ( *src != ckey ) { 494 sR = srcpal[*src].r; 495 sG = srcpal[*src].g; 496 sB = srcpal[*src].b; 497 DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA); 498 ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA); 499 ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); 500 } 501 src++; 502 dst += dstbpp; 503 }, 504 width); 505 /* *INDENT-ON* */ 506 src += srcskip; 507 dst += dstskip; 508 } 509} 510 511static const SDL_BlitFunc one_blit[] = { 512 (SDL_BlitFunc) NULL, Blit1to1, Blit1to2, Blit1to3, Blit1to4 513}; 514 515static const SDL_BlitFunc one_blitkey[] = { 516 (SDL_BlitFunc) NULL, Blit1to1Key, Blit1to2Key, Blit1to3Key, Blit1to4Key 517}; 518 519SDL_BlitFunc 520SDL_CalculateBlit1(SDL_Surface * surface) 521{ 522 int which; 523 SDL_PixelFormat *dstfmt; 524 525 dstfmt = surface->map->dst->format; 526 if (dstfmt->BitsPerPixel < 8) { 527 which = 0; 528 } else { 529 which = dstfmt->BytesPerPixel; 530 } 531 switch (surface->map->info.flags & ~SDL_COPY_RLE_MASK) { 532 case 0: 533 return one_blit[which]; 534 535 case SDL_COPY_COLORKEY: 536 return one_blitkey[which]; 537 538 case SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND: 539 /* Supporting 8bpp->8bpp alpha is doable but requires lots of 540 tables which consume space and takes time to precompute, 541 so is better left to the user */ 542 return which >= 2 ? Blit1toNAlpha : (SDL_BlitFunc) NULL; 543 544 case SDL_COPY_COLORKEY | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND: 545 return which >= 2 ? Blit1toNAlphaKey : (SDL_BlitFunc) NULL; 546 } 547 return (SDL_BlitFunc) NULL; 548} 549 550/* vi: set ts=4 sw=4 expandtab: */