mirror of https://github.com/axmolengine/axmol.git
Fix for CCRenderTexture on Android sleep/resume
When an android app goes into the background, all gl context is lost, including any frame buffer objects that are required for rendering to a texture. When the android app returns to focus, a new FBO is generated for each render texture allowing rendering to the texture to continue.
This commit is contained in:
parent
c53cfe88a7
commit
132a76d801
|
@ -59,12 +59,19 @@ CCRenderTexture::CCRenderTexture()
|
|||
, m_nClearStencil(0)
|
||||
, m_bAutoDraw(false)
|
||||
{
|
||||
#if CC_ENABLE_CACHE_TEXTURE_DATA
|
||||
// Listen this event to save render texture before come to background.
|
||||
// Then it can be restored after coming to foreground on Android.
|
||||
CCNotificationCenter::sharedNotificationCenter()->addObserver(this,
|
||||
callfuncO_selector(CCRenderTexture::listenToBackground),
|
||||
EVENT_COME_TO_BACKGROUND,
|
||||
NULL);
|
||||
|
||||
CCNotificationCenter::sharedNotificationCenter()->addObserver(this,
|
||||
callfuncO_selector(CCRenderTexture::listenToForeground),
|
||||
EVNET_COME_TO_FOREGROUND, // this is misspelt
|
||||
NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
CCRenderTexture::~CCRenderTexture()
|
||||
|
@ -79,28 +86,58 @@ CCRenderTexture::~CCRenderTexture()
|
|||
}
|
||||
CC_SAFE_DELETE(m_pUITextureImage);
|
||||
|
||||
#if CC_ENABLE_CACHE_TEXTURE_DATA
|
||||
CCNotificationCenter::sharedNotificationCenter()->removeObserver(this, EVENT_COME_TO_BACKGROUND);
|
||||
CCNotificationCenter::sharedNotificationCenter()->removeObserver(this, EVNET_COME_TO_FOREGROUND);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CCRenderTexture::listenToBackground(cocos2d::CCObject *obj)
|
||||
{
|
||||
#if CC_ENABLE_CACHE_TEXTURE_DATA
|
||||
|
||||
CC_SAFE_DELETE(m_pUITextureImage);
|
||||
|
||||
// to get the rendered texture data
|
||||
m_pUITextureImage = newCCImage();
|
||||
|
||||
m_pUITextureImage = newCCImage(false);
|
||||
|
||||
if (m_pUITextureImage)
|
||||
{
|
||||
const CCSize& s = m_pTexture->getContentSizeInPixels();
|
||||
VolatileTexture::addDataTexture(m_pTexture, m_pUITextureImage->getData(), kTexture2DPixelFormat_RGBA8888, s);
|
||||
|
||||
if ( m_pTextureCopy )
|
||||
{
|
||||
VolatileTexture::addDataTexture(m_pTextureCopy, m_pUITextureImage->getData(), kTexture2DPixelFormat_RGBA8888, s);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CCLOG("Cache rendertexture failed!");
|
||||
}
|
||||
|
||||
glDeleteFramebuffers(1, &m_uFBO);
|
||||
m_uFBO = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CCRenderTexture::listenToForeground(cocos2d::CCObject *obj)
|
||||
{
|
||||
#if CC_ENABLE_CACHE_TEXTURE_DATA
|
||||
// -- regenerate frame buffer object and attach the texture
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_nOldFBO);
|
||||
|
||||
glGenFramebuffers(1, &m_uFBO);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_uFBO);
|
||||
|
||||
m_pTexture->setAliasTexParameters();
|
||||
|
||||
if ( m_pTextureCopy )
|
||||
{
|
||||
m_pTextureCopy->setAliasTexParameters();
|
||||
}
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTexture->getName(), 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_nOldFBO);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -590,7 +627,7 @@ bool CCRenderTexture::saveToFile(const char *szFilePath)
|
|||
{
|
||||
bool bRet = false;
|
||||
|
||||
CCImage *pImage = newCCImage();
|
||||
CCImage *pImage = newCCImage(true);
|
||||
if (pImage)
|
||||
{
|
||||
bRet = pImage->saveToFile(szFilePath, kCCImageFormatJPEG);
|
||||
|
@ -605,7 +642,7 @@ bool CCRenderTexture::saveToFile(const char *fileName, tCCImageFormat format)
|
|||
CCAssert(format == kCCImageFormatJPEG || format == kCCImageFormatPNG,
|
||||
"the image can only be saved as JPG or PNG format");
|
||||
|
||||
CCImage *pImage = newCCImage();
|
||||
CCImage *pImage = newCCImage(true);
|
||||
if (pImage)
|
||||
{
|
||||
std::string fullpath = CCFileUtils::sharedFileUtils()->getWriteablePath() + fileName;
|
||||
|
@ -619,7 +656,7 @@ bool CCRenderTexture::saveToFile(const char *fileName, tCCImageFormat format)
|
|||
}
|
||||
|
||||
/* get buffer as CCImage */
|
||||
CCImage* CCRenderTexture::newCCImage()
|
||||
CCImage* CCRenderTexture::newCCImage(bool flipImage)
|
||||
{
|
||||
CCAssert(m_ePixelFormat == kCCTexture2DPixelFormat_RGBA8888, "only RGBA8888 can be saved as image");
|
||||
|
||||
|
@ -656,6 +693,8 @@ CCImage* CCRenderTexture::newCCImage()
|
|||
glReadPixels(0,0,nSavedBufferWidth, nSavedBufferHeight,GL_RGBA,GL_UNSIGNED_BYTE, pTempData);
|
||||
this->end();
|
||||
|
||||
if ( flipImage ) // -- flip is only required when saving image to file
|
||||
{
|
||||
// to get the actual texture data
|
||||
// #640 the image read from rendertexture is dirty
|
||||
for (int i = 0; i < nSavedBufferHeight; ++i)
|
||||
|
@ -666,6 +705,12 @@ CCImage* CCRenderTexture::newCCImage()
|
|||
}
|
||||
|
||||
pImage->initWithImageData(pBuffer, nSavedBufferWidth * nSavedBufferHeight * 4, CCImage::kFmtRawData, nSavedBufferWidth, nSavedBufferHeight, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
pImage->initWithImageData(pTempData, nSavedBufferWidth * nSavedBufferHeight * 4, CCImage::kFmtRawData, nSavedBufferWidth, nSavedBufferHeight, 8);
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
CC_SAFE_DELETE_ARRAY(pBuffer);
|
||||
|
|
|
@ -128,7 +128,7 @@ public:
|
|||
/* creates a new CCImage from with the texture's data.
|
||||
Caller is responsible for releasing it by calling delete.
|
||||
*/
|
||||
CCImage* newCCImage();
|
||||
CCImage* newCCImage(bool flipImage = true);
|
||||
|
||||
/** saves the texture into a file using JPEG format. The file will be saved in the Documents folder.
|
||||
Returns YES if the operation is successful.
|
||||
|
@ -145,6 +145,11 @@ public:
|
|||
*/
|
||||
void listenToBackground(CCObject *obj);
|
||||
|
||||
/** Listen "come to foreground" message and restore the frame buffer object
|
||||
It only has effect on Android.
|
||||
*/
|
||||
void listenToForeground(CCObject *obj);
|
||||
|
||||
/** Valid flags: GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT. They can be OR'ed. Valid when "autoDraw is YES. */
|
||||
unsigned int getClearFlags() const;
|
||||
void setClearFlags(unsigned int uClearFlags);
|
||||
|
|
Loading…
Reference in New Issue