pixman-access.c (49952B)
1 /* 2 * 3 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. 4 * 2005 Lars Knoll & Zack Rusin, Trolltech 5 * 2008 Aaron Plattner, NVIDIA Corporation 6 * 7 * Permission to use, copy, modify, distribute, and sell this software and its 8 * documentation for any purpose is hereby granted without fee, provided that 9 * the above copyright notice appear in all copies and that both that 10 * copyright notice and this permission notice appear in supporting 11 * documentation, and that the name of Keith Packard not be used in 12 * advertising or publicity pertaining to distribution of the software without 13 * specific, written prior permission. Keith Packard makes no 14 * representations about the suitability of this software for any purpose. It 15 * is provided "as is" without express or implied warranty. 16 * 17 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 18 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 22 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 23 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 24 * SOFTWARE. 25 */ 26 27 #ifdef HAVE_CONFIG_H 28 #include <pixman-config.h> 29 #endif 30 31 #include <stdlib.h> 32 #include <string.h> 33 #include <assert.h> 34 #include <math.h> 35 36 #include "pixman-accessor.h" 37 #include "pixman-private.h" 38 39 #define CONVERT_RGB24_TO_Y15(s) \ 40 (((((s) >> 16) & 0xff) * 153 + \ 41 (((s) >> 8) & 0xff) * 301 + \ 42 (((s) ) & 0xff) * 58) >> 2) 43 44 #define CONVERT_RGB24_TO_RGB15(s) \ 45 ((((s) >> 3) & 0x001f) | \ 46 (((s) >> 6) & 0x03e0) | \ 47 (((s) >> 9) & 0x7c00)) 48 49 /* Fetch macros */ 50 51 #ifdef WORDS_BIGENDIAN 52 #define FETCH_1(img,l,o) \ 53 (((READ ((img), ((uint32_t *)(l)) + ((o) >> 5))) >> (0x1f - ((o) & 0x1f))) & 0x1) 54 #else 55 #define FETCH_1(img,l,o) \ 56 ((((READ ((img), ((uint32_t *)(l)) + ((o) >> 5))) >> ((o) & 0x1f))) & 0x1) 57 #endif 58 59 #define FETCH_8(img,l,o) (READ (img, (((uint8_t *)(l)) + ((o) >> 3)))) 60 61 #ifdef WORDS_BIGENDIAN 62 #define FETCH_4(img,l,o) \ 63 (((4 * (o)) & 4) ? (FETCH_8 (img,l, 4 * (o)) & 0xf) : (FETCH_8 (img,l,(4 * (o))) >> 4)) 64 #else 65 #define FETCH_4(img,l,o) \ 66 (((4 * (o)) & 4) ? (FETCH_8 (img, l, 4 * (o)) >> 4) : (FETCH_8 (img, l, (4 * (o))) & 0xf)) 67 #endif 68 69 #ifdef WORDS_BIGENDIAN 70 #define FETCH_24(img,l,o) \ 71 ((uint32_t)(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 0)) << 16) | \ 72 (uint32_t)(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 1)) << 8) | \ 73 (uint32_t)(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 2)) << 0)) 74 #else 75 #define FETCH_24(img,l,o) \ 76 ((uint32_t)(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 0)) << 0) | \ 77 (uint32_t)(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 1)) << 8) | \ 78 (uint32_t)(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 2)) << 16)) 79 #endif 80 81 /* Store macros */ 82 83 #ifdef WORDS_BIGENDIAN 84 #define STORE_1(img,l,o,v) \ 85 do \ 86 { \ 87 uint32_t *__d = ((uint32_t *)(l)) + ((o) >> 5); \ 88 uint32_t __m, __v; \ 89 \ 90 __m = 1U << (0x1f - ((o) & 0x1f)); \ 91 __v = (v)? __m : 0; \ 92 \ 93 WRITE((img), __d, (READ((img), __d) & ~__m) | __v); \ 94 } \ 95 while (0) 96 #else 97 #define STORE_1(img,l,o,v) \ 98 do \ 99 { \ 100 uint32_t *__d = ((uint32_t *)(l)) + ((o) >> 5); \ 101 uint32_t __m, __v; \ 102 \ 103 __m = 1U << ((o) & 0x1f); \ 104 __v = (v)? __m : 0; \ 105 \ 106 WRITE((img), __d, (READ((img), __d) & ~__m) | __v); \ 107 } \ 108 while (0) 109 #endif 110 111 #define STORE_8(img,l,o,v) (WRITE (img, (uint8_t *)(l) + ((o) >> 3), (v))) 112 113 #ifdef WORDS_BIGENDIAN 114 #define STORE_4(img,l,o,v) \ 115 do \ 116 { \ 117 int bo = 4 * (o); \ 118 int v4 = (v) & 0x0f; \ 119 \ 120 STORE_8 (img, l, bo, ( \ 121 bo & 4 ? \ 122 (FETCH_8 (img, l, bo) & 0xf0) | (v4) : \ 123 (FETCH_8 (img, l, bo) & 0x0f) | (v4 << 4))); \ 124 } while (0) 125 #else 126 #define STORE_4(img,l,o,v) \ 127 do \ 128 { \ 129 int bo = 4 * (o); \ 130 int v4 = (v) & 0x0f; \ 131 \ 132 STORE_8 (img, l, bo, ( \ 133 bo & 4 ? \ 134 (FETCH_8 (img, l, bo) & 0x0f) | (v4 << 4) : \ 135 (FETCH_8 (img, l, bo) & 0xf0) | (v4))); \ 136 } while (0) 137 #endif 138 139 #ifdef WORDS_BIGENDIAN 140 #define STORE_24(img,l,o,v) \ 141 do \ 142 { \ 143 uint8_t *__tmp = (l) + 3 * (o); \ 144 \ 145 WRITE ((img), __tmp++, ((v) & 0x00ff0000) >> 16); \ 146 WRITE ((img), __tmp++, ((v) & 0x0000ff00) >> 8); \ 147 WRITE ((img), __tmp++, ((v) & 0x000000ff) >> 0); \ 148 } \ 149 while (0) 150 #else 151 #define STORE_24(img,l,o,v) \ 152 do \ 153 { \ 154 uint8_t *__tmp = (l) + 3 * (o); \ 155 \ 156 WRITE ((img), __tmp++, ((v) & 0x000000ff) >> 0); \ 157 WRITE ((img), __tmp++, ((v) & 0x0000ff00) >> 8); \ 158 WRITE ((img), __tmp++, ((v) & 0x00ff0000) >> 16); \ 159 } \ 160 while (0) 161 #endif 162 163 /* 164 * YV12 setup and access macros 165 */ 166 167 #define YV12_SETUP(image) \ 168 bits_image_t *__bits_image = (bits_image_t *)image; \ 169 uint32_t *bits = __bits_image->bits; \ 170 int stride = __bits_image->rowstride; \ 171 int offset0 = stride < 0 ? \ 172 ((-stride) >> 1) * ((__bits_image->height - 1) >> 1) - stride : \ 173 stride * __bits_image->height; \ 174 int offset1 = stride < 0 ? \ 175 offset0 + ((-stride) >> 1) * ((__bits_image->height) >> 1) : \ 176 offset0 + (offset0 >> 2) 177 178 /* Note no trailing semicolon on the above macro; if it's there, then 179 * the typical usage of YV12_SETUP(image); will have an extra trailing ; 180 * that some compilers will interpret as a statement -- and then any further 181 * variable declarations will cause an error. 182 */ 183 184 #define YV12_Y(line) \ 185 ((uint8_t *) ((bits) + (stride) * (line))) 186 187 #define YV12_U(line) \ 188 ((uint8_t *) ((bits) + offset1 + \ 189 ((stride) >> 1) * ((line) >> 1))) 190 191 #define YV12_V(line) \ 192 ((uint8_t *) ((bits) + offset0 + \ 193 ((stride) >> 1) * ((line) >> 1))) 194 195 /* Misc. helpers */ 196 197 static force_inline void 198 get_shifts (pixman_format_code_t format, 199 int *a, 200 int *r, 201 int *g, 202 int *b) 203 { 204 switch (PIXMAN_FORMAT_TYPE (format)) 205 { 206 case PIXMAN_TYPE_A: 207 *b = 0; 208 *g = 0; 209 *r = 0; 210 *a = 0; 211 break; 212 213 case PIXMAN_TYPE_ARGB: 214 case PIXMAN_TYPE_ARGB_SRGB: 215 *b = 0; 216 *g = *b + PIXMAN_FORMAT_B (format); 217 *r = *g + PIXMAN_FORMAT_G (format); 218 *a = *r + PIXMAN_FORMAT_R (format); 219 break; 220 221 case PIXMAN_TYPE_ABGR: 222 *r = 0; 223 *g = *r + PIXMAN_FORMAT_R (format); 224 *b = *g + PIXMAN_FORMAT_G (format); 225 *a = *b + PIXMAN_FORMAT_B (format); 226 break; 227 228 case PIXMAN_TYPE_BGRA: 229 /* With BGRA formats we start counting at the high end of the pixel */ 230 *b = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_B (format); 231 *g = *b - PIXMAN_FORMAT_B (format); 232 *r = *g - PIXMAN_FORMAT_G (format); 233 *a = *r - PIXMAN_FORMAT_R (format); 234 break; 235 236 case PIXMAN_TYPE_RGBA: 237 /* With BGRA formats we start counting at the high end of the pixel */ 238 *r = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_R (format); 239 *g = *r - PIXMAN_FORMAT_R (format); 240 *b = *g - PIXMAN_FORMAT_G (format); 241 *a = *b - PIXMAN_FORMAT_B (format); 242 break; 243 244 default: 245 assert (0); 246 break; 247 } 248 } 249 250 static force_inline uint32_t 251 convert_channel (uint32_t pixel, uint32_t def_value, 252 int n_from_bits, int from_shift, 253 int n_to_bits, int to_shift) 254 { 255 uint32_t v; 256 257 if (n_from_bits && n_to_bits) 258 v = unorm_to_unorm (pixel >> from_shift, n_from_bits, n_to_bits); 259 else if (n_to_bits) 260 v = def_value; 261 else 262 v = 0; 263 264 return (v & ((1 << n_to_bits) - 1)) << to_shift; 265 } 266 267 static force_inline uint32_t 268 convert_pixel (pixman_format_code_t from, pixman_format_code_t to, uint32_t pixel) 269 { 270 int a_from_shift, r_from_shift, g_from_shift, b_from_shift; 271 int a_to_shift, r_to_shift, g_to_shift, b_to_shift; 272 uint32_t a, r, g, b; 273 274 get_shifts (from, &a_from_shift, &r_from_shift, &g_from_shift, &b_from_shift); 275 get_shifts (to, &a_to_shift, &r_to_shift, &g_to_shift, &b_to_shift); 276 277 a = convert_channel (pixel, ~0, 278 PIXMAN_FORMAT_A (from), a_from_shift, 279 PIXMAN_FORMAT_A (to), a_to_shift); 280 281 r = convert_channel (pixel, 0, 282 PIXMAN_FORMAT_R (from), r_from_shift, 283 PIXMAN_FORMAT_R (to), r_to_shift); 284 285 g = convert_channel (pixel, 0, 286 PIXMAN_FORMAT_G (from), g_from_shift, 287 PIXMAN_FORMAT_G (to), g_to_shift); 288 289 b = convert_channel (pixel, 0, 290 PIXMAN_FORMAT_B (from), b_from_shift, 291 PIXMAN_FORMAT_B (to), b_to_shift); 292 293 return a | r | g | b; 294 } 295 296 static force_inline uint32_t 297 convert_pixel_to_a8r8g8b8 (bits_image_t *image, 298 pixman_format_code_t format, 299 uint32_t pixel) 300 { 301 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY || 302 PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR) 303 { 304 return image->indexed->rgba[pixel]; 305 } 306 else 307 { 308 return convert_pixel (format, PIXMAN_a8r8g8b8, pixel); 309 } 310 } 311 312 static force_inline uint32_t 313 convert_pixel_from_a8r8g8b8 (pixman_image_t *image, 314 pixman_format_code_t format, uint32_t pixel) 315 { 316 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY) 317 { 318 pixel = CONVERT_RGB24_TO_Y15 (pixel); 319 320 return image->bits.indexed->ent[pixel & 0x7fff]; 321 } 322 else if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR) 323 { 324 pixel = convert_pixel (PIXMAN_a8r8g8b8, PIXMAN_x1r5g5b5, pixel); 325 326 return image->bits.indexed->ent[pixel & 0x7fff]; 327 } 328 else 329 { 330 return convert_pixel (PIXMAN_a8r8g8b8, format, pixel); 331 } 332 } 333 334 static force_inline uint32_t 335 fetch_and_convert_pixel (bits_image_t * image, 336 const uint8_t * bits, 337 int offset, 338 pixman_format_code_t format) 339 { 340 uint32_t pixel; 341 342 switch (PIXMAN_FORMAT_BPP (format)) 343 { 344 case 1: 345 pixel = FETCH_1 (image, bits, offset); 346 break; 347 348 case 4: 349 pixel = FETCH_4 (image, bits, offset); 350 break; 351 352 case 8: 353 pixel = READ (image, bits + offset); 354 break; 355 356 case 16: 357 pixel = READ (image, ((uint16_t *)bits + offset)); 358 break; 359 360 case 24: 361 pixel = FETCH_24 (image, bits, offset); 362 break; 363 364 case 32: 365 pixel = READ (image, ((uint32_t *)bits + offset)); 366 break; 367 368 default: 369 pixel = 0xffff00ff; /* As ugly as possible to detect the bug */ 370 break; 371 } 372 373 return convert_pixel_to_a8r8g8b8 (image, format, pixel); 374 } 375 376 static force_inline void 377 convert_and_store_pixel (bits_image_t * image, 378 uint8_t * dest, 379 int offset, 380 pixman_format_code_t format, 381 uint32_t pixel) 382 { 383 uint32_t converted = convert_pixel_from_a8r8g8b8 ( 384 (pixman_image_t *)image, format, pixel); 385 386 switch (PIXMAN_FORMAT_BPP (format)) 387 { 388 case 1: 389 STORE_1 (image, dest, offset, converted & 0x01); 390 break; 391 392 case 4: 393 STORE_4 (image, dest, offset, converted & 0xf); 394 break; 395 396 case 8: 397 WRITE (image, (dest + offset), converted & 0xff); 398 break; 399 400 case 16: 401 WRITE (image, ((uint16_t *)dest + offset), converted & 0xffff); 402 break; 403 404 case 24: 405 STORE_24 (image, dest, offset, converted); 406 break; 407 408 case 32: 409 WRITE (image, ((uint32_t *)dest + offset), converted); 410 break; 411 412 default: 413 *dest = 0x0; 414 break; 415 } 416 } 417 418 #define MAKE_ACCESSORS(format) \ 419 static void \ 420 fetch_scanline_ ## format (bits_image_t *image, \ 421 int x, \ 422 int y, \ 423 int width, \ 424 uint32_t * buffer, \ 425 const uint32_t *mask) \ 426 { \ 427 uint8_t *bits = \ 428 (uint8_t *)(image->bits + y * image->rowstride); \ 429 int i; \ 430 \ 431 for (i = 0; i < width; ++i) \ 432 { \ 433 *buffer++ = \ 434 fetch_and_convert_pixel (image, bits, x + i, PIXMAN_ ## format); \ 435 } \ 436 } \ 437 \ 438 static void \ 439 store_scanline_ ## format (bits_image_t * image, \ 440 int x, \ 441 int y, \ 442 int width, \ 443 const uint32_t *values) \ 444 { \ 445 uint8_t *dest = \ 446 (uint8_t *)(image->bits + y * image->rowstride); \ 447 int i; \ 448 \ 449 for (i = 0; i < width; ++i) \ 450 { \ 451 convert_and_store_pixel ( \ 452 image, dest, i + x, PIXMAN_ ## format, values[i]); \ 453 } \ 454 } \ 455 \ 456 static uint32_t \ 457 fetch_pixel_ ## format (bits_image_t *image, \ 458 int offset, \ 459 int line) \ 460 { \ 461 uint8_t *bits = \ 462 (uint8_t *)(image->bits + line * image->rowstride); \ 463 \ 464 return fetch_and_convert_pixel ( \ 465 image, bits, offset, PIXMAN_ ## format); \ 466 } \ 467 \ 468 static const void *const __dummy__ ## format MAYBE_UNUSED 469 470 MAKE_ACCESSORS(a8r8g8b8); 471 MAKE_ACCESSORS(x8r8g8b8); 472 MAKE_ACCESSORS(a8b8g8r8); 473 MAKE_ACCESSORS(x8b8g8r8); 474 MAKE_ACCESSORS(x14r6g6b6); 475 MAKE_ACCESSORS(b8g8r8a8); 476 MAKE_ACCESSORS(b8g8r8x8); 477 MAKE_ACCESSORS(r8g8b8x8); 478 MAKE_ACCESSORS(r8g8b8a8); 479 MAKE_ACCESSORS(r8g8b8); 480 MAKE_ACCESSORS(b8g8r8); 481 MAKE_ACCESSORS(r5g6b5); 482 MAKE_ACCESSORS(b5g6r5); 483 MAKE_ACCESSORS(a1r5g5b5); 484 MAKE_ACCESSORS(x1r5g5b5); 485 MAKE_ACCESSORS(a1b5g5r5); 486 MAKE_ACCESSORS(x1b5g5r5); 487 MAKE_ACCESSORS(a4r4g4b4); 488 MAKE_ACCESSORS(x4r4g4b4); 489 MAKE_ACCESSORS(a4b4g4r4); 490 MAKE_ACCESSORS(x4b4g4r4); 491 MAKE_ACCESSORS(a8); 492 MAKE_ACCESSORS(c8); 493 MAKE_ACCESSORS(g8); 494 MAKE_ACCESSORS(r3g3b2); 495 MAKE_ACCESSORS(b2g3r3); 496 MAKE_ACCESSORS(a2r2g2b2); 497 MAKE_ACCESSORS(a2b2g2r2); 498 MAKE_ACCESSORS(x4a4); 499 MAKE_ACCESSORS(a4); 500 MAKE_ACCESSORS(g4); 501 MAKE_ACCESSORS(c4); 502 MAKE_ACCESSORS(r1g2b1); 503 MAKE_ACCESSORS(b1g2r1); 504 MAKE_ACCESSORS(a1r1g1b1); 505 MAKE_ACCESSORS(a1b1g1r1); 506 MAKE_ACCESSORS(a1); 507 MAKE_ACCESSORS(g1); 508 509 /********************************** Fetch ************************************/ 510 /* Table mapping sRGB-encoded 8 bit numbers to linearly encoded 511 * floating point numbers. We assume that single precision 512 * floating point follows the IEEE 754 format. 513 */ 514 static const uint32_t to_linear_u[256] = 515 { 516 0x00000000, 0x399f22b4, 0x3a1f22b4, 0x3a6eb40e, 0x3a9f22b4, 0x3ac6eb61, 517 0x3aeeb40e, 0x3b0b3e5d, 0x3b1f22b4, 0x3b33070b, 0x3b46eb61, 0x3b5b518a, 518 0x3b70f18a, 0x3b83e1c5, 0x3b8fe614, 0x3b9c87fb, 0x3ba9c9b5, 0x3bb7ad6d, 519 0x3bc63547, 0x3bd5635f, 0x3be539bd, 0x3bf5ba70, 0x3c0373b5, 0x3c0c6152, 520 0x3c15a703, 0x3c1f45bc, 0x3c293e68, 0x3c3391f4, 0x3c3e4149, 0x3c494d43, 521 0x3c54b6c7, 0x3c607eb1, 0x3c6ca5df, 0x3c792d22, 0x3c830aa8, 0x3c89af9e, 522 0x3c9085db, 0x3c978dc5, 0x3c9ec7c0, 0x3ca63432, 0x3cadd37d, 0x3cb5a601, 523 0x3cbdac20, 0x3cc5e639, 0x3cce54ab, 0x3cd6f7d2, 0x3cdfd00e, 0x3ce8ddb9, 524 0x3cf2212c, 0x3cfb9ac1, 0x3d02a569, 0x3d0798dc, 0x3d0ca7e4, 0x3d11d2ae, 525 0x3d171963, 0x3d1c7c2e, 0x3d21fb3a, 0x3d2796af, 0x3d2d4ebb, 0x3d332380, 526 0x3d39152b, 0x3d3f23e3, 0x3d454fd0, 0x3d4b991c, 0x3d51ffeb, 0x3d588466, 527 0x3d5f26b7, 0x3d65e6fe, 0x3d6cc564, 0x3d73c210, 0x3d7add25, 0x3d810b65, 528 0x3d84b793, 0x3d88732e, 0x3d8c3e48, 0x3d9018f4, 0x3d940343, 0x3d97fd48, 529 0x3d9c0714, 0x3da020b9, 0x3da44a48, 0x3da883d6, 0x3daccd70, 0x3db12728, 530 0x3db59110, 0x3dba0b38, 0x3dbe95b2, 0x3dc3308f, 0x3dc7dbe0, 0x3dcc97b4, 531 0x3dd1641c, 0x3dd6412a, 0x3ddb2eec, 0x3de02d75, 0x3de53cd3, 0x3dea5d16, 532 0x3def8e52, 0x3df4d091, 0x3dfa23e5, 0x3dff885e, 0x3e027f06, 0x3e05427f, 533 0x3e080ea2, 0x3e0ae376, 0x3e0dc104, 0x3e10a752, 0x3e139669, 0x3e168e50, 534 0x3e198f0e, 0x3e1c98ab, 0x3e1fab2e, 0x3e22c6a0, 0x3e25eb08, 0x3e29186a, 535 0x3e2c4ed0, 0x3e2f8e42, 0x3e32d6c4, 0x3e362861, 0x3e39831e, 0x3e3ce702, 536 0x3e405416, 0x3e43ca5e, 0x3e4749e4, 0x3e4ad2ae, 0x3e4e64c2, 0x3e520027, 537 0x3e55a4e6, 0x3e595303, 0x3e5d0a8a, 0x3e60cb7c, 0x3e6495e0, 0x3e6869bf, 538 0x3e6c4720, 0x3e702e08, 0x3e741e7f, 0x3e78188c, 0x3e7c1c34, 0x3e8014c0, 539 0x3e822039, 0x3e84308b, 0x3e8645b8, 0x3e885fc3, 0x3e8a7eb0, 0x3e8ca281, 540 0x3e8ecb3a, 0x3e90f8df, 0x3e932b72, 0x3e9562f6, 0x3e979f6f, 0x3e99e0e0, 541 0x3e9c274e, 0x3e9e72b8, 0x3ea0c322, 0x3ea31892, 0x3ea57308, 0x3ea7d28a, 542 0x3eaa3718, 0x3eaca0b7, 0x3eaf0f69, 0x3eb18332, 0x3eb3fc16, 0x3eb67a15, 543 0x3eb8fd34, 0x3ebb8576, 0x3ebe12de, 0x3ec0a56e, 0x3ec33d2a, 0x3ec5da14, 544 0x3ec87c30, 0x3ecb2380, 0x3ecdd008, 0x3ed081ca, 0x3ed338c9, 0x3ed5f508, 545 0x3ed8b68a, 0x3edb7d52, 0x3ede4962, 0x3ee11abe, 0x3ee3f168, 0x3ee6cd64, 546 0x3ee9aeb6, 0x3eec955d, 0x3eef815d, 0x3ef272ba, 0x3ef56976, 0x3ef86594, 547 0x3efb6717, 0x3efe6e02, 0x3f00bd2b, 0x3f02460c, 0x3f03d1a5, 0x3f055ff8, 548 0x3f06f105, 0x3f0884ce, 0x3f0a1b54, 0x3f0bb499, 0x3f0d509f, 0x3f0eef65, 549 0x3f1090ef, 0x3f12353c, 0x3f13dc50, 0x3f15862a, 0x3f1732cc, 0x3f18e237, 550 0x3f1a946d, 0x3f1c4970, 0x3f1e013f, 0x3f1fbbde, 0x3f21794c, 0x3f23398c, 551 0x3f24fca0, 0x3f26c286, 0x3f288b42, 0x3f2a56d3, 0x3f2c253d, 0x3f2df680, 552 0x3f2fca9d, 0x3f31a195, 0x3f337b6a, 0x3f35581e, 0x3f3737b1, 0x3f391a24, 553 0x3f3aff7a, 0x3f3ce7b2, 0x3f3ed2d0, 0x3f40c0d2, 0x3f42b1bc, 0x3f44a58e, 554 0x3f469c49, 0x3f4895ee, 0x3f4a9280, 0x3f4c91ff, 0x3f4e946c, 0x3f5099c8, 555 0x3f52a216, 0x3f54ad55, 0x3f56bb88, 0x3f58ccae, 0x3f5ae0cb, 0x3f5cf7de, 556 0x3f5f11ec, 0x3f612ef0, 0x3f634eef, 0x3f6571ea, 0x3f6797e1, 0x3f69c0d6, 557 0x3f6beccb, 0x3f6e1bc0, 0x3f704db6, 0x3f7282af, 0x3f74baac, 0x3f76f5ae, 558 0x3f7933b6, 0x3f7b74c6, 0x3f7db8de, 0x3f800000 559 }; 560 561 static const float * const to_linear = (const float *)to_linear_u; 562 563 static uint8_t 564 to_srgb (float f) 565 { 566 uint8_t low = 0; 567 uint8_t high = 255; 568 569 while (high - low > 1) 570 { 571 uint8_t mid = (low + high) / 2; 572 573 if (to_linear[mid] > f) 574 high = mid; 575 else 576 low = mid; 577 } 578 579 if (to_linear[high] - f < f - to_linear[low]) 580 return high; 581 else 582 return low; 583 } 584 585 static void 586 fetch_scanline_a8r8g8b8_sRGB_float (bits_image_t * image, 587 int x, 588 int y, 589 int width, 590 uint32_t * b, 591 const uint32_t *mask) 592 { 593 const uint32_t *bits = image->bits + y * image->rowstride; 594 const uint32_t *pixel = bits + x; 595 const uint32_t *end = pixel + width; 596 argb_t *buffer = (argb_t *)b; 597 598 while (pixel < end) 599 { 600 uint32_t p = READ (image, pixel++); 601 argb_t *argb = buffer; 602 603 argb->a = pixman_unorm_to_float ((p >> 24) & 0xff, 8); 604 605 argb->r = to_linear [(p >> 16) & 0xff]; 606 argb->g = to_linear [(p >> 8) & 0xff]; 607 argb->b = to_linear [(p >> 0) & 0xff]; 608 609 buffer++; 610 } 611 } 612 613 static void 614 fetch_scanline_r8g8b8_sRGB_float (bits_image_t * image, 615 int x, 616 int y, 617 int width, 618 uint32_t * b, 619 const uint32_t *mask) 620 { 621 const uint8_t *bits = (uint8_t *)(image->bits + y * image->rowstride); 622 argb_t *buffer = (argb_t *)b; 623 int i; 624 for (i = x; i < width; ++i) 625 { 626 uint32_t p = FETCH_24 (image, bits, i); 627 argb_t *argb = buffer; 628 629 argb->a = 1.0f; 630 631 argb->r = to_linear[(p >> 16) & 0xff]; 632 argb->g = to_linear[(p >> 8) & 0xff]; 633 argb->b = to_linear[(p >> 0) & 0xff]; 634 635 buffer++; 636 } 637 } 638 639 /* Expects a float buffer */ 640 static void 641 fetch_scanline_a2r10g10b10_float (bits_image_t * image, 642 int x, 643 int y, 644 int width, 645 uint32_t * b, 646 const uint32_t *mask) 647 { 648 const uint32_t *bits = image->bits + y * image->rowstride; 649 const uint32_t *pixel = bits + x; 650 const uint32_t *end = pixel + width; 651 argb_t *buffer = (argb_t *)b; 652 653 while (pixel < end) 654 { 655 uint32_t p = READ (image, pixel++); 656 uint64_t a = p >> 30; 657 uint64_t r = (p >> 20) & 0x3ff; 658 uint64_t g = (p >> 10) & 0x3ff; 659 uint64_t b = p & 0x3ff; 660 661 buffer->a = pixman_unorm_to_float (a, 2); 662 buffer->r = pixman_unorm_to_float (r, 10); 663 buffer->g = pixman_unorm_to_float (g, 10); 664 buffer->b = pixman_unorm_to_float (b, 10); 665 666 buffer++; 667 } 668 } 669 670 /* Expects a float buffer */ 671 #ifndef PIXMAN_FB_ACCESSORS 672 static void 673 fetch_scanline_rgbf_float (bits_image_t *image, 674 int x, 675 int y, 676 int width, 677 uint32_t * b, 678 const uint32_t *mask) 679 { 680 const float *bits = (float *)image->bits + y * image->rowstride; 681 const float *pixel = bits + x * 3; 682 argb_t *buffer = (argb_t *)b; 683 684 for (; width--; buffer++) { 685 buffer->r = *pixel++; 686 buffer->g = *pixel++; 687 buffer->b = *pixel++; 688 buffer->a = 1.f; 689 } 690 } 691 692 static void 693 fetch_scanline_rgbaf_float (bits_image_t *image, 694 int x, 695 int y, 696 int width, 697 uint32_t * b, 698 const uint32_t *mask) 699 { 700 const float *bits = (float *)image->bits + y * image->rowstride; 701 const float *pixel = bits + x * 4; 702 argb_t *buffer = (argb_t *)b; 703 704 for (; width--; buffer++) { 705 buffer->r = *pixel++; 706 buffer->g = *pixel++; 707 buffer->b = *pixel++; 708 buffer->a = *pixel++; 709 } 710 } 711 #endif 712 713 static void 714 fetch_scanline_a16b16g16r16_float (bits_image_t * image, 715 int x, 716 int y, 717 int width, 718 uint32_t * b, 719 const uint32_t *mask) 720 { 721 const uint64_t *bits = (uint64_t *)(image->bits + y * image->rowstride); 722 const uint64_t *pixel = bits + x; 723 const uint64_t *end = pixel + width; 724 argb_t *buffer = (argb_t *)b; 725 726 while (pixel < end) 727 { 728 uint64_t p = READ (image, pixel++); 729 uint64_t a = (p >> 48) & 0xffff; 730 uint64_t b = (p >> 32) & 0xffff; 731 uint64_t g = (p >> 16) & 0xffff; 732 uint64_t r = (p >> 0) & 0xffff; 733 734 buffer->a = pixman_unorm_to_float (a, 16); 735 buffer->r = pixman_unorm_to_float (r, 16); 736 buffer->g = pixman_unorm_to_float (g, 16); 737 buffer->b = pixman_unorm_to_float (b, 16); 738 739 buffer++; 740 } 741 } 742 743 static void 744 fetch_scanline_x2r10g10b10_float (bits_image_t *image, 745 int x, 746 int y, 747 int width, 748 uint32_t * b, 749 const uint32_t *mask) 750 { 751 const uint32_t *bits = image->bits + y * image->rowstride; 752 const uint32_t *pixel = (uint32_t *)bits + x; 753 const uint32_t *end = pixel + width; 754 argb_t *buffer = (argb_t *)b; 755 756 while (pixel < end) 757 { 758 uint32_t p = READ (image, pixel++); 759 uint64_t r = (p >> 20) & 0x3ff; 760 uint64_t g = (p >> 10) & 0x3ff; 761 uint64_t b = p & 0x3ff; 762 763 buffer->a = 1.0; 764 buffer->r = pixman_unorm_to_float (r, 10); 765 buffer->g = pixman_unorm_to_float (g, 10); 766 buffer->b = pixman_unorm_to_float (b, 10); 767 768 buffer++; 769 } 770 } 771 772 /* Expects a float buffer */ 773 static void 774 fetch_scanline_a2b10g10r10_float (bits_image_t *image, 775 int x, 776 int y, 777 int width, 778 uint32_t * b, 779 const uint32_t *mask) 780 { 781 const uint32_t *bits = image->bits + y * image->rowstride; 782 const uint32_t *pixel = bits + x; 783 const uint32_t *end = pixel + width; 784 argb_t *buffer = (argb_t *)b; 785 786 while (pixel < end) 787 { 788 uint32_t p = READ (image, pixel++); 789 uint64_t a = p >> 30; 790 uint64_t b = (p >> 20) & 0x3ff; 791 uint64_t g = (p >> 10) & 0x3ff; 792 uint64_t r = p & 0x3ff; 793 794 buffer->a = pixman_unorm_to_float (a, 2); 795 buffer->r = pixman_unorm_to_float (r, 10); 796 buffer->g = pixman_unorm_to_float (g, 10); 797 buffer->b = pixman_unorm_to_float (b, 10); 798 799 buffer++; 800 } 801 } 802 803 /* Expects a float buffer */ 804 static void 805 fetch_scanline_x2b10g10r10_float (bits_image_t *image, 806 int x, 807 int y, 808 int width, 809 uint32_t * b, 810 const uint32_t *mask) 811 { 812 const uint32_t *bits = image->bits + y * image->rowstride; 813 const uint32_t *pixel = (uint32_t *)bits + x; 814 const uint32_t *end = pixel + width; 815 argb_t *buffer = (argb_t *)b; 816 817 while (pixel < end) 818 { 819 uint32_t p = READ (image, pixel++); 820 uint64_t b = (p >> 20) & 0x3ff; 821 uint64_t g = (p >> 10) & 0x3ff; 822 uint64_t r = p & 0x3ff; 823 824 buffer->a = 1.0; 825 buffer->r = pixman_unorm_to_float (r, 10); 826 buffer->g = pixman_unorm_to_float (g, 10); 827 buffer->b = pixman_unorm_to_float (b, 10); 828 829 buffer++; 830 } 831 } 832 833 static void 834 fetch_scanline_yuy2 (bits_image_t *image, 835 int x, 836 int line, 837 int width, 838 uint32_t * buffer, 839 const uint32_t *mask) 840 { 841 const uint32_t *bits = image->bits + image->rowstride * line; 842 int i; 843 844 for (i = 0; i < width; i++) 845 { 846 int16_t y, u, v; 847 int32_t r, g, b; 848 849 y = ((uint8_t *) bits)[(x + i) << 1] - 16; 850 u = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 1] - 128; 851 v = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 3] - 128; 852 853 /* R = 1.164(Y - 16) + 1.596(V - 128) */ 854 r = 0x012b27 * y + 0x019a2e * v; 855 /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */ 856 g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u; 857 /* B = 1.164(Y - 16) + 2.018(U - 128) */ 858 b = 0x012b27 * y + 0x0206a2 * u; 859 860 *buffer++ = 0xff000000 | 861 (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) | 862 (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) | 863 (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0); 864 } 865 } 866 867 static void 868 fetch_scanline_yv12 (bits_image_t *image, 869 int x, 870 int line, 871 int width, 872 uint32_t * buffer, 873 const uint32_t *mask) 874 { 875 YV12_SETUP (image); 876 uint8_t *y_line = YV12_Y (line); 877 uint8_t *u_line = YV12_U (line); 878 uint8_t *v_line = YV12_V (line); 879 int i; 880 881 for (i = 0; i < width; i++) 882 { 883 int16_t y, u, v; 884 int32_t r, g, b; 885 886 y = y_line[x + i] - 16; 887 u = u_line[(x + i) >> 1] - 128; 888 v = v_line[(x + i) >> 1] - 128; 889 890 /* R = 1.164(Y - 16) + 1.596(V - 128) */ 891 r = 0x012b27 * y + 0x019a2e * v; 892 /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */ 893 g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u; 894 /* B = 1.164(Y - 16) + 2.018(U - 128) */ 895 b = 0x012b27 * y + 0x0206a2 * u; 896 897 *buffer++ = 0xff000000 | 898 (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) | 899 (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) | 900 (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0); 901 } 902 } 903 904 /**************************** Pixel wise fetching *****************************/ 905 906 #ifndef PIXMAN_FB_ACCESSORS 907 static argb_t 908 fetch_pixel_rgbf_float (bits_image_t *image, 909 int offset, 910 int line) 911 { 912 float *bits = (float *)image->bits + line * image->rowstride; 913 argb_t argb; 914 915 argb.r = bits[offset * 3]; 916 argb.g = bits[offset * 3 + 1]; 917 argb.b = bits[offset * 3 + 2]; 918 argb.a = 1.f; 919 920 return argb; 921 } 922 923 static argb_t 924 fetch_pixel_rgbaf_float (bits_image_t *image, 925 int offset, 926 int line) 927 { 928 float *bits = (float *)image->bits + line * image->rowstride; 929 argb_t argb; 930 931 argb.r = bits[offset * 4]; 932 argb.g = bits[offset * 4 + 1]; 933 argb.b = bits[offset * 4 + 2]; 934 argb.a = bits[offset * 4 + 3]; 935 936 return argb; 937 } 938 #endif 939 940 static argb_t 941 fetch_pixel_a16b16g16r16_float (bits_image_t *image, 942 int offset, 943 int line) 944 { 945 uint64_t *bits = (uint64_t *)(image->bits + line * image->rowstride); 946 uint64_t p = READ (image, bits + offset); 947 uint64_t a = (p >> 48) & 0xffff; 948 uint64_t b = (p >> 32) & 0xffff; 949 uint64_t g = (p >> 16) & 0xffff; 950 uint64_t r = (p >> 0) & 0xffff; 951 argb_t argb; 952 953 argb.a = pixman_unorm_to_float (a, 16); 954 argb.r = pixman_unorm_to_float (r, 16); 955 argb.g = pixman_unorm_to_float (g, 16); 956 argb.b = pixman_unorm_to_float (b, 16); 957 958 return argb; 959 } 960 961 static argb_t 962 fetch_pixel_x2r10g10b10_float (bits_image_t *image, 963 int offset, 964 int line) 965 { 966 uint32_t *bits = image->bits + line * image->rowstride; 967 uint32_t p = READ (image, bits + offset); 968 uint64_t r = (p >> 20) & 0x3ff; 969 uint64_t g = (p >> 10) & 0x3ff; 970 uint64_t b = p & 0x3ff; 971 argb_t argb; 972 973 argb.a = 1.0; 974 argb.r = pixman_unorm_to_float (r, 10); 975 argb.g = pixman_unorm_to_float (g, 10); 976 argb.b = pixman_unorm_to_float (b, 10); 977 978 return argb; 979 } 980 981 static argb_t 982 fetch_pixel_a2r10g10b10_float (bits_image_t *image, 983 int offset, 984 int line) 985 { 986 uint32_t *bits = image->bits + line * image->rowstride; 987 uint32_t p = READ (image, bits + offset); 988 uint64_t a = p >> 30; 989 uint64_t r = (p >> 20) & 0x3ff; 990 uint64_t g = (p >> 10) & 0x3ff; 991 uint64_t b = p & 0x3ff; 992 argb_t argb; 993 994 argb.a = pixman_unorm_to_float (a, 2); 995 argb.r = pixman_unorm_to_float (r, 10); 996 argb.g = pixman_unorm_to_float (g, 10); 997 argb.b = pixman_unorm_to_float (b, 10); 998 999 return argb; 1000 } 1001 1002 static argb_t 1003 fetch_pixel_a2b10g10r10_float (bits_image_t *image, 1004 int offset, 1005 int line) 1006 { 1007 uint32_t *bits = image->bits + line * image->rowstride; 1008 uint32_t p = READ (image, bits + offset); 1009 uint64_t a = p >> 30; 1010 uint64_t b = (p >> 20) & 0x3ff; 1011 uint64_t g = (p >> 10) & 0x3ff; 1012 uint64_t r = p & 0x3ff; 1013 argb_t argb; 1014 1015 argb.a = pixman_unorm_to_float (a, 2); 1016 argb.r = pixman_unorm_to_float (r, 10); 1017 argb.g = pixman_unorm_to_float (g, 10); 1018 argb.b = pixman_unorm_to_float (b, 10); 1019 1020 return argb; 1021 } 1022 1023 static argb_t 1024 fetch_pixel_x2b10g10r10_float (bits_image_t *image, 1025 int offset, 1026 int line) 1027 { 1028 uint32_t *bits = image->bits + line * image->rowstride; 1029 uint32_t p = READ (image, bits + offset); 1030 uint64_t b = (p >> 20) & 0x3ff; 1031 uint64_t g = (p >> 10) & 0x3ff; 1032 uint64_t r = p & 0x3ff; 1033 argb_t argb; 1034 1035 argb.a = 1.0; 1036 argb.r = pixman_unorm_to_float (r, 10); 1037 argb.g = pixman_unorm_to_float (g, 10); 1038 argb.b = pixman_unorm_to_float (b, 10); 1039 1040 return argb; 1041 } 1042 1043 static argb_t 1044 fetch_pixel_a8r8g8b8_sRGB_float (bits_image_t *image, 1045 int offset, 1046 int line) 1047 { 1048 uint32_t *bits = image->bits + line * image->rowstride; 1049 uint32_t p = READ (image, bits + offset); 1050 argb_t argb; 1051 1052 argb.a = pixman_unorm_to_float ((p >> 24) & 0xff, 8); 1053 1054 argb.r = to_linear [(p >> 16) & 0xff]; 1055 argb.g = to_linear [(p >> 8) & 0xff]; 1056 argb.b = to_linear [(p >> 0) & 0xff]; 1057 1058 return argb; 1059 } 1060 1061 static argb_t 1062 fetch_pixel_r8g8b8_sRGB_float (bits_image_t *image, 1063 int offset, 1064 int line) 1065 { 1066 uint8_t *bits = (uint8_t *)(image->bits + line * image->rowstride); 1067 uint32_t p = FETCH_24 (image, bits, offset); 1068 argb_t argb; 1069 1070 argb.a = 1.0f; 1071 1072 argb.r = to_linear[(p >> 16) & 0xff]; 1073 argb.g = to_linear[(p >> 8) & 0xff]; 1074 argb.b = to_linear[(p >> 0) & 0xff]; 1075 1076 return argb; 1077 } 1078 1079 static uint32_t 1080 fetch_pixel_yuy2 (bits_image_t *image, 1081 int offset, 1082 int line) 1083 { 1084 const uint32_t *bits = image->bits + image->rowstride * line; 1085 1086 int16_t y, u, v; 1087 int32_t r, g, b; 1088 1089 y = ((uint8_t *) bits)[offset << 1] - 16; 1090 u = ((uint8_t *) bits)[((offset << 1) & - 4) + 1] - 128; 1091 v = ((uint8_t *) bits)[((offset << 1) & - 4) + 3] - 128; 1092 1093 /* R = 1.164(Y - 16) + 1.596(V - 128) */ 1094 r = 0x012b27 * y + 0x019a2e * v; 1095 1096 /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */ 1097 g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u; 1098 1099 /* B = 1.164(Y - 16) + 2.018(U - 128) */ 1100 b = 0x012b27 * y + 0x0206a2 * u; 1101 1102 return 0xff000000 | 1103 (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) | 1104 (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) | 1105 (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0); 1106 } 1107 1108 static uint32_t 1109 fetch_pixel_yv12 (bits_image_t *image, 1110 int offset, 1111 int line) 1112 { 1113 YV12_SETUP (image); 1114 int16_t y = YV12_Y (line)[offset] - 16; 1115 int16_t u = YV12_U (line)[offset >> 1] - 128; 1116 int16_t v = YV12_V (line)[offset >> 1] - 128; 1117 int32_t r, g, b; 1118 1119 /* R = 1.164(Y - 16) + 1.596(V - 128) */ 1120 r = 0x012b27 * y + 0x019a2e * v; 1121 1122 /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */ 1123 g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u; 1124 1125 /* B = 1.164(Y - 16) + 2.018(U - 128) */ 1126 b = 0x012b27 * y + 0x0206a2 * u; 1127 1128 return 0xff000000 | 1129 (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) | 1130 (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) | 1131 (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0); 1132 } 1133 1134 /*********************************** Store ************************************/ 1135 1136 #ifndef PIXMAN_FB_ACCESSORS 1137 static void 1138 store_scanline_rgbaf_float (bits_image_t * image, 1139 int x, 1140 int y, 1141 int width, 1142 const uint32_t *v) 1143 { 1144 float *bits = (float *)image->bits + image->rowstride * y + 4 * x; 1145 const argb_t *values = (argb_t *)v; 1146 1147 for (; width; width--, values++) 1148 { 1149 *bits++ = values->r; 1150 *bits++ = values->g; 1151 *bits++ = values->b; 1152 *bits++ = values->a; 1153 } 1154 } 1155 1156 static void 1157 store_scanline_rgbf_float (bits_image_t * image, 1158 int x, 1159 int y, 1160 int width, 1161 const uint32_t *v) 1162 { 1163 float *bits = (float *)image->bits + image->rowstride * y + 3 * x; 1164 const argb_t *values = (argb_t *)v; 1165 1166 for (; width; width--, values++) 1167 { 1168 *bits++ = values->r; 1169 *bits++ = values->g; 1170 *bits++ = values->b; 1171 } 1172 } 1173 #endif 1174 1175 static void 1176 store_scanline_a16b16g16r16_float (bits_image_t * image, 1177 int x, 1178 int y, 1179 int width, 1180 const uint32_t *v) 1181 { 1182 uint64_t *bits = (uint64_t *)(image->bits + image->rowstride * y); 1183 uint64_t *pixel = bits + x; 1184 argb_t *values = (argb_t *)v; 1185 int i; 1186 1187 for (i = 0; i < width; ++i) 1188 { 1189 uint64_t a, r, g, b; 1190 1191 a = pixman_float_to_unorm (values[i].a, 16); 1192 r = pixman_float_to_unorm (values[i].r, 16); 1193 g = pixman_float_to_unorm (values[i].g, 16); 1194 b = pixman_float_to_unorm (values[i].b, 16); 1195 1196 WRITE (image, pixel++, 1197 (a << 48) | (b << 32) | (g << 16) | (r << 0)); 1198 } 1199 } 1200 1201 static void 1202 store_scanline_a2r10g10b10_float (bits_image_t * image, 1203 int x, 1204 int y, 1205 int width, 1206 const uint32_t *v) 1207 { 1208 uint32_t *bits = image->bits + image->rowstride * y; 1209 uint32_t *pixel = bits + x; 1210 argb_t *values = (argb_t *)v; 1211 int i; 1212 1213 for (i = 0; i < width; ++i) 1214 { 1215 uint32_t a, r, g, b; 1216 1217 a = pixman_float_to_unorm (values[i].a, 2); 1218 r = pixman_float_to_unorm (values[i].r, 10); 1219 g = pixman_float_to_unorm (values[i].g, 10); 1220 b = pixman_float_to_unorm (values[i].b, 10); 1221 1222 WRITE (image, pixel++, 1223 (a << 30) | (r << 20) | (g << 10) | b); 1224 } 1225 } 1226 1227 static void 1228 store_scanline_x2r10g10b10_float (bits_image_t * image, 1229 int x, 1230 int y, 1231 int width, 1232 const uint32_t *v) 1233 { 1234 uint32_t *bits = image->bits + image->rowstride * y; 1235 uint32_t *pixel = bits + x; 1236 argb_t *values = (argb_t *)v; 1237 int i; 1238 1239 for (i = 0; i < width; ++i) 1240 { 1241 uint32_t r, g, b; 1242 1243 r = pixman_float_to_unorm (values[i].r, 10); 1244 g = pixman_float_to_unorm (values[i].g, 10); 1245 b = pixman_float_to_unorm (values[i].b, 10); 1246 1247 WRITE (image, pixel++, 1248 (r << 20) | (g << 10) | b); 1249 } 1250 } 1251 1252 static void 1253 store_scanline_a2b10g10r10_float (bits_image_t * image, 1254 int x, 1255 int y, 1256 int width, 1257 const uint32_t *v) 1258 { 1259 uint32_t *bits = image->bits + image->rowstride * y; 1260 uint32_t *pixel = bits + x; 1261 argb_t *values = (argb_t *)v; 1262 int i; 1263 1264 for (i = 0; i < width; ++i) 1265 { 1266 uint32_t a, r, g, b; 1267 1268 a = pixman_float_to_unorm (values[i].a, 2); 1269 r = pixman_float_to_unorm (values[i].r, 10); 1270 g = pixman_float_to_unorm (values[i].g, 10); 1271 b = pixman_float_to_unorm (values[i].b, 10); 1272 1273 WRITE (image, pixel++, 1274 (a << 30) | (b << 20) | (g << 10) | r); 1275 } 1276 } 1277 1278 static void 1279 store_scanline_x2b10g10r10_float (bits_image_t * image, 1280 int x, 1281 int y, 1282 int width, 1283 const uint32_t *v) 1284 { 1285 uint32_t *bits = image->bits + image->rowstride * y; 1286 uint32_t *pixel = bits + x; 1287 argb_t *values = (argb_t *)v; 1288 int i; 1289 1290 for (i = 0; i < width; ++i) 1291 { 1292 uint32_t r, g, b; 1293 1294 r = pixman_float_to_unorm (values[i].r, 10); 1295 g = pixman_float_to_unorm (values[i].g, 10); 1296 b = pixman_float_to_unorm (values[i].b, 10); 1297 1298 WRITE (image, pixel++, 1299 (b << 20) | (g << 10) | r); 1300 } 1301 } 1302 1303 static void 1304 store_scanline_a8r8g8b8_sRGB_float (bits_image_t * image, 1305 int x, 1306 int y, 1307 int width, 1308 const uint32_t *v) 1309 { 1310 uint32_t *bits = image->bits + image->rowstride * y; 1311 uint32_t *pixel = bits + x; 1312 argb_t *values = (argb_t *)v; 1313 int i; 1314 1315 for (i = 0; i < width; ++i) 1316 { 1317 uint32_t a, r, g, b; 1318 1319 a = pixman_float_to_unorm (values[i].a, 8); 1320 r = to_srgb (values[i].r); 1321 g = to_srgb (values[i].g); 1322 b = to_srgb (values[i].b); 1323 1324 WRITE (image, pixel++, 1325 (a << 24) | (r << 16) | (g << 8) | b); 1326 } 1327 } 1328 1329 static void 1330 store_scanline_r8g8b8_sRGB_float (bits_image_t * image, 1331 int x, 1332 int y, 1333 int width, 1334 const uint32_t *v) 1335 { 1336 uint8_t *bits = (uint8_t *)(image->bits + image->rowstride * y) + 3 * x; 1337 argb_t *values = (argb_t *)v; 1338 int i; 1339 1340 for (i = 0; i < width; ++i) 1341 { 1342 uint32_t r, g, b, rgb; 1343 1344 r = to_srgb (values[i].r); 1345 g = to_srgb (values[i].g); 1346 b = to_srgb (values[i].b); 1347 1348 rgb = (r << 16) | (g << 8) | b; 1349 1350 STORE_24 (image, bits, i, rgb); 1351 } 1352 } 1353 1354 /* 1355 * Contracts a floating point image to 32bpp and then stores it using a 1356 * regular 32-bit store proc. Despite the type, this function expects an 1357 * argb_t buffer. 1358 */ 1359 static void 1360 store_scanline_generic_float (bits_image_t * image, 1361 int x, 1362 int y, 1363 int width, 1364 const uint32_t *values) 1365 { 1366 uint32_t *argb8_pixels; 1367 1368 assert (image->common.type == BITS); 1369 1370 argb8_pixels = pixman_malloc_ab (width, sizeof(uint32_t)); 1371 if (!argb8_pixels) 1372 return; 1373 1374 /* Contract the scanline. We could do this in place if values weren't 1375 * const. 1376 */ 1377 pixman_contract_from_float (argb8_pixels, (argb_t *)values, width); 1378 1379 image->store_scanline_32 (image, x, y, width, argb8_pixels); 1380 1381 free (argb8_pixels); 1382 } 1383 1384 static void 1385 fetch_scanline_generic_float (bits_image_t * image, 1386 int x, 1387 int y, 1388 int width, 1389 uint32_t * buffer, 1390 const uint32_t *mask) 1391 { 1392 image->fetch_scanline_32 (image, x, y, width, buffer, NULL); 1393 1394 pixman_expand_to_float ((argb_t *)buffer, buffer, image->format, width); 1395 } 1396 1397 /* The 32_sRGB paths should be deleted after narrow processing 1398 * is no longer invoked for formats that are considered wide. 1399 * (Also see fetch_pixel_generic_lossy_32) */ 1400 static void 1401 fetch_scanline_a8r8g8b8_32_sRGB (bits_image_t *image, 1402 int x, 1403 int y, 1404 int width, 1405 uint32_t *buffer, 1406 const uint32_t *mask) 1407 { 1408 const uint32_t *bits = image->bits + y * image->rowstride; 1409 const uint32_t *pixel = (uint32_t *)bits + x; 1410 const uint32_t *end = pixel + width; 1411 uint32_t tmp; 1412 1413 while (pixel < end) 1414 { 1415 uint32_t a, r, g, b; 1416 1417 tmp = READ (image, pixel++); 1418 1419 a = (tmp >> 24) & 0xff; 1420 r = (tmp >> 16) & 0xff; 1421 g = (tmp >> 8) & 0xff; 1422 b = (tmp >> 0) & 0xff; 1423 1424 r = to_linear[r] * 255.0f + 0.5f; 1425 g = to_linear[g] * 255.0f + 0.5f; 1426 b = to_linear[b] * 255.0f + 0.5f; 1427 1428 *buffer++ = (a << 24) | (r << 16) | (g << 8) | (b << 0); 1429 } 1430 } 1431 1432 static void 1433 fetch_scanline_r8g8b8_32_sRGB (bits_image_t *image, 1434 int x, 1435 int y, 1436 int width, 1437 uint32_t *buffer, 1438 const uint32_t *mask) 1439 { 1440 const uint8_t *bits = (uint8_t *)(image->bits + y * image->rowstride) + 3 * x; 1441 uint32_t tmp; 1442 int i; 1443 1444 for (i = 0; i < width; ++i) 1445 { 1446 uint32_t a, r, g, b; 1447 1448 tmp = FETCH_24 (image, bits, i); 1449 1450 a = 0xff; 1451 r = (tmp >> 16) & 0xff; 1452 g = (tmp >> 8) & 0xff; 1453 b = (tmp >> 0) & 0xff; 1454 1455 r = to_linear[r] * 255.0f + 0.5f; 1456 g = to_linear[g] * 255.0f + 0.5f; 1457 b = to_linear[b] * 255.0f + 0.5f; 1458 1459 *buffer++ = (a << 24) | (r << 16) | (g << 8) | (b << 0); 1460 } 1461 } 1462 1463 static uint32_t 1464 fetch_pixel_a8r8g8b8_32_sRGB (bits_image_t *image, 1465 int offset, 1466 int line) 1467 { 1468 uint32_t *bits = image->bits + line * image->rowstride; 1469 uint32_t tmp = READ (image, bits + offset); 1470 uint32_t a, r, g, b; 1471 1472 a = (tmp >> 24) & 0xff; 1473 r = (tmp >> 16) & 0xff; 1474 g = (tmp >> 8) & 0xff; 1475 b = (tmp >> 0) & 0xff; 1476 1477 r = to_linear[r] * 255.0f + 0.5f; 1478 g = to_linear[g] * 255.0f + 0.5f; 1479 b = to_linear[b] * 255.0f + 0.5f; 1480 1481 return (a << 24) | (r << 16) | (g << 8) | (b << 0); 1482 } 1483 1484 static uint32_t 1485 fetch_pixel_r8g8b8_32_sRGB (bits_image_t *image, 1486 int offset, 1487 int line) 1488 { 1489 uint8_t *bits = (uint8_t *)(image->bits + line * image->rowstride); 1490 uint32_t tmp = FETCH_24 (image, bits, offset); 1491 uint32_t a, r, g, b; 1492 1493 a = 0xff; 1494 r = (tmp >> 16) & 0xff; 1495 g = (tmp >> 8) & 0xff; 1496 b = (tmp >> 0) & 0xff; 1497 1498 r = to_linear[r] * 255.0f + 0.5f; 1499 g = to_linear[g] * 255.0f + 0.5f; 1500 b = to_linear[b] * 255.0f + 0.5f; 1501 1502 return (a << 24) | (r << 16) | (g << 8) | (b << 0); 1503 } 1504 1505 static void 1506 store_scanline_a8r8g8b8_32_sRGB (bits_image_t *image, 1507 int x, 1508 int y, 1509 int width, 1510 const uint32_t *v) 1511 { 1512 uint32_t *bits = image->bits + image->rowstride * y; 1513 uint64_t *values = (uint64_t *)v; 1514 uint32_t *pixel = bits + x; 1515 uint64_t tmp; 1516 int i; 1517 1518 for (i = 0; i < width; ++i) 1519 { 1520 uint32_t a, r, g, b; 1521 1522 tmp = values[i]; 1523 1524 a = (tmp >> 24) & 0xff; 1525 r = (tmp >> 16) & 0xff; 1526 g = (tmp >> 8) & 0xff; 1527 b = (tmp >> 0) & 0xff; 1528 1529 r = to_srgb (r * (1/255.0f)); 1530 g = to_srgb (g * (1/255.0f)); 1531 b = to_srgb (b * (1/255.0f)); 1532 1533 WRITE (image, pixel++, a | (r << 16) | (g << 8) | (b << 0)); 1534 } 1535 } 1536 1537 static void 1538 store_scanline_r8g8b8_32_sRGB (bits_image_t *image, 1539 int x, 1540 int y, 1541 int width, 1542 const uint32_t *v) 1543 { 1544 uint8_t *bits = (uint8_t *)(image->bits + image->rowstride * y) + 3 * x; 1545 uint64_t *values = (uint64_t *)v; 1546 uint64_t tmp; 1547 int i; 1548 1549 for (i = 0; i < width; ++i) 1550 { 1551 uint32_t r, g, b; 1552 1553 tmp = values[i]; 1554 1555 r = (tmp >> 16) & 0xff; 1556 g = (tmp >> 8) & 0xff; 1557 b = (tmp >> 0) & 0xff; 1558 1559 r = to_srgb (r * (1/255.0f)); 1560 g = to_srgb (g * (1/255.0f)); 1561 b = to_srgb (b * (1/255.0f)); 1562 1563 STORE_24 (image, bits, i, (r << 16) | (g << 8) | (b << 0)); 1564 } 1565 } 1566 1567 static argb_t 1568 fetch_pixel_generic_float (bits_image_t *image, 1569 int offset, 1570 int line) 1571 { 1572 uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line); 1573 argb_t f; 1574 1575 pixman_expand_to_float (&f, &pixel32, image->format, 1); 1576 1577 return f; 1578 } 1579 1580 /* 1581 * XXX: The transformed fetch path only works at 32-bpp so far. When all 1582 * paths have wide versions, this can be removed. 1583 * 1584 * WARNING: This function loses precision! 1585 */ 1586 static uint32_t 1587 fetch_pixel_generic_lossy_32 (bits_image_t *image, 1588 int offset, 1589 int line) 1590 { 1591 argb_t pixel64 = image->fetch_pixel_float (image, offset, line); 1592 uint32_t result; 1593 1594 pixman_contract_from_float (&result, &pixel64, 1); 1595 1596 return result; 1597 } 1598 1599 typedef struct 1600 { 1601 pixman_format_code_t format; 1602 fetch_scanline_t fetch_scanline_32; 1603 fetch_scanline_t fetch_scanline_float; 1604 fetch_pixel_32_t fetch_pixel_32; 1605 fetch_pixel_float_t fetch_pixel_float; 1606 store_scanline_t store_scanline_32; 1607 store_scanline_t store_scanline_float; 1608 } format_info_t; 1609 1610 #define FORMAT_INFO(format) \ 1611 { \ 1612 PIXMAN_ ## format, \ 1613 fetch_scanline_ ## format, \ 1614 fetch_scanline_generic_float, \ 1615 fetch_pixel_ ## format, \ 1616 fetch_pixel_generic_float, \ 1617 store_scanline_ ## format, \ 1618 store_scanline_generic_float \ 1619 } 1620 1621 static const format_info_t accessors[] = 1622 { 1623 /* 32 bpp formats */ 1624 FORMAT_INFO (a8r8g8b8), 1625 FORMAT_INFO (x8r8g8b8), 1626 FORMAT_INFO (a8b8g8r8), 1627 FORMAT_INFO (x8b8g8r8), 1628 FORMAT_INFO (b8g8r8a8), 1629 FORMAT_INFO (b8g8r8x8), 1630 FORMAT_INFO (r8g8b8a8), 1631 FORMAT_INFO (r8g8b8x8), 1632 FORMAT_INFO (x14r6g6b6), 1633 1634 /* sRGB formats */ 1635 { PIXMAN_a8r8g8b8_sRGB, 1636 fetch_scanline_a8r8g8b8_32_sRGB, fetch_scanline_a8r8g8b8_sRGB_float, 1637 fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_sRGB_float, 1638 store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_sRGB_float, 1639 }, 1640 { PIXMAN_r8g8b8_sRGB, 1641 fetch_scanline_r8g8b8_32_sRGB, fetch_scanline_r8g8b8_sRGB_float, 1642 fetch_pixel_r8g8b8_32_sRGB, fetch_pixel_r8g8b8_sRGB_float, 1643 store_scanline_r8g8b8_32_sRGB, store_scanline_r8g8b8_sRGB_float, 1644 }, 1645 1646 /* 24bpp formats */ 1647 FORMAT_INFO (r8g8b8), 1648 FORMAT_INFO (b8g8r8), 1649 1650 /* 16bpp formats */ 1651 FORMAT_INFO (r5g6b5), 1652 FORMAT_INFO (b5g6r5), 1653 1654 FORMAT_INFO (a1r5g5b5), 1655 FORMAT_INFO (x1r5g5b5), 1656 FORMAT_INFO (a1b5g5r5), 1657 FORMAT_INFO (x1b5g5r5), 1658 FORMAT_INFO (a4r4g4b4), 1659 FORMAT_INFO (x4r4g4b4), 1660 FORMAT_INFO (a4b4g4r4), 1661 FORMAT_INFO (x4b4g4r4), 1662 1663 /* 8bpp formats */ 1664 FORMAT_INFO (a8), 1665 FORMAT_INFO (r3g3b2), 1666 FORMAT_INFO (b2g3r3), 1667 FORMAT_INFO (a2r2g2b2), 1668 FORMAT_INFO (a2b2g2r2), 1669 1670 FORMAT_INFO (c8), 1671 1672 FORMAT_INFO (g8), 1673 1674 #define fetch_scanline_x4c4 fetch_scanline_c8 1675 #define fetch_pixel_x4c4 fetch_pixel_c8 1676 #define store_scanline_x4c4 store_scanline_c8 1677 FORMAT_INFO (x4c4), 1678 1679 #define fetch_scanline_x4g4 fetch_scanline_g8 1680 #define fetch_pixel_x4g4 fetch_pixel_g8 1681 #define store_scanline_x4g4 store_scanline_g8 1682 FORMAT_INFO (x4g4), 1683 1684 FORMAT_INFO (x4a4), 1685 1686 /* 4bpp formats */ 1687 FORMAT_INFO (a4), 1688 FORMAT_INFO (r1g2b1), 1689 FORMAT_INFO (b1g2r1), 1690 FORMAT_INFO (a1r1g1b1), 1691 FORMAT_INFO (a1b1g1r1), 1692 1693 FORMAT_INFO (c4), 1694 1695 FORMAT_INFO (g4), 1696 1697 /* 1bpp formats */ 1698 FORMAT_INFO (a1), 1699 FORMAT_INFO (g1), 1700 1701 /* Wide formats */ 1702 #ifndef PIXMAN_FB_ACCESSORS 1703 { PIXMAN_rgba_float, 1704 NULL, fetch_scanline_rgbaf_float, 1705 fetch_pixel_generic_lossy_32, fetch_pixel_rgbaf_float, 1706 NULL, store_scanline_rgbaf_float }, 1707 1708 { PIXMAN_rgb_float, 1709 NULL, fetch_scanline_rgbf_float, 1710 fetch_pixel_generic_lossy_32, fetch_pixel_rgbf_float, 1711 NULL, store_scanline_rgbf_float }, 1712 #endif 1713 { PIXMAN_a16b16g16r16, 1714 NULL, fetch_scanline_a16b16g16r16_float, 1715 fetch_pixel_generic_lossy_32, fetch_pixel_a16b16g16r16_float, 1716 NULL, store_scanline_a16b16g16r16_float }, 1717 1718 { PIXMAN_a2r10g10b10, 1719 NULL, fetch_scanline_a2r10g10b10_float, 1720 fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10_float, 1721 NULL, store_scanline_a2r10g10b10_float }, 1722 1723 { PIXMAN_x2r10g10b10, 1724 NULL, fetch_scanline_x2r10g10b10_float, 1725 fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10_float, 1726 NULL, store_scanline_x2r10g10b10_float }, 1727 1728 { PIXMAN_a2b10g10r10, 1729 NULL, fetch_scanline_a2b10g10r10_float, 1730 fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10_float, 1731 NULL, store_scanline_a2b10g10r10_float }, 1732 1733 { PIXMAN_x2b10g10r10, 1734 NULL, fetch_scanline_x2b10g10r10_float, 1735 fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10_float, 1736 NULL, store_scanline_x2b10g10r10_float }, 1737 1738 /* YUV formats */ 1739 { PIXMAN_yuy2, 1740 fetch_scanline_yuy2, fetch_scanline_generic_float, 1741 fetch_pixel_yuy2, fetch_pixel_generic_float, 1742 NULL, NULL }, 1743 1744 { PIXMAN_yv12, 1745 fetch_scanline_yv12, fetch_scanline_generic_float, 1746 fetch_pixel_yv12, fetch_pixel_generic_float, 1747 NULL, NULL }, 1748 1749 { PIXMAN_null }, 1750 }; 1751 1752 static void 1753 setup_accessors (bits_image_t *image) 1754 { 1755 const format_info_t *info = accessors; 1756 1757 while (info->format != PIXMAN_null) 1758 { 1759 if (info->format == image->format) 1760 { 1761 image->fetch_scanline_32 = info->fetch_scanline_32; 1762 image->fetch_scanline_float = info->fetch_scanline_float; 1763 image->fetch_pixel_32 = info->fetch_pixel_32; 1764 image->fetch_pixel_float = info->fetch_pixel_float; 1765 image->store_scanline_32 = info->store_scanline_32; 1766 image->store_scanline_float = info->store_scanline_float; 1767 1768 return; 1769 } 1770 1771 info++; 1772 } 1773 } 1774 1775 #ifndef PIXMAN_FB_ACCESSORS 1776 void 1777 _pixman_bits_image_setup_accessors_accessors (bits_image_t *image); 1778 1779 void 1780 _pixman_bits_image_setup_accessors (bits_image_t *image) 1781 { 1782 if (image->read_func || image->write_func) 1783 _pixman_bits_image_setup_accessors_accessors (image); 1784 else 1785 setup_accessors (image); 1786 } 1787 1788 #else 1789 1790 void 1791 _pixman_bits_image_setup_accessors_accessors (bits_image_t *image) 1792 { 1793 setup_accessors (image); 1794 } 1795 1796 #endif