关于Android下gralloc,hwcompoer以及surface模块的重新认识
引言
欠债还钱天经地义,知识的债也是如此!这不必须得将我前面欠下来的债给补上!对于任何复杂的知识点,我们都可以采用庖丁解牛的学习方式,一步步的分解。将知识由大到小吃透。虽说Android的graphics图形栈是一个非常负责的模块,但是完事开头难,我们先从基本面入手!
一. allocator service的实现
这里我只能无力的吐糟下Android为了所谓的system,vendor隔离,搞了一个HIDL,这可苦了我们这些搞Android的。这里我以最简单的alloctaor 2.0来作为参考,简单介绍其实现!
1.1 . allocator 2.0 service代码结构
这个比较简单,我们直接上代码!
//hardware/interfaces/graphics/allocator/2.0
├── Android.bp
├── default
│ ├── Android.bp
│ ├── android.hardware.graphics.allocator@2.0-service.rc
│ ├── OWNERS
│ ├── passthrough.cpp
│ └── service.cpp
├── IAllocator.hal
└── utils├── gralloc1-adapter│ ├── Android.bp│ ├── gralloc1-adapter.cpp│ ├── gralloc1-adapter.h│ ├── Gralloc1On0Adapter.cpp│ └── Gralloc1On0Adapter.h├── hal│ ├── Android.bp│ └── include│ └── allocator-hal│ └── 2.0│ ├── Allocator.h│ └── AllocatorHal.h├── OWNERS└── passthrough├── Android.bp└── include└── allocator-passthrough└── 2.0├── Gralloc0Hal.h├── Gralloc1Hal.h└── GrallocLoader.h11 directories, 20 files
1.2 allocator 2.0 service passthrough方式的实现
这里我们不对细节,做过多的纠缠,我们只梳理其大体框架!
/*** The id of this module*/
#define GRALLOC_HARDWARE_MODULE_ID "gralloc"
/*** Name of the graphics device to open*/#define GRALLOC_HARDWARE_GPU0 "gpu0"//[passthrough.cpp]
HIDL_FETCH_IAllocator(...)GrallocLoader::load() //GrallocLoader.hloadModule()//核心是这个,加载HAL MODLEhw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module)createHal(module)//这里无论是Gralloc1Hal还是Gralloc0Hal最终都会调用 gralloc_open(module, &mDevice)gralloc_open(module, &mDevice)module->methods->open(module, GRALLOC_HARDWARE_GPU0, TO_HW_DEVICE_T_OPEN(device)) //注意这里传递的id为GRALLOC_HARDWARE_GPU0createAllocator(std::move(hal))
这里我们重点需要关心的是,这里hw_get_modul传递的id是GRALLOC_HARDWARE_MODULE_ID!
1.3 allocator HAL的实现
通过前面分析可知,hw_get_module会加载HAL模块,这里我们以Android默认的gralloc实现来说明:
//[hardware/libhardware/modules/gralloc]├── Android.mk
├── framebuffer.cpp
├── gralloc.cpp
├── gralloc_priv.h
├── gr.h
└── mapper.cppstruct private_module_t HAL_MODULE_INFO_SYM = {.base = {.common = {.tag = HARDWARE_MODULE_TAG,.version_major = 1,.version_minor = 0,.id = GRALLOC_HARDWARE_MODULE_ID,//注意这里的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,
};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)) {//allocator的gralloc加载会走次分支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;
}
这里需要注意的是,此时allocator service调用open时候传递下来的id为GRALLOC_HARDWARE_GPU0,这个地方要和后面的composer的open对比来看
1.4 allocator HAL alloc的实现
上面的都是常规操作,下面我们接下来看下 allocator HAL alloc的实现!
//[gralloc.cpp]
static int gralloc_alloc(alloc_device_t* dev,int width, int height, int format, int usage,buffer_handle_t* pHandle, int* pStride)
{...if (usage & GRALLOC_USAGE_HW_FB) {err = gralloc_alloc_framebuffer(dev, size, format, usage, pHandle);} else {err = gralloc_alloc_buffer(dev, size, usage, pHandle);}if (err < 0) {return err;}*pStride = stride;return 0;
}
此时的你是不是蒙圈了!尼玛gralloc_alloc里面又有两个分支:
-
gralloc_alloc_framebuffer
这个分支比较特殊,主要用于GPU合成时候FramebufferSurface使用!然后该buffer在后面就可以用于hwcompower合成使用了。
并且这里注意这里的FramebufferSurface是消费者,当消费者设置了GRALLOC_USAGE_HW_FB后,这个值在其对应的生产者申请buffer类型的时候,会获取到这个usage,然后这个usage就会随着生产者allocat()的调用逻辑,传递到gralloc来了!//[frameworks/native/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp]FramebufferSurface::FramebufferSurface(HWComposer& hwc, DisplayId displayId,const sp<IGraphicBufferConsumer>& consumer,uint32_t maxWidth, uint32_t maxHeight): ConsumerBase(consumer),mDisplayId(displayId),mMaxWidth(maxWidth),mMaxHeight(maxHeight),mCurrentBufferSlot(-1),mCurrentBuffer(),mCurrentFence(Fence::NO_FENCE),mHwc(hwc),mHasPendingRelease(false),mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),mPreviousBuffer() {ALOGV("Creating for display %s", to_string(displayId).c_str());mName = "FramebufferSurface";mConsumer->setConsumerName(mName);mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |//注意这个地方GRALLOC_USAGE_HW_RENDER |GRALLOC_USAGE_HW_COMPOSER);...}
关于这块可以参考博客:
图像显示系统 - SurfaceFlinger GPU合成/CLIENT合成方式 -
gralloc_alloc_buffer
它是基本的,像App的渲染buffer啊,其它的通用buffer,都是通过它alloc的!
二. hwcomposer service的实现
这里我只能无力的吐糟下Android为了所谓的system,vendor隔离,搞了一个HIDL,这可苦了我们这些搞Android的。composer 2.1来作为参考,简单介绍其实现!
2.1 . composer 2.1 service代码结构
这个比较简单,我们直接上代码!
//[hardware/interfaces/graphics/composer/2.1]├── Android.bp
├── default
│ ├── Android.bp
│ ├── android.hardware.graphics.composer@2.1-service.rc
│ ├── OWNERS
│ └── service.cpp
├── IComposerCallback.hal
├── IComposerClient.hal
├── IComposer.hal
├── types.hal
└── utils├── command-buffer│ ├── Android.bp│ └── include│ └── composer-command-buffer│ └── 2.1│ └── ComposerCommandBuffer.h├── hal│ ├── Android.bp│ └── include│ └── composer-hal│ └── 2.1│ ├── ComposerClient.h│ ├── ComposerCommandEngine.h│ ├── Composer.h│ └── ComposerHal.h├── hwc2on1adapter│ ├── Android.bp│ ├── CleanSpec.mk│ ├── HWC2On1Adapter.cpp│ ├── include│ │ └── hwc2on1adapter│ │ ├── HWC2On1Adapter.h│ │ └── MiniFence.h│ └── MiniFence.cpp├── hwc2onfbadapter│ ├── Android.bp│ ├── HWC2OnFbAdapter.cpp│ └── include│ └── hwc2onfbadapter│ └── HWC2OnFbAdapter.h├── OWNERS├── passthrough│ ├── Android.bp│ └── include│ └── composer-passthrough│ └── 2.1│ ├── HwcHal.h│ └── HwcLoader.h└── resources├── Android.bp├── ComposerResources.cpp└── include└── composer-resources└── 2.1└── ComposerResources.h24 directories, 32 files
2.2 composer 2.1 service passthrough方式的实现
这里我们不对细节,做过多的纠缠,我们只梳理其大体框架!
这里有一点需要注意,composer使用Android默认的实现,即不设置ro属性指定!
//[service.cpp]
android::sp<IComposer> composer = HwcLoader::load()//HwcLoader.hloadModule()hw_get_module(HWC_HARDWARE_MODULE_ID, &module)//默认使用,这个分支加载失败hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module)//加载这个分支,和gralloc使用的HAL是同一个模块createHalWithAdapter()openDeviceWithAdapter()adaptGrallocModule(...)module->methods->open(module,GRALLOC_HARDWARE_FB0, TO_HW_DEVICE_T_OPEN(device));createComposer())
这里我需要重点注意的几点:
- composer的默认实现,加载的HAL库的实现是gralloc.default
- 调用HAL下open方法的时候,传递的ID的名称是GRALLOC_HARDWARE_FB0这个是需要和allocator实现区分开来的
2.3 composer 2.1 service HAL的实现
这里的实现,就很简单了。因为这里使用gralloc.default作为composer HAL的实现,只实现了其H2C 1.0。
//[hardware/libhardware/modules/gralloc]├── Android.mk
├── framebuffer.cpp
├── gralloc.cpp
├── gralloc_priv.h
├── gr.h
└── mapper.cppstruct private_module_t HAL_MODULE_INFO_SYM = {.base = {.common = {.tag = HARDWARE_MODULE_TAG,.version_major = 1,.version_minor = 0,.id = GRALLOC_HARDWARE_MODULE_ID,//注意这里的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,
};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)) {....} else {status = fb_device_open(module, name, device);//composer的HAL加载会走次分支}return status;
}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)) {//前面传递进来的id 那么就是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)? (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;
}
三. gralloc和hwcompoer中各种让人眼花缭乱的数据关系
这块之前的花式关系,真的是让人眼花缭乱,不知道是李鬼还是李逵。尼玛,让人不得不一吐为快啊!
3.1 native_handle_t*和buffer_handle_t
其它它们是一个东西,具体的定义如下:
//[system/core/libcutils/include/cutils/native_handle.h]
typedef struct native_handle
{int version; /* sizeof(native_handle_t) */int numFds; /* number of file-descriptors at &data[0] */int numInts; /* number of ints at &data[numFds] */
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wzero-length-array"
#endifint data[0]; /* numFds + numInts ints */
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} native_handle_t;typedef const native_handle_t* buffer_handle_t;
它的源码目录比较奇特,在libcutils里面。这点大家需要注意。
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是如何使用的.
3.2 private_handle_t
我们来看下,Android aosp为我们打样实现的一个private_handle_t,如下:
//[hardware/libhardware/modules/gralloc/gralloc_priv.h]
#ifdef __cplusplus
//在c++编译环境下private_handle_t继承于native_handle
struct private_handle_t : public native_handle {
#else
//在c编译环境下,private_handle_t的第一个成员是native_handle类型,其实和c++的继承是一个意思,
//总之就是一个指向private_handle_t的指针同样也可以表示一个指向native_handle的指针.
struct private_handle_t { struct native_handle nativeHandle;
#endif // file-descriptors int fd; // ints int magic; int flags; int size; int offset; // 因为native_handle的data成员是一个大小为0的数组,所以data[0]其实就是指向了fd,data[1]指向magic,以此类推. // 上面提到我们可以把native_handle看成是一个纯虚的基类,那么在private_handle_t这个派生类中,numFds=1 numInts=4. ...
}
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.3 小结
对于native_handle和native_handle_t,以及private_handle_t这三个类型可以看作是同一个东西,而buffer_handle_t则是指向他们的指针.
那么android是如何使用这些struct的,gralloc分配的buffer如何和android联系起来呢?我们继续来看window.h
3.4 ANativeWindowBuffer和ANativeWindow
在具体分析ANativeWindowBuffer和ANativeWindow之前,我们先来看下和这两个类型都相关的另外一个结构体android_native_base_t。
[frameworks/native/libs/nativebase/include/nativebase/nativebase.h]typedef struct android_native_base_t
{/* a magic value defined by the actual EGL native type */int magic;/* the sizeof() of the actual EGL native type */int version;void* reserved[4];/* reference-counting interface */void (*incRef)(struct android_native_base_t* base);void (*decRef)(struct android_native_base_t* base);
} android_native_base_t;
这里的incRef和decRef是为了把派生类和android所有class的老祖宗RefBase联系起来所预留的函数指针,在后面我们在会看到指针具体会指向哪些函数.
好了,前面该说的也已经说了。是时候亮出看家本领了,我们直接来看ANativeWindowBuffer。
ANativeWindowBuffer:
[frameworks/native/libs/nativebase/include/nativebase/nativebase.h]typedef struct ANativeWindowBuffer{#ifdef __cplusplusANativeWindowBuffer() {// ANDROID_NATIVE_BUFFER_MAGIC的值是"_bfr" common.magic = ANDROID_NATIVE_BUFFER_MAGIC;common.version = sizeof(ANativeWindowBuffer);memset(common.reserved, 0, sizeof(common.reserved));}// Implement the methods that sp<ANativeWindowBuffer> expects so that it// can be used to automatically refcount ANativeWindowBuffer's.// 调用common,也就是android_native_base_t的incRef和decRef函数void incStrong(const void* /*id*/) const {common.incRef(const_cast<android_native_base_t*>(&common));}void decStrong(const void* /*id*/) const {common.decRef(const_cast<android_native_base_t*>(&common));}#endif// common的incRef和decRef struct android_native_base_t common;int width;int height;int stride;int format;int usage_deprecated;uintptr_t layerCount;void* reserved[1];const native_handle_t* handle;uint64_t usage;// we needed extra space for storing the 64-bits usage flags// the number of slots to use from reserved_proc depends on the// architecture.void* reserved_proc[8 - (sizeof(uint64_t) / sizeof(void*))];} ANativeWindowBuffer_t;typedef struct ANativeWindowBuffer ANativeWindowBuffer;// Old typedef for backwards compatibility.typedef ANativeWindowBuffer_t android_native_buffer_t;**==ANativeWindow==** 的定义如下:[frameworks/native/libs/nativewindow/include/system/window.h]
struct ANativeWindow
{
#ifdef __cplusplusANativeWindow(): flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0){common.magic = ANDROID_NATIVE_WINDOW_MAGIC;common.version = sizeof(ANativeWindow);memset(common.reserved, 0, sizeof(common.reserved));}/* Implement the methods that sp<ANativeWindow> expects so that itcan be used to automatically refcount ANativeWindow's. */void incStrong(const void* /*id*/) const {common.incRef(const_cast<android_native_base_t*>(&common));}void decStrong(const void* /*id*/) const {common.decRef(const_cast<android_native_base_t*>(&common));}
#endifstruct android_native_base_t common;const uint32_t flags;const int minSwapInterval;const int maxSwapInterval;const float xdpi;const float ydpi;intptr_t oem[4];int (*setSwapInterval)(struct ANativeWindow* window,int interval);int (*dequeueBuffer_DEPRECATED)(struct ANativeWindow* window,struct ANativeWindowBuffer** buffer);int (*lockBuffer_DEPRECATED)(struct ANativeWindow* window,struct ANativeWindowBuffer* buffer);int (*queueBuffer_DEPRECATED)(struct ANativeWindow* window,struct ANativeWindowBuffer* buffer);int (*query)(const struct ANativeWindow* window,int what, int* value);int (*perform)(struct ANativeWindow* window,int operation, ... );int (*cancelBuffer_DEPRECATED)(struct ANativeWindow* window,struct ANativeWindowBuffer* buffer);int (*dequeueBuffer)(struct ANativeWindow* window,struct ANativeWindowBuffer** buffer, int* fenceFd);int (*queueBuffer)(struct ANativeWindow* window,struct ANativeWindowBuffer* buffer, int fenceFd);int (*cancelBuffer)(struct ANativeWindow* window,struct ANativeWindowBuffer* buffer, int fenceFd);
};//没有定义在这里,这里只是为了学习方便
[frameworks/native/libs/nativewindow/include/android/native_window.h]
typedef struct ANativeWindow ANativeWindow;
我们目前需要注意的是ANativeWindow的函数指针成员所指向的函数都需要一个struct ANativeWindowBuffer* buffer的参数.
ANativeWindowBuffer和ANativeWindow还是没有给android_native_base_t的incRef和decRef指针赋值,ANativeWindowBuffer和ANativeWindow两个还是可以理解为抽象类!
3.5 GraphicBuffer和Surface
前面我们认知了ANativeWindow和ANativeWindowBuffer,接下来也让我们揭开GraphicBuffer和Surface的庐山真面目。
frameworks/native/libs/ui/include/ui/GraphicBuffer.h]
class GraphicBuffer: public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase>,public Flattenable<GraphicBuffer>
{...
}
GraphicBuffer继承于模板类模版类ANativeObjectBase,这个模版类有三个模版.它的定义如下:
[frameworks/native/libs/ui/include/ui/ANativeObjectBase.h]
// NATIVE_TYPE=ANativeWindowBuffer TYPE=GraphicBuffer REF=RefBase
template <typename NATIVE_TYPE, typename TYPE, typename REF>
// ANativeObjectBase多重继承于ANativeWindowBuffer和RefBase
class ANativeObjectBase : public NATIVE_TYPE, public REF
{
public: // Disambiguate between the incStrong in REF and NATIVE_TYPE // incStrong和decStrong直接调用其中一个基类RefBase的对应函数 void incStrong(const void* id) const { REF::incStrong(id); } void decStrong(const void* id) const { REF::decStrong(id); } protected: // 给ANativeObjectBase取了个别名BASE typedef ANativeObjectBase<NATIVE_TYPE, TYPE, REF> BASE; ANativeObjectBase() : NATIVE_TYPE(), REF() { // 构造函数中给ANativeWindowBuffer.common的两个函数指针赋值了!这两个指针就是我们之前在分析ANativeWindowBuffer的时候悬而未决的地方. // incRef和decRef指针分别指向内部函数incRef和decRef NATIVE_TYPE::common.incRef = incRef; NATIVE_TYPE::common.decRef = decRef; } static inline TYPE* getSelf(NATIVE_TYPE* self) { return static_cast<TYPE*>(self); } static inline TYPE const* getSelf(NATIVE_TYPE const* self) { return static_cast<TYPE const *>(self); } static inline TYPE* getSelf(android_native_base_t* base) { return getSelf(reinterpret_cast<NATIVE_TYPE*>(base)); } static inline TYPE const * getSelf(android_native_base_t const* base) { return getSelf(reinterpret_cast<NATIVE_TYPE const*>(base)); } // 内部函数incRef和decRef调用上面的incStong和decStrong,也就是说ANativeWindowBuffer.common的两个函数指针最终会调用到RefBase的incStrong和decStrong. static void incRef(android_native_base_t* base) { ANativeObjectBase* self = getSelf(base); self->incStrong(self); } static void decRef(android_native_base_t* base) { ANativeObjectBase* self = getSelf(base); self->decStrong(self); }
};
搞了半天,原来GraphicBuffer就是ANativeWindowBuffer一种具体实现,把ANativeWindowBuffer的common成员的两个函数指针incRef decRef指向了GraphicBuffer的另一个基类RefBase的incStrong和decStrong,而ANativeWindowBuffer无非就是把buffer_handle_t包了一层.
我们看下另外一个从ANativeObjectBase派生的类,他就是大名鼎鼎的,Surface!它的定义如下:
class Surface : public ANativeObjectBase<ANativeWindow, Surface, RefBase>
{ enum { NUM_BUFFER_SLOTS = BufferQueue::NUM_BUFFER_SLOTS }; ... struct BufferSlot { sp<GraphicBuffer> buffer; Region dirtyRegion; }; // mSlots stores the buffers that have been allocated for each buffer slot. // It is initialized to null pointers, and gets filled in with the result of // IGraphicBufferProducer::requestBuffer when the client dequeues a buffer from a // slot that has not yet been used. The buffer allocated to a slot will also // be replaced if the requested buffer usage or geometry differs from that // of the buffer allocated to a slot. BufferSlot mSlots[NUM_BUFFER_SLOTS]; ...
}
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]
Surface::Surface( const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp) : mGraphicBufferProducer(bufferProducer)
{ // Initialize the ANativeWindow function pointers. ANativeWindow::setSwapInterval = hook_setSwapInterval; ANativeWindow::dequeueBuffer = hook_dequeueBuffer; ANativeWindow::cancelBuffer = hook_cancelBuffer; ANativeWindow::queueBuffer = hook_queueBuffer; ANativeWindow::query = hook_query; ANativeWindow::perform = hook_perform; ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED; ANativeWindow::cancelBuffer_DEPRECATED = hook_cancelBuffer_DEPRECATED; ANativeWindow::lockBuffer_DEPRECATED = hook_lockBuffer_DEPRECATED; ANativeWindow::queueBuffer_DEPRECATED = hook_queueBuffer_DEPRECATED; const_cast<int&>(ANativeWindow::minSwapInterval) = 0; const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
}
ANativeWindow定义的这些接口有什么用呢?谁会来call这些函数呢?举个例子来看.我们在EGL的api中可以找到eglCreateWindowSurface这个函数的定义:
[frameworks/native/opengl/libs/EGL/eglApi.cpp]EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list)
{ ...
}
注意其中一个参数NativeWindowType window,这个NativeWindowType又是什么呢?
[frameworks/native/opengl/include/EGL/eglplatform.h]
typedef struct ANativeWindow* EGLNativeWindowType;
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类型的数组,也就是说每个Surface中都包含有NUM_BUFFER_SLOTS个sp.
关于ANativeWindow的使用方法,我们可以在SurfaceFlinger中找到一个很好的列子,就是SF的captureScreen接口。
3.6 关于GraphicBuffer和Surface牵涉的各种数据结构小结
通过上述的一通咔咔学习,我们在以后的SurfaceFlinger HardWare Composer以及gralloc相关代码的学习过程中,native_handle private_handle_t ANativeWindowBuffer ANativeWindow GraphicBuffer Surface等等一系列和memory相关的struct和class,他们相互之间到底是什么区别,又有什么联系呢,我们应该已经很清楚了。
概括来说native_handle,private_handle_t,ANativeWindowBuffer,GraphicBuffer这四个struct/class所描述的是一块memory。而ANativeWindow和Surface所描述的是一系列上述memeofy的组合和对buffer的操作方法,有的struct/class在比较低的level使用,和平台有关,而另外一些在比较高的level使用和平台无关,还有一些介于低/高level之间,用以消除平台相关性,让android可以方便运行在不同的平台上。
写在最后
好了今天的博客关于Android下gralloc,hwcompoer以及surface模块的重新认识就到这里了。总之,青山不改绿水长流先到这里了。如果本博客对你有所帮助,麻烦关注或者点个赞,如果觉得很烂也可以踩一脚!谢谢各位了!!