2011-06-06 108 views
3

我正在开发一款安卓游戏,并使用SurfaceView。我有一个将被调用每16毫秒(我希望能有60fps的)SurfaceHolder.lockCanvas()为我的游戏应用程序花费太长时间

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的应用程序)

谢谢!

回答

6

我有一个类似的FPS问题与三星截获低FPS。我只得到12FPS,没有比空白屏幕更多的东西。我发现这个问题与Android在画布上进行自动缩放并绘制函数有关。 在AndroidManifest.xml如果添加行

<支持屏安卓anyDensity =“真” >

那么Android将不会自动缩放画布和借鉴作用。默认值是“false”,它将启用自动缩放。 With android:anyDensity="true"我能够获得40+ FPS! 所有这一切的缺点是,你现在必须自己做所有的数学来匹配不同的屏幕尺寸。但这不应该那么难。 希望这可以帮助任何有类似问题的人。我花了5个多小时才弄出了这个小小的杂物。

0

根据我的理解,lockCanvas()可能非常昂贵,具体取决于基础硬件实现。

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

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

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

所有这一切都可以是相当昂贵,特别是在移动设备:(

一个好方法,以避免上是使用API​​函数(的drawRect()的代替copyRect修改数据() )但它并不总是可能的。