博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SurfaceView的双缓冲机制
阅读量:3982 次
发布时间:2019-05-24

本文共 3543 字,大约阅读时间需要 11 分钟。

一、首先SurfaceView是双缓冲机制,有front和back,这两个交替显示,每post一次交替一次。

二、dirty区域是根据front和back来进行计算的。

三、程序没有填充的都算dirty区域

有了这几个前提后,自己的问题发现就解决了。首先自己第一、二次点击时,LockCanvas(Rect rect)无效,是因为back没有进行过程序填充,所以和front计算后,dirty是整个屏幕,而不是自己定义的rect大小。等交替完成一次后,front和back的背景就一致了,差别就在于自己定义的rect大小。

所以,要想使用dirty区域,可以在程序启动后,直接清两次屏,post后,然后再进行SurfaceView的操作。

surface是纵深排序(Z-ordered)的,这表明它总在自己所在窗口的后面。surfaceview提供了一个可见区域,只有在这个可见区域内 的surface部分内容才可见,可见区域外的部分不可见。surface的排版显示受到视图层级关系的影响,它的兄弟视图结点会在顶端显示。这意味者 surface的内容会被它的兄弟视图遮挡,这一特性可以用来放置遮盖物(overlays)(例如,文本和按钮等控件)。注意,如果surface上面 有透明控件,那么它的每次变化都会引起框架重新计算它和顶层控件的透明效果,这会影响性能。
        你可以通过SurfaceHolder接口访问这个surface,getHolder()方法可以得到这个接口。
        surfaceview变得可见时,surface被创建;surfaceview隐藏前,surface被销毁。这样能节省资源。如果你要查看 surface被创建和销毁的时机,可以重载surfaceCreated(SurfaceHolder)和 surfaceDestroyed(SurfaceHolder)。
        surfaceview的核心在于提供了两个线程:UI线程和渲染线程。这里应注意:
        1> 所有SurfaceView和SurfaceHolder.Callback的方法都应该在UI线程里调用,一般来说就是应用程序主线程。渲染线程所要访问的各种变量应该作同步处理。
        2> 由于surface可能被销毁,它只在SurfaceHolder.Callback.surfaceCreated()和 SurfaceHolder.Callback.surfaceDestroyed()之间有效,所以要确保渲染线程访问的是合法有效的surface。

surface就可以这样理解:它是内存中一块区域,它是surfaceview可见不那个部分,绘图操作作用于它,然后它就会被显卡之类的显示控制器绘制到屏幕上。

surface是个啥,大概已经有了些概念了。因为它对应了一个内存区,大家都知道,内存区的对象是有生命周期的,可以动态的申请创建和销毁,当然也可能会更新。于是,就有了作用于这个内存区的操作,这些操作就是surfaceCreated/Changed/Destroyed。三个操作放在一起,就是callback,

双缓冲技术
是游戏开发中的一个重要的技术。当一个动画争先显示时,程序又在改变它,前面还没有显示完,程序又请求重新绘制,这样屏幕就会不停地
闪烁
。而双缓冲技术是把要处理的图片在内存中处理好之后,再将其显示在屏幕上。双缓冲主要是为了解决 反复局部刷屏带来的闪烁把要画的东西先画到一个内存区域里,然后整体的一次性画出来

计算机访问显示屏和磁盘的速度远远小于CPU缓存和内存,每一次调用绘图函数往显示屏刷新数据,即使你的显示内容已经加载到了内存,但每一次访问显示屏,仍然会花费比内存大得多的时间,如果你的资源里有一百个图片,那么直接把他们全刷到屏幕上需要调用一百次drawBitmap方法,每次都需要访问显示屏,就会导致显示过程效率低下。这时如果使用双缓冲,创建一块屏幕客户区大小的BUFFER,把这一百个图片全画到BUFFER上,只就需要访问一百次内存,最后访问一次显示屏,把这块BUFFER刷到显示屏上就行了,如果内存与外设的速度比是一比十,那么几乎可以节约十分之九的时间,速度当然快了,这就是双缓冲技术。

