2013-07-01 15 views
5

Wir mit OpenGL ES 2.0 Live-Wallpaper sind die Entwicklung auf dem Nexus 10.Nexus 10 - machen zu externen rendertarget funktioniert nur in der Landschaft

Live-Tapete verwendet 2 klein (128x128) externen Framebuffer Pingpong-Rendering zwischen ihnen zu machen um das Bild zu verwischen.

Während dies auf jedem Gerät einwandfrei funktioniert (sogar auf alten Motorola Milestone), gibt es ein seltsames Problem mit Nexus 10. Dies funktioniert nur, wenn das Gerät im Querformat ausgerichtet ist. Wenn das Gerät in einer anderen Position gedreht wird (90, 180 oder 270 Grad), hat der Framebuffer nur eine klare Farbe. Ich habe glClearColor auf rot gesetzt, so dass deutlich sichtbar ist, dass diese Framebuffer gelöscht sind, aber nichts in ihnen gerendert wird.

ich es auf Tegra 2 getestet haben, Tegra 3, Adreno 200, Adreno 320, 2 PowerVR GPUs und es funktioniert gut.

Dies sieht aus wie ein seltsamer Treiber Bug, könnte aber auch einige Besonderheiten des Mali Treibers sein. Bitte um Rat.

Codeauszüge.

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); 
} 

auf FB RENDER:

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); 

Pingpong-Rendering zwischen 2 FBs Bild zu verwischen:

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); 

Test-Anwendung Fehler zu reproduzieren

Sie können Test APK hier herunterladen: https://dl.dropboxusercontent.com/u/7197208/LiveWallpaperAnimTest.apk Es ist ein Live Wallpaper App, installieren Sie es und wählen Sie "Test" Live Wallpaper (hat ein Symbol mit Rose).

Wie Sie sehen können, sehen Sie in der Standard-Querformatausrichtung einen Bloom-Effekt um den Vogel herum, der durch Ping-Pong-Rendering zwischen 2 Framebuffern implementiert wird. Bei jeder anderen Geräteausrichtung funktioniert es nicht und füllt FB mit klarer Farbe (rot).

Weiterführende Links

Ich habe auch dieses Problem zu Mali Developer Center veröffentlicht und 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

Antwort

1

Mali Treiber-Support-Team bestätigt Das ist ein Treiberfehler und wird es beheben in der nächsten Treiberversion. Als vorübergehende Lösung schlagen sie vor, glViewport nach glBindFramebuffer aufzurufen. Diese Problemumgehung funktioniert - nachdem ich die Reihenfolge der Aufrufe geändert habe, habe ich das korrekte Rendering erreicht.

Ich habe Google vorgeschlagen, sich an ARM zu wenden, um einen festen OpenGL ES-Treiber für Nexus 10 zu integrieren, sobald ein fester Treiber verfügbar ist.Wenn jemand bereit ist, für diese schneller passieren, können Sie ein Problem in Android Bug-Tracker Star: http://code.google.com/p/android/issues/detail?id=57391

Link zu Mali Developer Center Foren, in denen ich dieses Thema eingereicht haben: http://forums.arm.com/index.php?/topic/16894-nexus-10-render-to-external-rendertarget-works-only-in-landscape/

Da dieser Treiber Bug Verifiziert und bestätigt von ARM, bitte gehen Sie und Sterne Android issue #57391 statt für diese SO Frage zu stimmen. Hoffentlich zwingt Google Google dazu, auf das Problem zu achten und ein Firmware-Update zu veröffentlichen, das Nexus 10 besser macht. Dies ist der Grund, warum ich Kopfgeld für diese Frage vergeben habe.

BEARBEITEN. Dieser Bug ist endlich in Android 4.4 behoben.