/* cc -Os -o /tmp/gaussblur gaussblur.c -framework ApplicationServices -framework IOKit -Wall */ #include #include #include #include #include #include #include #define DEBG(idx, fmt, args...) \ do { \ printf(fmt, ## args); \ } while( false ) #define bcopy_nc bcopy #include "../IOGraphicsFamily/bmcompress.h" int main(int argc, char * argv[]) { CGError err; int i, j; CGDisplayCount max; CGDirectDisplayID displayIDs[8]; double scale = 0.0; uint64_t start, end; uint32_t * screen; uint32_t rowBytes, bytesPerPixel; uint32_t width, height; uint32_t * buffer; uint32_t * compressBuffer; uint32_t * input; uint32_t * output; uint32_t compressLen; { struct mach_timebase_info tbi; kern_return_t r; uint32_t num = 0; uint32_t denom = 0; r = mach_timebase_info(&tbi); if (r != KERN_SUCCESS) { abort(); } num = tbi.numer; denom = tbi.denom; scale = (double)num / (double)denom; } err = CGGetOnlineDisplayList(8, displayIDs, &max); if(err != kCGErrorSuccess) exit(1); if(max > 8) max = 8; screen = (uint32_t *) CGDisplayBaseAddress(displayIDs[0]); rowBytes = CGDisplayBytesPerRow(displayIDs[0]); printf("Base addr %p, rb %x\n", screen, rowBytes); rowBytes >>= 2; width = CGDisplayPixelsWide(displayIDs[0]); height = CGDisplayPixelsHigh(displayIDs[0]); buffer = malloc(width * height * sizeof(uint32_t)); start = mach_absolute_time(); for (j = 0; j < height; j++) bcopy(screen + j * rowBytes, buffer + j * width, width * sizeof(uint32_t)); end = mach_absolute_time(); printf("copy time %f\n", (end - start) * scale / NSEC_PER_SEC); printf("copy Mbs %f\n", ((double) width * height * sizeof(uint32_t)) / 1024.0 / 1024.0 / ((end - start) * scale / NSEC_PER_SEC) ); bytesPerPixel = sizeof(uint32_t); compressBuffer = malloc(width * height * sizeof(uint32_t) * 2); //screen = buffer; //rowBytes = width; start = mach_absolute_time(); compressLen = CompressData( (UInt8 *) screen, bytesPerPixel, width, height, rowBytes << 2, (UInt8 *) compressBuffer, width * height * sizeof(uint32_t) * 2 ); end = mach_absolute_time(); printf("compress time %f\n", (end - start) * scale / NSEC_PER_SEC); DEBG(thisIndex, " compressed to %d%%\n", (compressLen * 100) / (width * height * sizeof(uint32_t))); //exit(0); uint16_t * sc0 = malloc((width+2) * sizeof(uint16_t)); uint16_t * sc1 = malloc((width+2) * sizeof(uint16_t)); uint16_t * sc2 = malloc((width+2) * sizeof(uint16_t)); uint16_t * sc3 = malloc((width+2) * sizeof(uint16_t)); uint32_t sr0, sr1, sr2, sr3; bzero(sc0, (width+2) * sizeof(uint16_t)); bzero(sc1, (width+2) * sizeof(uint16_t)); bzero(sc2, (width+2) * sizeof(uint16_t)); bzero(sc3, (width+2) * sizeof(uint16_t)); input = buffer; output = screen; start = mach_absolute_time(); for (j = 0; j < height; j++) { for (i = 0; i < width; i++) output[i] = *input++; output += rowBytes; } end = mach_absolute_time(); printf("time %f\n", (end - start) * scale / NSEC_PER_SEC); output = screen; uint32_t tmp1, tmp2, out; for (j = 0; j < (height + 2); j++) { input = compressBuffer; if (j < height) input += j; else input += height - 1; input = (uint32_t *)(input[3] + ((uint8_t *)compressBuffer)); uint32_t data, repeat, fetch, count = 0; sr0 = sr1 = sr2 = sr3 = 0; for (i = 0; i < (width + 2); i++) { if (i < width) { if (!count) { count = *input++; repeat = (count & 0xff000000); count ^= repeat; fetch = true; } else fetch = (0 == repeat); count--; if (fetch) { data = *input++; // grayscale // srgb 13933, 46871, 4732 // ntsc 19595, 38470, 7471 data = 13933 * (0xff & (data >> 24)) + 46871 * (0xff & (data >> 16)) + 4732 * (0xff & data); data >>= 16; // 70% white, 30 % black data *= 19661; data += (103 << 16); data >>= 16; } } // gauss blur tmp2 = sr0 + data; sr0 = data; tmp1 = sr1 + tmp2; sr1 = tmp2; tmp2 = sr2 + tmp1; sr2 = tmp1; tmp1 = sr3 + tmp2; sr3 = tmp2; tmp2 = sc0[i] + tmp1; sc0[i] = tmp1; tmp1 = sc1[i] + tmp2; sc1[i] = tmp2; tmp2 = sc2[i] + tmp1; sc2[i] = tmp1; out = (128 + sc3[i] + tmp2) >> 8; sc3[i] = tmp2; out &= 0xff; if ((i > 1) && (j > 1)) output[i-2] = out | (out << 8) | (out << 16); } if (j > 1) output += rowBytes; } end = mach_absolute_time(); printf("time %f\n", (end - start) * scale / NSEC_PER_SEC); exit(0); return(0); }