µ±Ç°Î»Ö㺠´úÂëÃÔ >> Android >> Android GUIϵͳѧϰһ£ºGralloc
  Ïêϸ½â¾ö·½°¸

Android GUIϵͳѧϰһ£ºGralloc

Èȶȣº18   ·¢²¼Ê±¼ä£º2016-04-28 00:07:15.0
Android GUIϵͳѧϰ1£ºGralloc

GrallocÄ£¿éÊÇ´ÓAndroid Eclair£¨android 2.1£©¿ªÊ¼¼ÓÈëµÄÒ»¸öHALÄ£¿é£¬GrallocµÄº¬ÒåΪÊÇGraphics Alloc(ͼÐηÖÅä)¡£Ëû¶ÔÉÏΪlibuiÌṩ·þÎñ£¬ÎªÆä·ÖÅäÏԴ棬ˢÐÂÏÔʾµÈ¡£¶Ô϶Ôframebuffer½øÐйÜÀí¡£

gralloc´úÂëͨ³£Î»ÓÚhardware/libhardware/modules/grallocĿ¼Ï¡£°üº¬ÒÔϼ¸¸öÎļþ£º

Android.mk  framebuffer.cpp  gralloc.cpp  gralloc_priv.h  gr.h  mapper.cpp

ÁíÍ⣬ÓëÆäÏà¹ØµÄÍ·ÎļþλÓÚhardware/libhardware/include/hardware£¬Éæ¼°fb.hºÍgralloc.h¡£

ÏÂÃæ´ÓgrallocµÄµ÷ÓÿªÊ¼Ñ§Ï°grallocµÄ´úÂë¡£´úÂë»ùÓÚandroid4.4¡£

grallocµÄµ÷ÓÃÊÇ´ÓFramebufferNativeWindow.cppµÄ¹¹Ô캯Êý¿ªÊ¼µÄ¡£FramebufferNativeWindowʵÏÖFrameBufferµÄ¹ÜÀí£¬ËüÖ÷Òª±»SurfaceFlingerʹÓã¬Ò²¿ÉÒÔ±»OpenGL Native³ÌÐòʹÓá£ÔÚ±¾ÖÊÉÏ£¬ËüÔÚFramebufferÖ®ÉÏʵÏÖÁËÒ»¸öANativeWindow£¬Ä¿Ç°ËüÖ»¹ÜÀíÁ½¸öbuffers:front and back buffer¡£

ÈçÏÂËùʾ(FramebufferNativeWindow.cpp)£º

FramebufferNativeWindow::FramebufferNativeWindow() : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false) { hw_module_t const* module; if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { int stride; int err; int i; err = framebuffer_open(module, &fbDev); ALOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));err = gralloc_open(module, &grDev); ALOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err));// bail out if we can't initialize the modules if (!fbDev || !grDev) return;mUpdateOnDemand = (fbDev->setUpdateRect != 0);// initialize the buffer FIFO if(fbDev->numFramebuffers >= MIN_NUM_FRAME_BUFFERS && fbDev->numFramebuffers <= MAX_NUM_FRAME_BUFFERS){ mNumBuffers = fbDev->numFramebuffers; } else { mNumBuffers = MIN_NUM_FRAME_BUFFERS; } mNumFreeBuffers = mNumBuffers; mBufferHead = mNumBuffers-1;/* * This does not actually change the framebuffer format. It merely * fakes this format to surfaceflinger so that when it creates * framebuffer surfaces it will use this format. It's really a giant * HACK to allow interworking with buggy gralloc+GPU driver * implementations. You should *NEVER* need to set this for shipping * devices. */ #ifdef FRAMEBUFFER_FORCE_FORMAT *((uint32_t *)&fbDev->format) = FRAMEBUFFER_FORCE_FORMAT; #endiffor (i = 0; i < mNumBuffers; i++) { buffers[i] = new NativeBuffer( fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); }for (i = 0; i < mNumBuffers; i++) { err = grDev->alloc(grDev, fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride);ALOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s", i, fbDev->width, fbDev->height, strerror(-err));if (err) { mNumBuffers = i; mNumFreeBuffers = i; mBufferHead = mNumBuffers-1; break; } }const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags; const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi; const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi; const_cast<int&>(ANativeWindow::minSwapInterval) = fbDev->minSwapInterval; const_cast<int&>(ANativeWindow::maxSwapInterval) = fbDev->maxSwapInterval; } else { ALOGE("Couldn't get gralloc module"); }ANativeWindow::setSwapInterval = setSwapInterval; ANativeWindow::dequeueBuffer = dequeueBuffer; ANativeWindow::queueBuffer = queueBuffer; ANativeWindow::query = query; ANativeWindow::perform = perform;ANativeWindow::dequeueBuffer_DEPRECATED = dequeueBuffer_DEPRECATED; ANativeWindow::lockBuffer_DEPRECATED = lockBuffer_DEPRECATED; ANativeWindow::queueBuffer_DEPRECATED = queueBuffer_DEPRECATED; }

ÕâÀï»áÏȸù¾ÝgrallocµÄmodule IDÀ´µÃµ½hw_module_t½á¹¹¡£hw_get_module->hw_get_module_by_class¡£ÔÚhw_get_module_by_classÀïÃ棬Ê×Ïȸù¾Ýƽ̨ÅäÖÃÕÒµ½gralloc¶¯Ì¬¿âµÄλÖã¬Ä¬ÈÏʹÓÃgralloc.default.so¡£
²Î¼ûÒÔÏ´úÂë(hardware.c)£º

for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {        if (i < HAL_VARIANT_KEYS_COUNT) {            if (property_get(variant_keys[i], prop, NULL) == 0) {                continue;            }            snprintf(path, sizeof(path), "%s/%s.%s.so",                     HAL_LIBRARY_PATH2, name, prop);            if (access(path, R_OK) == 0) break;            snprintf(path, sizeof(path), "%s/%s.%s.so",                     HAL_LIBRARY_PATH1, name, prop);            if (access(path, R_OK) == 0) break;        } else {            snprintf(path, sizeof(path), "%s/%s.default.so",                     HAL_LIBRARY_PATH2, name);            if (access(path, R_OK) == 0) break;            snprintf(path, sizeof(path), "%s/%s.default.so",                     HAL_LIBRARY_PATH1, name);            if (access(path, R_OK) == 0) break;        }    } status = -ENOENT; if (i < HAL_VARIANT_KEYS_COUNT+1) { /* load the module, if this fails, we're doomed, and we should not try * to load a different variant. */ status = load(class_id, path, module); }

ÕÒµ½gralloc¿âµÄ·¾¶ºó£¬»áµ÷ÓÃloadº¯Êý£¬ÔÚloadº¯ÊýÖÐʹÓÃdlopen´ò¿ªÕÒµ½µÄ¿â£¬²¢¸ù¾ÝHAL_MODULE_INFO_SYM_AS_STR£¨Æä值ΪHMI£©»ñÈ¡µ½hw_module_t£¨¼´HAL_MODULE_INFO_SYM£©½á¹¹ÌåÖ¸Õ룬ÒÔ¼°°Ñdlopen·µ»ØµÄhandle±£´æÔÚhw_module_tÖС£¶øhw_module_t HMI
½á¹¹ÊÇÒ»¸öÈ«¾Ö½á¹¹£¬ÔÚgralloc.cppÖÐÒѾ­µÃµ½³õʼ»¯ÁË¡£ÕâÒ²ÊÇΪʲôÿһ¸öHALÄ£¿é¶¼Òª¶¨Òå²¢³õʼ»¯Ò»¸öÃû×ÖΪHAL_MODULE_INFO_SYMµÄhw_module_t½á¹¹

