mirror of https://github.com/axmolengine/axmol.git
fixed #1500:make rendertexture work ok on certain Qualcomm Andreno gpu
This commit is contained in:
parent
e7fea0449f
commit
96b3232910
|
@ -49,6 +49,7 @@ CCRenderTexture::CCRenderTexture()
|
|||
, m_uDepthRenderBufffer(0)
|
||||
, m_nOldFBO(0)
|
||||
, m_pTexture(0)
|
||||
, m_pTextureCopy(0)
|
||||
, m_pUITextureImage(NULL)
|
||||
, m_ePixelFormat(kCCTexture2DPixelFormat_RGBA8888)
|
||||
{
|
||||
|
@ -62,6 +63,8 @@ CCRenderTexture::CCRenderTexture()
|
|||
|
||||
CCRenderTexture::~CCRenderTexture()
|
||||
{
|
||||
CC_SAFE_RELEASE(m_pTextureCopy);
|
||||
|
||||
glDeleteFramebuffers(1, &m_uFBO);
|
||||
if (m_uDepthRenderBufffer)
|
||||
{
|
||||
|
@ -168,6 +171,7 @@ bool CCRenderTexture::initWithWidthAndHeight(int w, int h, CCTexture2DPixelForma
|
|||
CCAssert(m_ePixelFormat != kCCTexture2DPixelFormat_A8, "only RGB and RGBA formats are valid for a render texture");
|
||||
|
||||
bool bRet = false;
|
||||
void *data = NULL;
|
||||
do
|
||||
{
|
||||
w *= (int)CC_CONTENT_SCALE_FACTOR();
|
||||
|
@ -179,30 +183,47 @@ bool CCRenderTexture::initWithWidthAndHeight(int w, int h, CCTexture2DPixelForma
|
|||
unsigned int powW = 0;
|
||||
unsigned int powH = 0;
|
||||
|
||||
if( CCConfiguration::sharedConfiguration()->supportsNPOT() ) {
|
||||
if (CCConfiguration::sharedConfiguration()->supportsNPOT())
|
||||
{
|
||||
powW = w;
|
||||
powH = h;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
powW = ccNextPOT(w);
|
||||
powH = ccNextPOT(h);
|
||||
}
|
||||
|
||||
void *data = malloc((int)(powW * powH * 4));
|
||||
data = malloc((int)(powW * powH * 4));
|
||||
CC_BREAK_IF(! data);
|
||||
|
||||
memset(data, 0, (int)(powW * powH * 4));
|
||||
m_ePixelFormat = eFormat;
|
||||
|
||||
m_pTexture = new CCTexture2D();
|
||||
if (m_pTexture) {
|
||||
m_pTexture->initWithData(data, (CCTexture2DPixelFormat)m_ePixelFormat, powW, powH, CCSizeMake((float)w, (float)h));
|
||||
free( data );
|
||||
} else {
|
||||
free( data ); // ScopeGuard (a simulated Finally clause) would be more elegant.
|
||||
break;
|
||||
if (m_pTexture)
|
||||
{
|
||||
m_pTexture->initWithData(data, (CCTexture2DPixelFormat)m_ePixelFormat, powW, powH, CCSizeMake((float)w, (float)h));
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
GLint oldRBO;
|
||||
glGetIntegerv(GL_RENDERBUFFER_BINDING, &oldRBO);
|
||||
|
||||
if (CCConfiguration::sharedConfiguration()->checkForGLExtension("GL_QCOM"))
|
||||
{
|
||||
m_pTextureCopy = new CCTexture2D();
|
||||
if (m_pTextureCopy)
|
||||
{
|
||||
m_pTextureCopy->initWithData(data, (CCTexture2DPixelFormat)m_ePixelFormat, powW, powH, CCSizeMake((float)w, (float)h));
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// generate FBO
|
||||
glGenFramebuffers(1, &m_uFBO);
|
||||
|
@ -221,10 +242,11 @@ bool CCRenderTexture::initWithWidthAndHeight(int w, int h, CCTexture2DPixelForma
|
|||
|
||||
// if depth format is the one with stencil part, bind same render buffer as stencil attachment
|
||||
if (uDepthStencilFormat == CC_GL_DEPTH24_STENCIL8)
|
||||
{
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_uDepthRenderBufffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check if it worked (probably worth doing :) )
|
||||
CCAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Could not attach texture to framebuffer");
|
||||
|
||||
|
@ -243,8 +265,10 @@ bool CCRenderTexture::initWithWidthAndHeight(int w, int h, CCTexture2DPixelForma
|
|||
glBindFramebuffer(GL_FRAMEBUFFER, m_nOldFBO);
|
||||
bRet = true;
|
||||
} while (0);
|
||||
return bRet;
|
||||
|
||||
CC_SAFE_DELETE(data);
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
void CCRenderTexture::begin()
|
||||
|
@ -271,6 +295,17 @@ void CCRenderTexture::begin()
|
|||
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_nOldFBO);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_uFBO);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void CCRenderTexture::beginWithClear(float r, float g, float b, float a)
|
||||
|
@ -444,7 +479,6 @@ CCImage* CCRenderTexture::newCCImage()
|
|||
{
|
||||
CC_BREAK_IF(! (pBuffer = new GLubyte[nSavedBufferWidth * nSavedBufferHeight * 4]));
|
||||
|
||||
|
||||
if(! (pTempData = new GLubyte[nSavedBufferWidth * nSavedBufferHeight * 4]))
|
||||
{
|
||||
delete[] pBuffer;
|
||||
|
@ -462,8 +496,8 @@ CCImage* CCRenderTexture::newCCImage()
|
|||
for (int i = 0; i < nSavedBufferHeight; ++i)
|
||||
{
|
||||
memcpy(&pBuffer[i * nSavedBufferWidth * 4],
|
||||
&pTempData[(nSavedBufferHeight - i - 1) * nSavedBufferWidth * 4],
|
||||
nSavedBufferWidth * 4);
|
||||
&pTempData[(nSavedBufferHeight - i - 1) * nSavedBufferWidth * 4],
|
||||
nSavedBufferWidth * 4);
|
||||
}
|
||||
|
||||
pImage->initWithImageData(pBuffer, nSavedBufferWidth * nSavedBufferHeight * 4, CCImage::kFmtRawData, nSavedBufferWidth, nSavedBufferHeight, 8);
|
||||
|
|
|
@ -147,6 +147,7 @@ protected:
|
|||
GLuint m_uDepthRenderBufffer;
|
||||
GLint m_nOldFBO;
|
||||
CCTexture2D* m_pTexture;
|
||||
CCTexture2D* m_pTextureCopy; // a copy of m_pTexture
|
||||
CCImage* m_pUITextureImage;
|
||||
GLenum m_ePixelFormat;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue