2013-07-01 25 views
5

stiamo sviluppando live wallpaper con OpenGL ES 2.0 sul Nexus 10.Nexus 10 - rendere a renderTarget esterno funziona solo nel paesaggio

carta da parati Live utilizza 2 piccoli (128x128) framebuffer esterni per fare il rendering ping-pong tra di loro per sfocare l'immagine.

Mentre questo funziona perfettamente su qualsiasi dispositivo (anche su Motorola Milestone invecchiato) c'è un problema strano con Nexus 10. Funziona solo se il dispositivo è in orientamento orizzontale. Se il dispositivo viene ruotato in qualsiasi altra posizione (90, 180 o 270 gradi) i frame buffer hanno solo colori chiari. Ho impostato glClearColor in rosso, quindi è chiaramente visibile che questi framebuffer sono cancellati ma non viene eseguito il rendering di alcun elemento.

L'ho provato su Tegra 2, Tegra 3, Adreno 200, Adreno 320, 2 GPU PowerVR e funziona perfettamente.

Questo sembra un qualche strano bug del driver, ma potrebbe anche essere qualche dettaglio del driver Mali. Per favore consiglio

Estratti di codice.

Init framebuffer:

private void initBloomStuff() { 
    mBloomTextureID = loadTexture("textures/empty128.png"); 
    mBloomVertTextureID = loadTexture("textures/empty128.png"); 

    mBloomFBHeight = 128; 
    mBloomFBWidth = 128; 

    float blurSize = 1.0f; 

    // Texel offset for blur filter kernel 
    m_fTexelOffset = 1.0f/mBloomFBWidth/blurSize; 

    ByteBuffer tmpFB, tmpRB; 
    IntBuffer handle, renderbuffers; 
    int result; 

    tmpFB = ByteBuffer.allocateDirect(4); 
    tmpFB.order(ByteOrder.nativeOrder()); 
    handle = tmpFB.asIntBuffer(); 
    GLES20.glGenFramebuffers(1, handle); 
    framebufferHandle = handle.get(0); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBloomTextureID); 
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, framebufferHandle); 
    GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, mBloomTextureID, 0); 

    checkGlError("FB 1"); 
    tmpRB = ByteBuffer.allocateDirect(4); 
    renderbuffers = tmpRB.asIntBuffer(); 
    GLES20.glGenRenderbuffers(1, renderbuffers); 
    checkGlError("FB 1 - glGenRenderbuffers"); 
    depthbufferHandle = renderbuffers.get(0); 
    GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthbufferHandle); 
    checkGlError("FB 1 - glBindRenderbuffer"); 
    GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, mBloomFBWidth, mBloomFBHeight); 
    checkGlError("FB 1 - glRenderbufferStorage"); 
    GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, depthbufferHandle); 
    checkGlError("FB 1 - glFramebufferRenderbuffer"); 

    result = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER); 
    if (result != GLES20.GL_FRAMEBUFFER_COMPLETE) { 
     Log.d(TAG, "Error creating framebufer 1: " + result); 
    } else { 
     Log.d(TAG, "Created framebufer 1: " + result); 
    } 

    GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, 0); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); 
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 

    tmpFB = ByteBuffer.allocateDirect(4); 
    tmpFB.order(ByteOrder.nativeOrder()); 
    handle = tmpFB.asIntBuffer(); 
    GLES20.glGenFramebuffers(1, handle); 
    framebufferVertHandle = handle.get(0); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBloomVertTextureID); 
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, framebufferVertHandle); 
    GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, mBloomVertTextureID, 0); 

    checkGlError("FB 2"); 
    tmpRB = ByteBuffer.allocateDirect(4); 
    renderbuffers = tmpRB.asIntBuffer(); 
    GLES20.glGenRenderbuffers(1, renderbuffers); 
    checkGlError("FB 2 - glGenRenderbuffers"); 
    depthbufferVertHandle = renderbuffers.get(0); 
    GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthbufferVertHandle); 
    checkGlError("FB 2 - glBindRenderbuffer"); 
    GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, mBloomFBWidth, mBloomFBHeight); 
    checkGlError("FB 2 - glRenderbufferStorage"); 
    GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, depthbufferVertHandle); 
    checkGlError("FB 2 - glFramebufferRenderbuffer"); 

    result = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER); 
    if (result != GLES20.GL_FRAMEBUFFER_COMPLETE) { 
     Log.d(TAG, "Error creating framebufer 2: " + result); 
    } else { 
     Log.d(TAG, "Created framebufer 2: " + result); 
    } 

    GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, 0); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); 
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 

    mTriangleVerticesVignette = ByteBuffer.allocateDirect(mQuadTriangles.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); 
    mTriangleVerticesVignette.put(mQuadTriangles).position(0); 
} 

rendere a FB:

