1/*
2cc -Os -o /tmp/gaussblur gaussblur.c -framework ApplicationServices -framework IOKit -Wall
3*/
4
5#include <CoreFoundation/CoreFoundation.h>
6#include <ApplicationServices/ApplicationServices.h>
7#include <IOKit/graphics/IOGraphicsLib.h>
8#include <stdlib.h>
9#include <stdio.h>
10#include <mach/mach.h>
11#include <mach/mach_time.h>
12
13
14#define DEBG(idx, fmt, args...)         \
15do {                                    \
16    printf(fmt, ## args);               \
17} while( false )
18#define bcopy_nc bcopy
19
20#include "../IOGraphicsFamily/bmcompress.h"
21
22
23int main(int argc, char * argv[])
24{
25    CGError             err;
26    int                 i, j;
27    CGDisplayCount      max;
28    CGDirectDisplayID   displayIDs[8];
29    double scale = 0.0;
30    uint64_t start, end;
31
32    uint32_t * screen;
33    uint32_t rowBytes, bytesPerPixel;
34    uint32_t width, height;
35    uint32_t * buffer;
36    uint32_t * compressBuffer;
37    uint32_t * input;
38    uint32_t * output;
39    uint32_t   compressLen;
40
41    {
42        struct mach_timebase_info tbi;
43        kern_return_t r;
44        uint32_t num = 0;
45        uint32_t denom = 0;
46
47        r = mach_timebase_info(&tbi);
48        if (r != KERN_SUCCESS) {
49            abort();
50        }
51        num = tbi.numer;
52        denom = tbi.denom;
53
54        scale = (double)num / (double)denom;
55    }
56
57    err = CGGetOnlineDisplayList(8, displayIDs, &max);
58    if(err != kCGErrorSuccess)
59        exit(1);
60    if(max > 8)
61        max = 8;
62
63    screen = (uint32_t *) CGDisplayBaseAddress(displayIDs[0]);
64    rowBytes = CGDisplayBytesPerRow(displayIDs[0]);
65
66    printf("Base addr %p, rb %x\n", screen, rowBytes);
67
68    rowBytes >>= 2;
69
70    width = CGDisplayPixelsWide(displayIDs[0]);
71    height = CGDisplayPixelsHigh(displayIDs[0]);
72
73    buffer = malloc(width * height * sizeof(uint32_t));
74    start = mach_absolute_time();
75    for (j = 0; j < height; j++)
76        bcopy(screen + j * rowBytes, buffer + j * width, width * sizeof(uint32_t));
77    end = mach_absolute_time();
78
79    printf("copy time %f\n", (end - start) * scale / NSEC_PER_SEC);
80    printf("copy Mbs %f\n", ((double) width * height * sizeof(uint32_t)) / 1024.0 / 1024.0 / ((end - start) * scale / NSEC_PER_SEC) );
81
82
83bytesPerPixel = sizeof(uint32_t);
84
85    compressBuffer = malloc(width * height * sizeof(uint32_t) * 2);
86
87//screen = buffer;
88//rowBytes = width;
89
90
91    start = mach_absolute_time();
92    compressLen = CompressData( (UInt8 *) screen, bytesPerPixel,
93                            width, height, rowBytes << 2,
94                            (UInt8 *) compressBuffer, width * height * sizeof(uint32_t) * 2 );
95    end = mach_absolute_time();
96
97    printf("compress time %f\n", (end - start) * scale / NSEC_PER_SEC);
98
99    DEBG(thisIndex, " compressed to %d%%\n", (compressLen * 100) / (width * height * sizeof(uint32_t)));
100
101//exit(0);
102
103    uint16_t * sc0 = malloc((width+2) * sizeof(uint16_t));
104    uint16_t * sc1 = malloc((width+2) * sizeof(uint16_t));
105    uint16_t * sc2 = malloc((width+2) * sizeof(uint16_t));
106    uint16_t * sc3 = malloc((width+2) * sizeof(uint16_t));
107    uint32_t   sr0, sr1, sr2, sr3;
108
109    bzero(sc0, (width+2) * sizeof(uint16_t));
110    bzero(sc1, (width+2) * sizeof(uint16_t));
111    bzero(sc2, (width+2) * sizeof(uint16_t));
112    bzero(sc3, (width+2) * sizeof(uint16_t));
113
114    input = buffer;
115    output = screen;
116
117    start = mach_absolute_time();
118    for (j = 0; j < height; j++)
119    {
120        for (i = 0; i < width; i++)
121            output[i] = *input++;
122        output += rowBytes;
123    }
124
125    end = mach_absolute_time();
126
127    printf("time %f\n", (end - start) * scale / NSEC_PER_SEC);
128
129    output = screen;
130
131    uint32_t tmp1, tmp2, out;
132    for (j = 0; j < (height + 2); j++)
133    {
134        input = compressBuffer;
135        if (j < height)
136            input += j;
137        else
138            input += height - 1;
139        input = (uint32_t *)(input[3] + ((uint8_t *)compressBuffer));
140
141        uint32_t data, repeat, fetch, count = 0;
142        sr0 = sr1 = sr2 = sr3 = 0;
143
144        for (i = 0; i < (width + 2); i++)
145        {
146            if (i < width)
147            {
148                if (!count)
149                {
150                    count = *input++;
151                    repeat = (count & 0xff000000);
152                    count ^= repeat;
153                    fetch = true;
154                }
155                else
156                    fetch = (0 == repeat);
157
158                count--;
159
160                if (fetch)
161                {
162                    data = *input++;
163
164                    // grayscale
165                    // srgb 13933, 46871, 4732
166                    // ntsc 19595, 38470, 7471
167                    data = 13933 * (0xff & (data >> 24))
168                         + 46871 * (0xff & (data >> 16))
169                         +  4732 * (0xff & data);
170                    data >>= 16;
171
172                    // 70% white, 30 % black
173                    data *= 19661;
174                    data += (103 << 16);
175                    data >>= 16;
176                }
177            }
178
179            // gauss blur
180            tmp2 = sr0 + data;
181            sr0 = data;
182            tmp1 = sr1 + tmp2;
183            sr1 = tmp2;
184            tmp2 = sr2 + tmp1;
185            sr2 = tmp1;
186            tmp1 = sr3 + tmp2;
187            sr3 = tmp2;
188
189            tmp2 = sc0[i] + tmp1;
190            sc0[i] = tmp1;
191            tmp1 = sc1[i] + tmp2;
192            sc1[i] = tmp2;
193            tmp2 = sc2[i] + tmp1;
194            sc2[i] = tmp1;
195            out = (128 + sc3[i] + tmp2) >> 8;
196            sc3[i] = tmp2;
197
198            out &= 0xff;
199            if ((i > 1) && (j > 1))
200                output[i-2] = out | (out << 8) | (out << 16);
201        }
202
203        if (j > 1)
204            output += rowBytes;
205    }
206
207    end = mach_absolute_time();
208
209    printf("time %f\n", (end - start) * scale / NSEC_PER_SEC);
210
211    exit(0);
212    return(0);
213}
214
215