struct private_module_t HAL_MODULE_INFO_SYM = {    base: {        common: {            tag: HARDWARE_MODULE_TAG,            version_major: 1,            version_minor: 0,            id: GRALLOC_HARDWARE_MODULE_ID,            name: "Graphics Memory Allocator Module",            author: "The Android Open Source Project",            methods: &gralloc_module_methods        },        registerBuffer: gralloc_register_buffer,        unregisterBuffer: gralloc_unregister_buffer,        lock: gralloc_lock,        unlock: gralloc_unlock,    },    framebuffer: 0,    flags: 0,    numBuffers: 0,    bufferMask: 0,    lock: PTHREAD_MUTEX_INITIALIZER,    currentBuffer: 0,};

»Ø¹ýÍ·£¬»Øµ½FramebufferNativeWindowµÄ¹¹Ô캯Êý³ö£¬½ÓÏÂÀ´µ÷ÓÃÁËerr = framebuffer_open(module, &fbDev);framebuffer_open¶¨ÒåÔÚfb.hÖУ¬ÊÇÒ»¸öinlineº¯Êý£¬Æäʵ×îÖÕµ÷ÓÃÁ˾ÍÊÇÉÏÃæ½á¹¹ÌåÖгõʼ»¯µÄopenº¯Êý£¬openº¯ÊýÖ¸Ïògralloc_device_open£¬ÆäʵÏÖΪ(gralloc.cpp)£º

int gralloc_device_open(const hw_module_t* module, const char* name, hw_device_t** device){    int status = -EINVAL;    if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {        gralloc_context_t *dev;        dev = (gralloc_context_t*)malloc(sizeof(*dev));        /* initialize our state here */        memset(dev, 0, sizeof(*dev));        /* initialize the procs */        dev->device.common.tag = HARDWARE_DEVICE_TAG;        dev->device.common.version = 0;        dev->device.common.module = const_cast<hw_module_t*>(module);        dev->device.common.close = gralloc_close;        dev->device.alloc   = gralloc_alloc;        dev->device.free    = gralloc_free;        *device = &dev->device.common;        status = 0;    } else {        status = fb_device_open(module, name, device);    }    return status;}

fb_device_openµÄ¶¨ÒåÈçÏÂËùʾ(framebuffer.cpp)£º

int fb_device_open(hw_module_t const* module, const char* name,        hw_device_t** device){    int status = -EINVAL;    if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {        /* initialize our state here */        fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));        memset(dev, 0, sizeof(*dev));        /* initialize the procs */        dev->device.common.tag = HARDWARE_DEVICE_TAG;        dev->device.common.version = 0;        dev->device.common.module = const_cast<hw_module_t*>(module);        dev->device.common.close = fb_close;        dev->device.setSwapInterval = fb_setSwapInterval;        dev->device.post            = fb_post;        dev->device.setUpdateRect = 0;        private_module_t* m = (private_module_t*)module;        status = mapFrameBuffer(m);        if (status >= 0) {            int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);            int format = (m->info.bits_per_pixel == 32)                         ? HAL_PIXEL_FORMAT_RGBX_8888                         : HAL_PIXEL_FORMAT_RGB_565;            const_cast<uint32_t&>(dev->device.flags) = 0;            const_cast<uint32_t&>(dev->device.width) = m->info.xres;            const_cast<uint32_t&>(dev->device.height) = m->info.yres;            const_cast<int&>(dev->device.stride) = stride;            const_cast<int&>(dev->device.format) = format;            const_cast<float&>(dev->device.xdpi) = m->xdpi;            const_cast<float&>(dev->device.ydpi) = m->ydpi;            const_cast<float&>(dev->device.fps) = m->fps;            const_cast<int&>(dev->device.minSwapInterval) = 1;            const_cast<int&>(dev->device.maxSwapInterval) = 1;            *device = &dev->device.common;        }    }    return status;}

½ÓÏÂÀ´µÄgralloc_openÒ²Êǵ÷ÓÃÁËgralloc_device_open£¬Ö»²»¹ýname²ÎÊýÒ»¸öÊÇGRALLOC_HARDWARE_GPU0£¬¶øÁíÍâÒ»¸öÊÇGRALLOC_HARDWARE_FB0£¬ÕâÁ½¸öº¯Êý·Ö±ðµÃµ½alloc_device_t ºÍ framebuffer_device_t½á¹¹¡£µ½ÏÖÔÚΪֹ£¬grallocÄ£¿éµÄÈý¸öÖ÷Òª½á¹¹Ì壬gralloc_module_t£¬alloc_device_t£¬framebuffer_device_t¶¼ÒѾ­»ñÈ¡µ½ÁË¡£ÆäÖÐÔÚfb_device_openº¯ÊýÖлá»ñȡʵ¼ÊµÄframebufferÉ豸£¨Í¨³£ÊÇ/dev/graphics/fb0£©µÄһЩÖØÒª²ÎÊýÒÔ¼°ÄÜÁ¦£¬±ÈÈç·Ö±æÂÊÐÅÏ¢ÒÔ¼°Ö§³Ö¶àÉÙ¸ö»º³åµÈ£¬ÁíÍâ»á°ÑframebufferÓ³Éäµ½ÄÚ²âµÄµØÖ·±£´æµ½alloc_module_tÖС£androidÒ»°ãʹÓõĶ¼ÊÇË«»º³å»úÖÆ¡£¾ßÌå´úÂëÈçÏ£¨framebuffer.cpp£©£¬ÆäÖÐÉæ¼°µ½¶Ôprivate_module_tÖÐһЩ³ÉÔ±µÄÍêÉÆ£¬Éæ¼°µ½gralloc_module_tÒÔ¼°private_handle_tµÈ£¬Æ䶨ÒåÔÚgralloc_priv.hÖУ¬ÕâÁ½¸ö½á¹¹Öж¼±£´æÁËframebufferµÄһЩ˽ÓÐÐÅÏ¢¡£

