Implemented support for RLE compressed TGA images
Image import pipeline can now generate pre-multiplied alpha output images while they are compressed. --HG-- branch : nfb
This commit is contained in:
@@ -111,7 +111,7 @@ bool KRTexture::isAnimated()
|
||||
return false;
|
||||
}
|
||||
|
||||
KRTexture *KRTexture::compress()
|
||||
KRTexture *KRTexture::compress(bool premultiply_alpha)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
virtual void resetPoolExpiry();
|
||||
virtual bool isAnimated();
|
||||
|
||||
virtual KRTexture *compress();
|
||||
virtual KRTexture *compress(bool premultiply_alpha = false);
|
||||
int getCurrentLodMaxDim();
|
||||
int getMaxMipMap();
|
||||
int getMinMipMap();
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
virtual bool save(const std::string& path);
|
||||
virtual bool save(KRDataBlock &data);
|
||||
|
||||
virtual bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress = false) = 0;
|
||||
virtual bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress = false, bool premultiply_alpha = false) = 0;
|
||||
virtual void bind(GLuint texture_unit);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -153,7 +153,7 @@ long KRTextureKTX::getMemRequiredForSize(int max_dim)
|
||||
return memoryRequired;
|
||||
}
|
||||
|
||||
bool KRTextureKTX::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress)
|
||||
bool KRTextureKTX::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress, bool premultiply_alpha)
|
||||
{
|
||||
int target_dim = lod_max_dim;
|
||||
if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
virtual ~KRTextureKTX();
|
||||
virtual std::string getExtension();
|
||||
|
||||
bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress = false);
|
||||
bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress = false, bool premultiply_alpha = false);
|
||||
|
||||
virtual long getMemRequiredForSize(int max_dim);
|
||||
|
||||
|
||||
@@ -393,14 +393,14 @@ unordered_map<std::string, KRTexture *> &KRTextureManager::getTextures()
|
||||
return m_textures;
|
||||
}
|
||||
|
||||
void KRTextureManager::compress()
|
||||
void KRTextureManager::compress(bool premultiply_alpha)
|
||||
{
|
||||
std::vector<KRTexture *> textures_to_remove;
|
||||
std::vector<KRTexture *> textures_to_add;
|
||||
|
||||
for(unordered_map<std::string, KRTexture *>::iterator itr=m_textures.begin(); itr != m_textures.end(); itr++) {
|
||||
KRTexture *texture = (*itr).second;
|
||||
KRTexture *compressed_texture = texture->compress();
|
||||
KRTexture *compressed_texture = texture->compress(premultiply_alpha);
|
||||
if(compressed_texture) {
|
||||
textures_to_remove.push_back(texture);
|
||||
textures_to_add.push_back(compressed_texture);
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
|
||||
unordered_map<std::string, KRTexture *> &getTextures();
|
||||
|
||||
void compress();
|
||||
void compress(bool premultiply_alpha = false);
|
||||
|
||||
std::set<KRTexture *> &getActiveTextures();
|
||||
std::set<KRTexture *> &getPoolTextures();
|
||||
|
||||
@@ -173,7 +173,7 @@ long KRTexturePVR::getMemRequiredForSize(int max_dim)
|
||||
return memoryRequired;
|
||||
}
|
||||
|
||||
bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress)
|
||||
bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress, bool premultiply_alpha)
|
||||
{
|
||||
int target_dim = lod_max_dim;
|
||||
if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
|
||||
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
virtual ~KRTexturePVR();
|
||||
virtual std::string getExtension();
|
||||
|
||||
bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress = false);
|
||||
bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress = false, bool premultiply_alpha = false);
|
||||
|
||||
virtual long getMemRequiredForSize(int max_dim);
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ KRTextureTGA::KRTextureTGA(KRContext &context, KRDataBlock *data, std::string na
|
||||
m_min_lod_max_dim = m_max_lod_max_dim; // Mipmaps not yet supported for TGA images
|
||||
switch(pHeader->imagetype) {
|
||||
case 2: // rgb
|
||||
case 10: // rgb + rle
|
||||
switch(pHeader->bitsperpixel) {
|
||||
case 24:
|
||||
{
|
||||
@@ -70,7 +71,7 @@ KRTextureTGA::~KRTextureTGA()
|
||||
|
||||
}
|
||||
|
||||
bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress)
|
||||
bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress, bool premultiply_alpha)
|
||||
{
|
||||
m_pData->lock();
|
||||
TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart();
|
||||
@@ -133,7 +134,140 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo
|
||||
break;
|
||||
case 32:
|
||||
{
|
||||
if(premultiply_alpha) {
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
|
||||
while(pSource < pEnd) {
|
||||
*pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff;
|
||||
*pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff;
|
||||
*pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff;
|
||||
*pDest++ = pSource[3];
|
||||
pSource += 4;
|
||||
}
|
||||
|
||||
glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image);
|
||||
free(converted_image);
|
||||
} else {
|
||||
glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)pData);
|
||||
}
|
||||
|
||||
err = glGetError();
|
||||
if (err != GL_NO_ERROR) {
|
||||
m_pData->unlock();
|
||||
return false;
|
||||
}
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_pData->unlock();
|
||||
return false; // 16-bit images not yet supported
|
||||
}
|
||||
break;
|
||||
case 10: // rgb + rle
|
||||
switch(pHeader->bitsperpixel) {
|
||||
case 24:
|
||||
{
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4;
|
||||
if(premultiply_alpha) {
|
||||
while(pDest < pEnd) {
|
||||
int count = *pSource & 0x7f + 1;
|
||||
if(*pSource & 0x80) {
|
||||
// RLE Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff;
|
||||
*pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff;
|
||||
*pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff;
|
||||
*pDest++ = pSource[3];
|
||||
}
|
||||
pSource += 4;
|
||||
} else {
|
||||
// RAW Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff;
|
||||
*pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff;
|
||||
*pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff;
|
||||
*pDest++ = pSource[3];
|
||||
pSource += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while(pDest < pEnd) {
|
||||
int count = *pSource & 0x7f + 1;
|
||||
if(*pSource & 0x80) {
|
||||
// RLE Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[3];
|
||||
}
|
||||
pSource += 4;
|
||||
} else {
|
||||
// RAW Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[3];
|
||||
pSource += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image);
|
||||
free(converted_image);
|
||||
err = glGetError();
|
||||
if (err != GL_NO_ERROR) {
|
||||
m_pData->unlock();
|
||||
return false;
|
||||
}
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
{
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4;
|
||||
while(pDest < pEnd) {
|
||||
int count = *pSource & 0x7f + 1;
|
||||
if(*pSource & 0x80) {
|
||||
// RLE Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = 0xff;
|
||||
}
|
||||
pSource += 3;
|
||||
} else {
|
||||
// RAW Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = 0xff;
|
||||
pSource += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image);
|
||||
free(converted_image);
|
||||
err = glGetError();
|
||||
if (err != GL_NO_ERROR) {
|
||||
m_pData->unlock();
|
||||
@@ -156,7 +290,7 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo
|
||||
return true;
|
||||
}
|
||||
|
||||
KRTexture *KRTextureTGA::compress()
|
||||
KRTexture *KRTextureTGA::compress(bool premultiply_alpha)
|
||||
{
|
||||
m_pData->lock();
|
||||
|
||||
@@ -170,7 +304,7 @@ KRTexture *KRTextureTGA::compress()
|
||||
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compressed_handle));
|
||||
|
||||
int current_max_dim = 0;
|
||||
if(!uploadTexture(GL_TEXTURE_2D, m_max_lod_max_dim, current_max_dim, 0, true)) {
|
||||
if(!uploadTexture(GL_TEXTURE_2D, m_max_lod_max_dim, current_max_dim, 0, true, premultiply_alpha)) {
|
||||
assert(false); // Failed to upload the texture
|
||||
}
|
||||
GLDEBUG(glGenerateMipmap(GL_TEXTURE_2D));
|
||||
|
||||
@@ -18,8 +18,8 @@ public:
|
||||
virtual ~KRTextureTGA();
|
||||
virtual std::string getExtension();
|
||||
|
||||
bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress = false);
|
||||
virtual KRTexture *compress();
|
||||
bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress = false, bool premultiply_alpha = false);
|
||||
virtual KRTexture *compress(bool premultiply_alpha = false);
|
||||
|
||||
virtual long getMemRequiredForSize(int max_dim);
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user