Atlas - SDL_blit.h
Home / ext / SDL / src / video Lines: 1 | Size: 34828 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 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#ifndef SDL_blit_h_ 24#define SDL_blit_h_ 25 26// Table to do pixel byte expansion 27extern const Uint8 *SDL_expand_byte[9]; 28extern const Uint16 SDL_expand_byte_10[]; 29 30// SDL blit copy flags 31#define SDL_COPY_MODULATE_COLOR 0x00000001 32#define SDL_COPY_MODULATE_ALPHA 0x00000002 33#define SDL_COPY_MODULATE_MASK (SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA) 34#define SDL_COPY_BLEND 0x00000010 35#define SDL_COPY_BLEND_PREMULTIPLIED 0x00000020 36#define SDL_COPY_ADD 0x00000040 37#define SDL_COPY_ADD_PREMULTIPLIED 0x00000080 38#define SDL_COPY_MOD 0x00000100 39#define SDL_COPY_MUL 0x00000200 40#define SDL_COPY_BLEND_MASK (SDL_COPY_BLEND | SDL_COPY_BLEND_PREMULTIPLIED | SDL_COPY_ADD | SDL_COPY_ADD_PREMULTIPLIED | SDL_COPY_MOD | SDL_COPY_MUL) 41#define SDL_COPY_COLORKEY 0x00000400 42#define SDL_COPY_NEAREST 0x00000800 43#define SDL_COPY_RLE_DESIRED 0x00001000 44#define SDL_COPY_RLE_COLORKEY 0x00002000 45#define SDL_COPY_RLE_ALPHAKEY 0x00004000 46#define SDL_COPY_RLE_MASK (SDL_COPY_RLE_DESIRED | SDL_COPY_RLE_COLORKEY | SDL_COPY_RLE_ALPHAKEY) 47 48// SDL blit CPU flags 49#define SDL_CPU_ANY 0x00000000 50#define SDL_CPU_MMX 0x00000001 51#define SDL_CPU_SSE 0x00000002 52#define SDL_CPU_SSE2 0x00000004 53#define SDL_CPU_ALTIVEC_PREFETCH 0x00000008 54#define SDL_CPU_ALTIVEC_NOPREFETCH 0x00000010 55 56typedef struct 57{ 58 SDL_Surface *src_surface; 59 Uint8 *src; 60 int src_w, src_h; 61 int src_pitch; 62 int src_skip; 63 int leading_skip; 64 SDL_Surface *dst_surface; 65 Uint8 *dst; 66 int dst_w, dst_h; 67 int dst_pitch; 68 int dst_skip; 69 const SDL_PixelFormatDetails *src_fmt; 70 const SDL_Palette *src_pal; 71 const SDL_PixelFormatDetails *dst_fmt; 72 const SDL_Palette *dst_pal; 73 Uint8 *table; 74 SDL_HashTable *palette_map; 75 int flags; 76 Uint32 colorkey; 77 Uint8 r, g, b, a; 78} SDL_BlitInfo; 79 80typedef void (*SDL_BlitFunc)(SDL_BlitInfo *info); 81 82typedef struct 83{ 84 SDL_PixelFormat src_format; 85 SDL_PixelFormat dst_format; 86 int flags; 87 unsigned int cpu; 88 SDL_BlitFunc func; 89} SDL_BlitFuncEntry; 90 91typedef bool (SDLCALL *SDL_Blit) (struct SDL_Surface *src, const SDL_Rect *srcrect, struct SDL_Surface *dst, const SDL_Rect *dstrect); 92 93// Blit mapping definition 94typedef struct SDL_BlitMap 95{ 96 int identity; 97 SDL_Blit blit; 98 void *data; 99 SDL_BlitInfo info; 100 101 /* the version count matches the destination; mismatch indicates 102 an invalid mapping */ 103 Uint32 dst_palette_version; 104 Uint32 src_palette_version; 105} SDL_BlitMap; 106 107// Functions found in SDL_blit.c 108extern bool SDL_CalculateBlit(SDL_Surface *surface, SDL_Surface *dst); 109 110/* Functions found in SDL_blit_*.c */ 111extern SDL_BlitFunc SDL_CalculateBlit0(SDL_Surface *surface); 112extern SDL_BlitFunc SDL_CalculateBlit1(SDL_Surface *surface); 113extern SDL_BlitFunc SDL_CalculateBlitN(SDL_Surface *surface); 114extern SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface); 115 116/* 117 * Useful macros for blitting routines 118 */ 119 120#ifdef __GNUC__ 121#define DECLARE_ALIGNED(t, v, a) t __attribute__((aligned(a))) v 122#elif defined(_MSC_VER) 123#define DECLARE_ALIGNED(t, v, a) __declspec(align(a)) t v 124#else 125#define DECLARE_ALIGNED(t, v, a) t v 126#endif 127 128// Load pixel of the specified format from a buffer and get its R-G-B values 129#define RGB_FROM_PIXEL(Pixel, fmt, r, g, b) \ 130 { \ 131 r = SDL_expand_byte[fmt->Rbits][((Pixel & fmt->Rmask) >> fmt->Rshift)]; \ 132 g = SDL_expand_byte[fmt->Gbits][((Pixel & fmt->Gmask) >> fmt->Gshift)]; \ 133 b = SDL_expand_byte[fmt->Bbits][((Pixel & fmt->Bmask) >> fmt->Bshift)]; \ 134 } 135#define RGB_FROM_RGB565(Pixel, r, g, b) \ 136 { \ 137 r = SDL_expand_byte[5][((Pixel & 0xF800) >> 11)]; \ 138 g = SDL_expand_byte[6][((Pixel & 0x07E0) >> 5)]; \ 139 b = SDL_expand_byte[5][(Pixel & 0x001F)]; \ 140 } 141#define RGB_FROM_RGB555(Pixel, r, g, b) \ 142 { \ 143 r = SDL_expand_byte[5][((Pixel & 0x7C00) >> 10)]; \ 144 g = SDL_expand_byte[5][((Pixel & 0x03E0) >> 5)]; \ 145 b = SDL_expand_byte[5][(Pixel & 0x001F)]; \ 146 } 147#define RGB_FROM_XRGB8888(Pixel, r, g, b) \ 148 { \ 149 r = ((Pixel & 0xFF0000) >> 16); \ 150 g = ((Pixel & 0xFF00) >> 8); \ 151 b = (Pixel & 0xFF); \ 152 } 153#if SDL_BYTEORDER == SDL_LIL_ENDIAN 154#define GET_RGB24(B) (B[2] << 16) | (B[1] << 8) | B[0] 155#else 156#define GET_RGB24(B) (B[0] << 16) | (B[1] << 8) | B[2] 157#endif 158#define RETRIEVE_RGB_PIXEL(buf, bpp, Pixel) \ 159 do { \ 160 switch (bpp) { \ 161 case 1: \ 162 Pixel = *((Uint8 *)(buf)); \ 163 break; \ 164 \ 165 case 2: \ 166 Pixel = *((Uint16 *)(buf)); \ 167 break; \ 168 \ 169 case 3: \ 170 { \ 171 Uint8 *B = (Uint8 *)(buf); \ 172 Pixel = GET_RGB24(B); \ 173 } break; \ 174 \ 175 case 4: \ 176 Pixel = *((Uint32 *)(buf)); \ 177 break; \ 178 \ 179 default: \ 180 Pixel = 0; /* stop gcc complaints */ \ 181 break; \ 182 } \ 183 } while (0) 184 185#if SDL_BYTEORDER == SDL_LIL_ENDIAN 186#define GET_RGB24_COMPONENT(buf, fmt, shift) *((buf) + fmt->shift / 8) 187#else 188#define GET_RGB24_COMPONENT(buf, fmt, shift) *((buf) + 2 - fmt->shift / 8) 189#endif 190#define DISEMBLE_RGB(buf, bpp, fmt, Pixel, r, g, b) \ 191 do { \ 192 switch (bpp) { \ 193 case 1: \ 194 Pixel = *((Uint8 *)(buf)); \ 195 RGB_FROM_PIXEL(Pixel, fmt, r, g, b); \ 196 break; \ 197 \ 198 case 2: \ 199 Pixel = *((Uint16 *)(buf)); \ 200 RGB_FROM_PIXEL(Pixel, fmt, r, g, b); \ 201 break; \ 202 \ 203 case 3: \ 204 { \ 205 Pixel = 0; \ 206 r = GET_RGB24_COMPONENT(buf, fmt, Rshift); \ 207 g = GET_RGB24_COMPONENT(buf, fmt, Gshift); \ 208 b = GET_RGB24_COMPONENT(buf, fmt, Bshift); \ 209 } break; \ 210 \ 211 case 4: \ 212 Pixel = *((Uint32 *)(buf)); \ 213 RGB_FROM_PIXEL(Pixel, fmt, r, g, b); \ 214 break; \ 215 \ 216 default: \ 217 /* stop gcc complaints */ \ 218 Pixel = 0; \ 219 r = g = b = 0; \ 220 break; \ 221 } \ 222 } while (0) 223 224// Assemble R-G-B values into a specified pixel format and store them 225#define PIXEL_FROM_RGB(Pixel, fmt, r, g, b) \ 226 { \ 227 Pixel = ((r >> (8 - fmt->Rbits)) << fmt->Rshift) | \ 228 ((g >> (8 - fmt->Gbits)) << fmt->Gshift) | \ 229 ((b >> (8 - fmt->Bbits)) << fmt->Bshift) | \ 230 fmt->Amask; \ 231 } 232#define RGB332_FROM_RGB(Pixel, r, g, b) \ 233 { \ 234 Pixel = (Uint8)(((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6)); \ 235 } 236#define RGB565_FROM_RGB(Pixel, r, g, b) \ 237 { \ 238 Pixel = (Uint16)(((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)); \ 239 } 240#define RGB555_FROM_RGB(Pixel, r, g, b) \ 241 { \ 242 Pixel = (Uint16)(((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3)); \ 243 } 244#define XRGB8888_FROM_RGB(Pixel, r, g, b) \ 245 { \ 246 Pixel = (r << 16) | (g << 8) | b; \ 247 } 248#define ARGB8888_FROM_RGBA(Pixel, r, g, b, a) \ 249 { \ 250 Pixel = (a << 24) | (r << 16) | (g << 8) | b; \ 251 } 252#define RGBA8888_FROM_RGBA(Pixel, r, g, b, a) \ 253 { \ 254 Pixel = (r << 24) | (g << 16) | (b << 8) | a; \ 255 } 256#define ABGR8888_FROM_RGBA(Pixel, r, g, b, a) \ 257 { \ 258 Pixel = (a << 24) | (b << 16) | (g << 8) | r; \ 259 } 260#define BGRA8888_FROM_RGBA(Pixel, r, g, b, a) \ 261 { \ 262 Pixel = (b << 24) | (g << 16) | (r << 8) | a; \ 263 } 264#define ARGB2101010_FROM_RGBA(Pixel, r, g, b, a) \ 265 { \ 266 r = r ? ((r << 2) | 0x3) : 0; \ 267 g = g ? ((g << 2) | 0x3) : 0; \ 268 b = b ? ((b << 2) | 0x3) : 0; \ 269 a = (a * 3) / 255; \ 270 Pixel = (a << 30) | (r << 20) | (g << 10) | b; \ 271 } 272#define ARGB2101010_FROM_RGBAFLOAT(Pixel, r, g, b, a) \ 273 { \ 274 r = SDL_clamp(r, 0.0f, 1.0f) * 1023.0f; \ 275 g = SDL_clamp(g, 0.0f, 1.0f) * 1023.0f; \ 276 b = SDL_clamp(b, 0.0f, 1.0f) * 1023.0f; \ 277 a = SDL_clamp(a, 0.0f, 1.0f) * 3.0f; \ 278 Pixel = (((Uint32)SDL_roundf(a)) << 30) | \ 279 (((Uint32)SDL_roundf(r)) << 20) | \ 280 (((Uint32)SDL_roundf(g)) << 10) | \ 281 (Uint32)SDL_roundf(b); \ 282 } 283#define ABGR2101010_FROM_RGBA(Pixel, r, g, b, a) \ 284 { \ 285 r = r ? ((r << 2) | 0x3) : 0; \ 286 g = g ? ((g << 2) | 0x3) : 0; \ 287 b = b ? ((b << 2) | 0x3) : 0; \ 288 a = (a * 3) / 255; \ 289 Pixel = (a << 30) | (b << 20) | (g << 10) | r; \ 290 } 291#define ABGR2101010_FROM_RGBAFLOAT(Pixel, r, g, b, a) \ 292 { \ 293 r = SDL_clamp(r, 0.0f, 1.0f) * 1023.0f; \ 294 g = SDL_clamp(g, 0.0f, 1.0f) * 1023.0f; \ 295 b = SDL_clamp(b, 0.0f, 1.0f) * 1023.0f; \ 296 a = SDL_clamp(a, 0.0f, 1.0f) * 3.0f; \ 297 Pixel = (((Uint32)SDL_roundf(a)) << 30) | \ 298 (((Uint32)SDL_roundf(b)) << 20) | \ 299 (((Uint32)SDL_roundf(g)) << 10) | \ 300 (Uint32)SDL_roundf(r); \ 301 } 302#define ASSEMBLE_RGB(buf, bpp, fmt, r, g, b) \ 303 { \ 304 switch (bpp) { \ 305 case 1: \ 306 { \ 307 Uint8 _pixel; \ 308 \ 309 PIXEL_FROM_RGB(_pixel, fmt, r, g, b); \ 310 *((Uint8 *)(buf)) = _pixel; \ 311 } break; \ 312 \ 313 case 2: \ 314 { \ 315 Uint16 _pixel; \ 316 \ 317 PIXEL_FROM_RGB(_pixel, fmt, r, g, b); \ 318 *((Uint16 *)(buf)) = _pixel; \ 319 } break; \ 320 \ 321 case 3: \ 322 { \ 323 GET_RGB24_COMPONENT(buf, fmt, Rshift) = r; \ 324 GET_RGB24_COMPONENT(buf, fmt, Gshift) = g; \ 325 GET_RGB24_COMPONENT(buf, fmt, Bshift) = b; \ 326 } break; \ 327 \ 328 case 4: \ 329 { \ 330 Uint32 _pixel; \ 331 \ 332 PIXEL_FROM_RGB(_pixel, fmt, r, g, b); \ 333 *((Uint32 *)(buf)) = _pixel; \ 334 } break; \ 335 } \ 336 } 337 338// FIXME: Should we rescale alpha into 0..255 here? 339#define RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a) \ 340 { \ 341 r = SDL_expand_byte[fmt->Rbits][((Pixel & fmt->Rmask) >> fmt->Rshift)]; \ 342 g = SDL_expand_byte[fmt->Gbits][((Pixel & fmt->Gmask) >> fmt->Gshift)]; \ 343 b = SDL_expand_byte[fmt->Bbits][((Pixel & fmt->Bmask) >> fmt->Bshift)]; \ 344 a = SDL_expand_byte[fmt->Abits][((Pixel & fmt->Amask) >> fmt->Ashift)]; \ 345 } 346#define RGBA_FROM_8888(Pixel, fmt, r, g, b, a) \ 347 { \ 348 r = (Pixel & fmt->Rmask) >> fmt->Rshift; \ 349 g = (Pixel & fmt->Gmask) >> fmt->Gshift; \ 350 b = (Pixel & fmt->Bmask) >> fmt->Bshift; \ 351 a = (Pixel & fmt->Amask) >> fmt->Ashift; \ 352 } 353#define RGBA_FROM_RGBA8888(Pixel, r, g, b, a) \ 354 { \ 355 r = (Pixel >> 24); \ 356 g = ((Pixel >> 16) & 0xFF); \ 357 b = ((Pixel >> 8) & 0xFF); \ 358 a = (Pixel & 0xFF); \ 359 } 360#define RGBA_FROM_ARGB8888(Pixel, r, g, b, a) \ 361 { \ 362 r = ((Pixel >> 16) & 0xFF); \ 363 g = ((Pixel >> 8) & 0xFF); \ 364 b = (Pixel & 0xFF); \ 365 a = (Pixel >> 24); \ 366 } 367#define RGBA_FROM_ABGR8888(Pixel, r, g, b, a) \ 368 { \ 369 r = (Pixel & 0xFF); \ 370 g = ((Pixel >> 8) & 0xFF); \ 371 b = ((Pixel >> 16) & 0xFF); \ 372 a = (Pixel >> 24); \ 373 } 374#define RGBA_FROM_BGRA8888(Pixel, r, g, b, a) \ 375 { \ 376 r = ((Pixel >> 8) & 0xFF); \ 377 g = ((Pixel >> 16) & 0xFF); \ 378 b = (Pixel >> 24); \ 379 a = (Pixel & 0xFF); \ 380 } 381#define RGBA_FROM_ARGB2101010(Pixel, r, g, b, a) \ 382 { \ 383 r = ((Pixel >> 22) & 0xFF); \ 384 g = ((Pixel >> 12) & 0xFF); \ 385 b = ((Pixel >> 2) & 0xFF); \ 386 a = SDL_expand_byte[2][(Pixel >> 30)]; \ 387 } 388#define RGBAFLOAT_FROM_ARGB2101010(Pixel, r, g, b, a) \ 389 { \ 390 r = (float)((Pixel >> 20) & 0x3FF) / 1023.0f; \ 391 g = (float)((Pixel >> 10) & 0x3FF) / 1023.0f; \ 392 b = (float)((Pixel >> 0) & 0x3FF) / 1023.0f; \ 393 a = (float)(Pixel >> 30) / 3.0f; \ 394 } 395#define RGBA_FROM_ABGR2101010(Pixel, r, g, b, a) \ 396 { \ 397 r = ((Pixel >> 2) & 0xFF); \ 398 g = ((Pixel >> 12) & 0xFF); \ 399 b = ((Pixel >> 22) & 0xFF); \ 400 a = SDL_expand_byte[2][(Pixel >> 30)]; \ 401 } 402#define RGBAFLOAT_FROM_ABGR2101010(Pixel, r, g, b, a) \ 403 { \ 404 r = (float)((Pixel >> 0) & 0x3FF) / 1023.0f; \ 405 g = (float)((Pixel >> 10) & 0x3FF) / 1023.0f; \ 406 b = (float)((Pixel >> 20) & 0x3FF) / 1023.0f; \ 407 a = (float)(Pixel >> 30) / 3.0f; \ 408 } 409#define DISEMBLE_RGBA(buf, bpp, fmt, Pixel, r, g, b, a) \ 410 do { \ 411 switch (bpp) { \ 412 case 1: \ 413 Pixel = *((Uint8 *)(buf)); \ 414 RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a); \ 415 break; \ 416 \ 417 case 2: \ 418 Pixel = *((Uint16 *)(buf)); \ 419 RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a); \ 420 break; \ 421 \ 422 case 3: \ 423 { \ 424 Pixel = 0; \ 425 r = GET_RGB24_COMPONENT(buf, fmt, Rshift); \ 426 g = GET_RGB24_COMPONENT(buf, fmt, Gshift); \ 427 b = GET_RGB24_COMPONENT(buf, fmt, Bshift); \ 428 a = 0xFF; \ 429 } break; \ 430 \ 431 case 4: \ 432 Pixel = *((Uint32 *)(buf)); \ 433 RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a); \ 434 break; \ 435 \ 436 default: \ 437 /* stop gcc complaints */ \ 438 Pixel = 0; \ 439 r = g = b = a = 0; \ 440 break; \ 441 } \ 442 } while (0) 443 444// FIXME: this isn't correct, especially for Alpha (maximum != 255) 445#define PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a) \ 446 { \ 447 Pixel = ((r >> (8 - fmt->Rbits)) << fmt->Rshift) | \ 448 ((g >> (8 - fmt->Gbits)) << fmt->Gshift) | \ 449 ((b >> (8 - fmt->Bbits)) << fmt->Bshift) | \ 450 ((a >> (8 - fmt->Abits)) << fmt->Ashift); \ 451 } 452#define ASSEMBLE_RGBA(buf, bpp, fmt, r, g, b, a) \ 453 { \ 454 switch (bpp) { \ 455 case 1: \ 456 { \ 457 Uint8 _pixel; \ 458 \ 459 PIXEL_FROM_RGBA(_pixel, fmt, r, g, b, a); \ 460 *((Uint8 *)(buf)) = _pixel; \ 461 } break; \ 462 \ 463 case 2: \ 464 { \ 465 Uint16 _pixel; \ 466 \ 467 PIXEL_FROM_RGBA(_pixel, fmt, r, g, b, a); \ 468 *((Uint16 *)(buf)) = _pixel; \ 469 } break; \ 470 \ 471 case 3: \ 472 { \ 473 GET_RGB24_COMPONENT(buf, fmt, Rshift) = r; \ 474 GET_RGB24_COMPONENT(buf, fmt, Gshift) = g; \ 475 GET_RGB24_COMPONENT(buf, fmt, Bshift) = b; \ 476 } break; \ 477 \ 478 case 4: \ 479 { \ 480 Uint32 _pixel; \ 481 \ 482 PIXEL_FROM_RGBA(_pixel, fmt, r, g, b, a); \ 483 *((Uint32 *)(buf)) = _pixel; \ 484 } break; \ 485 } \ 486 } 487 488// Convert any 32-bit 4-bpp pixel to ARGB format 489#define PIXEL_TO_ARGB_PIXEL(src, srcfmt, dst) \ 490 do { \ 491 Uint8 a, r, g, b; \ 492 RGBA_FROM_PIXEL(src, srcfmt, r, g, b, a); \ 493 dst = a << 24 | r << 16 | g << 8 | b; \ 494 } while (0) 495// Blend a single color channel or alpha value 496/* dC = ((sC * sA) + (dC * (255 - sA))) / 255 */ 497#define ALPHA_BLEND_CHANNEL(sC, dC, sA) \ 498 do { \ 499 Uint16 x; \ 500 x = ((sC - dC) * sA) + ((dC << 8) - dC); \ 501 x += 0x1U; \ 502 x += x >> 8; \ 503 dC = x >> 8; \ 504 } while (0) 505// Perform a division by 255 after a multiplication of two 8-bit color channels 506/* out = (sC * dC) / 255 */ 507#define MULT_DIV_255(sC, dC, out) \ 508 do { \ 509 Uint16 x = sC * dC; \ 510 x += 0x1U; \ 511 x += x >> 8; \ 512 out = x >> 8; \ 513 } while (0) 514// Blend the RGB values of two pixels with an alpha value 515#define ALPHA_BLEND_RGB(sR, sG, sB, A, dR, dG, dB) \ 516 do { \ 517 ALPHA_BLEND_CHANNEL(sR, dR, A); \ 518 ALPHA_BLEND_CHANNEL(sG, dG, A); \ 519 ALPHA_BLEND_CHANNEL(sB, dB, A); \ 520 } while (0) 521 522// Blend two 8888 pixels with the same format 523/* Calculates dst = ((src * factor) + (dst * (255 - factor))) / 255 */ 524// FIXME: SDL_SIZE_MAX might not be an integer literal 525#if defined(SIZE_MAX) && (SIZE_MAX == 0xffffffffffffffff) 526#define FACTOR_BLEND_8888(src, dst, factor) \ 527 do { \ 528 Uint64 src64 = src; \ 529 src64 = (src64 | (src64 << 24)) & 0x00FF00FF00FF00FF; \ 530 \ 531 Uint64 dst64 = dst; \ 532 dst64 = (dst64 | (dst64 << 24)) & 0x00FF00FF00FF00FF; \ 533 \ 534 dst64 = ((src64 - dst64) * factor) + (dst64 << 8) - dst64; \ 535 dst64 += 0x0001000100010001; \ 536 dst64 += (dst64 >> 8) & 0x00FF00FF00FF00FF; \ 537 dst64 &= 0xFF00FF00FF00FF00; \ 538 \ 539 dst = (Uint32)((dst64 >> 8) | (dst64 >> 32)); \ 540 } while (0) 541#else 542#define FACTOR_BLEND_8888(src, dst, factor) \ 543 do { \ 544 Uint32 src02 = src & 0x00FF00FF; \ 545 Uint32 dst02 = dst & 0x00FF00FF; \ 546 \ 547 Uint32 src13 = (src >> 8) & 0x00FF00FF; \ 548 Uint32 dst13 = (dst >> 8) & 0x00FF00FF; \ 549 \ 550 Uint32 res02 = ((src02 - dst02) * factor) + (dst02 << 8) - dst02; \ 551 res02 += 0x00010001; \ 552 res02 += (res02 >> 8) & 0x00FF00FF; \ 553 res02 = (res02 >> 8) & 0x00FF00FF; \ 554 \ 555 Uint32 res13 = ((src13 - dst13) * factor) + (dst13 << 8) - dst13; \ 556 res13 += 0x00010001; \ 557 res13 += (res13 >> 8) & 0x00FF00FF; \ 558 res13 &= 0xFF00FF00; \ 559 dst = res02 | res13; \ 560 } while (0) 561#endif 562 563// Alpha blend two 8888 pixels with the same formats. 564#define ALPHA_BLEND_8888(src, dst, fmt) \ 565 do { \ 566 Uint32 srcA = (src >> fmt->Ashift) & 0xFF; \ 567 Uint32 tmp = src | fmt->Amask; \ 568 FACTOR_BLEND_8888(tmp, dst, srcA); \ 569 } while (0) 570 571// Alpha blend two 8888 pixels with differing formats. 572#define ALPHA_BLEND_SWIZZLE_8888(src, dst, srcfmt, dstfmt) \ 573 do { \ 574 Uint32 srcA = (src >> srcfmt->Ashift) & 0xFF; \ 575 Uint32 tmp = (((src >> srcfmt->Rshift) & 0xFF) << dstfmt->Rshift) | \ 576 (((src >> srcfmt->Gshift) & 0xFF) << dstfmt->Gshift) | \ 577 (((src >> srcfmt->Bshift) & 0xFF) << dstfmt->Bshift) | \ 578 dstfmt->Amask; \ 579 FACTOR_BLEND_8888(tmp, dst, srcA); \ 580 } while (0) 581// Blend the RGBA values of two pixels 582#define ALPHA_BLEND_RGBA(sR, sG, sB, sA, dR, dG, dB, dA) \ 583 do { \ 584 ALPHA_BLEND_CHANNEL(sR, dR, sA); \ 585 ALPHA_BLEND_CHANNEL(sG, dG, sA); \ 586 ALPHA_BLEND_CHANNEL(sB, dB, sA); \ 587 ALPHA_BLEND_CHANNEL(255, dA, sA); \ 588 } while (0) 589 590// This is a very useful loop for optimizing blitters 591#if defined(_MSC_VER) && (_MSC_VER == 1300) 592// There's a bug in the Visual C++ 7 optimizer when compiling this code 593#else 594#define USE_DUFFS_LOOP 595#endif 596 597#define DUFFS_LOOP1(pixel_copy_increment, width) \ 598 { \ 599 int n; \ 600 for (n = width; n > 0; --n) { \ 601 pixel_copy_increment; \ 602 } \ 603 } 604 605#ifdef USE_DUFFS_LOOP 606 607// 8-times unrolled loop 608#define DUFFS_LOOP8(pixel_copy_increment, width) \ 609 { \ 610 int n = (width + 7) / 8; \ 611 switch (width & 7) { \ 612 case 0: \ 613 do { \ 614 pixel_copy_increment; \ 615 SDL_FALLTHROUGH; \ 616 case 7: \ 617 pixel_copy_increment; \ 618 SDL_FALLTHROUGH; \ 619 case 6: \ 620 pixel_copy_increment; \ 621 SDL_FALLTHROUGH; \ 622 case 5: \ 623 pixel_copy_increment; \ 624 SDL_FALLTHROUGH; \ 625 case 4: \ 626 pixel_copy_increment; \ 627 SDL_FALLTHROUGH; \ 628 case 3: \ 629 pixel_copy_increment; \ 630 SDL_FALLTHROUGH; \ 631 case 2: \ 632 pixel_copy_increment; \ 633 SDL_FALLTHROUGH; \ 634 case 1: \ 635 pixel_copy_increment; \ 636 } while (--n > 0); \ 637 } \ 638 } 639 640// 4-times unrolled loop 641#define DUFFS_LOOP4(pixel_copy_increment, width) \ 642 { \ 643 int n = (width + 3) / 4; \ 644 switch (width & 3) { \ 645 case 0: \ 646 do { \ 647 pixel_copy_increment; \ 648 SDL_FALLTHROUGH; \ 649 case 3: \ 650 pixel_copy_increment; \ 651 SDL_FALLTHROUGH; \ 652 case 2: \ 653 pixel_copy_increment; \ 654 SDL_FALLTHROUGH; \ 655 case 1: \ 656 pixel_copy_increment; \ 657 } while (--n > 0); \ 658 } \ 659 } 660 661// 2-times unrolled loop 662#define DUFFS_LOOP2(pixel_copy_increment, width) \ 663 { \ 664 int n = (width + 1) / 2; \ 665 switch (width & 1) { \ 666 case 0: \ 667 do { \ 668 pixel_copy_increment; \ 669 SDL_FALLTHROUGH; \ 670 case 1: \ 671 pixel_copy_increment; \ 672 } while (--n > 0); \ 673 } \ 674 } 675 676// Use the 4-times version of the loop by default 677#define DUFFS_LOOP(pixel_copy_increment, width) \ 678 DUFFS_LOOP4(pixel_copy_increment, width) 679// Use the 8-times version of the loop for simple routines 680#define DUFFS_LOOP_TRIVIAL(pixel_copy_increment, width) \ 681 DUFFS_LOOP8(pixel_copy_increment, width) 682 683// Special version of Duff's device for even more optimization 684#define DUFFS_LOOP_124(pixel_copy_increment1, \ 685 pixel_copy_increment2, \ 686 pixel_copy_increment4, width) \ 687 { \ 688 int n = width; \ 689 if (n & 1) { \ 690 pixel_copy_increment1; \ 691 n -= 1; \ 692 } \ 693 if (n & 2) { \ 694 pixel_copy_increment2; \ 695 n -= 2; \ 696 } \ 697 if (n & 4) { \ 698 pixel_copy_increment4; \ 699 n -= 4; \ 700 } \ 701 if (n) { \ 702 n /= 8; \ 703 do { \ 704 pixel_copy_increment4; \ 705 pixel_copy_increment4; \ 706 } while (--n > 0); \ 707 } \ 708 } 709 710#else 711 712// Don't use Duff's device to unroll loops 713#define DUFFS_LOOP(pixel_copy_increment, width) \ 714 DUFFS_LOOP1(pixel_copy_increment, width) 715#define DUFFS_LOOP_TRIVIAL(pixel_copy_increment, width) \ 716 DUFFS_LOOP1(pixel_copy_increment, width) 717#define DUFFS_LOOP8(pixel_copy_increment, width) \ 718 DUFFS_LOOP1(pixel_copy_increment, width) 719#define DUFFS_LOOP4(pixel_copy_increment, width) \ 720 DUFFS_LOOP1(pixel_copy_increment, width) 721#define DUFFS_LOOP2(pixel_copy_increment, width) \ 722 DUFFS_LOOP1(pixel_copy_increment, width) 723#define DUFFS_LOOP_124(pixel_copy_increment1, \ 724 pixel_copy_increment2, \ 725 pixel_copy_increment4, width) \ 726 DUFFS_LOOP1(pixel_copy_increment1, width) 727 728#endif // USE_DUFFS_LOOP 729 730#if defined(_MSC_VER) && (_MSC_VER >= 600) 731#pragma warning(disable : 4244) // '=': conversion from 'X' to 'Y', possible loss of data 732#endif 733 734#endif // SDL_blit_h_ 735[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.