2010-11-12 17:29:14 +08:00
|
|
|
/****************************************************************************
|
2011-03-19 14:45:51 +08:00
|
|
|
Copyright (c) 2010-2011 cocos2d-x.org
|
|
|
|
Copyright (c) 2009 Jason Booth
|
2010-11-12 17:29:14 +08:00
|
|
|
|
|
|
|
http://www.cocos2d-x.org
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
****************************************************************************/
|
|
|
|
|
2011-06-08 10:02:07 +08:00
|
|
|
#include "CCConfiguration.h"
|
2010-11-12 17:29:14 +08:00
|
|
|
#include "CCRenderTexture.h"
|
|
|
|
#include "CCDirector.h"
|
|
|
|
#include "platform/platform.h"
|
2011-03-07 17:11:57 +08:00
|
|
|
#include "CCImage.h"
|
2012-03-14 14:55:17 +08:00
|
|
|
#include "CCGLProgram.h"
|
2012-03-15 10:42:22 +08:00
|
|
|
#include "ccGLStateCache.h"
|
2012-03-14 14:55:17 +08:00
|
|
|
#include "CCConfiguration.h"
|
2011-01-06 14:04:03 +08:00
|
|
|
#include "support/ccUtils.h"
|
2011-07-28 17:32:09 +08:00
|
|
|
#include "CCTextureCache.h"
|
2011-07-27 16:55:04 +08:00
|
|
|
#include "CCFileUtils.h"
|
2011-03-02 17:05:22 +08:00
|
|
|
#include "CCGL.h"
|
2012-03-14 14:55:17 +08:00
|
|
|
// extern
|
|
|
|
#include "kazmath/GL/matrix.h"
|
2010-11-12 17:29:14 +08:00
|
|
|
|
2012-03-14 14:55:17 +08:00
|
|
|
NS_CC_BEGIN
|
2010-08-18 15:15:02 +08:00
|
|
|
|
2010-12-25 15:09:42 +08:00
|
|
|
// implementation CCRenderTexture
|
|
|
|
CCRenderTexture::CCRenderTexture()
|
|
|
|
: m_pSprite(NULL)
|
|
|
|
, m_uFBO(0)
|
|
|
|
, m_nOldFBO(0)
|
|
|
|
, m_pTexture(0)
|
2011-09-06 09:51:35 +08:00
|
|
|
, m_pUITextureImage(NULL)
|
2011-10-19 15:24:19 +08:00
|
|
|
, m_ePixelFormat(kCCTexture2DPixelFormat_RGBA8888)
|
2010-12-25 15:09:42 +08:00
|
|
|
{
|
|
|
|
}
|
2010-08-18 15:15:02 +08:00
|
|
|
|
2010-12-25 15:09:42 +08:00
|
|
|
CCRenderTexture::~CCRenderTexture()
|
|
|
|
{
|
2012-03-14 14:55:17 +08:00
|
|
|
//TODO: 2.0 remove this line. removeAllChildrenWithCleanup(true);
|
|
|
|
glDeleteFramebuffers(1, &m_uFBO);
|
2011-07-28 17:32:09 +08:00
|
|
|
|
2011-09-06 09:51:35 +08:00
|
|
|
CC_SAFE_DELETE(m_pUITextureImage);
|
2010-12-25 15:09:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
CCSprite * CCRenderTexture::getSprite()
|
|
|
|
{
|
|
|
|
return m_pSprite;
|
|
|
|
}
|
|
|
|
void CCRenderTexture::setSprite(CCSprite* var)
|
|
|
|
{
|
|
|
|
m_pSprite = var;
|
|
|
|
}
|
|
|
|
|
|
|
|
CCRenderTexture * CCRenderTexture::renderTextureWithWidthAndHeight(int w, int h, CCTexture2DPixelFormat eFormat)
|
|
|
|
{
|
|
|
|
CCRenderTexture *pRet = new CCRenderTexture();
|
|
|
|
|
|
|
|
if(pRet && pRet->initWithWidthAndHeight(w, h, eFormat))
|
|
|
|
{
|
|
|
|
pRet->autorelease();
|
|
|
|
return pRet;
|
|
|
|
}
|
2011-03-07 17:11:57 +08:00
|
|
|
CC_SAFE_DELETE(pRet);
|
2010-12-25 15:09:42 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
CCRenderTexture * CCRenderTexture::renderTextureWithWidthAndHeight(int w, int h)
|
|
|
|
{
|
|
|
|
CCRenderTexture *pRet = new CCRenderTexture();
|
|
|
|
|
|
|
|
if(pRet && pRet->initWithWidthAndHeight(w, h, kCCTexture2DPixelFormat_RGBA8888))
|
2010-08-18 15:15:02 +08:00
|
|
|
{
|
2010-12-25 15:09:42 +08:00
|
|
|
pRet->autorelease();
|
|
|
|
return pRet;
|
2010-08-18 15:15:02 +08:00
|
|
|
}
|
2011-03-07 17:11:57 +08:00
|
|
|
CC_SAFE_DELETE(pRet)
|
2010-12-25 15:09:42 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
2011-06-03 15:22:50 +08:00
|
|
|
|
2010-12-25 15:09:42 +08:00
|
|
|
bool CCRenderTexture::initWithWidthAndHeight(int w, int h, CCTexture2DPixelFormat eFormat)
|
|
|
|
{
|
2012-03-14 14:55:17 +08:00
|
|
|
// If the gles version is lower than GLES_VER_2_0,
|
2011-06-03 15:22:50 +08:00
|
|
|
// some extended gles functions can't be implemented, so return false directly.
|
2012-03-14 18:11:25 +08:00
|
|
|
if (CCConfiguration::sharedConfiguration()->getGlesVersion() < GLES_VER_2_0)
|
2011-06-03 15:22:50 +08:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-12-25 15:09:42 +08:00
|
|
|
bool bRet = false;
|
|
|
|
do
|
|
|
|
{
|
2010-12-31 14:56:24 +08:00
|
|
|
w *= (int)CC_CONTENT_SCALE_FACTOR();
|
|
|
|
h *= (int)CC_CONTENT_SCALE_FACTOR();
|
2010-08-18 15:15:02 +08:00
|
|
|
|
2011-08-19 13:07:50 +08:00
|
|
|
glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &m_nOldFBO);
|
2010-08-18 15:15:02 +08:00
|
|
|
|
2010-12-25 15:09:42 +08:00
|
|
|
// textures must be power of two squared
|
2012-03-14 14:55:17 +08:00
|
|
|
unsigned int powW = 0;
|
|
|
|
unsigned int powH = 0;
|
|
|
|
|
|
|
|
if( CCConfiguration::sharedConfiguration()->isSupportsNPOT() ) {
|
|
|
|
powW = w;
|
|
|
|
powH = h;
|
|
|
|
} else {
|
|
|
|
powW = ccNextPOT(w);
|
|
|
|
powH = ccNextPOT(h);
|
|
|
|
}
|
2010-08-18 15:15:02 +08:00
|
|
|
|
2010-12-25 15:09:42 +08:00
|
|
|
void *data = malloc((int)(powW * powH * 4));
|
2011-03-07 17:11:57 +08:00
|
|
|
CC_BREAK_IF(! data);
|
2010-08-18 15:15:02 +08:00
|
|
|
|
2010-12-25 15:09:42 +08:00
|
|
|
memset(data, 0, (int)(powW * powH * 4));
|
|
|
|
m_ePixelFormat = eFormat;
|
2010-08-18 15:15:02 +08:00
|
|
|
|
2010-12-25 15:09:42 +08:00
|
|
|
m_pTexture = new CCTexture2D();
|
2011-03-07 17:11:57 +08:00
|
|
|
CC_BREAK_IF(! m_pTexture);
|
2010-08-18 15:15:02 +08:00
|
|
|
|
2011-03-07 17:11:57 +08:00
|
|
|
m_pTexture->initWithData(data, (CCTexture2DPixelFormat)m_ePixelFormat, powW, powH, CCSizeMake((float)w, (float)h));
|
2010-12-25 15:09:42 +08:00
|
|
|
free( data );
|
2010-08-18 15:15:02 +08:00
|
|
|
|
2010-12-25 15:09:42 +08:00
|
|
|
// generate FBO
|
2012-03-14 14:55:17 +08:00
|
|
|
glGenFramebuffers(1, &m_uFBO);
|
|
|
|
glBindFramebuffer(CC_GL_FRAMEBUFFER, m_uFBO);
|
2010-12-25 15:09:42 +08:00
|
|
|
|
|
|
|
// associate texture with FBO
|
2012-03-14 14:55:17 +08:00
|
|
|
glFramebufferTexture2D(CC_GL_FRAMEBUFFER, CC_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTexture->getName(), 0);
|
2010-12-25 15:09:42 +08:00
|
|
|
|
|
|
|
// check if it worked (probably worth doing :) )
|
2012-03-14 14:55:17 +08:00
|
|
|
GLuint status = glCheckFramebufferStatus(CC_GL_FRAMEBUFFER);
|
2010-12-25 15:09:42 +08:00
|
|
|
if (status != CC_GL_FRAMEBUFFER_COMPLETE)
|
|
|
|
{
|
2011-03-07 17:11:57 +08:00
|
|
|
CCAssert(0, "Render Texture : Could not attach texture to framebuffer");
|
|
|
|
CC_SAFE_DELETE(m_pTexture);
|
2010-12-25 15:09:42 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_pTexture->setAliasTexParameters();
|
|
|
|
|
|
|
|
m_pSprite = CCSprite::spriteWithTexture(m_pTexture);
|
|
|
|
|
|
|
|
m_pTexture->release();
|
|
|
|
m_pSprite->setScaleY(-1);
|
|
|
|
this->addChild(m_pSprite);
|
|
|
|
|
|
|
|
ccBlendFunc tBlendFunc = {GL_ONE, GL_ONE_MINUS_SRC_ALPHA };
|
|
|
|
m_pSprite->setBlendFunc(tBlendFunc);
|
|
|
|
|
2012-03-14 14:55:17 +08:00
|
|
|
glBindFramebuffer(CC_GL_FRAMEBUFFER, m_nOldFBO);
|
2010-12-25 15:09:42 +08:00
|
|
|
bRet = true;
|
|
|
|
} while (0);
|
|
|
|
return bRet;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCRenderTexture::begin()
|
|
|
|
{
|
|
|
|
// Save the current matrix
|
2012-03-14 14:55:17 +08:00
|
|
|
kmGLPushMatrix();
|
2010-12-25 15:09:42 +08:00
|
|
|
|
2011-08-17 21:19:57 +08:00
|
|
|
const CCSize& texSize = m_pTexture->getContentSizeInPixels();
|
2010-12-25 15:09:42 +08:00
|
|
|
|
|
|
|
// Calculate the adjustment ratios based on the old and new projections
|
2012-03-14 14:55:17 +08:00
|
|
|
CCDirector *director = CCDirector::sharedDirector();
|
|
|
|
CCSize size = director->getWinSizeInPixels();
|
2010-12-25 15:09:42 +08:00
|
|
|
float widthRatio = size.width / texSize.width;
|
|
|
|
float heightRatio = size.height / texSize.height;
|
|
|
|
|
2012-03-14 14:55:17 +08:00
|
|
|
// Adjust the orthographic projection and viewport
|
|
|
|
glViewport(0, 0, texSize.width * CC_CONTENT_SCALE_FACTOR(), texSize.height * CC_CONTENT_SCALE_FACTOR() );
|
|
|
|
|
|
|
|
// special viewport for 3d projection + retina display
|
|
|
|
if ( director->getProjection() == kCCDirectorProjection3D && CC_CONTENT_SCALE_FACTOR() != 1 )
|
|
|
|
glViewport(-texSize.width/2, -texSize.height/2, texSize.width * CC_CONTENT_SCALE_FACTOR(), texSize.height * CC_CONTENT_SCALE_FACTOR() );
|
|
|
|
|
|
|
|
kmMat4 orthoMatrix;
|
|
|
|
kmMat4OrthographicProjection(&orthoMatrix, (float)-1.0 / widthRatio, (float)1.0 / widthRatio,
|
|
|
|
(float)-1.0 / heightRatio, (float)1.0 / heightRatio, -1,1 );
|
|
|
|
kmGLMultMatrix(&orthoMatrix);
|
|
|
|
|
|
|
|
glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &m_nOldFBO);
|
|
|
|
glBindFramebuffer(CC_GL_FRAMEBUFFER, m_uFBO);
|
2010-12-25 15:09:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCRenderTexture::beginWithClear(float r, float g, float b, float a)
|
|
|
|
{
|
2011-07-04 16:01:57 +08:00
|
|
|
this->begin();
|
2010-12-25 15:09:42 +08:00
|
|
|
|
2011-07-04 16:01:57 +08:00
|
|
|
// save clear color
|
|
|
|
GLfloat clearColor[4];
|
|
|
|
glGetFloatv(GL_COLOR_CLEAR_VALUE,clearColor);
|
2010-12-25 15:09:42 +08:00
|
|
|
|
2011-07-04 16:01:57 +08:00
|
|
|
glClearColor(r, g, b, a);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
2010-12-25 15:09:42 +08:00
|
|
|
|
2011-07-04 16:01:57 +08:00
|
|
|
// restore clear color
|
|
|
|
glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
|
2010-12-25 15:09:42 +08:00
|
|
|
}
|
|
|
|
|
2011-09-06 11:33:48 +08:00
|
|
|
void CCRenderTexture::end(bool bIsTOCacheTexture)
|
|
|
|
{
|
2012-03-14 14:55:17 +08:00
|
|
|
glBindFramebuffer(CC_GL_FRAMEBUFFER, m_nOldFBO);
|
|
|
|
kmGLPopMatrix();
|
|
|
|
|
|
|
|
CCDirector *director = CCDirector::sharedDirector();
|
|
|
|
|
|
|
|
CCSize size = director->getWinSizeInPixels();
|
|
|
|
|
|
|
|
// restore viewport
|
|
|
|
glViewport(0, 0, size.width * CC_CONTENT_SCALE_FACTOR(), size.height * CC_CONTENT_SCALE_FACTOR() );
|
|
|
|
|
|
|
|
// special viewport for 3d projection + retina display
|
|
|
|
if ( director->getProjection() == kCCDirectorProjection3D && CC_CONTENT_SCALE_FACTOR() != 1 )
|
|
|
|
glViewport(-size.width/2, -size.height/2, size.width * CC_CONTENT_SCALE_FACTOR(), size.height * CC_CONTENT_SCALE_FACTOR() );
|
|
|
|
|
|
|
|
//TODO: Does this line take effect? director->setProjection(director->getProjection());
|
2011-10-19 15:24:19 +08:00
|
|
|
|
|
|
|
#if CC_ENABLE_CACHE_TEXTTURE_DATA
|
2011-09-06 11:33:48 +08:00
|
|
|
if (bIsTOCacheTexture)
|
|
|
|
{
|
|
|
|
CC_SAFE_DELETE(m_pUITextureImage);
|
|
|
|
|
|
|
|
// to get the rendered texture data
|
|
|
|
const CCSize& s = m_pTexture->getContentSizeInPixels();
|
|
|
|
int tx = (int)s.width;
|
|
|
|
int ty = (int)s.height;
|
|
|
|
m_pUITextureImage = new CCImage;
|
|
|
|
if (true == getUIImageFromBuffer(m_pUITextureImage, 0, 0, tx, ty))
|
2011-09-06 09:51:35 +08:00
|
|
|
{
|
2011-09-06 11:33:48 +08:00
|
|
|
VolatileTexture::addDataTexture(m_pTexture, m_pUITextureImage->getData(), kTexture2DPixelFormat_RGBA8888, s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CCLOG("Cache rendertexture failed!");
|
|
|
|
}
|
2011-10-19 15:24:19 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
2010-12-25 15:09:42 +08:00
|
|
|
|
|
|
|
void CCRenderTexture::clear(float r, float g, float b, float a)
|
|
|
|
{
|
2011-07-04 16:01:57 +08:00
|
|
|
this->beginWithClear(r, g, b, a);
|
2010-12-25 15:09:42 +08:00
|
|
|
this->end();
|
|
|
|
}
|
|
|
|
|
2011-08-02 14:25:58 +08:00
|
|
|
bool CCRenderTexture::saveBuffer(const char *szFilePath, int x, int y, int nWidth, int nHeight)
|
2010-12-25 15:09:42 +08:00
|
|
|
{
|
2011-07-29 11:36:04 +08:00
|
|
|
bool bRet = false;
|
|
|
|
|
|
|
|
CCImage *pImage = new CCImage();
|
2011-08-02 14:25:58 +08:00
|
|
|
if (pImage != NULL && getUIImageFromBuffer(pImage, x, y, nWidth, nHeight))
|
2011-07-29 11:36:04 +08:00
|
|
|
{
|
|
|
|
bRet = pImage->saveToFile(szFilePath);
|
|
|
|
}
|
|
|
|
|
|
|
|
CC_SAFE_DELETE(pImage);
|
|
|
|
return bRet;
|
2010-12-25 15:09:42 +08:00
|
|
|
}
|
2011-08-02 14:25:58 +08:00
|
|
|
bool CCRenderTexture::saveBuffer(int format, const char *fileName, int x, int y, int nWidth, int nHeight)
|
2010-12-25 15:09:42 +08:00
|
|
|
{
|
2011-07-27 16:55:04 +08:00
|
|
|
bool bRet = false;
|
|
|
|
CCAssert(format == kCCImageFormatJPG || format == kCCImageFormatPNG,
|
2011-07-28 10:09:56 +08:00
|
|
|
"the image can only be saved as JPG or PNG format");
|
2011-07-27 16:55:04 +08:00
|
|
|
|
|
|
|
CCImage *pImage = new CCImage();
|
2011-08-02 14:25:58 +08:00
|
|
|
if (pImage != NULL && getUIImageFromBuffer(pImage, x, y, nWidth, nHeight))
|
2011-07-27 16:55:04 +08:00
|
|
|
{
|
|
|
|
std::string fullpath = CCFileUtils::getWriteablePath() + fileName;
|
|
|
|
|
|
|
|
bRet = pImage->saveToFile(fullpath.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
CC_SAFE_DELETE(pImage);
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2011-10-19 15:24:19 +08:00
|
|
|
/* get buffer as UIImage */
|
|
|
|
bool CCRenderTexture::getUIImageFromBuffer(CCImage *pImage, int x, int y, int nWidth, int nHeight)
|
|
|
|
{
|
|
|
|
if (NULL == pImage || NULL == m_pTexture)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CCSize& s = m_pTexture->getContentSizeInPixels();
|
|
|
|
int tx = (int)s.width;
|
|
|
|
int ty = (int)s.height;
|
|
|
|
|
2011-08-02 14:25:58 +08:00
|
|
|
if (x < 0 || x >= tx || y < 0 || y >= ty)
|
2011-07-27 16:55:04 +08:00
|
|
|
{
|
|
|
|
return false;
|
2011-10-19 15:24:19 +08:00
|
|
|
}
|
|
|
|
|
2011-08-02 14:25:58 +08:00
|
|
|
if (nWidth < 0
|
|
|
|
|| nHeight < 0
|
|
|
|
|| (0 == nWidth && 0 != nHeight)
|
|
|
|
|| (0 == nHeight && 0 != nWidth))
|
|
|
|
{
|
|
|
|
return false;
|
2011-10-19 15:24:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// to get the image size to save
|
|
|
|
// if the saving image domain exeeds the buffer texture domain,
|
|
|
|
// it should be cut
|
|
|
|
int nSavedBufferWidth = nWidth;
|
|
|
|
int nSavedBufferHeight = nHeight;
|
2011-08-02 14:25:58 +08:00
|
|
|
if (0 == nWidth)
|
|
|
|
{
|
|
|
|
nSavedBufferWidth = tx;
|
2011-10-19 15:24:19 +08:00
|
|
|
}
|
2011-08-02 14:25:58 +08:00
|
|
|
if (0 == nHeight)
|
|
|
|
{
|
|
|
|
nSavedBufferHeight = ty;
|
2011-10-19 15:24:19 +08:00
|
|
|
}
|
|
|
|
nSavedBufferWidth = x + nSavedBufferWidth > tx ? (tx - x): nSavedBufferWidth;
|
|
|
|
nSavedBufferHeight = y + nSavedBufferHeight > ty ? (ty - y): nSavedBufferHeight;
|
|
|
|
|
2011-08-02 10:05:15 +08:00
|
|
|
GLubyte *pBuffer = NULL;
|
|
|
|
GLubyte *pTempData = NULL;
|
2010-12-25 15:09:42 +08:00
|
|
|
bool bRet = false;
|
2011-07-27 16:55:04 +08:00
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2011-07-28 10:09:56 +08:00
|
|
|
CCAssert(m_ePixelFormat == kCCTexture2DPixelFormat_RGBA8888, "only RGBA8888 can be saved as image");
|
2011-07-27 16:55:04 +08:00
|
|
|
|
2011-08-02 14:25:58 +08:00
|
|
|
CC_BREAK_IF(! (pBuffer = new GLubyte[nSavedBufferWidth * nSavedBufferHeight * 4]));
|
2011-10-19 15:24:19 +08:00
|
|
|
|
|
|
|
// On some machines, like Samsung i9000, Motorola Defy,
|
|
|
|
// the dimension need to be a power of 2
|
|
|
|
int nReadBufferWidth = 0;
|
|
|
|
int nReadBufferHeight = 0;
|
|
|
|
int nMaxTextureSize = 0;
|
|
|
|
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &nMaxTextureSize);
|
|
|
|
|
|
|
|
nReadBufferWidth = ccNextPOT(tx);
|
|
|
|
nReadBufferHeight = ccNextPOT(ty);
|
|
|
|
|
|
|
|
CC_BREAK_IF(0 == nReadBufferWidth || 0 == nReadBufferHeight);
|
|
|
|
CC_BREAK_IF(nReadBufferWidth > nMaxTextureSize || nReadBufferHeight > nMaxTextureSize);
|
|
|
|
|
|
|
|
CC_BREAK_IF(! (pTempData = new GLubyte[nReadBufferWidth * nReadBufferHeight * 4]));
|
|
|
|
|
|
|
|
this->begin();
|
|
|
|
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
|
|
|
glReadPixels(0,0,nReadBufferWidth,nReadBufferHeight,GL_RGBA,GL_UNSIGNED_BYTE, pTempData);
|
|
|
|
this->end(false);
|
|
|
|
|
|
|
|
// to get the actual texture data
|
|
|
|
// #640 the image read from rendertexture is upseted
|
|
|
|
for (int i = 0; i < nSavedBufferHeight; ++i)
|
|
|
|
{
|
|
|
|
memcpy(&pBuffer[i * nSavedBufferWidth * 4],
|
|
|
|
&pTempData[(y + nSavedBufferHeight - i - 1) * nReadBufferWidth * 4 + x * 4],
|
|
|
|
nSavedBufferWidth * 4);
|
|
|
|
}
|
2011-08-02 10:05:15 +08:00
|
|
|
|
2011-08-02 14:25:58 +08:00
|
|
|
bRet = pImage->initWithImageData(pBuffer, nSavedBufferWidth * nSavedBufferHeight * 4, CCImage::kFmtRawData, nSavedBufferWidth, nSavedBufferHeight, 8);
|
2011-10-19 15:24:19 +08:00
|
|
|
} while (0);
|
|
|
|
|
|
|
|
CC_SAFE_DELETE_ARRAY(pBuffer);
|
|
|
|
CC_SAFE_DELETE_ARRAY(pTempData);
|
|
|
|
|
|
|
|
return bRet;
|
2010-12-25 15:09:42 +08:00
|
|
|
}
|
|
|
|
|
2011-07-27 16:55:04 +08:00
|
|
|
|
2011-03-07 17:11:57 +08:00
|
|
|
CCData * CCRenderTexture::getUIImageAsDataFromBuffer(int format)
|
2010-12-25 15:09:42 +08:00
|
|
|
{
|
2011-06-10 17:51:37 +08:00
|
|
|
CC_UNUSED_PARAM(format);
|
2011-03-07 17:11:57 +08:00
|
|
|
CCData * pData = NULL;
|
2010-12-25 15:09:42 +08:00
|
|
|
//@ todo CCRenderTexture::getUIImageAsDataFromBuffer
|
|
|
|
|
|
|
|
// #include "Availability.h"
|
|
|
|
// #include "UIKit.h"
|
|
|
|
|
|
|
|
// GLubyte * pBuffer = NULL;
|
|
|
|
// GLubyte * pPixels = NULL;
|
|
|
|
// do
|
|
|
|
// {
|
2011-03-07 17:11:57 +08:00
|
|
|
// CC_BREAK_IF(! m_pTexture);
|
2010-12-25 15:09:42 +08:00
|
|
|
//
|
2011-03-07 17:11:57 +08:00
|
|
|
// CCAssert(m_ePixelFormat == kCCTexture2DPixelFormat_RGBA8888, "only RGBA8888 can be saved as image");
|
2010-12-25 15:09:42 +08:00
|
|
|
//
|
2011-08-17 21:19:57 +08:00
|
|
|
// const CCSize& s = m_pTexture->getContentSizeInPixels();
|
2010-12-25 15:09:42 +08:00
|
|
|
// int tx = s.width;
|
|
|
|
// int ty = s.height;
|
|
|
|
//
|
|
|
|
// int bitsPerComponent = 8;
|
|
|
|
// int bitsPerPixel = 32;
|
|
|
|
//
|
|
|
|
// int bytesPerRow = (bitsPerPixel / 8) * tx;
|
|
|
|
// int myDataLength = bytesPerRow * ty;
|
|
|
|
//
|
2011-03-07 17:11:57 +08:00
|
|
|
// CC_BREAK_IF(! (pBuffer = new GLubyte[tx * ty * 4]));
|
|
|
|
// CC_BREAK_IF(! (pPixels = new GLubyte[tx * ty * 4]));
|
2010-12-25 15:09:42 +08:00
|
|
|
//
|
|
|
|
// this->begin();
|
|
|
|
// glReadPixels(0,0,tx,ty,GL_RGBA,GL_UNSIGNED_BYTE, pBuffer);
|
|
|
|
// this->end();
|
|
|
|
//
|
|
|
|
// int x,y;
|
|
|
|
//
|
|
|
|
// for(y = 0; y <ty; y++) {
|
|
|
|
// for(x = 0; x <tx * 4; x++) {
|
|
|
|
// pPixels[((ty - 1 - y) * tx * 4 + x)] = pBuffer[(y * 4 * tx + x)];
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (format == kCCImageFormatRawData)
|
|
|
|
// {
|
2011-03-07 17:11:57 +08:00
|
|
|
// pData = CCData::dataWithBytesNoCopy(pPixels, myDataLength);
|
2010-12-25 15:09:42 +08:00
|
|
|
// break;
|
|
|
|
// }
|
|
|
|
|
|
|
|
//@ todo impliment save to jpg or png
|
|
|
|
/*
|
|
|
|
CGImageCreate(size_t width, size_t height,
|
|
|
|
size_t bitsPerComponent, size_t bitsPerPixel, size_t bytesPerRow,
|
|
|
|
CGColorSpaceRef space, CGBitmapInfo bitmapInfo, CGDataProviderRef provider,
|
|
|
|
const CGFloat decode[], bool shouldInterpolate,
|
|
|
|
CGColorRenderingIntent intent)
|
|
|
|
*/
|
|
|
|
// make data provider with data.
|
|
|
|
// CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault;
|
|
|
|
// CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, myDataLength, NULL);
|
|
|
|
// CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
|
|
|
|
// CGImageRef iref = CGImageCreate(tx, ty,
|
|
|
|
// bitsPerComponent, bitsPerPixel, bytesPerRow,
|
|
|
|
// colorSpaceRef, bitmapInfo, provider,
|
|
|
|
// NULL, false,
|
|
|
|
// kCGRenderingIntentDefault);
|
|
|
|
//
|
|
|
|
// UIImage* image = [[UIImage alloc] initWithCGImage:iref];
|
|
|
|
//
|
|
|
|
// CGImageRelease(iref);
|
|
|
|
// CGColorSpaceRelease(colorSpaceRef);
|
|
|
|
// CGDataProviderRelease(provider);
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// if (format == kCCImageFormatPNG)
|
|
|
|
// data = UIImagePNGRepresentation(image);
|
|
|
|
// else
|
|
|
|
// data = UIImageJPEGRepresentation(image, 1.0f);
|
|
|
|
//
|
|
|
|
// [image release];
|
|
|
|
// } while (0);
|
|
|
|
//
|
2011-03-07 17:11:57 +08:00
|
|
|
// CC_SAFE_DELETE_ARRAY(pBuffer);
|
|
|
|
// CC_SAFE_DELETE_ARRAY(pPixels);
|
2010-12-25 15:09:42 +08:00
|
|
|
return pData;
|
|
|
|
}
|
2010-11-12 17:29:14 +08:00
|
|
|
|
2012-03-14 14:55:17 +08:00
|
|
|
NS_CC_END
|