Android OpenGL: relación de aspecto loco después de dormir
Si golpeo el botón de encendido en mi teléfono Android (o esperar a que el tiempo de espera) y el teléfono se va a dormir, después de despertar de nuevo, la relación de aspecto de la pantalla es todo fuera de mal.
Capturas de pantalla:
- Aplicación de Android dañada usando texureview
- ¿Cómo funciona la función gluProject? No puedo entenderlo
- Esfera texturada en OpenGL ES
- Falta de controladores OpenGL en el emulador de Android
- Cómo inicializar y finalizar correctamente EGL en Android
roto
correcto
En GameActivity.onCreate ()
// Grab display info DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); ACTUAL_SCREEN_WIDTH = (int) dm.widthPixels; ACTUAL_SCREEN_HEIGHT = (int) dm.heightPixels; ACTUAL_DENSITY = dm.density; double scale = ((double) MainMenuActivity.resolutionScale / 100.0); SCREEN_WIDTH = (int) (ACTUAL_SCREEN_WIDTH * scale); SCREEN_HEIGHT = (int) (ACTUAL_SCREEN_HEIGHT * scale); DENSITY = ACTUAL_DENSITY * scale; // Setup graphics requestWindowFeature(Window.FEATURE_NO_TITLE); surface_view = new GLSurfaceView(this); if (SCREEN_WIDTH != ACTUAL_SCREEN_WIDTH || SCREEN_HEIGHT != ACTUAL_SCREEN_HEIGHT) surface_view.getSurfaceHolder().setFixedSize(SCREEN_WIDTH, SCREEN_HEIGHT);
Estoy recargando todo correctamente en GLSurfaceView (es decir, golpear a casa y volver al juego recarga las texturas, etc).
He imprimido la orientación en onWindowFocusChanged, y es el paisaje (como se esperaba).
El problema no aparece si no utilizo setFixedSize (es decir, si resolutionScale es 100). Además, el problema desaparece si aparece otra ventana delante del juego (como la ventana de preferencias) y luego devuelve el juego.
Gracias por adelantado. He estado probando cosas aleatorias durante una hora, ya que la investigación se secó.
- Android: ¿Es posible crear una SurfaceTexture sin SurfaceView?
- Cualquier buen ejemplo para openGLES shader en android?
- Cómo utilizar GLM en la aplicación Android NDK
- Uso de objetos de búfer de píxeles (PBO) en Android
- Android ICS: ¿Qué es lo que realmente hace el sistema "Forzar Rendición de GPU"?
- ¿Es posible renderizar una Vista de Android a una FBO o textura de OpenGL?
- ¿Cómo llamarías un método de todas las instancias de una clase?
- Reduzca el uso de memoria para texturas en OpenGL ES 1.1
Estoy trabajando en este tema ahora, y en este momento parece ser un error de Android relacionado con SurfaceHolder.setFixedSize ().
Lo que hago para obtener estos registros es esto: esperar a que el juego para cargar, empujar la energía, dejar la pantalla en blanco, empujar la energía de nuevo (rápidamente), desbloquear la diapositiva (rápidamente). Esto está en HTC Thunderbolt 2.3.4, por cierto.
Aquí está el curso normal de los eventos (sin usar setFixedSize):
----- power button pushed ------ JavaMain: onPause: called, thread: 1 ActivityManager: Config changed: { scale=1.0 imsi=310/12 loc=en_US touch=3 keys=1/1/2 nav=1/1 orien=1 layout=34 uiMode=17 seq=1509 skin=default} JavaMain: onConfigurationChanged, orientation: 1 thread: 1 JavaMain: mSView(old): 800x480 JavaMain: surfaceChanged: width: 480, height:800, thread: 1 JavaMain: onWindowFocusChanged: called, thread: 1 (screen is now off) ------ power button pushed, and slide-lock undone ----- JavaMain: onResume: called, thread: 1 ActivityManager: Config changed: { scale=1.0 imsi=310/12 loc=en_US touch=3 keys=1/1/2 nav=1/1 orien=2 layout=34 uiMode=17 seq=1510 skin=default} JavaMain: onConfigurationChanged, orientation: 2 thread: 1 JavaMain: mSView(old): 480x800 JavaMain: onWindowFocusChanged: called, thread: 1 JavaMain: surfaceChanged: width: 800, height:480, thread: 1 (back in game)
Tenga en cuenta, que después de onPause, mi vista de la superficie se vuelve a hacer como retrato y después onResume se cambia de nuevo a paisaje. Tengo screenOrientation fijado al paisaje en el manifiesto.
Ahora mira lo que ocurre durante la misma secuencia, pero ahora SurfaceHolder.setFixedSize () se utiliza (para reducir la resolución):
----- power button pushed ------- JavaMain: onPause: called, thread: 1 ActivityManager: Config changed: { scale=1.0 imsi=310/12 loc=en_US touch=3 keys=1/1/2 nav=1/1 orien=1 layout=34 uiMode=17 seq=1513 skin=default} JavaMain: onConfigurationChanged, orientation: 1 thread: 1 JavaMain: mSView(old): 800x480 JavaMain: surfaceChanged: width: 640, height:384, thread: 1 JavaMain: onWindowFocusChanged: called, thread: 1 (screen is now off) ------ power button pushed, and slide-lock undone ----- JavaMain: onResume: called, thread: 1 ActivityManager: Config changed: { scale=1.0 imsi=310/12 loc=en_US touch=3 keys=1/1/2 nav=1/1 orien=2 layout=34 uiMode=17 seq=1514 skin=default} JavaMain: onConfigurationChanged, orientation: 2 thread: 1 JavaMain: mSView(old): 480x800 JavaMain: onWindowFocusChanged: called, thread: 1 (back in game, with a messed up screen as in OP)
Ahora note que, después de onPause, surfaceChanged refleja el tamaño fijo que había especificado, sin embargo, en onResume la vista de la superficie está en orientación vertical (algo inesperado). Pero lo que realmente falta, es la llamada surfaceChanged con mis parámetros de tamaño fijo. Y antes de pedir, no hacer .setFixedSize () en onConfigurationChanged () no tiene ningún efecto.
ACTUALIZACIÓN Y SOLUCIÓN:
De hecho, la solución se redujo a restaurar (en realidad, nunca permitiendo cambios) a mi vista de la superficie. Esto se logra agregando las siguientes dos líneas después de la super llamada en onConfigurationChanged para su actividad. (Asumiendo que tiene el siguiente conjunto de ajustes de manifiesto).
android:configChanges="orientation" android:screenOrientation="landscape"
Esto impide efectivamente que las dimensiones de la vista de la superficie se fijen nunca a otra cosa (como el retrato). Que, por cierto, ES LO QUE QUERÍA CUANDO ESPECIFIQUE screenOrientation = paisaje !!! (Te estoy mirando aquí, Google)
public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // -- stomp any attempts by the OS to resize my view. // -- Hardcoded values for illustration only. In real life // -- you'll need to save these when the surface view is originally created mSView.getLayoutParams().width = 800; mSView.getLayoutParams().height = 480; }
Necesitas llamar a gl.glViewport (0, 0, width, height); O similar del método onSurfaceChanged de su GL10.Renderer. Mi suposición es que cuando el dispositivo se despierta del sueño, algo debe estar alterando el viewport, sin embargo el viewport se inicializa para usted cuando su aplicación se lanza por primera vez, por lo que funciona correctamente hasta que duerma.
Estado de OpenGL y actividades de pausa / reanudación
También debe tener en cuenta que su contexto de OpenGL (todos sus estados actuales como el color actual, las texturas enlazadas, etc.) se perderán cuando su actividad se detenga / reanude .
Así que tal vez usted se enfrenta a un problema de pérdida de contexto.
Si está utilizando una clase GLSurfaceView.Renderer debe volver a establecer sus estados de nuevo en el método onSurfaceCreated (..). Debería actualizar su pregunta con algún código.
Actualizado Sólo por referencia que se refiere el comentario en: http://www.youtube.com/watch?v=cdvaPyq_eBU (38:14 min) y el uso de setFixedSize (..)
http://developer.android.com/reference/android/view/SurfaceHolder.html#setFixedSize%28int,%20int%29
Indica que debe llamar al método setFixedSize (SCREEN_WIDTH, SCREEN_HEIGHT) del mismo subproceso que ejecuta la ventana de SurfaceView. Parece que se está configurando desde su hilo ui y no el hilo de renderizado .
Necesita hacer tres pasos:
- AndroidManifest.xml –
android:configChanges="keyboard|keyboardHidden|screenSize|orientation"
- Su diseño para el uso de la actividad
FrameLayout
-
En código java
Public void onSurfaceChanged (GL10 gl, int w, int h) {// necesitas test w> h y solo entonces haz tu inicialización de gráficos …}
- Android Volley método de eliminación, ¿por qué enviar parámetros vacíos
- Android Google Map V2 Pantalla ¿Mostrar y mostrar sólo el botón de zoom?