issue #536, integrate the CCTexturePVR to project, update from 0.99.5 to 1.0.0, compile successfully on ios & android. Haven't test on other platforms yet.

This commit is contained in:
Walzer 2011-07-19 15:14:59 +08:00
parent 0817d59edf
commit bc44855091
14 changed files with 891 additions and 582 deletions

View File

@ -88,7 +88,8 @@ text_input_node/CCIMEDispatcher.cpp \
text_input_node/CCTextFieldTTF.cpp \ text_input_node/CCTextFieldTTF.cpp \
textures/CCTexture2D.cpp \ textures/CCTexture2D.cpp \
textures/CCTextureAtlas.cpp \ textures/CCTextureAtlas.cpp \
textures/CCTextureCache.cpp \ textures/CCTextureCache.cpp \
textures/CCTexturePVR.cpp \
tileMap_parallax_nodes/CCParallaxNode.cpp \ tileMap_parallax_nodes/CCParallaxNode.cpp \
tileMap_parallax_nodes/CCTMXLayer.cpp \ tileMap_parallax_nodes/CCTMXLayer.cpp \
tileMap_parallax_nodes/CCTMXObjectGroup.cpp \ tileMap_parallax_nodes/CCTMXObjectGroup.cpp \

View File

@ -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 <string>
#include <GLES/gl.h>
#include <GLES/glext.h>
#include "CCObject.h"
#include "CCMutableArray.h"
namespace cocos2d {
class CCData;
class CCPVRTexture : public CCObject
{
protected:
CCMutableArray<CCData*> * 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

View File

@ -49,17 +49,17 @@ typedef enum {
kCCTexture2DPixelFormat_RGB565, kCCTexture2DPixelFormat_RGB565,
//! 8-bit textures used as masks //! 8-bit textures used as masks
kCCTexture2DPixelFormat_A8, kCCTexture2DPixelFormat_A8,
//! 8-bit intensity texture //! 8-bit intensity texture
kCCTexture2DPixelFormat_I8, kCCTexture2DPixelFormat_I8,
//! 16-bit textures used as masks //! 16-bit textures used as masks
kCCTexture2DPixelFormat_AI88, kCCTexture2DPixelFormat_AI88,
//! 16-bit textures: RGBA4444 //! 16-bit textures: RGBA4444
kCCTexture2DPixelFormat_RGBA4444, kCCTexture2DPixelFormat_RGBA4444,
//! 16-bit textures: RGB5A1 //! 16-bit textures: RGB5A1
kCCTexture2DPixelFormat_RGB5A1, kCCTexture2DPixelFormat_RGB5A1,
//! 4-bit PVRTC-compressed texture: PVRTC4 //! 4-bit PVRTC-compressed texture: PVRTC4
kCCTexture2DPixelFormat_PVRTC4, kCCTexture2DPixelFormat_PVRTC4,
//! 2-bit PVRTC-compressed texture: PVRTC2 //! 2-bit PVRTC-compressed texture: PVRTC2
kCCTexture2DPixelFormat_PVRTC2, kCCTexture2DPixelFormat_PVRTC2,
//! Default texture format: RGBA8888 //! Default texture format: RGBA8888
@ -157,16 +157,17 @@ public:
/** returns the content size of the texture in points */ /** returns the content size of the texture in points */
CCSize getContentSize(void); CCSize getContentSize(void);
#ifdef _POWERVR_SUPPORT_ #ifdef CC_SUPPORT_PVRTC
/** /**
Extensions to make it easy to create a CCTexture2D object from a PVRTC file 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). 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 */ /** Initializes a texture from a PVRTC buffer */
bool initWithPVRTCData(const void* data, int level, int bpp, bool hasAlpha, int length); bool initWithPVRTCData(const void *data, int level, int bpp, bool hasAlpha, int length, CCTexture2DPixelFormat pixelFormat);
/** Initializes a texture from a PVRTC file */ #endif // CC_SUPPORT_PVRTC
bool initWithPVRTCFile(const char* file);
#endif /** 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. /** 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}. 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(); void generateMipmap();
/** returns the bits-per-pixel of the in-memory OpenGL texture /** returns the bits-per-pixel of the in-memory OpenGL texture
@since v1.0 @since v1.0
*/ */
unsigned int bitsPerPixelForFormat(); unsigned int bitsPerPixelForFormat();
void setPVRImagesHavePremultipliedAlpha(bool haveAlphaPremultiplied);
/** sets the default pixel format for UIImages that contains alpha channel. /** sets the default pixel format for UIImages that contains alpha channel.
If the UIImage contains alpha channel, then the options are: If the UIImage contains alpha channel, then the options are:
- generate 32-bit textures: kCCTexture2DPixelFormat_RGBA8888 (default one) - generate 32-bit textures: kCCTexture2DPixelFormat_RGBA8888 (default one)
@ -227,6 +230,9 @@ public:
private: private:
bool initPremultipliedATextureWithImage(CCImage * image, unsigned int pixelsWide, unsigned int pixelsHigh); 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 }//namespace cocos2d

View File

@ -135,14 +135,14 @@ public:
*/ */
void removeTextureForKey(const char *textureKeyName); void removeTextureForKey(const char *textureKeyName);
/** Output to CCLOG the current contents of this CCTextureCache /** 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 * This will attempt to calculate the size of each texture, and the total texture memory in use
* *
* @since v1.0 * @since v1.0
*/ */
void dumpCachedTextureInfo(); void dumpCachedTextureInfo();
#if _POWERVR_SUPPORT_ #ifdef CC_SUPPORT_PVRTC
/** Returns a Texture2D object given an PVRTC RAW filename /** Returns a Texture2D object given an PVRTC RAW filename
* If the file image was not previously loaded, it will create a new CCTexture2D * 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 * 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 * hasAlpha: whether or not the image contains alpha channel
*/ */
CCTexture2D* addPVRTCImage(const char* fileimage, int bpp, bool hasAlpha, int width); CCTexture2D* addPVRTCImage(const char* fileimage, int bpp, bool hasAlpha, int width);
#endif // CC_SUPPORT_PVRTC
/** Returns a Texture2D object given an PVRTC filename
/** Returns a Texture2D object given an PVR filename
* If the file image was not previously loaded, it will create a new CCTexture2D * 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 * object and it will return it. Otherwise it will return a reference of a previosly loaded image
*/ */
CCTexture2D* addPVRTCImage(const char* fileimage); CCTexture2D* addPVRImage(const char* filename);
#endif
/** Reload all textures /** Reload all textures
It's only useful when the value of CC_ENABLE_CACHE_TEXTTURE_DATA is 1 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 #if CC_ENABLE_CACHE_TEXTTURE_DATA
class VolatileTexture class VolatileTexture
{ {
public: public:
VolatileTexture(CCTexture2D *t); VolatileTexture(CCTexture2D *t);
~VolatileTexture(); ~VolatileTexture();
static void addImageTexture(CCTexture2D *tt, const char* imageFileName, CCImage::EImageFormat format); 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 addStringTexture(CCTexture2D *tt, const char* text, CCSize dimensions, CCTextAlignment alignment, const char *fontName, float fontSize);
static void removeTexture(CCTexture2D *t); static void removeTexture(CCTexture2D *t);
static void reloadAllTextures(); static void reloadAllTextures();
public: public:
static std::list<VolatileTexture*> textures; static std::list<VolatileTexture*> textures;
static bool isReloading; static bool isReloading;
protected: protected:
CCTexture2D *texture; CCTexture2D *texture;
bool m_bIsString; bool m_bIsString;

139
cocos2dx/include/CCTexturePVR.h Executable file
View File

@ -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 <string>
#include <stdint.h>
#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__

View File

@ -77,17 +77,17 @@ THE SOFTWARE.
#include "CCActionPageTurn3D.h" #include "CCActionPageTurn3D.h"
#include "CCTransitionPageTurn.h" #include "CCTransitionPageTurn.h"
#include "CCTexture2D.h" #include "CCTexture2D.h"
#include "CCPVRTexture.h" #include "CCTexturePVR.h"
#include "CCTransitionRadial.h" #include "CCTransitionRadial.h"
#include "CCActionProgressTimer.h" #include "CCActionProgressTimer.h"
#include "CCTouchDispatcher.h" #include "CCTouchDispatcher.h"
#include "CCDrawingPrimitives.h" #include "CCDrawingPrimitives.h"
#include "CCScheduler.h" #include "CCScheduler.h"
// havn't implement on wophone and airplay // havn't implement on wophone and airplay
#if (CC_TARGET_PLATFORM != CC_PLATFORM_AIRPLAY) #if (CC_TARGET_PLATFORM != CC_PLATFORM_AIRPLAY)
#include "CCTextFieldTTF.h" #include "CCTextFieldTTF.h"
#endif #endif
// //
// cocoa includes // cocoa includes

View File

@ -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 @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 @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. @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 @brief Get resource file data from zip file
@param[in] pszFileName The resource file name which contain the relative path of 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 @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. @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); static unsigned char* getFileDataFromZip(const char* pszZipFilePath, const char* pszFileName, unsigned long * pSize);
/** removes the HD suffix from a path /** removes the HD suffix from a path
@returns const char * without the HD suffix @returns const char * without the HD suffix
@since v0.99.5 @since v0.99.5
*/ */
static std::string& ccRemoveHDSuffixFromFile(std::string& path); static std::string& ccRemoveHDSuffixFromFile(std::string& path);
/** /**
@ -116,7 +116,7 @@ public:
/////////////////////////////////////////////////// ///////////////////////////////////////////////////
// interfaces on ios // interfaces on ios
/////////////////////////////////////////////////// ///////////////////////////////////////////////////
int ccLoadFileIntoMemory(const char *filename, unsigned char **out); static int ccLoadFileIntoMemory(const char *filename, unsigned char **out);
}; };
class CCFileData class CCFileData

View File

@ -54,6 +54,7 @@ There are config below:
#define CC_TARGET_PLATFORM CC_PLATFORM_IOS #define CC_TARGET_PLATFORM CC_PLATFORM_IOS
#define CC_SUPPORT_MULTITHREAD 0 #define CC_SUPPORT_MULTITHREAD 0
#define CC_SUPPORT_UNICODE 0 #define CC_SUPPORT_UNICODE 0
#define CC_SUPPORT_PVRTC
#endif #endif
// android // android

View File

@ -256,7 +256,7 @@ namespace cocos2d {
int CCFileUtils::ccLoadFileIntoMemory(const char *filename, unsigned char **out) 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"); CCAssert( &*out, "ccLoadFileIntoMemory: invalid 'out' parameter");
size_t size = 0; size_t size = 0;
FILE *f = fopen(filename, "rb"); FILE *f = fopen(filename, "rb");

View File

@ -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<CCData*>(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

View File

@ -40,10 +40,7 @@ THE SOFTWARE.
#include "CCGL.h" #include "CCGL.h"
#include "support/ccUtils.h" #include "support/ccUtils.h"
#include "platform/CCPlatformMacros.h" #include "platform/CCPlatformMacros.h"
#include "CCTexturePVR.h"
#ifdef _POWERVR_SUPPORT_
#include "CCPVRTexture.h"
#endif
#if CC_ENABLE_CACHE_TEXTTURE_DATA #if CC_ENABLE_CACHE_TEXTTURE_DATA
#include "CCTextureCache.h" #include "CCTextureCache.h"
@ -68,6 +65,7 @@ CCTexture2D::CCTexture2D()
, m_fMaxS(0.0) , m_fMaxS(0.0)
, m_fMaxT(0.0) , m_fMaxT(0.0)
, m_bHasPremultipliedAlpha(false) , m_bHasPremultipliedAlpha(false)
, m_bPVRHaveAlphaPremultiplied(true)
{ {
} }
@ -506,12 +504,11 @@ void CCTexture2D::drawInRect(CCRect rect)
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
} }
#ifdef CC_SUPPORT_PVRTC
// implementation CCTexture2D (PVRTC) // implementation CCTexture2D (PVRTC);
#ifdef _POWERVR_SUPPORT_ bool CCTexture2D::initWithPVRTCData(const void *data, int level, int bpp, bool hasAlpha, int length, CCTexture2DPixelFormat pixelFormat)
bool CCTexture2D::initWithPVRTCData(const void *data, int level, int bpp, bool hasAlpha, int length)
{ {
if( !(CCPlatformConfiguration::sharedConfiguration()->isSupportsPVRTC()) ) if( !(CCConfiguration::sharedConfiguration()->isSupportsPVRTC()) )
{ {
CCLOG("cocos2d: WARNING: PVRTC images is not supported."); CCLOG("cocos2d: WARNING: PVRTC images is not supported.");
this->release(); this->release();
@ -540,47 +537,53 @@ bool CCTexture2D::initWithPVRTCData(const void *data, int level, int bpp, bool h
m_uPixelsHigh = length; m_uPixelsHigh = length;
m_fMaxS = 1.0f; m_fMaxS = 1.0f;
m_fMaxT = 1.0f; m_fMaxT = 1.0f;
m_bHasPremultipliedAlpha = m_bPVRHaveAlphaPremultiplied;
m_ePixelFormat = pixelFormat;
return true; return true;
} }
#endif // CC_SUPPORT_PVRTC
CCTexture2D * CCTexture2D::initWithPVRTCFile(const char* file) bool CCTexture2D::initWithPVRFile(const char* file)
{ {
if (! CCPlatformConfiguration::sharedConfiguration()->isSupportsPVRTC()) bool bRet = false;
{ // nothing to do with CCObject::init
CCLOG("cocos2d: WARNING: PVRTC images is not supported");
this->release(); CCTexturePVR *pvr = new CCTexturePVR;
return false; 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(); return bRet;
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;
} }
#endif
void CCTexture2D::setPVRImagesHavePremultipliedAlpha(bool haveAlphaPremultiplied)
{
m_bPVRHaveAlphaPremultiplied = haveAlphaPremultiplied;
}
// //
// Use to apply MIN/MAG filter // Use to apply MIN/MAG filter
// //

View File

@ -197,14 +197,11 @@ CCTexture2D * CCTextureCache::addImage(const char * path)
lowerCase[i] = tolower(lowerCase[i]); lowerCase[i] = tolower(lowerCase[i]);
} }
// all images are handled by UIImage except PVR extension that is handled by our own handler // all images are handled by UIImage except PVR extension that is handled by our own handler
// if ( [[path lowercaseString] hasSuffix:@".pvr"] )
do do
{ {
if (std::string::npos != lowerCase.find(".pvr")) if (std::string::npos != lowerCase.find(".pvr"))
{ {
#ifdef _POWERVR_SUPPORT_ texture = this->addPVRImage(fullpath.c_str());
texture = this->addPVRTCImage(fullpath.c_str());
#endif
} }
// Issue #886: TEMPORARY FIX FOR TRANSPARENT JPEGS IN IOS4 // Issue #886: TEMPORARY FIX FOR TRANSPARENT JPEGS IN IOS4
else if (std::string::npos != lowerCase.find(".jpg") || std::string::npos != lowerCase.find(".jpeg")) 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; return texture;
} }
#ifdef _POWERVR_SUPPORT_ #ifdef CC_SUPPORT_PVRTC
CCTexture2D* CCTextureCache::addPVRTCImage(const char* path, int bpp, bool hasAlpha, int width) CCTexture2D* CCTextureCache::addPVRTCImage(const char* path, int bpp, bool hasAlpha, int width)
{ {
CCAssert(path != NULL, "TextureCache: fileimage MUST not be nill"); CCAssert(path != NULL, "TextureCache: fileimage MUST not be nill");
CCAssert( bpp==2 || bpp==4, "TextureCache: bpp must be either 2 or 4"); CCAssert( bpp==2 || bpp==4, "TextureCache: bpp must be either 2 or 4");
CCTexture2D * texture; CCTexture2D * texture;
std::string temp(path); std::string temp(path);
CCFileUtils::ccRemoveHDSuffixFromFile(temp);
if ( (texture = m_pTextures->objectForKey(temp)) ) if ( (texture = m_pTextures->objectForKey(temp)) )
{ {
return texture; return texture;
@ -288,8 +287,9 @@ CCTexture2D* CCTextureCache::addPVRTCImage(const char* path, int bpp, bool hasAl
CCData * data = CCData::dataWithContentsOfFile(fullpath); CCData * data = CCData::dataWithContentsOfFile(fullpath);
texture = new CCTexture2D(); 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); m_pTextures->setObject(texture, temp);
texture->autorelease(); texture->autorelease();
@ -302,33 +302,37 @@ CCTexture2D* CCTextureCache::addPVRTCImage(const char* path, int bpp, bool hasAl
return texture; 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; CCTexture2D * tex;
std::string key(fileimage); std::string key(path);
if( (texture = m_pTextures->objectForKey(key)) ) // 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(); // Split up directory and filename
texture = texture->initWithPVRTCFile(fileimage); std::string fullpath = CCFileUtils::fullPathFromRelativePath(key.c_str());
if( texture ) tex = new CCTexture2D();
if( tex->initWithPVRFile(fullpath.c_str()) )
{ {
m_pTextures-> setObject( texture, key); m_pTextures->setObject(tex, key);
texture->autorelease(); tex->autorelease();
} }
else 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 /* @todo CGImageRef
-(CCTexture2D*) addCGImage: (CGImageRef) imageref forKey: (string & )key -(CCTexture2D*) addCGImage: (CGImageRef) imageref forKey: (string & )key
@ -450,63 +454,63 @@ void CCTextureCache::reloadAllTextures()
#endif #endif
} }
void CCTextureCache::dumpCachedTextureInfo() void CCTextureCache::dumpCachedTextureInfo()
{ {
unsigned int count = 0; unsigned int count = 0;
unsigned int totalBytes = 0; unsigned int totalBytes = 0;
vector<string> keys = m_pTextures->allKeys(); vector<string> keys = m_pTextures->allKeys();
vector<string>::iterator iter; vector<string>::iterator iter;
for (iter = keys.begin(); iter != keys.end(); iter++) for (iter = keys.begin(); iter != keys.end(); iter++)
{ {
CCTexture2D *tex = m_pTextures->objectForKey(*iter); CCTexture2D *tex = m_pTextures->objectForKey(*iter);
unsigned int bpp = tex->bitsPerPixelForFormat(); unsigned int bpp = tex->bitsPerPixelForFormat();
// Each texture takes up width * height * bytesPerPixel bytes. // Each texture takes up width * height * bytesPerPixel bytes.
unsigned int bytes = tex->getPixelsWide() * tex->getPixelsHigh() * bpp / 8; unsigned int bytes = tex->getPixelsWide() * tex->getPixelsHigh() * bpp / 8;
totalBytes += bytes; totalBytes += bytes;
count++; count++;
CCLOG("cocos2d: \"%s\" rc=%lu id=%lu %lu x %lu @ %ld bpp => %lu KB", CCLOG("cocos2d: \"%s\" rc=%lu id=%lu %lu x %lu @ %ld bpp => %lu KB",
(*iter).c_str(), (*iter).c_str(),
(long)tex->retainCount(), (long)tex->retainCount(),
(long)tex->getName(), (long)tex->getName(),
(long)tex->getPixelsWide(), (long)tex->getPixelsWide(),
(long)tex->getPixelsHigh(), (long)tex->getPixelsHigh(),
(long)bpp, (long)bpp,
(long)bytes / 1024); (long)bytes / 1024);
} }
CCLOG("cocos2d: CCTextureCache dumpDebugInfo: %ld textures, for %lu KB (%.2f MB)", (long)count, (long)totalBytes / 1024, totalBytes / (1024.0f*1024.0f)); 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 #if CC_ENABLE_CACHE_TEXTTURE_DATA
std::list<VolatileTexture*> VolatileTexture::textures; std::list<VolatileTexture*> VolatileTexture::textures;
bool VolatileTexture::isReloading = false; 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) if (isReloading)
return; return;
VolatileTexture *vt = 0; VolatileTexture *vt = 0;
std::list<VolatileTexture *>::iterator i = textures.begin(); std::list<VolatileTexture *>::iterator i = textures.begin();
while( i != textures.end() ) while( i != textures.end() )
@ -519,13 +523,13 @@ void VolatileTexture::addImageTexture(CCTexture2D *tt, const char* imageFileName
} }
if (!vt) if (!vt)
vt = new VolatileTexture(tt); vt = new VolatileTexture(tt);
vt->m_bIsString = false; vt->m_bIsString = false;
vt->m_strFileName = imageFileName; vt->m_strFileName = imageFileName;
vt->m_FmtImage = format; vt->m_FmtImage = format;
} }
void VolatileTexture::addStringTexture(CCTexture2D *tt, const char* text, CCSize dimensions, CCTextAlignment alignment, const char *fontName, float fontSize) void VolatileTexture::addStringTexture(CCTexture2D *tt, const char* text, CCSize dimensions, CCTextAlignment alignment, const char *fontName, float fontSize)
{ {
if (isReloading) if (isReloading)
@ -552,40 +556,40 @@ void VolatileTexture::addStringTexture(CCTexture2D *tt, const char* text, CCSize
vt->m_fFontSize = fontSize; vt->m_fFontSize = fontSize;
vt->m_strText = text; vt->m_strText = text;
} }
void VolatileTexture::removeTexture(CCTexture2D *t) { void VolatileTexture::removeTexture(CCTexture2D *t) {
std::list<VolatileTexture *>::iterator i = textures.begin(); std::list<VolatileTexture *>::iterator i = textures.begin();
while( i != textures.end() ) while( i != textures.end() )
{ {
VolatileTexture *vt = *i++; VolatileTexture *vt = *i++;
if (vt->texture == t) { if (vt->texture == t) {
delete vt; delete vt;
break; break;
} }
} }
} }
void VolatileTexture::reloadAllTextures() void VolatileTexture::reloadAllTextures()
{ {
isReloading = true; isReloading = true;
CCLOG("reload all texture"); CCLOG("reload all texture");
std::list<VolatileTexture *>::iterator i = textures.begin(); std::list<VolatileTexture *>::iterator i = textures.begin();
while( i != textures.end() ) while( i != textures.end() )
{ {
VolatileTexture *vt = *i++; VolatileTexture *vt = *i++;
if (vt->m_bIsString) if (vt->m_bIsString)
{ {
vt->texture->initWithString(vt->m_strText.c_str(), vt->texture->initWithString(vt->m_strText.c_str(),
vt->m_size, vt->m_size,
vt->m_alignment, vt->m_alignment,
vt->m_strFontName.c_str(), vt->m_strFontName.c_str(),
vt->m_fFontSize); vt->m_fFontSize);
} }
else else
{ {
CCImage image; CCImage image;
CCFileData data(vt->m_strFileName.c_str(), "rb"); CCFileData data(vt->m_strFileName.c_str(), "rb");
unsigned long nSize = data.getSize(); unsigned long nSize = data.getSize();
@ -595,10 +599,10 @@ void VolatileTexture::reloadAllTextures()
{ {
vt->texture->initWithImage(&image); vt->texture->initWithImage(&image);
} }
} }
} }
isReloading = false; isReloading = false;
} }
#endif // CC_ENABLE_CACHE_TEXTTURE_DATA #endif // CC_ENABLE_CACHE_TEXTTURE_DATA

View File

@ -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 <cctype>
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

View File

@ -1 +1 @@
c129ba52ba1803a75b0f1b1b7a6d95092a8b67b5 ee629ad852ffaadaaf47f1d39c96f7daf670f9be