07.显示系统:第004课_SurfaceFlinger内部机制:第006节_APP申请(lock)Buffer的过程_获得buffer信息

前面我们分析了:

		/*使用代理类,发起跨进程的远程调用,向SurfaceFlinger发起buf申请,导致对方分配内存*/
		status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,reqWidth, reqHeight, reqFormat, reqUsage);
		/*先向SurfaceFlinger请求,得到返回文件句柄fd,然后在APP边mmap*/
		result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);

中的mGraphicBufferProducer->requestBuffer通过远程调用如何获取buf,在IGraphicBufferProducer.cpp文件中,找到:

class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
	virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
		/*构建数据*/
		data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
        data.writeInt32(bufferIdx);
        /*发起远程调用*/
        status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
        bool nonNull = reply.readInt32();
        /*如果返回结果没问题*/
        if (nonNull) {
            *buf = new GraphicBuffer();
            result = reply.read(**buf);
            if(result != NO_ERROR) {
                (*buf).clear();
                return result;
            }
        }
        

发起远程调用,会导致BnGraphicBufferProducer中的onTransact被调用,在IGraphicBufferProducer.cpp文件找到onTransact函数:

status_t BnGraphicBufferProducer::onTransact(
	/*调用其派生类的requestBuffer,获得sp<GraphicBuffer> buffer;*/
	int result = requestBuffer(bufferIdx, &buffer);
	/*写入binder驱动,最终传递给应用程序*/
	reply->write(*buffer);

一个写入binder,一个从binder读出,简单的框图如下:
在这里插入图片描述

首先我们来看看,其是如何写入的:

status_t BnGraphicBufferProducer::onTransact(
	/*写入binder驱动,最终传递给应用程序*/
	reply->write(*buffer);

进入Parcel.cpp文件:

status_t Parcel::write(const FlattenableHelperInterface& val)
	/*确定文件句柄有多少个*/
	const size_t fd_count = val.getFdCount();
	/*该处val为sp<GraphicBuffer> buffer;*/
	err = val.flatten(buf, len, fds, fd_count);

我们找到GraphicBuffer.cpp中的flatten函数,

status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
	/*把一些重要的信息填写到buf中*/
	......
	buf[0] = 'GBFR';
    buf[1] = width;
    buf[6] = static_cast<int32_t>(mId >> 32);
    buf[7] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
    buf[8] = static_cast<int32_t>(mGenerationNumber);
    ......
	

填充之后通过binder写入。

现在我们来看看读的这边:

class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
	virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
        result = reply.read(**buf);

其中read函数也是也是在Parcel.cpp文件中实现:

status_t Parcel::read(FlattenableHelperInterface& val) const
	err = val.unflatten(buf, len, fds, fd_count);

其上的unflatten在GraphicBuffer.cpp中实现,与flatten相对应,主要对接收的数据进行判断,使用fd构建一个handle等等:

扫描二维码关注公众号,回复: 5708201 查看本文章
status_t GraphicBuffer::unflatten(
	status_t err = mBufferMapper.registerBuffer(this);
		
	

handle中还包含了一个虚拟地址,通过 mBufferMapper.registerBuffer(this)获得。registerBuffer主要是使用fd,然后进行memap,获得虚拟地址。

前面分析应用程序中lock主要会调用一下几个个函数:
在这里插入图片描述
当他申请完buf之后,会执行:

sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
status_t res = backBuffer->lockAsync(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,newDirtyRegion.bounds(), &vaddr, fenceFd);

我们看看lockAsync如何得到 &vaddr虚拟地址:

status_t res = backBuffer->lockAsync(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,newDirtyRegion.bounds(), &vaddr, fenceFd);
	status_t res = getBufferMapper().lockAsync(handle, inUsage, rect, vaddr,fenceFd);
	   gralloc1_error_t error = mDevice->lock(handle,static_cast<gralloc1_producer_usage_t>(usage),static_cast<gralloc1_consumer_usage_t>(usage),&accessRegion, vaddr, fence);    

这样lock函数的分析过程就完成了。

猜你喜欢

转载自blog.csdn.net/weixin_43013761/article/details/88893686