3

I'm developing an android game and I'm using SurfaceView. I have a method that will be called every 16ms (I want to have 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));
}

When I run my app, the output from LogCat is:

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

Why does the lock/unlock of canvas takes too much time? Are there any better approach to my problem? (that is, to have a 60 fps app)

Thanks!

4

2 に答える 2

6

Samsung Intercept で FPS が低いという同様の FPS 問題が発生しました。空白の画面だけで 12 FPS しか得られませんでした。この問題は、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 など) が含まれる場合があります。

データ バッファの編集が終了したら、元の HW 依存形式に戻すために、操作を逆方向に伝達する必要があります。

特にモバイルデバイスでは、これらすべてが非常に高価になる可能性があります:(

回避する良い方法は、API 関数 ( copyRect( )の代わりにdrawRect() )を使用してデータを変更することですが、常に可能であるとは限りません。

于 2011-08-02T22:13:36.740 に答える