int mapFrameBufferLocked(struct private_module_t* module){// already initialized...if (module->framebuffer) {return 0;}char const * const device_template[] = {"/dev/graphics/fb%u","/dev/fb%u",0 };int fd = -1;int i=0;char name[64];while ((fd==-1) && device_template[i]) {snprintf(name, 64, device_template[i], 0);fd = open(name, O_RDWR, 0);i++;}if (fd < 0)return -errno;struct fb_fix_screeninfo finfo;if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)return -errno;struct fb_var_screeninfo info;if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)return -errno;info.reserved[0] = 0;info.reserved[1] = 0;info.reserved[2] = 0;info.xoffset = 0;info.yoffset = 0;info.activate = FB_ACTIVATE_NOW;/** Request NUM_BUFFERS screens (at lest 2 for page flipping)*/info.yres_virtual = info.yres * NUM_BUFFERS;uint32_t flags = PAGE_FLIP;if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) {info.yres_virtual = info.yres;flags &= ~PAGE_FLIP;ALOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");}if (info.yres_virtual < info.yres * 2) {// we need at least 2 for page-flippinginfo.yres_virtual = info.yres;flags &= ~PAGE_FLIP;ALOGW("page flipping not supported (yres_virtual=%d, requested=%d)",info.yres_virtual, info.yres*2);}if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)return -errno;uint64_t refreshQuotient =(uint64_t( info.upper_margin + info.lower_margin + info.yres )* ( info.left_margin + info.right_margin + info.xres )* info.pixclock);/* Beware, info.pixclock might be 0 under emulation, so avoid a* division-by-0 here (SIGFPE on ARM) */int refreshRate = refreshQuotient > 0 ? (int)(1000000000000000LLU / refreshQuotient) : 0;if (refreshRate == 0) {// bleagh, bad info from the driverrefreshRate = 60*1000; // 60 Hz}if (int(info.width) <= 0 || int(info.height) <= 0) {// the driver doesn't return that information// default to 160 dpiinfo.width = ((info.xres * 25.4f)/160.0f + 0.5f);info.height = ((info.yres * 25.4f)/160.0f + 0.5f);}float xdpi = (info.xres * 25.4f) / info.width;float ydpi = (info.yres * 25.4f) / info.height;float fps = refreshRate / 1000.0f;ALOGI( "using (fd=%d)\n""id = %s\n""xres = %d px\n""yres = %d px\n""xres_virtual = %d px\n""yres_virtual = %d px\n""bpp = %d\n""r = %2u:%u\n""g = %2u:%u\n""b = %2u:%u\n",fd,finfo.id,info.xres,info.yres,info.xres_virtual,info.yres_virtual,info.bits_per_pixel,info.red.offset, info.red.length,info.green.offset, info.green.length,info.blue.offset, info.blue.length);ALOGI( "width = %d mm (%f dpi)\n""height = %d mm (%f dpi)\n""refresh rate = %.2f Hz\n",info.width, xdpi,info.height, ydpi,fps);if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)return -errno;if (finfo.smem_len <= 0)return -errno;module->flags = flags;module->info = info;module->finfo = finfo;module->xdpi = xdpi;module->ydpi = ydpi;module->fps = fps;/** map the framebuffer*/int err;size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual);module->framebuffer = new private_handle_t(dup(fd), fbSize, 0);module->numBuffers = info.yres_virtual / info.yres;module->bufferMask = 0;void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);if (vaddr == MAP_FAILED) {ALOGE("Error mapping the framebuffer (%s)", strerror(errno));return -errno;}module->framebuffer->base = intptr_t(vaddr);memset(vaddr, 0, fbSize);return 0;}

ÓÉÉÏÃ溯Êý¿´³ö£¬mapFrameBufferLockedÖ÷Òª×öÁËÏÂÃ漸¼þÊÂÇ飺
1. ´ò¿ªframebufferÉ豸

2. »ñÈ¡ fb_fix_screeninfo and fb_var_screeninfo

3. refill fb_var_screeninfo

4. ÅжÏÊÇ·ñÖ§³ÖPAGE_FLIP

5. ¼ÆËãË¢ÐÂÂÊ

6. ´òÓ¡grallocÐÅÏ¢

7. Ìî³äprivate_module_t

8. mmap the framebuffer
  
¿´Ö®Ç°µÄHALÄ£¿é±ÈÈçCameraÄ£¿é£¬ÓÐÒ»¸öhw_module_t½á¹¹ºÍÒ»¸öhw_device_t½á¹¹£¬¶øÕâÀïµÄgrallocÄ£¿éÈ´°üº¬ÁËÁ½¸öhw_device_t½á¹¹£¬Ò»¸öalloc_device_tºÍÒ»¸öframebuffer_device_t½á¹¹¡£ÏÈ¿´framebuffer_device_t¶¨Ò壺

framebuffer_device_t£¨fb.h£©£º

typedef struct framebuffer_device_t {struct hw_device_t common;/* flags describing some attributes of the framebuffer */const uint32_t flags;/* dimensions of the framebuffer in pixels */const uint32_t width;const uint32_t height;/* frambuffer stride in pixels */const int stride;/* framebuffer pixel format */const int format;/* resolution of the framebuffer's display panel in pixel per inch*/const float xdpi;const float ydpi;/* framebuffer's display panel refresh rate in frames per second */const float fps;/* min swap interval supported by this framebuffer */const int minSwapInterval;/* max swap interval supported by this framebuffer */const int maxSwapInterval;/* Number of framebuffers supported*/const int numFramebuffers;int reserved[7];/** requests a specific swap-interval (same definition than EGL)** Returns 0 on success or -errno on error.*/int (*setSwapInterval)(struct framebuffer_device_t* window,int interval);/** This hook is OPTIONAL.** It is non NULL If the framebuffer driver supports "update-on-demand"* and the given rectangle is the area of the screen that gets* updated during (*post)().** This is useful on devices that are able to DMA only a portion of* the screen to the display panel, upon demand -- as opposed to* constantly refreshing the panel 60 times per second, for instance.** Only the area defined by this rectangle is guaranteed to be valid, that* is, the driver is not allowed to post anything outside of this* rectangle.** The rectangle evaluated during (*post)() and specifies which area* of the buffer passed in (*post)() shall to be posted.** return -EINVAL if width or height <=0, or if left or top < 0*/int (*setUpdateRect)(struct framebuffer_device_t* window,int left, int top, int width, int height);/** Post <buffer> to the display (display it on the screen)* The buffer must have been allocated with the* GRALLOC_USAGE_HW_FB usage flag.* buffer must be the same width and height as the display and must NOT* be locked.** The buffer is shown during the next VSYNC.** If the same buffer is posted again (possibly after some other buffer),* post() will block until the the first post is completed.** Internally, post() is expected to lock the buffer so that a* subsequent call to gralloc_module_t::(*lock)() with USAGE_RENDER or* USAGE_*_WRITE will block until it is safe; that is typically once this* buffer is shown and another buffer has been posted.** Returns 0 on success or -errno on error.*/int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer);/** The (*compositionComplete)() method must be called after the* compositor has finished issuing GL commands for client buffers.*/int (*compositionComplete)(struct framebuffer_device_t* dev);/** This hook is OPTIONAL.** If non NULL it will be caused by SurfaceFlinger on dumpsys*/void (*dump)(struct framebuffer_device_t* dev, char *buff, int buff_len);/** (*enableScreen)() is used to either blank (enable=0) or* unblank (enable=1) the screen this framebuffer is attached to.** Returns 0 on success or -errno on error.*/int (*enableScreen)(struct framebuffer_device_t* dev, int enable);void* reserved_proc[6];} framebuffer_device_t;

´ÓÕâ¸ö½á¹¹¿´ÒÔ¿´³ö£¬framebuffer_device_tÀïÃæÖ÷Òª±£´æÁËframebufferÏà¹ØµÄһЩÐÅÏ¢£¬ÀýÈç·Ö±æÂÊ£¬Ë¢ÐÂÂÊ£¬framebufferµÄÊýÁ¿µÈ£¬ÁíÍ⣬ÀïÃ涨ÒåÁËһЩ²Ù×÷framebufferµÄº¯Êý£¬Ò»Ï¼òµ¥½éÉÜÆäÖм¸¸öº¯Êý¡£

