3

我正在开发一款安卓游戏,我正在使用 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 的应用程序)

谢谢!

4

2 回答 2

6

我在 Samsung Intercept 上遇到了类似的 FPS 问题,FPS 较低。我得到的只有 12FPS,只不过是一个空白屏幕。我发现这个问题与 Android 在画布和绘图功能上进行自动缩放有关。如果AndroidManifest.xml您添加该行

<supports-screens android:anyDensity="true">

那么 Android 将不会自动缩放画布和绘图功能。默认值为“ false”,这将启用自动缩放。我android:anyDensity="true"能够获得 40+ FPS!所有这一切的缺点是您现在必须自己进行所有数学运算以匹配不同的屏幕尺寸。但这不应该那么难。希望这可以帮助任何有类似问题的人。我花了 5 个多小时才弄清楚这个小混蛋。

于 2011-06-19T14:48:07.243 回答
0

据我了解, lockCanvas() 可能非常昂贵,具体取决于底层硬件实现。

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

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

完成数据缓冲区的编辑后,必须以相反的方式传达操作,回到原始的硬件相关格式。

所有这些都可能非常昂贵,尤其是在移动设备上:(

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

于 2011-08-02T22:13:36.740 回答