Android Graphics - 3 BufferQueue 和 Gralloc

3 篇文章 0 订阅
3 篇文章 0 订阅

BufferQueue and gralloc

摘要:BufferQueue生产者和消费者,gralloc HAL使用flags,使用systrace跟踪BufferQueue

让我们从BufferQueue和gralloc HAL的幕后开始来理解Android 图形系统

BufferQueue类是Android图形系统的核心。它的扮演的角色很简单:把生成图形数据的组件(生产者)和接收数据并用来显示或进一步处理的组件(消费者)联系在一起。几乎所有需要在系统种传输图形数据的组件都依赖BufferQueue。

gralloc内存分配器可以执行buffer分配并且通过特定厂商的HAL接口来实现(参考:hardware/libhardware/include/hardware/gralloc.h).alloc() 函数需要除了需要参数(width,height,pixel format)外还需要一组使用标志(细节如下)。

BufferQueue生产者和消费者(BufferQueue producers and consumers)

基础的使用方法是显而易见的:生产者请求一个空闲的buffer(dequeueBuffer()),指定一组包括width,height,pixel format 和使用标志的参数。生产者填充buffer然后将它返回到队列中。稍后,消费者请求buffer(acquireBufferQueue())并且使用这个buffer。当消费者完成任务后,将buffer返回给队列(releaseBuffer())。

近期的Android设备支持同步框架,这使System能够在与能够异步操作图形数据的硬件组件结合时做出漂亮事情。举例来说,一个生产者可以在提交一系列OpenGL ES绘制命令之后,然后在渲染完成前将输出buffer排队。因为和buffer在一起的有一个叫做fence的东西,fence可以在渲染完成时发出信号。第二种伴随buffer的fence是在它返回到空闲列表时,所以消费者可以在内容仍在使用时释放buffer。这种设计改善了buffer在系统种传输时的延迟和吞吐量的问题。

队列的一些特征,例如最大可持有的buffer数由生产者和消费者共同决定。但是BufferQueue负责根据需求分配buffer。除非特征发生变化,否则Buffer将会保留。例如,如果生产者请求不同大小的buffer,老的buffer会被释放,新的buffer将会被分配。

生产者和消费者可以存在于不同的进城。目前,消费者总是创建并拥有数据结构。在老版本的Android平台上,只有生产者端是被绑定的(例如 生产者可以作为一个远程的线程,但是消费者必须存在于queue所在的线程中)。Android 4.4以后,此处的实现朝着更加通用性的方向发展。

BufferQueue绝不会copybuffer的内容(移动如此多的数据会变的效率底下),而是buffer总是通过句柄(handle)传递。

gralloc HAL 使用标志 (gralloc HAL usage flags)

gralloc分配器不仅仅是另外一种在本地堆内存种申请的方法。在某些情况下,分配的内存可能不是缓存一致性的或者完全不能在用户空间访问。分配的性质由使用标志决定,其中包括以下属性:

  • How often the memory will be accessed from software (CPU) CPU访问内存的频率
  • How often the memory will be accessed from hardware (GPU)GPU访问内存的频率
  • Whether the memory will be used as an OpenGL ES (GLES) texture 内存是否被OpenGL ES texture访问
  • Whether the memory will be used by a video encoder 内存是否被Video编解码器使用

举个例子,如果你指定RGBA 8888 像素格式,这意味着你想要一个可以从软件访问的buffer(也就是说你的app会直接访问到每一个像素),那么分配器就必须创建一个按照RGBA排序的4字节每像素的内存。如果你不这样做,而是说想要一个仅从硬件访问并且作为一个GLES texture的时候,分配器可以做任何GLES dirver想要的事情---可能是BGRA排序,非线性旋转布局(non-linear swizzled layouts),可选的颜色格式(alternative color formats)等等。让硬件使用它想要的格式可以提高性能。

某些值不能在特定的平台上组合。例如,视频编解码器请求YUV像素,所以添加软件访问和指定RGBA 8888将会发生错误。

从gralloc分配器返回的buffer句柄可以通过Binder传输。

使用systrace跟踪BufferQueue (Tracking BufferQueue with systrace)

想要了解graphics buffer如何被移动的,使用systrace。systrace可以很好的检测系统级的Graphics代码和很多相关app的framework代码。去完成的描述如何有效的使用systrace将会占用大量的篇幅。从打开gfx,view,sched 标志开始。你也可以在trace里看到BufferQueue。如果你之前使用过systrace,你可能会看到他们,或许你不知道他们是什么。举个例子,如果你在Grafika的“Play video(SurfaceView)”正在运行时抓了一个trace,一列被标示的SurfaceView会告诉你在给定的时间内有多少buffer被排队了。

这个值在app活跃时增加(例如MediaCodec decoder触发帧的渲染),在SurfaceFlinger开始工作消耗buffer时,这个值会降低。当播放30fps的视频时,队列的的值可能变化很小(0~1),因为60fps的显示器可以轻松保持30fps的帧率。(另外请注意,SurfaceFlinger会在有工作的时候唤醒,而不是60次每秒。系统会尽量避免工作并且在屏幕不用刷新时关闭VSYNC)。

如果你切换到Grafika's "Play video(TextureView)"并且抓了一个trace时,你会看到一组符号:com.android.grafika/com.android.grafika.PlayMovieActivity. 这是主UI布局,是另外一个BufferQueue。因为TextureVIew是渲染到UI布局(而不是独立的layer),你会在这看到所有视频驱动的更新。

关于systrace工具,参考:Systrace documentation.

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值