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