SurfaceHolder.lockCanvas () toma demasiado tiempo para mi aplicación de juego

Estoy desarrollando un juego de Android y estoy usando SurfaceView. Tengo un método que se llamará cada 16ms (quiero tener 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)); } 

Cuando ejecuto mi aplicación, la salida de LogCat es:

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

¿Por qué el bloqueo / desbloqueo de la lona toma demasiado tiempo? ¿Hay mejor enfoque para mi problema? (es decir, para tener una aplicación de 60 fps)

¡Gracias!

Tuve un problema similar FPS con FPS bajo en el Samsung Intercept. Yo estaba recibiendo sólo 12FPS con nada más que una pantalla en blanco. Descubrí que el problema estaba relacionado con Android haciendo auto-escala en el lienzo y dibujar funciones. En AndroidManifest.xml si agrega la línea

<soportes-pantallas android: anyDensity = "true">

entonces Android no escalará automáticamente el lienzo ni dibujará funciones. El valor predeterminado es " false ", lo que permitirá la auto-escala. Con android:anyDensity="true" Pude obtener 40+ FPS! La desventaja de todo esto es que ahora tiene que hacer todas las matemáticas usted mismo para que coincida con los diferentes tamaños de pantalla por ahí. Pero eso no debería ser tan difícil. Espero que esto ayude a cualquiera con problemas similares. Me tomó 5+ horas para calcular este pequeño bicho.

En mi entendimiento, un lockCanvas () podría ser muy caro, dependiendo de la implementación de HW subyacente.

El objetivo es proporcionarle un búfer al que tenga acceso directo. Este búfer puede existir directamente dentro del hardware gráfico o puede ser una textura OpenGL o algo más.

Ahora, si llama a lockCanvas (), el sistema debe proporcionarle un búfer a esos datos, lo que podría implicar la transferencia de datos desde la GPU a la memoria y también una conversión de formato de imagen (por ejemplo, yuv a rgb).

Una vez que haya terminado de editar el búfer de datos, la operación debe comunicarse al revés, de nuevo al formato original dependiente de HW.

Todo esto puede ser bastante caro, especialmente en un dispositivo móvil 🙁

Una buena manera de evitar es es modificar los datos utilizando las funciones API ( drawRect () en lugar de copyRect () ), pero no siempre es posible.

  • Cómo tomar una foto (instantánea) mientras el video se ha grabado con la vista de la superficie
  • Cómo escalar el video en un SurfaceView más grande que la ventana en Android?
  • ¿Cómo hacer un SurfaceView siempre horizontal?
  • Invisible SurfaceView para previsualización de la cámara
  • La eficiencia sobre el dibujo de lienzo android
  • Android: ¿Cómo hacer una vista previa de cámara en forma de círculo?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.