From 4d68dc7c575fb74021f3872eb71a08e93eb6a019 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 25 Oct 2011 16:50:39 -0500 Subject: [PATCH] LLTexLayer refactored. Tried to keep behavior changes as minimal as possible. Consider as base slate for changes required for multi-wearables. --- indra/newview/CMakeLists.txt | 4 + indra/newview/llassetuploadresponders.h | 2 +- indra/newview/lltexglobalcolor.cpp | 145 ++ indra/newview/lltexglobalcolor.h | 83 + indra/newview/lltexlayer.cpp | 1936 ++++++++--------------- indra/newview/lltexlayer.h | 686 +++----- indra/newview/lltexlayerparams.cpp | 20 +- indra/newview/lltexlayerparams.h | 187 +++ indra/newview/llviewerstats.cpp | 3 +- indra/newview/llviewervisualparam.cpp | 8 +- indra/newview/llviewervisualparam.h | 2 +- indra/newview/llvoavatar.cpp | 2 +- indra/newview/llvoavatar.h | 1 + 13 files changed, 1324 insertions(+), 1755 deletions(-) create mode 100644 indra/newview/lltexglobalcolor.cpp create mode 100644 indra/newview/lltexglobalcolor.h create mode 100644 indra/newview/lltexlayerparams.h diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index ce601470f..b9816f240 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -386,7 +386,9 @@ set(viewer_SOURCE_FILES llstylemap.cpp llsurface.cpp llsurfacepatch.cpp + lltexglobalcolor.cpp lltexlayer.cpp + lltexlayerparams.cpp lltexturecache.cpp lltexturectrl.cpp lltexturefetch.cpp @@ -873,7 +875,9 @@ set(viewer_HEADER_FILES llsurface.h llsurfacepatch.h lltable.h + lltexglobalcolor.h lltexlayer.h + lltexlayerparams.h lltexturecache.h lltexturectrl.h lltexturefetch.h diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index c08f2999f..17d8f1a13 100644 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -71,7 +71,7 @@ public: virtual void uploadComplete(const LLSD& content); }; -class LLBakedUploadData; +struct LLBakedUploadData; class LLSendTexLayerResponder : public LLAssetUploadResponder { public: diff --git a/indra/newview/lltexglobalcolor.cpp b/indra/newview/lltexglobalcolor.cpp new file mode 100644 index 000000000..5704aa6ec --- /dev/null +++ b/indra/newview/lltexglobalcolor.cpp @@ -0,0 +1,145 @@ +/** + * @file lltexlayerglobalcolor.cpp + * @brief Color for texture layers. + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llagent.h" +#include "lltexlayer.h" +#include "llvoavatar.h" +#include "llwearable.h" +#include "lltexglobalcolor.h" + +//----------------------------------------------------------------------------- +// LLTexGlobalColor +//----------------------------------------------------------------------------- + +LLTexGlobalColor::LLTexGlobalColor(LLVOAvatar* avatar) + : + mAvatar(avatar), + mInfo(NULL) +{ +} + +LLTexGlobalColor::~LLTexGlobalColor() +{ + // mParamColorList are LLViewerVisualParam's and get deleted with ~LLCharacter() + //std::for_each(mParamColorList.begin(), mParamColorList.end(), DeletePointer()); +} + +BOOL LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info) +{ + llassert(mInfo == NULL); + mInfo = info; + //mID = info->mID; // No ID + + mParamGlobalColorList.reserve(mInfo->mParamColorInfoList.size()); + for (param_color_info_list_t::iterator iter = mInfo->mParamColorInfoList.begin(); + iter != mInfo->mParamColorInfoList.end(); + iter++) + { + LLTexParamGlobalColor* param_color = new LLTexParamGlobalColor(this); + if (!param_color->setInfo(*iter, TRUE)) + { + mInfo = NULL; + return FALSE; + } + mParamGlobalColorList.push_back(param_color); + } + + return TRUE; +} + +LLColor4 LLTexGlobalColor::getColor() const +{ + // Sum of color params + if (mParamGlobalColorList.empty()) + return LLColor4(1.f, 1.f, 1.f, 1.f); + + LLColor4 net_color(0.f, 0.f, 0.f, 0.f); + LLTexLayer::calculateTexLayerColor(mParamGlobalColorList, net_color); + return net_color; +} + +const std::string& LLTexGlobalColor::getName() const +{ + return mInfo->mName; +} + +//----------------------------------------------------------------------------- +// LLTexParamGlobalColor +//----------------------------------------------------------------------------- +LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color) : + LLTexLayerParamColor(tex_global_color->getAvatar()), + mTexGlobalColor(tex_global_color) +{ +} + +void LLTexParamGlobalColor::onGlobalColorChanged(bool upload_bake) +{ + mAvatar->onGlobalColorChanged(mTexGlobalColor, upload_bake); +} + +//----------------------------------------------------------------------------- +// LLTexGlobalColorInfo +//----------------------------------------------------------------------------- + +LLTexGlobalColorInfo::LLTexGlobalColorInfo() +{ +} + + +LLTexGlobalColorInfo::~LLTexGlobalColorInfo() +{ + for_each(mParamColorInfoList.begin(), mParamColorInfoList.end(), DeletePointer()); +} + +BOOL LLTexGlobalColorInfo::parseXml(LLXmlTreeNode* node) +{ + // name attribute + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (!node->getFastAttributeString(name_string, mName)) + { + llwarns << " element is missing name attribute." << llendl; + return FALSE; + } + // sub-element + for (LLXmlTreeNode* child = node->getChildByName("param"); + child; + child = node->getNextNamedChild()) + { + if (child->getChildByName("param_color")) + { + // + LLTexLayerParamColorInfo* info = new LLTexLayerParamColorInfo(); + if (!info->parseXml(child)) + { + delete info; + return FALSE; + } + mParamColorInfoList.push_back(info); + } + } + return TRUE; +} diff --git a/indra/newview/lltexglobalcolor.h b/indra/newview/lltexglobalcolor.h new file mode 100644 index 000000000..c01187a89 --- /dev/null +++ b/indra/newview/lltexglobalcolor.h @@ -0,0 +1,83 @@ +/** + * @file lltexglobalcolor.h + * @brief This is global texture color info used by llvoavatar. + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLTEXGLOBALCOLOR_H +#define LL_LLTEXGLOBALCOLOR_H + +#include "lltexlayer.h" +#include "lltexlayerparams.h" + +class LLVOAvatar; +class LLWearable; +class LLTexGlobalColorInfo; + +class LLTexGlobalColor +{ +public: + LLTexGlobalColor( LLVOAvatar* avatar ); + ~LLTexGlobalColor(); + + LLTexGlobalColorInfo* getInfo() const { return mInfo; } + // This sets mInfo and calls initialization functions + BOOL setInfo(LLTexGlobalColorInfo *info); + + LLVOAvatar* getAvatar() const { return mAvatar; } + LLColor4 getColor() const; + const std::string& getName() const; + +private: + param_color_list_t mParamGlobalColorList; + LLVOAvatar* mAvatar; // just backlink, don't LLPointer + LLTexGlobalColorInfo *mInfo; +}; + +// Used by llvoavatar to determine skin/eye/hair color. +class LLTexGlobalColorInfo +{ + friend class LLTexGlobalColor; +public: + LLTexGlobalColorInfo(); + ~LLTexGlobalColorInfo(); + + BOOL parseXml(LLXmlTreeNode* node); + +private: + param_color_info_list_t mParamColorInfoList; + std::string mName; +}; + +class LLTexParamGlobalColor : public LLTexLayerParamColor +{ +public: + LLTexParamGlobalColor(LLTexGlobalColor *tex_color); + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; +protected: + /*virtual*/ void onGlobalColorChanged(bool upload_bake); +private: + LLTexGlobalColor* mTexGlobalColor; +}; + +#endif diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index 0dd7614ba..0dfda5110 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -32,6 +32,8 @@ #include "llviewerprecompiledheaders.h" +#include "lltexlayer.h" + #include "imageids.h" #include "llagent.h" #include "llagentcamera.h" @@ -44,7 +46,6 @@ #include "llimagetga.h" #include "llpolymorph.h" #include "llquantize.h" -#include "lltexlayer.h" #include "llui.h" #include "llvfile.h" #include "llviewertexturelist.h" @@ -58,6 +59,7 @@ #include "v4coloru.h" #include "llrender.h" #include "llassetuploadresponders.h" +#include "lltexlayerparams.h" //#include "../tools/imdebug/imdebug.h" @@ -65,46 +67,73 @@ using namespace LLVOAvatarDefines; const S32 MAX_BAKE_UPLOAD_ATTEMPTS = 4; -// static -S32 LLTexLayerSetBuffer::sGLByteCount = 0; +class LLTexLayerInfo +{ + friend class LLTexLayer; + friend class LLTexLayerInterface; +public: + LLTexLayerInfo(); + ~LLTexLayerInfo(); + + BOOL parseXml(LLXmlTreeNode* node); + BOOL isUserSettable() { return mLocalTexture != -1; } + S32 getLocalTexture() const { return mLocalTexture; } + BOOL getOnlyAlpha() const { return mUseLocalTextureAlphaOnly; } + std::string getName() const { return mName; } + +private: + std::string mName; + + BOOL mWriteAllChannels; // Don't use masking. Just write RGBA into buffer, + LLTexLayerInterface::ERenderPass mRenderPass; + + std::string mGlobalColor; + LLColor4 mFixedColor; + + S32 mLocalTexture; + std::string mStaticImageFileName; + BOOL mStaticImageIsMask; + BOOL mUseLocalTextureAlphaOnly; // Ignore RGB channels from the input texture. Use alpha as a mask + BOOL mIsVisibilityMask; + + typedef std::vector< std::pair< std::string,BOOL > > morph_name_list_t; + morph_name_list_t mMorphNameList; + param_color_info_list_t mParamColorInfoList; + param_alpha_info_list_t mParamAlphaInfoList; +}; //----------------------------------------------------------------------------- // LLBakedUploadData() //----------------------------------------------------------------------------- -LLBakedUploadData::LLBakedUploadData( LLVOAvatarSelf* avatar, - LLTexLayerSet* layerset, - LLTexLayerSetBuffer* layerset_buffer, +LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar, + LLTexLayerSet* layerset, const LLUUID & id ) : - mAvatar( avatar ), - mTexLayerSet( layerset ), - mLayerSetBuffer( layerset_buffer ), - mID(id) -{ - mStartTime = LLFrameTimer::getTotalTime(); // Record starting time - for( S32 i = 0; i < LLWearableType::WT_COUNT; i++ ) - { - LLWearable* wearable = gAgentWearables.getWearable( (LLWearableType::EType)i); - if( wearable ) - { - mWearableAssets[i] = wearable->getAssetID(); - } - } + mAvatar(avatar), + mTexLayerSet(layerset), + mID(id), + mStartTime(LLFrameTimer::getTotalTime()) // Record starting time +{ } //----------------------------------------------------------------------------- // LLTexLayerSetBuffer + // The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one. //----------------------------------------------------------------------------- -LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* owner, S32 width, S32 height) - : + +// static +S32 LLTexLayerSetBuffer::sGLByteCount = 0; + +LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner, + S32 width, S32 height) : // ORDER_LAST => must render these after the hints are created. LLViewerDynamicTexture( width, height, 4, LLViewerDynamicTexture::ORDER_LAST, TRUE ), - mNeedsUpdate( TRUE ), - mNeedsUpload( FALSE ), - mUploadPending( FALSE ), // Not used for any logic here, just to sync sending of updates - mUploadFailCount( 0 ), + mUploadPending(FALSE), // Not used for any logic here, just to sync sending of updates + mNeedsUpload(FALSE), + mUploadFailCount(0), + mNeedsUpdate(TRUE), mUploadAfter( 0 ), - mTexLayerSet( owner ) + mTexLayerSet(owner) { LLTexLayerSetBuffer::sGLByteCount += getSize(); } @@ -113,7 +142,7 @@ LLTexLayerSetBuffer::~LLTexLayerSetBuffer() { LLTexLayerSetBuffer::sGLByteCount -= getSize(); destroyGLTexture(); - for (S32 order = 0; order < ORDER_COUNT; order++) + for( S32 order = 0; order < ORDER_COUNT; order++ ) { LLViewerDynamicTexture::sInstances[order].erase(this); // will fail in all but one case. } @@ -180,10 +209,7 @@ void LLTexLayerSetBuffer::requestDelayedUpload(U64 delay_usec) void LLTexLayerSetBuffer::cancelUpload() { - if (mNeedsUpload) - { - mNeedsUpload = FALSE; - } + mNeedsUpload = FALSE; mUploadPending = FALSE; mUploadAfter = 0; } @@ -195,7 +221,7 @@ BOOL LLTexLayerSetBuffer::needsUploadNow() const return (upload && (LLFrameTimer::getTotalTime() > mUploadAfter)); } -void LLTexLayerSetBuffer::pushProjection() +void LLTexLayerSetBuffer::pushProjection() const { glMatrixMode(GL_PROJECTION); gGL.pushMatrix(); @@ -207,7 +233,7 @@ void LLTexLayerSetBuffer::pushProjection() glLoadIdentity(); } -void LLTexLayerSetBuffer::popProjection() +void LLTexLayerSetBuffer::popProjection() const { glMatrixMode(GL_PROJECTION); gGL.popMatrix(); @@ -285,21 +311,21 @@ BOOL LLTexLayerSetBuffer::render() { if (!success) { - llinfos << "Failed attempt to bake " << mTexLayerSet->getBodyRegion() << llendl; + llinfos << "Failed attempt to bake " << mTexLayerSet->getBodyRegionName() << llendl; mUploadPending = FALSE; } else { if (mTexLayerSet->isVisible()) { - readBackAndUpload(); + doUpload(); } else { mUploadPending = FALSE; mNeedsUpload = FALSE; - mTexLayerSet->getAvatar()->setNewBakedTexture(mTexLayerSet->getAvatar()->getBakedTE(mTexLayerSet), IMG_INVISIBLE); - llinfos << "Invisible baked texture set for " << mTexLayerSet->getBodyRegion() << llendl; + mTexLayerSet->getAvatar()->setNewBakedTexture(mTexLayerSet->getBakedTexIndex(), IMG_INVISIBLE); + llinfos << "Invisible baked texture set for " << mTexLayerSet->getBodyRegionName() << llendl; } } } @@ -315,12 +341,16 @@ BOOL LLTexLayerSetBuffer::render() return success; } -bool LLTexLayerSetBuffer::isInitialized(void) const +BOOL LLTexLayerSetBuffer::isInitialized(void) const { return mGLTexturep.notNull() && mGLTexturep->isGLTextureCreated(); } +BOOL LLTexLayerSetBuffer::uploadPending() const +{ + return mUploadPending; +} -BOOL LLTexLayerSetBuffer::updateImmediate() +BOOL LLTexLayerSetBuffer::requestUpdateImmediate() { mNeedsUpdate = TRUE; BOOL result = FALSE; @@ -335,9 +365,11 @@ BOOL LLTexLayerSetBuffer::updateImmediate() return result; } -void LLTexLayerSetBuffer::readBackAndUpload() +// Create the baked texture, send it out to the server, then wait for it to come +// back so we can switch to using it. +void LLTexLayerSetBuffer::doUpload() { - llinfos << "Baked " << mTexLayerSet->getBodyRegion() << llendl; + llinfos << "Uploading baked " << mTexLayerSet->getBodyRegionName() << llendl; LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_BAKES); // Don't need caches since we're baked now. (note: we won't *really* be baked @@ -351,15 +383,13 @@ void LLTexLayerSetBuffer::readBackAndUpload() // Get the MASK information from our texture LLGLSUIDefault gls_ui; - LLPointer baked_mask_image = new LLImageRaw(mFullWidth, mFullHeight, 1 ); U8* baked_mask_data = baked_mask_image->getData(); - - mTexLayerSet->gatherAlphaMasks(baked_mask_data, mFullWidth, mFullHeight); -// imdebug("lum b=8 w=%d h=%d %p", mWidth, mHeight, baked_mask_data); + mTexLayerSet->gatherMorphMaskAlpha(baked_mask_data, mFullWidth, mFullHeight); - S32 baked_image_components = 5; // red green blue bump clothing + // Create the baked image from our color and mask information + const S32 baked_image_components = 5; // red green blue [bump] clothing LLPointer baked_image = new LLImageRaw( mFullWidth, mFullHeight, baked_image_components ); U8* baked_image_data = baked_image->getData(); S32 i = 0; @@ -367,11 +397,11 @@ void LLTexLayerSetBuffer::readBackAndUpload() { for (S32 v=0; v < mFullHeight; 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] = baked_color_data[4 * i + 3]; // alpha should be correct for eyelashes. - baked_image_data[5 * i + 4] = baked_mask_data[i]; + 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] = baked_color_data[4*i + 3]; // alpha should be correct for eyelashes. + baked_image_data[5*i + 4] = baked_mask_data[i]; i++; } } @@ -405,7 +435,7 @@ void LLTexLayerSetBuffer::readBackAndUpload() { // baked_upload_data is owned by the responder and deleted after the request completes LLBakedUploadData* baked_upload_data = - new LLBakedUploadData( gAgentAvatarp, this->mTexLayerSet, this, asset_id ); + new LLBakedUploadData( gAgentAvatarp, this->mTexLayerSet, asset_id ); mUploadID = asset_id; // Upload the image @@ -520,16 +550,17 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, gAgentAvatarp->dirtyMesh(); } - else - { + else + { + // 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; - } - - delete baked_upload_data; + llwarns << "Baked upload failed" << llendl; + } + + delete baked_upload_data; } //----------------------------------------------------------------------------- @@ -610,13 +641,12 @@ BOOL LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node) BOOL LLTexLayerSet::sHasCaches = FALSE; -LLTexLayerSet::LLTexLayerSet( LLVOAvatarSelf* avatar ) - : +LLTexLayerSet::LLTexLayerSet(LLVOAvatarSelf* const avatar) : mComposite( NULL ), mAvatar( avatar ), mUpdatesEnabled( FALSE ), - mIsVisible(TRUE), - mBakedTexIndex(BAKED_HEAD), + mIsVisible( TRUE ), + mBakedTexIndex(LLVOAvatarDefines::BAKED_HEAD), mInfo( NULL ) { } @@ -633,17 +663,19 @@ 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 ); + LLTexLayerInterface* layer = new LLTexLayer( this ); + // this is the first time this layer (of either type) is being created - make sure you add the parameters to the avatar if (!layer->setInfo(*iter)) { mInfo = NULL; @@ -651,7 +683,7 @@ BOOL LLTexLayerSet::setInfo(LLTexLayerSetInfo *info) } if (!layer->isVisibilityMask()) { - mLayerList.push_back(layer); + mLayerList.push_back( layer ); } else { @@ -693,30 +725,197 @@ void LLTexLayerSet::deleteCaches() { for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) { - LLTexLayer* layer = *iter; + LLTexLayerInterface* layer = *iter; layer->deleteCaches(); } for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) { - LLTexLayer* layer = *iter; + LLTexLayerInterface* 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); } +BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) +{ + BOOL success = TRUE; + mIsVisible = TRUE; + + if (mMaskLayerList.size() > 0) + { + for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) + { + LLTexLayerInterface* layer = *iter; + if (layer->isInvisibleAlphaMask()) + { + mIsVisible = FALSE; + } + } + } + + LLGLSUIDefault gls_ui; + LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE); + gGL.setColorMask(true, true); + + // clear buffer area to ensure we don't pick up UI elements + { + 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(); + } + + if (mIsVisible) + { + // composite color layers + for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + { + LLTexLayerInterface* layer = *iter; + if (layer->getRenderPass() == LLTexLayer::RP_COLOR || layer->getRenderPass() == LLTexLayer::RP_BUMP) + { + gGL.flush(); + success &= layer->render(x, y, width, height); + gGL.flush(); + } + } + + renderAlphaMaskTextures(x, y, width, height, false); + + stop_glerror(); + } + else + { + gGL.flush(); + + gGL.setSceneBlendType(LLRender::BT_REPLACE); + LLGLDisable no_alpha(GL_ALPHA_TEST); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color4f( 0.f, 0.f, 0.f, 0.f ); + + gl_rect_2d_simple( width, height ); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + gGL.flush(); + } + + return success; +} +BOOL LLTexLayerSet::isBodyRegion(const std::string& region) const +{ + return mInfo->mBodyRegion == region; +} + +const std::string LLTexLayerSet::getBodyRegionName() const +{ + return mInfo->mBodyRegion; +} + +void LLTexLayerSet::requestUpdate() +{ + if( mUpdatesEnabled ) + { + createComposite(); + mComposite->requestUpdate(); + } +} + +void LLTexLayerSet::requestUpload() +{ + createComposite(); + mComposite->requestUpload(); +} + +void LLTexLayerSet::cancelUpload() +{ + if(mComposite) + { + mComposite->cancelUpload(); + } +} + +void LLTexLayerSet::createComposite() +{ + if(!mComposite) + { + S32 width = mInfo->mWidth; + S32 height = mInfo->mHeight; + // Composite other avatars at reduced resolution + if( !mAvatar->isSelf() ) + { + width /= 2; + height /= 2; + } + mComposite = new LLTexLayerSetBuffer( this, width, height ); + } +} + +void LLTexLayerSet::destroyComposite() +{ + if( mComposite ) + { + mComposite = NULL; + } +} + +void LLTexLayerSet::setUpdatesEnabled( BOOL b ) +{ + mUpdatesEnabled = b; +} + + +void LLTexLayerSet::updateComposite() +{ + createComposite(); + mComposite->requestUpdateImmediate(); +} + +LLTexLayerSetBuffer* LLTexLayerSet::getComposite() +{ + if (!mComposite) + { + createComposite(); + } + return mComposite; +} + +const LLTexLayerSetBuffer* LLTexLayerSet::getComposite() const +{ + return mComposite; +} + +void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 width, S32 height) +{ + memset(data, 255, width * height); + + for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + { + LLTexLayerInterface* layer = *iter; + layer->gatherAlphaMasks(data, mComposite->getOriginX(),mComposite->getOriginY(), width, height); + } + + // Set alpha back to that of our alpha masks. + renderAlphaMaskTextures(mComposite->getOriginX(), mComposite->getOriginY(), width, height, true); +} + void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear) { const LLTexLayerSetInfo *info = getInfo(); @@ -730,7 +929,7 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLGLSNoAlphaTest gls_no_alpha_test; gGL.flush(); { - LLViewerTexture* tex = gTexStaticImageList.getTexture(info->mStaticAlphaFileName, TRUE); + LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(info->mStaticAlphaFileName, TRUE); if (tex) { LLGLSUIDefault gls_ui; @@ -762,7 +961,7 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_REPLACE); for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) { - LLTexLayer* layer = *iter; + LLTexLayerInterface* layer = *iter; gGL.flush(); layer->blendAlphaTexture(x, y, width, height); gGL.flush(); @@ -776,191 +975,48 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, gGL.setSceneBlendType(LLRender::BT_ALPHA); } -BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) -{ - BOOL success = TRUE; - mIsVisible = TRUE; - - if (mMaskLayerList.size() > 0) - { - for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) - { - LLTexLayer* layer = *iter; - if (layer->isInvisibleAlphaMask()) - { - mIsVisible = FALSE; - } - } - } - - LLGLSUIDefault gls_ui; - LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE); - gGL.setColorMask(true, true); - - // clear buffer area to ensure we don't pick up UI elements - { - 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(); - } - - if (mIsVisible) - { - // composite color layers - for (layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++) - { - LLTexLayer* layer = *iter; - if (layer->getRenderPass() == RP_COLOR || layer->getRenderPass() == RP_BUMP) - { - gGL.flush(); - success &= layer->render(x, y, width, height); - gGL.flush(); - } - } - - renderAlphaMaskTextures(x, y, width, height, false); - - stop_glerror(); - } - else - { - gGL.flush(); - - gGL.setSceneBlendType(LLRender::BT_REPLACE); - LLGLDisable no_alpha(GL_ALPHA_TEST); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4f( 0.f, 0.f, 0.f, 0.f ); - - gl_rect_2d_simple( width, height ); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - gGL.flush(); - } - - return success; - } - -void LLTexLayerSet::requestUpdate() -{ - if( mUpdatesEnabled ) - { - createComposite(); - mComposite->requestUpdate(); - } -} - -void LLTexLayerSet::requestUpload() -{ - createComposite(); - mComposite->requestUpload(); -} - -void LLTexLayerSet::cancelUpload() -{ - if(mComposite) - { - mComposite->cancelUpload(); - } -} - -void LLTexLayerSet::createComposite() -{ - if( !mComposite ) - { - S32 width = mInfo->mWidth; - S32 height = mInfo->mHeight; - // Composite other avatars at reduced resolution - if( !mAvatar->isSelf() ) - { - width /= 2; - height /= 2; - } - mComposite = new LLTexLayerSetBuffer(this, width, height); - } -} - -void LLTexLayerSet::destroyComposite() -{ - if( mComposite ) - { - mComposite = NULL; - } -} - -void LLTexLayerSet::setUpdatesEnabled( BOOL b ) -{ - mUpdatesEnabled = b; -} - - -void LLTexLayerSet::updateComposite() -{ - createComposite(); - mComposite->updateImmediate(); -} - -LLTexLayerSetBuffer* LLTexLayerSet::getComposite() -{ - createComposite(); - return mComposite; -} - -void LLTexLayerSet::gatherAlphaMasks(U8 *data, S32 width, S32 height) -{ - S32 size = width * height; - - memset(data, 255, width * height); - - for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) - { - LLTexLayer* layer = *iter; - U8* alphaData = layer->getAlphaData(); - if (!alphaData && layer->hasAlphaParams()) - { - LLColor4 net_color; - layer->findNetColor( &net_color ); - layer->invalidateMorphMasks(); - layer->renderAlphaMasks(mComposite->getOriginX(), mComposite->getOriginY(), width, height, &net_color); - alphaData = layer->getAlphaData(); - } - if (alphaData) - { - for( S32 i = 0; i < size; i++ ) - { - U8 curAlpha = data[i]; - U16 resultAlpha = curAlpha; - resultAlpha *= (alphaData[i] + 1); - resultAlpha = resultAlpha >> 8; - data[i] = (U8)resultAlpha; - } - } - } - - // Set alpha back to that of our alpha masks. - renderAlphaMaskTextures(mComposite->getOriginX(), mComposite->getOriginY(), width, height, true); -} - void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components) { for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) { - LLTexLayer* layer = *iter; + LLTexLayerInterface* layer = *iter; layer->applyMorphMask(tex_data, width, height, num_components); } } +BOOL LLTexLayerSet::isMorphValid() const +{ + for(layer_list_t::const_iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + { + const LLTexLayerInterface* layer = *iter; + if (layer && !layer->isMorphValid()) + { + return FALSE; + } + } + return TRUE; +} + +void LLTexLayerSet::invalidateMorphMasks() +{ + for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + { + LLTexLayerInterface* layer = *iter; + if (layer) + { + layer->invalidateMorphMasks(); + } + } +} + + + //----------------------------------------------------------------------------- // 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 ), @@ -971,8 +1027,8 @@ LLTexLayerInfo::LLTexLayerInfo( ) 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) @@ -995,7 +1051,7 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) { if( render_pass_name == "bump" ) { - mRenderPass = RP_BUMP; + mRenderPass = LLTexLayer::RP_BUMP; } } @@ -1025,7 +1081,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"); @@ -1034,105 +1090,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; + const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + if (local_texture_name == texture_dict->mName) + { + mLocalTexture = iter->first; + break; } - else if( "upper_bodypaint" == local_texture ) - { - mLocalTexture = TEX_UPPER_BODYPAINT; } - else if( "lower_pants" == local_texture ) + if (mLocalTexture == TEX_NUM_INDICES) { - 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; - } - else if( "skirt" == local_texture ) - { - mLocalTexture = TEX_SKIRT; - } - else if( "hair_grain" == local_texture ) - { - mLocalTexture = TEX_HAIR; - } - else if ("hair_alpha" == local_texture) - { - mLocalTexture = TEX_HAIR_ALPHA; - } - else if ("head_alpha" == local_texture) - { - mLocalTexture = TEX_HEAD_ALPHA; - } - else if ("upper_alpha" == local_texture) - { - mLocalTexture = TEX_UPPER_ALPHA; - } - else if ("lower_alpha" == local_texture) - { - mLocalTexture = TEX_LOWER_ALPHA; - } - else if ("eyes_alpha" == local_texture) - { - mLocalTexture = TEX_EYES_ALPHA; - } - else if ("head_tattoo" == local_texture) - { - mLocalTexture = TEX_HEAD_TATTOO; - } - else if ("upper_tattoo" == local_texture) - { - mLocalTexture = TEX_UPPER_TATTOO; - } - else if ("lower_tattoo" == local_texture) - { - mLocalTexture = TEX_LOWER_TATTOO; - } - else - { - llwarns << " element has invalid local_texture attribute: " << mName << " " << local_texture << llendl; + llwarns << " element has invalid local_texture attribute: " << mName << " " << local_texture_name << llendl; return FALSE; } } @@ -1166,13 +1144,13 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) if( child->getChildByName( "param_color" ) ) { // - 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" ) ) { @@ -1183,13 +1161,171 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) delete info; return FALSE; } - mAlphaInfoList.push_back( info ); + mParamAlphaInfoList.push_back(info); } } return TRUE; } + +LLTexLayerInterface::LLTexLayerInterface(LLTexLayerSet* const layer_set): + mTexLayerSet( layer_set ), + mMorphMasksValid( FALSE ), + mInfo(NULL), + mHasMorph(FALSE) +{ +} +BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info ) // This sets mInfo and calls initialization functions +{ + // setInfo should only be called once. Code is not robust enough to handle redefinition of a texlayer. + // Not a critical warning, but could be useful for debugging later issues. -Nyx + if (mInfo != NULL) + { + llwarns << "mInfo != NULL" << llendl; + } + mInfo = info; + //mID = info->mID; // No ID + + mParamColorList.reserve(mInfo->mParamColorInfoList.size()); + for (param_color_info_list_t::const_iterator iter = mInfo->mParamColorInfoList.begin(); + iter != mInfo->mParamColorInfoList.end(); + iter++) + { + LLTexLayerParamColor* param_color; + //if (!wearable) + { + param_color = new LLTexLayerParamColor(this); + if (!param_color->setInfo(*iter, TRUE)) + { + mInfo = NULL; + return FALSE; + } + } + /*else + { + param_color = (LLTexLayerParamColor*)wearable->getVisualParam((*iter)->getID()); + if (!param_color) + { + mInfo = NULL; + return FALSE; + } + }*/ + mParamColorList.push_back( param_color ); + } + + 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; + //if (!wearable) + { + param_alpha = new LLTexLayerParamAlpha( this ); + if (!param_alpha->setInfo(*iter, TRUE)) + { + mInfo = NULL; + return FALSE; + } + } + /*else + { + param_alpha = (LLTexLayerParamAlpha*) wearable->getVisualParam((*iter)->getID()); + if (!param_alpha) + { + mInfo = NULL; + return FALSE; + } + }*/ + mParamAlphaList.push_back( param_alpha ); + } + + LLTexLayerInfo::morph_name_list_t::const_iterator iter = getInfo()->mMorphNameList.begin(); + for (; iter != getInfo()->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; + const 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); + } + } + return TRUE; +} + +void LLTexLayerInterface::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components) +{ + for( morph_list_t::iterator iter = mMaskedMorphs.begin(); + iter != mMaskedMorphs.end(); iter++ ) + { + LLVOAvatar::LLMaskedMorph* maskedMorph = (LLVOAvatar::LLMaskedMorph*)(*iter); + maskedMorph->mMorphTarget->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert); + } +} + +void LLTexLayerInterface::addMaskedMorph(LLPolyMorphTarget* morph_target, BOOL invert) +{ + mMaskedMorphs.push_front((char*)new LLVOAvatar::LLMaskedMorph(morph_target, invert)); + setHasMorph(!mMaskedMorphs.empty()); +} + +/*virtual*/ void LLTexLayerInterface::requestUpdate() +{ + mTexLayerSet->requestUpdate(); +} + +const std::string& LLTexLayerInterface::getName() const +{ + return mInfo->mName; +} + +LLTexLayerInterface::ERenderPass LLTexLayerInterface::getRenderPass() const +{ + return mInfo->mRenderPass; +} + +const std::string& LLTexLayerInterface::getGlobalColor() const +{ + return mInfo->mGlobalColor; +} + +BOOL LLTexLayerInterface::isVisibilityMask() const +{ + return mInfo->mIsVisibilityMask; +} + +void LLTexLayerInterface::invalidateMorphMasks() +{ + mMorphMasksValid = FALSE; +} + +LLViewerVisualParam* LLTexLayerInterface::getVisualParamPtr(S32 index) const +{ + LLViewerVisualParam *result = NULL; + for (param_color_list_t::const_iterator color_iter = mParamColorList.begin(); color_iter != mParamColorList.end() && !result; ++color_iter) + { + if ((*color_iter)->getID() == index) + { + result = *color_iter; + } + } + for (param_alpha_list_t::const_iterator alpha_iter = mParamAlphaList.begin(); alpha_iter != mParamAlphaList.end() && !result; ++alpha_iter) + { + if ((*alpha_iter)->getID() == index) + { + result = *alpha_iter; + } + } + + return result; +} + //----------------------------------------------------------------------------- // LLTexLayer // A single texture layer, consisting of: @@ -1203,12 +1339,10 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) // * a texture entry index (TE) // * (optional) one or more alpha parameters (weighted alpha textures) //----------------------------------------------------------------------------- -LLTexLayer::LLTexLayer( LLTexLayerSet* layer_set ) - : - mTexLayerSet( layer_set ), - mMorphMasksValid( FALSE ), - mStaticImageInvalid( FALSE ), - mInfo( NULL ) +LLTexLayer::LLTexLayer(LLTexLayerSet* const layer_set) : + LLTexLayerInterface( layer_set ), + + mStaticImageInvalid( FALSE ) { } @@ -1225,100 +1359,50 @@ 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); // nyx says this is probably bogus but needs investigating - if (mInfo != NULL) // above llassert(), but softened into a warning - { - llwarns << "BAD STUFF! mInfo != NULL" << llendl; - } - mInfo = info; - //mID = info->mID; // No ID - - { - 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 ); - if (!param_color->setInfo(*iter)) - { - mInfo = NULL; - return FALSE; - } - 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++) - { - LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha( this ); - if (!param_alpha->setInfo(*iter)) - { - mInfo = NULL; - return FALSE; - } - mParamAlphaList.push_back( param_alpha ); - } - } - - return TRUE; + return LLTexLayerInterface::setInfo(info); } -#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++) { - delete info; - return FALSE; + const LLTexLayerParamColor* param = *iter; + LLColor4 param_net = param->getNetColor(); + const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)param->getInfo(); + switch(info->getOperation()) + { + 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() +/*virtual*/ void LLTexLayer::deleteCaches() { - for( alpha_list_t::iterator iter = mParamAlphaList.begin(); + // Only need to delete caches for alpha params. Color params don't hold extra memory + for (param_alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ ) { LLTexLayerParamAlpha* param = *iter; @@ -1327,14 +1411,14 @@ void LLTexLayer::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) { LLGLEnable color_mat(GL_COLOR_MATERIAL); gPipeline.disableLights(); LLColor4 net_color; BOOL color_specified = findNetColor(&net_color); - + if (mTexLayerSet->getAvatar()->mIsDummy) { color_specified = true; @@ -1350,18 +1434,18 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) } BOOL alpha_mask_specified = FALSE; - alpha_list_t::iterator iter = mParamAlphaList.begin(); + 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() ) { @@ -1376,9 +1460,9 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) { return success; } - }*/ + }//*/ - renderAlphaMasks( x, y, width, height, &net_color ); + renderMorphMasks(x, y, width, height, net_color); alpha_mask_specified = TRUE; gGL.flush(); gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA); @@ -1428,7 +1512,7 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) if( !getInfo()->mStaticImageFileName.empty() ) { { - LLViewerTexture* tex = gTexStaticImageList.getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); + LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); if( tex ) { gGL.getTexUnit(0)->bind(tex, TRUE); @@ -1474,20 +1558,85 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) return success; } +const U8* LLTexLayer::getAlphaData() const +{ + LLCRC alpha_mask_crc; + const LLUUID& uuid = getUUID(); + alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); + + for (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++) + { + const LLTexLayerParamAlpha* param = *iter; + // MULTI-WEARABLE: verify visual parameters used here + F32 param_weight = param->getWeight(); + alpha_mask_crc.update((U8*)¶m_weight, sizeof(F32)); + } + + U32 cache_index = alpha_mask_crc.getCRC(); + + alpha_cache_t::const_iterator iter2 = mAlphaCache.find(cache_index); + return (iter2 == mAlphaCache.end()) ? 0 : iter2->second; +} + +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) + // * a reference to a global color + // * a fixed color with non-zero alpha + // * opaque white (the default) + + if( !mParamColorList.empty() ) + { + if( !getGlobalColor().empty() ) + { + net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getInfo()->mGlobalColor ) ); + } + else if (getInfo()->mFixedColor.mV[VW]) + { + net_color->setVec( getInfo()->mFixedColor ); + } + else + { + net_color->setVec( 0.f, 0.f, 0.f, 0.f ); + } + + calculateTexLayerColor(mParamColorList, *net_color); + return TRUE; + } + + if( !getGlobalColor().empty() ) + { + net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getGlobalColor() ) ); + return TRUE; + } + + if( getInfo()->mFixedColor.mV[VW] ) + { + net_color->setVec( getInfo()->mFixedColor ); + return TRUE; + } + + net_color->setToWhite(); + + return FALSE; // No need to draw a separate colored polygon +} + BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) { BOOL success = TRUE; gGL.flush(); - if (!getInfo()->mStaticImageFileName.empty()) + + if( !getInfo()->mStaticImageFileName.empty() ) { - LLViewerTexture* tex = gTexStaticImageList.getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); - if (tex) + LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); + if( tex ) { LLGLSNoAlphaTest gls_no_alpha_test; gGL.getTexUnit(0)->bind(tex, TRUE); - gl_rect_2d_simple_tex(width, height); + gl_rect_2d_simple_tex( width, height ); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } else @@ -1517,95 +1666,12 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) return success; } -U8* LLTexLayer::getAlphaData() +/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) { - 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++ ) - { - 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); - return (iter2 == mAlphaCache.end()) ? 0 : iter2->second; + addAlphaMask(data, originX, originY, width, height); } -BOOL LLTexLayer::findNetColor( LLColor4* net_color ) -{ - // Color is either: - // * one or more color parameters (weighted colors) (which may make use of a global color or fixed color) - // * a reference to a global color - // * a fixed color with non-zero alpha - // * opaque white (the default) - - if( !mParamColorList.empty() ) - { - if( !getGlobalColor().empty() ) - { - net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getInfo()->mGlobalColor ) ); - } - else - if( getInfo()->mFixedColor.mV[VW] ) - { - net_color->setVec( getInfo()->mFixedColor ); - } - else - { - 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; - } - } - return TRUE; - } - - if( !getGlobalColor().empty() ) - { - net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getGlobalColor() ) ); - return TRUE; - } - - if( getInfo()->mFixedColor.mV[VW] ) - { - net_color->setVec( getInfo()->mFixedColor ); - return TRUE; - } - - net_color->setToWhite(); - - return FALSE; // No need to draw a separate colored polygon -} - - -BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4* colorp ) +BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color) { BOOL success = TRUE; @@ -1613,9 +1679,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() ) { @@ -1633,8 +1697,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 ); @@ -1671,7 +1734,7 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 if( !getInfo()->mStaticImageFileName.empty() ) { - LLViewerTexture* tex = gTexStaticImageList.getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); + LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); if( tex ) { if( (tex->getComponents() == 4) || @@ -1687,11 +1750,11 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 // 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 ); } @@ -1700,34 +1763,28 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 gGL.setColorMask(true, true); - if (success && !mMorphMasksValid && !mMaskedMorphs.empty()) + if (hasMorph() && success) { LLCRC alpha_mask_crc; - const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID((ETextureIndex)getInfo()->mLocalTexture); + const LLUUID& uuid = getUUID(); 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); @@ -1740,120 +1797,39 @@ 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++ ) - { - LLVOAvatar::LLMaskedMorph* maskedMorph = &(*iter3); - maskedMorph->mMorphTarget->applyMask(alpha_data, width, height, 1, maskedMorph->mInvert); - } + applyMorphMask(alpha_data, width, height, 1); } return success; } -void LLTexLayer::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components) +void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height) { - for( morph_list_t::iterator iter = mMaskedMorphs.begin(); - iter != mMaskedMorphs.end(); iter++ ) + S32 size = width * height; + const U8* alphaData = getAlphaData(); + if (!alphaData && hasAlphaParams()) { - LLVOAvatar::LLMaskedMorph* maskedMorph = &(*iter); - maskedMorph->mMorphTarget->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert); + LLColor4 net_color; + findNetColor( &net_color ); + // TODO: eliminate need for layer morph mask valid flag + invalidateMorphMasks(); + renderMorphMasks(originX, originY, width, height, net_color); + alphaData = getAlphaData(); } -} - -// 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 ) -{ - if (!in_data) + if (alphaData) { - return FALSE; - } - GLenum format_options[4] = { GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA }; - GLenum format = format_options[in_components-1]; - if( is_mask ) - { - llassert( 1 == in_components ); - format = GL_ALPHA; - } - - if( (in_width != SCRATCH_TEX_WIDTH) || (in_height != SCRATCH_TEX_HEIGHT) ) - { - LLGLSNoAlphaTest gls_no_alpha_test; - - GLenum internal_format_options[4] = { GL_LUMINANCE8, GL_LUMINANCE8_ALPHA8, GL_RGB8, GL_RGBA8 }; - GLenum internal_format = internal_format_options[in_components-1]; - if( is_mask ) + for( S32 i = 0; i < size; i++ ) { - llassert( 1 == in_components ); - internal_format = GL_ALPHA8; + U8 curAlpha = data[i]; + U16 resultAlpha = curAlpha; + resultAlpha *= (alphaData[i] + 1); + resultAlpha = resultAlpha >> 8; + data[i] = (U8)resultAlpha; } - - U32 name = 0; - LLImageGL::generateTextures(1, &name ); - stop_glerror(); - - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, name); - stop_glerror(); - - LLImageGL::setManualImage( - GL_TEXTURE_2D, 0, internal_format, - in_width, in_height, - format, GL_UNSIGNED_BYTE, in_data ); - stop_glerror(); - - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - - gl_rect_2d_simple_tex( width, height ); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - LLImageGL::deleteTextures(1, &name ); - stop_glerror(); } - else - { - LLGLSNoAlphaTest gls_no_alpha_test; - - if( !mTexLayerSet->getAvatar()->bindScratchTexture(format) ) - { - return FALSE; - } - - glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, in_width, in_height, format, GL_UNSIGNED_BYTE, in_data ); - stop_glerror(); - - gl_rect_2d_simple_tex( width, height ); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - - return TRUE; } -void LLTexLayer::requestUpdate() -{ - mTexLayerSet->requestUpdate(); -} - -void LLTexLayer::addMaskedMorph(LLPolyMorphTarget* morph_target, BOOL invert) -{ - mMaskedMorphs.push_front(LLVOAvatar::LLMaskedMorph(morph_target, invert)); -} - -void LLTexLayer::invalidateMorphMasks() -{ - mMorphMasksValid = FALSE; -} - -BOOL LLTexLayer::isVisibilityMask() const -{ - return mInfo->mIsVisibilityMask; -} - -BOOL LLTexLayer::isInvisibleAlphaMask() +BOOL LLTexLayer::isInvisibleAlphaMask() const { const LLTexLayerInfo *info = getInfo(); @@ -1868,656 +1844,60 @@ BOOL LLTexLayer::isInvisibleAlphaMask() return FALSE; } -//----------------------------------------------------------------------------- -// LLTexLayerParamAlphaInfo -//----------------------------------------------------------------------------- -LLTexLayerParamAlphaInfo::LLTexLayerParamAlphaInfo( ) - : - mMultiplyBlend( FALSE ), - mSkipIfZeroWeight( FALSE ), - mDomain( 0.f ) +LLUUID LLTexLayer::getUUID() const { + return mTexLayerSet->getAvatar()->getLocalTextureID((ETextureIndex)getInfo()->mLocalTexture); } -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 << " 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 +// finds a specific layer based on a passed in name //----------------------------------------------------------------------------- - -// static -LLTexLayerParamAlpha::param_alpha_ptr_list_t LLTexLayerParamAlpha::sInstances; - -// static -void LLTexLayerParamAlpha::dumpCacheByteCount() +LLTexLayerInterface* LLTexLayerSet::findLayerByName(const std::string& name) { - 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++ ) + for (layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) { - LLTexLayerParamAlpha* instance = *iter; - LLViewerTexture* tex = instance->mCachedProcessedTexture; - if( tex ) + LLTexLayerInterface* layer = *iter; + if (layer->getName() == name) { - S32 bytes = (S32)tex->getWidth() * tex->getHeight() * tex->getComponents(); - - if( tex->hasGLTexture() ) - { - *gl_bytes += bytes; - } + return layer; } } -} - -LLTexLayerParamAlpha::LLTexLayerParamAlpha( LLTexLayer* layer ) - : - mCachedProcessedTexture( 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 - mCachedProcessedTexture = NULL; - mStaticImageRaw = NULL; - mNeedsCreateTexture = FALSE; -} - -void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL set_by_user) -{ - if (mIsAnimating) + for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++ ) { - 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() ) + LLTexLayerInterface* layer = *iter; + if (layer->getName() == name) { - if ( gAgentCamera.cameraCustomizeAvatar() ) - { - set_by_user = FALSE; - } - avatar->invalidateComposite( mTexLayer->getTexLayerSet(), set_by_user ); - mTexLayer->invalidateMorphMasks(); - avatar->updateMeshTextures(); + return layer; } } -} - -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; - } - } - - LLWearableType::EType type = (LLWearableType::EType)getWearableType(); - if( (type != LLWearableType::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( !mCachedProcessedTexture || - (mCachedProcessedTexture->getWidth() != image_tga_width) || - (mCachedProcessedTexture->getHeight() != image_tga_height) || - (weight_changed) ) - { -// llinfos << "Building Cached Alpha: " << mName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << effective_weight << llendl; - mCachedEffectiveWeight = effective_weight; - - if( !mCachedProcessedTexture ) - { - mCachedProcessedTexture = LLViewerTextureManager::getLocalTexture( image_tga_width, image_tga_height, 1, FALSE ); - - // We now have something in one of our caches - LLTexLayerSet::sHasCaches |= mCachedProcessedTexture ? TRUE : FALSE; - - mCachedProcessedTexture->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( mCachedProcessedTexture ) - { - { - // Create the GL texture, and then hang onto it for future use. - if( mNeedsCreateTexture ) - { - mCachedProcessedTexture->createGLTexture(0, mStaticImageRaw, 0, TRUE, LLViewerTexture::BOOST_AVATAR_SELF); - mNeedsCreateTexture = FALSE; - gGL.getTexUnit(0)->bind(mCachedProcessedTexture); - mCachedProcessedTexture->setAddressMode(LLTexUnit::TAM_CLAMP); - } - - LLGLSNoAlphaTest gls_no_alpha_test; - gGL.getTexUnit(0)->bind(mCachedProcessedTexture, TRUE); - 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() ) - { - mCachedProcessedTexture = 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; + return NULL; } //----------------------------------------------------------------------------- -// LLTexGlobalColorInfo +// LLTexLayerStaticImageList //----------------------------------------------------------------------------- -LLTexGlobalColorInfo::LLTexGlobalColorInfo() +LLTexLayerStaticImageList::LLTexLayerStaticImageList() : + mGLBytes(0), + mTGABytes(0), + mImageNames(16384) { } - -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 << " element is missing name attribute." << llendl; - return FALSE; - } - // sub-element - for (LLXmlTreeNode* child = node->getChildByName( "param" ); - child; - child = node->getNextNamedChild()) - { - if( child->getChildByName( "param_color" ) ) - { - // - 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; -} - -//----------------------------------------------------------------------------- - -LLColor4 LLTexGlobalColor::getColor() -{ - // 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 ); -} - -//----------------------------------------------------------------------------- -// LLTexParamColorInfo -//----------------------------------------------------------------------------- -LLTexParamColorInfo::LLTexParamColorInfo() - : - mOperation( OP_ADD ), - mNumColors( 0 ) -{ -} - -BOOL LLTexParamColorInfo::parseXml(LLXmlTreeNode *node) -{ - 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 << " is missing sub-elements" << llendl; - return FALSE; - } - - if( (mOperation == OP_BLEND) && (mNumColors != 1) ) - { - llwarns << " with operation\"blend\" must have exactly one " << llendl; - return FALSE; - } - - return TRUE; -} - -//----------------------------------------------------------------------------- -// LLTexParamColor -//----------------------------------------------------------------------------- -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() ) -{ -} - - -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() const +void LLTexLayerStaticImageList::dumpByteCount() const { llinfos << "Avatar Static Textures " << "KB GL:" << (mGLBytes / 1024) << "KB TGA:" << (mTGABytes / 1024) << "KB" << llendl; } -void LLTexStaticImageList::deleteCachedImages() +void LLTexLayerStaticImageList::deleteCachedImages() { if( mGLBytes || mTGABytes ) { @@ -2535,16 +1915,16 @@ void LLTexStaticImageList::deleteCachedImages() } } -// Note: in general, for a given image image we'll call either getImageTga() or getImageGL(). +// Note: in general, for a given image image we'll call either getImageTga() or getTexture(). // We call getImageTga() if the image is used as an alpha gradient. -// Otherwise, we call getImageGL() +// Otherwise, we call getTexture() // 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; @@ -2567,14 +1947,12 @@ 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. -LLViewerTexture* LLTexStaticImageList::getTexture(const std::string& file_name, BOOL is_mask) +LLViewerTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, BOOL is_mask) { LLPointer tex; - const char *namekey = sImageNames.addString(file_name); + const char *namekey = mImageNames.addString(file_name); texture_map_t::const_iterator iter = mStaticImageList.find(namekey); if( iter != mStaticImageList.end() ) @@ -2612,7 +1990,7 @@ LLViewerTexture* LLTexStaticImageList::getTexture(const std::string& file_name, // 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; diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h index ae3633c39..eae4ab1e0 100644 --- a/indra/newview/lltexlayer.h +++ b/indra/newview/lltexlayer.h @@ -34,524 +34,312 @@ #define LL_LLTEXLAYER_H #include -#include "llassetstorage.h" #include "lldynamictexture.h" -#include "llrect.h" -#include "llstring.h" -#include "lluuid.h" -#include "llviewertexture.h" -#include "llviewervisualparam.h" #include "llvoavatardefines.h" -#include "llwearable.h" -#include "v4color.h" -#include "llfloater.h" -#include "llvoavatar.h" +#include "lltexlayerparams.h" -class LLTexLayerSetInfo; -class LLTexLayerSet; -class LLTexLayerInfo; -class LLTexLayer; -class LLViewerTexture; -class LLImageTGA; -class LLTexGlobalColorInfo; -class LLTexLayerParamAlphaInfo; -class LLTexLayerParamAlpha; -class LLTexParamColorInfo; -class LLTexParamColor; -class LLPolyMesh; -class LLXmlTreeNode; -class LLImageRaw; -class LLPolyMorphTarget; -class LLViewerTexture; - -class LLTextureCtrl; class LLVOAvatar; +class LLVOAvatarSelf; +class LLImageTGA; +class LLImageRaw; +class LLXmlTreeNode; +class LLTexLayerSet; +class LLTexLayerSetInfo; +class LLTexLayerInfo; +class LLTexLayerSetBuffer; +class LLWearable; +class LLViewerVisualParam; +class LLPolyMorphTarget; - -enum EColorOperation +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerInterface +// +// Interface class to generalize functionality shared by LLTexLayer +// and LLTexLayerTemplate. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerInterface { - OP_ADD = 0, - OP_MULTIPLY = 1, - OP_BLEND = 2, - OP_COUNT = 3 // Number of operations -}; - - -//----------------------------------------------------------------------------- -// LLTexLayerParamAlphaInfo -//----------------------------------------------------------------------------- -class LLTexLayerParamAlphaInfo : public LLViewerVisualParamInfo -{ - friend class LLTexLayerParamAlpha; public: - LLTexLayerParamAlphaInfo(); - /*virtual*/ ~LLTexLayerParamAlphaInfo() {}; + enum ERenderPass + { + RP_COLOR, + RP_BUMP, + RP_SHINE + }; - /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); + LLTexLayerInterface(LLTexLayerSet* const layer_set); + virtual ~LLTexLayerInterface() {} + + virtual BOOL render(S32 x, S32 y, S32 width, S32 height) = 0; + virtual void deleteCaches() = 0; + virtual BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) = 0; + virtual BOOL isInvisibleAlphaMask() const = 0; + + const LLTexLayerInfo* getInfo() const { return mInfo; } + virtual BOOL setInfo(const LLTexLayerInfo *info); // sets mInfo, calls initialization functions + + const std::string& getName() const; + const LLTexLayerSet* const getTexLayerSet() const { return mTexLayerSet; } + LLTexLayerSet* const getTexLayerSet() { return mTexLayerSet; } + + void invalidateMorphMasks(); + virtual void setHasMorph(BOOL newval) { mHasMorph = newval; } + BOOL hasMorph() const { return mHasMorph; } + BOOL isMorphValid() const { return mMorphMasksValid; } + void addMaskedMorph(LLPolyMorphTarget* morph_target, BOOL invert); + void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components); + + void requestUpdate(); + virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) = 0; + BOOL hasAlphaParams() const { return !mParamAlphaList.empty(); } + + ERenderPass getRenderPass() const; + BOOL isVisibilityMask() const; protected: - std::string mStaticImageFileName; - BOOL mMultiplyBlend; - BOOL mSkipIfZeroWeight; - F32 mDomain; -}; + const std::string& getGlobalColor() const; + LLViewerVisualParam* getVisualParamPtr(S32 index) const; -//----------------------------------------------------------------------------- -// LLTexParamColorInfo -//----------------------------------------------------------------------------- -class LLTexParamColorInfo : public LLViewerVisualParamInfo -{ - friend class LLTexParamColor; - -public: - LLTexParamColorInfo(); - virtual ~LLTexParamColorInfo() {}; - BOOL parseXml( LLXmlTreeNode* node ); - protected: - enum { MAX_COLOR_VALUES = 20 }; - EColorOperation mOperation; - LLColor4 mColors[MAX_COLOR_VALUES]; - S32 mNumColors; -}; + LLTexLayerSet* const mTexLayerSet; + const LLTexLayerInfo* mInfo; + BOOL mMorphMasksValid; + BOOL mHasMorph; -//----------------------------------------------------------------------------- -// LLTexGlobalColorInfo -//----------------------------------------------------------------------------- -class LLTexGlobalColorInfo -{ - friend class LLTexGlobalColor; -public: - LLTexGlobalColorInfo(); - ~LLTexGlobalColorInfo(); - - BOOL parseXml(LLXmlTreeNode* node); + // Layers can have either mParamColorList, mGlobalColor, or mFixedColor. They are looked for in that order. + param_color_list_t mParamColorList; + param_alpha_list_t mParamAlphaList; + // mGlobalColor name stored in mInfo + // mFixedColor value stored in mInfo -protected: - typedef std::vector color_info_list_t; - color_info_list_t mColorInfoList; - std::string mName; + typedef std::deque morph_list_t; //Hack. + morph_list_t mMaskedMorphs; }; -//----------------------------------------------------------------------------- +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayer +// +// A single texture layer. Only exists for llvoavatarself. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayer : public LLTexLayerInterface +{ +public: + LLTexLayer(LLTexLayerSet* const layer_set); + /*virtual*/ ~LLTexLayer(); + + /*virtual*/ BOOL setInfo(const LLTexLayerInfo *info); // This sets mInfo and calls initialization functions + /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height); + + /*virtual*/ void deleteCaches(); + const U8* getAlphaData() const; + + BOOL findNetColor(LLColor4* color) const; + /*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer + /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height); + BOOL renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color); + void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height); + /*virtual*/ BOOL isInvisibleAlphaMask() const; + + + static void calculateTexLayerColor(const param_color_list_t ¶m_list, LLColor4 &net_color); +protected: + LLUUID getUUID() const; + LLPointer mStaticImageRaw; +private: + typedef std::map alpha_cache_t; + alpha_cache_t mAlphaCache; + BOOL mStaticImageInvalid; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerSet +// +// An ordered set of texture layers that gets composited into a single texture. +// Only exists for llvoavatarself. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerSet +{ + friend class LLTexLayerSetBuffer; +public: + LLTexLayerSet(LLVOAvatarSelf* const avatar); + ~LLTexLayerSet(); + + const LLTexLayerSetInfo* getInfo() const { return mInfo; } + BOOL setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions + + BOOL render(S32 x, S32 y, S32 width, S32 height); + void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear = false); + + BOOL isBodyRegion(const std::string& region) const; + LLTexLayerSetBuffer* getComposite(); + const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist. + void requestUpdate(); + void requestUpload(); + void cancelUpload(); + void updateComposite(); + BOOL isLocalTextureDataAvailable() const; + BOOL isLocalTextureDataFinal() const; + void createComposite(); + void destroyComposite(); + void setUpdatesEnabled(BOOL b); + BOOL getUpdatesEnabled() const { return mUpdatesEnabled; } + void deleteCaches(); + void gatherMorphMaskAlpha(U8 *data, S32 width, S32 height); + void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components); + BOOL isMorphValid() const; + void invalidateMorphMasks(); + LLTexLayerInterface* findLayerByName(const std::string& name); + + LLVOAvatarSelf* getAvatar() const { return mAvatar; } + const std::string getBodyRegionName() const; + BOOL hasComposite() const { return (mComposite.notNull()); } + LLVOAvatarDefines::EBakedTextureIndex getBakedTexIndex() { return mBakedTexIndex; } + void setBakedTexIndex(LLVOAvatarDefines::EBakedTextureIndex index) { mBakedTexIndex = index; } + BOOL isVisible() const { return mIsVisible; } + + static BOOL sHasCaches; + +private: + typedef std::vector layer_list_t; + layer_list_t mLayerList; + layer_list_t mMaskLayerList; + LLPointer mComposite; + LLVOAvatarSelf* const mAvatar; // note: backlink only; don't make this an LLPointer. + BOOL mUpdatesEnabled; + BOOL mIsVisible; + + LLVOAvatarDefines::EBakedTextureIndex mBakedTexIndex; + const LLTexLayerSetInfo* mInfo; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLTexLayerSetInfo -// Containes shared layer set data -//----------------------------------------------------------------------------- +// +// Contains shared layer set data. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLTexLayerSetInfo { friend class LLTexLayerSet; public: LLTexLayerSetInfo(); ~LLTexLayerSetInfo(); - BOOL parseXml(LLXmlTreeNode* node); - -protected: +private: std::string mBodyRegion; S32 mWidth; S32 mHeight; std::string mStaticAlphaFileName; - BOOL mClearAlpha; // Set alpha to 1 for this layerset (if there is no mStaticAlphaFileName) - + BOOL mClearAlpha; // Set alpha to 1 for this layerset (if there is no mStaticAlphaFileName) typedef std::vector layer_info_list_t; layer_info_list_t mLayerInfoList; }; -//----------------------------------------------------------------------------- -// LLTexLayerInfo -//----------------------------------------------------------------------------- -enum ERenderPass -{ - RP_COLOR, - RP_BUMP, - RP_SHINE -}; - -class LLTexLayerInfo -{ - friend class LLTexLayer; -public: - LLTexLayerInfo(); - ~LLTexLayerInfo(); - - BOOL parseXml(LLXmlTreeNode* node); - -protected: - std::string mName; - - BOOL mWriteAllChannels; // Don't use masking. Just write RGBA into buffer, - ERenderPass mRenderPass; - - std::string mGlobalColor; - LLColor4 mFixedColor; - - S32 mLocalTexture; - std::string mStaticImageFileName; - BOOL mStaticImageIsMask; - BOOL mUseLocalTextureAlphaOnly; // Ignore RGB channels from the input texture. Use alpha as a mask - BOOL mIsVisibilityMask; - - typedef std::vector > morph_name_list_t; - morph_name_list_t mMorphNameList; - - typedef std::vector color_info_list_t; - color_info_list_t mColorInfoList; - - typedef std::vector alpha_info_list_t; - alpha_info_list_t mAlphaInfoList; - -}; - -//----------------------------------------------------------------------------- +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLTexLayerSetBuffer +// // The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one. -//----------------------------------------------------------------------------- +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLTexLayerSetBuffer : public LLViewerDynamicTexture { public: - LLTexLayerSetBuffer(LLTexLayerSet* owner, S32 width, S32 height); + LLTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height); virtual ~LLTexLayerSetBuffer(); +public: + /*virtual*/ S8 getType() const; + BOOL isInitialized(void) const; + static void dumpTotalByteCount(); + virtual void restoreGLTexture(); + virtual void destroyGLTexture(); +protected: + void pushProjection() const; + void popProjection() const; +private: + LLTexLayerSet* const mTexLayerSet; + static S32 sGLByteCount; + + //-------------------------------------------------------------------- + // Render + //-------------------------------------------------------------------- +public: + /*virtual*/ BOOL needsRender(); +protected: + BOOL render(S32 x, S32 y, S32 width, S32 height); virtual void preRender(BOOL clear_depth); virtual void postRender(BOOL success); - virtual BOOL render(); - BOOL updateImmediate(); - bool isInitialized(void) const; - BOOL needsRender(); - void requestUpdate(); + virtual BOOL render(); + + //-------------------------------------------------------------------- + // Uploads + //-------------------------------------------------------------------- +public: void requestUpload(); void requestDelayedUpload(U64 delay_usec); - void cancelUpload(); - BOOL uploadPending() { return mUploadPending; } - BOOL render( S32 x, S32 y, S32 width, S32 height ); - void readBackAndUpload(); - - static void onTextureUploadComplete( const LLUUID& uuid, - void* userdata, - S32 result, LLExtStat ext_status); - static void dumpTotalByteCount(); - - virtual S8 getType() const ; - virtual void restoreGLTexture() ; - virtual void destroyGLTexture() ; - -private: - void pushProjection(); - void popProjection(); BOOL needsUploadNow() const; - -private: - BOOL mNeedsUpdate; - BOOL mNeedsUpload; - BOOL mUploadPending; - LLUUID mUploadID; // Identifys the current upload process (null if none). Used to avoid overlaps (eg, when the user rapidly makes two changes outside of Face Edit) - S32 mUploadFailCount; - U64 mUploadAfter; // delay upload until after this time (in microseconds) - LLTexLayerSet* mTexLayerSet; - - static S32 sGLByteCount; -}; - -//----------------------------------------------------------------------------- -// LLTexLayerSet -// An ordered set of texture layers that get composited into a single texture. -//----------------------------------------------------------------------------- -class LLTexLayerSet -{ - friend class LLTexLayerSetBuffer; -public: - LLTexLayerSet( LLVOAvatarSelf* avatar ); - ~LLTexLayerSet(); - - //BOOL parseData(LLXmlTreeNode* node); - LLTexLayerSetInfo* getInfo() const { return mInfo; } - // This sets mInfo and calls initialization functions - BOOL setInfo(LLTexLayerSetInfo *info); - - BOOL render( S32 x, S32 y, S32 width, S32 height ); - void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear = false); - BOOL isBodyRegion( const std::string& region ) { return mInfo->mBodyRegion == region; } - LLTexLayerSetBuffer* getComposite(); - void requestUpdate(); - void requestUpload(); void cancelUpload(); - LLVOAvatarSelf* getAvatar() { return mAvatar; } - void updateComposite(); - BOOL isLocalTextureDataAvailable(); - BOOL isLocalTextureDataFinal(); - void createComposite(); - void destroyComposite(); - void setUpdatesEnabled( BOOL b ); - BOOL getUpdatesEnabled() { return mUpdatesEnabled; } - void deleteCaches(); - void gatherAlphaMasks(U8 *data, S32 width, S32 height); - void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components); - const std::string getBodyRegion() { return mInfo->mBodyRegion; } - BOOL hasComposite() { return (mComposite.notNull()); } - LLVOAvatarDefines::EBakedTextureIndex getBakedTexIndex() { return mBakedTexIndex; } - void setBakedTexIndex(LLVOAvatarDefines::EBakedTextureIndex index) { mBakedTexIndex = index; } - BOOL isVisible() const { return mIsVisible; } + BOOL uploadPending() const; // We are expecting a new texture to be uploaded at some point + static void onTextureUploadComplete(const LLUUID& uuid, + void* userdata, + S32 result, LLExtStat ext_status); + void doUpload(); // Does a read back and upload. +private: + + BOOL mNeedsUpload; // Whether we need to send our baked textures to the server + BOOL mUploadPending; // Whether we have received back the new baked textures + LLUUID mUploadID; // The current upload process (null if none). + S32 mUploadFailCount; // Number of consecutive upload failures + BOOL mNeedsUpdate; + U64 mUploadAfter; // delay upload until after this time (in microseconds) + //-------------------------------------------------------------------- + // Updates + //-------------------------------------------------------------------- public: - static BOOL sHasCaches; - -protected: - typedef std::vector layer_list_t; - layer_list_t mLayerList; - layer_list_t mMaskLayerList; - LLPointer mComposite; - // Backlink only; don't make this an LLPointer. - LLVOAvatarSelf* mAvatar; - BOOL mUpdatesEnabled; - BOOL mIsVisible; - - LLVOAvatarDefines::EBakedTextureIndex mBakedTexIndex; - - LLTexLayerSetInfo *mInfo; -}; - -//----------------------------------------------------------------------------- -// LLTexLayer -// A single texture layer -//----------------------------------------------------------------------------- -class LLTexLayer -{ -public: - LLTexLayer( LLTexLayerSet* layer_set ); - ~LLTexLayer(); - - //BOOL parseData(LLXmlTreeNode* node); - LLTexLayerInfo* getInfo() const { return mInfo; } - // This sets mInfo and calls initialization functions - BOOL setInfo(LLTexLayerInfo *info); - - BOOL render( S32 x, S32 y, S32 width, S32 height ); void requestUpdate(); - LLTexLayerSet* getTexLayerSet() { return mTexLayerSet; } - - const std::string& getName() { return mInfo->mName; } - - void addMaskedMorph(LLPolyMorphTarget* morph_target, BOOL invert); - void deleteCaches(); - U8* getAlphaData(); - void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components); - - void invalidateMorphMasks(); - ERenderPass getRenderPass() { return mInfo->mRenderPass; } - const std::string& getGlobalColor() { return mInfo->mGlobalColor; } - BOOL findNetColor( LLColor4* color ); - BOOL renderImageRaw( U8* in_data, S32 in_width, S32 in_height, S32 in_components, S32 width, S32 height, BOOL is_mask ); - BOOL renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4* colorp ); - BOOL hasAlphaParams() { return (!mParamAlphaList.empty());} - BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); - BOOL isVisibilityMask() const; - BOOL isInvisibleAlphaMask(); - -protected: - LLTexLayerSet* mTexLayerSet; - LLPointer mStaticImageRaw; - - // Layers can have either mParamColorList, mGlobalColor, or mFixedColor. They are looked for in that order. - typedef std::vector color_list_t; - color_list_t mParamColorList; - // mGlobalColor name stored in mInfo - // mFixedColor value stored in mInfo - - typedef std::vector alpha_list_t; - alpha_list_t mParamAlphaList; - - - typedef std::deque morph_list_t; - morph_list_t mMaskedMorphs; - typedef std::map alpha_cache_t; - alpha_cache_t mAlphaCache; - BOOL mMorphMasksValid; - BOOL mStaticImageInvalid; - - LLTexLayerInfo *mInfo; + BOOL requestUpdateImmediate(); }; -//----------------------------------------------------------------------------- -// LLTexLayerParamAlpha -//----------------------------------------------------------------------------- -class LLTexLayerParamAlpha : public LLViewerVisualParam +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerStaticImageList +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerStaticImageList : public LLSingleton { public: - LLTexLayerParamAlpha( LLTexLayer* layer ); - /*virtual*/ ~LLTexLayerParamAlpha(); - - // Special: These functions are overridden by child classes - LLTexLayerParamAlphaInfo* getInfo() const { return (LLTexLayerParamAlphaInfo*)mInfo; } - // This sets mInfo and calls initialization functions - BOOL setInfo(LLTexLayerParamAlphaInfo *info); - - // LLVisualParam Virtual functions - ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); - /*virtual*/ void apply( ESex avatar_sex ) {} - /*virtual*/ void setWeight(F32 weight, BOOL set_by_user); - /*virtual*/ void setAnimationTarget(F32 target_value, BOOL set_by_user); - /*virtual*/ void animate(F32 delta, BOOL set_by_user); - - // LLViewerVisualParam Virtual functions - /*virtual*/ F32 getTotalDistortion() { return 1.f; } - /*virtual*/ const LLVector3& getAvgDistortion() { return mAvgDistortionVec; } - /*virtual*/ F32 getMaxDistortion() { return 3.f; } - /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector3(1.f, 1.f, 1.f);} - /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; - /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; - - // New functions - BOOL render( S32 x, S32 y, S32 width, S32 height ); - BOOL getSkip(); - void deleteCaches(); - LLTexLayer* getTexLayer() { return mTexLayer; } - BOOL getMultiplyBlend() { return getInfo()->mMultiplyBlend; } - -protected: - LLPointer mCachedProcessedTexture; - LLTexLayer* mTexLayer; - LLPointer mStaticImageTGA; - LLPointer mStaticImageRaw; - BOOL mNeedsCreateTexture; - BOOL mStaticImageInvalid; - LLVector3 mAvgDistortionVec; - F32 mCachedEffectiveWeight; - -public: - // Global list of instances for gathering statistics - static void dumpCacheByteCount(); - static void getCacheByteCount( S32* gl_bytes ); - - typedef std::list< LLTexLayerParamAlpha* > param_alpha_ptr_list_t; - static param_alpha_ptr_list_t sInstances; -}; - - -//----------------------------------------------------------------------------- -// LLTexGlobalColor -//----------------------------------------------------------------------------- -class LLTexGlobalColor -{ -public: - LLTexGlobalColor( LLVOAvatar* avatar ); - ~LLTexGlobalColor(); - - //BOOL parseData(LLXmlTreeNode* node); - LLTexGlobalColorInfo* getInfo() const { return mInfo; } - // This sets mInfo and calls initialization functions - BOOL setInfo(LLTexGlobalColorInfo *info); - - void requstUpdate(); - LLVOAvatar* getAvatar() { return mAvatar; } - LLColor4 getColor(); - const std::string& getName() { return mInfo->mName; } - -protected: - typedef std::vector param_list_t; - param_list_t mParamList; - LLVOAvatar* mAvatar; // just backlink, don't LLPointer - - LLTexGlobalColorInfo *mInfo; -}; - - -//----------------------------------------------------------------------------- -// LLTexParamColor -//----------------------------------------------------------------------------- -class LLTexParamColor : public LLViewerVisualParam -{ -public: - LLTexParamColor( LLTexGlobalColor* tex_color ); - LLTexParamColor( LLTexLayer* layer ); - /* virtual */ ~LLTexParamColor(); - - // Special: These functions are overridden by child classes - LLTexParamColorInfo* getInfo() const { return (LLTexParamColorInfo*)mInfo; } - // This sets mInfo and calls initialization functions - BOOL setInfo(LLTexParamColorInfo *info); - - // LLVisualParam Virtual functions - ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); - /*virtual*/ void apply( ESex avatar_sex ) {} - /*virtual*/ void setWeight(F32 weight, BOOL set_by_user); - /*virtual*/ void setAnimationTarget(F32 target_value, BOOL set_by_user); - /*virtual*/ void animate(F32 delta, BOOL set_by_user); - - - // LLViewerVisualParam Virtual functions - /*virtual*/ F32 getTotalDistortion() { return 1.f; } - /*virtual*/ const LLVector3& getAvgDistortion() { return mAvgDistortionVec; } - /*virtual*/ F32 getMaxDistortion() { return 3.f; } - /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector3(1.f, 1.f, 1.f); } - /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; - /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; - - // New functions - LLColor4 getNetColor(); - EColorOperation getOperation() const { return getInfo()->mOperation; } - - -protected: - LLVector3 mAvgDistortionVec; - LLTexGlobalColor* mTexGlobalColor; // either has mTexGlobalColor or mTexLayer as its parent - LLTexLayer* mTexLayer; - LLVOAvatar* mAvatar; // redundant, but simplifies the code (don't LLPointer) -}; - -//----------------------------------------------------------------------------- -// LLTexStaticImageList -//----------------------------------------------------------------------------- - -class LLTexStaticImageList -{ -public: - LLTexStaticImageList(); - ~LLTexStaticImageList(); - - LLImageRaw* getImageRaw( const std::string& file_name ); - LLViewerTexture* getTexture( const std::string& file_name, BOOL is_mask ); - LLImageTGA* getImageTGA( const std::string& file_name ); - + LLTexLayerStaticImageList(); + ~LLTexLayerStaticImageList(); + LLViewerTexture* getTexture(const std::string& file_name, BOOL is_mask); + LLImageTGA* getImageTGA(const std::string& file_name); void deleteCachedImages(); void dumpByteCount() const; protected: BOOL loadImageRaw(const std::string& file_name, LLImageRaw* image_raw); - private: - static LLStringTable sImageNames; - + LLStringTable mImageNames; typedef std::map > texture_map_t; texture_map_t mStaticImageList; typedef std::map > image_tga_map_t; image_tga_map_t mStaticImageListTGA; -public: S32 mGLBytes; S32 mTGABytes; }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLBakedUploadData +// // Used by LLTexLayerSetBuffer for a callback. - -// For DEV-DEV-31590, "Heap corruption and crash after outfit -// changes", added the mLayerSet member. The current -// LLTexLayerSetBuffer can be found by querying mLayerSet->mComposite, -// but we still store the original mLayerSetBuffer here so we can -// detect when an upload is out of date. This prevents a memory -// stomp. See LLTexLayerSetBuffer::onTextureUploadComplete() for usage. -class LLBakedUploadData +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +struct LLBakedUploadData { -public: - LLBakedUploadData( LLVOAvatarSelf* avatar, LLTexLayerSet* layerset, LLTexLayerSetBuffer* layerset_buffer, const LLUUID & id); + LLBakedUploadData(const LLVOAvatarSelf* avatar, + LLTexLayerSet* layerset, + const LLUUID& id); ~LLBakedUploadData() {} + const LLUUID mID; + const LLVOAvatarSelf* mAvatar; // note: backlink only; don't LLPointer + LLTexLayerSet* mTexLayerSet; - LLUUID mID; - LLVOAvatarSelf* mAvatar; // just backlink, don't LLPointer - LLTexLayerSet* mTexLayerSet; - LLTexLayerSetBuffer* mLayerSetBuffer; - LLUUID mWearableAssets[LLWearableType::WT_COUNT]; - U64 mStartTime; // Used to measure time baked texture upload requires + const U64 mStartTime; // for measuring baked texture upload time }; -extern LLTexStaticImageList gTexStaticImageList; - - #endif // LL_LLTEXLAYER_H diff --git a/indra/newview/lltexlayerparams.cpp b/indra/newview/lltexlayerparams.cpp index ee6e534d2..8fb17e0c2 100644 --- a/indra/newview/lltexlayerparams.cpp +++ b/indra/newview/lltexlayerparams.cpp @@ -145,13 +145,6 @@ LLTexLayerParamAlpha::~LLTexLayerParamAlpha() sInstances.remove(this); } -/*virtual*/ LLViewerVisualParam* LLTexLayerParamAlpha::cloneParam(LLWearable* wearable) const -{ - LLTexLayerParamAlpha *new_param = new LLTexLayerParamAlpha(mTexLayer); - *new_param = *this; - return new_param; -} - void LLTexLayerParamAlpha::deleteCaches() { mStaticImageTGA = NULL; // deletes image @@ -188,6 +181,7 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL upload_bake) } mAvatar->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake); mTexLayer->invalidateMorphMasks(); + mAvatar->updateMeshTextures(); } } } @@ -323,14 +317,14 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) // Create the GL texture, and then hang onto it for future use. if (mNeedsCreateTexture) { - mCachedProcessedTexture->createGLTexture(0, mStaticImageRaw); + mCachedProcessedTexture->createGLTexture(0, mStaticImageRaw, 0, TRUE, LLViewerTexture::BOOST_AVATAR_SELF); mNeedsCreateTexture = FALSE; gGL.getTexUnit(0)->bind(mCachedProcessedTexture); mCachedProcessedTexture->setAddressMode(LLTexUnit::TAM_CLAMP); } LLGLSNoAlphaTest gls_no_alpha_test; - gGL.getTexUnit(0)->bind(mCachedProcessedTexture); + gGL.getTexUnit(0)->bind(mCachedProcessedTexture, TRUE); gl_rect_2d_simple_tex(width, height); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); stop_glerror(); @@ -419,12 +413,6 @@ LLTexLayerParamColor::~LLTexLayerParamColor() { } -/*virtual*/ LLViewerVisualParam* LLTexLayerParamColor::cloneParam(LLWearable* wearable) const -{ - LLTexLayerParamColor *new_param = new LLTexLayerParamColor(mTexLayer); - *new_param = *this; - return new_param; -} LLColor4 LLTexLayerParamColor::getNetColor() const { @@ -521,7 +509,7 @@ LLTexLayerParamColorInfo::LLTexLayerParamColorInfo() : BOOL LLTexLayerParamColorInfo::parseXml(LLXmlTreeNode *node) { - llassert(node->hasName("param") && node->getChildByName("param_color")); + llassert( node->hasName( "param" ) && node->getChildByName( "param_color" ) ); if (!LLViewerVisualParamInfo::parseXml(node)) return FALSE; diff --git a/indra/newview/lltexlayerparams.h b/indra/newview/lltexlayerparams.h new file mode 100644 index 000000000..c8ae2017c --- /dev/null +++ b/indra/newview/lltexlayerparams.h @@ -0,0 +1,187 @@ +/** + * @file lltexlayerparams.h + * @brief Texture layer parameters, used by lltexlayer. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLTEXLAYERPARAMS_H +#define LL_LLTEXLAYERPARAMS_H + +#include "llviewervisualparam.h" + +class LLImageRaw; +class LLImageTGA; +class LLTexLayer; +class LLTexLayerInterface; +class LLViewerTexture; +class LLVOAvatar; +class LLWearable; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerParam +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerParam : public LLViewerVisualParam +{ +public: + LLTexLayerParam(LLTexLayerInterface *layer); + LLTexLayerParam(LLVOAvatar *avatar); + /*virtual*/ BOOL setInfo(LLViewerVisualParamInfo *info, BOOL add_to_avatar ); +protected: + LLTexLayerInterface* mTexLayer; + LLVOAvatar* mAvatar; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerParamAlpha +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerParamAlpha : public LLTexLayerParam +{ +public: + LLTexLayerParamAlpha( LLTexLayerInterface* layer ); + LLTexLayerParamAlpha( LLVOAvatar* avatar ); + /*virtual*/ ~LLTexLayerParamAlpha(); + + // LLVisualParam Virtual functions + ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); + /*virtual*/ void apply( ESex avatar_sex ) {} + /*virtual*/ void setWeight(F32 weight, BOOL upload_bake); + /*virtual*/ void setAnimationTarget(F32 target_value, BOOL upload_bake); + /*virtual*/ void animate(F32 delta, BOOL upload_bake); + + // LLViewerVisualParam Virtual functions + /*virtual*/ F32 getTotalDistortion() { return 1.f; } + /*virtual*/ const LLVector3& getAvgDistortion() { return mAvgDistortionVec; } + /*virtual*/ F32 getMaxDistortion() { return 3.f; } + /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector3(1.f, 1.f, 1.f);} + /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; + /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; + + // New functions + BOOL render( S32 x, S32 y, S32 width, S32 height ); + BOOL getSkip() const; + void deleteCaches(); + BOOL getMultiplyBlend() const; + +private: + LLPointer mCachedProcessedTexture; + LLPointer mStaticImageTGA; + LLPointer mStaticImageRaw; + BOOL mNeedsCreateTexture; + BOOL mStaticImageInvalid; + LLVector3 mAvgDistortionVec; + F32 mCachedEffectiveWeight; + +public: + // Global list of instances for gathering statistics + static void dumpCacheByteCount(); + static void getCacheByteCount( S32* gl_bytes ); + + typedef std::list< LLTexLayerParamAlpha* > param_alpha_ptr_list_t; + static param_alpha_ptr_list_t sInstances; +}; +class LLTexLayerParamAlphaInfo : public LLViewerVisualParamInfo +{ + friend class LLTexLayerParamAlpha; +public: + LLTexLayerParamAlphaInfo(); + /*virtual*/ ~LLTexLayerParamAlphaInfo() {}; + + /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); + +private: + std::string mStaticImageFileName; + BOOL mMultiplyBlend; + BOOL mSkipIfZeroWeight; + F32 mDomain; +}; +// +// LLTexLayerParamAlpha +//----------------------------------------------------------------------------- + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerParamColor +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerParamColor : public LLTexLayerParam +{ +public: + enum EColorOperation + { + OP_ADD = 0, + OP_MULTIPLY = 1, + OP_BLEND = 2, + OP_COUNT = 3 // Number of operations + }; + + LLTexLayerParamColor( LLTexLayerInterface* layer ); + LLTexLayerParamColor( LLVOAvatar* avatar ); + /* virtual */ ~LLTexLayerParamColor(); + + // LLVisualParam Virtual functions + ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); + /*virtual*/ void apply( ESex avatar_sex ) {} + /*virtual*/ void setWeight(F32 weight, BOOL upload_bake); + /*virtual*/ void setAnimationTarget(F32 target_value, BOOL upload_bake); + /*virtual*/ void animate(F32 delta, BOOL upload_bake); + + + // LLViewerVisualParam Virtual functions + /*virtual*/ F32 getTotalDistortion() { return 1.f; } + /*virtual*/ const LLVector3& getAvgDistortion() { return mAvgDistortionVec; } + /*virtual*/ F32 getMaxDistortion() { return 3.f; } + /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector3(1.f, 1.f, 1.f); } + /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; + /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; + + // New functions + LLColor4 getNetColor() const; +protected: + virtual void onGlobalColorChanged(bool upload_bake) {} +private: + LLVector3 mAvgDistortionVec; +}; + +class LLTexLayerParamColorInfo : public LLViewerVisualParamInfo +{ + friend class LLTexLayerParamColor; + +public: + LLTexLayerParamColorInfo(); + virtual ~LLTexLayerParamColorInfo() {}; + BOOL parseXml( LLXmlTreeNode* node ); + LLTexLayerParamColor::EColorOperation getOperation() const { return mOperation; } +private: + enum { MAX_COLOR_VALUES = 20 }; + LLTexLayerParamColor::EColorOperation mOperation; + LLColor4 mColors[MAX_COLOR_VALUES]; + S32 mNumColors; +}; + +typedef std::vector param_color_list_t; +typedef std::vector param_alpha_list_t; +typedef std::vector param_color_info_list_t; +typedef std::vector param_alpha_info_list_t; + +#endif diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 7a7cd1660..3940662c7 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -45,6 +45,7 @@ #include "llviewerobjectlist.h" #include "llviewertexturelist.h" #include "lltexlayer.h" +#include "lltexlayerparams.h" #include "llsurface.h" #include "llvlmanager.h" #include "llagent.h" @@ -525,7 +526,7 @@ void output_statistics(void*) llinfos << "--------------------------------" << llendl; llinfos << "Avatar Memory (partly overlaps with above stats):" << llendl; - gTexStaticImageList.dumpByteCount(); + LLTexLayerStaticImageList::getInstance()->dumpByteCount(); LLVOAvatarSelf::dumpScratchTextureByteCount(); LLTexLayerSetBuffer::dumpTotalByteCount(); LLVOAvatarSelf::dumpTotalLocalTextureByteCount(); diff --git a/indra/newview/llviewervisualparam.cpp b/indra/newview/llviewervisualparam.cpp index 733fd485e..07d83326b 100644 --- a/indra/newview/llviewervisualparam.cpp +++ b/indra/newview/llviewervisualparam.cpp @@ -119,12 +119,6 @@ LLViewerVisualParam::LLViewerVisualParam() { } -/* -//============================================================================= -// These virtual functions should always be overridden, -// but are included here for use as templates -//============================================================================= - //----------------------------------------------------------------------------- // setInfo() //----------------------------------------------------------------------------- @@ -139,7 +133,7 @@ BOOL LLViewerVisualParam::setInfo(LLViewerVisualParamInfo *info) setWeight(getDefaultWeight(), FALSE ); return TRUE; } - +/* //----------------------------------------------------------------------------- // parseData() //----------------------------------------------------------------------------- diff --git a/indra/newview/llviewervisualparam.h b/indra/newview/llviewervisualparam.h index 48d28cebf..77a95db56 100644 --- a/indra/newview/llviewervisualparam.h +++ b/indra/newview/llviewervisualparam.h @@ -90,7 +90,7 @@ public: virtual const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **mesh) = 0; // interface methods - F32 getDisplayOrder() { return getInfo()->mEditGroupDisplayOrder; } + F32 getDisplayOrder() const { return getInfo()->mEditGroupDisplayOrder; } S32 getWearableType() const { return getInfo()->mWearableType; } const std::string& getEditGroup() const { return getInfo()->mEditGroup; } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 19ee949c6..a28282a3e 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1131,7 +1131,7 @@ void LLVOAvatar::deleteCachedImages(bool clearAll) } LLVOAvatarSelf::deleteScratchTextures(); - gTexStaticImageList.deleteCachedImages(); + LLTexLayerStaticImageList::getInstance()->deleteCachedImages(); } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 6dafdcac1..b7fd8755b 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -49,6 +49,7 @@ #include "llrendertarget.h" #include "llwearable.h" #include "llvoavatardefines.h" +#include "lltexglobalcolor.h" #include "emeraldboobutils.h" #include "llavatarname.h"