diff --git a/cocos2dx/Android.mk b/cocos2dx/Android.mk index ce3aa12f32..a3685d8418 100644 --- a/cocos2dx/Android.mk +++ b/cocos2dx/Android.mk @@ -88,7 +88,8 @@ text_input_node/CCIMEDispatcher.cpp \ text_input_node/CCTextFieldTTF.cpp \ textures/CCTexture2D.cpp \ textures/CCTextureAtlas.cpp \ -textures/CCTextureCache.cpp \ +textures/CCTextureCache.cpp \ +textures/CCTexturePVR.cpp \ tileMap_parallax_nodes/CCParallaxNode.cpp \ tileMap_parallax_nodes/CCTMXLayer.cpp \ tileMap_parallax_nodes/CCTMXObjectGroup.cpp \ diff --git a/cocos2dx/include/CCPVRTexture.h b/cocos2dx/include/CCPVRTexture.h deleted file mode 100644 index f53cf03a67..0000000000 --- a/cocos2dx/include/CCPVRTexture.h +++ /dev/null @@ -1,73 +0,0 @@ -/**************************************************************************** -Copyright (c) 2010 cocos2d-x.org - -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. -****************************************************************************/ - -#if 0 // PVR TEXTURE CANNOT CROSS PLATFORM - -#ifndef __CCPVRTEXTURE_H__ -#define __CCPVRTEXTURE_H__ - -#include -#include -#include - -#include "CCObject.h" -#include "CCMutableArray.h" - -namespace cocos2d { -class CCData; - -class CCPVRTexture : public CCObject -{ -protected: - CCMutableArray * m_pImageData; - -public: - - CCPVRTexture(); - virtual ~CCPVRTexture(); - - CCPVRTexture * initWithContentsOfFile(const char* path); -// @todo CCPVRTexture * initWithContentsOfURL(NSURL *url); - static CCPVRTexture * pvrTextureWithContentsOfFile(const char* path); -// @todo static CCPVRTexture * pvrTextureWithContentsOfURL(NSURL *url); - - CC_PROPERTY_READONLY(GLuint, m_uName, Name) - CC_PROPERTY_READONLY(unsigned int, m_uWidth, Width) - CC_PROPERTY_READONLY(unsigned int, m_uHeight, Height) - CC_PROPERTY_READONLY(GLenum, m_uInternalFormat, InternalFormat) - CC_PROPERTY_READONLY(bool, m_bHasAlpha, HasAlpha) - - // cocos2d integration - CC_PROPERTY(bool, m_bRetainName, RetainName); - -private: - bool unpackPVRData(CCData *data); - bool createGLTexture(); -}; -}//namespace cocos2d - - -#endif //__CCPVRTEXTURE_H__ - -#endif diff --git a/cocos2dx/include/CCTexture2D.h b/cocos2dx/include/CCTexture2D.h index 0e6328424e..c96165761a 100644 --- a/cocos2dx/include/CCTexture2D.h +++ b/cocos2dx/include/CCTexture2D.h @@ -49,17 +49,17 @@ typedef enum { kCCTexture2DPixelFormat_RGB565, //! 8-bit textures used as masks kCCTexture2DPixelFormat_A8, - //! 8-bit intensity texture + //! 8-bit intensity texture kCCTexture2DPixelFormat_I8, - //! 16-bit textures used as masks + //! 16-bit textures used as masks kCCTexture2DPixelFormat_AI88, //! 16-bit textures: RGBA4444 kCCTexture2DPixelFormat_RGBA4444, //! 16-bit textures: RGB5A1 kCCTexture2DPixelFormat_RGB5A1, - //! 4-bit PVRTC-compressed texture: PVRTC4 - kCCTexture2DPixelFormat_PVRTC4, - //! 2-bit PVRTC-compressed texture: PVRTC2 + //! 4-bit PVRTC-compressed texture: PVRTC4 + kCCTexture2DPixelFormat_PVRTC4, + //! 2-bit PVRTC-compressed texture: PVRTC2 kCCTexture2DPixelFormat_PVRTC2, //! Default texture format: RGBA8888 @@ -157,16 +157,17 @@ public: /** returns the content size of the texture in points */ CCSize getContentSize(void); -#ifdef _POWERVR_SUPPORT_ +#ifdef CC_SUPPORT_PVRTC /** Extensions to make it easy to create a CCTexture2D object from a PVRTC file Note that the generated textures don't have their alpha premultiplied - use the blending mode (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). */ /** Initializes a texture from a PVRTC buffer */ - bool initWithPVRTCData(const void* data, int level, int bpp, bool hasAlpha, int length); - /** Initializes a texture from a PVRTC file */ - bool initWithPVRTCFile(const char* file); -#endif + bool initWithPVRTCData(const void *data, int level, int bpp, bool hasAlpha, int length, CCTexture2DPixelFormat pixelFormat); +#endif // CC_SUPPORT_PVRTC + + /** Initializes a texture from a PVR file */ + bool initWithPVRFile(const char* file); /** sets the min filter, mag filter, wrap s and wrap t texture parameters. If the texture size is NPOT (non power of 2), then in can only use GL_CLAMP_TO_EDGE in GL_TEXTURE_WRAP_{S,T}. @@ -197,12 +198,14 @@ public: */ void generateMipmap(); - /** returns the bits-per-pixel of the in-memory OpenGL texture - @since v1.0 + /** returns the bits-per-pixel of the in-memory OpenGL texture + @since v1.0 */ unsigned int bitsPerPixelForFormat(); + void setPVRImagesHavePremultipliedAlpha(bool haveAlphaPremultiplied); + /** sets the default pixel format for UIImages that contains alpha channel. If the UIImage contains alpha channel, then the options are: - generate 32-bit textures: kCCTexture2DPixelFormat_RGBA8888 (default one) @@ -227,6 +230,9 @@ public: private: bool initPremultipliedATextureWithImage(CCImage * image, unsigned int pixelsWide, unsigned int pixelsHigh); + + // By default PVR images are treated as if they don't have the alpha channel premultiplied + bool m_bPVRHaveAlphaPremultiplied; }; }//namespace cocos2d diff --git a/cocos2dx/include/CCTextureCache.h b/cocos2dx/include/CCTextureCache.h index 3cc7d78626..ad5755bc57 100644 --- a/cocos2dx/include/CCTextureCache.h +++ b/cocos2dx/include/CCTextureCache.h @@ -135,14 +135,14 @@ public: */ void removeTextureForKey(const char *textureKeyName); - /** Output to CCLOG the current contents of this CCTextureCache - * This will attempt to calculate the size of each texture, and the total texture memory in use - * - * @since v1.0 + /** Output to CCLOG the current contents of this CCTextureCache + * This will attempt to calculate the size of each texture, and the total texture memory in use + * + * @since v1.0 */ void dumpCachedTextureInfo(); -#if _POWERVR_SUPPORT_ +#ifdef CC_SUPPORT_PVRTC /** 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 @@ -152,13 +152,13 @@ public: * 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 +#endif // CC_SUPPORT_PVRTC + + /** Returns a Texture2D object given an PVR 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 + CCTexture2D* addPVRImage(const char* filename); /** Reload all textures It's only useful when the value of CC_ENABLE_CACHE_TEXTTURE_DATA is 1 @@ -168,24 +168,24 @@ public: #if CC_ENABLE_CACHE_TEXTTURE_DATA -class VolatileTexture -{ -public: - VolatileTexture(CCTexture2D *t); - ~VolatileTexture(); - - static void addImageTexture(CCTexture2D *tt, const char* imageFileName, CCImage::EImageFormat format); - static void addStringTexture(CCTexture2D *tt, const char* text, CCSize dimensions, CCTextAlignment alignment, const char *fontName, float fontSize); - - static void removeTexture(CCTexture2D *t); - static void reloadAllTextures(); - -public: - static std::list textures; - static bool isReloading; - -protected: - CCTexture2D *texture; +class VolatileTexture +{ +public: + VolatileTexture(CCTexture2D *t); + ~VolatileTexture(); + + static void addImageTexture(CCTexture2D *tt, const char* imageFileName, CCImage::EImageFormat format); + static void addStringTexture(CCTexture2D *tt, const char* text, CCSize dimensions, CCTextAlignment alignment, const char *fontName, float fontSize); + + static void removeTexture(CCTexture2D *t); + static void reloadAllTextures(); + +public: + static std::list textures; + static bool isReloading; + +protected: + CCTexture2D *texture; bool m_bIsString; diff --git a/cocos2dx/include/CCTexturePVR.h b/cocos2dx/include/CCTexturePVR.h new file mode 100755 index 0000000000..4d2c8acc8a --- /dev/null +++ b/cocos2dx/include/CCTexturePVR.h @@ -0,0 +1,139 @@ +/**************************************************************************** +Copyright (c) 2011 Jirka Fajfr for cocos2d-x +Copyright (c) 2010 cocos2d-x.org + +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. +****************************************************************************/ + +#ifndef __CCPVRTEXTURE_H__ +#define __CCPVRTEXTURE_H__ + +#include +#include + +#include "CCGL.h" +#include "CCObject.h" +#include "CCMutableArray.h" + +namespace cocos2d { + +//Forward definition for CCData +class CCData; + +/** + @brief Structure which can tell where mimap begins and how long is it +*/ +struct CCPVRMipmap { + unsigned char *address; + unsigned int len; +}; + +/** + @brief Detemine how many mipmaps can we have. + Its same as define but it respects namespaces +*/ +enum { + CC_PVRMIPMAP_MAX = 16, +}; + + +/** CCTexturePVR + + Object that loads PVR images. + + Supported PVR formats: + - RGBA8888 + - BGRA8888 + - RGBA4444 + - RGBA5551 + - RGB565 + - A8 + - I8 + - AI88 + - PVRTC 4BPP + - PVRTC 2BPP + + Limitations: + Pre-generated mipmaps, such as PVR textures with mipmap levels embedded in file, + are only supported if all individual sprites are of _square_ size. + To use mipmaps with non-square textures, instead call CCTexture2D#generateMipmap on the sheet texture itself + (and to save space, save the PVR sprite sheet without mip maps included). +*/ +class CCTexturePVR : public CCObject +{ +public: + + CCTexturePVR(); + virtual ~CCTexturePVR(); + + /** initializes a CCTexturePVR with a path */ + bool initWithContentsOfFile(const char* path); + + /** creates and initializes a CCTexturePVR with a path */ + static CCTexturePVR * pvrTextureWithContentsOfFile(const char* path); + + CC_PROPERTY_READONLY(GLuint, m_uName, Name) + CC_PROPERTY_READONLY(unsigned int, m_uWidth, Width) + CC_PROPERTY_READONLY(unsigned int, m_uHeight, Height) + CC_PROPERTY_READONLY(CCTexture2DPixelFormat, m_eFormat, Format) + CC_PROPERTY_READONLY(bool, m_bHasAlpha, HasAlpha) + + // cocos2d integration + CC_PROPERTY(bool, m_bRetainName, RetainName); + +protected: + + /* + Unpacks data (data of pvr texture file) and determine + how many mipmaps it uses (m_uNumberOfMipmaps). Adresses + of mimaps (m_asMipmaps). And basic data like size, format + and alpha presence + */ + bool unpackPVRData(unsigned char* data, unsigned int len); + + /* + Binds all mipmaps to the GL state machine as separate + textures + */ + bool createGLTexture(); + + /* + Index to the tableFormats array. Which tells us what exact + format is file which initializes this object. + */ + unsigned int m_uTableFormatIndex; + + /* + How many mipmaps do we have. It must be at least one + when proper initialization finishes + */ + unsigned int m_uNumberOfMipmaps; + + /* + Makrs for mipmaps. Each entry contains position in file + and lenght of data which represents one mipmap. + */ + struct CCPVRMipmap m_asMipmaps[CC_PVRMIPMAP_MAX]; +}; +}//namespace cocos2d + + +#endif //__CCPVRTEXTURE_H__ \ No newline at end of file diff --git a/cocos2dx/include/cocos2d.h b/cocos2dx/include/cocos2d.h index e9870ccff4..8eab7f131a 100644 --- a/cocos2dx/include/cocos2d.h +++ b/cocos2dx/include/cocos2d.h @@ -77,17 +77,17 @@ THE SOFTWARE. #include "CCActionPageTurn3D.h" #include "CCTransitionPageTurn.h" #include "CCTexture2D.h" -#include "CCPVRTexture.h" +#include "CCTexturePVR.h" #include "CCTransitionRadial.h" #include "CCActionProgressTimer.h" #include "CCTouchDispatcher.h" #include "CCDrawingPrimitives.h" #include "CCScheduler.h" -// havn't implement on wophone and airplay -#if (CC_TARGET_PLATFORM != CC_PLATFORM_AIRPLAY) +// havn't implement on wophone and airplay +#if (CC_TARGET_PLATFORM != CC_PLATFORM_AIRPLAY) #include "CCTextFieldTTF.h" -#endif +#endif // // cocoa includes diff --git a/cocos2dx/platform/CCFileUtils.h b/cocos2dx/platform/CCFileUtils.h index 479f1f5149..c64e473457 100644 --- a/cocos2dx/platform/CCFileUtils.h +++ b/cocos2dx/platform/CCFileUtils.h @@ -41,9 +41,9 @@ public: @param[out] pSize If get the file data succeed the it will be the data size,or it will be 0 @return if success,the pointer of data will be returned,or NULL is returned @warning If you get the file data succeed,you must delete it after used. - */ - static unsigned char* getFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize); - + */ + static unsigned char* getFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize); + /** @brief Get resource file data from zip file @param[in] pszFileName The resource file name which contain the relative path of zip file @@ -51,12 +51,12 @@ public: @return if success,the pointer of data will be returned,or NULL is returned @warning If you get the file data succeed,you must delete it after used. */ - static unsigned char* getFileDataFromZip(const char* pszZipFilePath, const char* pszFileName, unsigned long * pSize); - - /** removes the HD suffix from a path - @returns const char * without the HD suffix - @since v0.99.5 - */ + static unsigned char* getFileDataFromZip(const char* pszZipFilePath, const char* pszFileName, unsigned long * pSize); + + /** removes the HD suffix from a path + @returns const char * without the HD suffix + @since v0.99.5 + */ static std::string& ccRemoveHDSuffixFromFile(std::string& path); /** @@ -116,7 +116,7 @@ public: /////////////////////////////////////////////////// // interfaces on ios /////////////////////////////////////////////////// - int ccLoadFileIntoMemory(const char *filename, unsigned char **out); + static int ccLoadFileIntoMemory(const char *filename, unsigned char **out); }; class CCFileData diff --git a/cocos2dx/platform/CCPlatformConfig.h b/cocos2dx/platform/CCPlatformConfig.h index d2dacd0d7c..7783bbf1f5 100644 --- a/cocos2dx/platform/CCPlatformConfig.h +++ b/cocos2dx/platform/CCPlatformConfig.h @@ -54,6 +54,7 @@ There are config below: #define CC_TARGET_PLATFORM CC_PLATFORM_IOS #define CC_SUPPORT_MULTITHREAD 0 #define CC_SUPPORT_UNICODE 0 + #define CC_SUPPORT_PVRTC #endif // android diff --git a/cocos2dx/platform/ios/CCFileUtils_ios.mm b/cocos2dx/platform/ios/CCFileUtils_ios.mm index 8fac0e5199..6d4f629706 100644 --- a/cocos2dx/platform/ios/CCFileUtils_ios.mm +++ b/cocos2dx/platform/ios/CCFileUtils_ios.mm @@ -256,7 +256,7 @@ namespace cocos2d { int CCFileUtils::ccLoadFileIntoMemory(const char *filename, unsigned char **out) { CCAssert( out, "ccLoadFileIntoMemory: invalid 'out' parameter"); - CCAssert( &*out, "ccLoadFileIntoMemory: invalid 'out' parameter"); + CCAssert( &*out, "ccLoadFileIntoMemory: invalid 'out' parameter"); size_t size = 0; FILE *f = fopen(filename, "rb"); diff --git a/cocos2dx/textures/CCPVRTexture.cpp b/cocos2dx/textures/CCPVRTexture.cpp deleted file mode 100644 index 1e5a672249..0000000000 --- a/cocos2dx/textures/CCPVRTexture.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/**************************************************************************** -Copyright (c) 2010-2011 cocos2d-x.org -Copyright (c) 2008 Apple Inc. All Rights Reserved. - -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. -****************************************************************************/ - -#if 0 // PVR TEXTURE CANNOT CROSS PLATFORM - -#include "CCPVRTexture.h" -#include "ccMacros.h" -#include "CCData.h" - -namespace cocos2d { - -#define PVR_TEXTURE_FLAG_TYPE_MASK 0xff - -static char* gPVRTexIdentifier[] = {"PVR!"}; - -enum -{ - kPVRTextureFlagTypePVRTC_2 = 24, - kPVRTextureFlagTypePVRTC_4 -}; - -typedef struct _PVRTexHeader -{ - unsigned int headerLength; - unsigned int height; - unsigned int width; - unsigned int numMipmaps; - unsigned int flags; - unsigned int dataLength; - unsigned int bpp; - unsigned int bitmaskRed; - unsigned int bitmaskGreen; - unsigned int bitmaskBlue; - unsigned int bitmaskAlpha; - unsigned int pvrTag; - unsigned int numSurfs; -} PVRTexHeader; - -CCPVRTexture::CCPVRTexture() -{ -} - -CCPVRTexture::~CCPVRTexture() -{ - CCLOGINFO( "cocos2d: deallocing CCPVRTexture" ); - - m_pImageData->removeAllObjects(); - CC_SAFE_DELETE(m_pImageData) - - if (m_uName != 0 && ! m_bRetainName ) - glDeleteTextures(1, &m_uName); -} - -GLuint CCPVRTexture::getName() -{ - return m_uName; -} - -unsigned int CCPVRTexture::getWidth() -{ - return m_uWidth; -} - -unsigned int CCPVRTexture::getHeight() -{ - return m_uHeight; -} - -GLenum CCPVRTexture::getInternalFormat() -{ - return m_uInternalFormat; -} - -bool CCPVRTexture::getHasAlpha() -{ - return m_bHasAlpha; -} - -bool CCPVRTexture::getRetainName() -{ - return m_bRetainName; -} - -void CCPVRTexture::setRetainName(bool var) -{ - m_bRetainName = var; -} - -/** @todo CCData uint8_t -- (BOOL)unpackPVRData:(CCData *)data -{ - BOOL success = FALSE; - PVRTexHeader *header = NULL; - uint32_t flags, pvrTag; - uint32_t dataLength = 0, dataOffset = 0, dataSize = 0; - uint32_t blockSize = 0, widthBlocks = 0, heightBlocks = 0; - uint32_t width = 0, height = 0, bpp = 4; - uint8_t *bytes = NULL; - uint32_t formatFlags; - - header = (PVRTexHeader *)[data bytes]; - - pvrTag = CFSwapInt32LittleToHost(header->pvrTag); - - if ((uint32_t)gPVRTexIdentifier[0] != ((pvrTag >> 0) & 0xff) || - (uint32_t)gPVRTexIdentifier[1] != ((pvrTag >> 8) & 0xff) || - (uint32_t)gPVRTexIdentifier[2] != ((pvrTag >> 16) & 0xff) || - (uint32_t)gPVRTexIdentifier[3] != ((pvrTag >> 24) & 0xff)) - { - return FALSE; - } - - flags = CFSwapInt32LittleToHost(header->flags); - formatFlags = flags & PVR_TEXTURE_FLAG_TYPE_MASK; - - if (formatFlags == kPVRTextureFlagTypePVRTC_4 || formatFlags == kPVRTextureFlagTypePVRTC_2) - { - [_imageData removeAllObjects]; - - if (formatFlags == kPVRTextureFlagTypePVRTC_4) - _internalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; - else if (formatFlags == kPVRTextureFlagTypePVRTC_2) - _internalFormat = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; - - _width = width = CFSwapInt32LittleToHost(header->width); - _height = height = CFSwapInt32LittleToHost(header->height); - - if (CFSwapInt32LittleToHost(header->bitmaskAlpha)) - _hasAlpha = TRUE; - else - _hasAlpha = FALSE; - - dataLength = CFSwapInt32LittleToHost(header->dataLength); - - bytes = ((uint8_t *)[data bytes]) + sizeof(PVRTexHeader); - - // Calculate the data size for each texture level and respect the minimum number of blocks - while (dataOffset < dataLength) - { - if (formatFlags == kPVRTextureFlagTypePVRTC_4) - { - blockSize = 4 * 4; // Pixel by pixel block size for 4bpp - widthBlocks = width / 4; - heightBlocks = height / 4; - bpp = 4; - } - else - { - blockSize = 8 * 4; // Pixel by pixel block size for 2bpp - widthBlocks = width / 8; - heightBlocks = height / 4; - bpp = 2; - } - - // Clamp to minimum number of blocks - if (widthBlocks < 2) - widthBlocks = 2; - if (heightBlocks < 2) - heightBlocks = 2; - - dataSize = widthBlocks * heightBlocks * ((blockSize * bpp) / 8); - - [_imageData addObject:[CCData dataWithBytes:bytes+dataOffset length:dataSize]]; - - dataOffset += dataSize; - - width = MAX(width >> 1, 1); - height = MAX(height >> 1, 1); - } - - success = TRUE; - } - - return success; -}*/ - - -bool CCPVRTexture::createGLTexture() -{ - int width = m_uWidth; - int height = m_uHeight; -/// @todo CCData *data; - GLenum err; - - if (m_pImageData->count() > 0) - { - if (m_uName != 0) - glDeleteTextures(1, &m_uName); - - glGenTextures(1, &m_uName); - glBindTexture(GL_TEXTURE_2D, m_uName); - } - - for (unsigned int i=0; i < m_pImageData->count(); i++) - { -/// @todo CCData data = m_pImageData->getObjectAtIndex(i); -/// @todo CCData glCompressedTexImage2D(GL_TEXTURE_2D, i, m_uInternalFormat, width, height, 0, [data length], [data bytes]); - - err = glGetError(); - if (err != GL_NO_ERROR) - { - CCLOG("Error uploading compressed texture level: %u. glError: %u", i, err); - return false; - } - - width = MAX(width >> 1, 1); - height = MAX(height >> 1, 1); - } - - m_pImageData->removeAllObjects(); - - return true; -} - - -CCPVRTexture * CCPVRTexture::initWithContentsOfFile(const char* path) -{ - /** @todo CCData*/ - CCData *data = CCData::dataWithContentsOfFile(path); - - m_pImageData = new CCMutableArray(10); - - m_uName = 0; - m_uWidth = m_uHeight = 0; - m_uInternalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; - m_bHasAlpha = false; - - m_bRetainName = false; // cocos2d integration -/// @todo -// if (!data || ![self unpackPVRData:data] || ![self createGLTexture]) -// { -// [self release]; -// self = nil; -// } - - return this; -} - -/** @todo NSURL -- (id)initWithContentsOfURL:(NSURL *)url -{ - if (![url isFileURL]) - { - CCLOG(@"cocos2d: CCPVRTexture: Only files are supported"); - [self release]; - return nil; - } - - return [self initWithContentsOfFile:[url path]]; -}*/ - - -CCPVRTexture * CCPVRTexture::pvrTextureWithContentsOfFile(const char* path) -{ - CCPVRTexture * pTexture = new CCPVRTexture(); - pTexture->initWithContentsOfFile(path); - pTexture->autorelease(); - return pTexture; -} - -/** @todo NSURL -+ (id)pvrTextureWithContentsOfURL:(NSURL *)url -{ - if (![url isFileURL]) - return nil; - - return [CCPVRTexture pvrTextureWithContentsOfFile:[url path]]; -}*/ - -}//namespace cocos2d - -#endif diff --git a/cocos2dx/textures/CCTexture2D.cpp b/cocos2dx/textures/CCTexture2D.cpp index 3eb9fa4891..866eafb3d1 100644 --- a/cocos2dx/textures/CCTexture2D.cpp +++ b/cocos2dx/textures/CCTexture2D.cpp @@ -40,10 +40,7 @@ THE SOFTWARE. #include "CCGL.h" #include "support/ccUtils.h" #include "platform/CCPlatformMacros.h" - -#ifdef _POWERVR_SUPPORT_ - #include "CCPVRTexture.h" -#endif +#include "CCTexturePVR.h" #if CC_ENABLE_CACHE_TEXTTURE_DATA #include "CCTextureCache.h" @@ -68,6 +65,7 @@ CCTexture2D::CCTexture2D() , m_fMaxS(0.0) , m_fMaxT(0.0) , m_bHasPremultipliedAlpha(false) +, m_bPVRHaveAlphaPremultiplied(true) { } @@ -506,12 +504,11 @@ void CCTexture2D::drawInRect(CCRect rect) glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } - -// implementation CCTexture2D (PVRTC) -#ifdef _POWERVR_SUPPORT_ -bool CCTexture2D::initWithPVRTCData(const void *data, int level, int bpp, bool hasAlpha, int length) +#ifdef CC_SUPPORT_PVRTC +// implementation CCTexture2D (PVRTC); +bool CCTexture2D::initWithPVRTCData(const void *data, int level, int bpp, bool hasAlpha, int length, CCTexture2DPixelFormat pixelFormat) { - if( !(CCPlatformConfiguration::sharedConfiguration()->isSupportsPVRTC()) ) + if( !(CCConfiguration::sharedConfiguration()->isSupportsPVRTC()) ) { CCLOG("cocos2d: WARNING: PVRTC images is not supported."); this->release(); @@ -540,47 +537,53 @@ bool CCTexture2D::initWithPVRTCData(const void *data, int level, int bpp, bool h m_uPixelsHigh = length; m_fMaxS = 1.0f; m_fMaxT = 1.0f; + m_bHasPremultipliedAlpha = m_bPVRHaveAlphaPremultiplied; + m_ePixelFormat = pixelFormat; return true; } +#endif // CC_SUPPORT_PVRTC -CCTexture2D * CCTexture2D::initWithPVRTCFile(const char* file) +bool CCTexture2D::initWithPVRFile(const char* file) { - if (! CCPlatformConfiguration::sharedConfiguration()->isSupportsPVRTC()) - { - CCLOG("cocos2d: WARNING: PVRTC images is not supported"); - this->release(); - return false; - } + bool bRet = false; + // nothing to do with CCObject::init + + CCTexturePVR *pvr = new CCTexturePVR; + bRet = pvr->initWithContentsOfFile(file); + + if (bRet) + { + pvr->setRetainName(true); // don't dealloc texture on release + + m_uName = pvr->getName(); + m_fMaxS = 1.0f; + m_fMaxT = 1.0f; + m_uPixelsWide = pvr->getWidth(); + m_uPixelsHigh = pvr->getHeight(); + m_tContentSize = CCSizeMake(m_uPixelsWide, m_uPixelsHigh); + m_bHasPremultipliedAlpha = m_bPVRHaveAlphaPremultiplied; + m_ePixelFormat = pvr->getFormat(); + + this->setAntiAliasTexParameters(); + } + else + { + CCLOG("cocos2d: Couldn't load PVR image %s", file); + } + + pvr->release(); - CCPVRTexture *pvr = new CCPVRTexture(); - pvr = pvr->initWithContentsOfFile(file); - if( pvr ) - { - pvr->setRetainName(true); // don't dealloc texture on release - - m_uName = pvr->getName(); // texture id - m_fMaxS = 1.0f; - m_fMaxT = 1.0f; - m_uPixelsWide = pvr->getWidth(); // width - m_uPixelsHigh = pvr->getHeight(); // height - /// be careful : unsigned int to float - m_tContentSize = CCSizeMake((float)(m_uPixelsWide), (float)(m_uPixelsHigh)); - - pvr->release(); - - this->setAntiAliasTexParameters(); - } - else - { - CCLOG("cocos2d: Couldn't load PVR image"); - this->release(); - return false; - } - return true; + return bRet; + } -#endif +void CCTexture2D::setPVRImagesHavePremultipliedAlpha(bool haveAlphaPremultiplied) +{ + m_bPVRHaveAlphaPremultiplied = haveAlphaPremultiplied; +} + + // // Use to apply MIN/MAG filter // diff --git a/cocos2dx/textures/CCTextureCache.cpp b/cocos2dx/textures/CCTextureCache.cpp index d2010b4fd0..3ff1d12430 100644 --- a/cocos2dx/textures/CCTextureCache.cpp +++ b/cocos2dx/textures/CCTextureCache.cpp @@ -197,14 +197,11 @@ CCTexture2D * CCTextureCache::addImage(const char * path) lowerCase[i] = tolower(lowerCase[i]); } // all images are handled by UIImage except PVR extension that is handled by our own handler - // if ( [[path lowercaseString] hasSuffix:@".pvr"] ) do { if (std::string::npos != lowerCase.find(".pvr")) { -#ifdef _POWERVR_SUPPORT_ - texture = this->addPVRTCImage(fullpath.c_str()); -#endif + texture = this->addPVRImage(fullpath.c_str()); } // Issue #886: TEMPORARY FIX FOR TRANSPARENT JPEGS IN IOS4 else if (std::string::npos != lowerCase.find(".jpg") || std::string::npos != lowerCase.find(".jpeg")) @@ -269,15 +266,17 @@ CCTexture2D * CCTextureCache::addImage(const char * path) return texture; } -#ifdef _POWERVR_SUPPORT_ +#ifdef CC_SUPPORT_PVRTC CCTexture2D* CCTextureCache::addPVRTCImage(const char* path, int bpp, bool hasAlpha, int width) { - CCAssert(path != NULL, "TextureCache: fileimage MUST not be nill"); CCAssert( bpp==2 || bpp==4, "TextureCache: bpp must be either 2 or 4"); CCTexture2D * texture; + std::string temp(path); + CCFileUtils::ccRemoveHDSuffixFromFile(temp); + if ( (texture = m_pTextures->objectForKey(temp)) ) { return texture; @@ -288,8 +287,9 @@ CCTexture2D* CCTextureCache::addPVRTCImage(const char* path, int bpp, bool hasAl CCData * data = CCData::dataWithContentsOfFile(fullpath); texture = new CCTexture2D(); - texture->initWithPVRTCData(data->bytes(), 0, bpp, hasAlpha, width); - if( texture ) + + if( texture->initWithPVRTCData(data->bytes(), 0, bpp, hasAlpha, width, + (bpp==2 ? kCCTexture2DPixelFormat_PVRTC2 : kCCTexture2DPixelFormat_PVRTC4))) { m_pTextures->setObject(texture, temp); texture->autorelease(); @@ -302,33 +302,37 @@ CCTexture2D* CCTextureCache::addPVRTCImage(const char* path, int bpp, bool hasAl return texture; } +#endif // CC_SUPPORT_PVRTC -CCTexture2D * CCTextureCache::addPVRTCImage(const char* fileimage) +CCTexture2D * CCTextureCache::addPVRImage(const char* path) { - CCAssert(fileimage != NULL, "TextureCache: fileimage MUST not be nill"); + CCAssert(path != NULL, "TextureCache: fileimage MUST not be nill"); - CCTexture2D * texture; - std::string key(fileimage); - if( (texture = m_pTextures->objectForKey(key)) ) + CCTexture2D * tex; + std::string key(path); + // remove possible -HD suffix to prevent caching the same image twice (issue #1040) + CCFileUtils::ccRemoveHDSuffixFromFile(key); + + if( (tex = m_pTextures->objectForKey(key)) ) { - return texture; + return tex; } - texture = new CCTexture2D(); - texture = texture->initWithPVRTCFile(fileimage); - if( texture ) + // Split up directory and filename + std::string fullpath = CCFileUtils::fullPathFromRelativePath(key.c_str()); + tex = new CCTexture2D(); + if( tex->initWithPVRFile(fullpath.c_str()) ) { - m_pTextures-> setObject( texture, key); - texture->autorelease(); + m_pTextures->setObject(tex, key); + tex->autorelease(); } else { - CCLOG("cocos2d: Couldn't add PVRTCImage:%s in CCTextureCache",fileimage); + CCLOG("cocos2d: Couldn't add PVRImage:%s in CCTextureCache",key); } - return texture; + return tex; } -#endif /* @todo CGImageRef -(CCTexture2D*) addCGImage: (CGImageRef) imageref forKey: (string & )key @@ -450,63 +454,63 @@ void CCTextureCache::reloadAllTextures() #endif } -void CCTextureCache::dumpCachedTextureInfo() -{ - unsigned int count = 0; - unsigned int totalBytes = 0; - - vector keys = m_pTextures->allKeys(); - vector::iterator iter; - for (iter = keys.begin(); iter != keys.end(); iter++) - { - CCTexture2D *tex = m_pTextures->objectForKey(*iter); - unsigned int bpp = tex->bitsPerPixelForFormat(); - // Each texture takes up width * height * bytesPerPixel bytes. - unsigned int bytes = tex->getPixelsWide() * tex->getPixelsHigh() * bpp / 8; - totalBytes += bytes; - count++; - CCLOG("cocos2d: \"%s\" rc=%lu id=%lu %lu x %lu @ %ld bpp => %lu KB", - (*iter).c_str(), - (long)tex->retainCount(), - (long)tex->getName(), - (long)tex->getPixelsWide(), - (long)tex->getPixelsHigh(), - (long)bpp, - (long)bytes / 1024); - } - - CCLOG("cocos2d: CCTextureCache dumpDebugInfo: %ld textures, for %lu KB (%.2f MB)", (long)count, (long)totalBytes / 1024, totalBytes / (1024.0f*1024.0f)); +void CCTextureCache::dumpCachedTextureInfo() +{ + unsigned int count = 0; + unsigned int totalBytes = 0; + + vector keys = m_pTextures->allKeys(); + vector::iterator iter; + for (iter = keys.begin(); iter != keys.end(); iter++) + { + CCTexture2D *tex = m_pTextures->objectForKey(*iter); + unsigned int bpp = tex->bitsPerPixelForFormat(); + // Each texture takes up width * height * bytesPerPixel bytes. + unsigned int bytes = tex->getPixelsWide() * tex->getPixelsHigh() * bpp / 8; + totalBytes += bytes; + count++; + CCLOG("cocos2d: \"%s\" rc=%lu id=%lu %lu x %lu @ %ld bpp => %lu KB", + (*iter).c_str(), + (long)tex->retainCount(), + (long)tex->getName(), + (long)tex->getPixelsWide(), + (long)tex->getPixelsHigh(), + (long)bpp, + (long)bytes / 1024); + } + + CCLOG("cocos2d: CCTextureCache dumpDebugInfo: %ld textures, for %lu KB (%.2f MB)", (long)count, (long)totalBytes / 1024, totalBytes / (1024.0f*1024.0f)); } #if CC_ENABLE_CACHE_TEXTTURE_DATA -std::list VolatileTexture::textures; +std::list VolatileTexture::textures; bool VolatileTexture::isReloading = false; - -VolatileTexture::VolatileTexture(CCTexture2D *t) -: texture(t) -, m_bIsString(false) -, m_strFileName("") -, m_FmtImage(CCImage::kFmtPng) -, m_alignment(CCTextAlignmentCenter) -, m_strFontName("") -, m_strText("") -, m_fFontSize(0.0f) -{ - m_size = CCSizeMake(0, 0); - textures.push_back(this); -} - -VolatileTexture::~VolatileTexture() -{ - textures.remove(this); -} -void VolatileTexture::addImageTexture(CCTexture2D *tt, const char* imageFileName, CCImage::EImageFormat format) -{ +VolatileTexture::VolatileTexture(CCTexture2D *t) +: texture(t) +, m_bIsString(false) +, m_strFileName("") +, m_FmtImage(CCImage::kFmtPng) +, m_alignment(CCTextAlignmentCenter) +, m_strFontName("") +, m_strText("") +, m_fFontSize(0.0f) +{ + m_size = CCSizeMake(0, 0); + textures.push_back(this); +} + +VolatileTexture::~VolatileTexture() +{ + textures.remove(this); +} + +void VolatileTexture::addImageTexture(CCTexture2D *tt, const char* imageFileName, CCImage::EImageFormat format) +{ if (isReloading) - return; - + return; + VolatileTexture *vt = 0; std::list::iterator i = textures.begin(); while( i != textures.end() ) @@ -519,13 +523,13 @@ void VolatileTexture::addImageTexture(CCTexture2D *tt, const char* imageFileName } if (!vt) - vt = new VolatileTexture(tt); - - vt->m_bIsString = false; - vt->m_strFileName = imageFileName; - vt->m_FmtImage = format; -} - + vt = new VolatileTexture(tt); + + vt->m_bIsString = false; + vt->m_strFileName = imageFileName; + vt->m_FmtImage = format; +} + void VolatileTexture::addStringTexture(CCTexture2D *tt, const char* text, CCSize dimensions, CCTextAlignment alignment, const char *fontName, float fontSize) { if (isReloading) @@ -552,40 +556,40 @@ void VolatileTexture::addStringTexture(CCTexture2D *tt, const char* text, CCSize vt->m_fFontSize = fontSize; vt->m_strText = text; } - -void VolatileTexture::removeTexture(CCTexture2D *t) { - - std::list::iterator i = textures.begin(); - while( i != textures.end() ) - { - VolatileTexture *vt = *i++; - if (vt->texture == t) { - delete vt; - break; - } - } -} - -void VolatileTexture::reloadAllTextures() -{ - isReloading = true; - - CCLOG("reload all texture"); - std::list::iterator i = textures.begin(); - - while( i != textures.end() ) - { - VolatileTexture *vt = *i++; - if (vt->m_bIsString) - { - vt->texture->initWithString(vt->m_strText.c_str(), - vt->m_size, - vt->m_alignment, - vt->m_strFontName.c_str(), - vt->m_fFontSize); - } - else - { + +void VolatileTexture::removeTexture(CCTexture2D *t) { + + std::list::iterator i = textures.begin(); + while( i != textures.end() ) + { + VolatileTexture *vt = *i++; + if (vt->texture == t) { + delete vt; + break; + } + } +} + +void VolatileTexture::reloadAllTextures() +{ + isReloading = true; + + CCLOG("reload all texture"); + std::list::iterator i = textures.begin(); + + while( i != textures.end() ) + { + VolatileTexture *vt = *i++; + if (vt->m_bIsString) + { + vt->texture->initWithString(vt->m_strText.c_str(), + vt->m_size, + vt->m_alignment, + vt->m_strFontName.c_str(), + vt->m_fFontSize); + } + else + { CCImage image; CCFileData data(vt->m_strFileName.c_str(), "rb"); unsigned long nSize = data.getSize(); @@ -595,10 +599,10 @@ void VolatileTexture::reloadAllTextures() { vt->texture->initWithImage(&image); } - } - } - - isReloading = false; + } + } + + isReloading = false; } #endif // CC_ENABLE_CACHE_TEXTTURE_DATA diff --git a/cocos2dx/textures/CCTexturePVR.cpp b/cocos2dx/textures/CCTexturePVR.cpp new file mode 100755 index 0000000000..de77974840 --- /dev/null +++ b/cocos2dx/textures/CCTexturePVR.cpp @@ -0,0 +1,522 @@ +/**************************************************************************** +Copyright (c) 2011 Jirka Fajfr for cocos2d-x +Copyright (c) 2010-2011 cocos2d-x.org +Copyright (c) 2008 Apple Inc. All Rights Reserved. + +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. +****************************************************************************/ + +#include "CCTexture2D.h" +#include "CCTexturePVR.h" +#include "ccMacros.h" +#include "CCData.h" +#include "CCConfiguration.h" +#include "support/ccUtils.h" +#include "CCStdC.h" +#include "CCFileUtils.h" +#include "support/zip_support/ZipUtils.h" + +#include + +namespace cocos2d { + +/* + When define returns true it means that our architecture + uses big endiant + + NOTE: this should be placed somewhere in macros +*/ +#define CC_HOST_IS_BIG_ENDIAN (*(uint16_t *)"\0\xff" < 0x100) + +/* + Helper function which converts 4-byte little endian + integral number to the machine native number representation + + It should work same as apples CFSwapInt32LittleToHost(..) +*/ +static unsigned int CCSwapInt32LittleToHost(unsigned int i) +{ + /* + When architecture is big endian (ARM) reorder bytes + otherwise return same numbeer + */ + if (CC_HOST_IS_BIG_ENDIAN == true) + { + return ((i&0xff)<<24) + ((i&0xff00)<<8) + ((i&0xff0000)>>8) + ((i>>24)&0xff); + } + else + { + return i; + } +} + +#define PVR_TEXTURE_FLAG_TYPE_MASK 0xff +#define PVR_TEXTURE_FLAG_FLIPPED_MASK 0x10000 + +// Values taken from PVRTexture.h from http://www.imgtec.com +enum { + kPVRTextureFlagMipmap = (1<<8), // has mip map levels + kPVRTextureFlagTwiddle = (1<<9), // is twiddled + kPVRTextureFlagBumpmap = (1<<10), // has normals encoded for a bump map + kPVRTextureFlagTiling = (1<<11), // is bordered for tiled pvr + kPVRTextureFlagCubemap = (1<<12), // is a cubemap/skybox + kPVRTextureFlagFalseMipCol = (1<<13), // are there false coloured MIP levels + kPVRTextureFlagVolume = (1<<14), // is this a volume texture + kPVRTextureFlagAlpha = (1<<15), // v2.1 is there transparency info in the texture + kPVRTextureFlagVerticalFlip = (1<<16), // v2.1 is the texture vertically flipped +}; + +/* + PVR header contains special field called PVRTag. This tag + is used only to determine that passed file is really pvrt. + + Its set of 4 numbers. Each number casted to the char + must correspond to the "PVR!" string +*/ +static unsigned int gPVRTexIdentifier[] = { 'P', 'V', 'R', '!'}; + +/* + List of formats in pvr container +*/ +enum +{ + kPVRTextureFlagTypeRGBA_4444= 0x10, + kPVRTextureFlagTypeRGBA_5551, + kPVRTextureFlagTypeRGBA_8888, + kPVRTextureFlagTypeRGB_565, + kPVRTextureFlagTypeRGB_555, // unsupported + kPVRTextureFlagTypeRGB_888, // unsupported + kPVRTextureFlagTypeI_8, + kPVRTextureFlagTypeAI_88, + kPVRTextureFlagTypePVRTC_2, + kPVRTextureFlagTypePVRTC_4, + kPVRTextureFlagTypeBGRA_8888, + kPVRTextureFlagTypeA_8, +}; + +/* + Helps us to convert pvr format to the gl compatible bitspaces + + WARNING!! OpenGL ES 1.1. does not support GL_BGRA format. Its PowerVR + extension and it will work only on PowerVR chipsets. It means that + + kPVRTextureFlagTypeBGRA_8888 can be used only on apple devices (or PowerVR compatible) +*/ +static const unsigned int tableFormats[][7] = { + + // - PVR texture format + // - OpenGL internal format + // - OpenGL format + // - OpenGL type + // - bpp + // - compressed + // - Cocos2d texture format constant + { kPVRTextureFlagTypeRGBA_4444, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 16, false, kCCTexture2DPixelFormat_RGBA4444 }, + { kPVRTextureFlagTypeRGBA_5551, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 16, false, kCCTexture2DPixelFormat_RGB5A1 }, + { kPVRTextureFlagTypeRGBA_8888, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 32, false, kCCTexture2DPixelFormat_RGBA8888 }, + { kPVRTextureFlagTypeRGB_565, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 16, false, kCCTexture2DPixelFormat_RGB565 }, + { kPVRTextureFlagTypeA_8, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, 8, false, kCCTexture2DPixelFormat_A8 }, + { kPVRTextureFlagTypeI_8, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 8, false, kCCTexture2DPixelFormat_I8 }, + { kPVRTextureFlagTypeAI_88, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 16, false, kCCTexture2DPixelFormat_AI88 }, +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + { kPVRTextureFlagTypePVRTC_2, GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, -1, -1, 2, true, kCCTexture2DPixelFormat_PVRTC2 }, + { kPVRTextureFlagTypePVRTC_4, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, -1, -1, 4, true, kCCTexture2DPixelFormat_PVRTC4 }, + { kPVRTextureFlagTypeBGRA_8888, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE, 32, false, kCCTexture2DPixelFormat_RGBA8888 }, +#endif +}; + +//Tells How large is tableFormats +#define MAX_TABLE_ELEMENTS (sizeof(tableFormats) / sizeof(tableFormats[0])) + +/* + Helper enum to traverse tableFormats +*/ +enum { + kCCInternalPVRTextureFormat, + kCCInternalOpenGLInternalFormat, + kCCInternalOpenGLFormat, + kCCInternalOpenGLType, + kCCInternalBPP, + kCCInternalCompressedImage, + kCCInternalCCTexture2DPixelFormat, +}; + +/* + Official PVRT header +*/ +typedef struct _PVRTexHeader +{ + unsigned int headerLength; + unsigned int height; + unsigned int width; + unsigned int numMipmaps; + unsigned int flags; + unsigned int dataLength; + unsigned int bpp; + unsigned int bitmaskRed; + unsigned int bitmaskGreen; + unsigned int bitmaskBlue; + unsigned int bitmaskAlpha; + unsigned int pvrTag; + unsigned int numSurfs; +} PVRTexHeader; + +CCTexturePVR::CCTexturePVR() : + m_uTableFormatIndex(0), + m_uNumberOfMipmaps(0) +{ +} + +CCTexturePVR::~CCTexturePVR() +{ + CCLOGINFO( "cocos2d: deallocing CCTexturePVR" ); + + if (m_uName != 0 && ! m_bRetainName ) + glDeleteTextures(1, &m_uName); +} + +GLuint CCTexturePVR::getName() +{ + return m_uName; +} + +unsigned int CCTexturePVR::getWidth() +{ + return m_uWidth; +} + +unsigned int CCTexturePVR::getHeight() +{ + return m_uHeight; +} + +CCTexture2DPixelFormat CCTexturePVR::getFormat() +{ + return m_eFormat; +} + +bool CCTexturePVR::getHasAlpha() +{ + return m_bHasAlpha; +} + +bool CCTexturePVR::getRetainName() +{ + return m_bRetainName; +} + +void CCTexturePVR::setRetainName(bool var) +{ + m_bRetainName = var; +} + +bool CCTexturePVR::unpackPVRData(unsigned char* data, unsigned int len) +{ + bool success = false; + PVRTexHeader *header = NULL; + unsigned int flags, pvrTag; + unsigned int dataLength = 0, dataOffset = 0, dataSize = 0; + unsigned int blockSize = 0, widthBlocks = 0, heightBlocks = 0; + unsigned int width = 0, height = 0, bpp = 4; + uint8_t *bytes = NULL; + unsigned int formatFlags; + + //Cast first sizeof(PVRTexHeader) bytes of data stream as PVRTexHeader + header = (PVRTexHeader *)data; + + //Make sure that tag is in correct formatting + pvrTag = CCSwapInt32LittleToHost(header->pvrTag); + + /* + Check that given data really represents pvrtexture + + [0] = 'P' + [1] = 'V' + [2] = 'R' + [3] = '!' + */ + if (gPVRTexIdentifier[0] != ((pvrTag >> 0) & 0xff) || + gPVRTexIdentifier[1] != ((pvrTag >> 8) & 0xff) || + gPVRTexIdentifier[2] != ((pvrTag >> 16) & 0xff) || + gPVRTexIdentifier[3] != ((pvrTag >> 24) & 0xff)) + { + return false; + } + + CCConfiguration *configuration = CCConfiguration::sharedConfiguration(); + + //Get file flags (in correct byte order) + flags = CCSwapInt32LittleToHost(header->flags); + + //Trim to only bites which are needed. Resulting flag is image format + formatFlags = flags & PVR_TEXTURE_FLAG_TYPE_MASK; + + /* + When flags combined with flipped mask is not empty (zero). + It means that image is compressed as flipped. We don't + support automatic flipping. + */ + bool flipped = flags & kPVRTextureFlagVerticalFlip; + if ( flipped ) + { + CCLOG("cocos2d: WARNING: Image is flipped. Regenerate it using PVRTexTool"); + } + + if ( ! configuration->isSupportsNPOT() && + (header->width != ccNextPOT(header->width) || header->height != ccNextPOT(header->height))) + { + CCLOG("cocos2d: ERROR: Loding an NPOT texture (%dx%d) but is not supported on this device", header->width, header->height); + return false; + } + + //Check that sides of texture are power of two + if(header->width != ccNextPOT(header->width) || header->height != ccNextPOT(header->height)) + { + CCLOG("cocos2d: WARNING: PVR NPOT textures are not supported. Regenerate it."); + return false; + } + + //Go thru format array + for (m_uTableFormatIndex = 0; m_uTableFormatIndex < (unsigned int)MAX_TABLE_ELEMENTS; m_uTableFormatIndex++) + { + //Does image format in table fits to the one parsed from header? + if (tableFormats[m_uTableFormatIndex][kCCInternalPVRTextureFormat] == formatFlags) + { + //Reset num of mipmaps + m_uNumberOfMipmaps = 0; + + //Get size of maimap + m_uWidth = width = CCSwapInt32LittleToHost(header->width); + m_uHeight = height = CCSwapInt32LittleToHost(header->height); + + //Do we use alpha ? + if (CCSwapInt32LittleToHost(header->bitmaskAlpha)) + m_bHasAlpha = true; + else + m_bHasAlpha = false; + + //Get ptr to where data starts.. + dataLength = CCSwapInt32LittleToHost(header->dataLength); + + //Move by size of header + bytes = ((unsigned char *)data) + sizeof(PVRTexHeader); + m_eFormat = (CCTexture2DPixelFormat)( tableFormats[m_uTableFormatIndex][kCCInternalCCTexture2DPixelFormat] ); + bpp = tableFormats[m_uTableFormatIndex][kCCInternalBPP]; + + // Calculate the data size for each texture level and respect the minimum number of blocks + while (dataOffset < dataLength) + { + switch (formatFlags) { + case kPVRTextureFlagTypePVRTC_2: + blockSize = 8 * 4; // Pixel by pixel block size for 2bpp + widthBlocks = width / 8; + heightBlocks = height / 4; + bpp = 2; + break; + case kPVRTextureFlagTypePVRTC_4: + blockSize = 4 * 4; // Pixel by pixel block size for 4bpp + widthBlocks = width / 4; + heightBlocks = height / 4; + bpp = 4; + break; + case kPVRTextureFlagTypeBGRA_8888: + if (CCConfiguration::sharedConfiguration()->isSupportsBGRA8888() == false) + { + CCLOG("cocos2d: TexturePVR. BGRA8888 not supported on this device"); + return false; + } + default: + blockSize = 1; + widthBlocks = width; + heightBlocks = height; + bpp = tableFormats[m_uTableFormatIndex][kCCInternalBPP]; + break; + } + + // Clamp to minimum number of blocks + if (widthBlocks < 2) + widthBlocks = 2; + if (heightBlocks < 2) + heightBlocks = 2; + + dataSize = widthBlocks * heightBlocks * ((blockSize * bpp) / 8); + float packetLength = (dataLength-dataOffset); + packetLength = packetLength > dataSize ? dataSize : packetLength; + + //Make record to the mipmaps array and increment coutner + m_asMipmaps[m_uNumberOfMipmaps].address = bytes+dataOffset; + m_asMipmaps[m_uNumberOfMipmaps].len = packetLength; + m_uNumberOfMipmaps++; + + //Check that we didn't overflow + CCAssert(m_uNumberOfMipmaps < CC_PVRMIPMAP_MAX, + "TexturePVR: Maximum number of mimpaps reached. Increate the CC_PVRMIPMAP_MAX value"); + + dataOffset += packetLength; + + //Update width and height to the next lower power of two + width = MAX(width >> 1, 1); + height = MAX(height >> 1, 1); + } + + //Mark pass as success + success = true; + break; + } + } + + if (false == success) + { + CCLOG("cocos2d: WARNING: Unssupported PVR Pixel Format: 0x%2x", formatFlags); + } + + return success; +} + +bool CCTexturePVR::createGLTexture() +{ + unsigned int width = m_uWidth; + unsigned int height = m_uHeight; + GLenum err; + + if (m_uNumberOfMipmaps > 0) + { + if (m_uName != 0) + { + glDeleteTextures(1, &m_uName); + } + + glGenTextures(1, &m_uName); + glBindTexture(GL_TEXTURE_2D, m_uName); + } + + // Generate textures with mipmaps + for (unsigned int i = 0; i < m_uNumberOfMipmaps; ++i) + { + GLenum internalFormat = tableFormats[m_uTableFormatIndex][kCCInternalOpenGLInternalFormat]; + GLenum format = tableFormats[m_uTableFormatIndex][kCCInternalOpenGLFormat]; + GLenum type = tableFormats[m_uTableFormatIndex][kCCInternalOpenGLType]; + bool compressed = tableFormats[m_uTableFormatIndex][kCCInternalCompressedImage] == 1; + + if (compressed == true && CCConfiguration::sharedConfiguration()->isSupportsPVRTC() == false) + { + CCLOG("cocos2d: WARNING: PVRTC images are not supported"); + return false; + } + + unsigned char *data = m_asMipmaps[i].address; + unsigned int datalen = m_asMipmaps[i].len; + + if (compressed == true) + { + glCompressedTexImage2D(GL_TEXTURE_2D, i, internalFormat, width, height, 0, datalen, data); + } + else + { + glTexImage2D(GL_TEXTURE_2D, i, internalFormat, width, height, 0, format, type, data); + } + + if(i > 0 && (width != height || ccNextPOT(width) != width ) ) + { + CCLOG("cocos2d: TexturePVR. WARNING. Mipmap level %lu is not squared. Texture won't render correctly. width=%lu != height=%lu", i, width, height); + } + + err = glGetError(); + if (err != GL_NO_ERROR) + { + CCLOG("cocos2d: TexturePVR: Error uploading compressed texture level: %u . glError: 0x%04X", (unsigned int)i, err); + return false; + } + + //Update width and height to the next lower power of two + width = MAX(width >> 1, 1); + height = MAX(height >> 1, 1); + } + + return true; +} + + +bool CCTexturePVR::initWithContentsOfFile(const char* path) +{ + unsigned char* pvrdata = NULL; + int pvrlen = 0; + + std::string lowerCase(path); + for (unsigned int i = 0; i < lowerCase.length(); ++i) + { + lowerCase[i] = tolower(lowerCase[i]); + } + + if (lowerCase.find(".ccz") != -1) + { + pvrlen = ZipUtils::ccInflateCCZFile(path, &pvrdata); + } + else if (lowerCase.find(".gz") != -1) + { + pvrlen = ZipUtils::ccInflateGZipFile(path, &pvrdata); + } + else + { + pvrlen = CCFileUtils::ccLoadFileIntoMemory(path, &pvrdata); + } + + if (pvrlen < 0) + { + this->release(); + return false; + } + + m_uNumberOfMipmaps = 0; + + m_uName = 0; + m_uWidth = m_uHeight = 0; + m_bHasAlpha = false; + + m_bRetainName = false; // cocos2d integration + + if ( !unpackPVRData(pvrdata, pvrlen) || !createGLTexture() ) + { + free(pvrdata); + this->release(); + return false; + } + + free(pvrdata); + + return true; +} + +CCTexturePVR * CCTexturePVR::pvrTextureWithContentsOfFile(const char* path) +{ + CCTexturePVR * pTexture = new CCTexturePVR(); + if(true == pTexture->initWithContentsOfFile(path)) + { + pTexture->autorelease(); + return pTexture; + } + else + { + return NULL; + } +} + +}//namespace cocos2d diff --git a/tests/test.ios/test.xcodeproj/project.pbxproj.REMOVED.git-id b/tests/test.ios/test.xcodeproj/project.pbxproj.REMOVED.git-id index 73b1a72646..e4b8848517 100644 --- a/tests/test.ios/test.xcodeproj/project.pbxproj.REMOVED.git-id +++ b/tests/test.ios/test.xcodeproj/project.pbxproj.REMOVED.git-id @@ -1 +1 @@ -c129ba52ba1803a75b0f1b1b7a6d95092a8b67b5 \ No newline at end of file +ee629ad852ffaadaaf47f1d39c96f7daf670f9be \ No newline at end of file