博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android中native_handle private_handle_t ANativeWindowBuffer ANativeWindow GraphicBuffer Surface的关系
阅读量:4155 次
发布时间:2019-05-25

本文共 11253 字,大约阅读时间需要 37 分钟。

在阅读SurfaceFlinger HardwareComposer以及gralloc相关代码的过程中,我们经常会遇到native_handle private_handle_t ANativeWindowBuffer ANativeWindow GraphicBuffer Surface等等一系列和memory相关的struct和class,他们相互之间到底是什么区别,又有什么联系呢?本文从struct/class的结构角度分析下上述类型之间的关联.

    概括来说,native_handle private_handle_t ANativeWindowBuffer GraphicBuffer这四个struct/class所描述的是一块memory,而ANativeWindow 和Surface所描述的是一系列上述memeory的组合和对buffer的操作方法.有的struct/class在比较低的level使用,和平台相关,而另外一些在比较高的level使用,和平台无关,还有一些介于低/高level之间,用以消除平台相关性,让android可以方便的运行在不同的平台上.

    我们依次来看下上述struct/class的定义:

1. native_handle 

system/core/include/cutils/native_handle.h

[cpp]   
  1. typedef struct native_handle  
  2. {  
  3.     int version;        /* sizeof(native_handle_t) */  
  4.     int numFds;         /* number of file-descriptors at &data[0] */  
  5.     int numInts;        /* number of ints at &data[numFds] */  
  6.     int data[0];        /* numFds + numInts ints */  
  7. } native_handle_t;  

    native_handle/native_handle_t只是定义了一个描述buffer的结构体原型,这个原型是和平台无关的,方便buffer在各个进程之间传递,注意成员data是一个大小为0的数组,这意味着data指向紧挨着numInts后面的一个地址.我们可以把native_handle_t看成是一个纯虚的基类.

    一般来说,我们描述一块buffer,需要知道它在kernel中对应的fd,虚拟地址/物理地址,offset,size等等信息,后面我们在private_handle_t中就可以看到这些字段.

    android的gralloc模块负责从fb设备或者gpu中分配meomory,所以我们在gralloc中就可以找到native_handle的具体实现,gralloc中对buffer的描述就和具体的平台相关了,我们以aosp中最基本的gralloc为例,来看下gralloc中对native_handle是如何使用的.

2.private_handle_t

hardware/libhardware/modules/gralloc/gralloc_priv.h

