关于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.h
11 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.h
loadModule()//核心是这个,加载HAL MODLE
hw_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_GPU0
createAllocator(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.cpp
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,//注意这里的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.h
24 directories, 32 files
2.2 composer 2.1 service passthrough方式的实现
这里我们不对细节,做过多的纠缠,我们只梳理其大体框架!
这里有一点需要注意,composer使用Android默认的实现,即不设置ro属性指定!
//[service.cpp]
android::sp<IComposer> composer = HwcLoader::load()//HwcLoader.h
loadModule()
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.cpp
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,//注意这里的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"
#endif
int 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 __cplusplus
ANativeWindowBuffer() {
// 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 __cplusplus
ANativeWindow()
: 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 it
can 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));
}
#endif
struct 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可以方便运行在不同的平台上。
文章来源:https://www.toymoban.com/news/detail-830704.html
写在最后
好了今天的博客关于Android下gralloc,hwcompoer以及surface模块的重新认识就到这里了。总之,青山不改绿水长流先到这里了。如果本博客对你有所帮助,麻烦关注或者点个赞,如果觉得很烂也可以踩一脚!谢谢各位了!!文章来源地址https://www.toymoban.com/news/detail-830704.html
到了这里,关于关于Android下gralloc,hwcompoer以及surface模块的重新认识的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!