diff options
author | Steven Bennetts <steve@lindenlab.com> | 2009-06-21 08:04:56 +0000 |
---|---|---|
committer | Steven Bennetts <steve@lindenlab.com> | 2009-06-21 08:04:56 +0000 |
commit | 9ec432034dc3c45d7ce763eb02dae4cc7f6b8da8 (patch) | |
tree | 4a505c1e0919af52800b3ffb3eaf135e7d6f9ce6 /indra/newview/lltexlayer.cpp | |
parent | 351ebe9fcb76f3b99c2957004bb8493a904869ee (diff) |
merge -r 122421-124917 viewer-2.0.0-2 -> viewer-2.0.0-3
ignore-dead-branch
Diffstat (limited to 'indra/newview/lltexlayer.cpp')
-rw-r--r-- | indra/newview/lltexlayer.cpp | 1505 |
1 files changed, 437 insertions, 1068 deletions
diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index b05da8c6d8..716ab8eef4 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -31,80 +31,56 @@ */ #include "llviewerprecompiledheaders.h" - -#include "imageids.h" #include "llagent.h" -#include "llcrc.h" -#include "lldir.h" -#include "llglheaders.h" -#include "llimagebmp.h" -#include "llimagej2c.h" -#include "llimagetga.h" -#include "llpolymorph.h" -#include "llquantize.h" #include "lltexlayer.h" -#include "llui.h" -#include "llvfile.h" -#include "llviewerimagelist.h" -#include "llviewerimagelist.h" -#include "llviewerregion.h" #include "llviewerstats.h" -#include "llviewerwindow.h" +#include "llviewerregion.h" #include "llvoavatar.h" -#include "llxmltree.h" +#include "llvoavatarself.h" #include "pipeline.h" -#include "v4coloru.h" -#include "llrender.h" #include "llassetuploadresponders.h" +#include "lltexlayerparams.h" +#include "llui.h" //#include "../tools/imdebug/imdebug.h" using namespace LLVOAvatarDefines; -// static -S32 LLTexLayerSetBuffer::sGLByteCount = 0; -S32 LLTexLayerSetBuffer::sGLBumpByteCount = 0; - //----------------------------------------------------------------------------- // LLBakedUploadData() //----------------------------------------------------------------------------- -LLBakedUploadData::LLBakedUploadData( LLVOAvatar* avatar, - LLTexLayerSet* layerset, - LLTexLayerSetBuffer* layerset_buffer, - const LLUUID & id ) : - mAvatar( avatar ), - mLayerSet( layerset ), - mLayerSetBuffer( layerset_buffer ), - mID(id) +LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar, + LLTexLayerSet* layerset, + const LLUUID& id) : + mAvatar(avatar), + mTexLayerSet(layerset), + mID(id), + mStartTime(LLFrameTimer::getTotalTime()) // Record starting time { - mStartTime = LLFrameTimer::getTotalTime(); // Record starting time - for( S32 i = 0; i < WT_COUNT; i++ ) - { - LLWearable* wearable = gAgent.getWearable( (EWearableType)i); - if( wearable ) - { - mWearableAssets[i] = wearable->getID(); - } - } } //----------------------------------------------------------------------------- // LLTexLayerSetBuffer // The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one. //----------------------------------------------------------------------------- -LLTexLayerSetBuffer::LLTexLayerSetBuffer( LLTexLayerSet* owner, S32 width, S32 height, BOOL has_bump ) - : + +// static +S32 LLTexLayerSetBuffer::sGLByteCount = 0; +S32 LLTexLayerSetBuffer::sGLBumpByteCount = 0; + +LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner, + S32 width, S32 height, + BOOL has_bump) : // ORDER_LAST => must render these after the hints are created. LLDynamicTexture( width, height, 4, LLDynamicTexture::ORDER_LAST, TRUE ), mNeedsUpdate( TRUE ), mNeedsUpload( FALSE ), mUploadPending( FALSE ), // Not used for any logic here, just to sync sending of updates - mTexLayerSet( owner ) + mTexLayerSet(owner), + mHasBump(has_bump), + mBumpTex(NULL) { LLTexLayerSetBuffer::sGLByteCount += getSize(); - mHasBump = has_bump ; - mBumpTex = NULL ; - createBumpTexture() ; } @@ -115,10 +91,11 @@ LLTexLayerSetBuffer::~LLTexLayerSetBuffer() if( mBumpTex.notNull()) { mBumpTex = NULL ; - LLImageGL::sGlobalTextureMemory -= mWidth * mHeight * 4; + LLImageGL::sGlobalTextureMemoryInBytes -= mWidth * mHeight * 4; LLTexLayerSetBuffer::sGLBumpByteCount -= mWidth * mHeight * 4; } } + //virtual void LLTexLayerSetBuffer::restoreGLTexture() { @@ -132,7 +109,7 @@ void LLTexLayerSetBuffer::destroyGLTexture() if( mBumpTex.notNull() ) { mBumpTex = NULL ; - LLImageGL::sGlobalTextureMemory -= mWidth * mHeight * 4; + LLImageGL::sGlobalTextureMemoryInBytes -= mWidth * mHeight * 4; LLTexLayerSetBuffer::sGLBumpByteCount -= mWidth * mHeight * 4; } @@ -163,7 +140,7 @@ void LLTexLayerSetBuffer::createBumpTexture() gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLImageGL::sGlobalTextureMemory += mWidth * mHeight * 4; + LLImageGL::sGlobalTextureMemoryInBytes += mWidth * mHeight * 4; LLTexLayerSetBuffer::sGLBumpByteCount += mWidth * mHeight * 4; } } @@ -202,7 +179,7 @@ void LLTexLayerSetBuffer::cancelUpload() mUploadPending = FALSE; } -void LLTexLayerSetBuffer::pushProjection() +void LLTexLayerSetBuffer::pushProjection() const { glMatrixMode(GL_PROJECTION); gGL.pushMatrix(); @@ -214,7 +191,7 @@ void LLTexLayerSetBuffer::pushProjection() glLoadIdentity(); } -void LLTexLayerSetBuffer::popProjection() +void LLTexLayerSetBuffer::popProjection() const { glMatrixMode(GL_PROJECTION); gGL.popMatrix(); @@ -225,12 +202,12 @@ void LLTexLayerSetBuffer::popProjection() BOOL LLTexLayerSetBuffer::needsRender() { - LLVOAvatar* avatar = mTexLayerSet->getAvatar(); + const LLVOAvatarSelf* avatar = mTexLayerSet->getAvatar(); BOOL upload_now = mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal(); - BOOL needs_update = gAgent.mNumPendingQueries == 0 && (mNeedsUpdate || upload_now) && !avatar->mAppearanceAnimating; + BOOL needs_update = gAgentQueryManager.hasNoPendingQueries() && (mNeedsUpdate || upload_now) && !avatar->mAppearanceAnimating; if (needs_update) { - BOOL invalid_skirt = avatar->getBakedTE(mTexLayerSet) == TEX_SKIRT_BAKED && !avatar->isWearingWearableType(WT_SKIRT); + BOOL invalid_skirt = avatar->getBakedTE(mTexLayerSet) == LLVOAvatarDefines::TEX_SKIRT_BAKED && !avatar->isWearingWearableType(WT_SKIRT); if (invalid_skirt) { // we were trying to create a skirt texture @@ -272,7 +249,7 @@ BOOL LLTexLayerSetBuffer::render() // do we need to upload, and do we have sufficient data to create an uploadable composite? // When do we upload the texture if gAgent.mNumPendingQueries is non-zero? - BOOL upload_now = (gAgent.mNumPendingQueries == 0 && mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal()); + BOOL upload_now = (gAgentQueryManager.hasNoPendingQueries() && mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal()); BOOL success = TRUE; // Composite bump @@ -312,7 +289,6 @@ BOOL LLTexLayerSetBuffer::render() { if (!success) { - delete [] baked_bump_data; llinfos << "Failed attempt to bake " << mTexLayerSet->getBodyRegion() << llendl; mUploadPending = FALSE; } @@ -330,6 +306,7 @@ BOOL LLTexLayerSetBuffer::render() mTexture->setGLTextureCreated(true); mNeedsUpdate = FALSE; + delete [] baked_bump_data; return success; } @@ -353,7 +330,7 @@ BOOL LLTexLayerSetBuffer::updateImmediate() return result; } -void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data) +void LLTexLayerSetBuffer::readBackAndUpload(const U8* baked_bump_data) { // pointers for storing data to upload U8* baked_color_data = new U8[ mWidth * mHeight * 4 ]; @@ -375,10 +352,8 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data) LLPointer<LLImageRaw> baked_mask_image = new LLImageRaw(mWidth, mHeight, 1 ); U8* baked_mask_data = baked_mask_image->getData(); - - mTexLayerSet->gatherAlphaMasks(baked_mask_data, mWidth, mHeight); -// imdebug("lum b=8 w=%d h=%d %p", mWidth, mHeight, baked_mask_data); - + + mTexLayerSet->gatherMorphMaskAlpha(baked_mask_data, mWidth, mHeight); // writes into baked_color_data const char* comment_text = NULL; @@ -387,13 +362,11 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data) LLPointer<LLImageRaw> baked_image = new LLImageRaw( mWidth, mHeight, baked_image_components ); U8* baked_image_data = baked_image->getData(); + if( mBumpTex.notNull() ) { comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // 5 channels: rgb, heightfield/alpha, mask - // Hide the alpha for the eyelashes in a corner of the bump map - if (mTexLayerSet->getBodyRegion() == "head") - { S32 i = 0; for( S32 u = 0; u < mWidth; u++ ) { @@ -415,25 +388,6 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data) { for( S32 v = 0; v < mHeight; v++ ) { - baked_image_data[5*i + 0] = baked_color_data[4*i + 0]; - baked_image_data[5*i + 1] = baked_color_data[4*i + 1]; - baked_image_data[5*i + 2] = baked_color_data[4*i + 2]; - baked_image_data[5*i + 3] = 255; // reserve for alpha - baked_image_data[5*i + 4] = baked_mask_data[i]; - i++; - } - } - } - } - else - { - if (mTexLayerSet->getBodyRegion() == "skirt" || mTexLayerSet->getBodyRegion() == "hair") - { - S32 i = 0; - for( S32 u = 0; u < mWidth; u++ ) - { - for( S32 v = 0; v < mHeight; v++ ) - { baked_image_data[4*i + 0] = baked_color_data[4*i + 0]; baked_image_data[4*i + 1] = baked_color_data[4*i + 1]; baked_image_data[4*i + 2] = baked_color_data[4*i + 2]; @@ -442,22 +396,6 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data) } } } - else - { - S32 i = 0; - for( S32 u = 0; u < mWidth; u++ ) - { - for( S32 v = 0; v < mHeight; v++ ) - { - baked_image_data[4*i + 0] = baked_color_data[4*i + 0]; - baked_image_data[4*i + 1] = baked_color_data[4*i + 1]; - baked_image_data[4*i + 2] = baked_color_data[4*i + 2]; - baked_image_data[4*i + 3] = 255; // eyes should have no mask - reserve for alpha - i++; - } - } - } - } LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C; compressedImage->setRate(0.f); @@ -490,7 +428,7 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data) { // baked_upload_data is owned by the responder and deleted after the request completes LLBakedUploadData* baked_upload_data = - new LLBakedUploadData( gAgent.getAvatarObject(), this->mTexLayerSet, this, asset_id ); + new LLBakedUploadData(gAgent.getAvatarObject(), this->mTexLayerSet, asset_id); mUploadID = asset_id; // upload the image @@ -536,73 +474,74 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data) } delete [] baked_color_data; - delete [] baked_bump_data; } // static -void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, void* userdata, S32 result, LLExtStat ext_status) // StoreAssetData callback (not fixed) +void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, + void* userdata, + S32 result, + LLExtStat ext_status) // StoreAssetData callback (not fixed) { LLBakedUploadData* baked_upload_data = (LLBakedUploadData*)userdata; - LLVOAvatar* avatar = gAgent.getAvatarObject(); + LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if (0 == result && avatar && !avatar->isDead()) + if (0 == result && + avatar && + !avatar->isDead() && + baked_upload_data->mAvatar == avatar && // Sanity check: only the user's avatar should be uploading textures. + baked_upload_data->mTexLayerSet->hasComposite() + ) { - // Sanity check: only the user's avatar should be uploading textures. - if( baked_upload_data->mAvatar == avatar ) + LLTexLayerSetBuffer* layerset_buffer = baked_upload_data->mTexLayerSet->getComposite(); + + if (layerset_buffer->mUploadID.isNull()) { - // Composite may have changed since the pointer was stored - need to do some checking. - LLTexLayerSetBuffer* prev_layerset_buffer = baked_upload_data->mLayerSetBuffer; - // Can't just call getComposite() because this will trigger creation if none exists. - LLTexLayerSetBuffer* curr_layerset_buffer = - baked_upload_data->mLayerSet->hasComposite()?baked_upload_data->mLayerSet->getComposite():NULL; + // The upload got canceled, we should be in the + // process of baking a new texture so request an + // upload with the new data - if (prev_layerset_buffer != curr_layerset_buffer) + // BAP: does this really belong in this callback, as + // opposed to where the cancellation takes place? + // suspect this does nothing. + layerset_buffer->requestUpload(); + } + else if (baked_upload_data->mID == layerset_buffer->mUploadID) + { + // This is the upload we're currently waiting for. + layerset_buffer->mUploadID.setNull(); + layerset_buffer->mUploadPending = FALSE; + + if (result >= 0) { - llinfos << "Baked texture out of date, composite no longer valid, ignored" << llendl; + LLVOAvatarDefines::ETextureIndex baked_te = avatar->getBakedTE(layerset_buffer->mTexLayerSet); + // Update baked texture info with the new UUID + U64 now = LLFrameTimer::getTotalTime(); // Record starting time + llinfos << "Baked texture upload took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl; + avatar->setNewBakedTexture(baked_te, uuid); } else - { - curr_layerset_buffer->mUploadPending = FALSE; - - if (curr_layerset_buffer->mUploadID.isNull()) - { - // The upload got canceled, we should be in the process of baking a new texture - // so request an upload with the new data - curr_layerset_buffer->requestUpload(); - } - else if( baked_upload_data->mID == curr_layerset_buffer->mUploadID ) - { - // This is the upload we're currently waiting for. - curr_layerset_buffer->mUploadID.setNull(); - - if( result >= 0 ) - { - ETextureIndex baked_te = avatar->getBakedTE( curr_layerset_buffer->mTexLayerSet ); - U64 now = LLFrameTimer::getTotalTime(); // Record starting time - llinfos << "Baked texture upload took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl; - avatar->setNewBakedTexture( baked_te, uuid ); - } - else - { - llinfos << "Baked upload failed. Reason: " << result << llendl; - // *FIX: retry upload after n seconds, asset server could be busy - } - } - else - { - llinfos << "Received baked texture out of date, ignored." << llendl; - } - - avatar->dirtyMesh(); + { + // Avatar appearance is changing, ignore the upload results + llinfos << "Baked upload failed. Reason: " << result << llendl; + // *FIX: retry upload after n seconds, asset server could be busy } } + else + { + llinfos << "Received baked texture out of date, ignored." << llendl; + } + + avatar->dirtyMesh(); } else { - // Baked texture failed to upload, but since we didn't set the new baked texture, it means that they'll - // try and rebake it at some point in the future (after login?) + // Baked texture failed to upload (in which case since we + // didn't set the new baked texture, it means that they'll try + // and rebake it at some point in the future (after login?)), + // or this response to upload is out of date, in which case a + // current response should be on the way or already processed. llwarns << "Baked upload failed" << llendl; } @@ -635,8 +574,7 @@ void LLTexLayerSetBuffer::bindBumpTexture( U32 stage ) // An ordered set of texture layers that get composited into a single texture. //----------------------------------------------------------------------------- -LLTexLayerSetInfo::LLTexLayerSetInfo( ) - : +LLTexLayerSetInfo::LLTexLayerSetInfo() : mBodyRegion( "" ), mWidth( 512 ), mHeight( 512 ), @@ -701,6 +639,19 @@ BOOL LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node) return TRUE; } +// creates visual params without generating layersets or layers +void LLTexLayerSetInfo::createVisualParams(LLVOAvatar *avatar) +{ + //layer_info_list_t mLayerInfoList; + for (layer_info_list_t::iterator layer_iter = mLayerInfoList.begin(); + layer_iter != mLayerInfoList.end(); + layer_iter++) + { + LLTexLayerInfo *layer_info = *layer_iter; + layer_info->createVisualParams(avatar); + } +} + //----------------------------------------------------------------------------- // LLTexLayerSet // An ordered set of texture layers that get composited into a single texture. @@ -708,8 +659,7 @@ BOOL LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node) BOOL LLTexLayerSet::sHasCaches = FALSE; -LLTexLayerSet::LLTexLayerSet( LLVOAvatar* avatar ) - : +LLTexLayerSet::LLTexLayerSet(LLVOAvatarSelf* const avatar) : mComposite( NULL ), mAvatar( avatar ), mUpdatesEnabled( FALSE ), @@ -720,7 +670,9 @@ LLTexLayerSet::LLTexLayerSet( LLVOAvatar* avatar ) LLTexLayerSet::~LLTexLayerSet() { + deleteCaches(); std::for_each(mLayerList.begin(), mLayerList.end(), DeletePointer()); + std::for_each(mMaskLayerList.begin(), mMaskLayerList.end(), DeletePointer()); delete mComposite; } @@ -728,15 +680,16 @@ LLTexLayerSet::~LLTexLayerSet() // setInfo //----------------------------------------------------------------------------- -BOOL LLTexLayerSet::setInfo(LLTexLayerSetInfo *info) +BOOL LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info) { llassert(mInfo == NULL); mInfo = info; //mID = info->mID; // No ID - LLTexLayerSetInfo::layer_info_list_t::iterator iter; mLayerList.reserve(info->mLayerInfoList.size()); - for (iter = info->mLayerInfoList.begin(); iter != info->mLayerInfoList.end(); iter++) + for (LLTexLayerSetInfo::layer_info_list_t::const_iterator iter = info->mLayerInfoList.begin(); + iter != info->mLayerInfoList.end(); + iter++) { LLTexLayer* layer = new LLTexLayer( this ); if (!layer->setInfo(*iter)) @@ -744,8 +697,15 @@ BOOL LLTexLayerSet::setInfo(LLTexLayerSetInfo *info) mInfo = NULL; return FALSE; } + if (!layer->isVisibilityMask()) + { mLayerList.push_back( layer ); } + else + { + mMaskLayerList.push_back(layer); + } + } requestUpdate(); @@ -784,19 +744,26 @@ void LLTexLayerSet::deleteCaches() LLTexLayer* layer = *iter; layer->deleteCaches(); } + for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) + { + LLTexLayer* layer = *iter; + layer->deleteCaches(); + } } // Returns TRUE if at least one packet of data has been received for each of the textures that this layerset depends on. -BOOL LLTexLayerSet::isLocalTextureDataAvailable() +BOOL LLTexLayerSet::isLocalTextureDataAvailable() const { - return mAvatar->isLocalTextureDataAvailable( this ); + if (!mAvatar->isSelf()) return FALSE; + return ((LLVOAvatarSelf *)mAvatar)->isLocalTextureDataAvailable(this); } // Returns TRUE if all of the data for the textures that this layerset depends on have arrived. -BOOL LLTexLayerSet::isLocalTextureDataFinal() +BOOL LLTexLayerSet::isLocalTextureDataFinal() const { - return mAvatar->isLocalTextureDataFinal( this ); + if (!mAvatar->isSelf()) return FALSE; + return ((LLVOAvatarSelf *)mAvatar)->isLocalTextureDataFinal(this); } @@ -808,62 +775,26 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE); gGL.setColorMask(true, true); + BOOL render_morph = mAvatar->morphMaskNeedsUpdate(mBakedTexIndex); + // composite color layers for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) { LLTexLayer* layer = *iter; - if( layer->getRenderPass() == RP_COLOR ) + if (layer->getRenderPass() == LLTexLayer::RP_COLOR) { gGL.flush(); - success &= layer->render( x, y, width, height ); + success &= layer->render(x, y, width, height, render_morph); gGL.flush(); - } - } - - // (Optionally) replace alpha with a single component image from a tga file. - if( !getInfo()->mStaticAlphaFileName.empty() ) - { - LLGLSNoAlphaTest gls_no_alpha_test; - gGL.flush(); - gGL.setColorMask(false, true); - gGL.setSceneBlendType(LLRender::BT_REPLACE); - - { - LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticAlphaFileName, TRUE ); - if( image_gl ) + if (layer->isMorphValid()) { - LLGLSUIDefault gls_ui; - gGL.getTexUnit(0)->bind(image_gl); - gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE ); - gl_rect_2d_simple_tex( width, height ); - } - else - { - success = FALSE; + mAvatar->setMorphMasksValid(TRUE, mBakedTexIndex); } } - gGL.flush(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - gGL.setColorMask(true, true); - gGL.setSceneBlendType(LLRender::BT_ALPHA); } - else - if( getInfo()->mClearAlpha ) - { - // Set the alpha channel to one (clean up after previous blending) - LLGLDisable no_alpha(GL_ALPHA_TEST); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4f( 0.f, 0.f, 0.f, 1.f ); - gGL.flush(); - gGL.setColorMask(false, true); + + renderAlphaMaskTextures(width, height, false); - gl_rect_2d_simple( width, height ); - - gGL.flush(); - gGL.setColorMask(true, true); - } stop_glerror(); return success; @@ -881,9 +812,9 @@ BOOL LLTexLayerSet::renderBump( S32 x, S32 y, S32 width, S32 height ) for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) { LLTexLayer* layer = *iter; - if( layer->getRenderPass() == RP_BUMP ) + if (layer->getRenderPass() == LLTexLayer::RP_BUMP) { - success &= layer->render( x, y, width, height ); +// success &= layer->render(x, y, width, height); } } @@ -901,6 +832,16 @@ BOOL LLTexLayerSet::renderBump( S32 x, S32 y, S32 width, S32 height ) return success; } +BOOL LLTexLayerSet::isBodyRegion(const std::string& region) const +{ + return mInfo->mBodyRegion == region; +} + +const std::string LLTexLayerSet::getBodyRegion() const +{ + return mInfo->mBodyRegion; +} + void LLTexLayerSet::requestUpdate() { if( mUpdatesEnabled ) @@ -933,8 +874,9 @@ void LLTexLayerSet::createComposite() // Composite other avatars at reduced resolution if( !mAvatar->isSelf() ) { - width /= 2; - height /= 2; + // TODO: replace with sanity check to ensure not called for non-self avatars +// width /= 2; +// height /= 2; } mComposite = new LLTexLayerSetBuffer( this, width, height, mHasBump ); } @@ -967,12 +909,14 @@ LLTexLayerSetBuffer* LLTexLayerSet::getComposite() return mComposite; } -void LLTexLayerSet::gatherAlphaMasks(U8 *data, S32 width, S32 height) +void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 width, S32 height) { S32 size = width * height; memset(data, 255, width * height); + BOOL render_morph = mAvatar->morphMaskNeedsUpdate(mBakedTexIndex); + for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) { LLTexLayer* layer = *iter; @@ -981,8 +925,10 @@ void LLTexLayerSet::gatherAlphaMasks(U8 *data, S32 width, S32 height) { LLColor4 net_color; layer->findNetColor( &net_color ); + // TODO: eliminate need for layer morph mask valid flag layer->invalidateMorphMasks(); - layer->renderAlphaMasks(mComposite->getOriginX(), mComposite->getOriginY(), width, height, &net_color); + mAvatar->invalidateMorphMasks(mBakedTexIndex); + layer->renderMorphMasks(mComposite->getOriginX(), mComposite->getOriginY(), width, height, net_color, render_morph); alphaData = layer->getAlphaData(); } if (alphaData) @@ -997,35 +943,111 @@ void LLTexLayerSet::gatherAlphaMasks(U8 *data, S32 width, S32 height) } } } + + // Set alpha back to that of our alpha masks. + renderAlphaMaskTextures(width, height, true); +} + +void LLTexLayerSet::renderAlphaMaskTextures(S32 width, S32 height, bool forceClear) +{ + const LLTexLayerSetInfo *info = getInfo(); + + gGL.setColorMask(false, true); + gGL.setSceneBlendType(LLRender::BT_REPLACE); + // (Optionally) replace alpha with a single component image from a tga file. + if (!info->mStaticAlphaFileName.empty() && mMaskLayerList.empty()) + { + LLGLSNoAlphaTest gls_no_alpha_test; + gGL.flush(); + { + LLImageGL* image_gl = LLTexLayerStaticImageList::getInstance()->getImageGL(info->mStaticAlphaFileName, TRUE); + if( image_gl ) + { + LLGLSUIDefault gls_ui; + gGL.getTexUnit(0)->bind(image_gl); + gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE ); + gl_rect_2d_simple_tex( width, height ); + } + } + gGL.flush(); + } + else if (forceClear || info->mClearAlpha || (mMaskLayerList.size() > 0)) + { + // Set the alpha channel to one (clean up after previous blending) + gGL.flush(); + LLGLDisable no_alpha(GL_ALPHA_TEST); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color4f( 0.f, 0.f, 0.f, 1.f ); + + gl_rect_2d_simple( width, height ); + + gGL.flush(); + } + + // (Optional) Mask out part of the baked texture with alpha masks + // will still have an effect even if mClearAlpha is set or the alpha component was replaced + if (mMaskLayerList.size() > 0) + { + gGL.setSceneBlendType(LLRender::BT_MULT_ALPHA); + gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE ); + for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) + { + LLTexLayer* layer = *iter; + gGL.flush(); + layer->blendAlphaTexture(width, height); + gGL.flush(); + } + + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + gGL.setColorMask(true, true); + gGL.setSceneBlendType(LLRender::BT_ALPHA); } void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components) { + mAvatar->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex); +} + +//----------------------------------------------------------------------------- +// finds a specific layer based on a passed in name +//----------------------------------------------------------------------------- +LLTexLayer* LLTexLayerSet::findLayerByName(std::string name) +{ for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) { LLTexLayer* layer = *iter; - layer->applyMorphMask(tex_data, width, height, num_components); + + if (layer->getName().compare(name) == 0) + { + return layer; + } } + return NULL; } + //----------------------------------------------------------------------------- // LLTexLayerInfo //----------------------------------------------------------------------------- -LLTexLayerInfo::LLTexLayerInfo( ) - : +LLTexLayerInfo::LLTexLayerInfo() : mWriteAllChannels( FALSE ), - mRenderPass( RP_COLOR ), + mRenderPass(LLTexLayer::RP_COLOR), mFixedColor( 0.f, 0.f, 0.f, 0.f ), mLocalTexture( -1 ), mStaticImageIsMask( FALSE ), - mUseLocalTextureAlphaOnly( FALSE ) + mUseLocalTextureAlphaOnly(FALSE), + mIsVisibilityMask(FALSE) { } LLTexLayerInfo::~LLTexLayerInfo( ) { - std::for_each(mColorInfoList.begin(), mColorInfoList.end(), DeletePointer()); - std::for_each(mAlphaInfoList.begin(), mAlphaInfoList.end(), DeletePointer()); + std::for_each(mParamColorInfoList.begin(), mParamColorInfoList.end(), DeletePointer()); + std::for_each(mParamAlphaInfoList.begin(), mParamAlphaInfoList.end(), DeletePointer()); } BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) @@ -1048,7 +1070,7 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) { if( render_pass_name == "bump" ) { - mRenderPass = RP_BUMP; + mRenderPass = LLTexLayer::RP_BUMP; } } @@ -1057,6 +1079,14 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) static LLStdStringHandle global_color_string = LLXmlTree::addAttributeString("global_color"); node->getFastAttributeString( global_color_string, mGlobalColor ); + // Visibility mask (optional) + BOOL is_visibility; + static LLStdStringHandle visibility_mask_string = LLXmlTree::addAttributeString("visibility_mask"); + if (node->getFastAttributeBOOL(visibility_mask_string, is_visibility)) + { + mIsVisibilityMask = is_visibility; + } + // color attribute (optional) LLColor4U color4u; static LLStdStringHandle fixed_color_string = LLXmlTree::addAttributeString("fixed_color"); @@ -1070,7 +1100,7 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) texture_node; texture_node = node->getNextNamedChild()) { - std::string local_texture; + std::string local_texture_name; static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file"); static LLStdStringHandle local_texture_string = LLXmlTree::addAttributeString("local_texture"); static LLStdStringHandle file_is_mask_string = LLXmlTree::addAttributeString("file_is_mask"); @@ -1079,73 +1109,27 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) { texture_node->getFastAttributeBOOL( file_is_mask_string, mStaticImageIsMask ); } - else if( texture_node->getFastAttributeString( local_texture_string, local_texture ) ) + else if (texture_node->getFastAttributeString(local_texture_string, local_texture_name)) { texture_node->getFastAttributeBOOL( local_texture_alpha_only_string, mUseLocalTextureAlphaOnly ); - if( "upper_shirt" == local_texture ) + /* if ("upper_shirt" == local_texture_name) + mLocalTexture = TEX_UPPER_SHIRT; */ + mLocalTexture = TEX_NUM_INDICES; + for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + iter++) { - mLocalTexture = TEX_UPPER_SHIRT; - } - else if( "upper_bodypaint" == local_texture ) - { - mLocalTexture = TEX_UPPER_BODYPAINT; - } - else if( "lower_pants" == local_texture ) + const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + if (local_texture_name == texture_dict->mName) { - mLocalTexture = TEX_LOWER_PANTS; - } - else if( "lower_bodypaint" == local_texture ) - { - mLocalTexture = TEX_LOWER_BODYPAINT; - } - else if( "lower_shoes" == local_texture ) - { - mLocalTexture = TEX_LOWER_SHOES; - } - else if( "head_bodypaint" == local_texture ) - { - mLocalTexture = TEX_HEAD_BODYPAINT; - } - else if( "lower_socks" == local_texture ) - { - mLocalTexture = TEX_LOWER_SOCKS; - } - else if( "upper_jacket" == local_texture ) - { - mLocalTexture = TEX_UPPER_JACKET; - } - else if( "lower_jacket" == local_texture ) - { - mLocalTexture = TEX_LOWER_JACKET; - } - else if( "upper_gloves" == local_texture ) - { - mLocalTexture = TEX_UPPER_GLOVES; - } - else if( "upper_undershirt" == local_texture ) - { - mLocalTexture = TEX_UPPER_UNDERSHIRT; - } - else if( "lower_underpants" == local_texture ) - { - mLocalTexture = TEX_LOWER_UNDERPANTS; - } - else if( "eyes_iris" == local_texture ) - { - mLocalTexture = TEX_EYES_IRIS; + mLocalTexture = iter->first; + break; } - else if( "skirt" == local_texture ) - { - mLocalTexture = TEX_SKIRT; - } - else if( "hair_grain" == local_texture ) - { - mLocalTexture = TEX_HAIR; } - else + if (mLocalTexture == TEX_NUM_INDICES) { - llwarns << "<texture> element has invalid local_texure attribute: " << mName << " " << local_texture << llendl; + llwarns << "<texture> element has invalid local_texure attribute: " << mName << " " << local_texture_name << llendl; return FALSE; } } @@ -1179,13 +1163,13 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) if( child->getChildByName( "param_color" ) ) { // <param><param_color/></param> - LLTexParamColorInfo* info = new LLTexParamColorInfo( ); + LLTexLayerParamColorInfo* info = new LLTexLayerParamColorInfo(); if (!info->parseXml(child)) { delete info; return FALSE; } - mColorInfoList.push_back( info ); + mParamColorInfoList.push_back(info); } else if( child->getChildByName( "param_alpha" ) ) { @@ -1196,13 +1180,47 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) delete info; return FALSE; } - mAlphaInfoList.push_back( info ); + mParamAlphaInfoList.push_back(info); } } return TRUE; } +BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar) +{ + BOOL success = TRUE; + for (param_color_info_list_t::iterator color_info_iter = mParamColorInfoList.begin(); + color_info_iter != mParamColorInfoList.end(); + color_info_iter++) + { + LLTexLayerParamColorInfo * color_info = *color_info_iter; + LLTexLayerParamColor* param_color = new LLTexLayerParamColor(avatar); + if (!param_color->setInfo(color_info)) + { + llwarns << "NULL TexLayer Color Param could not be added to visual param list. Deleting." << llendl; + delete param_color; + success = FALSE; + } + } + + for (param_alpha_info_list_t::iterator alpha_info_iter = mParamAlphaInfoList.begin(); + alpha_info_iter != mParamAlphaInfoList.end(); + alpha_info_iter++) + { + LLTexLayerParamAlphaInfo * alpha_info = *alpha_info_iter; + LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha(avatar); + if (!param_alpha->setInfo(alpha_info)) + { + llwarns << "NULL TexLayer Alpha Param could not be added to visual param list. Deleting." << llendl; + delete param_alpha; + success = FALSE; + } + } + + return success; +} + //----------------------------------------------------------------------------- // LLTexLayer // A single texture layer, consisting of: @@ -1216,12 +1234,12 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) // * a texture entry index (TE) // * (optional) one or more alpha parameters (weighted alpha textures) //----------------------------------------------------------------------------- -LLTexLayer::LLTexLayer( LLTexLayerSet* layer_set ) - : +LLTexLayer::LLTexLayer(LLTexLayerSet* layer_set) : mTexLayerSet( layer_set ), mMorphMasksValid( FALSE ), mStaticImageInvalid( FALSE ), - mInfo( NULL ) + mInfo(NULL), + mHasMorph(FALSE) { } @@ -1238,45 +1256,28 @@ LLTexLayer::~LLTexLayer() U8* alpha_data = iter->second; delete [] alpha_data; } + } //----------------------------------------------------------------------------- // setInfo //----------------------------------------------------------------------------- -BOOL LLTexLayer::setInfo(LLTexLayerInfo* info) +BOOL LLTexLayer::setInfo(const LLTexLayerInfo* info) { llassert(mInfo == NULL); mInfo = info; //mID = info->mID; // No ID - if (info->mRenderPass == RP_BUMP) + if (info->mRenderPass == LLTexLayer::RP_BUMP) mTexLayerSet->setBump(TRUE); + mParamColorList.reserve(mInfo->mParamColorInfoList.size()); + for (param_color_info_list_t::const_iterator iter = mInfo->mParamColorInfoList.begin(); + iter != mInfo->mParamColorInfoList.end(); + iter++) { - LLTexLayerInfo::morph_name_list_t::iterator iter; - for (iter = mInfo->mMorphNameList.begin(); iter != mInfo->mMorphNameList.end(); iter++) - { - // *FIX: we assume that the referenced visual param is a - // morph target, need a better way of actually looking - // this up. - LLPolyMorphTarget *morph_param; - std::string *name = &(iter->first); - morph_param = (LLPolyMorphTarget *)(getTexLayerSet()->getAvatar()->getVisualParam(name->c_str())); - if (morph_param) - { - BOOL invert = iter->second; - addMaskedMorph(morph_param, invert); - } - } - } - - { - LLTexLayerInfo::color_info_list_t::iterator iter; - mParamColorList.reserve(mInfo->mColorInfoList.size()); - for (iter = mInfo->mColorInfoList.begin(); iter != mInfo->mColorInfoList.end(); iter++) - { - LLTexParamColor* param_color = new LLTexParamColor( this ); + LLTexLayerParamColor* param_color = new LLTexLayerParamColor(this); if (!param_color->setInfo(*iter)) { mInfo = NULL; @@ -1284,11 +1285,11 @@ BOOL LLTexLayer::setInfo(LLTexLayerInfo* info) } mParamColorList.push_back( param_color ); } - } - { - LLTexLayerInfo::alpha_info_list_t::iterator iter; - mParamAlphaList.reserve(mInfo->mAlphaInfoList.size()); - for (iter = mInfo->mAlphaInfoList.begin(); iter != mInfo->mAlphaInfoList.end(); iter++) + + mParamAlphaList.reserve(mInfo->mParamAlphaInfoList.size()); + for (param_alpha_info_list_t::const_iterator iter = mInfo->mParamAlphaInfoList.begin(); + iter != mInfo->mParamAlphaInfoList.end(); + iter++) { LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha( this ); if (!param_alpha->setInfo(*iter)) @@ -1298,84 +1299,83 @@ BOOL LLTexLayer::setInfo(LLTexLayerInfo* info) } mParamAlphaList.push_back( param_alpha ); } - } return TRUE; } -#if 0 // obsolete -//----------------------------------------------------------------------------- -// parseData -//----------------------------------------------------------------------------- -BOOL LLTexLayer::parseData( LLXmlTreeNode* node ) +//static +void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LLColor4 &net_color) { - LLTexLayerInfo *info = new LLTexLayerInfo; - - if (!info->parseXml(node)) + for (param_color_list_t::const_iterator iter = param_list.begin(); + iter != param_list.end(); iter++) +{ + const LLTexLayerParamColor* param = *iter; + LLColor4 param_net = param->getNetColor(); + const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)param->getInfo(); + switch(info->getOperation()) { - delete info; - return FALSE; + case LLTexLayerParamColor::OP_ADD: + net_color += param_net; + break; + case LLTexLayerParamColor::OP_MULTIPLY: + net_color = net_color * param_net; + break; + case LLTexLayerParamColor::OP_BLEND: + net_color = lerp(net_color, param_net, param->getWeight()); + break; + default: + llassert(0); + break; } - if (!setInfo(info)) - { - delete info; - return FALSE; } - return TRUE; + net_color.clamp(); } -#endif - -//----------------------------------------------------------------------------- - void LLTexLayer::deleteCaches() { - for( alpha_list_t::iterator iter = mParamAlphaList.begin(); + for (param_alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ ) { LLTexLayerParamAlpha* param = *iter; param->deleteCaches(); } - mStaticImageRaw = NULL; } -BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) +BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph) { LLGLEnable color_mat(GL_COLOR_MATERIAL); gPipeline.disableLights(); - BOOL success = TRUE; - - BOOL color_specified = FALSE; - BOOL alpha_mask_specified = FALSE; - LLColor4 net_color; - color_specified = findNetColor( &net_color ); - + BOOL color_specified = findNetColor(&net_color); + if (mTexLayerSet->getAvatar()->mIsDummy) { color_specified = true; net_color = LLVOAvatar::getDummyColor(); } + BOOL success = TRUE; + // If you can't see the layer, don't render it. if( is_approx_zero( net_color.mV[VW] ) ) { return success; } - alpha_list_t::iterator iter = mParamAlphaList.begin(); + BOOL alpha_mask_specified = FALSE; + param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); if( iter != mParamAlphaList.end() ) { // If we have alpha masks, but we're skipping all of them, skip the whole layer. // However, we can't do this optimization if we have morph masks that need updating. - if( mMaskedMorphs.empty() ) + if (!mHasMorph) { BOOL skip_layer = TRUE; while( iter != mParamAlphaList.end() ) { - LLTexLayerParamAlpha* param = *iter; + const LLTexLayerParamAlpha* param = *iter; if( !param->getSkip() ) { @@ -1392,7 +1392,7 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) } } - renderAlphaMasks( x, y, width, height, &net_color ); + renderMorphMasks(x, y, width, height, net_color, render_morph); alpha_mask_specified = TRUE; gGL.flush(); gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA); @@ -1437,7 +1437,7 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) if( !getInfo()->mStaticImageFileName.empty() ) { { - LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); + LLImageGL* image_gl = LLTexLayerStaticImageList::getInstance()->getImageGL(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); if( image_gl ) { gGL.getTexUnit(0)->bind(image_gl); @@ -1451,14 +1451,14 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) } } - if( ((-1 == getInfo()->mLocalTexture) || + if(((-1 == getInfo()->mLocalTexture) || getInfo()->mUseLocalTextureAlphaOnly) && getInfo()->mStaticImageFileName.empty() && color_specified ) { LLGLDisable no_alpha(GL_ALPHA_TEST); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4fv( net_color.mV); + gGL.color4fv( net_color.mV ); gl_rect_2d_simple( width, height ); } @@ -1483,9 +1483,9 @@ U8* LLTexLayer::getAlphaData() const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID((ETextureIndex)getInfo()->mLocalTexture); alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); - for( alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ ) + for (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++) { - LLTexLayerParamAlpha* param = *iter; + const LLTexLayerParamAlpha* param = *iter; F32 param_weight = param->getWeight(); alpha_mask_crc.update((U8*)¶m_weight, sizeof(F32)); } @@ -1496,7 +1496,7 @@ U8* LLTexLayer::getAlphaData() return (iter2 == mAlphaCache.end()) ? 0 : iter2->second; } -BOOL LLTexLayer::findNetColor( LLColor4* net_color ) +BOOL LLTexLayer::findNetColor(LLColor4* net_color) const { // Color is either: // * one or more color parameters (weighted colors) (which may make use of a global color or fixed color) @@ -1510,8 +1510,7 @@ BOOL LLTexLayer::findNetColor( LLColor4* net_color ) { net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getInfo()->mGlobalColor ) ); } - else - if( getInfo()->mFixedColor.mV[VW] ) + else if (getInfo()->mFixedColor.mV[VW]) { net_color->setVec( getInfo()->mFixedColor ); } @@ -1520,30 +1519,7 @@ BOOL LLTexLayer::findNetColor( LLColor4* net_color ) net_color->setVec( 0.f, 0.f, 0.f, 0.f ); } - for( color_list_t::iterator iter = mParamColorList.begin(); - iter != mParamColorList.end(); iter++ ) - { - LLTexParamColor* param = *iter; - LLColor4 param_net = param->getNetColor(); - switch( param->getOperation() ) - { - case OP_ADD: - *net_color += param_net; - break; - case OP_MULTIPLY: - net_color->mV[VX] *= param_net.mV[VX]; - net_color->mV[VY] *= param_net.mV[VY]; - net_color->mV[VZ] *= param_net.mV[VZ]; - net_color->mV[VW] *= param_net.mV[VW]; - break; - case OP_BLEND: - net_color->setVec( lerp(*net_color, param_net, param->getWeight()) ); - break; - default: - llassert(0); - break; - } - } + calculateTexLayerColor(mParamColorList, *net_color); return TRUE; } @@ -1564,8 +1540,51 @@ BOOL LLTexLayer::findNetColor( LLColor4* net_color ) return FALSE; // No need to draw a separate colored polygon } +BOOL LLTexLayer::blendAlphaTexture(S32 width, S32 height) +{ + BOOL success = TRUE; -BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4* colorp ) + gGL.flush(); + + if( !getInfo()->mStaticImageFileName.empty() ) + { + LLImageGL* image_gl = LLTexLayerStaticImageList::getInstance()->getImageGL( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); + if( image_gl ) + { + LLGLSNoAlphaTest gls_no_alpha_test; + gGL.getTexUnit(0)->bind(image_gl); + gl_rect_2d_simple_tex( width, height ); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + else + { + success = FALSE; + } + } + else + { + if (getInfo()->mLocalTexture >=0 && getInfo()->mLocalTexture < TEX_NUM_INDICES) + { + LLImageGL* image_gl = NULL; + if (mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl)) + { + if (image_gl) + { + LLGLSNoAlphaTest gls_no_alpha_test; + gGL.getTexUnit(0)->bind(image_gl); + gl_rect_2d_simple_tex( width, height ); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + success = TRUE; + } + } + } + } + + return success; +} + + +BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, BOOL render_morph) { BOOL success = TRUE; @@ -1573,9 +1592,7 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 gGL.setColorMask(false, true); - alpha_list_t::iterator iter = mParamAlphaList.begin(); - LLTexLayerParamAlpha* first_param = *iter; - + LLTexLayerParamAlpha* first_param = *mParamAlphaList.begin(); // Note: if the first param is a mulitply, multiply against the current buffer's alpha if( !first_param || !first_param->getMultiplyBlend() ) { @@ -1593,8 +1610,7 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 // Accumulate alphas LLGLSNoAlphaTest gls_no_alpha_test; gGL.color4f( 1.f, 1.f, 1.f, 1.f ); - - for( iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ ) + for (param_alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++) { LLTexLayerParamAlpha* param = *iter; success &= param->render( x, y, width, height ); @@ -1602,12 +1618,11 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 // Approximates a min() function gGL.flush(); - gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO); + gGL.setSceneBlendType(LLRender::BT_MULT_ALPHA); // Accumulate the alpha component of the texture if( getInfo()->mLocalTexture != -1 ) { - { LLImageGL* image_gl = NULL; if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) ) { @@ -1631,12 +1646,10 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 success = FALSE; } } - } if( !getInfo()->mStaticImageFileName.empty() ) { - { - LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); + LLImageGL* image_gl = LLTexLayerStaticImageList::getInstance()->getImageGL(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); if( image_gl ) { if( (image_gl->getComponents() == 4) || @@ -1653,15 +1666,14 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 success = FALSE; } } - } // Draw a rectangle with the layer color to multiply the alpha by that color's alpha. // Note: we're still using gGL.blendFunc( GL_DST_ALPHA, GL_ZERO ); - if( colorp->mV[VW] != 1.f ) + if (layer_color.mV[VW] != 1.f) { LLGLDisable no_alpha(GL_ALPHA_TEST); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4fv( colorp->mV ); + gGL.color4fv(layer_color.mV); gl_rect_2d_simple( width, height ); } @@ -1670,34 +1682,28 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 gGL.setColorMask(true, true); - if (!mMorphMasksValid && !mMaskedMorphs.empty()) + if (render_morph && mHasMorph) { LLCRC alpha_mask_crc; const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID((ETextureIndex)getInfo()->mLocalTexture); alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); - for( alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ ) + for (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++) { - LLTexLayerParamAlpha* param = *iter; + const LLTexLayerParamAlpha* param = *iter; F32 param_weight = param->getWeight(); alpha_mask_crc.update((U8*)¶m_weight, sizeof(F32)); } U32 cache_index = alpha_mask_crc.getCRC(); - - alpha_cache_t::iterator iter2 = mAlphaCache.find(cache_index); - U8* alpha_data; - if (iter2 != mAlphaCache.end()) - { - alpha_data = iter2->second; - } - else + U8* alpha_data = get_if_there(mAlphaCache,cache_index,(U8*)NULL); + if (!alpha_data) { // clear out a slot if we have filled our cache S32 max_cache_entries = getTexLayerSet()->getAvatar()->isSelf() ? 4 : 1; while ((S32)mAlphaCache.size() >= max_cache_entries) { - iter2 = mAlphaCache.begin(); // arbitrarily grab the first entry + alpha_cache_t::iterator iter2 = mAlphaCache.begin(); // arbitrarily grab the first entry alpha_data = iter2->second; delete [] alpha_data; mAlphaCache.erase(iter2); @@ -1710,28 +1716,12 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 getTexLayerSet()->getAvatar()->dirtyMesh(); mMorphMasksValid = TRUE; - - for( morph_list_t::iterator iter3 = mMaskedMorphs.begin(); - iter3 != mMaskedMorphs.end(); iter3++ ) - { - LLMaskedMorph* maskedMorph = &(*iter3); - maskedMorph->mMorphTarget->applyMask(alpha_data, width, height, 1, maskedMorph->mInvert); - } + getTexLayerSet()->applyMorphMask(alpha_data, width, height, 1); } return success; } -void LLTexLayer::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components) -{ - for( morph_list_t::iterator iter = mMaskedMorphs.begin(); - iter != mMaskedMorphs.end(); iter++ ) - { - LLMaskedMorph* maskedMorph = &(*iter); - maskedMorph->mMorphTarget->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert); - } -} - // Returns TRUE on success. BOOL LLTexLayer::renderImageRaw( U8* in_data, S32 in_width, S32 in_height, S32 in_components, S32 width, S32 height, BOOL is_mask ) { @@ -1808,666 +1798,54 @@ void LLTexLayer::requestUpdate() mTexLayerSet->requestUpdate(); } -void LLTexLayer::addMaskedMorph(LLPolyMorphTarget* morph_target, BOOL invert) +const std::string& LLTexLayer::getName() const { - mMaskedMorphs.push_front(LLMaskedMorph(morph_target, invert)); -} - -void LLTexLayer::invalidateMorphMasks() -{ - mMorphMasksValid = FALSE; -} - -//----------------------------------------------------------------------------- -// LLTexLayerParamAlphaInfo -//----------------------------------------------------------------------------- -LLTexLayerParamAlphaInfo::LLTexLayerParamAlphaInfo( ) - : - mMultiplyBlend( FALSE ), - mSkipIfZeroWeight( FALSE ), - mDomain( 0.f ) -{ -} - -BOOL LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node) -{ - llassert( node->hasName( "param" ) && node->getChildByName( "param_alpha" ) ); - - if( !LLViewerVisualParamInfo::parseXml(node) ) - return FALSE; - - LLXmlTreeNode* param_alpha_node = node->getChildByName( "param_alpha" ); - if( !param_alpha_node ) - { - return FALSE; - } - - static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file"); - if( param_alpha_node->getFastAttributeString( tga_file_string, mStaticImageFileName ) ) - { - // Don't load the image file until it's actually needed. - } -// else -// { -// llwarns << "<param_alpha> element is missing tga_file attribute." << llendl; -// } - - static LLStdStringHandle multiply_blend_string = LLXmlTree::addAttributeString("multiply_blend"); - param_alpha_node->getFastAttributeBOOL( multiply_blend_string, mMultiplyBlend ); - - static LLStdStringHandle skip_if_zero_string = LLXmlTree::addAttributeString("skip_if_zero"); - param_alpha_node->getFastAttributeBOOL( skip_if_zero_string, mSkipIfZeroWeight ); - - static LLStdStringHandle domain_string = LLXmlTree::addAttributeString("domain"); - param_alpha_node->getFastAttributeF32( domain_string, mDomain ); - - return TRUE; -} - -//----------------------------------------------------------------------------- -// LLTexLayerParamAlpha -//----------------------------------------------------------------------------- - -// static -LLTexLayerParamAlpha::param_alpha_ptr_list_t LLTexLayerParamAlpha::sInstances; - -// static -void LLTexLayerParamAlpha::dumpCacheByteCount() -{ - S32 gl_bytes = 0; - getCacheByteCount( &gl_bytes ); - llinfos << "Processed Alpha Texture Cache GL:" << (gl_bytes/1024) << "KB" << llendl; -} - -// static -void LLTexLayerParamAlpha::getCacheByteCount( S32* gl_bytes ) -{ - *gl_bytes = 0; - - for( param_alpha_ptr_list_t::iterator iter = sInstances.begin(); - iter != sInstances.end(); iter++ ) - { - LLTexLayerParamAlpha* instance = *iter; - LLImageGL* image_gl = instance->mCachedProcessedImageGL; - if( image_gl ) - { - S32 bytes = (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents(); - - if( image_gl->getHasGLTexture() ) - { - *gl_bytes += bytes; - } - } - } -} - -LLTexLayerParamAlpha::LLTexLayerParamAlpha( LLTexLayer* layer ) - : - mCachedProcessedImageGL( NULL ), - mTexLayer( layer ), - mNeedsCreateTexture( FALSE ), - mStaticImageInvalid( FALSE ), - mAvgDistortionVec(1.f, 1.f, 1.f), - mCachedEffectiveWeight(0.f) -{ - sInstances.push_front( this ); -} - -LLTexLayerParamAlpha::~LLTexLayerParamAlpha() -{ - deleteCaches(); - sInstances.remove( this ); -} - -//----------------------------------------------------------------------------- -// setInfo() -//----------------------------------------------------------------------------- -BOOL LLTexLayerParamAlpha::setInfo(LLTexLayerParamAlphaInfo *info) -{ - llassert(mInfo == NULL); - if (info->mID < 0) - return FALSE; - mInfo = info; - mID = info->mID; - - mTexLayer->getTexLayerSet()->getAvatar()->addVisualParam( this ); - setWeight(getDefaultWeight(), FALSE ); - - return TRUE; -} - -//----------------------------------------------------------------------------- - -void LLTexLayerParamAlpha::deleteCaches() -{ - mStaticImageTGA = NULL; // deletes image - mCachedProcessedImageGL = NULL; - mStaticImageRaw = NULL; - mNeedsCreateTexture = FALSE; -} - -void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL set_by_user) -{ - if (mIsAnimating) - { - return; - } - F32 min_weight = getMinWeight(); - F32 max_weight = getMaxWeight(); - F32 new_weight = llclamp(weight, min_weight, max_weight); - U8 cur_u8 = F32_to_U8( mCurWeight, min_weight, max_weight ); - U8 new_u8 = F32_to_U8( new_weight, min_weight, max_weight ); - if( cur_u8 != new_u8) - { - mCurWeight = new_weight; - - LLVOAvatar* avatar = mTexLayer->getTexLayerSet()->getAvatar(); - if( avatar->getSex() & getSex() ) - { - if ( gAgent.cameraCustomizeAvatar() ) - { - set_by_user = FALSE; - } - avatar->invalidateComposite( mTexLayer->getTexLayerSet(), set_by_user ); - mTexLayer->invalidateMorphMasks(); - avatar->updateMeshTextures(); - } - } -} - -void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL set_by_user) -{ - mTargetWeight = target_value; - setWeight(target_value, set_by_user); - mIsAnimating = TRUE; - if (mNext) - { - mNext->setAnimationTarget(target_value, set_by_user); - } -} - -void LLTexLayerParamAlpha::animate(F32 delta, BOOL set_by_user) -{ - if (mNext) - { - mNext->animate(delta, set_by_user); - } -} - -BOOL LLTexLayerParamAlpha::getSkip() -{ - LLVOAvatar *avatar = mTexLayer->getTexLayerSet()->getAvatar(); - - if( getInfo()->mSkipIfZeroWeight ) - { - F32 effective_weight = ( avatar->getSex() & getSex() ) ? mCurWeight : getDefaultWeight(); - if (is_approx_zero( effective_weight )) - { - return TRUE; - } - } - - EWearableType type = (EWearableType)getWearableType(); - if( (type != WT_INVALID) && !avatar->isWearingWearableType( type ) ) - { - return TRUE; - } - - return FALSE; -} - - -BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height ) -{ - BOOL success = TRUE; - - F32 effective_weight = ( mTexLayer->getTexLayerSet()->getAvatar()->getSex() & getSex() ) ? mCurWeight : getDefaultWeight(); - BOOL weight_changed = effective_weight != mCachedEffectiveWeight; - if( getSkip() ) - { - return success; - } - - gGL.flush(); - if( getInfo()->mMultiplyBlend ) - { - gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO); // Multiplication: approximates a min() function - } - else - { - gGL.setSceneBlendType(LLRender::BT_ADD); // Addition: approximates a max() function - } - - if( !getInfo()->mStaticImageFileName.empty() && !mStaticImageInvalid) - { - if( mStaticImageTGA.isNull() ) - { - // Don't load the image file until we actually need it the first time. Like now. - mStaticImageTGA = gTexStaticImageList.getImageTGA( getInfo()->mStaticImageFileName ); - // We now have something in one of our caches - LLTexLayerSet::sHasCaches |= mStaticImageTGA.notNull() ? TRUE : FALSE; - - if( mStaticImageTGA.isNull() ) - { - llwarns << "Unable to load static file: " << getInfo()->mStaticImageFileName << llendl; - mStaticImageInvalid = TRUE; // don't try again. - return FALSE; - } - } - - const S32 image_tga_width = mStaticImageTGA->getWidth(); - const S32 image_tga_height = mStaticImageTGA->getHeight(); - if( !mCachedProcessedImageGL || - (mCachedProcessedImageGL->getWidth() != image_tga_width) || - (mCachedProcessedImageGL->getHeight() != image_tga_height) || - (weight_changed) ) - { -// llinfos << "Building Cached Alpha: " << mName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << effective_weight << llendl; - mCachedEffectiveWeight = effective_weight; - - if( !mCachedProcessedImageGL ) - { - mCachedProcessedImageGL = new LLImageGL( image_tga_width, image_tga_height, 1, FALSE); - - // We now have something in one of our caches - LLTexLayerSet::sHasCaches |= mCachedProcessedImageGL ? TRUE : FALSE; - - mCachedProcessedImageGL->setExplicitFormat( GL_ALPHA8, GL_ALPHA ); - } - - // Applies domain and effective weight to data as it is decoded. Also resizes the raw image if needed. - mStaticImageRaw = NULL; - mStaticImageRaw = new LLImageRaw; - mStaticImageTGA->decodeAndProcess( mStaticImageRaw, getInfo()->mDomain, effective_weight ); - mNeedsCreateTexture = TRUE; - } - - if( mCachedProcessedImageGL ) - { - { - // Create the GL texture, and then hang onto it for future use. - if( mNeedsCreateTexture ) - { - mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw); - mNeedsCreateTexture = FALSE; - gGL.getTexUnit(0)->bind(mCachedProcessedImageGL); - mCachedProcessedImageGL->setAddressMode(LLTexUnit::TAM_CLAMP); - } - - LLGLSNoAlphaTest gls_no_alpha_test; - gGL.getTexUnit(0)->bind(mCachedProcessedImageGL); - gl_rect_2d_simple_tex( width, height ); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - stop_glerror(); - } - } - - // Don't keep the cache for other people's avatars - // (It's not really a "cache" in that case, but the logic is the same) - if( !mTexLayer->getTexLayerSet()->getAvatar()->isSelf() ) - { - mCachedProcessedImageGL = NULL; - } - } - else - { - LLGLDisable no_alpha(GL_ALPHA_TEST); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4f( 0.f, 0.f, 0.f, effective_weight ); - gl_rect_2d_simple( width, height ); - } - - return success; -} - -//----------------------------------------------------------------------------- -// LLTexGlobalColorInfo -//----------------------------------------------------------------------------- - -LLTexGlobalColorInfo::LLTexGlobalColorInfo() -{ -} - - -LLTexGlobalColorInfo::~LLTexGlobalColorInfo() -{ - for_each(mColorInfoList.begin(), mColorInfoList.end(), DeletePointer()); -} - -BOOL LLTexGlobalColorInfo::parseXml(LLXmlTreeNode* node) -{ - // name attribute - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if( !node->getFastAttributeString( name_string, mName ) ) - { - llwarns << "<global_color> element is missing name attribute." << llendl; - return FALSE; - } - // <param> sub-element - for (LLXmlTreeNode* child = node->getChildByName( "param" ); - child; - child = node->getNextNamedChild()) - { - if( child->getChildByName( "param_color" ) ) - { - // <param><param_color/></param> - LLTexParamColorInfo* info = new LLTexParamColorInfo(); - if (!info->parseXml(child)) - { - delete info; - return FALSE; - } - mColorInfoList.push_back( info ); - } - } - return TRUE; -} - -//----------------------------------------------------------------------------- -// LLTexGlobalColor -//----------------------------------------------------------------------------- - -LLTexGlobalColor::LLTexGlobalColor( LLVOAvatar* avatar ) - : - mAvatar( avatar ), - mInfo( NULL ) -{ -} - - -LLTexGlobalColor::~LLTexGlobalColor() -{ - // mParamList are LLViewerVisualParam's and get deleted with ~LLCharacter() - //std::for_each(mParamList.begin(), mParamList.end(), DeletePointer()); -} - -BOOL LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info) -{ - llassert(mInfo == NULL); - mInfo = info; - //mID = info->mID; // No ID - - LLTexGlobalColorInfo::color_info_list_t::iterator iter; - mParamList.reserve(mInfo->mColorInfoList.size()); - for (iter = mInfo->mColorInfoList.begin(); iter != mInfo->mColorInfoList.end(); iter++) - { - LLTexParamColor* param_color = new LLTexParamColor( this ); - if (!param_color->setInfo(*iter)) - { - mInfo = NULL; - return FALSE; - } - mParamList.push_back( param_color ); - } - - return TRUE; + return mInfo->mName; } -//----------------------------------------------------------------------------- - -LLColor4 LLTexGlobalColor::getColor() +LLTexLayer::ERenderPass LLTexLayer::getRenderPass() const { - // Sum of color params - if( !mParamList.empty() ) - { - LLColor4 net_color( 0.f, 0.f, 0.f, 0.f ); - - for( param_list_t::iterator iter = mParamList.begin(); - iter != mParamList.end(); iter++ ) - { - LLTexParamColor* param = *iter; - LLColor4 param_net = param->getNetColor(); - switch( param->getOperation() ) - { - case OP_ADD: - net_color += param_net; - break; - case OP_MULTIPLY: - net_color.mV[VX] *= param_net.mV[VX]; - net_color.mV[VY] *= param_net.mV[VY]; - net_color.mV[VZ] *= param_net.mV[VZ]; - net_color.mV[VW] *= param_net.mV[VW]; - break; - case OP_BLEND: - net_color = lerp(net_color, param_net, param->getWeight()); - break; - default: - llassert(0); - break; - } - } - - net_color.mV[VX] = llclampf( net_color.mV[VX] ); - net_color.mV[VY] = llclampf( net_color.mV[VY] ); - net_color.mV[VZ] = llclampf( net_color.mV[VZ] ); - net_color.mV[VW] = llclampf( net_color.mV[VW] ); - - return net_color; - } - return LLColor4( 1.f, 1.f, 1.f, 1.f ); + return mInfo->mRenderPass; } - -//----------------------------------------------------------------------------- -// LLTexParamColorInfo -//----------------------------------------------------------------------------- -LLTexParamColorInfo::LLTexParamColorInfo() - : - mOperation( OP_ADD ), - mNumColors( 0 ) +const std::string& LLTexLayer::getGlobalColor() const { + return mInfo->mGlobalColor; } -BOOL LLTexParamColorInfo::parseXml(LLXmlTreeNode *node) +void LLTexLayer::invalidateMorphMasks() { - llassert( node->hasName( "param" ) && node->getChildByName( "param_color" ) ); - - if (!LLViewerVisualParamInfo::parseXml(node)) - return FALSE; - - LLXmlTreeNode* param_color_node = node->getChildByName( "param_color" ); - if( !param_color_node ) - { - return FALSE; - } - - std::string op_string; - static LLStdStringHandle operation_string = LLXmlTree::addAttributeString("operation"); - if( param_color_node->getFastAttributeString( operation_string, op_string ) ) - { - LLStringUtil::toLower(op_string); - if ( op_string == "add" ) mOperation = OP_ADD; - else if ( op_string == "multiply" ) mOperation = OP_MULTIPLY; - else if ( op_string == "blend" ) mOperation = OP_BLEND; - } - - mNumColors = 0; - - LLColor4U color4u; - for (LLXmlTreeNode* child = param_color_node->getChildByName( "value" ); - child; - child = param_color_node->getNextNamedChild()) - { - if( (mNumColors < MAX_COLOR_VALUES) ) - { - static LLStdStringHandle color_string = LLXmlTree::addAttributeString("color"); - if( child->getFastAttributeColor4U( color_string, color4u ) ) - { - mColors[ mNumColors ].setVec(color4u); - mNumColors++; - } - } - } - if( !mNumColors ) - { - llwarns << "<param_color> is missing <value> sub-elements" << llendl; - return FALSE; + mMorphMasksValid = FALSE; } - if( (mOperation == OP_BLEND) && (mNumColors != 1) ) +BOOL LLTexLayer::isVisibilityMask() const { - llwarns << "<param_color> with operation\"blend\" must have exactly one <value>" << llendl; - return FALSE; - } - - return TRUE; + return mInfo->mIsVisibilityMask; } //----------------------------------------------------------------------------- -// LLTexParamColor +// LLTexLayerStaticImageList //----------------------------------------------------------------------------- -LLTexParamColor::LLTexParamColor( LLTexGlobalColor* tex_global_color ) - : - mAvgDistortionVec(1.f, 1.f, 1.f), - mTexGlobalColor( tex_global_color ), - mTexLayer( NULL ), - mAvatar( tex_global_color->getAvatar() ) -{ -} -LLTexParamColor::LLTexParamColor( LLTexLayer* layer ) - : - mAvgDistortionVec(1.f, 1.f, 1.f), - mTexGlobalColor( NULL ), - mTexLayer( layer ), - mAvatar( layer->getTexLayerSet()->getAvatar() ) +LLTexLayerStaticImageList::LLTexLayerStaticImageList() : + mGLBytes(0), + mTGABytes(0), + mImageNames(16384) { } - -LLTexParamColor::~LLTexParamColor() -{ -} - -//----------------------------------------------------------------------------- -// setInfo() -//----------------------------------------------------------------------------- - -BOOL LLTexParamColor::setInfo(LLTexParamColorInfo *info) -{ - llassert(mInfo == NULL); - if (info->mID < 0) - return FALSE; - mID = info->mID; - mInfo = info; - - mAvatar->addVisualParam( this ); - setWeight( getDefaultWeight(), FALSE ); - - return TRUE; -} - -LLColor4 LLTexParamColor::getNetColor() -{ - llassert( getInfo()->mNumColors >= 1 ); - - F32 effective_weight = ( mAvatar && (mAvatar->getSex() & getSex()) ) ? mCurWeight : getDefaultWeight(); - - S32 index_last = getInfo()->mNumColors - 1; - F32 scaled_weight = effective_weight * index_last; - S32 index_start = (S32) scaled_weight; - S32 index_end = index_start + 1; - if( index_start == index_last ) - { - return getInfo()->mColors[index_last]; - } - else - { - F32 weight = scaled_weight - index_start; - const LLColor4 *start = &getInfo()->mColors[ index_start ]; - const LLColor4 *end = &getInfo()->mColors[ index_end ]; - return LLColor4( - (1.f - weight) * start->mV[VX] + weight * end->mV[VX], - (1.f - weight) * start->mV[VY] + weight * end->mV[VY], - (1.f - weight) * start->mV[VZ] + weight * end->mV[VZ], - (1.f - weight) * start->mV[VW] + weight * end->mV[VW] ); - } -} - -void LLTexParamColor::setWeight(F32 weight, BOOL set_by_user) -{ - if (mIsAnimating) - { - return; - } - F32 min_weight = getMinWeight(); - F32 max_weight = getMaxWeight(); - F32 new_weight = llclamp(weight, min_weight, max_weight); - U8 cur_u8 = F32_to_U8( mCurWeight, min_weight, max_weight ); - U8 new_u8 = F32_to_U8( new_weight, min_weight, max_weight ); - if( cur_u8 != new_u8) - { - mCurWeight = new_weight; - - if( getInfo()->mNumColors <= 0 ) - { - // This will happen when we set the default weight the first time. - return; - } - - if( mAvatar->getSex() & getSex() ) - { - if( mTexGlobalColor ) - { - mAvatar->onGlobalColorChanged( mTexGlobalColor, set_by_user ); - } - else - if( mTexLayer ) - { - mAvatar->invalidateComposite( mTexLayer->getTexLayerSet(), set_by_user ); - } - } -// llinfos << "param " << mName << " = " << new_weight << llendl; - } -} - -void LLTexParamColor::setAnimationTarget(F32 target_value, BOOL set_by_user) -{ - // set value first then set interpolating flag to ignore further updates - mTargetWeight = target_value; - setWeight(target_value, set_by_user); - mIsAnimating = TRUE; - if (mNext) - { - mNext->setAnimationTarget(target_value, set_by_user); - } -} - -void LLTexParamColor::animate(F32 delta, BOOL set_by_user) -{ - if (mNext) - { - mNext->animate(delta, set_by_user); - } -} - - -//----------------------------------------------------------------------------- -// LLTexStaticImageList -//----------------------------------------------------------------------------- - -// static -LLTexStaticImageList gTexStaticImageList; -LLStringTable LLTexStaticImageList::sImageNames(16384); - -LLTexStaticImageList::LLTexStaticImageList() - : - mGLBytes( 0 ), - mTGABytes( 0 ) -{} - -LLTexStaticImageList::~LLTexStaticImageList() +LLTexLayerStaticImageList::~LLTexLayerStaticImageList() { deleteCachedImages(); } -void LLTexStaticImageList::dumpByteCount() +void LLTexLayerStaticImageList::dumpByteCount() { llinfos << "Avatar Static Textures " << "KB GL:" << (mGLBytes / 1024) << "KB TGA:" << (mTGABytes / 1024) << "KB" << llendl; } -void LLTexStaticImageList::deleteCachedImages() +void LLTexLayerStaticImageList::deleteCachedImages() { if( mGLBytes || mTGABytes ) { @@ -2491,10 +1869,10 @@ void LLTexStaticImageList::deleteCachedImages() // Returns an LLImageTGA that contains the encoded data from a tga file named file_name. // Caches the result to speed identical subsequent requests. -LLImageTGA* LLTexStaticImageList::getImageTGA(const std::string& file_name) +LLImageTGA* LLTexLayerStaticImageList::getImageTGA(const std::string& file_name) { - const char *namekey = sImageNames.addString(file_name); - image_tga_map_t::iterator iter = mStaticImageListTGA.find(namekey); + const char *namekey = mImageNames.addString(file_name); + image_tga_map_t::const_iterator iter = mStaticImageListTGA.find(namekey); if( iter != mStaticImageListTGA.end() ) { return iter->second; @@ -2517,16 +1895,14 @@ LLImageTGA* LLTexStaticImageList::getImageTGA(const std::string& file_name) } } - - // Returns a GL Image (without a backing ImageRaw) that contains the decoded data from a tga file named file_name. // Caches the result to speed identical subsequent requests. -LLImageGL* LLTexStaticImageList::getImageGL(const std::string& file_name, BOOL is_mask ) +LLImageGL* LLTexLayerStaticImageList::getImageGL(const std::string& file_name, BOOL is_mask) { LLPointer<LLImageGL> image_gl; - const char *namekey = sImageNames.addString(file_name); + const char *namekey = mImageNames.addString(file_name); - image_gl_map_t::iterator iter = mStaticImageListGL.find(namekey); + image_gl_map_t::const_iterator iter = mStaticImageListGL.find(namekey); if( iter != mStaticImageListGL.end() ) { image_gl = iter->second; @@ -2562,7 +1938,7 @@ LLImageGL* LLTexStaticImageList::getImageGL(const std::string& file_name, BOOL i // Reads a .tga file, decodes it, and puts the decoded data in image_raw. // Returns TRUE if successful. -BOOL LLTexStaticImageList::loadImageRaw( const std::string& file_name, LLImageRaw* image_raw ) +BOOL LLTexLayerStaticImageList::loadImageRaw(const std::string& file_name, LLImageRaw* image_raw) { BOOL success = FALSE; std::string path; @@ -2577,11 +1953,4 @@ BOOL LLTexStaticImageList::loadImageRaw( const std::string& file_name, LLImageRa return success; } -//----------------------------------------------------------------------------- -// LLMaskedMorph() -//----------------------------------------------------------------------------- -LLMaskedMorph::LLMaskedMorph( LLPolyMorphTarget *morph_target, BOOL invert ) : mMorphTarget(morph_target), mInvert(invert) -{ - morph_target->addPendingMorphMask(); -} |