eclair snapshot
diff --git a/adb/framebuffer_service.c b/adb/framebuffer_service.c
index 65cb20a..2f45694 100644
--- a/adb/framebuffer_service.c
+++ b/adb/framebuffer_service.c
@@ -28,18 +28,35 @@
 #include <sys/mman.h>
 
 /* TODO:
-** - grab the current buffer, not the first buffer
 ** - sync with vsync to avoid tearing
 */
+/* This version number defines the format of the fbinfo struct.
+   It must match versioning in ddms where this data is consumed. */
+#define DDMS_RAWIMAGE_VERSION 1
+struct fbinfo {
+    unsigned int version;
+    unsigned int bpp;
+    unsigned int size;
+    unsigned int width;
+    unsigned int height;
+    unsigned int red_offset;
+    unsigned int red_length;
+    unsigned int blue_offset;
+    unsigned int blue_length;
+    unsigned int green_offset;
+    unsigned int green_length;
+    unsigned int alpha_offset;
+    unsigned int alpha_length;
+} __attribute__((packed));
 
 void framebuffer_service(int fd, void *cookie)
 {
     struct fb_var_screeninfo vinfo;
-    int fb;
-    void *ptr = MAP_FAILED;
-    char x;
+    int fb, offset;
+    char x[256];
 
-    unsigned fbinfo[4];
+    struct fbinfo fbinfo;
+    unsigned i, bytespp;
 
     fb = open("/dev/graphics/fb0", O_RDONLY);
     if(fb < 0) goto done;
@@ -47,24 +64,43 @@
     if(ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) goto done;
     fcntl(fb, F_SETFD, FD_CLOEXEC);
 
-    fbinfo[0] = 16;
-    fbinfo[1] = vinfo.xres * vinfo.yres * 2;
-    fbinfo[2] = vinfo.xres;
-    fbinfo[3] = vinfo.yres;
+    bytespp = vinfo.bits_per_pixel / 8;
 
-    ptr = mmap(0, fbinfo[1], PROT_READ, MAP_SHARED, fb, 0);
-    if(ptr == MAP_FAILED) goto done;
+    fbinfo.version = DDMS_RAWIMAGE_VERSION;
+    fbinfo.bpp = vinfo.bits_per_pixel;
+    fbinfo.size = vinfo.xres * vinfo.yres * bytespp;
+    fbinfo.width = vinfo.xres;
+    fbinfo.height = vinfo.yres;
+    fbinfo.red_offset = vinfo.red.offset;
+    fbinfo.red_length = vinfo.red.length;
+    fbinfo.green_offset = vinfo.green.offset;
+    fbinfo.green_length = vinfo.green.length;
+    fbinfo.blue_offset = vinfo.blue.offset;
+    fbinfo.blue_length = vinfo.blue.length;
+    fbinfo.alpha_offset = vinfo.transp.offset;
+    fbinfo.alpha_length = vinfo.transp.length;
 
-    if(writex(fd, fbinfo, sizeof(unsigned) * 4)) goto done;
+    /* HACK: for several of our 3d cores a specific alignment
+     * is required so the start of the fb may not be an integer number of lines
+     * from the base.  As a result we are storing the additional offset in
+     * xoffset. This is not the correct usage for xoffset, it should be added
+     * to each line, not just once at the beginning */
+    offset = vinfo.xoffset * bytespp;
 
-    for(;;) {
-        if(readx(fd, &x, 1)) goto done;
-        if(writex(fd, ptr, fbinfo[1])) goto done;
+    offset += vinfo.xres * vinfo.yoffset * bytespp;
+
+    if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done;
+
+    lseek(fb, offset, SEEK_SET);
+    for(i = 0; i < fbinfo.size; i += 256) {
+      if(readx(fb, &x, 256)) goto done;
+      if(writex(fd, &x, 256)) goto done;
     }
 
+    if(readx(fb, &x, fbinfo.size % 256)) goto done;
+    if(writex(fd, &x, fbinfo.size % 256)) goto done;
+
 done:
-    if(ptr != MAP_FAILED) munmap(ptr, fbinfo[1]);
     if(fb >= 0) close(fb);
     close(fd);
 }
-