1. static int fb_setSwapInterval(struct framebuffer_device_t* dev, int interval)
Õâ¸öº¯Êý»ù±¾Ã»ÓÐÓã¬ÒòΪmaxSwapInterval=minSwapInterval= 1£»
2. int (*setUpdateRect)(struct framebuffer_device_t* window, int left, int top, int width, int height);
Õâ¸öº¯ÊýÊǾֲ¿Ë¢ÐÂÓõģ¬Ä¬ÈÏûÓÐÆôÓ᣺Íƽ̨Óйء£
3. int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer);
Õâ¸öÊÇ×î¹Ø¼üµÄº¯Êý¡£ÓÃÀ´½«Í¼Ðλº³åÇøbufferµÄÄÚÈÝäÖȾµ½Ö¡»º³åÇøÖÐÈ¥£¬¼´ÏÔʾÔÚÉ豸µÄÏÔʾÆÁÖÐÈ¥¡£º¯ÊýʵÏÖÈçÏ£º
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer){if (private_handle_t::validate(buffer) < 0)return -EINVAL;fb_context_t* ctx = (fb_context_t*)dev;private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer);private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module);if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {const size_t offset = hnd->base - m->framebuffer->base;m->info.activate = FB_ACTIVATE_VBL;m->info.yoffset = offset / m->finfo.line_length;if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {ALOGE("FBIOPUT_VSCREENINFO failed");m->base.unlock(&m->base, buffer);return -errno;}m->currentBuffer = buffer;} else {// If we can't do the page_flip, just copy the buffer to the front// FIXME: use copybit HAL instead of memcpyvoid* fb_vaddr;void* buffer_vaddr;m->base.lock(&m->base, m->framebuffer,GRALLOC_USAGE_SW_WRITE_RARELY,0, 0, m->info.xres, m->info.yres,&fb_vaddr);m->base.lock(&m->base, buffer,GRALLOC_USAGE_SW_READ_RARELY,0, 0, m->info.xres, m->info.yres,&buffer_vaddr);memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres);m->base.unlock(&m->base, buffer);m->base.unlock(&m->base, m->framebuffer);}return 0;}

´Ófb_postµÄº¯Êý¶¨Òå¿ÉÒÔ¿´³ö£¬ÆäʵÏÖ·½Ê½ÓÐÁ½ÖÖ·½Ê½£¬µÚÒ»ÖÖ·½Ê½ÊÇ°ÑFramebufferµÄºóbufferÇÐΪǰbuffer£¬È»ºóͨ¹ýIOCTRL»úÖƸæËßFBÇý¶¯Çл»DMAÔ´µØµØÖ·¡£

¾ßÌåÔ­ÀíÊÇÕâÑùµÄ£ºµ±private_handle_t½á¹¹ÌåhndËùÃèÊöµÄͼÐλº³åÇøÊÇÔÚϵͳ֡»º³åÇøÖзÖÅäµÄʱºò£¬¼´Õâ¸öͼÐλº³åÇøµÄ±êÖ¾值flagsµÄPRIV_FLAGS_FRAMEBUFFERλµÈÓÚ1µÄʱºò£¬ÎÒÃÇÊDz»ÐèÒª½«Í¼Ðλº³åÇøµÄÄÚÈÝ¿½±´µ½ÏµÍ³Ö¡»º³åÇøÈ¥µÄ£¬ÒòΪÎÒÃǽ«ÄÚÈÝдÈ뵽ͼÐλº³åÇøµÄʱºò£¬ÒѾ­Ï൱ÓÚÊǽ«ÄÚÈÝдÈëµ½ÁËϵͳ֡»º³åÇøÖÐÈ¥ÁË¡£ËäÈ»ÔÚÕâÖÖÇé¿öÏ£¬ÎÒÃDz»ÐèÒª½«Í¼Ðλº³åÇøµÄÄÚÈÝ¿½±´µ½ÏµÍ³Ö¡»º³åÇøÈ¥£¬µ«ÊÇÎÒÃÇÐèÒª¸æËßϵͳ֡»º³åÇøÉ豸½«ÒªäÖȾµÄͼÐλº³åÇø×÷Ϊϵͳµ±Ç°µÄÊä³öͼÐλº³åÇø£¬ÕâÑù²Å¿ÉÒÔ½«ÒªäÖȾµÄͼÐλº³åÇøµÄÄÚÈÝ»æÖƵ½É豸ÏÔʾÆÁÀ´¡£ÀýÈ磬¼ÙÉèϵͳ֡»º³åÇøÓÐ2¸öͼÐλº³åÇø£¬µ±Ç°ÊÇÒÔµÚ1¸öͼÐλº³åÇø×÷ΪÊä³öͼÐλº³åÇøµÄ£¬ÕâʱºòÈç¹ûÎÒÃÇÐèÒªäÖȾµÚ2¸öͼÐλº³åÇø£¬ÄÇô¾Í±ØÐë¸æËßϵͳ֡»æ³åÇøÉ豸£¬½«µÚ2¸öͼÐλº³åÇø×÷ΪÊä³öͼÐλº³åÇø¡£Õâ¸öʵÏÖ·½Ê½µÄÇ°ÌáÊÇLinuxÄں˱ØÐë·ÖÅäÖÁÉÙÁ½¸ö»º³åÇø´óСµÄÎïÀíÄÚ´æºÍʵÏÖÇл»µÄioctrol£¬Õâ¸ö±È½Ï¿ìËÙ¡£

ÉèÖÃϵͳ֡»º³åÇøµÄµ±Ç°Êä³öͼÐλº³åÇøÊÇͨ¹ýIO¿ØÖÆÃüÁîFBIOPUT_VSCREENINFOÀ´½øÐеġ£IO¿ØÖÆÃüÁîFBIOPUT_VSCREENINFOÐèÒªÒ»¸öfb_var_screeninfo½á¹¹Ìå×÷Ϊ²ÎÊý¡£´ÓÇ°ÃæµÚ3²¿·ÖµÄÄÚÈÝ¿ÉÒÔÖªµÀ£¬private_module_t½á¹¹ÌåmµÄ³ÉÔ±±äÁ¿infoÕýºÃ±£´æÔÚÎÒÃÇËùÐèÒªµÄÕâ¸öfb_var_screeninfo½á¹¹Ìå¡£ÓÐÁ˸öm->infoÕâ¸öfb_var_screeninfo½á¹¹ÌåÖ®ºó£¬ÎÒÃÇÖ»ÐèÒªÉèÖúÃËüµÄ³ÉÔ±±äÁ¿yoffsetµÄ值£¨²»ÓÃÉèÖóÉÔ±±äÁ¿xoffsetµÄ值ÊÇÒòΪËùÓеÄͼÐλº³åÇøµÄ¿í¶ÈÊÇÏàµÈµÄ£©£¬¾Í¿ÉÒÔ½«ÒªäÖȾµÄͼÐλº³åÇøÉèÖÃΪϵͳ֡»º³åÇøµÄµ±Ç°Êä³öͼÐλº³åÇø¡£fb_var_screeninfo½á¹¹ÌåµÄ³ÉÔ±±äÁ¿yoffset±£´æµÄÊǵ±Ç°Êä³öͼÐλº³åÇøÔÚÕû¸öϵͳ֡»º³åÇøµÄ×ÝÏòÆ«ÒÆÁ¿£¬¼´YÆ«ÒÆÁ¿¡£ÎÒÃÇÖ»ÐèÒª½«ÒªäÖȾµÄͼÐλº³åÇøµÄ¿ªÊ¼µØÖ·hnd->baseµÄ值¼õȥϵͳ֡»º³åÇøµÄ»ùµØÖ·m->framebuffer->baseµÄ值£¬ÔÙ³ýÒÔͼÐλº³åÇøÒ»ÐÐËùÕ¼¾ÝµÄ×Ö½ÚÊým->finfo.line_length£¬¾Í¿ÉÒԵõ½ËùÐèÒªµÄYÆ«ÒÆÁ¿¡£

ÔÚÖ´ÐÐIO¿ØÖÆÃüÁîFBIOPUT_VSCREENINFO֮ǰ£¬»¹»á½«×÷Ϊ²ÎÊýµÄfb_var_screeninfo½á¹¹ÌåµÄ³ÉÔ±±äÁ¿activateµÄ值ÉèÖÃFB_ACTIVATE_VBL£¬±íʾҪµÈµ½ÏÂÒ»¸ö´¹Ö±Í¬²½Ê¼þ³öÏÖʱ£¬ÔÙ½«µ±Ç°ÒªäÖȾµÄͼÐλº³åÇøµÄÄÚÈÝ»æÖƳöÀ´¡£ÕâÑù×öµÄÄ¿µÄÊDZÜÃâ³öÏÖÆÁÄ»ÉÁ˸£¬¼´±ÜÃâÇ°ºóÁ½¸öͼÐλº³åÇøµÄÄÚÈݸ÷ÓÐÒ»²¿·Öͬʱ³öÏÖÆÁÄ»ÖС£

µÚ¶þÖÖ·½Ê½ÊÇÀûÓÃcopyµÄ·½Ê½À´ÊµÏÖ£¬±È½ÏºÄʱ¡£µ±private_handle_t½á¹¹ÌåhndËùÃèÊöµÄͼÐλº³åÇøÊÇÔÚÄÚ´æÖзÖÅäµÄʱºò£¬¼´Õâ¸öͼÐλº³åÇøµÄ±êÖ¾值flagsµÄPRIV_FLAGS_FRAMEBUFFERλµÈÓÚ0µÄʱºò£¬ÎÒÃǾÍÐèÒª½«ËüµÄÄÚÈÝ¿½±´µ½ÏµÍ³Ö¡»º³åÇøÖÐÈ¥ÁË¡£Õâ¸ö¿½±´µÄ¹¤×÷ÊÇͨ¹ýµ÷Óú¯ÊýmemcpyÀ´Íê³ÉµÄ¡£ÔÚ¿½±´Ö®Ç°£¬ÎÒÃÇÐèÒªÈý¸ö²ÎÊý¡£µÚÒ»¸ö²ÎÊýÊÇÒªäÖȾµÄͼÐλº³åÇøµÄÆðÖ·µØÖ·£¬Õâ¸öµØÖ·±£´æÔÚ²ÎÊýbufferËùÖ¸ÏòµÄÒ»¸öprivate_handle_t½á¹¹ÌåÖС£µÚ¶þ¸ö²ÎÊýÊÇҪϵͳ֡»º³åÇøµÄ»ùµØÖ·£¬Õâ¸öµØÖ·±£´æÔÚprivate_module_t½á¹¹ÌåmµÄ³ÉÔ±±äÁ¿framebufferËùÖ¸ÏòµÄÒ»¸öprivate_handle_t½á¹¹ÌåÖС£µÚÈý¸ö²ÎÊýÊÇÒª¿½±´µÄÄÚÈݵĴóС£¬Õâ¸ö´óС¾Í¸ÕºÃÊÇÒ»¸öÆÁÄ»ÏñËØËùÕ¼¾ÝµÄÄÚ´æµÄ´óС¡£ÆÁÄ»¸ß¶ÈÓÉm->info.yresÀ´ÃèÊö£¬¶øÒ»ÐÐÆÁÄ»ÏñËØËùÕ¼ÓõÄ×Ö½ÚÊýÓÉm->finfo.line_lengthÀ´ÃèÊö£¬½«ÕâÁ½ÕßÏà³Ë£¬¾Í¿ÉÒԵõ½Ò»¸öÆÁÄ»ÏñËØËùÕ¼¾ÝµÄÄÚ´æµÄ´óС¡£

ÔÚ½«Ò»¿éÄڴ滺³åÇøµÄÄÚÈÝ¿½±´µ½ÏµÍ³Ö¡»º³åÇøÖÐȥ֮ǰ£¬ÐèÒª¶ÔÕâÁ½¿é»º³åÇø½øÐÐËø¶¨£¬ÒÔ±£Ö¤ÔÚ¿½±´µÄ¹ý³ÌÖУ¬ÕâÁ½¿é»º³åÇøµÄÄÚÈݲ»»á±»Ð޸ġ£Õâ¸öËø¶¨µÄ¹¤×÷ÊÇÓÉGrallocÄ£¿éÖеĺ¯Êýgralloc_lockÀ´ÊµÏֵġ£´ÓÇ°ÃæµÚ1²¿·ÖµÄÄÚÈÝ¿ÉÒÔÖªµÀ£¬GrallocÄ£¿éÖеĺ¯Êýgralloc_lockµÄµØÖ·ÕýºÃ¾Í±£´æÔÚprivate_module_t½á¹¹ÌåmµÄ³ÉÔ±±äÁ¿baseËùÃèÊöµÄÒ»¸ögralloc_module_t½á¹¹ÌåµÄ³ÉÔ±º¯ÊýlockÖС£
ÔÚµ÷Óú¯Êýgralloc_lockÀ´Ëø¶¨Ò»¿é»º³åÇøÖ®ºó£¬»¹¿ÉÒÔͨ¹ý×îºóÒ»¸öÊä³ö²ÎÊýÀ´»ñµÃ±»Ëø¶¨µÄ»º³åÇøµÄ¿ªÊ¼µØÖ·£¬Òò´Ë£¬Í¨¹ýµ÷Óú¯Êýgralloc_lockÀ´Ëø¶¨ÒªäÖȾµÄͼÐλº³åÇøÒÔ¼°ÏµÍ³Ö¡»º³åÇø£¬¾Í¿ÉÒԵõ½Ç°ÃæËùÐèÒªµÄµÚÒ»¸öºÍµÚ¶þ¸ö²ÎÊý¡£

½«ÒªäÖȾµÄͼÐλº³åÇøµÄÄÚÈÝ¿½±´µ½ÏµÍ³Ö¡»º³åÇøÖ®ºó£¬¾Í¿ÉÒÔ½â³ýÇ°Ãæ¶ÔËüÃǵÄËø¶¨ÁË£¬Õâ¸ö½âËøµÄ¹¤×÷ÊÇÓÉGrallocÄ£¿éÖеĺ¯Êýgralloc_unlockÀ´ÊµÏֵġ£´ÓÇ°ÃæµÚ1²¿·ÖµÄÄÚÈÝ¿ÉÒÔÖªµÀ£¬GrallocÄ£¿éÖеĺ¯Êýgralloc_unlockµÄµØÖ·ÕýºÃ¾Í±£´æÔÚprivate_module_t½á¹¹ÌåmµÄ³ÉÔ±±äÁ¿baseËùÃèÊöµÄÒ»¸ögralloc_module_t½á¹¹ÌåµÄ³ÉÔ±º¯ÊýunlockÖС£

ÒÔÉÏÊÇframebuffer_device_t½á¹¹Ïà¹ØµÄһЩÄÚÈÝ£¬ÆäÖ÷Òª×÷ÓÃÊÇäÖȾͼÐλº³åÇøÀ´ÏÔʾÄÚÈÝ¡£ÏÂÃæÔÚ¿´¿´alloc_device_tµÄÄÚÈÝ¡£
alloc_device_t½á¹¹µÄÄÚÈÝÈçÏ£º
typedef struct alloc_device_t {struct hw_device_t common;/** (*alloc)() Allocates a buffer in graphic memory with the requested* parameters and returns a buffer_handle_t and the stride in pixels to* allow the implementation to satisfy hardware constraints on the width* of a pixmap (eg: it may have to be multiple of 8 pixels).* The CALLER TAKES OWNERSHIP of the buffer_handle_t.** If format is HAL_PIXEL_FORMAT_YCbCr_420_888, the returned stride must be* 0, since the actual strides are available from the android_ycbcr* structure.** Returns 0 on success or -errno on error.*/int (*alloc)(struct alloc_device_t* dev,int w, int h, int format, int usage,buffer_handle_t* handle, int* stride);/** (*free)() Frees a previously allocated buffer.* Behavior is undefined if the buffer is still mapped in any process,* but shall not result in termination of the program or security breaches* (allowing a process to get access to another process' buffers).* THIS FUNCTION TAKES OWNERSHIP of the buffer_handle_t which becomes* invalid after the call.** Returns 0 on success or -errno on error.*/int (*free)(struct alloc_device_t* dev,buffer_handle_t handle);/* This hook is OPTIONAL.** If non NULL it will be caused by SurfaceFlinger on dumpsys*/void (*dump)(struct alloc_device_t *dev, char *buff, int buff_len);void* reserved_proc[7];} alloc_device_t;

´ÓÆä½á¹¹Ìå³ÉÔ±¿ÉÒÔ¿´³ö£¬ÆäÖ÷Òª×÷ÓÃÊÇΪÇëÇóÕß·ÖÅäͼÐλº³åÇø¡£ÏÈ¿´allocº¯ÊýµÄʵÏÖ£¨gralloc.cpp£©:

static int gralloc_alloc(alloc_device_t* dev, int w, int h, int format, int usage, buffer_handle_t* pHandle, int* pStride){ if (!pHandle || !pStride) return -EINVAL;size_t size, stride;int align = 4; int bpp = 0; switch (format) { case HAL_PIXEL_FORMAT_RGBA_8888: case HAL_PIXEL_FORMAT_RGBX_8888: case HAL_PIXEL_FORMAT_BGRA_8888: bpp = 4; break; case HAL_PIXEL_FORMAT_RGB_888: bpp = 3; break; case HAL_PIXEL_FORMAT_RGB_565: case HAL_PIXEL_FORMAT_RAW_SENSOR: bpp = 2; break; default: return -EINVAL; } size_t bpr = (w*bpp + (align-1)) & ~(align-1); size = bpr * h; stride = bpr / bpp;int err; if (usage & GRALLOC_USAGE_HW_FB) { err = gralloc_alloc_framebuffer(dev, size, usage, pHandle); } else { err = gralloc_alloc_buffer(dev, size, usage, pHandle); }if (err < 0) { return err; }*pStride = stride; return 0;}

²ÎÊýformatÓÃÀ´ÃèÊöÒª·ÖÅäµÄͼÐλº³åÇøµÄÑÕÉ«格ʽ£¬ÃèÊöÒ»¸öÏñËØÐèÒª¼¸¸ö×Ö½ÚÀ´±íʾ¡£²ÎÊýw±íʾҪ·ÖÅäµÄͼÐλº³åÇøËù±£´æµÄͼÏñµÄ¿í¶È£¬½«Ëü³ËÒÔbpp£¬¾Í¿ÉÒԵõ½±£´æÒ»ÐÐÏñËØËùÐèҪʹÓõÄ×Ö½ÚÊý¡£ÎÒÃÇÐèÒª½«Õâ¸ö×Ö½ÚÊý¶ÔÆëµ½4¸ö×ֽڱ߽磬×îºóµÃµ½Ò»ÐÐÏñËØËùÐèÒªµÄ×Ö½ÚÊý¾Í±£´æÔÚ±äÁ¿bprÖС£

²ÎÊýh±íʾҪ·ÖÅäµÄͼÐλº³åÇøËù±£´æµÄͼÏñµÄ¸ß¶È£¬½«Ëü³ËÒÔbpr£¬¾Í¿ÉÒԵõ½±£´æÕû¸öͼÏñËùÐèҪʹÓõÄ×Ö½ÚÊý¡£½«±äÁ¿bprµÄ值³ýÒÔ±äÁ¿bppµÄ值£¬¾ÍµÃµ½Òª·ÖÅäµÄͼÐλº³åÇøÒ»Ðаüº¬ÓжàÉÙ¸öÏñËص㣬Õâ¸ö½á¹ûÐèÒª±£´æÔÚÊä³ö²ÎÊýpStrideÖУ¬ÒÔ±ã¿ÉÒÔ·µ»Ø¸øµ÷ÓÃÕß¡£

²ÎÊýusageÓÃÀ´ÃèÊöÒª·ÖÅäµÄͼÐλº³åÇøµÄÓÃ;¡£Èç¹ûÊÇÓÃÀ´ÔÚϵͳ֡»º³åÇøÖÐäÖȾµÄ£¬¼´²ÎÊýusageµÄGRALLOC_USAGE_HW_FBλµÈÓÚ1£¬ÄÇô¾Í±ØÐëҪϵͳ֡»º³åÇøÖзÖÅ䣬·ñÔòµÄ»°£¬¾ÍÔÚÄÚ´æÖзÖÅä¡£×¢Ò⣬ÔÚÄÚ´æÖзÖÅäµÄͼÐλº³åÇø£¬×îÖÕÊÇÐèÒª¿½±´µ½ÏµÍ³Ö¡»º³åÇøÈ¥µÄ£¬ÒÔ±ã¿ÉÒÔ½«ËüËùÃèÊöµÄͼÐÎäÖȾ³öÀ´¡£º¯Êýgralloc_alloc_framebufferÓÃÀ´ÔÚϵͳ֡»º³åÇøÖзÖÅäͼÐλº³åÇø£¬¶øº¯Êýgralloc_alloc_bufferÓÃÀ´ÔÚÄÚ´æÔÚ·ÖÅäͼÐλº³åÇø£¬½ÓÏÂÀ´ÎÒÃǾÍÀ´¿´¿´ÕâÁ½¸öº¯ÊýµÄʵÏÖ¡£

gralloc_alloc_framebuffer×îÖÕµ÷ÓÃÁËgralloc_alloc_framebuffer_locked£¨gralloc.cpp£©£º

static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle){ private_module_t* m = reinterpret_cast<private_module_t*>( dev->common.module);// allocate the framebuffer if (m->framebuffer == NULL) { // initialize the framebuffer, the framebuffer is mapped once // and forever. int err = mapFrameBufferLocked(m); if (err < 0) { return err; } }const uint32_t bufferMask = m->bufferMask; const uint32_t numBuffers = m->numBuffers; const size_t bufferSize = m->finfo.line_length * m->info.yres; if (numBuffers == 1) { // If we have only one buffer, we never use page-flipping. Instead, // we return a regular buffer which will be memcpy'ed to the main // screen when post is called. int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D; return gralloc_alloc_buffer(dev, bufferSize, newUsage, pHandle); }if (bufferMask >= ((1LU<<numBuffers)-1)) { // We ran out of buffers. return -ENOMEM; }// create a "fake" handles for it intptr_t vaddr = intptr_t(m->framebuffer->base); private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size, private_handle_t::PRIV_FLAGS_FRAMEBUFFER);// find a free slot for (uint32_t i=0 ; i<numBuffers ; i++) { if ((bufferMask & (1LU<<i)) == 0) { m->bufferMask |= (1LU<<i); break; } vaddr += bufferSize; } hnd->base = vaddr; hnd->offset = vaddr - intptr_t(m->framebuffer->base); *pHandle = hnd;return 0;}

±äÁ¿bufferMaskÓÃÀ´ÃèÊöϵͳ֡»º³åÇøµÄʹÓÃÇé¿ö£¬¶ø±äÁ¿numBuffersÓÃÀ´ÃèÊöϵͳ֡»º³åÇø¿ÉÒÔ»®·ÖΪ¶àÉÙ¸öͼÐλº³åÇøÀ´Ê¹Óã¬ÁíÍâÒ»¸ö±äÁ¿bufferSizeÓÃÀ´ÃèÊöÉ豸ÏÔʾÆÁÒ»ÆÁÄÚÈÝËùÕ¼ÓõÄÄÚ´æµÄ´óС¡£Èç¹ûϵͳ֡»º³åÇøÖ»ÓÐÒ»¸öͼÐλº³åÇø´óС£¬¼´±äÁ¿numBuffersµÄ值µÈÓÚ1£¬ÄÇôÕâ¸öͼÐλº³åÇø¾ÍʼÖÕÓÃ×÷ϵͳÖ÷ͼÐλº³åÇøÀ´Ê¹Óá£ÔÚÕâÖÖÇé¿öÏ£¬ÎÒÃǾͲ»Äܹ»ÔÚϵͳ֡»º³åÇøÖзÖÅäͼÐλº³åÇøÀ´¸øÓû§¿Õ¼äµÄÓ¦ÓóÌÐòʹÓã¬Òò´Ë£¬Õâʱºò¾Í»áתÏòÄÚ´æÖÐÀ´·ÖÅäͼÐλº³åÇø£¬¼´µ÷Óú¯Êýgralloc_alloc_bufferÀ´·ÖÅäͼÐλº³åÇø¡£×¢Ò⣬Õâʱºò·ÖÅäµÄͼÐλº³åÇøµÄ´óСΪһÆÁÄÚÈݵĴóС£¬¼´bufferSize¡£

Èç¹ûbufferMaskµÄ值´óÓÚµÈÓÚ((1LU<<numBuffers)-1)µÄ值£¬ÄÇô¾Í˵Ã÷ϵͳ֡»º³åÇøÖеÄͼÐλº³åÇøÈ«²¿¶¼·ÖÅä³öÈ¥ÁË£¬Õâʱºò·ÖÅäͼÐλº³åÇø¾Íʧ°ÜÁË¡£ÀýÈ磬¼ÙÉèͼÐλº³åÇøµÄ¸öÊýΪ2£¬ÄÇô((1LU<<numBuffers)-1)µÄ值¾ÍµÈÓÚ3£¬¼´¶þÖÆÖÆ0x11¡£Èç¹ûÕâʱºòbufferMaskµÄ值Ò²µÈÓÚ0x11£¬ÄÇô¾Í±íʾµÚÒ»¸öºÍµÚ¶þ¸öͼÐλº³åÇø¶¼ÒѾ­·ÖÅä³öÈ¥ÁË¡£Òò´Ë£¬Õâʱºò¾Í²»ÄÜÔÙÔÚϵͳ֡»º³åÇøÖзÖÅäͼÐλº³åÇø¡£

¼ÙÉè´Ëʱϵͳ֡»º³åÇøÖÐÉÐÓпÕÏеÄͼÐλº³åÇøµÄ£¬½ÓÏÂÀ´º¯Êý¾Í»á´´½¨Ò»¸öprivate_handle_t½á¹¹ÌåhndÀ´ÃèÊöÕâ¸ö¼´½«Òª·ÖÅä³öÈ¥µÄͼÐλº³åÇø¡£×¢Ò⣬Õâ¸öͼÐλº³åÇøµÄ±êÖ¾值µÈÓÚPRIV_FLAGS_FRAMEBUFFER£¬¼´±íʾÕâÊÇÒ»¿éÔÚϵͳ֡»º³åÇøÖзÖÅäµÄͼÐλº³åÇø¡£

½ÓÏÂÀ´µÄforÑ­»·´ÓµÍλµ½¸ßλ¼ì²é±äÁ¿bufferMaskµÄ值£¬²¢ÇÒÕÒµ½µÚÒ»¸ö值µÈÓÚ0µÄ룬ÕâÑù¾Í¿ÉÒÔÖªµÀÔÚϵͳ֡»º³åÇøÖУ¬µÚ¼¸¸öͼÐλº³åÇøµÄÊÇ¿ÕÏеġ£×¢Ò⣬±äÁ¿vadrrµÄ值¿ªÊ¼µÄʱºòÖ¸Ïòϵͳ֡»º³åÇøµÄ»ùµØÖ·£¬ÔÚÏÂÃæµÄforÑ­»·ÖУ¬Ã¿Ñ­»·Ò»´ÎËüµÄ值¶¼»áÔö¼ÓbufferSize¡£´ÓÕâÀï¾Í¿ÉÒÔ¿´³ö£¬Ã¿´Î´Óϵͳ֡»º³åÇøÖзÖÅä³öÈ¥µÄͼÐλº³åÇøµÄ´óС¶¼ÊǸպõÈÓÚÏÔʾÆÁÒ»ÆÁÄÚÈÝ´óСµÄ¡£×îºó·ÖÅä³öÈ¥µÄͼÐλº³åÇøµÄ¿ªÊ¼µØÖ·¾Í±£´æÔÚÇ°ÃæËù´´½¨µÄprivate_handle_t½á¹¹ÌåhndµÄ³ÉÔ±±äÁ¿baseÖУ¬ÕâÑù£¬Óû§¿Õ¼äµÄÓ¦ÓóÌÐò¾Í¿ÉÒÔÖ±½Ó½«ÒªäÖȾµÄͼÐÎÄÚÈÝ¿½±´µ½Õâ¸öµØÖ·ÉÏÈ¥£¬Õâ¾ÍÏ൱ÓÚÊÇÖ±½Ó½«Í¼ÐÎäÖȾµ½ÏµÍ³Ö¡»º³åÇøÖÐÈ¥¡£
ÔÚ½«private_handle_t½á¹¹Ìåhnd·µ»Ø¸øµ÷ÓÃÕß֮ǰ£¬»¹ÐèÒªÉèÖÃËüµÄ³ÉÔ±±äÁ¿offset£¬ÒÔ±ã¿ÉÒÔÖªµÀËüËùÃèÊöµÄͼÐλº³åÇøµÄÆðʼµØÖ·Ïà¶ÔÓÚϵͳ֡»º³åÇøµÄ»ùµØÖ·µÄÆ«ÒÆÁ¿¡£

gralloc_alloc_buffer£¨gralloc.cpp£©µÄʵÏÖÈçÏ£º

static int gralloc_alloc_buffer(alloc_device_t* dev,size_t size, int usage, buffer_handle_t* pHandle){int err = 0;int fd = -1;size = roundUpToPageSize(size);fd = ashmem_create_region("gralloc-buffer", size);if (fd < 0) {ALOGE("couldn't create ashmem (%s)", strerror(-errno));err = -errno;}if (err == 0) {private_handle_t* hnd = new private_handle_t(fd, size, 0);gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(dev->common.module);err = mapBuffer(module, hnd);if (err == 0) {*pHandle = hnd;}}ALOGE_IF(err, "gralloc failed err=%s", strerror(-err));return err;}

ËüÊ×Ïȵ÷Óú¯Êýashmem_create_regionÀ´´´½¨Ò»¿éÄäÃû¹²ÏíÄڴ棬½Ó×ÅÔÙÔÚÕâ¿éÄäÃû¹²ÏíÄÚ´æÉÏ·ÖÅäÒ»¸öͼÐλº³åÇø¡£×¢Ò⣬Õâ¸öͼÐλº³åÇøÒ²ÊÇʹÓÃÒ»¸öprivate_handle_t½á¹¹ÌåÀ´ÃèÊöµÄ£¬²»¹ýÕâ¸öͼÐλº³åÇøµÄ±êÖ¾值µÈÓÚ0£¬ÒÔÇø±ðÓÚÔÚϵͳ֡»º³åÇøÖзÖÅäµÄͼÐλº³åÇø¡£ÆäÖÐmapBufferÓÖ°ÑhndËùÃèÊöµÄÒ»¸öͼÐλº³åÇøÓ³Éäµ½µ±Ç°½ø³ÌµÄµØÖ·¿Õ¼äÀ´¡£

ÒÔÉÏÄÚÈݾÍÊÇalloc_device_tµÄÏà¹ØÄÚÈÝ¡£ÔÚprivate_module_tÖÐÓÐÒ»¸öregisterBufferµÄº¯ÊýÖ¸Õ룬´Ëº¯ÊýÊǸÉʲôµÄÄØ£¿ÔÚAndroidϵͳÖУ¬ËùÓеÄͼÐλº³åÇø¶¼ÊÇÓÉSurfaceFlinger·þÎñ·ÖÅäµÄ£¬¶øµ±Ò»¸öͼÐλº³åÇø±»·ÖÅäµÄʱºò£¬Ëü»áͬʱ±»Ó³Éäµ½ÇëÇó·ÖÅäµÄ½ø³ÌµÄµØÖ·¿Õ¼äÈ¥£¬¼´·ÖÅäµÄ¹ý³ÌͬʱҲ°üº¬ÁË×¢²áµÄ¹ý³Ì¡£µ«ÊǶÔÓû§¿Õ¼äµÄÆäËüµÄÓ¦ÓóÌÐòÀ´Ëµ£¬ËüÃÇËùÐèÒªµÄͼÐλº³åÇøÊÇÔÚÓÉSurfaceFlinger·þÎñ·ÖÅäµÄ£¬Òò´Ë£¬µ±ËüÃǵõ½SurfaceFlinger·þÎñ·ÖÅäµÄͼÐλº³åÇøÖ®ºó£¬»¹ÐèÒª½«Õâ¿éͼÐλº³åÇøÓ³Éäµ½×Ô¼ºµÄµØÖ·¿Õ¼äÀ´£¬ÒÔ±ã¿ÉÒÔʹÓÃÕâ¿éͼÐλº³åÇø¡£Õâ¸öÓ³ÉäµÄ¹ý³Ì¼´ÎªÎÒÃǽÓÏÂÀ´Òª·ÖÎöµÄͼÐλº³åÇø×¢²á¹ý³Ì¡£

ÓÉÓÚÔÚϵͳ֡»º³åÇøÖзÖÅäµÄͼÐλº³åÇøÖ»ÔÚSurfaceFlinger·þÎñÖÐʹÓ㬶øSurfaceFlinger·þÎñÔÚ³õʼ»¯ÏµÍ³Ö¡»º³åÇøµÄʱºò£¬ÒѾ­½«ÏµÍ³Ö¡»º³åÇøÓ³Éäµ½×Ô¼ºËùÔڵĽø³ÌÖÐÀ´ÁË£¬Òò´Ë£¬º¯Êýgralloc_mapÈç¹û·¢ÏÖҪע²áµÄͼÐλº³åÇøÊÇÔÚϵͳ֡»º³åÇø·ÖÅäµÄʱºò£¬ÄÇô¾Í²»ÐèÒªÔÙÖ´ÐÐÓ³ÉäͼÐλº³åÇøµÄ²Ù×÷ÁË¡£

Èç¹ûҪע²áµÄͼÐλº³åÇøÊÇÔÚÄÚ´æÖзÖÅäµÄ£¬¼´ËüµÄ±êÖ¾值flagsµÄPRIV_FLAGS_FRAMEBUFFERλµÈÓÚ1£¬ÄÇô½ÓÏÂÀ´¾ÍÐèÒª½«ËüÓ³Éäµ½µ±Ç°½ø³ÌµÄµØÖ·¿Õ¼äÀ´ÁË¡£ÓÉÓÚҪע²áµÄͼÐλº³åÇøÊÇÔÚÎļþÃèÊö·ûhnd->fdËùÃèÊöµÄÒ»¿éÄäÃû¹²ÏíÄÚ´æÖзÖÅäµÄ£¬Òò´Ë£¬ÎÒÃÇÖ»ÐèÒª½«ÎļþÃèÊö·ûhnd->fdËùÃèÊöµÄÒ»¿éÄäÃû¹²ÏíÄÚ´æÓ³Éäµ½µ±Ç°½ø³ÌµÄµØÖ·¿Õ¼äÀ´£¬¾Í¿ÉÒÔ½«²ÎÊýhndËùÃèÊöµÄÒ»¸öͼÐλº³åÇøÓ³Éäµ½µ±Ç°½ø³ÌµÄµØÖ·¿Õ¼äÀ´¡£

ÓÉÓÚÓ³ÉäÎļþÃèÊö·ûhnd->fdµÃµ½µÄÊÇÒ»Õû¿éÄäÃû¹²ÏíÄÚ´æÔÚµ±Ç°½ø³ÌµØÖ·¿Õ¼äµÄ»ùµØÖ·£¬¶øҪע²áµÄͼÐλº³åÇø¿ÉÄÜÖ»Õ¼¾ÝÕâ¿éÄäÃû¹²ÏíÄÚ´æµÄijһС²¿·Ö£¬Òò´Ë£¬ÎÒÃÇ»¹ÐèÒª½«Òª×¢²áµÄͼÐλº³åÇøµÄÔÚ±»Ó³ÉäµÄÄäÃû¹²ÏíÄÚ´æÖеÄÆ«ÒÆÁ¿hnd->offset¼ÓÉϱ»Ó³ÉäµÄÄäÃû¹²ÏíÄÚ´æµÄ»ùµØÖ·hnd->base£¬²Å¿ÉÒԵõ½Òª×¢²áµÄͼÐλº³åÇøÔÚµ±Ç°½ø³ÌÖеķÃÎʵØÖ·£¬Õâ¸öµØÖ·×îÖÕÓÖ±»Ð´Èëµ½hnd->baseÖÐÈ¥¡£

²Î¿¼Îĵµ£ºhttp://blog.csdn.net/luoshengyang/article/details/7747932

²é¿´ÏêÇé

¹Øע΢ÐŹ«ÖÚƽ̨:³ÌÐòÔ±»¥¶¯ÁªÃË(coder_online)£¬Äã¿ÉÒÔµÚһʱ¼ä»ñÈ¡Ô­´´¼¼ÊõÎÄÕ£¬ºÍ£¨java/C/C++/Android/Windows/Linux£©¼¼Êõ´óÅ£×öÅóÓÑ£¬ÔÚÏß½»Á÷±à³Ì¾­Ñ飬»ñÈ¡±à³Ì»ù´¡ÖªÊ¶£¬½â¾ö±à³ÌÎÊÌâ¡£³ÌÐòÔ±»¥¶¯ÁªÃË£¬¿ª·¢ÈËÔ±×Ô¼ºµÄ¼Ò¡£

¡¾Windows±à³Ì¡¿ÏµÁеÚËÄƪ£ºÊ¹ÓÃUnicode±à³Ì

°æȨÉùÃ÷£º±¾ÎÄΪ²©Ö÷Ô­´´ÎÄÕ£¬Î´¾­²©Ö÷ÔÊÐí²»µÃתÔØ¡£

  Ïà¹Ø½â¾ö·½°¸