Android Gralloc模块分析--深入分析
来源:互联网 发布:json字符串中url编码 编辑:程序博客网 时间:2024/06/05 16:59
前一篇的文章《Android Gralloc模块分析》从功能的角度分析了Gralloc模块,基本掌握了Gralloc的总体结构,但是具体函数还有待进一步学习与分析。它们包括:
分别对应gralloc.cpp、framebuffer.cpp、mapper.cpp
这里的组织感觉不太合理,应该改成:gralloc_module.cpp跟映射相关、alloc_device.cpp跟分配图形缓冲区相关、framebuffer_device.cpp跟渲染相关。今天看了瑞星微的gralloc代码,组织得就很好,逻辑性强。
回顾
上一篇文章提到,模块在被框架层加载后,就导出了HMI符号地址对应的hw_module_t结构。实际上导出了gralloc_device_open方法
gralloc_register_buffer方法
其中后者用来将图形缓冲区映射进程地址空间中;而前者用来打开两个设备,这两个设备分别是alloc_device_t和framebuffer_device_t,它们返回了主要函数有:
gralloc_alloc方法
fb_post方法
上面两种方法,分别用来分配图形缓冲区,渲染帧缓冲区。本文下面的内容具体分析这些函数及相关的函数。
gralloc设备 gralloc.cpp
/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include <limits.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <pthread.h>#include <stdlib.h>#include <string.h>#include <sys/mman.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/ioctl.h>#include <cutils/ashmem.h>#include <cutils/log.h>#include <cutils/atomic.h>#include <hardware/hardware.h>#include <hardware/gralloc.h>#include "gralloc_priv.h"#include "gr.h"/*****************************************************************************/struct gralloc_context_t { alloc_device_t device; /* our private data here */};static int gralloc_alloc_buffer(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle);/*****************************************************************************/int fb_device_open(const hw_module_t* module, const char* name, hw_device_t** device);static int gralloc_device_open(const hw_module_t* module, const char* name, hw_device_t** device);extern int gralloc_lock(gralloc_module_t const* module, buffer_handle_t handle, int usage, int l, int t, int w, int h, void** vaddr);extern int gralloc_unlock(gralloc_module_t const* module, buffer_handle_t handle);extern int gralloc_register_buffer(gralloc_module_t const* module, buffer_handle_t handle);extern int gralloc_unregister_buffer(gralloc_module_t const* module, buffer_handle_t handle);/*****************************************************************************///模块被加载后,会执行的open方法,用来打开设备static struct hw_module_methods_t gralloc_module_methods = { open: gralloc_device_open};// 导出符号HMI,是HAL框架编程规范定义的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,};/*****************************************************************************///帧缓冲区锁定后的操作,在帧缓冲区找一个空闲的图形缓冲区,记录到private_handle_t结构中并返回// dev :gralloc设备// size:整个图像所占用的字节数// usage:图形缓冲区位置标志位:fb、内存// pHandle: 图形缓冲区描述符static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle){//将至类型转化,hw_module_t转化为private_module_t 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来描述一个将要分配出去的图形缓冲区 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; } //分配出去的图形缓冲区的基地址保存在private_handle_t的base变量中 hnd->base = vaddr;//相对于帧缓冲区的基地址偏移保存在private_handle_t的offset变量中 hnd->offset = vaddr - intptr_t(m->framebuffer->base);//返回private_handle_t这个图形缓冲区描述符 *pHandle = hnd; return 0;}/*****************************************************************************///1.在帧缓冲区中分配图形缓冲区// dev :gralloc设备// size:整个图像所占用的字节数// usage:图形缓冲区位置标志位:fb、内存// pHandle: 图形缓冲区描述符static int gralloc_alloc_framebuffer(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle){//将至类型转化,hw_module_t转化为private_module_t private_module_t* m = reinterpret_cast<private_module_t*>( dev->common.module);//并发问题加锁 pthread_mutex_lock(&m->lock); int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle); //锁定帧缓冲区后操作 pthread_mutex_unlock(&m->lock); return err;}/*****************************************************************************///2.在内存中分配图形缓冲区// dev :gralloc设备// size:整个图像所占用的字节数// usage:图形缓冲区位置标志位:fb、内存// pHandle: 图形缓冲区描述符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; }//创建成功后,分配一个private_handle_t用来记录图形缓冲区,并返回给调用者 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;}/*****************************************************************************///用来分配图形缓冲区// int w : 图形缓冲区所保存图像的宽度,即一行多少个像素点// int h : 图形缓冲区所保存图像的高度,即一共有多少行// format: 表示图形的格式// usage : 标志位,GRALLOC_USAGE_HW_FB值表示在帧缓冲区中分配图形缓冲区// pHandle: 图形缓冲区句柄,用来描述一个图形缓冲区// pStride: 用来返回一行的像素点个数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_RGBA_5551: case HAL_PIXEL_FORMAT_RGBA_4444: case HAL_PIXEL_FORMAT_RAW_SENSOR: bpp = 2; break; default: return -EINVAL; }//将一行所占的字节数对齐到4个字节,例如:2013对齐到四个字节会变为2016 size_t bpr = (w*bpp + (align-1)) & ~(align-1);//对齐后乘以高度,表示整个图像所占的字节数 size = bpr * h;//stride表示一行的像素点个数 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;}/*****************************************************************************///用来释放图形缓冲区static int gralloc_free(alloc_device_t* dev, buffer_handle_t handle){ if (private_handle_t::validate(handle) < 0) return -EINVAL; private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle);//图形缓冲区在帧缓冲区分配 if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { // free this buffer private_module_t* m = reinterpret_cast<private_module_t*>( dev->common.module);//计算该图形缓冲区的大小 const size_t bufferSize = m->finfo.line_length * m->info.yres; int index = (hnd->base - m->framebuffer->base) / bufferSize;//图形缓冲区使用情况记录到buffer屏蔽位中 m->bufferMask &= ~(1<<index); } else { //图形缓冲区是匿名内存 gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>( dev->common.module);//在mapper.cpp中实现的 terminateBuffer(module, const_cast<private_handle_t*>(hnd)); } close(hnd->fd); delete hnd; return 0;}/*****************************************************************************/static int gralloc_close(struct hw_device_t *dev){ gralloc_context_t* ctx = reinterpret_cast<gralloc_context_t*>(dev); if (ctx) { /* TODO: keep a list of all buffer_handle_t created, and free them * all here. */ free(ctx); } return 0;}//模块的入口函数,用来打开gralloc设备、fb设备int gralloc_device_open(const hw_module_t* module, const char* name, hw_device_t** device){ int status = -EINVAL;//1. 打开gralloc设备 if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) { gralloc_context_t *dev;//对gralloc设备的封装结构 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;//gralloc封装的主要方法gralloc_alloc,用来分配图形缓冲区 dev->device.alloc = gralloc_alloc; dev->device.free = gralloc_free;//设备指针返回给框架层,即封装方法返回给框架层 *device = &dev->device.common; status = 0; } else {//2. 打开fb设备 status = fb_device_open(module, name, device); } return status;}
fb设备
/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include <sys/mman.h>#include <dlfcn.h>#include <cutils/ashmem.h>#include <cutils/log.h>#include <hardware/hardware.h>#include <hardware/gralloc.h>#include <fcntl.h>#include <errno.h>#include <sys/ioctl.h>#include <string.h>#include <stdlib.h>#include <cutils/log.h>#include <cutils/atomic.h>#if HAVE_ANDROID_OS#include <linux/fb.h>#endif#include "gralloc_priv.h"#include "gr.h"/*****************************************************************************/// numbers of buffers for page flipping#define NUM_BUFFERS 2enum { PAGE_FLIP = 0x00000001, LOCKED = 0x00000002};struct fb_context_t { framebuffer_device_t device;};/*****************************************************************************///检查两个图形缓冲区渲染到帧缓冲区的间隔时间是否合法static int fb_setSwapInterval(struct framebuffer_device_t* dev, int interval){ fb_context_t* ctx = (fb_context_t*)dev; if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval) return -EINVAL; // FIXME: implement fb_setSwapInterval return 0;}//设置可以更新的区域,放在fix_var_screeninfo的保留字段当中static int fb_setUpdateRect(struct framebuffer_device_t* dev, int l, int t, int w, int h){ if (((w|h) <= 0) || ((l|t)<0)) return -EINVAL; fb_context_t* ctx = (fb_context_t*)dev; private_module_t* m = reinterpret_cast<private_module_t*>( dev->common.module); m->info.reserved[0] = 0x54445055; // "UPDT"; m->info.reserved[1] = (uint16_t)l | ((uint32_t)t << 16); m->info.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16); return 0;}//用来渲染图形缓冲区数据到系统缓冲区// dev :fb设备// 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;//用哪一个图形缓冲区,不用设置成员变量xoffset的值是因为所有的图形缓冲区的宽度是相等的//根据上面两个参数,设置帧缓冲区中绘制的图形缓冲区 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 memcpy void* 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);//参数1:图形缓冲区的起始地址 参数2:帧缓冲区的起始地址 参数3:一帧图形的大小(字节) 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;}/*疑问: 这里为什么没有指定yoffset来指定系统缓冲区使用哪一个图形缓冲区呢。解答: 原来这里有个模式问题。 1.当虚拟屏幕的图形缓冲区只有一个时,是不支持PAGE_FLIP的, 这时分配的图形缓冲区必然在内存中,而帧缓冲区中输出的只有一个图形缓冲区 2.当虚拟屏幕的图形缓冲区有两个或以上是,才支持PAGE_FLIP, 这是分配的图形缓冲区就在帧缓冲区中,这样帧缓冲区才有选择哪一个输出的问题*//*****************************************************************************///获取帧缓冲区信息,映射到当前进程的虚拟地址空间中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;//通过ioctl获取fb_fix_screeninfo信息 struct fb_fix_screeninfo finfo; if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) return -errno;//通过ioctl获取fb_var_screeninfo信息 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) *///NUM_BUFFERS = 2,虚拟屏容纳两个可见屏,虚拟和可见的宽度值不变,高度前者是后者的整数倍 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"); }//若设置完毕后,若虚拟屏的高度小于可见屏的2倍,那么说明帧缓冲区不支持双图形缓冲区 if (info.yres_virtual < info.yres * 2) { // we need at least 2 for page-flipping info.yres_virtual = info.yres; flags &= ~PAGE_FLIP; ALOGW("page flipping not supported (yres_virtual=%d, requested=%d)", info.yres_virtual, info.yres*2); }//设置成功后再次或者fb_var_screen信息 if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) return -errno;//计算刷新频率,先计算扫描一帧图形需要的时间//每个像素点扫描的时间为pixclock//一共有 ( info.upper_margin + info.lower_margin + info.yres ) * ( info.left_margin + info.right_margin + info.xres ) 个像素点 uint64_t refreshQuotient = ( uint64_t( info.upper_margin + info.lower_margin + info.yres ) * ( info.left_margin + info.right_margin + info.xres ) * info.pixclock ); //求倒数得到1s钟能刷新的次数 /* 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;//默认60HZ if (refreshRate == 0) { // bleagh, bad info from the driver refreshRate = 60*1000; // 60 Hz }//dpi默认 160 if (int(info.width) <= 0 || int(info.height) <= 0) { // the driver doesn't return that information // default to 160 dpi info.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);//分配描述符并记录到模块中,private_handle_t中的framebuffer结构用来描述帧缓冲区 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; }//private_handle_t中的framebuffer结构中记录帧缓冲区的基址 module->framebuffer->base = intptr_t(vaddr); memset(vaddr, 0, fbSize); return 0;}static int mapFrameBuffer(struct private_module_t* module){//针对多线程并发问题加锁 pthread_mutex_lock(&module->lock); int err = mapFrameBufferLocked(module); pthread_mutex_unlock(&module->lock); return err;}/*****************************************************************************/static int fb_close(struct hw_device_t *dev){ fb_context_t* ctx = (fb_context_t*)dev; if (ctx) { free(ctx); } return 0;}//fb设备的打开函数//module : 用来描述模块的//name : 打开哪一个fb设备文件//device : 用来描述设备的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设备的抽象封装结构 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; //获取帧缓冲区信息,并保存到m中 private_module_t* m = (private_module_t*)module; status = mapFrameBuffer(m);//根据帧缓冲区信息来初始化alloc_device_t相关的结构 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模块
/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include <limits.h>#include <errno.h>#include <pthread.h>#include <unistd.h>#include <string.h>#include <sys/mman.h>#include <sys/stat.h>#include <sys/types.h>#include <cutils/log.h>#include <cutils/atomic.h>#include <hardware/hardware.h>#include <hardware/gralloc.h>#include "gralloc_priv.h"/* desktop Linux needs a little help with gettid() */#if defined(ARCH_X86) && !defined(HAVE_ANDROID_OS)#define __KERNEL__# include <linux/unistd.h>pid_t gettid() { return syscall(__NR_gettid);}#undef __KERNEL__#endif/*****************************************************************************///图形缓冲区的映射static int gralloc_map(gralloc_module_t const* module, buffer_handle_t handle, void** vaddr){ private_handle_t* hnd = (private_handle_t*)handle;//在内存中分配的话,需要映射到进程虚拟地址空间中,并需要计算图形缓冲区的在匿名内存中的基地址再返回 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { size_t size = hnd->size; void* mappedAddress = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0); if (mappedAddress == MAP_FAILED) { ALOGE("Could not mmap %s", strerror(errno)); return -errno; } hnd->base = intptr_t(mappedAddress) + hnd->offset; //ALOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p", // hnd->fd, hnd->offset, hnd->size, mappedAddress); }//在帧缓冲区中分配的话,是不需要计算的,因为在初始化帧缓冲区时已经做了 *vaddr = (void*)hnd->base; return 0;}static int gralloc_unmap(gralloc_module_t const* module, buffer_handle_t handle){ private_handle_t* hnd = (private_handle_t*)handle;//内存中 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { void* base = (void*)hnd->base; size_t size = hnd->size; //ALOGD("unmapping from %p, size=%d", base, size);//注销图形缓冲区,与上面函数执行过程相反 if (munmap(base, size) < 0) { ALOGE("Could not unmap %s", strerror(errno)); } }//帧缓冲区中 hnd->base = 0; return 0;}/*****************************************************************************/static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER; /*****************************************************************************/// 关键调用gralloc_mapint gralloc_register_buffer(gralloc_module_t const* module, buffer_handle_t handle){ if (private_handle_t::validate(handle) < 0) return -EINVAL; // if this handle was created in this process, then we keep it as is. int err = 0; private_handle_t* hnd = (private_handle_t*)handle; if (hnd->pid != getpid()) { void *vaddr; err = gralloc_map(module, handle, &vaddr); } return err;}// 关键调用gralloc_unmapint gralloc_unregister_buffer(gralloc_module_t const* module, buffer_handle_t handle){ if (private_handle_t::validate(handle) < 0) return -EINVAL; // never unmap buffers that were created in this process private_handle_t* hnd = (private_handle_t*)handle; if (hnd->pid != getpid()) { if (hnd->base) { gralloc_unmap(module, handle); } } return 0;}int mapBuffer(gralloc_module_t const* module, private_handle_t* hnd){ void* vaddr; return gralloc_map(module, hnd, &vaddr);}int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd){ if (hnd->base) { // this buffer was mapped, unmap it now gralloc_unmap(module, hnd); } return 0;}//图形缓冲区的锁定int gralloc_lock(gralloc_module_t const* module, buffer_handle_t handle, int usage, int l, int t, int w, int h, void** vaddr){ // this is called when a buffer is being locked for software // access. in thin implementation we have nothing to do since // not synchronization with the h/w is needed. // typically this is used to wait for the h/w to finish with // this buffer if relevant. the data cache may need to be // flushed or invalidated depending on the usage bits and the // hardware. if (private_handle_t::validate(handle) < 0) return -EINVAL;//检测参数并返回帧缓冲区的基址,锁定操作并没有实现,需要调用者实现 private_handle_t* hnd = (private_handle_t*)handle; *vaddr = (void*)hnd->base; return 0;}//图形缓冲区的解锁定int gralloc_unlock(gralloc_module_t const* module, buffer_handle_t handle){ // we're done with a software buffer. nothing to do in this // implementation. typically this is used to flush the data cache.//解锁操作没实现,交给调用者实现 if (private_handle_t::validate(handle) < 0) return -EINVAL; return 0;}
总结
经过详细的分析发现,分配图形缓冲区和映射过程是有重叠逻辑的,在分配的过程中就需要做映射操作;还有帧缓冲区初始化时,也会有映射操作。只不过Gralloc模块单独将映射过程封装出来了,即提供register_gralloc_buffer给调用者,用来映射图形缓冲区到进程的虚拟地址空间。
总体上,Gralloc模块还是提供了这三种抽象功能:分配、映射、渲染。其中gralloc设备打开过程,为调用者返回了gralloc_alloc方法;fb设备打开过程,获取了帧缓冲区的信息、并初始化了虚拟显示屏,同时映射了帧缓冲区,并返回了渲染方法fb_post。而gralloc模块,提供了register_gralloc_buffer方法给调用者用来映射。
参考:http://www.myexception.cn/image/1442367.html
0 0
- Android Gralloc模块分析--深入分析
- Android Gralloc模块分析
- android gralloc 流程分析
- android gralloc 流程分析
- android gralloc 流程分析
- android的gralloc分析
- android gralloc 流程分析
- android gralloc 流程分析
- Android Gralloc 流程分析
- Android HAL层分析 (gralloc显示模块 举例)
- 转android gralloc流程分析for msm8960
- 转android gralloc流程分析for msm8960
- 转android gralloc流程分析for msm8960
- android gralloc流程分析for msm8960
- Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析
- Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析
- Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析
- Android帧缓冲区(Frame Buffer)硬件抽象层(HAL) 模块Gralloc的实现原理分析
- 警惕!iPhone 6即将上市 诈骗邮件已现身网络
- java跳出多重循环
- hdu 3766 Knight's Trip
- android基础笔记:显示意图并传递简单参数
- UVA 10474 - Where is the Marble?
- Android Gralloc模块分析--深入分析
- keychain应用
- 对hibernate懒加载的理解
- git命令
- 【代码备忘】VC判断自己窗口的另一种方法
- 上学的时候Java写的打字练习
- import 语句的模块顺序
- HWOJ-字符串运用-密码截取
- 数据库范式(1NF 2NF 3NF BCNF)详解一