bool GridBase::initWithSize(const Size& gridSize) { Director *pDirector = Director::getInstance(); Size s = pDirector->getWinSizeInPixels(); unsigned long POTWide = ccNextPOT((unsigned int)s.width); unsigned long POTHigh = ccNextPOT((unsigned int)s.height); // we only use rgba8888 Texture2D::PixelFormat format = Texture2D::PixelFormat::RGBA8888; long dataLen = POTWide * POTHigh * 4; void *data = kdCalloc(dataLen, 1); if (! data) { CCLOG("cocos2d: Grid: not enough memory."); this->release(); return false; } Texture2D *texture = new Texture2D(); texture->initWithData(data, dataLen, format, POTWide, POTHigh, s); kdFree(data); if (! texture) { CCLOG("cocos2d: Grid: error creating texture"); return false; } initWithSize(gridSize, texture, false); texture->release(); return true; }
bool CCGridBase::initWithSize(const CCSize& gridSize) { CCDirector *pDirector = CCDirector::sharedDirector(); CCSize s = pDirector->getWinSizeInPixels(); unsigned long POTWide = ccNextPOT((unsigned int)s.width); unsigned long POTHigh = ccNextPOT((unsigned int)s.height); // we only use rgba8888 CCTexture2DPixelFormat format = kCCTexture2DPixelFormat_RGBA8888; void *data = calloc((int)(POTWide * POTHigh * 4), 1); if (! data) { CCLOG("cocos2d: CCGrid: not enough memory."); this->release(); return false; } CCTexture2D *pTexture = new CCTexture2D(); pTexture->initWithData(data, format, POTWide, POTHigh, s); free(data); if (! pTexture) { CCLOG("cocos2d: CCGrid: error creating texture"); return false; } initWithSize(gridSize, pTexture, false); pTexture->release(); return true; }
bool RenderTexture::initWithWidthAndHeight(int w, int h, Texture2D::PixelFormat format, GLuint depthStencilFormat) { CCASSERT(format != Texture2D::PixelFormat::A8, "only RGB and RGBA formats are valid for a render texture"); bool ret = false; void *data = nullptr; do { _fullRect = _rtTextureRect = Rect(0,0,w,h); Size size = Director::getInstance()->getWinSizeInPixels(); _fullviewPort = Rect(0,0,size.width,size.height); w = (int)(w * CC_CONTENT_SCALE_FACTOR()); h = (int)(h * CC_CONTENT_SCALE_FACTOR()); glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO); // textures must be power of two squared int powW = 0; int powH = 0; if (Configuration::getInstance()->supportsNPOT()) { powW = w; powH = h; } else { powW = ccNextPOT(w); powH = ccNextPOT(h); } auto dataLen = powW * powH * 4; data = malloc(dataLen); CC_BREAK_IF(! data); memset(data, 0, dataLen); _pixelFormat = format; _texture = new Texture2D(); if (_texture) { _texture->initWithData(data, dataLen, (Texture2D::PixelFormat)_pixelFormat, powW, powH, Size((float)w, (float)h)); } else { break; } GLint oldRBO; glGetIntegerv(GL_RENDERBUFFER_BINDING, &oldRBO); if (Configuration::getInstance()->checkForGLExtension("GL_QCOM")) { _textureCopy = new Texture2D(); if (_textureCopy) { _textureCopy->initWithData(data, dataLen, (Texture2D::PixelFormat)_pixelFormat, powW, powH, Size((float)w, (float)h)); } else { break; } } // generate FBO glGenFramebuffers(1, &_FBO); glBindFramebuffer(GL_FRAMEBUFFER, _FBO); // associate texture with FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture->getName(), 0); if (depthStencilFormat != 0) { //create and attach depth buffer glGenRenderbuffers(1, &_depthRenderBufffer); glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBufffer); glRenderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, (GLsizei)powW, (GLsizei)powH); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBufffer); // if depth format is the one with stencil part, bind same render buffer as stencil attachment if (depthStencilFormat == GL_DEPTH24_STENCIL8) { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBufffer); } } // check if it worked (probably worth doing :) ) CCASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Could not attach texture to framebuffer"); _texture->setAliasTexParameters(); // retained setSprite(Sprite::createWithTexture(_texture)); _texture->release(); _sprite->setFlippedY(true); _sprite->setBlendFunc( BlendFunc::ALPHA_PREMULTIPLIED ); glBindRenderbuffer(GL_RENDERBUFFER, oldRBO); glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO); // Diabled by default. _autoDraw = false; // add sprite for backward compatibility addChild(_sprite); ret = true; } while (0); CC_SAFE_FREE(data); return ret; }
bool CCRenderTexture::initWithWidthAndHeight(int w, int h, CCTexture2DPixelFormat eFormat) { // If the gles version is lower than GLES_VER_1_0, // some extended gles functions can't be implemented, so return false directly. if (CCConfiguration::sharedConfiguration()->getGlesVersion() <= GLES_VER_1_0) { return false; } bool bRet = false; do { w *= (int)CC_CONTENT_SCALE_FACTOR(); h *= (int)CC_CONTENT_SCALE_FACTOR(); glGetIntegerv(CC_GL_FRAMEBUFFER_BINDING, &m_nOldFBO); // textures must be power of two squared unsigned int powW = ccNextPOT(w); unsigned int powH = ccNextPOT(h); void *data = malloc((int)(powW * powH * 4)); CC_BREAK_IF(! data); memset(data, 0, (int)(powW * powH * 4)); m_ePixelFormat = eFormat; m_pTexture = new CCTexture2D(); CC_BREAK_IF(! m_pTexture); m_pTexture->initWithData(data, (CCTexture2DPixelFormat)m_ePixelFormat, powW, powH, CCSizeMake((float)w, (float)h)); free( data ); // generate FBO ccglGenFramebuffers(1, &m_uFBO); ccglBindFramebuffer(CC_GL_FRAMEBUFFER, m_uFBO); // associate texture with FBO ccglFramebufferTexture2D(CC_GL_FRAMEBUFFER, CC_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTexture->getName(), 0); // check if it worked (probably worth doing :) ) GLuint status = ccglCheckFramebufferStatus(CC_GL_FRAMEBUFFER); if (status != CC_GL_FRAMEBUFFER_COMPLETE) { CCAssert(0, "Render Texture : Could not attach texture to framebuffer"); CC_SAFE_DELETE(m_pTexture); 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); ccglBindFramebuffer(CC_GL_FRAMEBUFFER, m_nOldFBO); bRet = true; } while (0); return bRet; }
/* 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; if (x < 0 || x >= tx || y < 0 || y >= ty) { return false; } if (nWidth < 0 || nHeight < 0 || (0 == nWidth && 0 != nHeight) || (0 == nHeight && 0 != nWidth)) { return false; } // 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; if (0 == nWidth) { nSavedBufferWidth = tx; } if (0 == nHeight) { nSavedBufferHeight = ty; } nSavedBufferWidth = x + nSavedBufferWidth > tx ? (tx - x): nSavedBufferWidth; nSavedBufferHeight = y + nSavedBufferHeight > ty ? (ty - y): nSavedBufferHeight; GLubyte *pBuffer = NULL; GLubyte *pTempData = NULL; bool bRet = false; do { CCAssert(m_ePixelFormat == kCCTexture2DPixelFormat_RGBA8888, "only RGBA8888 can be saved as image"); CC_BREAK_IF(! (pBuffer = new GLubyte[nSavedBufferWidth * nSavedBufferHeight * 4])); // 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); } bRet = pImage->initWithImageData(pBuffer, nSavedBufferWidth * nSavedBufferHeight * 4, CCImage::kFmtRawData, nSavedBufferWidth, nSavedBufferHeight, 8); } while (0); CC_SAFE_DELETE_ARRAY(pBuffer); CC_SAFE_DELETE_ARRAY(pTempData); return bRet; }
bool CCRenderTexture::initWithWidthAndHeight(int w, int h, CCTexture2DPixelFormat eFormat, GLuint uDepthStencilFormat) { 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)(w * CC_CONTENT_SCALE_FACTOR()); h = (int)(h * CC_CONTENT_SCALE_FACTOR()); glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_nOldFBO); // textures must be power of two squared unsigned int powW = 0; unsigned int powH = 0; if (CCConfiguration::sharedConfiguration()->supportsNPOT()) { powW = w; powH = h; } else { powW = ccNextPOT(w); powH = ccNextPOT(h); } 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)); } 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); glBindFramebuffer(GL_FRAMEBUFFER, m_uFBO); // associate texture with FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTexture->getName(), 0); if (m_uDepthRenderBufffer != 0) { //create and attach depth buffer glGenRenderbuffers(1, &m_uDepthRenderBufffer); glBindRenderbuffer(GL_RENDERBUFFER, m_uDepthRenderBufffer); glRenderbufferStorage(GL_RENDERBUFFER, uDepthStencilFormat, (GLsizei)powW, (GLsizei)powH); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_uDepthRenderBufffer); // if depth format is the one with stencil part, bind same render buffer as stencil attachment if (uDepthStencilFormat == 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"); m_pTexture->setAliasTexParameters(); // retained setSprite(CCSprite::createWithTexture(m_pTexture)); m_pTexture->release(); m_pSprite->setScaleY(-1); ccBlendFunc tBlendFunc = {GL_ONE, GL_ONE_MINUS_SRC_ALPHA }; m_pSprite->setBlendFunc(tBlendFunc); glBindRenderbuffer(GL_RENDERBUFFER, oldRBO); glBindFramebuffer(GL_FRAMEBUFFER, m_nOldFBO); // Diabled by default. m_bAutoDraw = false; // add sprite for backward compatibility addChild(m_pSprite); bRet = true; } while (0); CC_SAFE_FREE(data); return bRet; }