2013-07-01 121 views
5

我们在Nexus发展动态壁纸与OpenGL ES 2.0的10的Nexus 10 - 渲染外部渲染目标只能在景观

动态壁纸使用2小(128×128)外的帧缓冲区,使它们之间的乒乓渲染模糊图像。

虽然这适用于任何设备上(甚至在老年摩托罗拉Milestone)完全没有存在于Nexus 10.一个奇怪的问题,这只能当设备处于横向。如果设备在任何其他位置(90,180或270度)旋转,帧缓冲区只有清晰的颜色。我已经设置glClearColor红色所以很清楚地看到,这些帧缓存被清除,但没有被渲染成他们。

我已经测试过它Tegra 2,Tegra 3,Adreno 200,Adreno 320,2 PowerVR GPUs,它工作得很好。

这看起来有些怪异的驱动程序的bug,但也可能是马里驾驶员的一些具体细节。请指教。

代码摘录。

初始化帧缓冲区:

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: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模糊图像:

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应用程序来再现错误

您可以下载测试APK这里:https://dl.dropboxusercontent.com/u/7197208/LiveWallpaperAnimTest.apk 这是一个动态壁纸应用程序,安装它,并选择“测试”动态壁纸(有玫瑰花的图标)。

正如您所看到的,在默认的横向方向上,您会看到鸟的周围出现一些“绽放”效果,这是由两个帧缓冲区之间的乒乓渲染实现的。在任何其他设备方向上,它都不起作用,并以清晰的颜色(红色)填充FB。

其他链接

我也张贴了这个问题Mali开发中心谷歌代码

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。 此变通办法 - 改变呼叫顺序后,我设法实现正确的渲染。

我建议谷歌联系ARM,在固定驱动程序可用后立即为Nexus 10添加一个固定的OpenGL ES驱动程序。如果有人愿意为这样的事情发生快,你可以在Android的bug跟踪明星的问题:http://code.google.com/p/android/issues/detail?id=57391

链接到我提起这个问题Mali开发中心论坛:由于此驱动程序的bug是 http://forums.arm.com/index.php?/topic/16894-nexus-10-render-to-external-rendertarget-works-only-in-landscape/

验证和ARM确认,请去和星Android issue #57391而不是为这太问题投票。希望这将迫使谷歌关注发行并释放一个固件更新,使得Nexus 10的更好。这是我分配赏金这个问题的原因。

编辑。此错误是最后固定于Android 4.4系统。