SurfaceHolder.lockCanvas()太贵了

时间:2012-01-05 00:43:44

标签: android locking android-canvas surfaceview

每当我调用这些方法时,需要14-20毫秒才能继续。

Canvas canvas = holder.lockCanvas();
holder.unlockCanvasAndPost(canvas);

这是正常行为吗? 我应该采取不同的方法吗?

这是整个代码

public class Render extends SurfaceView {
    Context c = null;
    SurfaceHolder holder;
    volatile boolean running = true;

    public Render(Context c) {
        super(c);
        this.c = c;
        this.holder = getHolder();
    }

    public void run() {
        if(running) { 
            if(!holder.getSurface().isValid()){
                System.out.println("not valid");
                return;          
            }

            Canvas canvas = holder.lockCanvas();
            holder.unlockCanvasAndPost(canvas);

        }
    }
}

跟踪:

01-05 15:49:20.322:I / System.out(4892):帧时间:0 ms frame291
01-05 15:49:20.322:I / System.out(4892):无效
01-05 15:49:20.322:I / System.out(4892):帧时间:0 ms frame292
01-05 15:49:20.332:I / System.out(4892):帧时间:2 ms frame293
01-05 15:49:20.357:I / System.out(4892):帧时间:22 ms frame294
01-05 15:49:20.357:I / System.out(4892):帧时间:1 ms frame295
01-05 15:49:20.362:I / System.out(4892):帧时间:1 ms frame296
01-05 15:49:20.367:D / CLIPBOARD(4892):在开始输入时隐藏剪贴板对话框:由其他人完成...!

01-05 15:49:20.367:I / System.out(4892):帧时间:8 ms帧297
01-05 15:49:20.377:I / System.out(4892):帧时间:10 ms frame298
01-05 15:49:20.397:I / System.out(4892):帧时间:16 ms frame299
01-05 15:49:20.412:I / System.out(4892):帧时间:16 ms frame300
01-05 15:49:20.427:I / System.out(4892):帧时间:16 ms frame301

UPDATE

<小时/> 当我使用OpenGL

时,同样的事情
package android.apps.td;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;

public class Render extends GLSurfaceView implements Renderer {

    private final int MILLION = 1000000;
    private long frame;

    public Render(Context context) {
        super(context);
        setRenderer(this);
        // TODO Auto-generated constructor stub
    }

    public void onDrawFrame(GL10 arg0) {
        System.out.println("Frame "+(System.nanoTime()-frame)/MILLION+" ms");
        frame = System.nanoTime();
    }

    public void onSurfaceChanged(GL10 gl, int width, int height) {
        System.out.println("Surface changed w:"+width+" h:"+height);
    }

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        System.out.println("Surface created");
    }
}

2 个答案:

答案 0 :(得分:2)

我发现了这篇文章:http://replicaisland.blogspot.com/2009/10/rendering-with-two-threads.html

eglSwapBuffers()可能在onDrawFrame之后被调用并阻塞,直到硬件完成绘制而不是交换缓冲区,这会使最小延迟为16.67 ms。

答案 1 :(得分:0)

我一直在调查这个问题。我在Galaxy Tab GT-P7500上发现的是那个

  • unlockCanvasAndPost + lockCanvas对之间的最短时间是1/60秒或17毫秒。
  • 但是,您最多可以完成6毫秒的工作,帧速率将保持在60 fps。
  • 页面翻转所需的最短时间(unlockCanvasAndPost + lockCanvas)约为3毫秒。
  • 工作时间超过6毫秒,lockCanvas()函数可能会引入一个额外的延迟,强制帧速率降至40 fps,30 fps,20 fps或15 fps。在最坏的情况下,页面翻转可能需要超过1/60秒。例如,如果你每帧执行48毫秒的工作(当你为页面翻转增加3毫秒时,这对于20 fps而言还不够快),页面翻转会浪费19-20毫秒,以便将帧速率降低到15毫秒每秒帧数。低于15 fps,页面翻转可能会持续17毫秒。
  • 这种现象并不总是发生。在基准测试中观察到这种行为后,我创建了一个专门的活动来进一步调查,在那个专门的活动中,这种现象没有发生。到目前为止,我还没有弄清楚我的原始基准测试和新基准测试之间的区别:它们都在工作线程中的SurfaceView上绘制帧,但在第二个活动中,页面翻转持续3 ms,而在第一个,页面翻转最初需要3毫秒,但在大约1/2秒后突然上升,在稳定状态下最大为20毫秒。
  • 插入墙壁电源没有任何区别。