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:

roto

Http://i.imgur.com/4C6ID.png

correcto

Http://i.imgur.com/CNAV0.png

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ó.

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:

  1. AndroidManifest.xml – android:configChanges="keyboard|keyboardHidden|screenSize|orientation"
  2. Su diseño para el uso de la actividad FrameLayout
  3. 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 …}

  • ¿Por qué la matriz generada por el frustumM de Android difiere de la de los Redbook?
  • ¿Cómo deshacerse de los bordes dentados en Android OpenGL ES?
  • ¿Cuál es la forma más fácil de dibujar textura con OpenGL ES?
  • Prevenga onPause de la basura OpenGL Context
  • Java anidado clase interna acceso a las variables de clase externa
  • OpenGL y diseños
  • Juego gratuito de asignación
  • Open GL ES en Android: cómo usar gluUnProject?
  • Android NDK - OpenGL ES Tutorial / Bibliotecas
  • Coordenadas de textura en opengl android mostrando la imagen invertida
  • OpenGL para Android y iPhone
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.