This commit is contained in:
minggo 2010-12-30 17:30:11 +08:00
parent 0a4ff84f87
commit 942d0233cf
6 changed files with 121 additions and 90 deletions

View File

@ -26,7 +26,6 @@ THE SOFTWARE.
#define __CCTEXTURE2D_H__
#include <string>
#include <GLES/gl.h>
#include "CCXCocos2dDefine.h"
#include "NSObject.h"
@ -47,7 +46,7 @@ typedef enum {
kCCTexture2DPixelFormat_RGBA8888,
//! 24-bit texture: RGBA888
kCCTexture2DPixelFormat_RGB888,
//! 16-bit texture: used with images that have alpha pre-multiplied
//! 16-bit texture without Alpha channel
kCCTexture2DPixelFormat_RGB565,
//! 8-bit textures used as masks
kCCTexture2DPixelFormat_A8,
@ -102,7 +101,7 @@ class CCX_DLL CCTexture2D : public NSObject
CCX_PROPERTY_READONLY(GLuint, m_uName, Name)
/** content size */
CCX_PROPERTY_READONLY(CGSize, m_tContentSize, ContentSize)
CCX_PROPERTY_READONLY(CGSize, m_tContentSize, ContentSizeInPixels)
/** texture max S */
CCX_PROPERTY(GLfloat, m_fMaxS, MaxS)
/** texture max T */
@ -116,6 +115,10 @@ public:
char * description(void);
/** These functions are needed to create mutable textures */
void releaseData(void *data);
void* keepData(void *data, unsigned int length);
/** Intializes with a texture2d with data */
bool initWithData(const void* data, CCTexture2DPixelFormat pixelFormat, unsigned int pixelsWide, unsigned int pixelsHigh, CGSize contentSize);
@ -144,6 +147,9 @@ public:
/** Initializes a texture from a string with font name and font size */
bool initWithString(const char *text, const char *fontName, float fontSize);
/** returns the content size of the texture in points */
CGSize getContentSize(void);
#ifdef _POWERVR_SUPPORT_
/**
Extensions to make it easy to create a CCTexture2D object from a PVRTC file

View File

@ -49,9 +49,9 @@ class CCX_DLL CCTextureAtlas : public NSObject
{
protected:
GLushort *m_pIndices;
#if CC_TEXTURE_ATLAS_USES_VBO
#if CC_USES_VBO
GLuint m_pBuffersVBO[2]; //0: vertex 1: indices
#endif // CC_TEXTURE_ATLAS_USES_VBO
#endif // CC_USES_VBO
/** quantity of quads that are going to be drawn */
CCX_PROPERTY_READONLY(unsigned int, m_uTotalQuads, TotalQuads)

View File

@ -82,25 +82,7 @@ public:
* @since v0.8
*/
// @todo void addImageAsync(const char* filename, NSObject*target, fpAsyncCallback func);
#if _POWERVR_SUPPORT_
/** Returns a Texture2D object given an PVRTC RAW filename
* If the file image was not previously loaded, it will create a new CCTexture2D
* object and it will return it. Otherwise it will return a reference of a previosly loaded image
*
* It can only load square images: width == height, and it must be a power of 2 (128,256,512...)
* bpp can only be 2 or 4. 2 means more compression but lower quality.
* hasAlpha: whether or not the image contains alpha channel
*/
CCTexture2D* addPVRTCImage(const char* fileimage, int bpp, bool hasAlpha, int width);
/** Returns a Texture2D object given an PVRTC filename
* If the file image was not previously loaded, it will create a new CCTexture2D
* object and it will return it. Otherwise it will return a reference of a previosly loaded image
*/
CCTexture2D* addPVRTCImage(const char* fileimage);
#endif
// @todo void addImageAsync(const char* filename, NSObject*target, fpAsyncCallback func);
/* Returns a Texture2D object given an CGImageRef image
* If the image was not previously loaded, it will create a new CCTexture2D object and it will return it.
@ -117,6 +99,11 @@ public:
* If "key" is nil, then a new texture will be created each time.
*/
CCTexture2D* addUIImage(UIImage *image, const char *key);
/** Returns an already created texture. Returns nil if the texture doesn't exist.
@since v0.99.5
*/
CCTexture2D* textureForKey(const char* key);
/** Purges the dictionary of loaded textures.
* Call this method if you receive the "Memory Warning"
* In the short term: it will free some resources preventing your app from being killed
@ -139,7 +126,25 @@ public:
/** Deletes a texture from the cache given a its key name
@since v0.99.4
*/
void removeTextureForKey(const std::string & textureKeyName);
void removeTextureForKey(const char *textureKeyName);
#if _POWERVR_SUPPORT_
/** Returns a Texture2D object given an PVRTC RAW filename
* If the file image was not previously loaded, it will create a new CCTexture2D
* object and it will return it. Otherwise it will return a reference of a previosly loaded image
*
* It can only load square images: width == height, and it must be a power of 2 (128,256,512...)
* bpp can only be 2 or 4. 2 means more compression but lower quality.
* hasAlpha: whether or not the image contains alpha channel
*/
CCTexture2D* addPVRTCImage(const char* fileimage, int bpp, bool hasAlpha, int width);
/** Returns a Texture2D object given an PVRTC filename
* If the file image was not previously loaded, it will create a new CCTexture2D
* object and it will return it. Otherwise it will return a reference of a previosly loaded image
*/
CCTexture2D* addPVRTCImage(const char* fileimage);
#endif
};
}//namespace cocos2d

