【问题标题】:SurfaceHolder.lockCanvas() takes too long for my game appSurfaceHolder.lockCanvas() 对我的游戏应用程序来说花费的时间太长
【发布时间】:2011-06-06 06:18:02
【问题描述】:

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

谢谢!

【问题讨论】:

    标签: android canvas surfaceholder


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      一旦你完成了数据缓冲区的编辑,操作必须以相反的方式进行通信,回到原来的硬件依赖格式。

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多