2013-04-24 13 views
5

Sto scrivendo una determinata applicazione OpenGL in cui mi piacerebbe in particolare disegnare frame in modo incrementale. Per questo, mi piacerebbe disabilitare la cancellazione automatica del buffer che capisco, è il comportamento predefinito di GLSurfaceView.Renderer.onDrawFrame(). Qualcuno può aiutarmi per come farlo? Devo scrivere l'applicazione in Java, non usando l'SDK nativo.Cancellazione automatica del buffer durante l'utilizzo di OpenGL su Android

ho capito che avrei potuto fare questo: -

(1) setting EGL_SWAP_BEHAVIOR_PRESERVED_BIT bit for EGL_SURFACE_TYPE attribute while doing [eglChooseConfig][1](), and 
(2) setting EGL_SWAP_BEHAVIOR attribute to EGL_BUFFER_PRESERVED by calling [eglSurfaceAttrib][2] on the EGLSurface object 

Tuttavia, mi sembra di capire dalla doc Khronos che: -

"EGL_SWAP_BEHAVIOR_PRESERVED_BIT are supported only if the EGL version is 1.4 or greater." 
"EGL_SWAP_BEHAVIOR is supported only if the EGL version is 1.2 or greater." 

Ora, capisco che ho potuto accedere EGL in due modi nella mia applicazione Android: -

(1) use the Khronos API class [EGL10][3] in javax.microedition.khronos.egl package (EGL11 doesn't seem to be implemented yet) 
(2) use the Android API class [EGL14][4] in android.opengl package (similar to using class android.opengl.GLES20) 

il problema con (1) è che la versione è < 1.4 quindi non supporta la funzionalità di cui ho bisogno. Il problema con (2) è che la mia applicazione si blocca semplicemente nel momento in cui chiamo qualsiasi metodo in EGL14, e non sono sicuro di come dovrei usarlo (non sono riuscito a trovare un singolo programma/tutorial di esempio su come EGL14 dovrebbe essere utilizzato in un'app). In particolare, vorrei imparare come ottenere un contesto GL valido da EGL14: nel caso di EGL10, potrei farlo chiamando javax.microedition.khronos.egl.EGLContext.getGL(). Tuttavia, non vedo alcun metodo equivalente in classe android.opengl.EGLContext. Infatti, tutte le classi relative a EGL in android.opengl eccetto EGL14 sembrano essere per lo più vuote.

La mia scommessa migliore è stato quello di seguire la stessa linea di ragionamento, come in caso di GLES20: per chiamare i metodi solo all'interno dei metodi GLSurfaceView.Renderer: onDrawFrame(), onSurfaceCreated(), onSurfaceChanged(), perché questi fornitura valida GL (GL10) ed EGL (EGLConfig) contesti come argomenti. Così ho messo seguente codice all'interno onDrawFrame(): -

public void onDrawFrame(GL10 gl) 
{ 
    ... 
    android.opengl.EGLDisplay d = null; 
    if ((d = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY)) == EGL14.EGL_NO_DISPLAY) { 
     Log.i("Triangle", "EGL14.eglGetDisplay() failed!"); 
    } else { 
     Log.i("Triangle", "EGL14.eglGetDisplay() succeeded!"); 
    } 
    ... 
} 

credo che non avrò istanziare EGL14 prima di chiamare il sopra dal momento che tutti i metodi sono statici. Tuttavia, la chiamata a EGL14.eglGetDisplay() arresta l'app in modo anomalo.

Qualsiasi aiuto sarebbe molto apprezzato, grazie :)

+0

Ciao, stavo affrontando lo stesso problema, e ho appena scoperto che il mio problema era una chiamata a "glColorMask" , dopo aver rimosso la mia chiamata a questo metodo, tutto è stato risolto. Probabilmente la causa del tuo problema è diversa, ma nel caso in cui aiuti il ​​tuo, ti lascio il suggerimento. – PerracoLabs

risposta

0

Invece di usare direttamente EGL, si potrebbe estendere GLSurfaceView e chiamare setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); su init.

Questa impostazione impedisce il ridisegno del frame GLSurfaceView finché non si chiama requestRender(), che è più efficiente per questa app di esempio.

Vedere i documenti android 1 su come configurare GLES con Java.

Building an OpenGL ES Environment

+1

Grazie per la risposta, tuttavia penso che abbiate frainteso la mia domanda. Non desidero controllare quando viene disegnato il nuovo frame (continuo o su richiesta). Quello che voglio è che quando il nuovo frame viene disegnato, non dovrebbe cancellare automaticamente il contenuto del frame precedente (come il comportamento predefinito di onDrawFrame()). In altre parole, i contenuti già disegnati in un frame dovrebbero essere mantenuti e il frame successivo dovrebbe essere disegnato sopra il frame precedente. –

+0

Potresti semplicemente ignorare suDrawFrame per non fare nulla? Se il suo comportamento predefinito è chiamare glClear. – torbjoernwh

1

La versione EGL implementato può essere superiore dell'interfaccia che si sta utilizzando. La versione effettiva viene restituita da EGL10.eglInitialize(). Se è [1,4] o superiore, puoi passare [EGL10.EGL_SURFACE_TYPE, EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT] quando chiami EGL10.eglChooseConfig(). Va bene usare la definizione EGL14 di EGL_SWAP_BEHAVIOR_PRESERVED_BIT qui - è solo un int definito dalla specifica EGL.

In che modo EGL14.eglGetDisplay() arresta l'app in modo anomalo. Sta generando un'eccezione che non viene rilevata?Potrebbe essere utile archiviare un bug (con tutti i dettagli su cosa stai facendo e su quale dispositivo) allo https://code.google.com/p/android/issues/list.

0

Per sviluppare la soluzione di Jesse Hall:

import javax.microedition.khronos.egl.EGL10; 
import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.egl.EGLDisplay; 
import android.opengl.EGL14; 

si può avere una classe interna nella vostra GLSurfaceView sottoclasse che implementa un EGLConfigChooser:

private static class MyEGLConfigChooser implements GLSurfaceView.EGLConfigChooser { 
    public EGLConfig chooseConfig (EGL10 egl, EGLDisplay display) { 
     EGLConfig [] configs = new EGLConfig[1]; 
     int [] num_config = new int[1]; 
     int [] attrib_list = new int[] { 
      EGL10.EGL_RED_SIZE, 8, 
      EGL10.EGL_GREEN_SIZE, 8, 
      // ... + anything else you want ... 
      EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT | EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT, 
      EGL10.EGL_NONE, 
     }; 

     if (egl.eglChooseConfig(display, attrib_list, configs, configs.length, num_config) && num_config[0] > 0) { 
      // We just pick the first here, but you could interrogate all 
      return configs[0]; 
     } 

     return null; 
    } 
} 

nel costruttore della GLSurfaceView sottoclasse, aggiungere:

setEGLConfigChooser(new MyEGLConfigChooser()); 

Quindi, nell'imp ementation del vostro GLSurfaceView.Renderer, ogni volta che i cambiamenti della superficie, è possibile impostare gli attributi su di esso:

public void onSurfaceChanged(GL10 gl, int width, int height) { 
    EGL14.eglSurfaceAttrib(EGL14.eglGetCurrentDisplay(), 
          EGL14.getCurrentSurface(EGL14.EGL_DRAW), 
          EGL14.EGL_SWAP_BEHAVIOR, 
          EGL14.EGL_BUFFER_PRESERVED); 
} 
Problemi correlati