2013-06-09 15 views
6

sto avendo la seguente situazione:Cosa superficie da utilizzare per eglMakeCurrent per il contesto che rende solo in FBO

In un cross-platform libreria di rendering per iOS e Android (scritti in C (++)), ho due thread che hanno entrambi bisogno del proprio EGLContext: Il thread A è il thread principale; rende alla finestra. Il thread B è un thread generatore, che esegue vari calcoli e restituisce i risultati in trame che vengono successivamente utilizzate dalla filettatura A.

Poiché non è possibile utilizzare EGL su iOS, la libreria utilizza i puntatori di funzione Obj statici.- C funziona per creare un nuovo contesto e impostarlo corrente. Questo funziona già, Creo contesto del filo A utilizzando

EAGLContext *contextA = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 

Il contesto del filo B viene creata usando

EAGLContext *contextB = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:[contextA sharegroup]]; 

posso quindi impostare una delle due correnti:

[EAGLContext setCurrentContext:context]; 

Per utilizzare la stessa logica (i puntatori di funzione passati alla libreria) su Android, voglio farlo nel lato C dei bind JNI, questa volta utilizzando EGL reale anziché EAGL di Apple. Posso facilmente creare contextA usando WindowSurface e la finestra nativa, posso creare contextB e passare contextA al parametro shareContext della chiamata eglCreateContext.

Ma quando voglio rendere corrente contestoB, devo passare una superficie alla chiamata eglMakeCurrent, e sto cercando di capire che tipo di superficie passare lì.

  • non posso usare il WindowSurface io uso per Contexta come spec dice nella sezione 3.7 che "al più un contesto per ogni API client supportato può essere corrente in un particolare filo in un dato momento, e al massimo un contesto può essere legato a una particolare superficie in un dato momento. "
  • Non riesco a specificare EGL_NO_SURFACE, perché ciò comporterebbe un errore EGL_BAD_MATCH nella chiamata eglMakeCurrent.
  • Sembra che potrei usare una superficie PBuffer, ma esita perché dovrei specificare la larghezza e l'altezza quando creo una tale superficie, e il thread B potrebbe voler creare trame di dimensioni diverse. In aggiunta a ciò, lo "OpenGL ES 2.0 Programming Guide" di Munshi, Ginsburg e Shreiner afferma nella sezione 3.8 che "I Pbuffer sono spesso usati per generare mappe di texture. Se tutto quello che vuoi è renderizzare su una texture, ti consigliamo di usare oggetti framebuffer [.. .] invece di pbuffers perché sono più efficienti", che è esattamente quello che voglio fare in filo B.

non capisco cosa Munshi, Ginsurg e Shreiner dire con quella frase, come sarebbe un framebuffer oggetto essere una sostituzione di una superficie pbuffer? Cosa succede se creo una superficie pbuffer molto piccola (ad esempio 1x1px) per rendere corrente il contesto - posso quindi eseguire il rendering in FBO arbitrariamente grandi? Ci sono altre possibilità di cui non sono ancora a conoscenza?

Grazie mille per il vostro aiuto!

risposta

2

ho finito per usare una superficie pBuffer (1x1 dimensioni) - Ho quindi creare un FBO e rendere in trame più che bene. Per visualizzarli (in un thread diverso e in un diverso contesto (condiviso) opengl), uso una superficie Windows con una finestra ANative (ce ne è un esempio da qualche parte nel sdk).

3

La superficie che si passa a eglMakeCurrent() deve essere una superficie EGL da eglCreateWindowSurface().Per esempio:

EGLSurface EglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, maEGLconfigs[0], surfaceTexture, null); 
    mEgl.eglMakeCurrent(mEglDisplay, EglSurface, EglSurface, mEglContext); 

Ma, eglCreateWindowSurface() richiede un SurfaceTexture che è fornito al callback onSurfaceTextureAvailable() quando viene creata una TextureView, ma è anche possibile creare SurfaceTextures off-schermo senza alcun View.

c'è un app esempio che utilizza TextureView nel SDK di Android qui, anche se usa il SurfaceTexture per la videocamera, piuttosto che rendering OpenGL ES:

sources\android-17\com\android\test\hwui\GLTextureViewActivity.java 

Per impostazione predefinita, la superficie EGL per FBO avrà la stesse dimensioni di SurfaceTexture da cui sono stati creati. È possibile modificare le dimensioni di un SurfaceTexture con:

surfaceTexture.setDefaultBufferSize(width, height); 

Non utilizzare pbuffers su Android perché alcune piattaforme (Nvidia Tegra) non li supportano. Questo articolo spiega i vantaggi di FBO oltre pbuffers in dettaglio:

http://processors.wiki.ti.com/index.php/Render_to_Texture_with_OpenGL_ES

+1

Potrebbe spiegare come è possibile creare un SurfaceTexture fuori dallo schermo senza alcun punto di vista? So che è una domanda ampia, ma bastano pochi suggerimenti. –

+0

In sostanza, si utilizza il nuovo operatore, in questo modo: mSurfaceTexture = new SurfaceTexture (1); mSurfaceTexture.setDefaultBufferSize (miMaxWidth, miMaxHeight); – ClayMontgomery

+0

Può essere fatto da codice nativo? Ho provato a usare SurfaceTexture (inclusa l'intestazione da framework/native/include/gui/SurfaceTexture.h) ma ottengo ancora un errore di compilazione: la dichiarazione di SurfaceTexture non può essere trovata in questo ambito. –

0

Se il disegno su FBO è l'unica cosa che vuoi fare, puoi afferrare qualsiasi EGLContext già creato da te o da qualcun altro (ad esempio GLSurfaceView) e renderlo attuale, quindi devi solo generare il tuo FBO e disegnare con esso. Il problema è come condividere il contesto diciamo creato da GLSurfaceView alla tua libreria C++ multipiattaforma. L'ho fatto richiamando una funzione statica all'interno del C++ per ottenere eglcontext e superficie immediatamente dopo che il contesto è stato reso corrente dal livello Java. come il codice qui sotto:

//This is a GLSurfaceView renderer method 
@override 
public void onSurfaceCreated(GL10 gl, EGLConfig config) { 
    //up to this point, we know the EGLContext 
    //has already been set current on this thread. 
    //call JNI function to setup context 
    graphics_library_setup_context(); 
} 

il C++ controparte

void setup_context() { 
    context = eglGetCurrentContext(); 
    display = eglGetCurrentDisplay(); 
    surface = eglGetCurrentSurface(EGL_DRAW); 
}