韦东山 笔记
04, AP申请buffer的过程,lock
AP显示界面需要用到SF的服务,
1,SF端用client表示要使用界面的APP,
2,AP端创建Surface,SF端对应Layer,Layer有生产者和消费者,
Surface里有mGraphicBufferProducer,它是一个代理类,指向SF端的Layer的生产者,所以AP端可以使用生产者的所有函数
Surface里还有mSlots,Layer的生产者也有个mCore和mSlots[64],它是BufferSlot类型
3,要获得Surface中的Buffer,才可以填数据,
猜想,AP如何获得Surface中的buffer?
1,AP端查看mSlots是否有空余项目,(其实并没做这个步骤)
2,没有的话,向SF端生产者申请,在SF端:
生产者也要查看自己的mSlots中有无空余项,
若没有就向Gralloc HAL申请,就是向Ashmem申请得到一个fd,返回给AP,
3,通过binder,AP端获得fd',mmap获得地址(通过Gralloc HAL来mmap)
做了图,在create_client的A4步骤
这节分析surface->lock();
关键点:
1,SF端分配buffer,
2,SF端返回fd
3,AP端mmap
看代码,慕课网讲过这里
Surface->lock(&outBuffer, NULL);
//framewok/native/libs/gui/Surface.cpp
status_t Surface::lock(
ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
{
ANativeWindowBuffer* out;
int fenceFd = -1;
//取出的buffer放在out里面
status_t err = dequeueBuffer(&out, &fenceFd);
//记得慕课网讲过,GraphicBuffer继承自ANativeWindowBuffer所以可以这么用
//backBuffer是绘制的那个buffer,准备好后提交,它就变为frontBuffer了
sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
status res = backBuffer->lockAsync(GRALLOC_YSAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, ..,&vaddr, fenceFd);
mLockedBuffer = backBuffer;
outBuffer->format = backBuffer->format;
//Surface_test就是往这里面写
outBuffer->bits = vaddr;
}
看看DequeueBuffer的实现
//framewok/native/libs/gui/Surface.cpp
int Surface::dequeueBuffer(android_natgive_buffer_t** buffer, int* fenceFd) {
int buf = -1;
//buf是int型,这里dequeue返回的是数组的下标:mSlots[],表明这个数组项对应的GraphicBuffer已经被分配,
//使用mGraphicBufferProducer代理类发起跨进程binder远程调用,
//1,向SF发出buffer申请,导致对方allocate buffer=
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, reqWidth,...,reqFormat, reqUsage);
sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
if((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
//,2,向SF请求返回fd,然后在AP端mmap
result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
}
*buffer = gbuf.get();
}
下节分析SurfaceFlinger端,native服务端的代码
==============================
05,surface->lock过程,分配buffer
AP调用lock,发起mGraphicBufferProducer->dequeueBuffer,然后发起binder远程调用,所以它并没有查看自己的mSlots有无空余项,
反查IGraphicBufferProducer,
好像接口写在AP端,和代理类在一起?看到BnGraphicBuuferProducer也在这里,
//framework/natvei/libs/gui/IGraphicBufferProducer.cpp
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
{
virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, uint32_t with, PixelFormat format, uint32_t usage) {
Parcel data, reply;
data.writeInterfaceToken();
data.writeUint32(width);
....
data.writeUint32(usage);
//填好Parcel的data,发起binder远程调用,
status_t result = remote()->trasact(DEQUEUE_BUFFER, data, &reply);
*buf = reply.readInt32();
*fence = new Fence();
reply.read(**fence);
result = reply.readInt32();
}
}
//framework/natvei/libs/gui/IGraphicBufferProducer.cpp
status_t BnGraphicBufferProducer::onTransact(uint32_t code, const Parcel& data, ....)
{
switch(code) {
uint32_t width = data.readUint32();
....
int buf = 0;
sp<Fence> fence;
//是派生类BufferQueueProducer的函数
int result = dequeueBuffer(&buf, &fence, width, ...);
reply->writeInt32(bif);
reply->write(*fence);
reply->writeInt32(result);
}
}
为什么派生类是BufferQueueProducer?
//naitve/include/gui/BufferQueueProducer.h
class BufferQueueProducer : public BnGraphicBufferProducer,...
//native/libs/gui/BufferQueueProducer.cpp
status_t BufferQueueProducer::dequeueBuffer(int *outSlot, sp<Android::Fence> *outFence, ...) {
while(found == BufferItem::INVALID_BUFFER_SLOT) {
//1,等待空闲slot,然后relock,也就是看看有没有空闲的slot,
status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue, &found);
}
const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
//,2,检查是否需要重新alloc,比如第一次申请buffer时slots的第0项一定是空闲的,而且没有被分配buffer,
if( (buffer == NULL) || buffer->needsReallocation(width, heifth, foramt, usage))
{
mCore->mBufferAge = 0;
returnFlags |= BUFFER_NEEDS_REALLCATION;
} else {
//we add 1 because that will be the frame number when this buffer is queued
mCore->mBufferAge = mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
}
BQ_LOGV("dequeueBuffer: setting buffer age to %"PRIu64, mCore->mBufferAge);
if(returnFlags & BUFFER_NEEDS_REALLOCATION) {
BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
//,3,分配buffer,mCore是BufferQueueCore,生产者和消费者都会指向同一个mCore,
//mAllocator是谁?
sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
width, height, foramt, suage,
{mConsumerName.string(), mConsumerName.size()}, &error));
{
}
}
}
mAllocator是谁?在前面看BufferQueueCore的时候看过:
1,看看BufferQueueCore
//framework/native/libs/gui/BufferQueueCore.cpp
BufferQueueCore::BufferQueueCore(const sp<IGraphicBuferAlloc>& allocator) :
mAllocator(allocator),
mBufferAge(0),
....
{
if(allocator == NULL) {
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
//后面分析buffer的分配的时候再看它
//sp<IGraphicBufferAlloc> mAllocator
mAllocator = composer->createGraphicBufferAlloc();
}
}
看看mCore->mAllocator->createGraphicBuffer(),
IGraphicBufferAlloc.cpp的BpGraphicBufferAlloc的createGraphicBuffer填parcel,
然后remote->onTransact发起binder调用,
BnGraphicBufferAlloc的onTransact接收到,通过code调用派生类的createGraphicBuffer,
//native/include/gui/GraphicBufferAlloc.h
class GraphicBufferAlloc : public BnGraphicBufferAlloc {
}
//native/libs/gui/GraphicBufferAlloc.cpp
sp<GraphicBuffer> GraphicBufferAlooc::createGraphicBuffer(uint32_t w,...usage, *error) {
sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h ,foramt, usage));
}
看看new GraphicBuffer做了什么
//framework/native/libs/ui/GraphicBuffer.cpp
GraphicBufer::GraphicBuffer(uint inWidth,....,inUsage, std::string requestorName)
{
mInitCheck = initSize(inWidth, inHeigth, inFormat, inUsage, std::move(requestorName));
}
//framework/native/libs/ui/GraphicBuffer.cpp
status_t GraphicBuffer::initSize(uint32_t inWidth,...)
{
//这里是GraphicBufferAllocator,前面是GraphicBufferAlloc
//这个构造函数打开gralloc
GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
//这里就是通过gralloc分配内存的地方
status_t err = allocator.allocate(inWidth, inHeight,...., &handle, &outStride, ...);
}
看看哪里用了hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
cnw_init in cnativewindow.c (E:\p4vcode\sw\s3gdrv\code\s3driverSDK\libhardware\tests\hwc) : if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) != 0) {
cnw_init in cnativewindow.c (libhardware\tests\hwc) : if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) != 0) {
arc::GrallocFrameBuffer::GrallocFrameBuffer in frame_buffer.cpp (libhardware\modules\camera\3_4\arc) : int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
android::Gralloc1::Loader::Loader in Gralloc1.cpp (E:\p4vcode\sw\s3gdrv\code\s3driverSDK\native\libs\ui) : int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
hwc_s3g_init in hwc_s3g.c (E:\p4vcode\sw\s3gdrv\code\s3driverSDK\hwcomposer) : if(hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &gralloc) == 0)
hwc_s3g_init in hwc_s3g.c (hwcomposer) : if(hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &gralloc) == 0)
视频里面说是GraphicBufferAllocator的构造函数做的,这里没做,可能是ZX改的?还是Android版本问题?
接着看看GraphicBufferAllocator::allocate
//native/libs/ui/GraphicBufferAllocator.cpp
status_t GraphicBufferAllocator::allocate(uint32_t width...., buffer_handle_t *handle, ...., uint64_t graphicBufferid,..)
{
auto descriptor = mDevice->createDescriptor();
error = mDevice->allocate(descriptor, graphicBufferId, handle);
}
然后会进入Gralloc.cpp,我们是gralloc_s3g.c
//gralloc/gralloc_s3g.c
static struct hw_module_methods_t gralloc_module_methods = {
.open = grallc_device_open
};
static int gralloc_device_open(const hw_module_t* module, const char* name, hw_devic_t** device)
{
gralloc_s3g_t *s3g = (gralloc_s3g_t *)module;
gralloc_info("Load Module gralloc: %02d.%02d.%02d%s\n",DRIVER_MAJOR, DRIVER_MINOR, DRIVER_PATCHLEVEL, DRIVER_BRANCH);
if(!strcmp(name, GRALLOC_HARDWARE_GPU0))
{
alloc_dev_s3g_t *s3g_dev = calloc(1, sizeof(*s3g_dev));
s3g_dev->base.alloc = gralloc_alloc;
//这里拿了s3g,它是在gralloc_s3g_init()填的,
//里面填了s3g->base.common,还有s3g->base.registerBuffer\lock等
s3g_dev->s3g = s3g;
*device = &s3g_dev->base.common;
}
}
//看看gralloc_alloc
static int gralloc_alloc(alloc_device_t* dev, int w, h,format,usage, buffer_handle_t* pHandle, int* pStride)
{
alloc_dev_s3g_t *s3g_dev = (alloc_dev_s3g_t *)dev;
gralloc_s3g_t *s3g = s3g_dev->s3g;
native_buffer_s3g_t *buf = NULL;
{
s3g_create_allocation_t create;
memset(&create, 0, sizeof(create));
format = SelectHALFormat(format, usage);
create.device = s3g->device;
create.format = HALFormat2S3GFormat(format);
create.usage_mask = Usage2S3GUsage(usage, create.format);
create.tiled = 1; //default try to enable tile, krnl will enable/disable tile accord HW&usage&access_hint;
create.secured = NeedSecured(s3g, usage);
create.scramble = NeedScramble(s3g, usage);
create.fence_sync = NeedFenceSync(s3g. usage);
create.need_hdr = NeedHDR(s3g, usage);
create.lossy_compress = NeedLossyCompress(s3g, usage, w, h, create.format);
create.need_fd = 1;
status = s3gCreateAllocation(s3g->fd, &create);
buf = calloc(1, sizeof(*buf));
buf->fd = create.buffer_fd;
buf->device = create.device;
buf->allocation = crerate.allocation;
buf->format = create.format;
buf->hw_foramt = create_foramt;
buf->gbd = create.gdb;
buf->gvirt_addr = create.gpu_virt_addr;
buf->unpageble = create.unpagable;
buf->fence_addr = create.fence_addr;
buf->sync_obj = create.sync_obj;
.....
}
//buf转换成pHandle返回了出去
*pHandle = (buffer_handle_t)buf;
}
另外看到了gralloc_register_buffer,它是一次s3gOpenAllocation(s3g->fd, &open);
gralloc_lock则对应s3gLockAllocation(s3g->fd, &lock);
回头看android framework,
//native/libs/ui/GraphicBufferAllocator.cpp
GraphicBufferAllocator::GraphicBufferAllocator()
: mLoader(std::make_unique<Gralloc1::Loader>()),
mDevice(mLoader->getDevice()){}
//native/include/ui/GraphicBuferAllocator.h
class GraphicBufferAllocator : public Singleton<GrahpicBufferAllocator>
{
private:
std::unique_ptr<Gralloc1::loader> mloader;
std::unique_ptr<Gralloc1::Device> mDevice;
}
看看Loader的构造函数
//native/libs/ui/Gralloc1.cpp
Loader::Loader()
: mDevice(nullptr)
{
hw_module_t const* module;
//得到module
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
gralloc1_device_t* device = nullptr;
mAdapter = std::make_unique<Gralloc1On0Adapter>(module);
device = mAdapter->getDevice();
mDevice = std::make_unique<Gralloc1::Device>(device);
}
这里GraphicBufferAllocator在构造函数确实拿到了Hwc,叫做mDevice,但是是怎么拿到的?
另外GraphicBufferAllocator::allocate在调用mDevice->allocate(),与graloc_s3g里面的alloc的函数名和参数个数都对不上,这是同一个函数吗?怎么调过去的?
继续看韦东山的视频,它看的是/libhardware/modules/gralloc/Gralloc.cpp
gralloc_alloc里面会根据 usage&GRALLOC_USAGE_HW_FB选择走
gralloc_alloc_framrbuffer()还是
gralloc_alloc_buffer(),与深入理解Android内核思想里面写的一样。
而gralloc_alloc_buffer中:
{
fd = ashmem_create_region(size) //分配size大小的内存,得到文件句柄
private_handle_t* hnd = new private_handle_t(fd, size, 0); //使用文件句柄fd构造handle,
gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(dev->common.module);
mapBuffer(module, hnd);
*pHandle = hnd;
}
mapBuffer() => gralloc_map(module, hnd, &vaddr) =>
void* mappedAddress = mmap(); *vaddr = (void*)hnd->base; //hnd->base就是用mappedAddress算出来的,
所以通过mmap,就得到了应用空间里,可以供CPU使用的virtual addr,
如果通过硬件加速,应该不需要拿到virtual addr?只需要handle就行了?
另外hwui是什么?
https://www.jianshu.com/p/824a9ddf68b9
这个讲了android p的知识,里面有hwc和hwui,优先看
https://blog.youkuaiyun.com/lewif/article/details/50526494
这个是旧一些的android现实系统,次之,
重新看韦东山,
总结:
SurfaceTest,调用surface->lock(&outBuffer)获得buffer,outBuffer是ANativeWIndow_Buffer类型,
lock调用Surface.cpp的mGraphicBufferProducer->dequeueBuffer(&buf, w, h, format, usage,);,这是生产者的代理类,会发起binder远程调用,
SF端的dequeueBuffer被调用:BufferQueueProducer::dequeueBuffer
当有NEED_REALLOCATION时,它通过mCore->mAllocator->createGraphicBuffer()分配内存,
里面allocator.alloc(w,h,foramt,usage,&handle,..)通过gralloc做事情:
通过Ashmem分配buffer,得到fd,
使用fd构造handle,
mmap得到vaddr供SurfaceFlinger自己使用。
看看申请内存后,数据结构的变化
在mGraphicBufferProducer,
生产者有mCore和mSlots[],分配内存就是选择某个空余的slots,然后构造它。
看看mSlots是什么,在BufferQueueProducer.h
//native/include/gui/BufferQueueProducer.h
class BufferQueueProducer : public BnGraphicBuferProducer {
sp<BufferQueueCore> mCore;
//typedef BufferSlots SlotsType[NUM_BUFFER_SLOTS];
BufferQueueDefs::SlotsType& mSlots; //是一个数组的引用
}
看看每项BufferSlots里面有什么东西
他是一个结构体,含有sp<GraphicBuffer> mGraphicBuffer
那么mGraphicBuffer有什么?
它继承自Flattenable
//native/include/ui/GraphicBuffer.h
class GraphicBuffer
: public ANativeObjectBase< ANativeWidnowBuffer, GraphicBuffer, RefBase >,
public Flattenable<GgrahpicBuffer>
{
friend class Flattenable<GraphicBuffer>;
}
GraphicBuffer里面有handle,handle里面有fd,gralloc进行mmap后把地址放到了handle->base里面
所以handle有fd,有base,
而以上都是在SF端,AP不能使用,需要传回去,
AP端的Surface同样有一个mSlots[],也是一个BufferSlot,里面也有GraphicBuffer,GraphicBuffer里也有handle,handle里有fd和base,
现在要构造AP端的某个mSlots,使用result = mGraphicBufferProducer->dequeueBuffer(&buf)这个buf,它是一个下标
这个result等于SF端的BufferQueueProducer的returnFlags,
AP端判断这个result是否有BUFFER_NEEDS_REALLOCATION,
如果有,则使用mGraphicBuferProducer->requestBuffer(buf, &gbuf)远程调用,来获得SF端的slot信息,然后构造自的slot