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:
- Cámara Android: la aplicación superó la superficie NULL
- Canvas en SurfaceView - Aceleración de hardware
- SuperficieCreada () Nunca llamado
- ¿Cómo pasar la vista previa de la cámara a la superficie creada por MediaCodec.createInputSurface ()?
- Reabrir la cámara después de cancelar el selector de intenciones
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!
- Corregir la relación de aspecto y la rotación de la aplicación de la cámara Android
- agregar imagen a la vista de la superficie en android
- ¿Es OpenGL en Android un asesino de la batería?
- Android: onPreviewFrame nunca llamado sin SurfaceView
- Error al inflarse al extender una clase
- Crear ImageView de forma programática sin diseño
- La cámara Android no funcionará. StartPreview falla
- Imagen de leva en el soporte de superficie, dibujar: Excepción debido al tipo de superficie
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.
- Servicio de fondo de Android para determinar la aplicación de primer plano
- ¿La llamada de runOnUiThread de Android llama a getView () en Adapters?