BUG with texture->beginWithClear(0, 0, 0, 0, 0, 0) on Kindle Fire (android)

* Please read the note in the next comment below*

I have a class derived from CCNode. The CCSprite object is NOT added to the CCNode as a child; instead the CCNode keeps a pointer to the CCSprite (you will see why in a minute). I subclass the draw() method and then draw my CCSprite at multiple locations on the screen. This works correctly for all circumstances except one.

If you press the power button (which minimizes the app and turns off the display), then restore the power and return to the app, I now have the background that was beneath my CCNode gone, and there is a “copy” of my sprite that was drawn multiple times left on the screen along with the new copies that are currently being drawn.

The code is like this:

MyNode::MyNode()
{

    m_pTexture = NULL;
    m_pSprite = NULL;
}

MyNode::myInit( CCSprite *pSprite )
{
    CCSize size = CCDirector::sharedDirector()->getWinSize();

    m_pSprite = pSprite;
    m_pSprite->setAnchorPoint( ccp( 0.5f, 0.5f ) );

    m_pTexture = CCRenderTexture::create( (int)size.width, (int)size.height, kCCTexture2DPixelFormat_RGBA8888 );

    setContentSize( CCSize( size.width, size.height ) );
    m_pTexture->setPosition( ccp( ((int)size.width)>>1, ((int)size.height)>>1 ) );

    addChild( m_pTexture );
}

MyNode::draw()
{

    if ( !m_pTexture )
    return;

    // Begin the texture
    m_pTexture->beginWithClear( 0, 0, 0, 0 );

    m_pSprite->setVisible( true );

    for( int i=0;i<5;i++ )
    {
        m_pSprite->setPosition( ccp( i*200 + 110, 384 ) );
        m_pSprite->visit();
    }

    // End the texture
    m_pTexture->end();

    m_pSprite->setVisible( false );
}

The code above works fine on Windows, iOS and Android for normal drawing. The only issue is when I minimize the app on Android and then restore, it doesn’t restore properly.

This seems to be some sort of OpenGL state issue, but I am not sure what it is. Does anyone have any ideas?

Ken

You can duplicate the same issue using the TestCpp example. Run it on a Kindle Fire, then go to the RenderTextureTest menu item. Start drawing on the texture with your finger, then press the power button to minimize the app, then restore it.

When the app comes back and you try to draw on the screen it will appear as though you aren’t doing anything. In fact you are, but the old texture is on top of everything so you cannot see your new drawing.

This code does the same thing we are doing. It appears to be related to the texture->beginWithClear(0, 0, 0, 0, 0, 0); call. Of course if you just use a begin() call then it won’t clear the buffer so you get garbage, so this isn’t the right fix.

Hopefully, by eliminating the code we are using and showing this issue in the sample that ships with Cocos2d-x, we can get someone to look at it.

hello, do you resolve this issue?

thanks
Don

What we had to do was add in a “hack” to our app code and make sure we recreate any textures we were doing this with, in:

void AppDelegate::applicationWillEnterForeground()

Hi Ken, if you are resolved issue of RenderTextureTest in the TestCpp you could be my savior.

Referring to testcpp, would you be so kind as to tell me how you can fix the RenderTextureTest?

thanks
Don

Don,

Our solution was really just a hack. We couldn’t figure out how to fix Cocos2d-x so it wouldn’t cause this.

What you need to do is make the object that contains the render texture a global, and add a method to that class to recreate the render texture. Then do something like this:

void AppDelegate::applicationWillEnterForeground()
{
    // Whatever you currently do here
    if ( g_pMyGlobalRenderObj )
    {
        g_pMyGlobalRenderObj->RecreateRenderTexture();
    }
}

Hopefully that makes sense to you. As I said, this is just a hack, not really the right way to “solve” the bug in Cocos2d-x.

Which Kindle are you using? I could not repro in TestCpp on the newest one?

We have 5 different Kindle Fire devices, from the 2nd Gen Kindle Fire all the way up to the Kindle Fire 7" HDX. The RenderTest portion of the TestCPP does this on all of the devices.

Ken

I have Kindle HD 7" (no latest model HDX)

with POWERVR SGX540 graphics card

But same issue happens with:

*** Samsung Galaxy S Plus
LogCat Error:
OpenGL error 0x0502 in myPath/Cpp/TestCpp/proj.android/…/…/…/…/cocos2dx/misc_nodes/CCRenderTexture.cpp begin 407
OpenGL error 0x0502 in myPath/Cpp/TestCpp/proj.android/…/…/…/…/cocos2dx/sprite_nodes/CCSprite.cpp draw 584
*** Nexus 7 (new model HD with Android 4.4.2 and Adreno 320)
LogCat Error:
same as above, and one more: W/Adreno-ES20(6383): <core_glFramebufferTexture2D:2341>: GL_INVALID_OPERATION

** Asus TF300 (Android 2.2.1 and Tegra 3)
No LogCat Error

I’ve done this test with original TestCPP 2.2.1.
I’m surprised that there are so few post about that, maybe drawing on a render texture is a little used feature.

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