Atlas - SDL_pixels.c

Home / ext / SDL2 / src / video Lines: 1 | Size: 32028 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 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/* General (mostly internal) pixel/color manipulation routines for SDL */ 24 25#include "SDL_endian.h" 26#include "SDL_video.h" 27#include "SDL_sysvideo.h" 28#include "SDL_blit.h" 29#include "SDL_pixels_c.h" 30#include "SDL_RLEaccel_c.h" 31 32 33/* Lookup tables to expand partial bytes to the full 0..255 range */ 34 35static Uint8 lookup_0[] = { 360, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 37}; 38 39static Uint8 lookup_1[] = { 400, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 255 41}; 42 43static Uint8 lookup_2[] = { 440, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 170, 174, 178, 182, 186, 190, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 255 45}; 46 47static Uint8 lookup_3[] = { 480, 8, 16, 24, 32, 41, 49, 57, 65, 74, 82, 90, 98, 106, 115, 123, 131, 139, 148, 156, 164, 172, 180, 189, 197, 205, 213, 222, 230, 238, 246, 255 49}; 50 51static Uint8 lookup_4[] = { 520, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255 53}; 54 55static Uint8 lookup_5[] = { 560, 36, 72, 109, 145, 182, 218, 255 57}; 58 59static Uint8 lookup_6[] = { 600, 85, 170, 255 61}; 62 63static Uint8 lookup_7[] = { 640, 255 65}; 66 67static Uint8 lookup_8[] = { 68255 69}; 70 71Uint8* SDL_expand_byte[9] = { 72 lookup_0, 73 lookup_1, 74 lookup_2, 75 lookup_3, 76 lookup_4, 77 lookup_5, 78 lookup_6, 79 lookup_7, 80 lookup_8 81}; 82 83/* Helper functions */ 84 85const char* 86SDL_GetPixelFormatName(Uint32 format) 87{ 88 switch (format) { 89#define CASE(X) case X: return #X; 90 CASE(SDL_PIXELFORMAT_INDEX1LSB) 91 CASE(SDL_PIXELFORMAT_INDEX1MSB) 92 CASE(SDL_PIXELFORMAT_INDEX4LSB) 93 CASE(SDL_PIXELFORMAT_INDEX4MSB) 94 CASE(SDL_PIXELFORMAT_INDEX8) 95 CASE(SDL_PIXELFORMAT_RGB332) 96 CASE(SDL_PIXELFORMAT_RGB444) 97 CASE(SDL_PIXELFORMAT_RGB555) 98 CASE(SDL_PIXELFORMAT_BGR555) 99 CASE(SDL_PIXELFORMAT_ARGB4444) 100 CASE(SDL_PIXELFORMAT_RGBA4444) 101 CASE(SDL_PIXELFORMAT_ABGR4444) 102 CASE(SDL_PIXELFORMAT_BGRA4444) 103 CASE(SDL_PIXELFORMAT_ARGB1555) 104 CASE(SDL_PIXELFORMAT_RGBA5551) 105 CASE(SDL_PIXELFORMAT_ABGR1555) 106 CASE(SDL_PIXELFORMAT_BGRA5551) 107 CASE(SDL_PIXELFORMAT_RGB565) 108 CASE(SDL_PIXELFORMAT_BGR565) 109 CASE(SDL_PIXELFORMAT_RGB24) 110 CASE(SDL_PIXELFORMAT_BGR24) 111 CASE(SDL_PIXELFORMAT_RGB888) 112 CASE(SDL_PIXELFORMAT_RGBX8888) 113 CASE(SDL_PIXELFORMAT_BGR888) 114 CASE(SDL_PIXELFORMAT_BGRX8888) 115 CASE(SDL_PIXELFORMAT_ARGB8888) 116 CASE(SDL_PIXELFORMAT_RGBA8888) 117 CASE(SDL_PIXELFORMAT_ABGR8888) 118 CASE(SDL_PIXELFORMAT_BGRA8888) 119 CASE(SDL_PIXELFORMAT_ARGB2101010) 120 CASE(SDL_PIXELFORMAT_YV12) 121 CASE(SDL_PIXELFORMAT_IYUV) 122 CASE(SDL_PIXELFORMAT_YUY2) 123 CASE(SDL_PIXELFORMAT_UYVY) 124 CASE(SDL_PIXELFORMAT_YVYU) 125 CASE(SDL_PIXELFORMAT_NV12) 126 CASE(SDL_PIXELFORMAT_NV21) 127#undef CASE 128 default: 129 return "SDL_PIXELFORMAT_UNKNOWN"; 130 } 131} 132 133SDL_bool 134SDL_PixelFormatEnumToMasks(Uint32 format, int *bpp, Uint32 * Rmask, 135 Uint32 * Gmask, Uint32 * Bmask, Uint32 * Amask) 136{ 137 Uint32 masks[4]; 138 139 /* This function doesn't work with FourCC pixel formats */ 140 if (SDL_ISPIXELFORMAT_FOURCC(format)) { 141 SDL_SetError("FOURCC pixel formats are not supported"); 142 return SDL_FALSE; 143 } 144 145 /* Initialize the values here */ 146 if (SDL_BYTESPERPIXEL(format) <= 2) { 147 *bpp = SDL_BITSPERPIXEL(format); 148 } else { 149 *bpp = SDL_BYTESPERPIXEL(format) * 8; 150 } 151 *Rmask = *Gmask = *Bmask = *Amask = 0; 152 153 if (format == SDL_PIXELFORMAT_RGB24) { 154#if SDL_BYTEORDER == SDL_BIG_ENDIAN 155 *Rmask = 0x00FF0000; 156 *Gmask = 0x0000FF00; 157 *Bmask = 0x000000FF; 158#else 159 *Rmask = 0x000000FF; 160 *Gmask = 0x0000FF00; 161 *Bmask = 0x00FF0000; 162#endif 163 return SDL_TRUE; 164 } 165 166 if (format == SDL_PIXELFORMAT_BGR24) { 167#if SDL_BYTEORDER == SDL_BIG_ENDIAN 168 *Rmask = 0x000000FF; 169 *Gmask = 0x0000FF00; 170 *Bmask = 0x00FF0000; 171#else 172 *Rmask = 0x00FF0000; 173 *Gmask = 0x0000FF00; 174 *Bmask = 0x000000FF; 175#endif 176 return SDL_TRUE; 177 } 178 179 if (SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED8 && 180 SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED16 && 181 SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED32) { 182 /* Not a format that uses masks */ 183 return SDL_TRUE; 184 } 185 186 switch (SDL_PIXELLAYOUT(format)) { 187 case SDL_PACKEDLAYOUT_332: 188 masks[0] = 0x00000000; 189 masks[1] = 0x000000E0; 190 masks[2] = 0x0000001C; 191 masks[3] = 0x00000003; 192 break; 193 case SDL_PACKEDLAYOUT_4444: 194 masks[0] = 0x0000F000; 195 masks[1] = 0x00000F00; 196 masks[2] = 0x000000F0; 197 masks[3] = 0x0000000F; 198 break; 199 case SDL_PACKEDLAYOUT_1555: 200 masks[0] = 0x00008000; 201 masks[1] = 0x00007C00; 202 masks[2] = 0x000003E0; 203 masks[3] = 0x0000001F; 204 break; 205 case SDL_PACKEDLAYOUT_5551: 206 masks[0] = 0x0000F800; 207 masks[1] = 0x000007C0; 208 masks[2] = 0x0000003E; 209 masks[3] = 0x00000001; 210 break; 211 case SDL_PACKEDLAYOUT_565: 212 masks[0] = 0x00000000; 213 masks[1] = 0x0000F800; 214 masks[2] = 0x000007E0; 215 masks[3] = 0x0000001F; 216 break; 217 case SDL_PACKEDLAYOUT_8888: 218 masks[0] = 0xFF000000; 219 masks[1] = 0x00FF0000; 220 masks[2] = 0x0000FF00; 221 masks[3] = 0x000000FF; 222 break; 223 case SDL_PACKEDLAYOUT_2101010: 224 masks[0] = 0xC0000000; 225 masks[1] = 0x3FF00000; 226 masks[2] = 0x000FFC00; 227 masks[3] = 0x000003FF; 228 break; 229 case SDL_PACKEDLAYOUT_1010102: 230 masks[0] = 0xFFC00000; 231 masks[1] = 0x003FF000; 232 masks[2] = 0x00000FFC; 233 masks[3] = 0x00000003; 234 break; 235 default: 236 SDL_SetError("Unknown pixel format"); 237 return SDL_FALSE; 238 } 239 240 switch (SDL_PIXELORDER(format)) { 241 case SDL_PACKEDORDER_XRGB: 242 *Rmask = masks[1]; 243 *Gmask = masks[2]; 244 *Bmask = masks[3]; 245 break; 246 case SDL_PACKEDORDER_RGBX: 247 *Rmask = masks[0]; 248 *Gmask = masks[1]; 249 *Bmask = masks[2]; 250 break; 251 case SDL_PACKEDORDER_ARGB: 252 *Amask = masks[0]; 253 *Rmask = masks[1]; 254 *Gmask = masks[2]; 255 *Bmask = masks[3]; 256 break; 257 case SDL_PACKEDORDER_RGBA: 258 *Rmask = masks[0]; 259 *Gmask = masks[1]; 260 *Bmask = masks[2]; 261 *Amask = masks[3]; 262 break; 263 case SDL_PACKEDORDER_XBGR: 264 *Bmask = masks[1]; 265 *Gmask = masks[2]; 266 *Rmask = masks[3]; 267 break; 268 case SDL_PACKEDORDER_BGRX: 269 *Bmask = masks[0]; 270 *Gmask = masks[1]; 271 *Rmask = masks[2]; 272 break; 273 case SDL_PACKEDORDER_BGRA: 274 *Bmask = masks[0]; 275 *Gmask = masks[1]; 276 *Rmask = masks[2]; 277 *Amask = masks[3]; 278 break; 279 case SDL_PACKEDORDER_ABGR: 280 *Amask = masks[0]; 281 *Bmask = masks[1]; 282 *Gmask = masks[2]; 283 *Rmask = masks[3]; 284 break; 285 default: 286 SDL_SetError("Unknown pixel format"); 287 return SDL_FALSE; 288 } 289 return SDL_TRUE; 290} 291 292Uint32 293SDL_MasksToPixelFormatEnum(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, 294 Uint32 Amask) 295{ 296 switch (bpp) { 297 case 1: 298 /* SDL defaults to MSB ordering */ 299 return SDL_PIXELFORMAT_INDEX1MSB; 300 case 4: 301 /* SDL defaults to MSB ordering */ 302 return SDL_PIXELFORMAT_INDEX4MSB; 303 case 8: 304 if (Rmask == 0) { 305 return SDL_PIXELFORMAT_INDEX8; 306 } 307 if (Rmask == 0xE0 && 308 Gmask == 0x1C && 309 Bmask == 0x03 && 310 Amask == 0x00) { 311 return SDL_PIXELFORMAT_RGB332; 312 } 313 break; 314 case 12: 315 if (Rmask == 0) { 316 return SDL_PIXELFORMAT_RGB444; 317 } 318 if (Rmask == 0x0F00 && 319 Gmask == 0x00F0 && 320 Bmask == 0x000F && 321 Amask == 0x0000) { 322 return SDL_PIXELFORMAT_RGB444; 323 } 324 break; 325 case 15: 326 if (Rmask == 0) { 327 return SDL_PIXELFORMAT_RGB555; 328 } 329 /* fallthrough */ 330 case 16: 331 if (Rmask == 0) { 332 return SDL_PIXELFORMAT_RGB565; 333 } 334 if (Rmask == 0x7C00 && 335 Gmask == 0x03E0 && 336 Bmask == 0x001F && 337 Amask == 0x0000) { 338 return SDL_PIXELFORMAT_RGB555; 339 } 340 if (Rmask == 0x001F && 341 Gmask == 0x03E0 && 342 Bmask == 0x7C00 && 343 Amask == 0x0000) { 344 return SDL_PIXELFORMAT_BGR555; 345 } 346 if (Rmask == 0x0F00 && 347 Gmask == 0x00F0 && 348 Bmask == 0x000F && 349 Amask == 0xF000) { 350 return SDL_PIXELFORMAT_ARGB4444; 351 } 352 if (Rmask == 0xF000 && 353 Gmask == 0x0F00 && 354 Bmask == 0x00F0 && 355 Amask == 0x000F) { 356 return SDL_PIXELFORMAT_RGBA4444; 357 } 358 if (Rmask == 0x000F && 359 Gmask == 0x00F0 && 360 Bmask == 0x0F00 && 361 Amask == 0xF000) { 362 return SDL_PIXELFORMAT_ABGR4444; 363 } 364 if (Rmask == 0x00F0 && 365 Gmask == 0x0F00 && 366 Bmask == 0xF000 && 367 Amask == 0x000F) { 368 return SDL_PIXELFORMAT_BGRA4444; 369 } 370 if (Rmask == 0x7C00 && 371 Gmask == 0x03E0 && 372 Bmask == 0x001F && 373 Amask == 0x8000) { 374 return SDL_PIXELFORMAT_ARGB1555; 375 } 376 if (Rmask == 0xF800 && 377 Gmask == 0x07C0 && 378 Bmask == 0x003E && 379 Amask == 0x0001) { 380 return SDL_PIXELFORMAT_RGBA5551; 381 } 382 if (Rmask == 0x001F && 383 Gmask == 0x03E0 && 384 Bmask == 0x7C00 && 385 Amask == 0x8000) { 386 return SDL_PIXELFORMAT_ABGR1555; 387 } 388 if (Rmask == 0x003E && 389 Gmask == 0x07C0 && 390 Bmask == 0xF800 && 391 Amask == 0x0001) { 392 return SDL_PIXELFORMAT_BGRA5551; 393 } 394 if (Rmask == 0xF800 && 395 Gmask == 0x07E0 && 396 Bmask == 0x001F && 397 Amask == 0x0000) { 398 return SDL_PIXELFORMAT_RGB565; 399 } 400 if (Rmask == 0x001F && 401 Gmask == 0x07E0 && 402 Bmask == 0xF800 && 403 Amask == 0x0000) { 404 return SDL_PIXELFORMAT_BGR565; 405 } 406 if (Rmask == 0x003F && 407 Gmask == 0x07C0 && 408 Bmask == 0xF800 && 409 Amask == 0x0000) { 410 /* Technically this would be BGR556, but Witek says this works in bug 3158 */ 411 return SDL_PIXELFORMAT_RGB565; 412 } 413 break; 414 case 24: 415 switch (Rmask) { 416 case 0: 417 case 0x00FF0000: 418#if SDL_BYTEORDER == SDL_BIG_ENDIAN 419 return SDL_PIXELFORMAT_RGB24; 420#else 421 return SDL_PIXELFORMAT_BGR24; 422#endif 423 case 0x000000FF: 424#if SDL_BYTEORDER == SDL_BIG_ENDIAN 425 return SDL_PIXELFORMAT_BGR24; 426#else 427 return SDL_PIXELFORMAT_RGB24; 428#endif 429 } 430 case 32: 431 if (Rmask == 0) { 432 return SDL_PIXELFORMAT_RGB888; 433 } 434 if (Rmask == 0x00FF0000 && 435 Gmask == 0x0000FF00 && 436 Bmask == 0x000000FF && 437 Amask == 0x00000000) { 438 return SDL_PIXELFORMAT_RGB888; 439 } 440 if (Rmask == 0xFF000000 && 441 Gmask == 0x00FF0000 && 442 Bmask == 0x0000FF00 && 443 Amask == 0x00000000) { 444 return SDL_PIXELFORMAT_RGBX8888; 445 } 446 if (Rmask == 0x000000FF && 447 Gmask == 0x0000FF00 && 448 Bmask == 0x00FF0000 && 449 Amask == 0x00000000) { 450 return SDL_PIXELFORMAT_BGR888; 451 } 452 if (Rmask == 0x0000FF00 && 453 Gmask == 0x00FF0000 && 454 Bmask == 0xFF000000 && 455 Amask == 0x00000000) { 456 return SDL_PIXELFORMAT_BGRX8888; 457 } 458 if (Rmask == 0x00FF0000 && 459 Gmask == 0x0000FF00 && 460 Bmask == 0x000000FF && 461 Amask == 0xFF000000) { 462 return SDL_PIXELFORMAT_ARGB8888; 463 } 464 if (Rmask == 0xFF000000 && 465 Gmask == 0x00FF0000 && 466 Bmask == 0x0000FF00 && 467 Amask == 0x000000FF) { 468 return SDL_PIXELFORMAT_RGBA8888; 469 } 470 if (Rmask == 0x000000FF && 471 Gmask == 0x0000FF00 && 472 Bmask == 0x00FF0000 && 473 Amask == 0xFF000000) { 474 return SDL_PIXELFORMAT_ABGR8888; 475 } 476 if (Rmask == 0x0000FF00 && 477 Gmask == 0x00FF0000 && 478 Bmask == 0xFF000000 && 479 Amask == 0x000000FF) { 480 return SDL_PIXELFORMAT_BGRA8888; 481 } 482 if (Rmask == 0x3FF00000 && 483 Gmask == 0x000FFC00 && 484 Bmask == 0x000003FF && 485 Amask == 0xC0000000) { 486 return SDL_PIXELFORMAT_ARGB2101010; 487 } 488 } 489 return SDL_PIXELFORMAT_UNKNOWN; 490} 491 492static SDL_PixelFormat *formats; 493static SDL_SpinLock formats_lock = 0; 494 495SDL_PixelFormat * 496SDL_AllocFormat(Uint32 pixel_format) 497{ 498 SDL_PixelFormat *format; 499 500 SDL_AtomicLock(&formats_lock); 501 502 /* Look it up in our list of previously allocated formats */ 503 for (format = formats; format; format = format->next) { 504 if (pixel_format == format->format) { 505 ++format->refcount; 506 SDL_AtomicUnlock(&formats_lock); 507 return format; 508 } 509 } 510 511 /* Allocate an empty pixel format structure, and initialize it */ 512 format = SDL_malloc(sizeof(*format)); 513 if (format == NULL) { 514 SDL_AtomicUnlock(&formats_lock); 515 SDL_OutOfMemory(); 516 return NULL; 517 } 518 if (SDL_InitFormat(format, pixel_format) < 0) { 519 SDL_AtomicUnlock(&formats_lock); 520 SDL_free(format); 521 SDL_InvalidParamError("format"); 522 return NULL; 523 } 524 525 if (!SDL_ISPIXELFORMAT_INDEXED(pixel_format)) { 526 /* Cache the RGB formats */ 527 format->next = formats; 528 formats = format; 529 } 530 531 SDL_AtomicUnlock(&formats_lock); 532 533 return format; 534} 535 536int 537SDL_InitFormat(SDL_PixelFormat * format, Uint32 pixel_format) 538{ 539 int bpp; 540 Uint32 Rmask, Gmask, Bmask, Amask; 541 Uint32 mask; 542 543 if (!SDL_PixelFormatEnumToMasks(pixel_format, &bpp, 544 &Rmask, &Gmask, &Bmask, &Amask)) { 545 return -1; 546 } 547 548 /* Set up the format */ 549 SDL_zerop(format); 550 format->format = pixel_format; 551 format->BitsPerPixel = bpp; 552 format->BytesPerPixel = (bpp + 7) / 8; 553 554 format->Rmask = Rmask; 555 format->Rshift = 0; 556 format->Rloss = 8; 557 if (Rmask) { 558 for (mask = Rmask; !(mask & 0x01); mask >>= 1) 559 ++format->Rshift; 560 for (; (mask & 0x01); mask >>= 1) 561 --format->Rloss; 562 } 563 564 format->Gmask = Gmask; 565 format->Gshift = 0; 566 format->Gloss = 8; 567 if (Gmask) { 568 for (mask = Gmask; !(mask & 0x01); mask >>= 1) 569 ++format->Gshift; 570 for (; (mask & 0x01); mask >>= 1) 571 --format->Gloss; 572 } 573 574 format->Bmask = Bmask; 575 format->Bshift = 0; 576 format->Bloss = 8; 577 if (Bmask) { 578 for (mask = Bmask; !(mask & 0x01); mask >>= 1) 579 ++format->Bshift; 580 for (; (mask & 0x01); mask >>= 1) 581 --format->Bloss; 582 } 583 584 format->Amask = Amask; 585 format->Ashift = 0; 586 format->Aloss = 8; 587 if (Amask) { 588 for (mask = Amask; !(mask & 0x01); mask >>= 1) 589 ++format->Ashift; 590 for (; (mask & 0x01); mask >>= 1) 591 --format->Aloss; 592 } 593 594 format->palette = NULL; 595 format->refcount = 1; 596 format->next = NULL; 597 598 return 0; 599} 600 601void 602SDL_FreeFormat(SDL_PixelFormat *format) 603{ 604 SDL_PixelFormat *prev; 605 606 if (!format) { 607 SDL_InvalidParamError("format"); 608 return; 609 } 610 611 SDL_AtomicLock(&formats_lock); 612 613 if (--format->refcount > 0) { 614 SDL_AtomicUnlock(&formats_lock); 615 return; 616 } 617 618 /* Remove this format from our list */ 619 if (format == formats) { 620 formats = format->next; 621 } else if (formats) { 622 for (prev = formats; prev->next; prev = prev->next) { 623 if (prev->next == format) { 624 prev->next = format->next; 625 break; 626 } 627 } 628 } 629 630 SDL_AtomicUnlock(&formats_lock); 631 632 if (format->palette) { 633 SDL_FreePalette(format->palette); 634 } 635 SDL_free(format); 636} 637 638SDL_Palette * 639SDL_AllocPalette(int ncolors) 640{ 641 SDL_Palette *palette; 642 643 /* Input validation */ 644 if (ncolors < 1) { 645 SDL_InvalidParamError("ncolors"); 646 return NULL; 647 } 648 649 palette = (SDL_Palette *) SDL_malloc(sizeof(*palette)); 650 if (!palette) { 651 SDL_OutOfMemory(); 652 return NULL; 653 } 654 palette->colors = 655 (SDL_Color *) SDL_malloc(ncolors * sizeof(*palette->colors)); 656 if (!palette->colors) { 657 SDL_free(palette); 658 return NULL; 659 } 660 palette->ncolors = ncolors; 661 palette->version = 1; 662 palette->refcount = 1; 663 664 SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors)); 665 666 return palette; 667} 668 669int 670SDL_SetPixelFormatPalette(SDL_PixelFormat * format, SDL_Palette *palette) 671{ 672 if (!format) { 673 return SDL_SetError("SDL_SetPixelFormatPalette() passed NULL format"); 674 } 675 676 if (palette && palette->ncolors > (1 << format->BitsPerPixel)) { 677 return SDL_SetError("SDL_SetPixelFormatPalette() passed a palette that doesn't match the format"); 678 } 679 680 if (format->palette == palette) { 681 return 0; 682 } 683 684 if (format->palette) { 685 SDL_FreePalette(format->palette); 686 } 687 688 format->palette = palette; 689 690 if (format->palette) { 691 ++format->palette->refcount; 692 } 693 694 return 0; 695} 696 697int 698SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors, 699 int firstcolor, int ncolors) 700{ 701 int status = 0; 702 703 /* Verify the parameters */ 704 if (!palette) { 705 return -1; 706 } 707 if (ncolors > (palette->ncolors - firstcolor)) { 708 ncolors = (palette->ncolors - firstcolor); 709 status = -1; 710 } 711 712 if (colors != (palette->colors + firstcolor)) { 713 SDL_memcpy(palette->colors + firstcolor, colors, 714 ncolors * sizeof(*colors)); 715 } 716 ++palette->version; 717 if (!palette->version) { 718 palette->version = 1; 719 } 720 721 return status; 722} 723 724void 725SDL_FreePalette(SDL_Palette * palette) 726{ 727 if (!palette) { 728 SDL_InvalidParamError("palette"); 729 return; 730 } 731 if (--palette->refcount > 0) { 732 return; 733 } 734 SDL_free(palette->colors); 735 SDL_free(palette); 736} 737 738/* 739 * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors 740 */ 741void 742SDL_DitherColors(SDL_Color * colors, int bpp) 743{ 744 int i; 745 if (bpp != 8) 746 return; /* only 8bpp supported right now */ 747 748 for (i = 0; i < 256; i++) { 749 int r, g, b; 750 /* map each bit field to the full [0, 255] interval, 751 so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */ 752 r = i & 0xe0; 753 r |= r >> 3 | r >> 6; 754 colors[i].r = r; 755 g = (i << 3) & 0xe0; 756 g |= g >> 3 | g >> 6; 757 colors[i].g = g; 758 b = i & 0x3; 759 b |= b << 2; 760 b |= b << 4; 761 colors[i].b = b; 762 colors[i].a = SDL_ALPHA_OPAQUE; 763 } 764} 765 766/* 767 * Match an RGB value to a particular palette index 768 */ 769Uint8 770SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 771{ 772 /* Do colorspace distance matching */ 773 unsigned int smallest; 774 unsigned int distance; 775 int rd, gd, bd, ad; 776 int i; 777 Uint8 pixel = 0; 778 779 smallest = ~0; 780 for (i = 0; i < pal->ncolors; ++i) { 781 rd = pal->colors[i].r - r; 782 gd = pal->colors[i].g - g; 783 bd = pal->colors[i].b - b; 784 ad = pal->colors[i].a - a; 785 distance = (rd * rd) + (gd * gd) + (bd * bd) + (ad * ad); 786 if (distance < smallest) { 787 pixel = i; 788 if (distance == 0) { /* Perfect match! */ 789 break; 790 } 791 smallest = distance; 792 } 793 } 794 return (pixel); 795} 796 797/* Find the opaque pixel value corresponding to an RGB triple */ 798Uint32 799SDL_MapRGB(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b) 800{ 801 if (format->palette == NULL) { 802 return (r >> format->Rloss) << format->Rshift 803 | (g >> format->Gloss) << format->Gshift 804 | (b >> format->Bloss) << format->Bshift | format->Amask; 805 } else { 806 return SDL_FindColor(format->palette, r, g, b, SDL_ALPHA_OPAQUE); 807 } 808} 809 810/* Find the pixel value corresponding to an RGBA quadruple */ 811Uint32 812SDL_MapRGBA(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b, 813 Uint8 a) 814{ 815 if (format->palette == NULL) { 816 return (r >> format->Rloss) << format->Rshift 817 | (g >> format->Gloss) << format->Gshift 818 | (b >> format->Bloss) << format->Bshift 819 | ((a >> format->Aloss) << format->Ashift & format->Amask); 820 } else { 821 return SDL_FindColor(format->palette, r, g, b, a); 822 } 823} 824 825void 826SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat * format, Uint8 * r, Uint8 * g, 827 Uint8 * b) 828{ 829 if (format->palette == NULL) { 830 unsigned v; 831 v = (pixel & format->Rmask) >> format->Rshift; 832 *r = SDL_expand_byte[format->Rloss][v]; 833 v = (pixel & format->Gmask) >> format->Gshift; 834 *g = SDL_expand_byte[format->Gloss][v]; 835 v = (pixel & format->Bmask) >> format->Bshift; 836 *b = SDL_expand_byte[format->Bloss][v]; 837 } else { 838 if (pixel < (unsigned)format->palette->ncolors) { 839 *r = format->palette->colors[pixel].r; 840 *g = format->palette->colors[pixel].g; 841 *b = format->palette->colors[pixel].b; 842 } else { 843 *r = *g = *b = 0; 844 } 845 } 846} 847 848void 849SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormat * format, 850 Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a) 851{ 852 if (format->palette == NULL) { 853 unsigned v; 854 v = (pixel & format->Rmask) >> format->Rshift; 855 *r = SDL_expand_byte[format->Rloss][v]; 856 v = (pixel & format->Gmask) >> format->Gshift; 857 *g = SDL_expand_byte[format->Gloss][v]; 858 v = (pixel & format->Bmask) >> format->Bshift; 859 *b = SDL_expand_byte[format->Bloss][v]; 860 v = (pixel & format->Amask) >> format->Ashift; 861 *a = SDL_expand_byte[format->Aloss][v]; 862 } else { 863 if (pixel < (unsigned)format->palette->ncolors) { 864 *r = format->palette->colors[pixel].r; 865 *g = format->palette->colors[pixel].g; 866 *b = format->palette->colors[pixel].b; 867 *a = format->palette->colors[pixel].a; 868 } else { 869 *r = *g = *b = *a = 0; 870 } 871 } 872} 873 874/* Map from Palette to Palette */ 875static Uint8 * 876Map1to1(SDL_Palette * src, SDL_Palette * dst, int *identical) 877{ 878 Uint8 *map; 879 int i; 880 881 if (identical) { 882 if (src->ncolors <= dst->ncolors) { 883 /* If an identical palette, no need to map */ 884 if (src == dst 885 || 886 (SDL_memcmp 887 (src->colors, dst->colors, 888 src->ncolors * sizeof(SDL_Color)) == 0)) { 889 *identical = 1; 890 return (NULL); 891 } 892 } 893 *identical = 0; 894 } 895 map = (Uint8 *) SDL_malloc(src->ncolors); 896 if (map == NULL) { 897 SDL_OutOfMemory(); 898 return (NULL); 899 } 900 for (i = 0; i < src->ncolors; ++i) { 901 map[i] = SDL_FindColor(dst, 902 src->colors[i].r, src->colors[i].g, 903 src->colors[i].b, src->colors[i].a); 904 } 905 return (map); 906} 907 908/* Map from Palette to BitField */ 909static Uint8 * 910Map1toN(SDL_PixelFormat * src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, Uint8 Amod, 911 SDL_PixelFormat * dst) 912{ 913 Uint8 *map; 914 int i; 915 int bpp; 916 SDL_Palette *pal = src->palette; 917 918 bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel); 919 map = (Uint8 *) SDL_malloc(pal->ncolors * bpp); 920 if (map == NULL) { 921 SDL_OutOfMemory(); 922 return (NULL); 923 } 924 925 /* We memory copy to the pixel map so the endianness is preserved */ 926 for (i = 0; i < pal->ncolors; ++i) { 927 Uint8 R = (Uint8) ((pal->colors[i].r * Rmod) / 255); 928 Uint8 G = (Uint8) ((pal->colors[i].g * Gmod) / 255); 929 Uint8 B = (Uint8) ((pal->colors[i].b * Bmod) / 255); 930 Uint8 A = (Uint8) ((pal->colors[i].a * Amod) / 255); 931 ASSEMBLE_RGBA(&map[i * bpp], dst->BytesPerPixel, dst, R, G, B, A); 932 } 933 return (map); 934} 935 936/* Map from BitField to Dithered-Palette to Palette */ 937static Uint8 * 938MapNto1(SDL_PixelFormat * src, SDL_PixelFormat * dst, int *identical) 939{ 940 /* Generate a 256 color dither palette */ 941 SDL_Palette dithered; 942 SDL_Color colors[256]; 943 SDL_Palette *pal = dst->palette; 944 945 dithered.ncolors = 256; 946 SDL_DitherColors(colors, 8); 947 dithered.colors = colors; 948 return (Map1to1(&dithered, pal, identical)); 949} 950 951SDL_BlitMap * 952SDL_AllocBlitMap(void) 953{ 954 SDL_BlitMap *map; 955 956 /* Allocate the empty map */ 957 map = (SDL_BlitMap *) SDL_calloc(1, sizeof(*map)); 958 if (map == NULL) { 959 SDL_OutOfMemory(); 960 return (NULL); 961 } 962 map->info.r = 0xFF; 963 map->info.g = 0xFF; 964 map->info.b = 0xFF; 965 map->info.a = 0xFF; 966 967 /* It's ready to go */ 968 return (map); 969} 970 971void 972SDL_InvalidateMap(SDL_BlitMap * map) 973{ 974 if (!map) { 975 return; 976 } 977 if (map->dst) { 978 /* Release our reference to the surface - see the note below */ 979 if (--map->dst->refcount <= 0) { 980 SDL_FreeSurface(map->dst); 981 } 982 } 983 map->dst = NULL; 984 map->src_palette_version = 0; 985 map->dst_palette_version = 0; 986 SDL_free(map->info.table); 987 map->info.table = NULL; 988} 989 990int 991SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst) 992{ 993 SDL_PixelFormat *srcfmt; 994 SDL_PixelFormat *dstfmt; 995 SDL_BlitMap *map; 996 997 /* Clear out any previous mapping */ 998 map = src->map; 999 if ((src->flags & SDL_RLEACCEL) == SDL_RLEACCEL) { 1000 SDL_UnRLESurface(src, 1); 1001 } 1002 SDL_InvalidateMap(map); 1003 1004 /* Figure out what kind of mapping we're doing */ 1005 map->identity = 0; 1006 srcfmt = src->format; 1007 dstfmt = dst->format; 1008 if (SDL_ISPIXELFORMAT_INDEXED(srcfmt->format)) { 1009 if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) { 1010 /* Palette --> Palette */ 1011 map->info.table = 1012 Map1to1(srcfmt->palette, dstfmt->palette, &map->identity); 1013 if (!map->identity) { 1014 if (map->info.table == NULL) { 1015 return (-1); 1016 } 1017 } 1018 if (srcfmt->BitsPerPixel != dstfmt->BitsPerPixel) 1019 map->identity = 0; 1020 } else { 1021 /* Palette --> BitField */ 1022 map->info.table = 1023 Map1toN(srcfmt, src->map->info.r, src->map->info.g, 1024 src->map->info.b, src->map->info.a, dstfmt); 1025 if (map->info.table == NULL) { 1026 return (-1); 1027 } 1028 } 1029 } else { 1030 if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) { 1031 /* BitField --> Palette */ 1032 map->info.table = MapNto1(srcfmt, dstfmt, &map->identity); 1033 if (!map->identity) { 1034 if (map->info.table == NULL) { 1035 return (-1); 1036 } 1037 } 1038 map->identity = 0; /* Don't optimize to copy */ 1039 } else { 1040 /* BitField --> BitField */ 1041 if (srcfmt == dstfmt) { 1042 map->identity = 1; 1043 } 1044 } 1045 } 1046 1047 map->dst = dst; 1048 1049 if (map->dst) { 1050 /* Keep a reference to this surface so it doesn't get deleted 1051 while we're still pointing at it. 1052 1053 A better method would be for the destination surface to keep 1054 track of surfaces that are mapped to it and automatically 1055 invalidate them when it is freed, but this will do for now. 1056 */ 1057 ++map->dst->refcount; 1058 } 1059 1060 if (dstfmt->palette) { 1061 map->dst_palette_version = dstfmt->palette->version; 1062 } else { 1063 map->dst_palette_version = 0; 1064 } 1065 1066 if (srcfmt->palette) { 1067 map->src_palette_version = srcfmt->palette->version; 1068 } else { 1069 map->src_palette_version = 0; 1070 } 1071 1072 /* Choose your blitters wisely */ 1073 return (SDL_CalculateBlit(src)); 1074} 1075 1076void 1077SDL_FreeBlitMap(SDL_BlitMap * map) 1078{ 1079 if (map) { 1080 SDL_InvalidateMap(map); 1081 SDL_free(map); 1082 } 1083} 1084 1085void 1086SDL_CalculateGammaRamp(float gamma, Uint16 * ramp) 1087{ 1088 int i; 1089 1090 /* Input validation */ 1091 if (gamma < 0.0f ) { 1092 SDL_InvalidParamError("gamma"); 1093 return; 1094 } 1095 if (ramp == NULL) { 1096 SDL_InvalidParamError("ramp"); 1097 return; 1098 } 1099 1100 /* 0.0 gamma is all black */ 1101 if (gamma == 0.0f) { 1102 SDL_memset(ramp, 0, 256 * sizeof(Uint16)); 1103 return; 1104 } else if (gamma == 1.0f) { 1105 /* 1.0 gamma is identity */ 1106 for (i = 0; i < 256; ++i) { 1107 ramp[i] = (i << 8) | i; 1108 } 1109 return; 1110 } else { 1111 /* Calculate a real gamma ramp */ 1112 int value; 1113 gamma = 1.0f / gamma; 1114 for (i = 0; i < 256; ++i) { 1115 value = 1116 (int) (SDL_pow((double) i / 256.0, gamma) * 65535.0 + 0.5); 1117 if (value > 65535) { 1118 value = 65535; 1119 } 1120 ramp[i] = (Uint16) value; 1121 } 1122 } 1123} 1124 1125/* vi: set ts=4 sw=4 expandtab: */ 1126
[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.