(转)flash player的重绘渲染机制
原文:http://blog.csdn.net/bbmjfpig/article/details/6294347
?
这篇文章写的太好了,不得不转。以下内容全部是转载。
?
?
先简洁说下前人的研究成果。
?
一个是Tencent的YouYee发现的fp重绘特性,即便舞台上有多于三个的显示对象需要被重绘,Flash Player 会将其中的两个或者多
个集合(根据位置来判断)在一起,然后重绘在一个大区域里面,结果是重绘区域不会超过三个。
?
另一个就是Adobe公司的Lee Thomason 介绍的FP的可变跑到的重绘执行周期。其中有俩方面内容
?
重绘的执行基础
FP的执行本身是多线程,不过没有提供给开发人员多线程开发模式,我们只要把FP当成单线程处理理解就成。在FP执行一帧的周期
里,前一部分时间用于执行代码,剩余时间用于渲染显示列表中的对象。每个执行阶段都可以根据实际需求增加执行时间来执行更
多代码或做更多的渲染工作,周期总长度也将相应增长。
?
可变跑道概念
Flash Player执行一帧的周期里,前一部分时间用于执行代码,剩余时间用于渲染显示列表中的对象。每个执行阶段都可以根据实际需求
增加执行时间来执行更多代码或做更多的渲染工作,而跑道的总长度也将相应增长。
?
在前一模型基础上发生改变的是每一阶段在一个微观周期里的样子以及他们怎样形成一帧。
AVM2是由Flash Player中一个叫做Marshal的元帅级组件所操控,Marshal负责将时间切割成Flash Player工作所依的基本时间片,在
这里我希望澄清一下Flash Player的时间片跟swf文件运行时的帧速率没有任何关系,我们将最终看到Flash Player是如何将这些时间片
合成为一帧。在Mac OS版Firefox中执行一个由Flex编译得来的swf文件,Marshal通常会将时间切割成19-20毫秒的时间片,时间片大小
根据平台和浏览器的不同而存在差异.为方便我们接下来的讨论,我们假定时间片大小为20毫秒,也就是说Marshal每秒钟会产生不超过50个
时间片,每个时间片中,五步可能的操作按如下顺序执行:
?
Marshal如此反复的执行20毫秒时间片并在运行中决定下一步操作。一个时间片中执行的所有这些操作最终归纳为上述两段式跑道(代码
执行,图像渲染)也就是我们所说的一帧。用户代码和失效操作填充在代码执行区,渲染操作填充在跑道的渲染区段。需要指出的是相关操
作只能在Marshal预定的时间内发生,如果你的用户代码很短,那么Marshal仍然会在执行完用户代码后等待一段时间然后进入渲染阶段。
?
?
?
不同的帧速率下,一个帧周期中的可变跑道会执行不同操作,例如对于5fps的swf,每帧处理10个用户action,1个失效action,1个渲
染action;帧速率25fps的swf,每帧处理2个用户action,1个失效action,1个渲染action;对于50fps的swf,每帧只能处理1个用
户action,1个失效action,1个渲染action。需要指出的很重要的一点是,某些事件只可能能发生在某些特定的时间片里,比如,Event.ENTER_FRAME事件只能在某一帧的初始时间片中被调度。
好了,稍微了解了重绘机制后,在写程序时可以避免一些不必要的重绘。
?
1、显示列表中的所有显示对象的根都是舞台stage,所以当这些显示对象的形态属性发生变化时, 会引发重绘,包括width,height
?? ? ,scale,alpha等,所以这就是tween等类做UI的缓动效果时,重绘频繁,导致了CPU占用偏高。
2、当显示对象的层级发生变化时也会引发重绘,例如,在做RPG时,要时刻检测角色的层级,从而更正相互的遮挡状态,在设置层级
?? ? 时最好判断下再做变化,因为即使层级没变,但调用了setChildIndex方法,也会重绘。
?? ? 当用removeChild和addChild时会引发重绘。
3、在stage显示窗外外的元素不会重绘,这是FP本身实现的,之前有很多人在研究针对flash的卡马轴的算法,我认为没必要了,FP已经
?? ? 实现了这功能,另外我敲了两个位图滚动的粒子对比了一下,貌似卡马轴算法的例子占CPU还会稍多一些,有时间的话还不如研究下
?? ?位图的高速存取实用些。
?? ? 另外值得一提的是,我试了试,如果一个显示元素被遮挡的话,在符合重绘条件时仍会重绘,所以跟遮挡无关。这跟Tencent Team的
?? ?测试冲突,我想是因为当被遮挡住的话,重绘的边框也被遮挡住了,所以认为被遮挡的元素不会重绘,这个大家可以敲个例子试一试,
?? ?也有可能是我的例子有一定特殊性。
4、对于设置了cacheAsBitmap = true 的元素,由于元素整体被缓存成了位图,当元素有变化时,缓存的位图也会变化,所以会引起
?? ?元素的重绘,所以对于大小变形经常变化的显示元素最好不要用缓存位图,而且占内存。
5、对于设置了buttonMode 为true的显示元素,无论鼠标点击、经过、弹起等皮肤有没有,都会引发重绘。
?
说了减少重绘的注意方面,再来说说必要时引发重绘,MouseEvent和TimeEvent的事件有updateAfterEvent()方法,可以即刻强制
FP重绘,举例:当游戏使用自定义鼠标样式时,如果游戏帧频较低,又不想单独为了鼠标样式的流畅而提高帧频,可以在每次改变鼠标
样式(bitmap、mc等)的位置后即可强制重绘,从而使用户感觉游戏运行流畅。