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