1/* 2cc -o /tmp/timefb timefb.c -framework IOKit -framework ApplicationServices -Wall -arch x86_64 3*/ 4 5#include <IOKit/IOKitLib.h> 6#include <ApplicationServices/ApplicationServicesPriv.h> 7#include <IOKit/i2c/IOI2CInterface.h> 8#include <IOKit/graphics/IOFramebufferShared.h> 9#include <IOKit/graphics/IOGraphicsTypesPrivate.h> 10#include <IOKit/graphics/IOAccelSurfaceControl.h> 11#include <IOKit/graphics/IOGraphicsLib.h> 12#include </System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/PrivateHeaders/blt.h> 13#include <libc.h> 14 15double currentTime(void) 16{ 17 struct timeval v; 18 19 gettimeofday(&v, NULL); 20 return (v.tv_sec + (1e-6) * v.tv_usec); 21} 22 23int main(int argc, char * argv[]) 24{ 25 IOReturn kr; 26 CGDirectDisplayID dspy = CGMainDisplayID(); 27 io_service_t framebuffer; 28 io_connect_t connect; 29 CGRect bounds; 30 mach_vm_size_t size; 31 CGSRowBytes rb; 32 mach_vm_address_t p, mapAddr; 33 double t; 34 int i; 35 36 dspy = CGMainDisplayID(); 37 bounds = CGDisplayBounds(dspy); 38// rb = CGDisplayBytesPerRow(dspy); 39 CGSGetDisplayRowBytes(dspy, &rb); 40 41 framebuffer = CGDisplayIOServicePort(dspy); 42 assert (framebuffer != MACH_PORT_NULL); 43 kr = IOServiceOpen(framebuffer, mach_task_self(), kIOFBSharedConnectType, &connect); 44 if (kIOReturnSuccess != kr) 45 { 46 printf("IOServiceOpen(%x)\n", kr); 47 exit(1); 48 } 49 50 static IOOptionBits mapTypes[] = { 51 kIOMapInhibitCache, kIOMapWriteThruCache, kIOMapCopybackCache, kIOMapWriteCombineCache }; 52 static const char * mapNames[] = { 53 "kIOMapInhibitCache", "kIOMapWriteThruCache", "kIOMapCopybackCache", "kIOMapWriteCombineCache" }; 54 55 bounds.size.height -= 40; 56 57 int mapType, x, y; 58 for (mapType = 0; mapType < sizeof(mapTypes) / sizeof(mapTypes[0]); mapType++) 59 { 60 kr = IOConnectMapMemory64(connect, kIOFBVRAMMemory, mach_task_self(), 61 &mapAddr, &size, 62 kIOMapAnywhere | mapTypes[mapType]); 63 if (kIOReturnSuccess != kr) 64 { 65 printf("IOConnectMapMemory(%x)\n", kr); 66 exit(1); 67 } 68 69 mapAddr += 128*1024; 70 t = currentTime(); 71 72 uint32_t sum; 73 for (i = 0; i < 20; i++) { 74 p = mapAddr; 75 sum = 0; 76 for (y = 0; y < bounds.size.height; y++) 77 { 78 for (x = 0; x < bounds.size.width; x++) 79 { 80 sum += ((uint32_t*)(uintptr_t)p)[x]; 81 } 82 p += rb; 83 } 84 } 85 printf("read (%s) %d times at (%dx%dx32): %g MB/sec sum 0x%x\n", mapNames[mapType], i, 86 (int)bounds.size.width, (int)bounds.size.height, 87 i*bounds.size.width*bounds.size.height*4/(1e6*(currentTime() - t)), sum); 88 89 t = currentTime(); 90 for (i = 0; i < 20; i++) { 91 CGBlt_fillBytes(bounds.size.width*4, bounds.size.height, 1, (void*)(uintptr_t) mapAddr, rb, 0); 92 } 93 printf("CGBlt_fillBytes(%s) %d times at (%dx%dx32): %g MB/sec\n", mapNames[mapType], i, 94 (int)bounds.size.width, (int)bounds.size.height, 95 i*bounds.size.width*bounds.size.height*4/(1e6*(currentTime() - t))); 96 97 for (i = 0; i < 20; i++) { 98 p = mapAddr; 99 for (y = 0; y < bounds.size.height; y++) 100 { 101 for (x = 0; x < bounds.size.width; x++) 102 { 103 ((uint32_t*)(uintptr_t)p)[x] = random(); 104 } 105 p += rb; 106 } 107 } 108 printf("fill random(%s) %d times at (%dx%dx32): %g MB/sec\n", mapNames[mapType], i, 109 (int)bounds.size.width, (int)bounds.size.height, 110 i*bounds.size.width*bounds.size.height*4/(1e6*(currentTime() - t))); 111 112 kr = IOConnectUnmapMemory(connect, kIOFBVRAMMemory, mach_task_self(), mapAddr); 113 if (kIOReturnSuccess != kr) 114 { 115 printf("IOConnectUnmapMemory(%x)\n", kr); 116 exit(1); 117 } 118 } 119 120 return (0); 121} 122 123