第十七篇:使用窗口的cache属性加速SOUI的渲染
内容渲染速度是决定一个UI成败的关键。无论UI做得多华丽,没有速度都没有意义。
在MFC,WTL等开发框架下,每个控件都是一个窗口,窗口只需要画前景,背景。因为窗口之间的内容不需要做混合,一个子窗口的一次刷新只涉及该窗口本身,和其它窗口无关,因此这样效率很高。但是美中不足在于,窗口之间内容是孤立的,要想不同窗口之间的内容更协调,对美术有很高的要求,同时也基本只能适应个别窗口大小相对固定的场景。
要使UI更加漂亮,最简单有效的方法就是采用alpha混合的方式将各层的窗口相互混合,这样窗口之间没有了边界的感觉,从而使得UI更像一个整体,这也是现代UI的主要实现方式。
想像一下,如果一个最上层的子窗口内容发生了变化,UI系统如何把窗口内容绘制出来呢?
首先需要通知UI系统的渲染对象说我的窗口显示区域内容发生了变化,请求重绘。
UI系统拿到渲染对象后,对渲染范围设定剪裁区(clip),防止刷新那些不需要重绘的区域。
UI系统从最顶层的窗口开始依次绘制每一层的和剪裁区重叠的窗口的内容(不同窗口之间绘制内容的混合由绘制方法定义,例如图片可能是利用alpha通道)。
为了防止绘制过程中出现闪烁,一般上面绘制都是在一个内存绘图设备(如内存DC)上进行。在全部绘制完成后,将绘制内容再呈现到屏幕。
那么问题来了:一般子窗口会比父窗口小,子窗口请求重绘时,要执行父窗口的绘制函数,如果父窗口没有根据当前的剪裁范围来确定自己的绘制范围,那么尽管有剪裁区限制了不会绘制超出边界,在实际执行过程中,超出剪裁区的绘制行为也可能极大的影响UI的性能。
如何解决这个问题呢?
解决的方法可以有很多,比如在每个窗口的绘制方法都实现只绘制在剪裁区的那部分(实际上实现起来非常麻烦,附加的剪裁区计算也可能成为新的绘制瓶颈);又比如每个窗口都保留背景窗口的内容,当窗口需要刷新时,直接直接把背景内容拿过来在上面画。
第二种方法看起来效率是最高的,但是实际上可能并不高:虽然在绘制自己的内容时速度快了,问题是自己更新以后,还需要同时更新它的上层窗口的缓存,可能导致内存开销大,效率也不高。
在SOUI中,我们采用了第三种方法:给窗口加一个cache属性。
当cache=0时,窗口的绘制和前面提到的流程一样,只是如果窗口比较大,而需要一时半会的区域比较小时,速度慢一点。
如果cache=1,则窗口绘制的内容会被保存到一张缓存位图上,当其它窗口刷新并导致该窗口重绘时,直接从缓存中复制出来就可以了。
假定一个窗口使用一张小图片进行九宫格拉伸绘制出来,绘制整个窗口由于拉伸中的插值等一系列的计算,绘制可能需要消耗大量的CPU时间,而有了缓存以后,只在第一次绘制的时候使用图片绘制方法进行绘制,其它时间都是直接从缓存复制,效率能够极大的提高。
很显然,cache属性在提高渲染效率的同时,也需要开辟一块缓存来保存绘制内容,也就是常见的空间换时间的方法。因此如果绘制本身速度就足够快,那么完全可以不使用缓存(比如给一个窗口填充一个纯色的矩形)。
总结:
cache可以提高绘制速度,但是是以更高的内存占用为代价的,应该只在需要的地方使用(例如顶层背景窗口)。
第十七篇:使用窗口的cache属性加速SOUI的渲染的更多相关文章
- 第六十七篇:Vue的计算属性
好家伙, 1.什么是计算属性? 首先它是一种属性,其次他有计算这个特殊的性质, 它是一个依赖于其他属性的属性,当依赖的属性发生变化的时候就会触发我们计算属性的逻辑 它会对这个属性进行计算, 所以说它是 ...
- Python之路【第十七篇】:Django之【进阶篇】
Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...
- Python之路【第十七篇】:Django【进阶篇】
Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...
- Python之路【第十七篇】:Django【进阶篇 】
Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...
- 第十六篇:SWindow的布局属性pos2type及offset
当窗口大小需要根据内容来确定时,使用XML布局可能需要做一些特殊的处理. 例如:不管窗口多大,我需要将该窗口相对于父窗口居中在XML中应该怎么处理? 如果窗口大小是固定的(如, 100 *100),这 ...
- 解剖SQLSERVER 第十七篇 使用 OrcaMDF Corruptor 故意损坏数据库(译)
解剖SQLSERVER 第十七篇 使用 OrcaMDF Corruptor 故意损坏数据库(译) http://improve.dk/corrupting-databases-purpose-usin ...
- Document对象关于窗口的一些属性
在网上搜罗的,只为自己查用方便,不做他用 window.screen.availWidth 返回当前屏幕宽度(空白空间) window.screen.availHeight 返回当前屏幕高度(空白空间 ...
- 第六篇 ANDROID窗口系统机制之显示机制
第六篇 ANDROID窗口系统机制之显示机制 ANDROID的显示系统是整个框架中最复杂的系统之一,涉及包括窗口管理服务.VIEW视图系统.SurfaceFlinger本地服务.硬件加速等.窗口管理服 ...
- 跟我学SpringCloud | 第十七篇:服务网关Zuul基于Apollo动态路由
目录 SpringCloud系列教程 | 第十七篇:服务网关Zuul基于Apollo动态路由 Apollo概述 Apollo相比于Spring Cloud Config优势 工程实战 示例代码 Spr ...
随机推荐
- 转: 认识 HTTPS
HTTPS简介 HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版. ...
- ubuntu下查找某个文件的路径
参考:ubuntu下如何查找某个文件的路径 http://blog.csdn.net/lieyanhaipo/article/details/17055667 在Ubuntu有时候会遇到记得 ...
- [转载]C++虚函数浅析
原文:http://glgjing.github.io/blog/2015/01/03/c-plus-plus-xu-han-shu-qian-xi/ 感谢:单刀土豆 C++虚函数浅析 JAN 3RD ...
- echo 单引号和双引号
echo输出 $key=value echo "$key" echo 后面带双引号的话,双引号里面的内容会翻译,输出value echo '$key' echo后面带单引号的话,双 ...
- emoji表情初探
2015年12月28日 14:24:51 星期一 首先注意的地方: 1. emoji是需要操作系统支持的, 例如: ios更新时, 会在升级日志里说明, 增加了对多少个emoji图标的支持. 原理上是 ...
- [Linux]非外网环境下配置lnmp心得
1.安装gcc编译器 基本所有编译安装包都需要gcc编译器,而且编译安装gcc也需要一个编译器,这是一个悖论.所以,这里只能寻求rpm包安装.但是rpm包需要匹配特定的操作系统内核,所以没有一个通用的 ...
- Effective C++ -----条款50:了解new 和delete 的合理替换时机
有许多理由需要写个自定的new 和delete ,包括改善效能.对heap 运用错误进行调试.收集heap 使用信息.
- Windows update 失败的解决方案
由于刚刚装了新的系统,结果在电脑用了刚刚一周之后,我打开了自动更新,结果电脑就一直处于更新状态中.期初我以为是更新比较慢,等等可能就结束了,结果等了足足一晚上,到了第二天,电脑显示是:配置更新失败,正 ...
- 【leetcode】 Scramble String (hard)★
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...
- 【编程之美】2.5 寻找最大的k个数
有若干个互不相等的无序的数,怎么选出其中最大的k个数. 我自己的方案:因为学过找第k大数的O(N)算法,所以第一反应就是找第K大的数.然后把所有大于等于第k大的数取出来. 写这个知道算法的代码都花了2 ...