RenderTexture Problem

I am developing android app with cocos2dx 0.9.1 on GalaxyTab 10.1.

Everything works fine with CCRenderTexture on this device but I found error when the device goes to lock mode and unlocked.

Any scene using CCRenderTexture crashes or draws abnormal pixels when the device get resumed from unlocked mode.

Anyone have any idea on this issue?

Hook “application will deactivate” event and save CCRenderTexture frame buffer to file. using saveBuffer()

And when application will active, restore it from the file you made. :wink:

어플리케이션이 비활성화 될 당시의 메세지를 받아서, 이미지를 파일로 저장하고
어플리케이션이 다시 활성화 됐을 때 다시 불러오세요.

YoungJae Kwon wrote:

I am developing android app with cocos2dx 0.9.1 on GalaxyTab 10.1.
>
Everything works fine with CCRenderTexture on this device but I found error when the device goes to lock mode and unlocked.
>
Any scene using CCRenderTexture crashes or draws abnormal pixels when the device get resumed from unlocked mode.
>
Anyone have any idea on this issue?

Mark! Very useful information

I have same problem with CCRenderTexture on Android. Could you provide an example, how to hook “application will deactivate” ?
Do I have to modify *.java boilerplate files, provided by cocos2d-x android template project, or more general method of interrupt detection exists in cocos2d-x?

Randy Randomize wrote:

I have same problem with CCRenderTexture on Android. Could you provide an example, how to hook “application will deactivate” ?
Do I have to modify **.java boilerplate files, provided by cocos2d-x android template project, or more general method of interrupt detection exists in cocos2d-x?

To fix the CCRenderTexture bug on Android, you need to keep created render textures to VolatileTexture class too.
This is how I managed the bug.

  1. add following code to AppDelgate class
    void AppDelegate::applicationDidEnterBackground
    {
    #if
    CCTextureCache::sharedTextureCache->addRegisteredRenderTexturesToVolatileTexture;
    #endif
    CCDirector::sharedDirector->pause;
    }
  2. register created CCRenderTexture to TextureCache
    When created, call
    CCRenderTexture**render;
    CCTextureCache::sharedTextureCache()->registerRenderTexture(render);
    .
    .
    .

When released, call
CCTextureCache::sharedTextureCache()~~>unregisterRenderTexture;

I wrote some registration code inside CCTextureCache.cpp. Please refer the following link.


If you look at methods such as “addRegisteredRenderTexturesToVolatileTexture”, “registerRenderTexture”, “unregisterRenderTexture”, “reloadAllTextures” you will find out how it works.
Cheers
~~YoungJae

YoungJae Kwon wrote:

Randy Randomize wrote:
> I have same problem with CCRenderTexture on Android. Could you provide an example, how to hook “application will deactivate” ?
> Do I have to modify **.java boilerplate files, provided by cocos2d-x android template project, or more general method of interrupt detection exists in cocos2d-x?
>
>
To fix the CCRenderTexture bug on Android, you need to keep created render textures to VolatileTexture class too.
>
This is how I managed the bug.
>

  1. add following code to AppDelgate class
    >
    void AppDelegate::applicationDidEnterBackground
    {
    #if
    CCTextureCache::sharedTextureCache->addRegisteredRenderTexturesToVolatileTexture;
    #endif
    >
    CCDirector::sharedDirector->pause;
    }
    >
  2. register created CCRenderTexture to TextureCache
    >
    When created, call
    >
    CCRenderTexture**render;
    CCTextureCache::sharedTextureCache()->registerRenderTexture(render);
    .
    .
    .
    >
    When released, call
    CCTextureCache::sharedTextureCache()~~>unregisterRenderTexture;
    >
    >
    I wrote some registration code inside CCTextureCache.cpp. Please refer the following link.
    https://github.com/yjiq150/cocos2d-x/blob/master/cocos2dx/textures/CCTextureCache.cpp
    >
    If you look at methods such as “addRegisteredRenderTexturesToVolatileTexture”, “registerRenderTexture”, “unregisterRenderTexture”, “reloadAllTextures” you will find out how it works.
    >
    Cheers
    >~~YoungJae

