您的位置:首页 > 移动开发 > Android开发

Android GDI共享缓冲区

2013-05-07 10:52 369 查看
1 native_handle_对private_handle_t 的包裹

private_handle_t是gralloc.so使用的本地缓冲区私有的数据结构,而Native_handle_t是上层抽象的可以在进程间传递的数据结构。



numFds=sNumFds=1;

numInts=sNumInts=8;

这个是Parcel中描述句柄的抽象模式。

numFds=1 表示有一个文件句柄:fd/

numInts= 8 表示后面跟了8 个INT 型的数据:magic,flags,size,offset,base,lockState,writeOwner,pid;

在上层系统不要关心buffer_handle_t中data的具体内容。在客户端通过Binder读取readNativeHandle @Parcel.cpp 新生成一个native_handle。

native_handle* Parcel::readNativeHandle() const

{



native_handle* h = native_handle_create(numFds, numInts);

for (int i=0 ; err==NO_ERROR && i

h->data[i] = dup(readFileDescriptor());

if (h->data[i] < 0) err = BAD_VALUE;

}

err = read(h->data + numFds, sizeof(int)*numInts);

….

return h;

}

在构造客户端的native_handle时,对方传递过来的文件句柄处理。由于不在同一个进程中,所以需要dup(…)一下为客户端使用。将Native_handle句柄中的,客户端感兴趣的从服务端复制过来。将Private_native_t 的数据:magic,flags,size,offset,base,lockState,writeOwner,pid;复制到了客户端。客户端利用这个新的Native_buffer被Mapper传回到gralloc.xxx.so 中,获取到native_handle关联的共享缓冲区映射地址,获取到该缓冲区的控制权,达到了客户端和服务端的内存共享。从SurfaceFlinger来看就是作图区域的共享。

2 Graphic Mapper 是干什么的?

服务端(SurfaceFlinger分配了一段内存作为Surface的作图缓冲,客户端怎样在这个作图缓冲区上工作呢?

这个就是Mapper(GraphicBufferMapper)要干的事情。需要利用到两个信息:共享缓冲区设备句柄,分配时的偏移量。

进程1在共享内存设备上预分配了8M的内存。以后所有的分配都是在这个8M的空间进行。对以该文件设备来讲,8M物理内存提交后,就实实在在的占用了8M内存。每个进程都可以共享该8M 的内存。由于在mmap都是用0开始获取映射地址,所有的客户端进程都有了同一个物理起始地址,此时偏移量和size就可以标识一段内存。而偏移量和size是个数值,从服务进程传递到客户端直接就可以使用。



3.GraphicBuffer(缓冲区代理对象)

typedef struct android_native_buffer_t

{

struct android_native_base_t common;

int width;

int height;

int stride;

int format;

int usage;



buffer_handle_t handle;

} android_native_buffer_t;

关系图表:GraphicBuffer :EGLNativeBase :android_native_buffer_t

GraphicBuffer(parcel &)建立本地的GraphicBuffer的数据native_buffer_t。再通过接收对方的传递的native_buffer_t构建GraphicBuffer。

Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)

{int Surface::dequeueBuffer(android_native_buffer_t** buffer)(Surface)

{status_t Surface::getBufferLocked(int index, int usage)

{

sp buffer = s->requestBuffer(index, usage);

{

virtual sp requestBuffer(int bufferIdx, int usage)

{ remote()->transact(REQUEST_BUFFER, data, &reply);

sp buffer = new GraphicBuffer(reply);

Surface::Lock 在Client端建立了一个新的GraphicBuffer对象,该对象通过(1)描述的原理将SurfaceFlinger的buffer_handle_t相关数据构成新的客户端buffer_handle_t数据。在客户端的Surface对象就可以使用GraphicMapper对客户端buffer_handle_t进行mmap从而获取到共享缓冲区的开始地址。

4 总结

Android使用了共享内存的方式来管理与显示相关的缓冲区,他设计成了两层,上层是缓冲区管理的代理机构GraphicBuffer,及其相关的native_buffer_t,下层是具体的缓冲区的分配管理及其缓冲区本身。上层的对象可以通过Binder传递的,而在进程间并不是传递缓冲区本身,而是使用mmap来获取指向共同物理内存的映射地址。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: