注:文章都是通过阅读各位前辈总结的资料、Android 11 Rockchip平台源码、加上自己的思考分析总结出来的,其中难免有理解不对的地方,欢迎大家批评指正。文章为个人学习、研究、欣赏之用,图文内容整理自互联网,如有侵权,请联系删除(◕‿◕),转载请注明出处(©Rockchip ©Android @Linux 版权所有),谢谢。
(==文章基于 Android 11.0==)
正是由于前人的分析和总结,帮助我节约了大量的时间和精力,特别感谢,由于不喜欢图片水印,去除了水印,敬请谅解!!!
==源码(部分)==:
xxx
==源码(部分)==:
一、Native Surface和App Surface创建流程
(1)、App Surface创建步骤
app中Activity回调onCreate(),setContentView最终会走到ViewRootImpl的setView中,然后接收到vSync信号后,会执行relayoutWindow
进一步会请求system_server创建Surface(SurfaceControl)。
走到这里已经到Native 创建Surface了,接下来看看Native Surface创建步骤。
(2)、Native Surface创建步骤
我们这里直接找hwui的一个测试Demo。
Y:\home\zhoujinjian\android11_rockpi4\frameworks\base\libs\hwui\tests\common\TestContext.cpp
Y:\home\zhoujinjian\android11_rockpi4\frameworks\native\libs\gui\SurfaceComposerClient.cpp
SurfaceComposerClient将Surface创建请求转交给保存在其成员变量中的Bp SurfaceComposerClient对象来完成。
Y:\home\zhoujinjian\android11_rockpi4\frameworks\native\libs\gui\ISurfaceComposerClient.cpp
Y:\home\zhoujinjian\android11_rockpi4\frameworks\native\services\surfaceflinger\Client.cpp
通过Binder通信进入SurfaceFlinger创建Layer。
Y:\home\zhoujinjian\android11_rockpi4\frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp
SurfaceFlinger根据标志位创建对应类型的Surface,当前系统定义了4种类型的Layer:
Y:\home\zhoujinjian\android11_rockpi4\frameworks\native\libs\gui\include\gui\ISurfaceComposerClient.h
Y:\home\zhoujinjian\android11_rockpi4\frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp
在SurfaceFlinger服务端为应用程序创建的Surface创建对应的Layer对象。
创建BufferQueueLayer 会首先调用onFirstRef()函数,创建IGraphicBufferProducer,IGraphicBufferConsumer,BufferQueue对象。设置最大setMaxDequeuedBufferCount为2。BufferQueueLayer继承BufferLayer,看看BufferLayer构造函数。
获取CompositionEngine创造对应layer,这个后面用于渲染作用。
看看Log:
Y:\home\zhoujinjian\android11_rockpi4\frameworks\native\services\surfaceflinger\BufferLayer.cpp
上面已经创建好Layer,初始化好了GraphicBufferProducer、GraphicBufferConsumer、
二、BufferQueue内部机制
(1)、BufferQueue介绍
BufferQueue 类是 Android 中所有图形处理操作的核心。它的是将生成图形数据缓冲区的一方(生产者Producer)连接到接受数据以进行显示或进一步处理的一方(消费者Consumer)。几乎所有在系统中移动图形数据缓冲区的内容都依赖于 BufferQueue。
从上图APP与SurfaceFlinger交互中可以看出,BufferQueue内部维持着64个BufferSlot,每一个BufferSlot内部有一个GraphicBuffer指向分配的Graphic Buffer。
先来看一下图中几个状态代表的含义:
1 | frameworks/native/include/gui/BufferSlot.h |
FREE :
FREE表示缓冲区可由生产者(Producer)DEQUEUED出列。 该BufferSlot由BufferQueue“拥有”。 它转换到DEQUEUED
当调用dequeueBuffer时。
DEQUEUED:
DEQUEUED表示缓冲区已经被生产者(Producer)出列,但是尚未queued 或canceled。生产者(Producer)可以修改缓冲区的内容一旦相关的释放围栏被发信号通知。BufferSlot由Producer“拥有”。 它可以转换到QUEUED(通过
queueBuffer或者attachBuffer)或者返回FREE(通过cancelBuffer或者detachBuffer)。
QUEUED:
QUEUED表示缓冲区已经被生产者(Producer)填充排队等待消费者(Consumer)使用。 缓冲区内容可能被继续
修改在有限的时间内,所以内容不能被访问,直到关联的栅栏fence发信号。 该BufferSlot由BufferQueue“拥有”。 它
可以转换为ACQUIRED(通过acquireBuffer)或FREE(如果是另一个缓冲区以异步模式排队)。
ACQUIRED:
ACQUIRED表示缓冲区已被消费者(Consumer)获取。 如与QUEUED,内容不能被消费者访问,直到
获得栅栏fence信号。 BufferSlot由Consumer“拥有”。 它当releaseBuffer(或detachBuffer)被调用时转换为FREE。 一个
分离的缓冲区也可以通过attachBuffer进入ACQUIRED状态。
SHARED:
SHARED表示此缓冲区正在共享缓冲区中使用模式。 它可以同时在其他State的任何组合,
除了FREE (因为这不包括在任何其他State)。 它可以也可以出列,排队或多次获得。
简单描述一下状态转换过程:
1、首先生产者dequeue过来一块Buffer,此时该buffer的状态为DEQUEUED,所有者为PRODUCER,生产者可以填充数据了。在没有dequeue操作时,buffer的状态为free,所有者为BUFFERQUEUE。
2、生产者填充完数据后,进行queue操作,此时buffer的状态由DEQUEUED->QUEUED的转变,buffer所有者也变成了BufferQueue了。
3、上面已经通知消费者去拿buffer了,这个时候消费者就进行acquire操作将buffer拿过来,此时buffer的状态由QUEUED->ACQUIRED转变,buffer的拥有者由BufferQueue变成Consumer。
4、当消费者已经消费了这块buffer(已经合成,已经编码等),就进行release操作释放buffer,将buffer归还给BufferQueue,buffer状态由ACQUIRED变成FREE.buffer拥有者由Consumer变成BufferQueue.
(2)、生产者Producer
生产者Producer实现IGraphicBufferProducer的接口,在实际运作过程中,应用(Client端)存在代理端BpGraphicBufferProducer,SurfaceFlinger(Server端)存在Native端BnGraphicBufferProducer。生产者代理端Bp通过Binder通信,不断的dequeueBuffer和queueBuffer操作,Native端同样响应这些操作请求,这样buffer就转了起来了。
这里介绍几个非常重要的函数:
1、requestBuffer
requestBuffer为给定的索引请求一个新的Buffer。 服务器(即IGraphicBufferProducer实现)分配新创建的Buffer到给定的BufferSlot槽索引,并且客户端可以镜像slot->Buffer映射,这样就没有必要传输一个GraphicBuffer用于每个出队操作。
1 | // requestBuffer requests a new buffer for the given index. The server (i.e. |
2、dequeueBuffer
dequeueBuffer请求一个新的Buffer Slot供客户端使用。 插槽的所有权被转移到客户端,这意味着服务器不会使用与该插槽关联的缓冲区的内容。
1 | // dequeueBuffer requests a new buffer slot for the client to use. Ownership |
3、detachBuffer
detachBuffer尝试删除给定buffer 的所有权插槽从buffer queue。 如果这个请求成功,该slot将会被free,并且将无法从这个接口获得缓冲区。释放的插槽将保持未分配状态,直到被选中为止在dequeueBuffer中保存一个新分配的缓冲区,或者附加一个缓冲区到插槽。 缓冲区必须已经被取出,并且调用者必须已经拥有sp
1 | // detachBuffer attempts to remove all ownership of the buffer in the given |
4、attachBuffer
attachBuffer尝试将缓冲区的所有权转移给缓冲区队列。 如果这个调用成功,就好像这个缓冲区已经出队一样从返回的插槽号码。 因此,如果连接,这个调用将失败这个缓冲区会导致很多的缓冲区同时出队。
1 | // attachBuffer attempts to transfer ownership of a buffer to the buffer |
(3)、消费者Consumer
这里介绍几个非常重要的函数:
1、acquireBuffer
acquireBuffer尝试获取下一个未决缓冲区的所有权BufferQueue。 如果没有缓冲区等待,则返回NO_BUFFER_AVAILABLE。 如果缓冲区被成功获取,有关缓冲区的信息将在BufferItem中返回。
1 | // acquireBuffer attempts to acquire ownership of the next pending buffer in |
2、releaseBuffer
releaseBuffer从消费者释放一个BufferSlot回到BufferQueue。 这可以在缓冲区的内容仍然存在时完成被访问。 栅栏将在缓冲区不再正在使用时发出信号。 frameNumber用于标识返回的确切缓冲区。
1 | // releaseBuffer releases a buffer slot from the consumer back to the |
3、detachBuffer
detachBuffer尝试删除给定缓冲区的所有权插槽从缓冲区队列。 如果这个请求成功,该插槽将会是释放,并且将无法从这个接口获得缓冲区。释放的插槽将保持未分配状态,直到被选中为止在dequeueBuffer中保存一个新分配的缓冲区,或者附加一个缓冲区到slot。 缓冲区必须已被acquired。
1 | // detachBuffer attempts to remove all ownership of the buffer in the given |
4、attachBuffer
attachBuffer尝试将缓冲区的所有权转移给缓冲区队列。 如果这个调用成功,就好像这个缓冲区被获取了一样从返回的插槽号码。 因此,如果连接,这个调用将失败这个缓冲区会导致太多的缓冲区被同时acquired。
1 | // attachBuffer attempts to transfer ownership of a buffer to the buffer |
三、Surface::dequeueBuffer、Surface::queueBuffer实例
(1)、Surface::dequeueBuffer介绍
1 | Stack Trace: |
这里就衔接到《Android 11 Display System源码分析(1):GraphicBuffer allocate流程》第五步:importBuffer了。
(2)、Surface::queueBuffer介绍
frameAvailableListener->onFrameAvailable(item):通知SurfaceFlinger去消费