/* droid vnc server - Android VNC server Copyright (C) 2011 Jose Pereira This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "gralloc_method.h" #include "common.h" #include #include #include #include #include #include #include #include #include #include #define r(fd, ptr, size) (read((fd), (ptr), (size)) != (int)(size)) #define w(fd, ptr, size) (write((fd), (ptr), (size)) != (int)(size)) static int fill_format(struct fbinfo* info, int format) { // bpp, red, green, blue, alpha static const int format_map[][9] = { {0, 0, 0, 0, 0, 0, 0, 0, 0}, // INVALID {32, 0, 8, 8, 8, 16, 8, 24, 8}, // HAL_PIXEL_FORMAT_RGBA_8888 {32, 0, 8, 8, 8, 16, 8, 0, 0}, // HAL_PIXEL_FORMAT_RGBX_8888 {24, 16, 8, 8, 8, 0, 8, 0, 0}, // HAL_PIXEL_FORMAT_RGB_888 {16, 11, 5, 5, 6, 0, 5, 0, 0}, // HAL_PIXEL_FORMAT_RGB_565 {32, 16, 8, 8, 8, 0, 8, 24, 8}, // HAL_PIXEL_FORMAT_BGRA_8888 {16, 11, 5, 6, 5, 1, 5, 0, 1}, // HAL_PIXEL_FORMAT_RGBA_5551 {16, 12, 4, 8, 4, 4, 4, 0, 4} // HAL_PIXEL_FORMAT_RGBA_4444 }; const int *p; if (format == 0 || format > HAL_PIXEL_FORMAT_RGBA_4444) return -ENOTSUP; p = format_map[format]; info->bpp = *(p++); info->red_offset = *(p++); info->red_length = *(p++); info->green_offset = *(p++); info->green_length = *(p++); info->blue_offset = *(p++); info->blue_length = *(p++); info->alpha_offset = *(p++); info->alpha_length = *(p++); return 0; } #if 0 static int readfb_devfb (int fd) { struct fb_var_screeninfo vinfo; int fb, offset; char x[256]; int rv = -ENOTSUP; struct fbinfo fbinfo; unsigned i, bytespp; fb = open("/dev/graphics/fb0", O_RDONLY); if (fb < 0) goto done; if (ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) goto done; fcntl(fb, F_SETFD, FD_CLOEXEC); bytespp = vinfo.bits_per_pixel / 8; 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; /* 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; offset += vinfo.xres * vinfo.yoffset * bytespp; rv = 0; if (w(fd, &fbinfo, sizeof(fbinfo))) goto done; lseek(fb, offset, SEEK_SET); for (i = 0; i < fbinfo.size; i += 256) { if (r(fb, &x, 256)) goto done; if (w(fd, &x, 256)) goto done; } if (r(fb, &x, fbinfo.size % 256)) goto done; if (w(fd, &x, fbinfo.size % 256)) goto done; done: if (fb >= 0) close(fb); return rv; } #endif struct gralloc_module_t *gralloc; struct framebuffer_device_t *fbdev = 0; struct alloc_device_t *allocdev = 0; buffer_handle_t buf = 0; unsigned char* data = 0; int stride; #define CHECK_RV if (rv != 0){close_gralloc();return -1;} int init_gralloc() { L("--Initializing gralloc access method--\n"); grallocfb=0; int linebytes; int rv; rv = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t**)&gralloc); CHECK_RV; rv = framebuffer_open(&gralloc->common, &fbdev); CHECK_RV; if (!fbdev->read) { rv = -ENOTSUP; close_gralloc(); return rv; } rv = gralloc_open(&gralloc->common, &allocdev); CHECK_RV; rv = allocdev->alloc(allocdev, fbdev->width, fbdev->height, fbdev->format, GRALLOC_USAGE_SW_READ_OFTEN, &buf, &stride); rv = fbdev->read(fbdev, buf); CHECK_RV; rv = gralloc->lock(gralloc, buf, GRALLOC_USAGE_SW_READ_OFTEN, 0, 0, fbdev->width, fbdev->height, (void**)&data); CHECK_RV; rv = fill_format(&displayInfo, fbdev->format); CHECK_RV; stride *= (displayInfo.bpp >> 3); linebytes = fbdev->width * (displayInfo.bpp >> 3); displayInfo.size = linebytes * fbdev->height; displayInfo.width = fbdev->width; displayInfo.height = fbdev->height; // point of no return: don't attempt alternative means of reading // after this rv = 0; grallocfb=malloc(displayInfo.size); L("Stride=%d Linebytes=%d %p\n",stride,linebytes,fbdev->setUpdateRect); memcpy(grallocfb,data,displayInfo.size); if (data) gralloc->unlock(gralloc, buf); L("Copy %d bytes\n",displayInfo.size); L("Returning rv=%d\n",rv); return rv; } void close_gralloc() { if (buf) allocdev->free(allocdev, buf); if (allocdev) gralloc_close(allocdev); if (fbdev) framebuffer_close(fbdev); } int readfb_gralloc () { int rv; rv = fbdev->read(fbdev, buf); CHECK_RV; rv = gralloc->lock(gralloc, buf, GRALLOC_USAGE_SW_READ_OFTEN, 0, 0, fbdev->width, fbdev->height, (void**)&data); CHECK_RV; memcpy(grallocfb,data,displayInfo.size); if (data) gralloc->unlock(gralloc, buf); return rv; }