[cpp]   
  1. #ifdef __cplusplus  
  2. //在c++编译环境下private_handle_t继承于native_handle  
  3. struct private_handle_t : public native_handle {  
  4. #else  
  5. //在c编译环境下,private_handle_t的第一个成员是native_handle类型,其实和c++的继承是一个意思,  
  6. //总之就是一个指向private_handle_t的指针同样也可以表示一个指向native_handle的指针.  
  7. struct private_handle_t {  
  8.     struct native_handle nativeHandle;  
  9. #endif  
  10.     // file-descriptors  
  11.     int     fd;   
  12.     // ints  
  13.     int     magic;  
  14.     int     flags;  
  15.     int     size;  
  16.     int     offset;  
  17.     // 因为native_handle的data成员是一个大小为0的数组,所以data[0]其实就是指向了fd,data[1]指向magic,以此类推.  
  18.     // 上面提到我们可以把native_handle看成是一个纯虚的基类,那么在private_handle_t这个派生类中,numFds=1 numInts=4.  
  19.     ...  
  20. }  
    gralloc分配的buffer都可以用一个private_handle_t来描述,同时也可以用一个native_handle来描述.在不同的平台的实现上,private_handle_t可能会有不同的定义,所以private_handle_t在各个模块之间传递的时候很不方便,而如果用native_handle的身份来传递,就可以消除平台的差异性.在HardwareComposer中,由SurfaceFlinger传给hwc的handle即是native_handle类型,而hwc作为平台相关的模块,他需要知道native_handle中各个字段的具体含义,所以hwc往往会将native_handle指针转化为private_handle_t指针来使用.


3. buffer_handle_t

    标题中并没有提到这个类型,因为这个类型实在是太简单了,我们看code

system/core/include/system/window.h

[cpp]   
  1. typedef const native_handle_t* buffer_handle_t;  
    在window.h中又把指向native_handle_t的指针define为buffer_handle_t,

sturct native_handle

native_handle_t

struct private_handle_t

这三个类型可以看作是同一个东西,而buffer_handle_t则是指向他们的指针.

    那么android是如何使用这些struct的,gralloc分配的buffer如何和android联系起来呢?

我们继续来看window.h

4. ANativeWindowBuffer和ANativeWindow

    在具体分析ANativeWindowBuffer和ANativeWindow之前,我们先来看下和这两个类型都相关的另外一个结构体android_native_base_t

system/core/include/system/window.h

[cpp]   
  1. typedef struct android_native_base_t  
  2. {  
  3.     /* a magic value defined by the actual EGL native type */  
  4.     int magic;  
  5.   
  6.     /* the sizeof() of the actual EGL native type */  
  7.     int version;  
  8.   
  9.     void* reserved[4];  
  10.   
  11.     /* reference-counting interface */  
  12.     void (*incRef)(struct android_native_base_t* base);  
  13.     void (*decRef)(struct android_native_base_t* base);  
  14. } android_native_base_t;  
incRef和decRef是为了把派生类和android所有class的老祖宗RefBase联系起来所预留的函数指针,在后面我们在会看到指针具体会指向哪些函数.

[cpp]   
  1. typedef struct ANativeWindowBuffer  
  2. {  
  3. #ifdef __cplusplus  
  4.     ANativeWindowBuffer() {  
  5.         // ANDROID_NATIVE_BUFFER_MAGIC的值是"_bfr"  
  6.         common.magic = ANDROID_NATIVE_BUFFER_MAGIC;  
  7.         common.version = sizeof(ANativeWindowBuffer);  
  8.         memset(common.reserved, 0, sizeof(common.reserved));  
  9.     }     
  10.   
  11.     // Implement the methods that sp<ANativeWindowBuffer> expects so that it  
  12.     // can be used to automatically refcount ANativeWindowBuffer's.  
  13.     // 调用common,也就是android_native_base_t的incRef和decRef函数,具体函数是什么还不知道  
  14.     void incStrong(const void/*id*/const {  
  15.         common.incRef(const_cast<android_native_base_t*>(&common));  
  16.     }     
  17.     void decStrong(const void/*id*/const {  
  18.         common.decRef(const_cast<android_native_base_t*>(&common));  
  19.     }     
  20. #endif  
  21.   
  22.     // common的incRef和decRef还没有明确是什么  
  23.    struct android_native_base_t common;  
  24.   
  25.     int width;  
  26.     int height;  
  27.     int stride;  
  28.     int format;  
  29.     int usage;  
  30.   
  31.     void* reserved[2];  
  32.     // buffer_handle_t是指向sturct native_handle, native_handle_t, struct private_handle_t的指针.  
  33.     buffer_handle_t handle;  
  34.   
  35.     void* reserved_proc[8];  
  36. } ANativeWindowBuffer_t;  
  37. // Old typedef for backwards compatibility.  
  38. typedef ANativeWindowBuffer_t android_native_buffer_t;  
ANativeWindow的定义如下

[cpp]   
  1. struct ANativeWindow  
  2. {  
  3. #ifdef __cplusplus  
  4.     ANativeWindow()  
  5.         : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0)  
  6.     {  
  7.         // ANDROID_NATIVE_WINDOW_MAGIC的值是"_wnd"  
  8.         common.magic = ANDROID_NATIVE_WINDOW_MAGIC;  
  9.         common.version = sizeof(ANativeWindow);  
  10.         memset(common.reserved, 0, sizeof(common.reserved));  
  11.     }  
  12.   
  13.     /* Implement the methods that sp<ANativeWindow> expects so that it 
  14.        can be used to automatically refcount ANativeWindow's. */  
  15.     // 调用common,也就是android_native_base_t的incRef和decRef函数,具体函数是什么还不知道  
  16.     void incStrong(const void/*id*/const {  
  17.         common.incRef(const_cast<android_native_base_t*>(&common));  
  18.     }  
  19.     void decStrong(const void/*id*/const {  
  20.         common.decRef(const_cast<android_native_base_t*>(&common));  
  21.     }  
  22. #endif  
  23.     // common的incRef和decRef还没有明确是什么  
  24.     struct android_native_base_t common;  
  25.     ...  
  26.     int     (*dequeueBuffer)(struct ANativeWindow* window,  
  27.                 struct ANativeWindowBuffer** buffer, int* fenceFd);  
  28.     int     (*queueBuffer)(struct ANativeWindow* window,  
  29.                 struct ANativeWindowBuffer* buffer, int fenceFd);  
  30.     int     (*cancelBuffer)(struct ANativeWindow* window,  
  31.                 struct ANativeWindowBuffer* buffer, int fenceFd);  
  32. };  
  33.  /* Backwards compatibility: use ANativeWindow (struct ANativeWindow in C). 
  34.   * android_native_window_t is deprecated. 
  35.   */  
  36. typedef struct ANativeWindow ANativeWindow;  
  37. typedef struct ANativeWindow android_native_window_t __deprecated;  
我们目前需要注意的是ANativeWindow的函数指针成员所指向的函数都需要一个struct ANativeWindowBuffer* buffer的参数.

ANativeWindowBuffer和ANativeWindow还是没有给android_native_base_t的incRef和decRef指针赋值,ANativeWindowBuffer和ANativeWindow两个还是可以理解为抽象类!

5. GraphicBuffer和Surface

frameworks/native/include/ui/GraphicBuffer.h 

[cpp]   
  1. class GraphicBuffer  
  2.     : public ANativeObjectBase< ANativeWindowBuffer, GraphicBuffer, RefBase >,  
  3.       public Flattenable<GraphicBuffer>  
  4. {  
  5. ...  
  6. }  
GraphicBuffer继承于模版类ANativeObjectBase,这个模版类有三个模版.

frameworks/native/include/ui/ANativeObjectBase.h

[cpp]   
  1. // NATIVE_TYPE=ANativeWindowBuffer TYPE=GraphicBuffer REF=RefBase  
  2. template <typename NATIVE_TYPE, typename TYPE, typename REF>  
  3. // ANativeObjectBase多重继承于ANativeWindowBuffer和RefBase  
  4. class ANativeObjectBase : public NATIVE_TYPE, public REF   
  5. {  
  6. public:  
  7.     // Disambiguate between the incStrong in REF and NATIVE_TYPE  
  8.     // incStrong和decStrong直接调用其中一个基类RefBase的对应函数  
  9.     void incStrong(const void* id) const {  
  10.         REF::incStrong(id);  
  11.     }     
  12.     void decStrong(const void* id) const {  
  13.         REF::decStrong(id);  
  14.     }     
  15.   
  16. protected:  
  17.     // 给ANativeObjectBase取了个别名BASE  
  18.     typedef ANativeObjectBase<NATIVE_TYPE, TYPE, REF> BASE;  
  19.     ANativeObjectBase() : NATIVE_TYPE(), REF() {  
  20.         // 构造函数中给ANativeWindowBuffer.common的两个函数指针赋值了!这两个指针就是我们之前在分析ANativeWindowBuffer的时候悬而未决的地方.  
  21.         // incRef和decRef指针分别指向内部函数incRef和decRef  
  22.         NATIVE_TYPE::common.incRef = incRef;  
  23.         NATIVE_TYPE::common.decRef = decRef;  
  24.     }     
  25.     static inline TYPE* getSelf(NATIVE_TYPE* self) {  
  26.         return static_cast<TYPE*>(self);  
  27.     }     
  28.     static inline TYPE const* getSelf(NATIVE_TYPE const* self) {  
  29.         return static_cast<TYPE const *>(self);  
  30.     }     
  31.     static inline TYPE* getSelf(android_native_base_t* base) {  
  32.         return getSelf(reinterpret_cast<NATIVE_TYPE*>(base));  
  33.     }     
  34.     static inline TYPE const * getSelf(android_native_base_t const* base) {  
  35.         return getSelf(reinterpret_cast<NATIVE_TYPE const*>(base));  
  36.     }  
  37.     // 内部函数incRef和decRef调用上面的incStong和decStrong,也就是说ANativeWindowBuffer.common的两个函数指针最终会调用到RefBase的incStrong和decStrong.  
  38.     static void incRef(android_native_base_t* base) {  
  39.         ANativeObjectBase* self = getSelf(base);  
  40.         self->incStrong(self);  
  41.     }     
  42.     static void decRef(android_native_base_t* base) {  
  43.         ANativeObjectBase* self = getSelf(base);  
  44.         self->decStrong(self);  
  45.     }   
  46. };  
    搞了半天,原来GraphicBuffer就是ANativeWindowBuffer一种具体实现,把ANativeWindowBuffer的common成员的两个函数指针incRef decRef指向了GraphicBuffer的另一个基类RefBase的incStrong和decStrong,而ANativeWindowBuffer无非就是把buffer_handle_t包了一层.我们看下另外一个从ANativeObjectBase派生的类,他就是大名鼎鼎的,Surface!

frameworks/native/include/gui/Surface.h

[cpp]   
  1. class Surface  
  2.     : public ANativeObjectBase<ANativeWindow, Surface, RefBase>  
  3. {  
  4.     enum { NUM_BUFFER_SLOTS = BufferQueue::NUM_BUFFER_SLOTS };  
  5.     ...  
  6.     struct BufferSlot {  
  7.         sp<GraphicBuffer> buffer;  
  8.         Region dirtyRegion;  
  9.     };  
  10.     // mSlots stores the buffers that have been allocated for each buffer slot.  
  11.     // It is initialized to null pointers, and gets filled in with the result of  
  12.     // IGraphicBufferProducer::requestBuffer when the client dequeues a buffer from a  
  13.     // slot that has not yet been used. The buffer allocated to a slot will also  
  14.     // be replaced if the requested buffer usage or geometry differs from that  
  15.     // of the buffer allocated to a slot.  
  16.     BufferSlot mSlots[NUM_BUFFER_SLOTS];  
  17.     ...  
  18. }  

    Surface和GraphicBuffer都继承自模版类ANativeObjectBase,他使用的三个模版是ANativeWindow, Surface, RefBase,关于incRef和decRef两个函数指针的指向问题和上面GraphicBuffer是完全相同的, 这里就不赘述了.我们需要注意的是Surface有一个BufferSlot类型的成员数组mSlots,BufferSlot是GraphicBuffer的包装,所以我们可以理解为每个Surface中都有一个大小为NUM_BUFFER_SLOTS的GraphicBuffer数组.

    因为Surface继承自ANativeWindow,所以Surface需要实现ANativeWindow中定义的一些接口,这些实现在Surface的构造函数中:

frameworks/native/libs/gui/Surface.cpp

[cpp]   
  1. Surface::Surface(  
  2.         const sp<IGraphicBufferProducer>& bufferProducer,  
  3.         bool controlledByApp)  
  4.     : mGraphicBufferProducer(bufferProducer)  
  5. {  
  6.     // Initialize the ANativeWindow function pointers.  
  7.     ANativeWindow::setSwapInterval  = hook_setSwapInterval;  
  8.     ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;  
  9.     ANativeWindow::cancelBuffer     = hook_cancelBuffer;  
  10.     ANativeWindow::queueBuffer      = hook_queueBuffer;  
  11.     ANativeWindow::query            = hook_query;  
  12.     ANativeWindow::perform          = hook_perform;  
  13.   
  14.     ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;  
  15.     ANativeWindow::cancelBuffer_DEPRECATED  = hook_cancelBuffer_DEPRECATED;  
  16.     ANativeWindow::lockBuffer_DEPRECATED    = hook_lockBuffer_DEPRECATED;  
  17.     ANativeWindow::queueBuffer_DEPRECATED   = hook_queueBuffer_DEPRECATED;  
  18.   
  19.     const_cast<int&>(ANativeWindow::minSwapInterval) = 0;  
  20.     const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;  
  21. }  
ANativeWindow定义的这些接口有什么用呢?谁会来call这些函数呢?举个例子来看.我们在EGL的api中可以找到eglCreateWindowSurface这个函数的定义:

frameworks/native/opengl/libs/EGL/eglApi.cpp

[cpp]   
  1. EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,  
  2.                                     NativeWindowType window,  
  3.                                     const EGLint *attrib_list)  
  4. {  
  5.     ...  
  6. }  
注意其中一个参数NativeWindowType window,这个NativeWindowType又是什么呢?

frameworks/native/opengl/include/EGL/eglplatform.h

[cpp]   
  1. typedef struct ANativeWindow*           EGLNativeWindowType;  
  2. typedef EGLNativeWindowType  NativeWindowType;  
原来NativeWindowType在Android环境下,就是ANativeWindow*,也就是Surface*!


总结一下,

native_handle/native_handle_t是private_handle_t的抽象表示方法,消除平台相关性,方便private_handle_t所表示的memory信息在android各个层次之间传递.而buffer_handle_t是指向他们的指针.

ANativeWindowBuffer将buffer_handle_t进行了包装,ANativeWindow和ANativeWindowBuffer都继承于android_native_base_t,定义了common.incRef和common.decRef两个函数指针,但是并没有为函数指针赋值,所以ANativeWindow和ANativeWindowBuffer仍然是抽象类.

GraphicBuffer和Surface通过继承模版类ANativeObjectBase并指定其中一个模版是RefBase,为incRef和decRef两个指针分别赋值为RefBase的incStrong和decStrong,这样

GraphicBuffer继承了ANativeWindowBuffer,Surface继承了ANativeWindow,并且两者都具有的和RefBase同样的incStong decStrong成员函数.

Surface的成员BufferSlot mSlots[NUM_BUFFER_SLOTS];可以看作是sp<GraphicBuffer>类型的数组,也就是说每个Surface中都包含有NUM_BUFFER_SLOTS个sp<GraphicBuffer>.

转载自:http://blog.csdn.net/ear5cm/article/details/45458683

你可能感兴趣的文章
vue项目打包后无法运行报错空白页面
查看>>
Vue 解决部署到服务器后或者build之后Element UI图标不显示问题(404错误)
查看>>
element-ui全局自定义主题
查看>>
facebook库runtime.js
查看>>
js报错显示subString/subStr is not a function
查看>>
高德地图js API实现鼠标悬浮于点标记时弹出信息窗体显示详情,点击点标记放大地图操作
查看>>
初始化VUE项目报错
查看>>
vue项目使用安装sass
查看>>
在osg场景中使用GLSL语言——一个例子
查看>>
laravel 修改api返回默认的异常处理
查看>>
laravel事务
查看>>
【JavaScript 教程】浏览器—History 对象
查看>>
这才是学习Vite2的正确姿势!
查看>>
7 个适用于所有前端开发人员的很棒API,你需要了解一下
查看>>
20种在学习编程的同时也可以在线赚钱的方法
查看>>
隐藏搜索框:CSS 动画正反向序列
查看>>
【视频教程】Javascript ES6 教程27—ES6 构建一个Promise
查看>>
【5分钟代码练习】01—导航栏鼠标悬停效果的实现
查看>>
127个超级实用的JavaScript 代码片段,你千万要收藏好(中)
查看>>
127个超级实用的JavaScript 代码片段,你千万要收藏好(下)
查看>>