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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRTexture *KRTexture::compress()
|
KRTexture *KRTexture::compress(bool premultiply_alpha)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public:
|
|||||||
virtual void resetPoolExpiry();
|
virtual void resetPoolExpiry();
|
||||||
virtual bool isAnimated();
|
virtual bool isAnimated();
|
||||||
|
|
||||||
virtual KRTexture *compress();
|
virtual KRTexture *compress(bool premultiply_alpha = false);
|
||||||
int getCurrentLodMaxDim();
|
int getCurrentLodMaxDim();
|
||||||
int getMaxMipMap();
|
int getMaxMipMap();
|
||||||
int getMinMipMap();
|
int getMinMipMap();
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public:
|
|||||||
virtual bool save(const std::string& path);
|
virtual bool save(const std::string& path);
|
||||||
virtual bool save(KRDataBlock &data);
|
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);
|
virtual void bind(GLuint texture_unit);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ long KRTextureKTX::getMemRequiredForSize(int max_dim)
|
|||||||
return memoryRequired;
|
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;
|
int target_dim = lod_max_dim;
|
||||||
if(target_dim < m_min_lod_max_dim) target_dim = m_min_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 ~KRTextureKTX();
|
||||||
virtual std::string getExtension();
|
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);
|
virtual long getMemRequiredForSize(int max_dim);
|
||||||
|
|
||||||
|
|||||||
@@ -393,14 +393,14 @@ unordered_map<std::string, KRTexture *> &KRTextureManager::getTextures()
|
|||||||
return m_textures;
|
return m_textures;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRTextureManager::compress()
|
void KRTextureManager::compress(bool premultiply_alpha)
|
||||||
{
|
{
|
||||||
std::vector<KRTexture *> textures_to_remove;
|
std::vector<KRTexture *> textures_to_remove;
|
||||||
std::vector<KRTexture *> textures_to_add;
|
std::vector<KRTexture *> textures_to_add;
|
||||||
|
|
||||||
for(unordered_map<std::string, KRTexture *>::iterator itr=m_textures.begin(); itr != m_textures.end(); itr++) {
|
for(unordered_map<std::string, KRTexture *>::iterator itr=m_textures.begin(); itr != m_textures.end(); itr++) {
|
||||||
KRTexture *texture = (*itr).second;
|
KRTexture *texture = (*itr).second;
|
||||||
KRTexture *compressed_texture = texture->compress();
|
KRTexture *compressed_texture = texture->compress(premultiply_alpha);
|
||||||
if(compressed_texture) {
|
if(compressed_texture) {
|
||||||
textures_to_remove.push_back(texture);
|
textures_to_remove.push_back(texture);
|
||||||
textures_to_add.push_back(compressed_texture);
|
textures_to_add.push_back(compressed_texture);
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public:
|
|||||||
|
|
||||||
unordered_map<std::string, KRTexture *> &getTextures();
|
unordered_map<std::string, KRTexture *> &getTextures();
|
||||||
|
|
||||||
void compress();
|
void compress(bool premultiply_alpha = false);
|
||||||
|
|
||||||
std::set<KRTexture *> &getActiveTextures();
|
std::set<KRTexture *> &getActiveTextures();
|
||||||
std::set<KRTexture *> &getPoolTextures();
|
std::set<KRTexture *> &getPoolTextures();
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ long KRTexturePVR::getMemRequiredForSize(int max_dim)
|
|||||||
return memoryRequired;
|
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;
|
int target_dim = lod_max_dim;
|
||||||
if(target_dim < m_min_lod_max_dim) target_dim = m_min_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 ~KRTexturePVR();
|
||||||
virtual std::string getExtension();
|
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);
|
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
|
m_min_lod_max_dim = m_max_lod_max_dim; // Mipmaps not yet supported for TGA images
|
||||||
switch(pHeader->imagetype) {
|
switch(pHeader->imagetype) {
|
||||||
case 2: // rgb
|
case 2: // rgb
|
||||||
|
case 10: // rgb + rle
|
||||||
switch(pHeader->bitsperpixel) {
|
switch(pHeader->bitsperpixel) {
|
||||||
case 24:
|
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();
|
m_pData->lock();
|
||||||
TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart();
|
TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart();
|
||||||
@@ -133,7 +134,26 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo
|
|||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
{
|
{
|
||||||
glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)pData);
|
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();
|
err = glGetError();
|
||||||
if (err != GL_NO_ERROR) {
|
if (err != GL_NO_ERROR) {
|
||||||
m_pData->unlock();
|
m_pData->unlock();
|
||||||
@@ -147,6 +167,120 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo
|
|||||||
return false; // 16-bit images not yet supported
|
return false; // 16-bit images not yet supported
|
||||||
}
|
}
|
||||||
break;
|
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();
|
||||||
|
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;
|
||||||
default:
|
default:
|
||||||
m_pData->unlock();
|
m_pData->unlock();
|
||||||
return false; // Image type not yet supported
|
return false; // Image type not yet supported
|
||||||
@@ -156,7 +290,7 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRTexture *KRTextureTGA::compress()
|
KRTexture *KRTextureTGA::compress(bool premultiply_alpha)
|
||||||
{
|
{
|
||||||
m_pData->lock();
|
m_pData->lock();
|
||||||
|
|
||||||
@@ -170,7 +304,7 @@ KRTexture *KRTextureTGA::compress()
|
|||||||
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compressed_handle));
|
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compressed_handle));
|
||||||
|
|
||||||
int current_max_dim = 0;
|
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
|
assert(false); // Failed to upload the texture
|
||||||
}
|
}
|
||||||
GLDEBUG(glGenerateMipmap(GL_TEXTURE_2D));
|
GLDEBUG(glGenerateMipmap(GL_TEXTURE_2D));
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ public:
|
|||||||
virtual ~KRTextureTGA();
|
virtual ~KRTextureTGA();
|
||||||
virtual std::string getExtension();
|
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 KRTexture *compress();
|
virtual KRTexture *compress(bool premultiply_alpha = false);
|
||||||
|
|
||||||
virtual long getMemRequiredForSize(int max_dim);
|
virtual long getMemRequiredForSize(int max_dim);
|
||||||
private:
|
private:
|
||||||
|
|||||||
Reference in New Issue
Block a user