Andreno gpu bug? CCRenderTexture lost texture when goes into the background in 2.2

Hi all,

I just upgrade my app from cocos2dx 2.1.4 to 2.2, but my two CCRenderTexture sprite will become black when the app comes back from background, it doesn’t happen in 2.1.4. I test on Galaxy S3 with OS 4.1.1.

Thanks:)

Update1: I then test some phones the problem is still there, the only phone works is Galaxy note 2 on OS 4.1.2, any thoughts?

following is the error info I got:
10-09 17:04:58.402: E/Adreno200-ES20(4020): <qgl2DrvAPI_glFramebufferTexture2D:1282>: GL_INVALID_OPERATION
10-09 17:04:58.452: D/cocos2d-x debug info(4020): OpenGL error 0x0502 in /Users/suyuzhang/Documents/cocos2d-x-2.2.0/projects/RockTheVault/proj.android/…/…/…/cocos2dx/misc_nodes/CCRenderTexture.cpp begin 407

Update2:
I looked into CCRenderTexture.cpp line 407, it saids

“Certain Qualcomm Andreno gpu’s will retain data in memory after a frame buffer switch which corrupts the render to the texture. The solution is to clear the frame buffer before rendering to the texture. However, calling glClear has the unintended result of clearing the current texture. Create a temporary texture to overcome this. At the end of CCRenderTexture::begin(), switch the attached texture to the second one, call glClear, and then switch back to the original texture. This solution is unnecessary for other devices as they don’t have the same issue with switching frame buffers.”

Not working device is Galaxy S3 T-mobile which has Andreno gpu, the working device is Galaxy note 2 which doesn’t have Andreno gpu.

Then I comment following codes, everything works fine

if (CCConfiguration::sharedConfiguration()>checkForGLExtension)
{
m_pTextureCopy = new CCTexture2D;
if
{
m_pTextureCopy
>initWithData(data, (CCTexture2DPixelFormat)m_ePixelFormat, powW, powH, CCSizeMake((float)w, (float)h));
}
else
{
break;
}
}
……
if (CCConfiguration::sharedConfiguration()->checkForGLExtension(“GL_QCOM”))
{
// — bind a temporary texture so we can clear the render buffer without losing our texture
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTextureCopy->getName(), 0);
CHECK_GL_ERROR_DEBUG();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTexture->getName(), 0);
}

I think there should be a bug somewhere.

Thanks:)

Somethings tells me that it’s quite unreliable. Consider a situation when the user switches from your brilliant game to some heavy ugly app which requires all RAM. Android will unload your game from the memory and OpenGL ES won’t automagically dump your textures to the filesystem and restore them when the user switches back to the game. So its your responsibility to restore those textures.

Thank you for your report.
I think you can comment these codes.

  1. As the line 407 suggests, that some old driver of “GL_QCOM” (HTC g10, android 2.3.3 and older) will retain some data when init renderTarget(FBOs, DepthAttachments, ColorAttachments etc). So glClear function is called to clear the FBO attachments to the data you specified. In the new version of anroid phone( HTC G14, android 4.0), the init of renderTargets will not retain data.
  2. I tested the black block based on sample “Testing issue #937”. The black block happens because we need to save the “rendered” texture result to memory when our app goes background. then we need to call renderTexture::begin() to bind renderTexture FBO. So the glClear function is called which we do not want to. There is an interesting bug here. My newer G14 will have a black block but the older G10 will behave nothing wrong. I will go further to find the reason.

Please use a temp solution.

  1. comment the codes as you have done before.
  2. if the FBO need a clear, please call glClear() manually.

Thanks so much for your info:)

huabing xu wrote:

Thank you for your report.
I think you can comment these codes.

  1. As the line 407 suggests, that some old driver of “GL_QCOM” (HTC g10, android 2.3.3 and older) will retain some data when init renderTarget(FBOs, DepthAttachments, ColorAttachments etc). So glClear function is called to clear the FBO attachments to the data you specified. In the new version of anroid phone( HTC G14, android 4.0), the init of renderTargets will not retain data.
  2. I tested the black block based on sample “Testing issue #937”. The black block happens because we need to save the “rendered” texture result to memory when our app goes background. then we need to call renderTexture::begin() to bind renderTexture FBO. So the glClear function is called which we do not want to. There is an interesting bug here. My newer G14 will have a black block but the older G10 will behave nothing wrong. I will go further to find the reason.
    >
    Please use a temp solution.
  3. comment the codes as you have done before.
  4. if the FBO need a clear, please call glClear() manually.

I’m encounter this issue too. I already comment the code like suyu zhang said, but it doesn’t works. Am I right place the comment like this?

if (CCConfiguration::sharedConfiguration()->checkForGLExtension("GL_QCOM"))
    {
            /* COMMENT HERE?
            m_pTextureCopy = new CCTexture2D();
            if (m_pTextureCopy)
        {
                m_pTextureCopy->initWithData(data, (CCTexture2DPixelFormat)m_ePixelFormat, powW, powH, CCSizeMake((float)w, (float)h));
            }
            else
        {
                break;
            }
        }
            */ //CLOSE COMMENT?
      ......
    if (CCConfiguration::sharedConfiguration()->checkForGLExtension("GL_QCOM"))
{
            /* COMMENT HERE AGAIN?
        // -- bind a temporary texture so we can clear the render buffer without losing our texture
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTextureCopy->getName(), 0);
        CHECK_GL_ERROR_DEBUG();
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTexture->getName(), 0);
            */ AND CLOSE HERE?
    }

And could you tell me more details how to glClear() the FBO? I’m not familiar with OpenGL.
And how about clear the frame buffer before rendering to the texture. Is it works? how can I do this in the code? thanks

I have a similar issue.
It happens when I change my CCLabelTTF’s string using setString() when the Facebook login popup is dismissed.

Try commenting this code in CCRenderTexture.cpp, It worked for me

CCNotificationCenter::sharedNotificationCenter()->addObserver(this,
                                                              callfuncO_selector(CCRenderTexture::listenToBackground),
                                                              EVENT_COME_TO_BACKGROUND,
                                                              NULL);

CCNotificationCenter::sharedNotificationCenter()->addObserver(this,
                                                              callfuncO_selector(CCRenderTexture::listenToForeground),
                                                              EVENT_COME_TO_FOREGROUND, // this is misspelt
                                                              NULL);