Android显示系统 SurfaceFlinger内部机制 6 应用端request buffer过程

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<IGraphicBUfferProducer>
{
public:
    virtual status_t requestBuffer(int bufferIdx,  sp<GraphicBuffer>* 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<GraphicBuffer>* buf) {
    mSlots[slot].mRequestBufferCalled = true;
    *buf = mSlots[slot].mGraphicBuffer;
}

 

这导致BnGraphicBufferProducer的onTransact被调用,

里面会解析Parcel,然后调用派生类的requestBuffer(bufferIdx, &buffer);

再reply->write(*buffer); //这个buffer是sp<GraphicBuffer> buffer;

 

猜测它怎么写:

应该是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<int32_t*>(buffer);
    buf[0] = 'GBFR';
    buf[1] = width;
    buf[....
    if(handle) {
        memcpy(fds, handle->data, static_cast<size_t>(handle->numFds) * sizeof(int));
        memcpy(&buf[11], handle->data + handle->numFds, static_cast<size_t>(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<int>(numFds), static_cast<int>(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<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();
}

看看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<gralloc1_producer_usage_t>(usage),
        static_cast<gralloc1_consumer_usage_t(usage),
        &accessRegion, vaddr, fence);
}  

  调用我们的gralloc_lock,里面直接返回Buf->virt_addr就行了  

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值