From 942d0233cfc557e4d197079c074dc6efecca02bb Mon Sep 17 00:00:00 2001 From: minggo Date: Thu, 30 Dec 2010 17:30:11 +0800 Subject: [PATCH] fixed #290 --- cocos2dx/include/CCTexture2D.h | 12 +++-- cocos2dx/include/CCTextureAtlas.h | 4 +- cocos2dx/include/CCTextureCache.h | 45 ++++++++++-------- cocos2dx/textures/CCTexture2D.cpp | 65 +++++++++++++------------- cocos2dx/textures/CCTextureAtlas.cpp | 69 ++++++++++++++++------------ cocos2dx/textures/CCTextureCache.cpp | 16 +++++-- 6 files changed, 121 insertions(+), 90 deletions(-) diff --git a/cocos2dx/include/CCTexture2D.h b/cocos2dx/include/CCTexture2D.h index c8720cead2..e0a97e1a5d 100644 --- a/cocos2dx/include/CCTexture2D.h +++ b/cocos2dx/include/CCTexture2D.h @@ -26,7 +26,6 @@ THE SOFTWARE. #define __CCTEXTURE2D_H__ #include -#include #include "CCXCocos2dDefine.h" #include "NSObject.h" @@ -47,7 +46,7 @@ typedef enum { kCCTexture2DPixelFormat_RGBA8888, //! 24-bit texture: RGBA888 kCCTexture2DPixelFormat_RGB888, - //! 16-bit texture: used with images that have alpha pre-multiplied + //! 16-bit texture without Alpha channel kCCTexture2DPixelFormat_RGB565, //! 8-bit textures used as masks kCCTexture2DPixelFormat_A8, @@ -102,7 +101,7 @@ class CCX_DLL CCTexture2D : public NSObject CCX_PROPERTY_READONLY(GLuint, m_uName, Name) /** content size */ - CCX_PROPERTY_READONLY(CGSize, m_tContentSize, ContentSize) + CCX_PROPERTY_READONLY(CGSize, m_tContentSize, ContentSizeInPixels) /** texture max S */ CCX_PROPERTY(GLfloat, m_fMaxS, MaxS) /** texture max T */ @@ -116,6 +115,10 @@ public: char * description(void); + /** These functions are needed to create mutable textures */ + void releaseData(void *data); + void* keepData(void *data, unsigned int length); + /** Intializes with a texture2d with data */ bool initWithData(const void* data, CCTexture2DPixelFormat pixelFormat, unsigned int pixelsWide, unsigned int pixelsHigh, CGSize contentSize); @@ -144,6 +147,9 @@ public: /** Initializes a texture from a string with font name and font size */ bool initWithString(const char *text, const char *fontName, float fontSize); + /** returns the content size of the texture in points */ + CGSize getContentSize(void); + #ifdef _POWERVR_SUPPORT_ /** Extensions to make it easy to create a CCTexture2D object from a PVRTC file diff --git a/cocos2dx/include/CCTextureAtlas.h b/cocos2dx/include/CCTextureAtlas.h index 6c2894af55..b22b708c3d 100644 --- a/cocos2dx/include/CCTextureAtlas.h +++ b/cocos2dx/include/CCTextureAtlas.h @@ -49,9 +49,9 @@ class CCX_DLL CCTextureAtlas : public NSObject { protected: GLushort *m_pIndices; -#if CC_TEXTURE_ATLAS_USES_VBO +#if CC_USES_VBO GLuint m_pBuffersVBO[2]; //0: vertex 1: indices -#endif // CC_TEXTURE_ATLAS_USES_VBO +#endif // CC_USES_VBO /** quantity of quads that are going to be drawn */ CCX_PROPERTY_READONLY(unsigned int, m_uTotalQuads, TotalQuads) diff --git a/cocos2dx/include/CCTextureCache.h b/cocos2dx/include/CCTextureCache.h index 0bc0d3edfd..8356ed8b98 100644 --- a/cocos2dx/include/CCTextureCache.h +++ b/cocos2dx/include/CCTextureCache.h @@ -82,25 +82,7 @@ public: * @since v0.8 */ - // @todo void addImageAsync(const char* filename, NSObject*target, fpAsyncCallback func); - -#if _POWERVR_SUPPORT_ - /** Returns a Texture2D object given an PVRTC RAW filename - * If the file image was not previously loaded, it will create a new CCTexture2D - * object and it will return it. Otherwise it will return a reference of a previosly loaded image - * - * It can only load square images: width == height, and it must be a power of 2 (128,256,512...) - * bpp can only be 2 or 4. 2 means more compression but lower quality. - * hasAlpha: whether or not the image contains alpha channel - */ - CCTexture2D* addPVRTCImage(const char* fileimage, int bpp, bool hasAlpha, int width); - - /** Returns a Texture2D object given an PVRTC filename - * If the file image was not previously loaded, it will create a new CCTexture2D - * object and it will return it. Otherwise it will return a reference of a previosly loaded image - */ - CCTexture2D* addPVRTCImage(const char* fileimage); -#endif + // @todo void addImageAsync(const char* filename, NSObject*target, fpAsyncCallback func); /* Returns a Texture2D object given an CGImageRef image * If the image was not previously loaded, it will create a new CCTexture2D object and it will return it. @@ -117,6 +99,11 @@ public: * If "key" is nil, then a new texture will be created each time. */ CCTexture2D* addUIImage(UIImage *image, const char *key); + + /** Returns an already created texture. Returns nil if the texture doesn't exist. + @since v0.99.5 + */ + CCTexture2D* textureForKey(const char* key); /** Purges the dictionary of loaded textures. * Call this method if you receive the "Memory Warning" * In the short term: it will free some resources preventing your app from being killed @@ -139,7 +126,25 @@ public: /** Deletes a texture from the cache given a its key name @since v0.99.4 */ - void removeTextureForKey(const std::string & textureKeyName); + void removeTextureForKey(const char *textureKeyName); + +#if _POWERVR_SUPPORT_ + /** Returns a Texture2D object given an PVRTC RAW filename + * If the file image was not previously loaded, it will create a new CCTexture2D + * object and it will return it. Otherwise it will return a reference of a previosly loaded image + * + * It can only load square images: width == height, and it must be a power of 2 (128,256,512...) + * bpp can only be 2 or 4. 2 means more compression but lower quality. + * hasAlpha: whether or not the image contains alpha channel + */ + CCTexture2D* addPVRTCImage(const char* fileimage, int bpp, bool hasAlpha, int width); + + /** Returns a Texture2D object given an PVRTC filename + * If the file image was not previously loaded, it will create a new CCTexture2D + * object and it will return it. Otherwise it will return a reference of a previosly loaded image + */ + CCTexture2D* addPVRTCImage(const char* fileimage); +#endif }; }//namespace cocos2d diff --git a/cocos2dx/textures/CCTexture2D.cpp b/cocos2dx/textures/CCTexture2D.cpp index 8bd7ae202d..da0317bf3a 100644 --- a/cocos2dx/textures/CCTexture2D.cpp +++ b/cocos2dx/textures/CCTexture2D.cpp @@ -37,8 +37,8 @@ THE SOFTWARE. #include "CCConfiguration.h" #include "platform/platform.h" #include "CCXUIImage.h" - -#include +#include "CCGL.h" +#include "support/ccUtils.h" #ifdef _POWERVR_SUPPORT_ #include "CCPVRTexture.h" @@ -50,18 +50,6 @@ namespace cocos2d { // FontLabel support #endif// CC_FONT_LABEL_SUPPORT - -static unsigned int nextPOT(unsigned int x) -{ - x = x - 1; - x = x | (x >> 1); - x = x | (x >> 2); - x = x | (x >> 4); - x = x | (x >> 8); - x = x | (x >>16); - return x + 1; -} - //CLASS IMPLEMENTATIONS: @@ -103,11 +91,20 @@ GLuint CCTexture2D::getName() return m_uName; } -CGSize CCTexture2D::getContentSize() +CGSize CCTexture2D::getContentSizeInPixels() { return m_tContentSize; } +CGSize CCTexture2D::getContentSize() +{ + CGSize ret; + ret.width = m_tContentSize.width / CC_CONTENT_SCALE_FACTOR(); + ret.height = m_tContentSize.height / CC_CONTENT_SCALE_FACTOR(); + + return ret; +} + GLfloat CCTexture2D::getMaxS() { return m_fMaxS; @@ -128,6 +125,17 @@ void CCTexture2D::setMaxT(GLfloat maxT) m_fMaxT = maxT; } +void CCTexture2D::releaseData(void *data) +{ + free(data); +} + +void* CCTexture2D::keepData(void *data, unsigned int length) +{ + //The texture data mustn't be saved becuase it isn't a mutable texture. + return data; +} + bool CCTexture2D::getHasPremultipliedAlpha() { return m_bHasPremultipliedAlpha; @@ -353,11 +361,11 @@ bool CCTexture2D::initPremultipliedATextureWithImage(UIImage *image, unsigned in if(pixelFormat == kCCTexture2DPixelFormat_RGB565) { //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB" - tempData = new UINT8[POTHigh * POTWide * 2]; + tempData = new unsigned char[POTHigh * POTWide * 2]; inPixel32 = (unsigned int*)data; outPixel16 = (unsigned short*)tempData; - for(i = 0; i < POTWide * POTHigh; ++i, ++inPixel32) + for(unsigned int i = 0; i < POTWide * POTHigh; ++i, ++inPixel32) *outPixel16++ = ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | ((((*inPixel32 >> 8) & 0xFF) >> 2) << 5) | ((((*inPixel32 >> 16) & 0xFF) >> 3) << 0); delete [] data; @@ -365,11 +373,11 @@ bool CCTexture2D::initPremultipliedATextureWithImage(UIImage *image, unsigned in } else if (pixelFormat == kCCTexture2DPixelFormat_RGBA4444) { //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRGGGGBBBBAAAA" - tempData = new UINT8[POTHigh * POTWide * 2]; + tempData = new unsigned char[POTHigh * POTWide * 2]; inPixel32 = (unsigned int*)data; outPixel16 = (unsigned short*)tempData; - for(i = 0; i < POTWide * POTHigh; ++i, ++inPixel32) + for(unsigned int i = 0; i < POTWide * POTHigh; ++i, ++inPixel32) *outPixel16++ = ((((*inPixel32 >> 0) & 0xFF) >> 4) << 12) | // R ((((*inPixel32 >> 8) & 0xFF) >> 4) << 8) | // G @@ -381,11 +389,11 @@ bool CCTexture2D::initPremultipliedATextureWithImage(UIImage *image, unsigned in } else if (pixelFormat == kCCTexture2DPixelFormat_RGB5A1) { //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGBBBBBA" - tempData = new UINT8[POTHigh * POTWide * 2]; + tempData = new unsigned char[POTHigh * POTWide * 2]; inPixel32 = (unsigned int*)data; outPixel16 = (unsigned short*)tempData; - for(i = 0; i < POTWide * POTHigh; ++i, ++inPixel32) + for(unsigned int i = 0; i < POTWide * POTHigh; ++i, ++inPixel32) *outPixel16++ = ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | // R ((((*inPixel32 >> 8) & 0xFF) >> 3) << 6) | // G @@ -441,20 +449,11 @@ void CCTexture2D::drawAtPoint(CGPoint point) GLfloat width = (GLfloat)m_uPixelsWide * m_fMaxS, height = (GLfloat)m_uPixelsHigh * m_fMaxT; -#if 0 - GLfloat vertices[] = { - -width / 2 + point.x, -height / 2 + point.y, 0.0f, - width / 2 + point.x, -height / 2 + point.y, 0.0f, - -width / 2 + point.x, height / 2 + point.y, 0.0f, - width / 2 + point.x, height / 2 + point.y, 0.0f }; - -#else // anchor is done by cocos2d automagically GLfloat vertices[] = { point.x, point.y, 0.0f, width + point.x, point.y, 0.0f, point.x, height + point.y, 0.0f, width + point.x, height + point.y, 0.0f }; -#endif glBindTexture(GL_TEXTURE_2D, m_uName); glVertexPointer(3, GL_FLOAT, 0, vertices); @@ -563,14 +562,14 @@ CCTexture2D * CCTexture2D::initWithPVRTCFile(const char* file) void CCTexture2D::generateMipmap() { - NSAssert( m_uPixelsWide == nextPOT(m_uPixelsWide) && m_uPixelsHigh == nextPOT(m_uPixelsHigh), "Mimpap texture only works in POT textures"); + NSAssert( m_uPixelsWide == ccNextPOT(m_uPixelsWide) && m_uPixelsHigh == ccNextPOT(m_uPixelsHigh), "Mimpap texture only works in POT textures"); glBindTexture( GL_TEXTURE_2D, this->m_uName ); - glGenerateMipmapOES(GL_TEXTURE_2D); + ccglGenerateMipmap(GL_TEXTURE_2D); } void CCTexture2D::setTexParameters(ccTexParams *texParams) { - NSAssert( (m_uPixelsWide == nextPOT(m_uPixelsWide) && m_uPixelsHigh == nextPOT(m_uPixelsHigh)) || + NSAssert( (m_uPixelsWide == ccNextPOT(m_uPixelsWide) && m_uPixelsHigh == ccNextPOT(m_uPixelsHigh)) || (texParams->wrapS == GL_CLAMP_TO_EDGE && texParams->wrapT == GL_CLAMP_TO_EDGE), "GL_CLAMP_TO_EDGE should be used in NPOT textures"); glBindTexture( GL_TEXTURE_2D, this->m_uName ); diff --git a/cocos2dx/textures/CCTextureAtlas.cpp b/cocos2dx/textures/CCTextureAtlas.cpp index 95c476253a..4d952641f8 100644 --- a/cocos2dx/textures/CCTextureAtlas.cpp +++ b/cocos2dx/textures/CCTextureAtlas.cpp @@ -52,9 +52,9 @@ CCTextureAtlas::~CCTextureAtlas() CCX_SAFE_FREE(m_pQuads) CCX_SAFE_FREE(m_pIndices) -#if CC_TEXTURE_ATLAS_USES_VBO +#if CC_USES_VBO glDeleteBuffers(2, m_pBuffersVBO); -#endif // CC_TEXTURE_ATLAS_USES_VBO +#endif // CC_USES_VBO CCX_SAFE_RELEASE(m_pTexture); } @@ -120,9 +120,19 @@ CCTextureAtlas * CCTextureAtlas::textureAtlasWithTexture(CCTexture2D *texture, u bool CCTextureAtlas::initWithFile(const char * file, unsigned int capacity) { // retained in property - CCTexture2D *texture = CCTextureCache::sharedTextureCache()->addImage(file); + CCTexture2D *texture = CCTextureCache::sharedTextureCache()->addImage(file); - return initWithTexture(texture, capacity); + if (texture) + { + return initWithTexture(texture, capacity); + } + else + { + CCLOG("cocos2d: Could not open file: %s", file); + delete this; + + return NULL; + } } bool CCTextureAtlas::initWithTexture(CCTexture2D *texture, unsigned int capacity) @@ -145,10 +155,10 @@ bool CCTextureAtlas::initWithTexture(CCTexture2D *texture, unsigned int capacity return false; } -#if CC_TEXTURE_ATLAS_USES_VBO +#if CC_USES_VBO // initial binding glGenBuffers(2, &m_pBuffersVBO[0]); -#endif // CC_TEXTURE_ATLAS_USES_VBO +#endif // CC_USES_VBO this->initIndices(); @@ -189,14 +199,14 @@ void CCTextureAtlas::initIndices() #endif } -#if CC_TEXTURE_ATLAS_USES_VBO +#if CC_USES_VBO glBindBuffer(GL_ARRAY_BUFFER, m_pBuffersVBO[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(m_pQuads[0]) * m_uCapacity, m_pQuads, GL_DYNAMIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_pBuffersVBO[1]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(m_pIndices[0]) * m_uCapacity * 6, m_pIndices, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); -#endif // CC_TEXTURE_ATLAS_USES_VBO +#endif // CC_USES_VBO } // TextureAtlas - Update, Insert, Move & Remove @@ -212,13 +222,13 @@ void CCTextureAtlas::updateQuad(ccV3F_C4B_T2F_Quad *quad, unsigned int index) void CCTextureAtlas::insertQuad(ccV3F_C4B_T2F_Quad *quad, unsigned int index) { - NSAssert( index >= 0 && index < m_uCapacity, "insertQuadWithTexture: Invalid index"); + NSAssert( index < m_uCapacity, "insertQuadWithTexture: Invalid index"); m_uTotalQuads++; NSAssert( m_uTotalQuads <= m_uCapacity, "invalid totalQuads"); // issue #575. index can be > totalQuads - int remaining = (m_uTotalQuads-1) - index; + unsigned int remaining = (m_uTotalQuads-1) - index; // last object doesn't need to be moved if( remaining > 0) { @@ -240,8 +250,8 @@ void CCTextureAtlas::insertQuadFromIndex(unsigned int oldIndex, unsigned int new // because it is ambigious in iphone, so we implement abs ourself // unsigned int howMany = abs( oldIndex - newIndex); unsigned int howMany = (oldIndex - newIndex) >= 0 ? (oldIndex - newIndex) : (newIndex - oldIndex); - int dst = oldIndex; - int src = oldIndex + 1; + unsigned int dst = oldIndex; + unsigned int src = oldIndex + 1; if( oldIndex > newIndex) { dst = newIndex+1; src = newIndex; @@ -255,7 +265,7 @@ void CCTextureAtlas::insertQuadFromIndex(unsigned int oldIndex, unsigned int new void CCTextureAtlas::removeQuadAtIndex(unsigned int index) { - NSAssert( index >= 0 && index < m_uTotalQuads, "removeQuadAtIndex: Invalid index"); + NSAssert( index < m_uTotalQuads, "removeQuadAtIndex: Invalid index"); unsigned int remaining = (m_uTotalQuads-1) - index; @@ -267,8 +277,6 @@ void CCTextureAtlas::removeQuadAtIndex(unsigned int index) } m_uTotalQuads--; - - NSAssert( m_uTotalQuads >= 0, "invalid totalQuads"); } void CCTextureAtlas::removeAllQuads() @@ -324,52 +332,55 @@ void CCTextureAtlas::drawQuads() void CCTextureAtlas::drawNumberOfQuads(unsigned int n) { + // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY + // Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY + // Unneeded states: - glBindTexture(GL_TEXTURE_2D, m_pTexture->getName()); #define kQuadSize sizeof(m_pQuads[0].bl) -#if CC_TEXTURE_ATLAS_USES_VBO +#if CC_USES_VBO glBindBuffer(GL_ARRAY_BUFFER, m_pBuffersVBO[0]); // XXX: update is done in draw... perhaps it should be done in a timer glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(m_pQuads[0]) * n, m_pQuads); // vertices - glVertexPointer(3, GL_FLOAT, kQuadSize, (void*) offsetof( ccV3F_C4B_T2F, vertices)); + glVertexPointer(3, GL_FLOAT, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, vertices)); // colors - glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (void*) offsetof( ccV3F_C4B_T2F, colors)); + glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, colors)); // texture coords - glTexCoordPointer(2, GL_FLOAT, kQuadSize, (void*) offsetof( ccV3F_C4B_T2F, texCoords)); + glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, texCoords)); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_pBuffersVBO[1]); #if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP - glDrawElements(GL_TRIANGLE_STRIP, n*6, GL_UNSIGNED_SHORT, (void*)0); + glDrawElements(GL_TRIANGLE_STRIP, n*6, GL_UNSIGNED_SHORT, (GLvoid*)0); #else - glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, (void*)0); -#endif // CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP + glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, (GLvoid*)0); +#endif // CC_USES_VBO glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); -#else // ! CC_TEXTURE_ATLAS_USES_VBO +#else // ! CC_USES_VBO - int offset = (int)m_pQuads; + unsigned int offset = (unsigned int)m_pQuads; // vertex - int diff = offsetof( ccV3F_C4B_T2F, vertices); - glVertexPointer(3, GL_FLOAT, kQuadSize, (void*) (offset + diff) ); + unsigned int diff = offsetof( ccV3F_C4B_T2F, vertices); + glVertexPointer(3, GL_FLOAT, kQuadSize, (GLvoid*) (offset + diff) ); // color diff = offsetof( ccV3F_C4B_T2F, colors); - glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (void*)(offset + diff)); + glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*)(offset + diff)); // texture coords diff = offsetof( ccV3F_C4B_T2F, texCoords); - glTexCoordPointer(2, GL_FLOAT, kQuadSize, (void*)(offset + diff)); + glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*)(offset + diff)); #if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP glDrawElements(GL_TRIANGLE_STRIP, n*6, GL_UNSIGNED_SHORT, m_pIndices); @@ -377,7 +388,7 @@ void CCTextureAtlas::drawNumberOfQuads(unsigned int n) glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, m_pIndices); #endif -#endif // CC_TEXTURE_ATLAS_USES_VBO +#endif // CC_USES_VBO } diff --git a/cocos2dx/textures/CCTextureCache.cpp b/cocos2dx/textures/CCTextureCache.cpp index c8a6fd56f9..d89139e405 100644 --- a/cocos2dx/textures/CCTextureCache.cpp +++ b/cocos2dx/textures/CCTextureCache.cpp @@ -184,6 +184,9 @@ CCTexture2D * CCTextureCache::addImage(const char * path) m_pDictLock->lock(); + // remove possible -HD suffix to prevent caching the same image twice (issue #1040) + fullpath = string(ccRemoveHDSuffixFromFile(fullpath.c_str())); + texture = m_pTextures->objectForKey(fullpath); if( ! texture ) @@ -419,12 +422,19 @@ void CCTextureCache::removeTexture(CCTexture2D* texture) } } -void CCTextureCache::removeTextureForKey(const std::string & textureKeyName) +void CCTextureCache::removeTextureForKey(const char *textureKeyName) { - if( textureKeyName.empty() ) + if (textureKeyName == NULL) + { return; + } - m_pTextures->removeObjectForKey(textureKeyName); + m_pTextures->removeObjectForKey(string(textureKeyName)); +} + +CCTexture2D* CCTextureCache::textureForKey(const char* key) +{ + return m_pTextures->objectForKey(string(key)); } }//namespace cocos2d