Android显示系统 SF内部机制 06 应用端request buffer过程
上节讲了分配buffer的过程,如果发现某个slot的buffer需要重新分配,
则使用mGraphicBufferProducer->requestBuffer(buf, &gbuf);远程调用来更新重新分配的buffer的信息,
下面分析requestBuffer
Surface::lock => Surface::dequeueBuffer里面会:
mGraphicBufferProducer->dequeueBuffer();
if(NEEDS_REALLOCATION)mGraphicBufferProducer->requestBuffer(buf, &gbuf);
看看代理类做的事情:
if(NEEDS_REALLOCATION)mGraphicBufferProducer->requestBuffer(buf, &gbuf);
//native/libs/gui/IGraphicBufferProducer.cpp
class BpGraphicBufferProducer : public BpInterface
{
public:
virtual status_t requestBuffer(int bufferIdx, sp* buf) {
Parcel data, reply;
data.writeInt32(bufferIdx);
remote()->transact(REQUEST_BUFFER, data, &reply);
bool nonNull = reply.readInt32();
if(nonNull) {
//创建GraphicBuffer实例化对象,使用返回结构来构造这个对象
*buf = new GraphicBuffer();
result = reply.read(**buf);
}
}
}
//natvie/libs/gui/BufferQueueProducer.cpp
status_t BufferQueueProducer::requestBuffer(int slot, sp* buf) {
mSlots[slot].mRequestBufferCalled = true;
*buf = mSlots[slot].mGraphicBuffer;
}
这导致BnGraphicBufferProducer的onTransact被调用,
里面会解析Parcel,然后调用派生类的requestBuffer(bufferIdx, &buffer);
再reply->write(*buffer); //这个buffer是sp
猜测它怎么写:
应该是SF端写fd,AP端读出fd',binder驱动帮助转换了这个fd,
看看怎么做的l,看Parcel的reply->write();
//native/libs/binder/Parcel.cpp
status_t Parcel::write(const FlattenableHelperInterface& val)
{
//确定fd个数
const size_t fd_count = vla.getFdCount();
void* const buf = this->writeInplace(pad_size(len));
//value就是传进去的GraphicBuffer。看看它是否实现了flatten
err = val.flatten(buf, len. fds, fd_count);
}
//native/libs/ui/GraphicBuffer.cpp
//把buf的数据扁平化,通过binder传给AP
status_t GraphicBuffer::flatten(void*& buffer, size_t& szie, int*&fds, size_t& count) const {
int32_t* buf = static_cast(buffer);
buf[0] = 'GBFR';
buf[1] = width;
buf[....
if(handle) {
memcpy(fds, handle->data, static_cast(handle->numFds) * sizeof(int));
memcpy(&buf[11], handle->data + handle->numFds, static_cast(handle->numInts) * sizeof(int));
}
}
接着,AP需要把数据读出来,reply.read(**buf);
通过Parcel::read,会走到GraphicBufer::unflatten
status_t GraphicBuffer::unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count)
{
//从buf[]拿出width,height等,然后使用fd构造handle
native_handle* h = native_handle_create(static_cast(numFds), static_cast(numInts));
//得到vaddr,它肯定是mmap(fd')获得虚拟地址
//它走的应该是mAllocModule->requestBuffer,但是android7没看到,
mBufferMapper.registerBuffer(this);
}
AP端使用fd'构造handle,handle里面除了fd还有个vaddr,如何得到?
对于Gralloc.cpp,gralloc_register_buffer()会返回gralloc_mmap(module, handle, &vaddr);
我们的gralloc_register_buffer()里面试一次s3gOpenAllocation,
mmap得到的值vaddr放在handle->base里面,
所以这里的mmap,对我们的GPU来说,就是一次openAllocation,open也没有返回vaddr,怎么办?
而且这里open了一次,ref_cnt要加1的
Surface->lock()中,Surface->dequeueBuffer做完了,就要调用backBuffer->lockAsync()了,
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 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& 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();
}
看看lockAsync()如何得到刚刚mmap的地址vaddr
//native/libs/ui/GraphicBuffer.cpp
status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect,
void** vaddr, int fenceFd)
{
getBufferMapper().lockAsync(handle, inUsage, rect, vaddr, fenceFd);
}
//native/libs/ui/GraphicBufferMapper.cpp
status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle,
usage, const Rect& bounds, void** vaddr, int fenceFd)
{
gralloc1_error_t error = mDevice->lock(handle,
static_cast(usage),
static_castvirt_addr就行了