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