2013-07-01 11 views
5

に私たちは10ネクサス10 - 外部レンダーターゲットにレンダリングするには、唯一の風景

ライブ壁紙は、それらの間でピンポンレンダリングを行うために2小(128×128)の外部フレームバッファを使用していますネクサス上のOpenGL ES 2.0とのライブ壁紙を開発している作品画像をぼかします。

Nexus 10でこれが問題になります。これは、デバイスが(老化したMotorola Milestoneであっても)完璧に機能しますが、デバイスが横向きの場合にのみ機能します。デバイスを他の任意の位置(90度、180度または270度)で回転させると、フレームバッファの色が鮮明になります。私はglClearColorを赤色に設定しているので、これらのフレームバッファがクリアされていても何も描画されていないことがはっきりとわかります。

私はTegra 2、Tegra 3、Adreno 200、Adreno 320,2 PowerVR GPUでテストしましたが、うまく動作します。

これはいくつかの不思議なドライバのバグのようですが、Maliドライバのいくつかの特徴かもしれません。ご意見をお聞かせください。

コード抜粋。

初期フレームバッファ:

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

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

ピンポン​​は、画像をぼかす2つのFBの間のレンダリング:バグを再現する

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

テストアプリケーション

ここにテストAPKをダウンロードすることができます:https://dl.dropboxusercontent.com/u/7197208/LiveWallpaperAnimTest.apk ライブ壁紙アプリです。インストールし、「テスト」ライブ壁紙(バラのアイコン付き)を選択します。

デフォルトの横向きの向きでは、2つのフレームバッファの間でピンポンレンダリングによって実装される鳥の周りに「ブルーム」効果が表示されます。それ以外のデバイスの向きでは機能しませんし、FBをクリアカラー(赤色)で塗りつぶします。

追加リンク

私もマリデベロッパーセンター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

答えて

1

マリドライバサポートチームの確認これはドライバのバグであり、修正する次のドライババージョンで。一時的な回避策として、glBindFramebufferの後にglViewportを呼び出すことを提案します。 この回避策は機能します - 呼び出し順序を変更した後、私は正しいレンダリングを達成することができました。

私は、固定ドライバが利用可能になるとすぐに、Nexus 10用の固定OpenGL ESドライバをARMに連絡するようGoogleに提案しました。これはより速く起こることのために、誰もが喜んでいる場合は、Androidのバグトラッカーに問題が主演することができます:私は、この問題を提起してきたマリデベロッパーセンターフォーラムへhttp://code.google.com/p/android/issues/detail?id=57391

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

このドライバのバグとしてあります確認され、ARMによって確認されて、このSOの質問に投票するのではなく、Android issue #57391にスターをしてください。うまくいけば、Googleに注意を払ってファームウェアのアップデートを発行してリリースして、Nexus 10をより良くすることができたらうれしいです。これが私がこの質問に対して賞金を割り当てた理由です。

EDIT。このバグは最終的にAndroid 4.4で修正されました。