android Surface(1, 2)
android的Surface相关内容从底层依次往上分别是:
1.frameBuffer,简称fb,对于同一个android系统,可以同时存在多个frameBuffer,本机是fb0,依次外接时,fb1, fb2, ……fbn等。fb文件的目录在类Linux操作系统的dev/目录下,因为一般而言,只有一个显示器。
2.hal层对设备的定义gralloc。
3.FrameBufferNativeWindow。
4.HWCompose。
5.SurfaceFlinger。
6.java层的frameWork。
7.应用。
他们的大致关系图如下所示:
这个图是参考的,在最新的版本中会有一些变动的,比如FrameBufferNativeWindow在新的andori版本已经没有了,被ANativeWindow替换掉了。
1.FrameBuffer
android底层在绘制图形时分为两种方式:
1.CPU为主,GPU为辅。?
2.GPU绘制,CPU为辅。?
其中CPU作为主要角色绘制时,在底层是通过gralloc,framebuffer绘制的,这个过程中CPU为主,GPU为辅。FrameBuffer绘制是使用CPU进行图形绘制和渲染,然后将最终结果存储在内存中的一个FrameBuffer对象中。这种方式虽然简单,但是在绘制复杂图形时会占用大量的CPU资源,导致性能下降。如果是GPU为主进行绘制时,这个过程中,GPU绘制使用GPU进行图形绘制和渲染,最终的结果直接输出到屏幕上。这种方式可以充分利用GPU的性能,提高图形渲染的速度和质量。但是相对于FrameBuffer绘制,GPU绘制需要更加复杂的渲染管线和硬件支持。
但是他们两个不是互相独立的,framebuffer绘制时,也需要GPU参与,GPU绘制时也需要framebuffer参与。
Android系统在硬件抽象层中提供了一个Gralloc模块,封装了对帧缓冲区的所有访问操作。用户空间的应用程序在使用帧缓冲区之间,首先要加载Gralloc模块,并且获得一个gralloc设备和一个fb设备。有了gralloc设备之后,用户空间中的应用程序就可以申请分配一块图形缓冲区,并且将这块图形缓冲区映射到应用程序的地址空间来,以便可以向里面写入要绘制的画面的内容。最后,用户空间中的应用程序就通过fb设备来将已经准备好了的图形缓冲区渲染到帧缓冲区中去,即将图形缓冲区的内容绘制到显示屏中去。相应地,当用户空间中的应用程序不再需要使用一块图形缓冲区的时候,就可以通过gralloc设备来释放它,并且将它从地址空间中解除映射。
这个过程中相关的头文件路径如下:
hardware/libhardware/include/hardware/
其中涉及到的头文件如下:
fb.h 指的就是framebuffer
gralloc.h
hardware.h
对应定义的文件路径如下:
hardware/libhardware/modules/gralloc/
其中涉及到的文件如下:
framebuffer.cpp
gr.h
gralloc.cpp
gralloc_priv.h
mapper.cpp
1.1Hardware
Every hardware module must have a data structure named HAL_MODULE_INFO_SYM and the fields of this data structure must begin with hw_module_t followed by module specific information.
hardware.h文件中主要定义了三个结构体,分别是:
1.hw_module_t
2.hw_module_methods_t
3.hw_device_t
其中hw_module_t定义了一些基本的内容,包括tag,版本,作者,还有hw_module_methods_t。hw_module_methods_t结构体中定义了一个打开设备的方法。hw_device_t中包含hw_module_t,还多了一些其他的变量,还有一个指向关闭设备的指针。
1.2FrameBuffer
framebuffer的头文件中定义了一些内容:
#define GRALLOC_HARDWARE_FB0 "fb0" //这个指的是本机的设备
typedef struct framebuffer_device_t {/*** Common methods of the framebuffer device. This *must* be the first member of* framebuffer_device_t as users of this structure will cast a hw_device_t to* framebuffer_device_t pointer in contexts where it's known the hw_device_t references a* framebuffer_device_t.*/struct hw_device_t common;//这个在hardware.h里面有定义/* 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);//设置更新区域,一般通过framebuffer更新/** 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数据,刷新/** 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;/** convenience API for opening and closing a supported device */static inline int framebuffer_open(const struct hw_module_t* module,struct framebuffer_device_t** device) {return module->methods->open(module,GRALLOC_HARDWARE_FB0, TO_HW_DEVICE_T_OPEN(device));
}static inline int framebuffer_close(struct framebuffer_device_t* device) {return device->common.close(&device->common);
}
总结:
fb.h的头文件中主要定义了framebuffer_device_t这个结构体,framebuffer_device_t结构体中大致如下:hw_device_t,宽高,像素步幅,x方向的像素,y方向的像素,帧率,framebuffer交换间隔,刷新区域。
他的实现文件framebuffer.cpp里面主要解释如下:定义了android设备的buffer数量是2(默认是2),里面有6个函数,分别是:
//设置两个buffer的交换间隔
static int fb_setSwapInterval(struct framebuffer_device_t* dev,int interval)
//往framebuffer里面写数据
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
//映射buffer的数据,并初始化buffer的内容
int mapFrameBufferLocked(struct private_module_t* module, int format)
//带了个锁,里面执行的是mapFrameBufferLocked函数
static int mapFrameBuffer(struct private_module_t* module)
//关闭设备
static int fb_close(struct hw_device_t *dev)
//打开设备
int fb_device_open(hw_module_t const* module, const char* name,hw_device_t** device)
Q1:CPU和GPU是怎么协作的?
2.Gralloc
2.1基本定义
gralloc和Framebuffer是密不可分的。他的头文件主要内容如下:
路径:hardware/libhardware/include/hardware/gralloc.h
主要定义了两个结构体和几个静态方法:
typedef struct gralloc_module_t {struct hw_module_t common;//在hardware.h里面定义的/** 在buffer_handle_t没有被初始化之前调用* (*registerBuffer)() must be called before a buffer_handle_t that has not* been created with (*alloc_device_t::alloc)() can be used.* * This is intended to be used with buffer_handle_t's that have been* received in this process through IPC.* * This function checks that the handle is indeed a valid one and prepares* it for use with (*lock)() and (*unlock)().* * It is not necessary to call (*registerBuffer)() on a handle created * with (*alloc_device_t::alloc)().* * returns an error if this buffer_handle_t is not valid.*/int (*registerBuffer)(struct gralloc_module_t const* module,buffer_handle_t handle);/** (*unregisterBuffer)() is called once this handle is no longer needed in* this process. After this call, it is an error to call (*lock)(),* (*unlock)(), or (*registerBuffer)().* * This function doesn't close or free the handle itself; this is done* by other means, usually through libcutils's native_handle_close() and* native_handle_free(). * * It is an error to call (*unregisterBuffer)() on a buffer that wasn't* explicitly registered first.*/int (*unregisterBuffer)(struct gralloc_module_t const* module,buffer_handle_t handle);//当一个buffer被使用之前调用,会阻塞,比如硬件需要完成渲染或者CPU缓存需要被同步时/** The (*lock)() method is called before a buffer is accessed for the * specified usage. This call may block, for instance if the h/w needs* to finish rendering or if CPU caches need to be synchronized.* * The caller promises to modify only pixels in the area specified * by (l,t,w,h).* * The content of the buffer outside of the specified area is NOT modified* by this call.** If usage specifies GRALLOC_USAGE_SW_*, vaddr is filled with the address* of the buffer in virtual memory.** Note calling (*lock)() on HAL_PIXEL_FORMAT_YCbCr_*_888 buffers will fail* and return -EINVAL. These buffers must be locked with (*lock_ycbcr)()* instead.** THREADING CONSIDERATIONS:** It is legal for several different threads to lock a buffer from * read access, none of the threads are blocked.* * However, locking a buffer simultaneously for write or read/write is* undefined, but:* - shall not result in termination of the process* - shall not block the caller* It is acceptable to return an error or to leave the buffer's content* into an indeterminate state.** If the buffer was created with a usage mask incompatible with the* requested usage flags here, -EINVAL is returned. * */int (*lock)(struct gralloc_module_t const* module,buffer_handle_t handle, int usage,int l, int t, int w, int h,void** vaddr);/** The (*unlock)() method must be called after all changes to the buffer* are completed.*/int (*unlock)(struct gralloc_module_t const* module,buffer_handle_t handle);//留作扩展用/* reserved for future use */int (*perform)(struct gralloc_module_t const* module,int operation, ... );/** 和lock差不多,只不过使用的ycbcr的格式存储的像素之类的数据* The (*lock_ycbcr)() method is like the (*lock)() method, with the* difference that it fills a struct ycbcr with a description of the buffer* layout, and zeroes out the reserved fields.** If the buffer format is not compatible with a flexible YUV format (e.g.* the buffer layout cannot be represented with the ycbcr struct), it* will return -EINVAL.** This method must work on buffers with HAL_PIXEL_FORMAT_YCbCr_*_888* if supported by the device, as well as with any other format that is* requested by the multimedia codecs when they are configured with a* flexible-YUV-compatible color-format with android native buffers.** Note that this method may also be called on buffers of other formats,* including non-YUV formats.** Added in GRALLOC_MODULE_API_VERSION_0_2.*/int (*lock_ycbcr)(struct gralloc_module_t const* module,buffer_handle_t handle, int usage,int l, int t, int w, int h,struct android_ycbcr *ycbcr);/** 把锁传进去不用让调用者等待结束* The (*lockAsync)() method is like the (*lock)() method except* that the buffer's sync fence object is passed into the lock* call instead of requiring the caller to wait for completion.** The gralloc implementation takes ownership of the fenceFd and* is responsible for closing it when no longer needed.** Added in GRALLOC_MODULE_API_VERSION_0_3.*/int (*lockAsync)(struct gralloc_module_t const* module,buffer_handle_t handle, int usage,int l, int t, int w, int h,void** vaddr, int fenceFd);/** The (*unlockAsync)() method is like the (*unlock)() method* except that a buffer sync fence object is returned from the* lock call, representing the completion of any pending work* performed by the gralloc implementation.** The caller takes ownership of the fenceFd and is responsible* for closing it when no longer needed.** Added in GRALLOC_MODULE_API_VERSION_0_3.*/int (*unlockAsync)(struct gralloc_module_t const* module,buffer_handle_t handle, int* fenceFd);/** The (*lockAsync_ycbcr)() method is like the (*lock_ycbcr)()* method except that the buffer's sync fence object is passed* into the lock call instead of requiring the caller to wait for* completion.** The gralloc implementation takes ownership of the fenceFd and* is responsible for closing it when no longer needed.** Added in GRALLOC_MODULE_API_VERSION_0_3.*/int (*lockAsync_ycbcr)(struct gralloc_module_t const* module,buffer_handle_t handle, int usage,int l, int t, int w, int h,struct android_ycbcr *ycbcr, int fenceFd);/* 获取缓冲区的大小* getTransportSize(..., outNumFds, outNumInts)* This function is mandatory on devices running IMapper2.1 or higher.** Get the transport size of a buffer. An imported buffer handle is a raw* buffer handle with the process-local runtime data appended. This* function, for example, allows a caller to omit the process-local* runtime data at the tail when serializing the imported buffer handle.** Note that a client might or might not omit the process-local runtime* data when sending an imported buffer handle. The mapper must support* both cases on the receiving end.*/int32_t (*getTransportSize)(struct gralloc_module_t const* module, buffer_handle_t handle, uint32_t *outNumFds,uint32_t *outNumInts);/* validateBufferSize(..., w, h, format, usage, stride)* This function is mandatory on devices running IMapper2.1 or higher.** Validate that the buffer can be safely accessed by a caller who assumes* the specified width, height, format, usage, and stride. This must at least validate* that the buffer size is large enough. Validating the buffer against* individual buffer attributes is optional.*/int32_t (*validateBufferSize)(struct gralloc_module_t const* device, buffer_handle_t handle,uint32_t w, uint32_t h, int32_t format, int usage,uint32_t stride);//留作扩展用/* reserved for future use */void* reserved_proc[1];} gralloc_module_t;
下面又定义了另外一个结构体:
/*** Every device data structure must begin with hw_device_t* followed by module specific public methods and attributes.*/typedef struct alloc_device_t {struct hw_device_t common; //在hardware.h里面有定义//分配buffer,返回buffer_handle_t/* * (*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;
总结:
1.gralloc_module_t结构体里面定义了hw_module_t common(hw_module_t 在hardware.h中定义)一个变量,还有注册,取消注册缓冲器,加锁,去锁,常规,yuv分量存储,获取缓冲区大小,校验缓冲区大小的几个方法。
2.alloc_device_t结构体中定义了hw_device_t common(hw_device_t 在hardware.h中定义)一个变量,还有分配,释放buffer的两个指向函数的变量。
后面还有几个静态方法:
/** convenience API for opening and closing a supported device */static inline int gralloc_open(const struct hw_module_t* module, struct alloc_device_t** device) {return module->methods->open(module, GRALLOC_HARDWARE_GPU0, TO_HW_DEVICE_T_OPEN(device));
}static inline int gralloc_close(struct alloc_device_t* device) {return device->common.close(&device->common);
}
上面的是gralloc.h中文件的大概内容,gralloc.cpp的文件路径是hardware/libhardware/modules/gralloc/gralloc.cpp,在gralloc.cpp里面的内容大致如下:
1.定义了一个gralloc_context_t结构体变量,gralloc_context_t结构体里面有一个alloc_device_t。
2.初始化了HAL_MODULE_INFO_SYM这个private_module_t结构体类型的变量,其中private_module_t结构体在同级目录下的gralloc_priv.h中。
为了方便直接查找上下文的代码,这里把他的代码大概罗列一下:
struct gralloc_context_t {alloc_device_t device;/* our private data here */
};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,
};
上述是在gralloc中主要做的两个大的操作。
下面是gralloc_priv.h中定义的两个结构体:
struct private_module_t {gralloc_module_t base;private_handle_t* framebuffer;uint32_t flags;uint32_t numBuffers;uint32_t bufferMask;pthread_mutex_t lock;buffer_handle_t currentBuffer;int pmem_master;void* pmem_master_base;struct fb_var_screeninfo info;struct fb_fix_screeninfo finfo;float xdpi;float ydpi;float fps;
};#ifdef __cplusplus
struct private_handle_t : public native_handle {
#else
struct private_handle_t {struct native_handle nativeHandle;
#endifenum {PRIV_FLAGS_FRAMEBUFFER = 0x00000001};// file-descriptorsint fd;// intsint magic;int flags;int size;int offset;// FIXME: the attributes below should be out-of-lineuint64_t base __attribute__((aligned(8)));int pid;#ifdef __cplusplusstatic inline int sNumInts() {return (((sizeof(private_handle_t) - sizeof(native_handle_t))/sizeof(int)) - sNumFds);}static const int sNumFds = 1;static const int sMagic = 0x3141592;//这里是赋值操作private_handle_t(int fd, int size, int flags) :fd(fd), magic(sMagic), flags(flags), size(size), offset(0),base(0), pid(getpid()){version = sizeof(native_handle);numInts = sNumInts();numFds = sNumFds;}~private_handle_t() {magic = 0;}static int validate(const native_handle* h) {const private_handle_t* hnd = (const private_handle_t*)h;if (!h || h->version != sizeof(native_handle) ||h->numInts != sNumInts() || h->numFds != sNumFds ||hnd->magic != sMagic){ALOGE("invalid gralloc handle (at %p)", h);return -EINVAL;}return 0;}
#endif
};
设备gpu用于分配图形缓冲区,而设备fb用于渲染图形缓冲区;hw_module_t用于描述硬件抽象层Gralloc模块,而hw_device_t则用于描述硬件抽象层Gralloc设备,通过硬件抽象层设备可以找到对应的硬件抽象层模块。
2.2Gralloc打开流程
2.2.1FB打开流程
fb的打开流程如下:
framebuffer_open的最终定义是在gralloc.cpp文件中:
int gralloc_device_open(const hw_module_t* module, const char* name,hw_device_t** device)
{int status = -EINVAL;//if里面是打开GPU的函数,传GPU0,进到函数里面,传frameBuffer,走到else里面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 {//这里是打开framebufferstatus = fb_device_open(module, name, device);}return status;
}
fb_device_open函数定义:
int fb_device_open(hw_module_t const* module, const char* name,hw_device_t** device)
{int status = -EINVAL;//判断打开的是fb设备时,再做操作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;//这里是在处理映射地址,将fb映射到当前进程地址空间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)? (m->info.red.offset ? HAL_PIXEL_FORMAT_BGRA_8888 : 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;} else {free(dev);}}return status;
}
mapFrameBuffer通过锁结构最终申请了一块区域后初始化:
int mapFrameBufferLocked(struct private_module_t* module, int format)
{// 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* To enable page flipping, NUM_BUFFERS should be at least 2.*/info.yres_virtual = info.yres * NUM_BUFFERS;switch (format) {case HAL_PIXEL_FORMAT_RGBA_8888:info.bits_per_pixel = 32;info.red.offset = 0;info.red.length = 8;info.green.offset = 8;info.green.length = 8;info.blue.offset = 16;info.blue.length = 8;break;default:ALOGW("unknown format: %d", format);break;}uint32_t flags = PAGE_FLIP;
#if USE_PAN_DISPLAYif (ioctl(fd, FBIOPAN_DISPLAY, &info) == -1) {ALOGW("FBIOPAN_DISPLAY failed, page flipping not supported");
#elseif (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) {ALOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");
#endifinfo.yres_virtual = info.yres;flags &= ~PAGE_FLIP;}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*/size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual);module->framebuffer = new private_handle_t(dup(fd), fbSize, 0);//设置pagerFlip的缓存数量module->numBuffers = info.yres_virtual / info.yres;module->bufferMask = 0;//通过mmap映射得到一个地址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);//最终把这里空间全部置为0memset(vaddr, 0, fbSize);return 0;
}
2.2.2GPU打开流程
GPU的打开流程在上面已经大概描述过,也是通过gralloc_device_open打开的。函数主要是用来创建一个gralloc_context_t结构体,并且对它的成员变量device进行初始化。结构体gralloc_context_t的成员变量device的类型为gralloc_device_t,它用来描述一个gralloc设备。前面提到,gralloc设备是用来分配和释放图形缓冲区的,这是通过调用它的成员函数alloc和free来实现的。函数gralloc_device_open所打开的gralloc设备的成员函数alloc和free分别被设置为Gralloc模块中的函数gralloc_alloc和gralloc_free。
参考:(133条消息) Android图形显示之硬件抽象层Gralloc_android gralloc_快乐安卓的博客-CSDN博客
Q1: YUV存储图像格式的方式?