Layer收到onFrameAvaliable通知后,会通知SurfaceFlinger更新,重新进行图像合成
在SurfaceFlinger重新合成图像的过程中,会遍历所有发生变化的Layer,此时调用Layer的latchBuffer函数去BufferQueue中拿方才生产者入队的Buffer进行处理
latchBuffer比较长, 主要作用分析是否需要重新计算当前Layer的visibleRegion
接着看下updateTextureImage方法
updateTextureImage函数主要包含个流程
1:acquireBufferLocked从BufferQueue中获取Buffer,拿到Buffer后,将Buffer保存在mSlots[item->mSlot]mGraphicBuffer中。
2:调用参数传入的Rejecter对象。来判断图像缓冲区Buffer是否符合条件。
3:调用updateAndReleaseLocked函数更新Buffer,并且释放掉上一个Buffer
SurfaceFlingerConsumer的acquireBufferLocked直接调用了父类的acquireBufferLocked函数。
GLConsumer的acquireBufferLocked函数也比较简单,调用父类ConsumerBase的acquireBufferLocked函数获取新的Buffer,然后根据获取的新GraphicBuffer创建一个EglImage,保存在GLConsumer的数组mEglSlots中。
GLConsumer维护了一个数组mEglSlots,和前面讲的mSlots类似,将EglImage对象保存在数组对应的slot位置上
同理GLConsumer的acquireBufferLocked也是直接调用BufferQueueConsumer的方法。
BufferQueueConsumer的acquiredBuffer函数从BufferQueue中拿准备好的Buffer数据。
1:先统计消费者acquire的buffer的数量是否查过最大限度,超过的话则禁止获取
2:遍历mQueue队列,获取合适的Buffer。如果Queue中等待显示的Buffer数量大于1,需要查看队列后边是否有指定显示时间且显示时间已经到的Buffer,有到话则直接放弃前边一个,显示后一个。循环处理,直到找到最紧急显示到Buffer。
3:根据找到的Buffer判断该Buffer是有需要立刻显示,如果离指定显示时间大于一定时间,则发挥PRESENT_LATER,此次显示不再处理该Buffer。
4:拿到需要显示的Buffer,设置需要显示Buffer的状态为ACQUIRED,并且将它从mQueue等待对了移除。
5:如果有遗弃的Buffer,需要同时有Buffer释放。
分析到这里Buffer已经从BufferQueue队列获取到了,下一步看如何更新Buffer。
updateAndRelease方法从名称就可看出其 *** 作内容。更新新Buffer,释放旧Buffer。
每一个Layer都和一个Surface对应, Surface在App端,是 *** 作和填充当前窗口的接口,而Layer则在SurfaceFlinger端来描述这个窗口。Layer在创建的时候会创建一个纹理Texture,这个Texture id也保存在了SurfaceFlingerConsumer中。SurfaceFlinger绘制的时候遍历Layer,Layer又会调用自己的SurfaceFlingerConsumer将合适的Buffer更新到纹理中。
SufaceFlinger更新纹理,上一步介绍了如果从BufferQueue中获取Buffer这一步介绍,如何更新到纹理。
1:首先做判断,是否attach到EGLContext,没有Attach则直接释放当前Buffer。普通Layer默认是Attach到SurfaceFlinger主线程的EGLContext上的。(需要attach的SurfaceView)
2:检查EGL状态和上次是否发生了变化
3:每个slot中的GraphicBuffer都会创建一个EGLImage,保存在GLConsumer的mEglSlots数组中。
4:释放掉旧的buffer
5:保存新的Buffer信息到GLConsumer信息中,等待将Buffer数据填充到openGL纹理中
上面的步骤已经把Buffer从Buffer队列获取到了,也已经将Buffer更新到GLConsumer中,同时也释放掉了旧的Buffer,但是何时填充纹理进行绘制呢?
也是在SurfaceFlinger进行图形合成的过程中,先执行了latchBuffer来更新纹理,后边后依次执行Layer的onDraw方法,进行绘制,Layer的onDraw方法会调用SurfaceFlingerConsumer的bindTextureImage来绑定并填充纹理。
这个步骤将纹理绑定到了EGLContext, 然后调用了glEGLImageTargetTexture2DOES(texTarget,static_cast<GLeglImageOES>(mEglImage));将Buffer内容填充到了纹理中。这样纹理也准备好了,就等SurfaceFlinger进行合成了。
一个GraphicBuffer缓冲区如何从Producer传递到Consumer,以及Consumer接收到之后如何处理已经分析完成了。过程比较长,做一下简单的总结。
以上就是关于GLFW介绍全部的内容,包括:GLFW介绍、java里面获得图像像素后怎么做dct变换、BufferQueue分析:消费者从Buffer队列取出的过程等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)