View File

@ -37,8 +37,8 @@ THE SOFTWARE.
#include "CCConfiguration.h"
#include "platform/platform.h"
#include "CCXUIImage.h"
#include <GLES/glext.h>
#include "CCGL.h"
#include "support/ccUtils.h"
#ifdef _POWERVR_SUPPORT_
#include "CCPVRTexture.h"
@ -50,18 +50,6 @@ namespace cocos2d {
// FontLabel support
#endif// CC_FONT_LABEL_SUPPORT
static unsigned int nextPOT(unsigned int x)
{
x = x - 1;
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
x = x | (x >>16);
return x + 1;
}
//CLASS IMPLEMENTATIONS:
@ -103,11 +91,20 @@ GLuint CCTexture2D::getName()
return m_uName;
}
CGSize CCTexture2D::getContentSize()
CGSize CCTexture2D::getContentSizeInPixels()
{
return m_tContentSize;
}
CGSize CCTexture2D::getContentSize()
{
CGSize ret;
ret.width = m_tContentSize.width / CC_CONTENT_SCALE_FACTOR();
ret.height = m_tContentSize.height / CC_CONTENT_SCALE_FACTOR();
return ret;
}
GLfloat CCTexture2D::getMaxS()
{
return m_fMaxS;
@ -128,6 +125,17 @@ void CCTexture2D::setMaxT(GLfloat maxT)
m_fMaxT = maxT;
}
void CCTexture2D::releaseData(void *data)
{
free(data);
}
void* CCTexture2D::keepData(void *data, unsigned int length)
{
//The texture data mustn't be saved becuase it isn't a mutable texture.
return data;
}
bool CCTexture2D::getHasPremultipliedAlpha()
{
return m_bHasPremultipliedAlpha;
@ -353,11 +361,11 @@ bool CCTexture2D::initPremultipliedATextureWithImage(UIImage *image, unsigned in
if(pixelFormat == kCCTexture2DPixelFormat_RGB565) {
//Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB"
tempData = new UINT8[POTHigh * POTWide * 2];
tempData = new unsigned char[POTHigh * POTWide * 2];
inPixel32 = (unsigned int*)data;
outPixel16 = (unsigned short*)tempData;
for(i = 0; i < POTWide * POTHigh; ++i, ++inPixel32)
for(unsigned int i = 0; i < POTWide * POTHigh; ++i, ++inPixel32)
*outPixel16++ = ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | ((((*inPixel32 >> 8) & 0xFF) >> 2) << 5) | ((((*inPixel32 >> 16) & 0xFF) >> 3) << 0);
delete [] data;
@ -365,11 +373,11 @@ bool CCTexture2D::initPremultipliedATextureWithImage(UIImage *image, unsigned in
}
else if (pixelFormat == kCCTexture2DPixelFormat_RGBA4444) {
//Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRGGGGBBBBAAAA"
tempData = new UINT8[POTHigh * POTWide * 2];
tempData = new unsigned char[POTHigh * POTWide * 2];
inPixel32 = (unsigned int*)data;
outPixel16 = (unsigned short*)tempData;
for(i = 0; i < POTWide * POTHigh; ++i, ++inPixel32)
for(unsigned int i = 0; i < POTWide * POTHigh; ++i, ++inPixel32)
*outPixel16++ =
((((*inPixel32 >> 0) & 0xFF) >> 4) << 12) | // R
((((*inPixel32 >> 8) & 0xFF) >> 4) << 8) | // G
@ -381,11 +389,11 @@ bool CCTexture2D::initPremultipliedATextureWithImage(UIImage *image, unsigned in
}
else if (pixelFormat == kCCTexture2DPixelFormat_RGB5A1) {
//Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGBBBBBA"
tempData = new UINT8[POTHigh * POTWide * 2];
tempData = new unsigned char[POTHigh * POTWide * 2];
inPixel32 = (unsigned int*)data;
outPixel16 = (unsigned short*)tempData;
for(i = 0; i < POTWide * POTHigh; ++i, ++inPixel32)
for(unsigned int i = 0; i < POTWide * POTHigh; ++i, ++inPixel32)
*outPixel16++ =
((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | // R
((((*inPixel32 >> 8) & 0xFF) >> 3) << 6) | // G
@ -441,20 +449,11 @@ void CCTexture2D::drawAtPoint(CGPoint point)
GLfloat width = (GLfloat)m_uPixelsWide * m_fMaxS,
height = (GLfloat)m_uPixelsHigh * m_fMaxT;
#if 0
GLfloat vertices[] = {
-width / 2 + point.x, -height / 2 + point.y, 0.0f,
width / 2 + point.x, -height / 2 + point.y, 0.0f,
-width / 2 + point.x, height / 2 + point.y, 0.0f,
width / 2 + point.x, height / 2 + point.y, 0.0f };
#else // anchor is done by cocos2d automagically
GLfloat vertices[] = {
point.x, point.y, 0.0f,
width + point.x, point.y, 0.0f,
point.x, height + point.y, 0.0f,
width + point.x, height + point.y, 0.0f };
#endif
glBindTexture(GL_TEXTURE_2D, m_uName);
glVertexPointer(3, GL_FLOAT, 0, vertices);
@ -563,14 +562,14 @@ CCTexture2D * CCTexture2D::initWithPVRTCFile(const char* file)
void CCTexture2D::generateMipmap()
{
NSAssert( m_uPixelsWide == nextPOT(m_uPixelsWide) && m_uPixelsHigh == nextPOT(m_uPixelsHigh), "Mimpap texture only works in POT textures");
NSAssert( m_uPixelsWide == ccNextPOT(m_uPixelsWide) && m_uPixelsHigh == ccNextPOT(m_uPixelsHigh), "Mimpap texture only works in POT textures");
glBindTexture( GL_TEXTURE_2D, this->m_uName );
glGenerateMipmapOES(GL_TEXTURE_2D);
ccglGenerateMipmap(GL_TEXTURE_2D);
}
void CCTexture2D::setTexParameters(ccTexParams *texParams)
{
NSAssert( (m_uPixelsWide == nextPOT(m_uPixelsWide) && m_uPixelsHigh == nextPOT(m_uPixelsHigh)) ||
NSAssert( (m_uPixelsWide == ccNextPOT(m_uPixelsWide) && m_uPixelsHigh == ccNextPOT(m_uPixelsHigh)) ||
(texParams->wrapS == GL_CLAMP_TO_EDGE && texParams->wrapT == GL_CLAMP_TO_EDGE),
"GL_CLAMP_TO_EDGE should be used in NPOT textures");
glBindTexture( GL_TEXTURE_2D, this->m_uName );

View File

@ -52,9 +52,9 @@ CCTextureAtlas::~CCTextureAtlas()
CCX_SAFE_FREE(m_pQuads)
CCX_SAFE_FREE(m_pIndices)
#if CC_TEXTURE_ATLAS_USES_VBO
#if CC_USES_VBO
glDeleteBuffers(2, m_pBuffersVBO);
#endif // CC_TEXTURE_ATLAS_USES_VBO
#endif // CC_USES_VBO
CCX_SAFE_RELEASE(m_pTexture);
}
@ -120,9 +120,19 @@ CCTextureAtlas * CCTextureAtlas::textureAtlasWithTexture(CCTexture2D *texture, u
bool CCTextureAtlas::initWithFile(const char * file, unsigned int capacity)
{
// retained in property
CCTexture2D *texture = CCTextureCache::sharedTextureCache()->addImage(file);
CCTexture2D *texture = CCTextureCache::sharedTextureCache()->addImage(file);
return initWithTexture(texture, capacity);
if (texture)
{
return initWithTexture(texture, capacity);
}
else
{
CCLOG("cocos2d: Could not open file: %s", file);
delete this;
return NULL;
}
}
bool CCTextureAtlas::initWithTexture(CCTexture2D *texture, unsigned int capacity)
@ -145,10 +155,10 @@ bool CCTextureAtlas::initWithTexture(CCTexture2D *texture, unsigned int capacity
return false;
}
#if CC_TEXTURE_ATLAS_USES_VBO
#if CC_USES_VBO
// initial binding
glGenBuffers(2, &m_pBuffersVBO[0]);
#endif // CC_TEXTURE_ATLAS_USES_VBO
#endif // CC_USES_VBO
this->initIndices();
@ -189,14 +199,14 @@ void CCTextureAtlas::initIndices()
#endif
}
#if CC_TEXTURE_ATLAS_USES_VBO
#if CC_USES_VBO
glBindBuffer(GL_ARRAY_BUFFER, m_pBuffersVBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(m_pQuads[0]) * m_uCapacity, m_pQuads, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_pBuffersVBO[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(m_pIndices[0]) * m_uCapacity * 6, m_pIndices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#endif // CC_TEXTURE_ATLAS_USES_VBO
#endif // CC_USES_VBO
}
// TextureAtlas - Update, Insert, Move & Remove
@ -212,13 +222,13 @@ void CCTextureAtlas::updateQuad(ccV3F_C4B_T2F_Quad *quad, unsigned int index)
void CCTextureAtlas::insertQuad(ccV3F_C4B_T2F_Quad *quad, unsigned int index)
{
NSAssert( index >= 0 && index < m_uCapacity, "insertQuadWithTexture: Invalid index");
NSAssert( index < m_uCapacity, "insertQuadWithTexture: Invalid index");
m_uTotalQuads++;
NSAssert( m_uTotalQuads <= m_uCapacity, "invalid totalQuads");
// issue #575. index can be > totalQuads
int remaining = (m_uTotalQuads-1) - index;
unsigned int remaining = (m_uTotalQuads-1) - index;
// last object doesn't need to be moved
if( remaining > 0) {
@ -240,8 +250,8 @@ void CCTextureAtlas::insertQuadFromIndex(unsigned int oldIndex, unsigned int new
// because it is ambigious in iphone, so we implement abs ourself
// unsigned int howMany = abs( oldIndex - newIndex);
unsigned int howMany = (oldIndex - newIndex) >= 0 ? (oldIndex - newIndex) : (newIndex - oldIndex);
int dst = oldIndex;
int src = oldIndex + 1;
unsigned int dst = oldIndex;
unsigned int src = oldIndex + 1;
if( oldIndex > newIndex) {
dst = newIndex+1;
src = newIndex;
@ -255,7 +265,7 @@ void CCTextureAtlas::insertQuadFromIndex(unsigned int oldIndex, unsigned int new
void CCTextureAtlas::removeQuadAtIndex(unsigned int index)
{
NSAssert( index >= 0 && index < m_uTotalQuads, "removeQuadAtIndex: Invalid index");
NSAssert( index < m_uTotalQuads, "removeQuadAtIndex: Invalid index");
unsigned int remaining = (m_uTotalQuads-1) - index;
@ -267,8 +277,6 @@ void CCTextureAtlas::removeQuadAtIndex(unsigned int index)
}
m_uTotalQuads--;
NSAssert( m_uTotalQuads >= 0, "invalid totalQuads");
}
void CCTextureAtlas::removeAllQuads()
@ -324,52 +332,55 @@ void CCTextureAtlas::drawQuads()
void CCTextureAtlas::drawNumberOfQuads(unsigned int n)
{
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Unneeded states: -
glBindTexture(GL_TEXTURE_2D, m_pTexture->getName());
#define kQuadSize sizeof(m_pQuads[0].bl)
#if CC_TEXTURE_ATLAS_USES_VBO
#if CC_USES_VBO
glBindBuffer(GL_ARRAY_BUFFER, m_pBuffersVBO[0]);
// XXX: update is done in draw... perhaps it should be done in a timer
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(m_pQuads[0]) * n, m_pQuads);
// vertices
glVertexPointer(3, GL_FLOAT, kQuadSize, (void*) offsetof( ccV3F_C4B_T2F, vertices));
glVertexPointer(3, GL_FLOAT, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, vertices));
// colors
glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (void*) offsetof( ccV3F_C4B_T2F, colors));
glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, colors));
// texture coords
glTexCoordPointer(2, GL_FLOAT, kQuadSize, (void*) offsetof( ccV3F_C4B_T2F, texCoords));
glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, texCoords));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_pBuffersVBO[1]);
#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
glDrawElements(GL_TRIANGLE_STRIP, n*6, GL_UNSIGNED_SHORT, (void*)0);
glDrawElements(GL_TRIANGLE_STRIP, n*6, GL_UNSIGNED_SHORT, (GLvoid*)0);
#else
glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, (void*)0);
#endif // CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, (GLvoid*)0);
#endif // CC_USES_VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#else // ! CC_TEXTURE_ATLAS_USES_VBO
#else // ! CC_USES_VBO
int offset = (int)m_pQuads;
unsigned int offset = (unsigned int)m_pQuads;
// vertex
int diff = offsetof( ccV3F_C4B_T2F, vertices);
glVertexPointer(3, GL_FLOAT, kQuadSize, (void*) (offset + diff) );
unsigned int diff = offsetof( ccV3F_C4B_T2F, vertices);
glVertexPointer(3, GL_FLOAT, kQuadSize, (GLvoid*) (offset + diff) );
// color
diff = offsetof( ccV3F_C4B_T2F, colors);
glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (void*)(offset + diff));
glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (GLvoid*)(offset + diff));
// texture coords
diff = offsetof( ccV3F_C4B_T2F, texCoords);
glTexCoordPointer(2, GL_FLOAT, kQuadSize, (void*)(offset + diff));
glTexCoordPointer(2, GL_FLOAT, kQuadSize, (GLvoid*)(offset + diff));
#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
glDrawElements(GL_TRIANGLE_STRIP, n*6, GL_UNSIGNED_SHORT, m_pIndices);
@ -377,7 +388,7 @@ void CCTextureAtlas::drawNumberOfQuads(unsigned int n)
glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, m_pIndices);
#endif
#endif // CC_TEXTURE_ATLAS_USES_VBO
#endif // CC_USES_VBO
}

View File

@ -184,6 +184,9 @@ CCTexture2D * CCTextureCache::addImage(const char * path)
m_pDictLock->lock();
// remove possible -HD suffix to prevent caching the same image twice (issue #1040)
fullpath = string(ccRemoveHDSuffixFromFile(fullpath.c_str()));
texture = m_pTextures->objectForKey(fullpath);
if( ! texture )
@ -419,12 +422,19 @@ void CCTextureCache::removeTexture(CCTexture2D* texture)
}
}
void CCTextureCache::removeTextureForKey(const std::string & textureKeyName)
void CCTextureCache::removeTextureForKey(const char *textureKeyName)
{
if( textureKeyName.empty() )
if (textureKeyName == NULL)
{
return;
}
m_pTextures->removeObjectForKey(textureKeyName);
m_pTextures->removeObjectForKey(string(textureKeyName));
}
CCTexture2D* CCTextureCache::textureForKey(const char* key)
{
return m_pTextures->objectForKey(string(key));
}
}//namespace cocos2d