GLES20.glUseProgram(mProgram); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mStemTextureID); 
    drawBird(); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mSphereTextureID); 
    drawSphere(); 

    GLES20.glViewport(0, 0, mBloomFBWidth, mBloomFBHeight); 
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, framebufferHandle); 
    // GLES20.glBindRenderbuffer(GLES20.GL_FRAMEBUFFER, depthbufferHandle); 

    GLES20.glClearColor(1.0f, 0.5f, 0.5f, 1.0f); 
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mStemTextureID); 
    drawBird(); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mSphereTextureID); 
    drawSphere(); 

    GLES20.glViewport(0, 0, screenWidth, screenHeight); 
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 
    // GLES20.glBindRenderbuffer(GLES20.GL_FRAMEBUFFER, 0); 

il rendering da ping-pong tra 2 FB per sfocare immagine:

GLES20.glUseProgram(mBloomProgram); 
    GLES20.glUniform1i(mBloom_sTexture, 0); 
    GLES20.glUniform1f(mBloom_bloomFactor, 0.8f); 

    GLES20.glActiveTexture(GL10.GL_TEXTURE0); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBloomTextureID); 
    GLES20.glViewport(0, 0, mBloomFBWidth, mBloomFBHeight); 
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, framebufferVertHandle); 
    GLES20.glUniform1f(mBloom_TexelOffsetX, m_fTexelOffset); 
    GLES20.glUniform1f(mBloom_TexelOffsetY, 0.0f); 
    GLES20.glActiveTexture(GL10.GL_TEXTURE0); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBloomTextureID); 
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 
    drawBloom(); 
    GLES20.glViewport(0, 0, screenWidth, screenHeight); 
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 

    GLES20.glActiveTexture(GL10.GL_TEXTURE0); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBloomVertTextureID); 
    GLES20.glViewport(0, 0, mBloomFBWidth, mBloomFBHeight); 
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, framebufferHandle); 
    GLES20.glUniform1f(mBloom_TexelOffsetX, 0.0f); 
    GLES20.glUniform1f(mBloom_TexelOffsetY, m_fTexelOffset); 
    GLES20.glActiveTexture(GL10.GL_TEXTURE0); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBloomVertTextureID); 
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 
    drawBloom(); 
    GLES20.glViewport(0, 0, screenWidth, screenHeight); 
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 

    GLES20.glActiveTexture(GL10.GL_TEXTURE0); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBloomTextureID); 
    GLES20.glViewport(0, 0, mBloomFBWidth, mBloomFBHeight); 
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, framebufferVertHandle); 
    GLES20.glUniform1f(mBloom_TexelOffsetX, m_fTexelOffset/2); 
    GLES20.glUniform1f(mBloom_TexelOffsetY, m_fTexelOffset/2); 
    GLES20.glActiveTexture(GL10.GL_TEXTURE0); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBloomTextureID); 
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 
    drawBloom(); 
    GLES20.glViewport(0, 0, screenWidth, screenHeight); 
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 

applicazione prova a riprodurre bug

È possibile scaricare l'APK di test qui: https://dl.dropboxusercontent.com/u/7197208/LiveWallpaperAnimTest.apk È un'applicazione di sfondo animato, installarlo e selezionare "Test" live wallpaper (ha un'icona con rose).

Come potete vedere, nell'orientamento orizzontale predefinito vedrete un effetto "bloom" attorno all'uccello che viene implementato dal rendering ping-pong tra 2 framebuffer. In qualsiasi altro orientamento del dispositivo non funziona e riempie FB con colore chiaro (rosso).

Ulteriori link

ho anche postato questo problema a Mali Developer Center e Google Code:

http://forums.arm.com/index.php?/topic/16894-nexus-10-render-to-external-rendertarget-works-only-in-landscape/

http://code.google.com/p/android/issues/detail?id=57391

risposta

1

Mali supporto conducente conferma squadra che questo è un bug del driver e lo risolverà nella prossima versione del driver. Come soluzione temporanea, propongono di chiamare glViewport dopo glBindFramebuffer. Questa soluzione funziona, dopo aver modificato l'ordine delle chiamate sono riuscito a ottenere il rendering corretto.

Ho proposto a Google di contattare ARM per includere un driver ES OpenGL fisso per Nexus 10 non appena è disponibile il driver fisso.Se qualcuno è disposto perché questo avvenga più rapidamente, è possibile classificare un problema nel bug di Android Tracker: http://code.google.com/p/android/issues/detail?id=57391

Link Mali forum Developer Center, dove ho depositato questo problema: http://forums.arm.com/index.php?/topic/16894-nexus-10-render-to-external-rendertarget-works-only-in-landscape/

Come questo driver bug è verificato e confermato da ARM, per favore vai a stella Android issue #57391 invece di votare per questa domanda SO. Speriamo che questo costringa Google a prestare attenzione al problema ea rilasciare un aggiornamento del firmware, rendendo Nexus 10 migliore. Questo è il motivo per cui ho assegnato la taglia per questa domanda.

MODIFICA. Questo bug è stato finalmente risolto in Android 4.4.

Problemi correlati