From 0984822b3ebd85e84b3c017c082d859134801ecd Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Tue, 11 Aug 2009 01:56:56 +0000 Subject: [PATCH] extend alpha mask calculation to GL_UNSIGNED_INT_8_8_8_8 and GL_UNSIGNED_INT_8_8_8_8_REV. also fix EXT-389: clean up warnings: Cannot analyze alpha for image with format type 8035. --- indra/llrender/llimagegl.cpp | 136 +++++++++++++++++++++++++++-------- indra/llrender/llimagegl.h | 7 +- 2 files changed, 110 insertions(+), 33 deletions(-) diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index c3d1d9e894..20c45aa2d3 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -132,6 +132,13 @@ void LLImageGL::checkTexSize() const //************************************************************************************** //---------------------------------------------------------------------------- +BOOL is_little_endian() +{ + S32 a = 0x12345678; + U8 *c = (U8*)(&a); + + return (*c == 0x78) ; +} //static S32 LLImageGL::dataFormatBits(S32 dataformat) @@ -363,6 +370,8 @@ void LLImageGL::init(BOOL usemipmaps) mGLTextureCreated = FALSE ; mIsMask = FALSE; mNeedsAlphaAndPickMask = TRUE ; + mAlphaStride = 0 ; + mAlphaOffset = 0 ; } void LLImageGL::cleanup() @@ -501,6 +510,8 @@ void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_for else mFormatType = type_format; mFormatSwapBytes = swap_bytes; + + calcAlphaChannelOffsetAndStride() ; } //---------------------------------------------------------------------------- @@ -951,6 +962,8 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S default: llerrs << "Bad number of components for texture: " << (U32)getComponents() << llendl; } + + calcAlphaChannelOffsetAndStride() ; } const U8* rawdata = imageraw->getData(); @@ -1355,6 +1368,96 @@ void LLImageGL::setTarget(const LLGLenum target, const LLTexUnit::eTextureType b mBindTarget = bind_target; } +const S8 INVALID_OFFSET = -99 ; +void LLImageGL::setNeedsAlphaAndPickMask(BOOL need_mask) +{ + if(mNeedsAlphaAndPickMask != need_mask) + { + mNeedsAlphaAndPickMask = need_mask; + + if(mNeedsAlphaAndPickMask) + { + mAlphaOffset = 0 ; + } + else //do not need alpha mask + { + mAlphaOffset = INVALID_OFFSET ; + mIsMask = FALSE; + } + } +} + +void LLImageGL::calcAlphaChannelOffsetAndStride() +{ + if(mAlphaOffset == INVALID_OFFSET)//do not need alpha mask + { + return ; + } + + mAlphaOffset = -1 ; + + if (mFormatType == GL_UNSIGNED_BYTE) + { + mAlphaOffset = 3 ; + } + else if(is_little_endian()) + { + if (mFormatType == GL_UNSIGNED_INT_8_8_8_8) + { + mAlphaOffset = 0 ; + } + else if (mFormatType == GL_UNSIGNED_INT_8_8_8_8_REV) + { + mAlphaOffset = 3 ; + } + } + else //big endian + { + if (mFormatType == GL_UNSIGNED_INT_8_8_8_8) + { + mAlphaOffset = 3 ; + } + else if (mFormatType == GL_UNSIGNED_INT_8_8_8_8_REV) + { + mAlphaOffset = 0 ; + } + } + + mAlphaStride = -1 ; + switch (mFormatPrimary) + { + case GL_LUMINANCE: + case GL_ALPHA: + mAlphaStride = 1; + break; + case GL_LUMINANCE_ALPHA: + mAlphaStride = 2; + break; + case GL_RGB: + mNeedsAlphaAndPickMask = FALSE ; + mIsMask = FALSE; + return ; //no alpha channel. + case GL_RGBA: + mAlphaStride = 4; + break; + case GL_BGRA_EXT: + mAlphaStride = 4; + break; + default: + break; + } + + if( mAlphaStride < 1 || //unsupported format + mAlphaOffset < 0 || //unsupported type + (mFormatPrimary == GL_BGRA_EXT && mFormatType != GL_UNSIGNED_BYTE)) //unknown situation + { + llwarns << "Cannot analyze alpha for image with format type " << std::hex << mFormatType << std::dec << llendl; + + mNeedsAlphaAndPickMask = FALSE ; + mIsMask = FALSE; + } +} + void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h) { if(!mNeedsAlphaAndPickMask) @@ -1362,37 +1465,8 @@ void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h) return ; } - if (mFormatType != GL_UNSIGNED_BYTE) - { - llwarns << "Cannot analyze alpha for image with format type " << std::hex << mFormatType << std::dec << llendl; - } - - U32 stride = 0; - switch (mFormatPrimary) - { - case GL_LUMINANCE: - case GL_ALPHA: - stride = 1; - break; - case GL_LUMINANCE_ALPHA: - stride = 2; - break; - case GL_RGB: - //no alpha - mIsMask = FALSE; - return; - case GL_RGBA: - stride = 4; - break; - case GL_BGRA_EXT: - stride = 4; - break; - default: - return; - } - U32 length = w * h; - const GLubyte* current = ((const GLubyte*) data_in)+stride-1; + const GLubyte* current = ((const GLubyte*) data_in) + mAlphaOffset ; S32 sample[16]; memset(sample, 0, sizeof(S32)*16); @@ -1400,7 +1474,7 @@ void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h) for (U32 i = 0; i < length; i++) { ++sample[*current/16]; - current += stride; + current += mAlphaStride ; } U32 total = 0; diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 5f32b23356..bcb57d3a21 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -88,6 +88,7 @@ protected: virtual ~LLImageGL(); void analyzeAlpha(const void* data_in, S32 w, S32 h); + void calcAlphaChannelOffsetAndStride(); public: virtual void dump(); // debugging info to llinfos @@ -167,7 +168,7 @@ public: void init(BOOL usemipmaps); virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors - void setNeedsAlphaAndPickMask(BOOL need_mask) {mNeedsAlphaAndPickMask = need_mask;} + void setNeedsAlphaAndPickMask(BOOL need_mask); public: // Various GL/Rendering options S32 mTextureMemory; @@ -182,7 +183,9 @@ private: BOOL mIsMask; BOOL mNeedsAlphaAndPickMask; - + S8 mAlphaStride ; + S8 mAlphaOffset ; + bool mGLTextureCreated ; LLGLuint mTexName; U16 mWidth;