06 深入解析surface lock

surface lock

主要用于锁定(获取)一个图像缓冲区,以便应用程序可以直接读取或写入该缓冲区的像素数据。

  1. 调用dequeueBuffer方法从队列中取出一个可用的缓冲区,并将其存储在out参数中
  2. 通过GraphicBuffer::getSelf方法获取到该缓冲区对应的GraphicBuffer对象backBuffer,并根据其宽度和高度构建一个矩形bounds。
  3. 根据传入的inOutDirtyBounds参数(表示脏区域的边界),创建一个新的脏区域newDirtyRegion。如果inOutDirtyBounds为空,则将脏区域设为整个缓冲区的范围。
  4. 调用backBuffer的lockAsync方法,异步地锁定(映射)缓冲区的内存,并将结果存储在vaddr指针中。同时,设置了GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN标志,表示应用程序将频繁地读取和写入缓冲区的像素数据。fenceFd参数用于同步访问缓冲区的操作。
  5. 将锁定的缓冲区信息保存在outBuffer结构体中,包括宽度、高度、步长、格式和像素数据的指针。
status_t Surface::lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds) {
    status_t err = dequeueBuffer(&out, &fenceFd); // 从缓冲区队列中取出一个可用的缓冲区
    if (err == NO_ERROR) {
        sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out)); // 获取该缓冲区对应的GraphicBuffer对象
        const Rect bounds(backBuffer->width, backBuffer->height); // 构建矩形表示缓冲区的范围

        Region newDirtyRegion;
        if (inOutDirtyBounds) {
            newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds)); // 使用传入的脏区域边界创建新的脏区域
            newDirtyRegion.andSelf(bounds); // 将新的脏区域与缓冲区范围取交集
        } else {
            newDirtyRegion.set(bounds); // 如果未指定脏区域边界,则将整个缓冲区设置为脏区域
        }
        mDirtyRegion.orSelf(newDirtyRegion); // 将新的脏区域合并到Surface的脏区域中

        void* vaddr;
        status_t res = backBuffer->lockAsync(
                GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
                newDirtyRegion.bounds(), &vaddr, fenceFd); // 异步锁定(映射)缓冲区的内存

        mLockedBuffer = backBuffer; // 将锁定的缓冲区设置为Surface的当前缓冲区
        outBuffer->width  = backBuffer->width; // 将缓冲区宽度保存在输出结构体中
        outBuffer->height = backBuffer->height; // 将缓冲区高度保存在输出结构体中
        outBuffer->stride = backBuffer->stride; // 将缓冲区步长保存在输出结构体中
        outBuffer->format = backBuffer->format; // 将缓冲区格式保存在输出结构体中
        outBuffer->bits   = vaddr; // 将缓冲区像素数据的指针保存在输出结构体中
    }
}

Surface dequeueBuffer

dequeueBuffer用于从缓冲区队列中取出一个可用的缓冲区,并返回该缓冲区对应的android_native_buffer_t对象和Fence对象的文件描述符。

  1. Surface设置了共享缓冲区模式、自动刷新且当前共享缓冲区不为空,则直接返回共享缓冲区。
  2. 调用mGraphicBufferProducer的dequeueBuffer方法从缓冲区队列中取出一个可用的缓冲区,并获取该缓冲区对应的GraphicBuffer对象。
  3. 该缓冲区需要重新分配或者对应的GraphicBuffer对象为空,调用mGraphicBufferProducer的requestBuffer方法重新请求该缓冲区,并获取新的GraphicBuffer对象。
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
    // 如果Surface设置了共享缓冲区模式、自动刷新且当前共享缓冲区不为空
    if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot != BufferItem::INVALID_BUFFER_SLOT) {
        sp<GraphicBuffer>& gbuf(mSlots[mSharedBufferSlot].buffer); // 获取共享缓冲区对应的GraphicBuffer对象
        if (gbuf != nullptr) { // 如果GraphicBuffer对象不为空
            *buffer = gbuf.get(); // 将android_native_buffer_t对象指针设置为该GraphicBuffer对象
            *fenceFd = -1; // 设置文件描述符为-1,表示没有Fence对象
            return OK; // 返回执行成功
        }
    }

    // 从缓冲区队列中取出一个可用的缓冲区,并返回该缓冲区对应的android_native_buffer_t对象和Fence对象的文件描述符
    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, dqInput.width,
                                                            dqInput.height, dqInput.format,
                                                            dqInput.usage, &mBufferAge,
                                                            dqInput.getTimestamps ?
                                                                    &frameTimestamps : nullptr);

    // 获取该缓冲区对应的GraphicBuffer对象
    sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
    // 如果该缓冲区需要重新分配或者对应的GraphicBuffer对象为空
    if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == nullptr) {
        // 如果需要记录移除的缓冲区,将该GraphicBuffer对象添加到列表中
        if (mReportRemovedBuffers && (gbuf != nullptr)) {
            mRemovedBuffers.push_back(gbuf);
        }
        // 重新请求该缓冲区,并获取新的GraphicBuffer对象
        result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);

    }

    // 将android_native_buffer_t对象指针设置为该缓冲区对应的GraphicBuffer对象
    *buffer = gbuf.get();
    // 将Fence对象的文件描述符保存到输出参数中
    *fenceFd = fence->dup();
    // 将该缓冲区标记为已取出状态
    mDequeuedSlots.insert(buf);
}

总结

总之,Surface::lock主要目的是获取一个可用的图像缓冲区,并锁定该缓冲区以进行读写操作。

还记录了脏区域的边界,并返回缓冲区的相关信息给调用者,以便用户对buffer进行操作。

创作不易,欢迎点赞收藏。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值