Surface类是使用一种称为双缓冲的技术来渲染应用程序窗口的UI的。这种双缓冲技术需要两个图形缓冲区,其中一个称为前端缓冲区,另外一个称为后端缓冲区。前端缓冲区是正在渲染的图形缓冲区,而后端缓冲区是接下来要渲染的图形缓冲区,它们分别通过Surface类的成员变量mPostedBuffer和mLockedBuffer所指向的两个GraphicBuffer对象来描述。前面所获得的图形缓冲区backBuffer是作为后端缓冲区来使用的,即接下来它所指向的图形缓冲区也需要保存在Surface类的成员变量mLockedBuffer中。

       在将图形缓冲区backBuffer返回给调用者之前,Surface类的成员函数lock还需要对它进行进一步的处理,即判断是否需要前端缓冲区mPostedBuffer的内容拷贝回它里面去,以便可以支持部分更新应用程序窗口UI的功能。在满足以下三个条件下,Surface类的成员函数lock可以将前端缓冲区的内容拷贝到后端缓冲区中去:

       1. 前端缓冲区的内容拷贝到后端缓冲区所描述的区域的宽度和高度相同。

       2. 前端缓冲区和后端缓冲区的像素格式相同。

       3. 应用程序窗口绘图表面的属性值mFlags的ISurfaceComposer::eDestroyBackbuffer位等于0,即在渲染了应用程序窗口的UI之后,应该保留正在渲染的图形缓冲区的内容。

       如果能将前端缓冲区的内容拷贝到后端缓冲区中去,那么就不用重新绘制应用程序窗口的所有区域,而只需要绘制那些脏的区域,即Region对象newDirtyRegion所描述的区域。注意,参数dirtyIn所描述的区域是原先指定的脏区域,但是在分配了新的后端缓冲区backBuffer之后,我们需要将新的图形缓冲区backBuffer所描述的区域boundsRegion与原先指定的脏区域作一个与操作,得到才是最后需要重绘的脏区域newDirtyRegion。由于在这种情况下,我们只在后端缓冲区backBuffer绘制中绘制应用程序窗口的脏区域,因此,就需要将那些干净的区域从前端缓冲区frontBuffer拷贝到图形缓冲区backBuffer的对应位置去,这是通过调用函数copyBlt来实现的。应用程序窗口的干净区域使用Region对象copyback来描述,它是从应用程序窗口上一次所重绘的区域减去接下来需要重绘的脏区域newDirtyRegion得到的,而应用程序窗口上一次所重绘的区域是保存在Surface类的成员变量mOldDirtyRegion中的。

       如果不能将前端缓冲区的内容拷贝到后端缓冲区中去,那么接下来就需要重新绘制应用程序窗口的所有区域了,这时候应用程序窗口的脏区域newDirtyRegion就会被修改为后端缓冲区backBuffer所描述的区域boundsRegion。

       Surface类的成员函数lock处理完成前后端缓冲区的拷贝问题之后,接下来就会调用后端缓冲区backBuffer所指向的一个GraphicBuffer对象的成员函数lock来获得它的地址vaddr,以便接下来保存在参数other所描述的一个SurfaceInfo对象的成员变量bits中,这样调用者就获得后端缓冲区backBuffer的地址值了。注意,同时保存在SurfaceInfo对象中的信息还包括后端缓冲区backBuffer的宽度width、高度height、每行像素点stride、用途usage和像素格式format。

       Surface类的成员函数lock还会将接下来要重绘的脏缓冲区newDirtyRegion保存在Surface类的成员变量mOldDirtyRegion中,以便再下一次为应用程序窗口分配图形缓冲区时,可以知道应用程序窗口的上一次重绘区域,即上一次干净区域。

       此外,Surface类的成员函数lock还会将后端缓冲区backBuffer保存在Surface类的成员变量mLockedBuffer,这样就可以知道应用程序窗口当前正在使用的图形缓冲区,即下一次要请求SurfaceFlinger服务渲染的图形缓冲区。

       最后,Surface类的成员函数lock首先调用成员变量mApiLock所指向的一个Mutex对象的成员函数unlock,以便中可以释放前面所获得的锁,然后再返回到上一步去。

转载地址:http://cupui.baihongyu.com/

你可能感兴趣的文章
socket编程中select的使用
查看>>
C++获取文件大小常用技巧分享
查看>>
未来5年大机遇:做贩卖多巴胺的超级玩家
查看>>
30 岁之前,应当学会哪些技能?
查看>>
关于AIS编码解码的两个小问题
查看>>
GitHub 万星推荐:黑客成长技术清单
查看>>
可以在线C++编译的工具站点
查看>>
关于无人驾驶的过去、现在以及未来,看这篇文章就够了!
查看>>
所谓的进步和提升,就是完成认知升级
查看>>
Web开发之路
查看>>
昨夜今晨最大八卦终于坐实——人类首次直接探测到了引力波
查看>>
年纪轻轻记忆力就衰退得厉害,我还有救吗?
查看>>
如何优雅、机智地和新公司谈薪水?
查看>>
为什么读了很多书,却学不到什么东西?
查看>>
长文干货:如何轻松应对工作中最棘手的13种场景?
查看>>
关于WebClient超时问题
查看>>
创业公司如何与巨头竞争?利用好这9大优势是关键
查看>>
读书 | 如何像沉迷游戏一样对工作上瘾?
查看>>
如何确保自己的Mac数据安全呢?这里有四个“小秘诀”
查看>>
如何用好碎片化时间,让思维更有效率?
查看>>