内容渲染速度是决定一个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的渲染的更多相关文章

  1. 第六十七篇:Vue的计算属性

    好家伙, 1.什么是计算属性? 首先它是一种属性,其次他有计算这个特殊的性质, 它是一个依赖于其他属性的属性,当依赖的属性发生变化的时候就会触发我们计算属性的逻辑 它会对这个属性进行计算, 所以说它是 ...

  2. Python之路【第十七篇】:Django之【进阶篇】

    Python之路[第十七篇]:Django[进阶篇 ]   Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...

  3. Python之路【第十七篇】:Django【进阶篇】

    Python之路[第十七篇]:Django[进阶篇 ]   Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...

  4. Python之路【第十七篇】:Django【进阶篇 】

    Python之路[第十七篇]:Django[进阶篇 ]   Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...

  5. 第十六篇:SWindow的布局属性pos2type及offset

    当窗口大小需要根据内容来确定时,使用XML布局可能需要做一些特殊的处理. 例如:不管窗口多大,我需要将该窗口相对于父窗口居中在XML中应该怎么处理? 如果窗口大小是固定的(如, 100 *100),这 ...

  6. 解剖SQLSERVER 第十七篇 使用 OrcaMDF Corruptor 故意损坏数据库(译)

    解剖SQLSERVER 第十七篇 使用 OrcaMDF Corruptor 故意损坏数据库(译) http://improve.dk/corrupting-databases-purpose-usin ...

  7. Document对象关于窗口的一些属性

    在网上搜罗的,只为自己查用方便,不做他用 window.screen.availWidth 返回当前屏幕宽度(空白空间) window.screen.availHeight 返回当前屏幕高度(空白空间 ...

  8. 第六篇 ANDROID窗口系统机制之显示机制

    第六篇 ANDROID窗口系统机制之显示机制 ANDROID的显示系统是整个框架中最复杂的系统之一,涉及包括窗口管理服务.VIEW视图系统.SurfaceFlinger本地服务.硬件加速等.窗口管理服 ...

  9. 跟我学SpringCloud | 第十七篇:服务网关Zuul基于Apollo动态路由

    目录 SpringCloud系列教程 | 第十七篇:服务网关Zuul基于Apollo动态路由 Apollo概述 Apollo相比于Spring Cloud Config优势 工程实战 示例代码 Spr ...

随机推荐

  1. ASP.NET MVC Dropdownlist

    本文介绍如何在网页里显示DropDownList. Step 1: 在Control里面添加方法 public ActionResult ShowDropDownList() { return Vie ...

  2. emmet 太 hackble 了 。。。

    http://www.open-open.com/lib/view/open1451954899292.html

  3. 【Unity3D】使用鼠标键盘控制Camera视角(即时战略类游戏视角):缩近,拉远,旋转

    今天写一个demo,要用到鼠标键盘控制三维视角,因此写了个脚本用于控制. 该脚本可以用于即时战略类游戏的视角,提供了缩进,拉伸,旋转.同时按住鼠标右键不放,移动鼠标可以实现第一人称视角的效果. usi ...

  4. robotFramework——截屏

    测试执行过程中进行截屏并且保存,是任何一款自动化测试工具或者框架必备的功能.那么Robotframework如何进行截屏呢?Robotframework提供了一个“Screenshot”库.    使 ...

  5. ios 跟踪UITextField更改的简单方法

    如图,用xib链接,用到的消息是Editing Changed 消息.

  6. iOS 在UITableViewCell中加入自定义view时view的frame设定注意

    由于需要重用同一个布局,于是在cellForRowAtIndexPath中把自定义view加在了cell上,我是这样设定view的frame的 var screenFrame = UIScreen.m ...

  7. ubuntu14.04和win7共享文件夹

    环境:vmware12 问题:安装了vmware-tools,但是在/mnt/hgfs下面看不到共享的文件夹. 按照网上的一些经验和教程使用如下命令: mount -t vmhgfs .host:/ ...

  8. 安装VisualSvn Server时遇到的问题

    安装标准版VisualSvnserver,端口443,启用https//,安装过程中报服务启动失败,后用命令行 msiexec /i VisualSVN-Server-2.7.3.msi NO_STA ...

  9. Django~Views

    In Django, web pages and other content are delivered by views. To get from a URL to a view, Django u ...

  10. FIX_前缀后缀_未提交

    问题 B: FIX 时间限制: 1 Sec  内存限制: 64 MB提交: 38  解决: 11[提交][状态][讨论版] 题目描述 如果单词 X 由单词 Y 的前若干个字母构成,我们称 X 是 Y ...