SurfaceHolder.lockCanvas()对我的游戏应用来说需要太长时间

时间:2011-06-06 06:18:02

标签: android canvas surfaceholder

我正在开发一款Android游戏,我正在使用SurfaceView。我有一个方法,每16ms调用一次(我希望有60fps)

public void myDraw(SurfaceHolder holder) {
    Canvas c = null;
    long start = System.currentMillis();    
    try {
        synchronized(holder) {
            c = holder.lockCanvas();
            if (c != null) {
                c.drawColor(Color.GREEN);
            }    
        }
    } finally {
        if (c != null) {
            holder.unlockCanvas(c);
        }
    }
    Log.i(TAG, "total time:" + (System.currentMillis() - start));
}

当我运行我的应用程序时,LogCat的输出是:

total time:30
total time:23
total time:6
total time:39
total time:17

为什么画布的锁定/解锁需要花费太多时间?有没有更好的方法解决我的问题? (也就是说,拥有一个60 fps的应用程序)

谢谢!

2 个答案:

答案 0 :(得分:6)

我有类似的FPS问题,三星拦截的FPS很低。我只得到12FPS只有一个空白屏幕。我发现这个问题与Android在画布上自动缩放和绘制函数有关。 在AndroidManifest.xml中添加第

< supports-screens android:anyDensity =“true”>

然后Android不会自动缩放画布并绘制函数。默认为“false”,可启用自动缩放功能。 使用android:anyDensity="true"我能够获得40+ FPS! 所有这一切的缺点是你现在必须自己完成所有数学运算以匹配不同的屏幕尺寸。但那不应该那么难。 希望这有助于任何有类似问题的人。我花了5个多小时才把这个小虫子弄出来。

答案 1 :(得分:0)

根据我的理解,lockCanvas()可能非常昂贵,具体取决于底层的HW实现。

目标是为您提供可直接访问的缓冲区。此缓冲区可以直接存在于图形硬件中,也可以是OpenGL纹理或其他内容。

现在,如果你调用lockCanvas(),系统必须为你提供一个缓冲区,这可能涉及从GPU到内存的数据传输以及图像格式转换(例如yuv到rgb)。

完成编辑数据缓冲区后,必须以相反的方式传达操作,返回原始的HW依赖格式。

所有这些都非常昂贵,特别是在移动设备上:(

要避免的一个好方法是使用API​​函数修改数据( drawRect()而不是 copyRect()),但并不总是可行。