SurfaceHolder.lockCanvas () занимает слишком много времени для моего игрового приложения - PullRequest
3 голосов
/ 06 июня 2011

Я занимаюсь разработкой игры для Android и использую SurfaceView. У меня есть метод, который будет вызываться каждые 16 мс (я хочу, чтобы 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 кадров в секунду)

Спасибо!

Ответы [ 2 ]

6 голосов
/ 19 июня 2011

У меня была похожая проблема FPS с низким FPS на Samsung Intercept.Я получал только 12FPS с не более чем пустой экран.Я обнаружил, что проблема связана с тем, что Android выполняет автоматическое масштабирование на холсте и функции рисования.В AndroidManifest.xml добавьте строку

, тогда Android не будет автоматически масштабировать функции холста и рисования.По умолчанию используется значение «false», что включает автоматическое масштабирование.С android:anyDensity="true" я смог получить 40+ FPS!Недостатком всего этого является то, что теперь вы должны выполнять всю математику самостоятельно, чтобы соответствовать разным размерам экрана.Но это не должно быть так сложно.Надеюсь, что это помогает любому с подобными проблемами.Мне понадобилось 5 с лишним часов, чтобы понять этого маленького подонка.

0 голосов
/ 03 августа 2011

В моем понимании, lockCanvas () может быть очень дорогим, в зависимости от базовой реализации HW.

Цель - предоставить вам буфер, к которому у вас есть прямой доступ.Этот буфер может существовать непосредственно в графическом оборудовании, или это может быть текстура OpenGL или что-то еще.

Теперь, если вы вызываете lockCanvas (), система должна предоставить вам буфер для этих данных, который может включать передачу данных из графического процессора в память, а также преобразование формата изображения (например, yuv в rgb).

Как только вы закончите редактирование своего буфера данных, об операции необходимо сообщить наоборот, обратно в исходный HW-зависимый формат.

Все это может быть довольно дорого, особенно на мобильном устройстве: (

Хороший способ избежать - это изменить данные с помощью функций API ( drawRect () вместо copyRect () ), но это не всегда возможно.

...