Dear YoungJae,

I try your solution for a whole day without luck. I’m using cocos2dx v2.0.1. First I port your solution, but it has no effect. Then, after examining the code, I see that v2.0.1 implement most the functions in your solution. CCRenderTexture in v2.0.1 (https://github.com/cocos2d/cocos2d-x/blob/gles20/cocos2dx/misc_nodes/CCRenderTexture.cpp) listens to EVENT_COME_TO_BACKGROUND event and calls VolatileTexture::addDataTexture(). So compare to your code, I just need to let CCRenderTexture listen to EVENT_COME_TO_FOREGROUND event and call CCRenderTexture::reloadAfterWakeup() in your solution. Am I right? Sadly, it has no effect.

There seems something wrong with VolatileTexture (https://github.com/cocos2d/cocos2d-x/blob/gles20/cocos2dx/textures/CCTextureCache.cpp), I can’t find where it save texture to disk, so maybe the texture data get lost after locking screen and wakeup. I’m really confused with VolatileTexture. Does it mean the texture never save to disk or that could auto save to disk? How could I fix it?

Dear Le,

I forgot to mention the cocos2dx version i was using. My codes are based on cocos2dx 0.13-beta.
I am sorry, but I am not sure how VolatileTexture is implemented in cocos2dx 2.0 version.

Although I could give you some tips how VolatileTexture works.

VoltileTexture is required because when android app goes to background, the bind between ‘raw texture data’ and ‘opengl texture id’ which is created by “glTexture2D” function is released.( I don’t know why.)
All the raw texture data is still there but only ‘binding’ is released.
So what VolatileTexture do is rebind all the textures which was being used before app went to background.

Other classes like CCSprite keep only the file path for key to rebind later by VolatileTexture.

But render texture has no file path property like CCSprite. That’s why addDataTexture function is necessary.
The raw data which was used to create CCTexture2D inside CCRenderTexture has to be kept for rebinding by VolatileTexture.

Le Yang wrote:

YoungJae Kwon wrote:
> Randy Randomize wrote:
> > I have same problem with CCRenderTexture on Android. Could you provide an example, how to hook “application will deactivate” ?
> > Do I have to modify .java boilerplate files, provided by cocos2d-x android template project, or more general method of interrupt detection exists in cocos2d-x?
>
>
> To fix the CCRenderTexture bug on Android, you need to keep created render textures to VolatileTexture class too.
>
> This is how I managed the bug.
>
> 1. add following code to AppDelgate class
>
> void AppDelegate::applicationDidEnterBackground
> {
> #if
> CCTextureCache::sharedTextureCache->addRegisteredRenderTexturesToVolatileTexture;
> #endif
>
> CCDirector::sharedDirector->pause;
> }
>
> 2. register created CCRenderTexture to TextureCache
>
> When created, call
>
> CCRenderTexture
render;
> CCTextureCache::sharedTextureCache()->registerRenderTexture(render);
> .
> .
> .
>
> When released, call
> CCTextureCache::sharedTextureCache()~~>unregisterRenderTexture;
>
>
> I wrote some registration code inside CCTextureCache.cpp. Please refer the following link.
> https://github.com/yjiq150/cocos2d-x/blob/master/cocos2dx/textures/CCTextureCache.cpp
>
> If you look at methods such as “addRegisteredRenderTexturesToVolatileTexture”, “registerRenderTexture”, “unregisterRenderTexture”, “reloadAllTextures” you will find out how it works.
>
> Cheers
>~~YoungJae
>
Dear YoungJae,
>
I try your solution for a whole day without luck. I’m using cocos2dx v2.0.1. First I port your solution, but it has no effect. Then, after examining the code, I see that v2.0.1 implement most the functions in your solution. CCRenderTexture in v2.0.1 (https://github.com/cocos2d/cocos2d-x/blob/gles20/cocos2dx/misc_nodes/CCRenderTexture.cpp) listens to EVENT_COME_TO_BACKGROUND event and calls VolatileTexture::addDataTexture(). So compare to your code, I just need to let CCRenderTexture listen to EVENT_COME_TO_FOREGROUND event and call CCRenderTexture::reloadAfterWakeup() in your solution. Am I right? Sadly, it has no effect.
>
There seems something wrong with VolatileTexture (https://github.com/cocos2d/cocos2d-x/blob/gles20/cocos2dx/textures/CCTextureCache.cpp), I can’t find where it save texture to disk, so maybe the texture data get lost after locking screen and wakeup. I’m really confused with VolatileTexture. Does it mean the texture never save to disk or that could auto save to disk? How could I fix it?

YoungJae Kwon wrote:

Dear Le,
>
I forgot to mention the cocos2dx version i was using. My codes are based on cocos2dx 0.13-beta.
I am sorry, but I am not sure how VolatileTexture is implemented in cocos2dx 2.0 version.
>
Although I could give you some tips how VolatileTexture works.
>
VoltileTexture is required because when android app goes to background, the bind between ‘raw texture data’ and ‘opengl texture id’ which is created by “glTexture2D” function is released.( I don’t know why.)
All the raw texture data is still there but only ‘binding’ is released.
So what VolatileTexture do is rebind all the textures which was being used before app went to background.
>
>
Other classes like CCSprite keep only the file path for key to rebind later by VolatileTexture.
>
But render texture has no file path property like CCSprite. That’s why addDataTexture function is necessary.
The raw data which was used to create CCTexture2D inside CCRenderTexture has to be kept for rebinding by VolatileTexture.

So the VoltileTexture keep the data, we just need to rebind the texture id on load, right? I examine the cocos2dx v2.0.1 code again and do some testing. v2.0.1 does that stuff and works fine when tap home button and come back.

But it fails (losing texture) when lock screen and awake. I search the web, it seems to relate to the android GLSurfaceView context issue on pause.

YoungJae, did you have that problem once? How you solve it?

Le Yang wrote:

YoungJae Kwon wrote:
> Dear Le,
>
> I forgot to mention the cocos2dx version i was using. My codes are based on cocos2dx 0.13-beta.
> I am sorry, but I am not sure how VolatileTexture is implemented in cocos2dx 2.0 version.
>
> Although I could give you some tips how VolatileTexture works.
>
> VoltileTexture is required because when android app goes to background, the bind between ‘raw texture data’ and ‘opengl texture id’ which is created by “glTexture2D” function is released.( I don’t know why.)
> All the raw texture data is still there but only ‘binding’ is released.
> So what VolatileTexture do is rebind all the textures which was being used before app went to background.
>
>
> Other classes like CCSprite keep only the file path for key to rebind later by VolatileTexture.
>
> But render texture has no file path property like CCSprite. That’s why addDataTexture function is necessary.
> The raw data which was used to create CCTexture2D inside CCRenderTexture has to be kept for rebinding by VolatileTexture.
>
So the VoltileTexture keep the data, we just need to rebind the texture id on load, right? I examine the cocos2dx v2.0.1 code again and do some testing. v2.0.1 does that stuff and works fine when tap home button and come back.
>
But it fails (losing texture) when lock screen and awake. I search the web, it seems to relate to the android GLSurfaceView context issue on pause.
>
YoungJae, did you have that problem once? How you solve it?

Refer to following codes for CCRenderTexture rebinding.

For CCTextureCache class:

void CCTextureCache::reloadAllTextures()
{
#if CC_ENABLE_CACHE_TEXTTURE_DATA
VolatileTexture::reloadAllTextures();
CCTextureCache::sharedTextureCache()~~>rebindRenderTextures;
#endif
}

//added by YoungJae Kwon
// below codes are ANDROID ONLY
void CCTextureCache::rebindRenderTextures
{
// rebind frame buffer used by rendertexture
vector keys = m_pRenderTextures~~>allKeys();
vector::iterator iter;
for (iter = keys.begin(); iter != keys.end(); iter++)
{
CCLog(“RenderTexture rebind, key:%s,”,(*iter).c_str());
m_pRenderTextures->objectForKey(*iter)->reloadAfterWakeup();
#if CC_ENABLE_CACHE_TEXTTURE_DATA
// remove from volatileTexture cache after rebind
VolatileTexture::removeTexture( m_pRenderTextures->objectForKey(*iter)>getSprite>getTexture);
#endif
}
}

For CCRenderTexture class:
// added by YoungJae Kwon
// when app restored from lockscreen in ANDROID, reloaded VolatileTexture should be rebinded to FBO
void CCRenderTexture::reloadAfterWakeup
{
glGetIntegerv;

// generate FBO
ccglGenFramebuffers;
ccglBindFramebuffer;
// associate texture with FBO
ccglFramebufferTexture2D, 0);
// check if it worked )
GLuint status = ccglCheckFramebufferStatus;
if
{
CCAssert;
}
m_pTexture~~>setAliasTexParameters;
ccBlendFunc tBlendFunc = ;
m_pSprite~~>setBlendFunc(tBlendFunc);

ccglBindFramebuffer(CC_GL_FRAMEBUFFER, m_nOldFBO);

}

Hi,
I got the same problem when I activate CC_TEXTURE_CACHE my game get very slooooooow (don’t know why) on last cocos2D 1 release.
When screen lock or going back to home screen and coming back every texture get lost on my game.
As far as I think I have understood (I’m a newbie in java/android), It appear to be an issue with early version of android not being able to maintain multiple gles context.
I followed the last answer from arberg here :

I replaced the GLsurfaceview from android with the one from sdk-15 that support multiple context.
And activated context preservation.

And it worked
The only drawback is that it need gles 2.0 capability and it seems that a lot of qualcom adreno chips does not support multicontext
I put an archive with the modified java files if someone want to test it or integrate it to cocos

joseph pinkasfeld wrote:

Hi,
I got the same problem when I activate CC_TEXTURE_CACHE my game get very slooooooow (don’t know why) on last cocos2D 1 release.
When screen lock or going back to home screen and coming back every texture get lost on my game.
As far as I think I have understood (I’m a newbie in java/android), It appear to be an issue with early version of android not being able to maintain multiple gles context.
I followed the last answer from arberg here :
http://stackoverflow.com/questions/2112768/prevent-onpause-from-trashing-opengl-context
>
I replaced the GLsurfaceview from android with the one from sdk-15 that support multiple context.
And activated context preservation.
>
And it worked
The only drawback is that it need gles 2.0 capability and it seems that a lot of qualcom adreno chips does not support multicontext
I put an archive with the modified java files if someone want to test it or integrate it to cocos

Thanks very much joseph. It works when the android:targetSdkVersion in AndroidManifest.xml <= 12.

Le Yang wrote:

joseph pinkasfeld wrote:
> Hi,
> I got the same problem when I activate CC_TEXTURE_CACHE my game get very slooooooow (don’t know why) on last cocos2D 1 release.
> When screen lock or going back to home screen and coming back every texture get lost on my game.
> As far as I think I have understood (I’m a newbie in java/android), It appear to be an issue with early version of android not being able to maintain multiple gles context.
> I followed the last answer from arberg here :
> http://stackoverflow.com/questions/2112768/prevent-onpause-from-trashing-opengl-context
>
> I replaced the GLsurfaceview from android with the one from sdk-15 that support multiple context.
> And activated context preservation.
>
> And it worked
> The only drawback is that it need gles 2.0 capability and it seems that a lot of qualcom adreno chips does not support multicontext
> I put an archive with the modified java files if someone want to test it or integrate it to cocos
>
Thanks very much joseph. It works when the android:targetSdkVersion in AndroidManifest.xml <= 12.

Hi joseph pinkasfeld:
Your GLSurfaceView multicontext works fine except following issue. When I click home button on android and launch game, it’s ok. But then again I click home button and launch game, I encounter IllegalArgumentException exception, it comes from GLSurfaceView.java:

public EGLSurface createWindowSurface(final EGL10 egl, final EGLDisplay display,
final EGLConfig config, final Object nativeWindow) {
EGLSurface result = null;
try {
result = egl.eglCreateWindowSurface(display, config, nativeWindow, null);
} catch (final IllegalArgumentException e) {
// This exception indicates that the surface flinger surface
// is not valid. This can happen if the surface flinger surface
// has
// been torn down, but the application has not yet been
// notified via SurfaceHolder.Callback.surfaceDestroyed.
// In theory the application should be notified first,
// but in practice sometimes it is not. See b/4588890
Log.e(TAG, “eglCreateWindowSurface”, e);
}
return result;
}

Have you met this exception before, and how to solve it?

No I don’t met this
Can you tell your phone model and android version ?

I use galaxy nexus, android version 4.1, and set minSdkVersion&targetSdkVersion to 7.

joseph pinkasfeld wrote:

No I don’t met this
Can you tell your phone model and android version ?

I use cocos2dx v2.0.2, there’s tiny different with your code, I don’t know whether it matters.
In Cocos2dxGLSurfaceView.java, your code:

protected void initView() {
mRenderer = new Cocos2dxRenderer();
setFocusableInTouchMode(true);
setRenderer(mRenderer);

v2.0.2 code:

public void setCocos2dxRenderer(Cocos2dxRenderer renderer){
mRenderer = renderer;
setRenderer(mRenderer);
}
protected void initView() {
setFocusableInTouchMode(true);

and in ProjectName.java the class ProjectName which extends Cocos2dxActivity, within it onCreate() call:

mGLView.setCocos2dxRenderer(new Cocos2dxRenderer());

I try to change code to exactly like yours, but it raise the exception in GLSurfaceView.java:

private void checkRenderThreadState() {
if (mGLThread != null) {
throw new IllegalStateException(
“setRenderer has already been called for this instance.”);
}
}

Le Yang wrote:

I use galaxy nexus, android version 4.1, and set minSdkVersion&targetSdkVersion to 7.
>
joseph pinkasfeld wrote:
> No I don’t met this
> Can you tell your phone model and android version ?

Hi,
joseph pinkasfeld and Le Yang can you post full solution for cocos2dx v2.0.3? Current problem also cause shader programs. It is easy to reload shaders, but for me redrawing all rendertextures is not that simply.

I don’t have a final solution. Joseph’s solution works fine except the problem I met. In my game, I finally choose to avoid using CCRenderTexture to implement my mask layer.

Danil Valmar wrote:

Hi,
joseph pinkasfeld and Le Yang can you post full solution for cocos2dx v2.0.3? Current problem also cause shader programs. It is easy to reload shaders, but for me redrawing all rendertextures is not that simply.

Why they don’t fix it?
I know about this problem for near 7 months. I was hoping, developers will fix it, when i finish the game. Not cool.

Le Yang wrote:

I don’t have a final solution. Joseph’s solution works fine except the problem I met. In my game, I finally choose to avoid using CCRenderTexture to implement my mask layer.
>
Danil Valmar wrote:
> Hi,
> joseph pinkasfeld and Le Yang can you post full solution for cocos2dx v2.0.3? Current problem also cause shader programs. It is easy to reload shaders, but for me redrawing all rendertextures is not that simply.

Are you serious ? Common guy it’s open source world, the only thing you can do is giving back to the community.
Blaming other people if you can’t fix bugs is not part of the deal …

Danil Valmar wrote:

Why they don’t fix it?
I know about this problem for near 7 months. I was hoping, developers will fix it, when i finish the game. Not cool.
>

Sorry. I didn’t mean to blame someone. It just, this bug pisses me off. I will do my best to find a solution, but i was hoping that people who know engine better then me can fix it easily.
Oh well. joseph pinkasfeld i will try to improve your solution. My first idea was to dump all render textures in file, but i couldn’t finish it.

joseph pinkasfeld wrote:

Are you serious ? Common guy it’s open source world, the only thing you can do is giving back to the community.
Blaming other people if you can’t fix bugs is not part of the deal …
>
Danil Valmar wrote:
> Why they don’t fix it?
> I know about this problem for near 7 months. I was hoping, developers will fix it, when i finish the game. Not cool.
>