1/* 2 * Copyright (c) 1995-2002 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23/* 24** Write quadword fill pattern helper macros 25*/ 26#if __BIG_ENDIAN__ 27#define WRITEBYTE(c0,c1,d,n) do { \ 28 uint32_t c = c0; STOREINC(d, c0 >> 24, UInt8); n -= 1; \ 29 c0 = ((c0 << 8) & 0xFFFFFF00) | ((c1 >> 24) & 0x000000FF); \ 30 c1 = ((c1 << 8) & 0xFFFFFF00) | ((c >> 24) & 0x000000FF); \ 31} while(0) 32#define WRITESHORT(c0,c1,d,n) do { \ 33 uint32_t c = c0; STOREINC(d, c0 >> 16, UInt16); n -= 2; \ 34 c0 = ((c0 << 16) & 0xFFFF0000) | ((c1 >> 16) & 0x0000FFFF); \ 35 c1 = ((c1 << 16) & 0xFFFF0000) | ((c >> 16) & 0x0000FFFF); \ 36} while(0) 37#else 38#define WRITEBYTE(c0,c1,d,n) do { \ 39 uint32_t c = c0; STOREINC(d, c0 & 0xFF, UInt8); n -= 1; \ 40 c0 = ((c0 >> 8) & 0x00FFFFFF) | ((c1 << 24) & 0xFF000000); \ 41 c1 = ((c1 >> 8) & 0x00FFFFFF) | ((c << 24) & 0xFF000000); \ 42} while(0) 43#define WRITESHORT(c0,c1,d,n) do { \ 44 uint32_t c = c0; STOREINC(d, c0 & 0xFFFF, UInt16); n -= 2; \ 45 c0 = ((c0 >> 16) & 0x0000FFFF) | ((c1 << 16) & 0xFFFF0000); \ 46 c1 = ((c1 >> 16) & 0x0000FFFF) | ((c << 16) & 0xFFFF0000); \ 47} while(0) 48#endif 49#define WRITEWORD(c0,c1,d,n) do { \ 50 uint32_t c = c0; STOREINC(d, c0, UInt32); n -= 4; c0 = c1; c1 = c; \ 51} while(0) 52 53static void FillVRAM8by1(int w, int h, uint32_t k0,uint32_t k1, uint8_t *dst, int dbpr) 54{ 55 uint8_t *d; 56 uint32_t c0,c1, n,v, i; 57 58 if(w<=0 || h<=0) 59 return; 60 61 while(h > 0) 62 { 63 n = w; 64 d = dst; 65 dst = dst + dbpr; 66 h = h - 1; 67 68 c0 = k0; 69 c1 = k1; 70 71 if((uintptr_t)d & 0x0001) 72 WRITEBYTE(c0, c1, d, n); 73 74 if(((uintptr_t)d & 0x0002) && n>=2) 75 WRITESHORT(c0, c1, d, n); 76 77 if(((uintptr_t)d & 0x0004) && n>=4) 78 WRITEWORD(c0, c1, d, n); 79 80 if(n >= 16) 81 { 82#if __BIG_ENDIAN__ 83 double kd, km[1]; 84 85 ((uint32_t *)km)[0] = c0; 86 ((uint32_t *)km)[1] = c1; 87 v = n >> 3; 88 n = n & 0x07; 89 kd = km[0]; 90 91 for(i=0 ; i<v ; i++) 92 STOREINC(d, kd, double) 93#else 94 v = n >> 3; 95 n = n & 0x07; 96 for(i=0 ; i<v ; i++) 97 { 98 STOREINC(d, c0, uint32_t); 99 STOREINC(d, c1, uint32_t); 100 } 101#endif 102 } 103 else if(n >= 8) 104 { 105 STOREINC(d, c0, uint32_t); 106 n = n - 8; 107 STOREINC(d, c1, uint32_t); 108 } 109 110 if(n & 0x04) 111 WRITEWORD(c0, c1, d, n); 112 113 if(n & 0x02) 114 WRITESHORT(c0, c1, d, n); 115 116 if(n & 0x01) 117 WRITEBYTE(c0, c1, d, n); 118 } 119} 120 121static void DecompressRLE32(uint8_t *srcbase, uint8_t *dstbase, int minx, int maxx) 122{ 123 uint32_t *src, *dst; 124 int cnt, code, n,s,x; 125 126 src = (uint32_t *)srcbase; 127 dst = (uint32_t *)dstbase; 128 129 for(x=0 ; x<maxx ;) 130 { 131 code = src[0]; 132 cnt = (code & 0x00FFFFFF); 133 code = (code & 0xFF000000) >> 24; 134 135 if(code == 0x80) 136 { 137 if(x+cnt > minx) 138 { 139 n = (maxx-x < cnt) ? (maxx-x) : cnt; 140 s = (minx-x > 0) ? (minx-x) : 0; 141 n = n - s; 142 143 FillVRAM8by1(4*n, 1, src[1],src[1], (UInt8 *) dst, 0); 144 dst = dst + n; 145 } 146 147 x = x + cnt; 148 src = src + 2; 149 } 150 151 else 152 { 153 if(x+cnt > minx) 154 { 155 n = (maxx-x < cnt) ? (maxx-x) : cnt; 156 s = (minx-x > 0) ? (minx-x) : 0; 157 n = n - s; 158 159 bcopy_nc((void*)(src+s+1), (void*)dst, 4*n); 160 dst = dst + n; 161 } 162 163 x = x + cnt; 164 src = src + cnt + 1; 165 } 166 } 167} 168 169static void DecompressRLE16(uint8_t *srcbase, uint8_t *dstbase, int minx, int maxx) 170{ 171 typedef u_int16_t Pixel_Type; 172 typedef u_int32_t CodeWord_Type; 173 Pixel_Type *src, *dst; 174 CodeWord_Type *codePtr; 175 int cnt, code, n,s,c, x; 176 177 src = (Pixel_Type *)srcbase; 178 dst = (Pixel_Type *)dstbase; 179 180 for(x=0 ; x<maxx ;) 181 { 182 codePtr = (CodeWord_Type*) src; 183 code = codePtr[0]; 184 src = (Pixel_Type*) &codePtr[1]; 185 cnt = (code & 0x00FFFFFF); 186 code = (code & 0xFF000000) >> 24; 187 188 if(code == 0x80) 189 { 190 if(x+cnt > minx) 191 { 192 n = (maxx-x < cnt) ? (maxx-x) : cnt; 193 s = (minx-x > 0) ? (minx-x) : 0; 194 n = n - s; 195 196 c = src[0]; 197 c |= c << 16; //Note: line not depth independent 198 FillVRAM8by1(sizeof( Pixel_Type)*n,1, c,c, (UInt8 *)dst,0); 199 dst = dst + n; 200 } 201 202 x = x + cnt; 203 src = src + 1; 204 } 205 206 else 207 { 208 if(x+cnt > minx) 209 { 210 n = (maxx-x < cnt) ? (maxx-x) : cnt; 211 s = (minx-x > 0) ? (minx-x) : 0; 212 n = n - s; 213 214 bcopy_nc((void*)(src+s), (void*)dst, sizeof(Pixel_Type)*n); 215 dst = dst + n; 216 } 217 218 x = x + cnt; 219 src = src + cnt; 220 } 221 } 222} 223 224static void DecompressRLE8(uint8_t *srcbase, uint8_t *dstbase, int minx, int maxx) 225{ 226 typedef u_int8_t Pixel_Type; 227 typedef u_int32_t CodeWord_Type; 228 Pixel_Type *src, *dst; 229 CodeWord_Type *codePtr; 230 int cnt, code, n,s,c, x; 231 232 src = (Pixel_Type *)srcbase; 233 dst = (Pixel_Type *)dstbase; 234 235 for(x=0 ; x<maxx ;) 236 { 237 codePtr = (CodeWord_Type*) src; 238 code = codePtr[0]; 239 src = (Pixel_Type*) &codePtr[1]; 240 cnt = (code & 0x00FFFFFF); 241 code = (code & 0xFF000000) >> 24; 242 243 if(code == 0x80) 244 { 245 if(x+cnt > minx) 246 { 247 n = (maxx-x < cnt) ? (maxx-x) : cnt; 248 s = (minx-x > 0) ? (minx-x) : 0; 249 n = n - s; 250 251 c = src[0]; 252 c |= c << 8; //Note: line not depth independent 253 c |= c << 16; //Note: line not depth independent 254 FillVRAM8by1(sizeof( Pixel_Type)*n,1, c,c, (UInt8 *)dst,0); 255 dst = dst + n; 256 } 257 258 x = x + cnt; 259 src = src + 1; 260 } 261 262 else 263 { 264 if(x+cnt > minx) 265 { 266 n = (maxx-x < cnt) ? (maxx-x) : cnt; 267 s = (minx-x > 0) ? (minx-x) : 0; 268 n = n - s; 269 270 bcopy_nc((void*)(src+s), (void*)dst, sizeof(Pixel_Type)*n); 271 dst = dst + n; 272 } 273 274 x = x + cnt; 275 src = src + cnt; 276 } 277 } 278} 279 280 281static inline int compress_line_32(UInt8 *srcbase, int width, UInt8 *dstbase) 282{ 283 uint32_t *src, *dst; 284 uint32_t *start, *end; 285 uint32_t c0,c1; 286 int cpyCnt, rplCnt, wrtCnt; 287 288 wrtCnt = 0; 289 src = (uint32_t *)srcbase; 290 dst = (uint32_t *)dstbase; 291 end = src + width; 292 293 while(src<end) 294 { 295 cpyCnt = 0; 296 rplCnt = 1; 297 start = src; 298 c0 = src[0]; 299 300 for(src++ ; src<end ; src++) 301 { 302 c1 = src[0]; 303 304 if(c1 != c0) 305 { 306 if(rplCnt >= 4) break; 307 308 cpyCnt = cpyCnt + rplCnt; 309 rplCnt = 1; 310 c0 = c1; 311 } 312 313 else 314 rplCnt++; 315 } 316 317 if(rplCnt < 4) 318 { 319 cpyCnt = cpyCnt + rplCnt; 320 rplCnt = 0; 321 } 322 323 if(cpyCnt > 0) 324 { 325 dst[0] = cpyCnt; 326 bcopy_nc(start, &dst[1], 4*cpyCnt); 327 328 wrtCnt = wrtCnt + cpyCnt + 1; 329 dst = dst + cpyCnt + 1; 330 } 331 332 if(rplCnt > 0) 333 { 334 dst[0] = 0x80000000 | rplCnt; 335 dst[1] = c0; 336 337 wrtCnt = wrtCnt + 2; 338 dst = dst + 2; 339 } 340 } 341 342 return 4*wrtCnt; 343} 344 345static inline int compress_line_16(uint8_t *srcbase, int width, uint8_t *dstbase) 346{ 347 typedef u_int16_t Pixel_Type; 348 typedef u_int32_t CodeWord_Type; 349 Pixel_Type *src, *dst; 350 Pixel_Type *start, *end; 351 Pixel_Type c0,c1; 352 int cpyCnt, rplCnt, wrtCnt; 353 const int kMinRunLength = ( 2 * sizeof(CodeWord_Type) + 2 * sizeof 354( Pixel_Type ) ) / sizeof( Pixel_Type ); 355 356 wrtCnt = 0; 357 src = (Pixel_Type *)srcbase; 358 dst = (Pixel_Type *)dstbase; 359 end = src + width; 360 361 while(src < end) 362 { 363 cpyCnt = 0; 364 rplCnt = 1; 365 start = src; 366 c0 = src[0]; 367 368 for(src++ ; src < end ; src++) 369 { 370 c1 = src[0]; 371 372 if(c1 != c0) 373 { 374 if(rplCnt >= kMinRunLength) break; 375 376 cpyCnt = cpyCnt + rplCnt; 377 rplCnt = 1; 378 c0 = c1; 379 } 380 else 381 rplCnt++; 382 } 383 384 if(rplCnt < kMinRunLength ) 385 { 386 cpyCnt = cpyCnt + rplCnt; 387 rplCnt = 0; 388 } 389 390 if(cpyCnt > 0) 391 { 392 CodeWord_Type *codeWord = (CodeWord_Type*) dst; 393 codeWord[0] = cpyCnt; 394 dst = (Pixel_Type*) (codeWord + 1); 395 bcopy_nc(start, dst, sizeof( Pixel_Type )*cpyCnt); 396 397 wrtCnt = wrtCnt + cpyCnt + sizeof(CodeWord_Type) / sizeof 398( Pixel_Type ); 399 dst = dst + cpyCnt; 400 } 401 402 if(rplCnt > 0) 403 { 404 CodeWord_Type *codeWord = (CodeWord_Type*) dst; 405 codeWord[0] = 0x80000000UL | rplCnt; 406 dst = (Pixel_Type*) (codeWord + 1); 407 dst[0] = c0; 408 409 wrtCnt = wrtCnt + 1 + sizeof(CodeWord_Type) / sizeof 410( Pixel_Type ); 411 dst = dst + 1; 412 } 413 } 414 415 return sizeof( Pixel_Type )*wrtCnt; 416} 417 418static inline int compress_line_8(uint8_t *srcbase, int width, uint8_t *dstbase) 419{ 420 typedef u_int8_t Pixel_Type; 421 typedef u_int32_t CodeWord_Type; 422 Pixel_Type *src, *dst; 423 Pixel_Type *start, *end; 424 Pixel_Type c0,c1; 425 int cpyCnt, rplCnt, wrtCnt; 426 const int kMinRunLength = ( 2 * sizeof(CodeWord_Type) + 2 * sizeof 427( Pixel_Type ) ) / sizeof( Pixel_Type ); 428 429 wrtCnt = 0; 430 src = (Pixel_Type *)srcbase; 431 dst = (Pixel_Type *)dstbase; 432 end = src + width; 433 434 while(src < end) 435 { 436 cpyCnt = 0; 437 rplCnt = 1; 438 start = src; 439 c0 = src[0]; 440 441 for(src++ ; src < end ; src++) 442 { 443 c1 = src[0]; 444 445 if(c1 != c0) 446 { 447 if(rplCnt >= kMinRunLength) break; 448 449 cpyCnt = cpyCnt + rplCnt; 450 rplCnt = 1; 451 c0 = c1; 452 } 453 else 454 rplCnt++; 455 } 456 457 if(rplCnt < kMinRunLength ) 458 { 459 cpyCnt = cpyCnt + rplCnt; 460 rplCnt = 0; 461 } 462 463 if(cpyCnt > 0) 464 { 465 CodeWord_Type *codeWord = (CodeWord_Type*) dst; 466 codeWord[0] = cpyCnt; 467 dst = (Pixel_Type*) (codeWord + 1); 468 bcopy_nc(start, dst, sizeof( Pixel_Type )*cpyCnt); 469 470 wrtCnt = wrtCnt + cpyCnt + sizeof(CodeWord_Type) / sizeof 471( Pixel_Type ); 472 dst = dst + cpyCnt; 473 } 474 475 if(rplCnt > 0) 476 { 477 CodeWord_Type *codeWord = (CodeWord_Type*) dst; 478 codeWord[0] = 0x80000000UL | rplCnt; 479 dst = (Pixel_Type*) (codeWord + 1); 480 dst[0] = c0; 481 482 wrtCnt = wrtCnt + 1 + sizeof(CodeWord_Type) / sizeof 483( Pixel_Type ); 484 dst = dst + 1; 485 } 486 } 487 488 return sizeof( Pixel_Type )*wrtCnt; 489} 490 491static int CompressData(uint8_t *srcbase[], uint32_t imageCount, 492 uint32_t depth, uint32_t width, uint32_t height, 493 uint32_t rowbytes, uint8_t *dstbase, uint32_t dlen, 494 uint32_t gammaChannelCount, uint32_t gammaDataCount, 495 uint32_t gammaDataWidth, uint8_t * gammaData) 496{ 497 hibernate_preview_t * hdr; 498 uint32_t * dst; 499 uint32_t * cScan,*pScan; 500 UInt8 * lineBuffer; 501 int32_t cSize, pSize; 502 uint32_t image, y, lineLen; 503 504 if (dlen <= sizeof(hibernate_preview_t) + imageCount*height*sizeof(uint32_t)) 505 { 506 DEBG("", "compressData: destination buffer size %d too small for y index (%ld)\n", 507 dlen, (imageCount+height)*sizeof(uint32_t)); 508 return 0; 509 } 510 511 hdr = (typeof(hdr)) dstbase; 512 dst = (typeof(dst)) (hdr + 1); 513 514 lineLen = width * depth; 515 dlen -= lineLen; 516 517 bzero(hdr, sizeof(*hdr)); 518#if !IOHIB_PREVIEW_V0 519 hdr->imageCount = imageCount; 520#endif 521 hdr->depth = depth; 522 hdr->width = width; 523 hdr->height = height; 524 525 uint8_t * gammaOut = (uint8_t *) &dst[imageCount * height]; 526 uint32_t idx, idxIn, channel; 527 for (channel = 0; channel < 3; channel++) 528 { 529 for (idx = 0; idx < 256; idx++) 530 { 531 if (!gammaData) 532 { 533 *gammaOut++ = idx; 534 continue; 535 } 536 idxIn = (idx * (gammaDataCount - 1)) / 255; 537 if (gammaDataWidth <= 8) 538 *gammaOut++ = gammaData[idxIn] << (8 - gammaDataWidth); 539 else 540 *gammaOut++ = ((uint16_t *) gammaData)[idxIn] >> (gammaDataWidth - 8); 541 } 542 if (gammaData) 543 { 544 gammaData += gammaDataCount * ((gammaDataWidth + 7) / 8); 545 } 546 } 547 548 cScan = (uint32_t *) gammaOut; 549 pScan = cScan; 550 pSize = -1; 551 552 for (image = 0; image < imageCount; image++) 553 { 554 if (!srcbase[image]) 555 { 556 lineBuffer = dstbase + dlen - lineLen; 557 bzero(lineBuffer, lineLen); 558 } 559 for(y=0 ; y<height ; y++) 560 { 561 if(((((uint8_t *)cScan)-dstbase) + 8*(width+1)) > dlen) 562 { 563 DEBG("", "compressData: overflow: %ld bytes in %d byte buffer at scanline %d (of %d).\n", 564 (size_t)(((uint8_t *)cScan)-dstbase), dlen, y, height); 565 566 return 0; 567 } 568 569 if (srcbase[image]) lineBuffer = srcbase[image] + y*rowbytes; 570 571 cSize = (depth <= 1 ? compress_line_8 : 572 (depth <= 2 ? compress_line_16 : 573 compress_line_32))(lineBuffer, width, (uint8_t *)cScan); 574 575 if(cSize != pSize || bcmp(pScan, cScan, cSize)) 576 { 577 pScan = cScan; 578 cScan = (uint32_t *)((uint8_t *)cScan + cSize); 579 pSize = cSize; 580 } 581 582 dst[image * height + y] = (uint8_t *)pScan - dstbase; 583 } 584 DEBG1("", " image %d ends 0x%lx\n", image, (uintptr_t)(((uint8_t *)cScan) - dstbase)); 585 } 586 587 return (uint8_t *)cScan - dstbase; 588} 589 590static void DecompressData(uint8_t *srcbase, uint32_t image, UInt8 *dstbase, uint32_t dx, uint32_t dy, 591 uint32_t dw, uint32_t dh, uint32_t rowbytes) 592{ 593 hibernate_preview_t * hdr; 594 uint32_t *src; 595 uint8_t *dst; 596 uint32_t xMin,xMax; 597 uint32_t y, depth; 598 599 hdr = (typeof(hdr)) srcbase; 600 dst = (typeof(dst)) dstbase; 601 602 if ((dw != hdr->width) 603#if !IOHIB_PREVIEW_V0 604 || (image >= hdr->imageCount) 605#endif 606 || (dh != hdr->height)) 607 { 608 DEBG1("", " DecompressData mismatch\n"); 609 return; 610 } 611 612 depth = hdr->depth; 613 src = (typeof(src)) (hdr + 1); 614 src += dy + image * dh; 615 616 xMin = dx; 617 xMax = dx + dw; 618 619 for(y=0 ; y<dh ; y++) 620 { 621 UInt8 *scan; 622 623 scan = srcbase + *src; 624 625 if (0 == (y & 7)) 626 { 627 AbsoluteTime deadline; 628 clock_interval_to_deadline(8, kMicrosecondScale, &deadline); 629 assert_wait_deadline((event_t)&clock_delay_until, THREAD_UNINT, __OSAbsoluteTime(deadline)); 630 thread_block(NULL); 631 } 632 633 (depth <= 1 ? DecompressRLE8 : 634 (depth <= 2 ? DecompressRLE16 : DecompressRLE32)) 635 (scan, dst, xMin,xMax); 636 637 dst = dst + rowbytes; 638 src = src + 1; 639 } 640} 641 642static void 643PreviewDecompress16(const hibernate_preview_t * src, uint32_t image, 644 uint32_t width, uint32_t height, uint32_t row, 645 uint16_t * output) 646{ 647 uint32_t i, j; 648 uint32_t * input; 649 650 uint16_t * sc0 = IONew(uint16_t, (width+2)); 651 uint16_t * sc1 = IONew(uint16_t, (width+2)); 652 uint16_t * sc2 = IONew(uint16_t, (width+2)); 653 uint16_t * sc3 = IONew(uint16_t, (width+2)); 654 uint32_t sr0, sr1, sr2, sr3; 655 656 bzero(sc0, (width+2) * sizeof(uint16_t)); 657 bzero(sc1, (width+2) * sizeof(uint16_t)); 658 bzero(sc2, (width+2) * sizeof(uint16_t)); 659 bzero(sc3, (width+2) * sizeof(uint16_t)); 660 661 uint32_t tmp1, tmp2, out; 662 for (j = 0; j < (height + 2); j++) 663 { 664 input = (typeof(input)) (src + 1); 665 input += image * height; 666 if (j < height) 667 input += j; 668 else 669 input += height - 1; 670 input = (uint32_t *)(input[0] + ((uint8_t *)src)); 671 672 uint32_t data = 0, repeat = 0, fetch, count = 0; 673 sr0 = sr1 = sr2 = sr3 = 0; 674 675 for (i = 0; i < (width + 2); i++) 676 { 677 if (i < width) 678 { 679 if (!count) 680 { 681 count = *input++; 682 repeat = (count & 0xff000000); 683 count ^= repeat; 684 fetch = true; 685 } 686 else 687 fetch = (0 == repeat); 688 689 count--; 690 691 if (fetch) 692 { 693 data = *((uint16_t *)input); 694 input = (uint32_t *)(((uint8_t *) input) + sizeof(uint16_t)); 695 696 // grayscale 697 // srgb 13933, 46871, 4732 698 // ntsc 19595, 38470, 7471 699 data = 13933 * (0x1f & (data >> 10)) 700 + 46871 * (0x1f & (data >> 5)) 701 + 4732 * (0x1f & data); 702 data >>= 13; 703 704 // 70% white, 30 % black 705 data *= 19661; 706 data += (103 << 16); 707 data >>= 16; 708 } 709 } 710 711 // gauss blur 712 tmp2 = sr0 + data; 713 sr0 = data; 714 tmp1 = sr1 + tmp2; 715 sr1 = tmp2; 716 tmp2 = sr2 + tmp1; 717 sr2 = tmp1; 718 tmp1 = sr3 + tmp2; 719 sr3 = tmp2; 720 721 tmp2 = sc0[i] + tmp1; 722 sc0[i] = tmp1; 723 tmp1 = sc1[i] + tmp2; 724 sc1[i] = tmp2; 725 tmp2 = sc2[i] + tmp1; 726 sc2[i] = tmp1; 727 out = (128 + sc3[i] + tmp2) >> 11; 728 sc3[i] = tmp2; 729 730 out &= 0x1f; 731 if ((i > 1) && (j > 1)) 732 output[i-2] = out | (out << 5) | (out << 10); 733 } 734 735 if (j > 1) 736 output += row; 737 } 738 IODelete(sc3, uint16_t, (width+2)); 739 IODelete(sc2, uint16_t, (width+2)); 740 IODelete(sc1, uint16_t, (width+2)); 741 IODelete(sc0, uint16_t, (width+2)); 742} 743 744static void 745PreviewDecompress32(const hibernate_preview_t * src, uint32_t image, 746 uint32_t width, uint32_t height, uint32_t row, 747 uint32_t * output) 748{ 749 uint32_t i, j; 750 uint32_t * input; 751 752 uint16_t * sc0 = IONew(uint16_t, (width+2)); 753 uint16_t * sc1 = IONew(uint16_t, (width+2)); 754 uint16_t * sc2 = IONew(uint16_t, (width+2)); 755 uint16_t * sc3 = IONew(uint16_t, (width+2)); 756 uint32_t sr0, sr1, sr2, sr3; 757 758 bzero(sc0, (width+2) * sizeof(uint16_t)); 759 bzero(sc1, (width+2) * sizeof(uint16_t)); 760 bzero(sc2, (width+2) * sizeof(uint16_t)); 761 bzero(sc3, (width+2) * sizeof(uint16_t)); 762 763 uint32_t tmp1, tmp2, out; 764 for (j = 0; j < (height + 2); j++) 765 { 766 input = (typeof(input)) (src + 1); 767 input += image * height; 768 if (j < height) 769 input += j; 770 else 771 input += height - 1; 772 input = (uint32_t *)(input[0] + ((uint8_t *)src)); 773 774 uint32_t data = 0, repeat = 0, fetch, count = 0; 775 sr0 = sr1 = sr2 = sr3 = 0; 776 777 for (i = 0; i < (width + 2); i++) 778 { 779 if (i < width) 780 { 781 if (!count) 782 { 783 count = *input++; 784 repeat = (count & 0xff000000); 785 count ^= repeat; 786 fetch = true; 787 } 788 else 789 fetch = (0 == repeat); 790 791 count--; 792 793 if (fetch) 794 { 795 data = *input++; 796 797 // grayscale 798 // srgb 13933, 46871, 4732 799 // ntsc 19595, 38470, 7471 800 data = 13933 * (0xff & (data >> 24)) 801 + 46871 * (0xff & (data >> 16)) 802 + 4732 * (0xff & data); 803 data >>= 16; 804 805 // 70% white, 30 % black 806 data *= 19661; 807 data += (103 << 16); 808 data >>= 16; 809 } 810 } 811 812 // gauss blur 813 tmp2 = sr0 + data; 814 sr0 = data; 815 tmp1 = sr1 + tmp2; 816 sr1 = tmp2; 817 tmp2 = sr2 + tmp1; 818 sr2 = tmp1; 819 tmp1 = sr3 + tmp2; 820 sr3 = tmp2; 821 822 tmp2 = sc0[i] + tmp1; 823 sc0[i] = tmp1; 824 tmp1 = sc1[i] + tmp2; 825 sc1[i] = tmp2; 826 tmp2 = sc2[i] + tmp1; 827 sc2[i] = tmp1; 828 out = (128 + sc3[i] + tmp2) >> 8; 829 sc3[i] = tmp2; 830 831 out &= 0xff; 832 if ((i > 1) && (j > 1)) 833 output[i-2] = out | (out << 8) | (out << 16); 834 } 835 836 if (j > 1) 837 output += row; 838 } 839 840 IODelete(sc3, uint16_t, (width+2)); 841 IODelete(sc2, uint16_t, (width+2)); 842 IODelete(sc1, uint16_t, (width+2)); 843 IODelete(sc0, uint16_t, (width+2)); 844} 845 846bool 847PreviewDecompressData(void *srcbase, uint32_t image, void *dstbase, 848 uint32_t dw, uint32_t dh, uint32_t bytesPerPixel, uint32_t rowbytes) 849{ 850 const hibernate_preview_t * src = (typeof(src)) srcbase; 851 852 if ((bytesPerPixel != src->depth) 853#if !IOHIB_PREVIEW_V0 854 || (image >= src->imageCount) 855#endif 856 || (dw != src->width) || (dh != src->height)) 857 return (false); 858 859 switch(bytesPerPixel) 860 { 861 case 4: 862 PreviewDecompress32(src, image, dw, dh, rowbytes >> 2, (uint32_t *) dstbase); 863 return (true); 864 case 2: 865 PreviewDecompress16(src, image, dw, dh, rowbytes >> 1, (uint16_t *) dstbase); 866 return (true); 867 default: 868 return (false); 869 } 870} 871 872