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.cpp852
1 files changed, 481 insertions, 371 deletions
diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp
index 5a5f187415..de8458c0fa 100644
--- a/indra/newview/lltexlayer.cpp
+++ b/indra/newview/lltexlayer.cpp
@@ -41,6 +41,9 @@
#include "llassetuploadresponders.h"
#include "lltexlayerparams.h"
#include "llui.h"
+#include "llagentwearables.h"
+#include "llwearable.h"
+#include "llviewervisualparam.h"
//#include "../tools/imdebug/imdebug.h"
@@ -66,90 +69,45 @@ LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar,
// static
S32 LLTexLayerSetBuffer::sGLByteCount = 0;
-S32 LLTexLayerSetBuffer::sGLBumpByteCount = 0;
LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner,
- S32 width, S32 height,
- BOOL has_bump) :
+ 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
- mTexLayerSet(owner),
- mHasBump(has_bump),
- mBumpTex(NULL)
+ mTexLayerSet(owner)
{
LLTexLayerSetBuffer::sGLByteCount += getSize();
- createBumpTexture() ;
}
LLTexLayerSetBuffer::~LLTexLayerSetBuffer()
{
LLTexLayerSetBuffer::sGLByteCount -= getSize();
-
- if( mBumpTex.notNull())
+ destroyGLTexture();
+ for( S32 order = 0; order < ORDER_COUNT; order++ )
{
- mBumpTex = NULL ;
- LLImageGL::sGlobalTextureMemoryInBytes -= mFullWidth * mFullHeight * 4;
- LLTexLayerSetBuffer::sGLBumpByteCount -= mFullWidth * mFullHeight * 4;
+ LLViewerDynamicTexture::sInstances[order].erase(this); // will fail in all but one case.
}
}
//virtual
void LLTexLayerSetBuffer::restoreGLTexture()
{
- createBumpTexture() ;
LLViewerDynamicTexture::restoreGLTexture() ;
}
//virtual
void LLTexLayerSetBuffer::destroyGLTexture()
{
- if( mBumpTex.notNull() )
- {
- mBumpTex = NULL ;
- LLImageGL::sGlobalTextureMemoryInBytes -= mFullWidth * mFullHeight * 4;
- LLTexLayerSetBuffer::sGLBumpByteCount -= mFullWidth * mFullHeight * 4;
- }
-
LLViewerDynamicTexture::destroyGLTexture() ;
}
-void LLTexLayerSetBuffer::createBumpTexture()
-{
- if( mHasBump )
- {
- LLGLSUIDefault gls_ui;
- mBumpTex = LLViewerTextureManager::getLocalTexture(FALSE) ;
- if(!mBumpTex->createGLTexture())
- {
- mBumpTex = NULL ;
- return ;
- }
-
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTex->getTexName());
- stop_glerror();
-
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
-
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-
- 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 += mFullWidth * mFullHeight * 4;
- LLTexLayerSetBuffer::sGLBumpByteCount += mFullWidth * mFullHeight * 4;
- }
-}
-
// static
void LLTexLayerSetBuffer::dumpTotalByteCount()
{
llinfos << "Composite System GL Buffers: " << (LLTexLayerSetBuffer::sGLByteCount/1024) << "KB" << llendl;
- llinfos << "Composite System GL Bump Buffers: " << (LLTexLayerSetBuffer::sGLBumpByteCount/1024) << "KB" << llendl;
}
void LLTexLayerSetBuffer::requestUpdate()
@@ -242,8 +200,6 @@ void LLTexLayerSetBuffer::postRender(BOOL success)
BOOL LLTexLayerSetBuffer::render()
{
- U8* baked_bump_data = NULL;
-
// Default color mask for tex layer render
gGL.setColorMask(true, true);
@@ -252,33 +208,6 @@ BOOL LLTexLayerSetBuffer::render()
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, mFullWidth, mFullHeight );
- stop_glerror();
-
- if (success)
- {
- LLGLSUIDefault gls_ui;
-
- // read back into texture (this is done externally for the color data)
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTex->getTexName());
- stop_glerror();
-
- 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[ mFullWidth * mFullHeight * 4 ];
- glReadPixels(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_bump_data );
- stop_glerror();
- }
- }
- }
// Composite the color data
LLGLSUIDefault gls_ui;
@@ -294,7 +223,7 @@ BOOL LLTexLayerSetBuffer::render()
}
else
{
- readBackAndUpload(baked_bump_data);
+ readBackAndUpload();
}
}
@@ -306,7 +235,6 @@ BOOL LLTexLayerSetBuffer::render()
mGLTexturep->setGLTextureCreated(true);
mNeedsUpdate = FALSE;
- delete [] baked_bump_data;
return success;
}
@@ -330,7 +258,7 @@ BOOL LLTexLayerSetBuffer::updateImmediate()
return result;
}
-void LLTexLayerSetBuffer::readBackAndUpload(const U8* baked_bump_data)
+void LLTexLayerSetBuffer::readBackAndUpload()
{
// pointers for storing data to upload
U8* baked_color_data = new U8[ mFullWidth * mFullHeight * 4 ];
@@ -358,44 +286,25 @@ void LLTexLayerSetBuffer::readBackAndUpload(const U8* baked_bump_data)
// writes into baked_color_data
const char* comment_text = NULL;
- S32 baked_image_components = mBumpTex.notNull() ? 5 : 4; // red green blue [bump] clothing
+ S32 baked_image_components = 5; // red green blue [bump] clothing
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
+ comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // 5 channels: rgb, heightfield/alpha, mask
- S32 i = 0;
- for( S32 u = 0; u < mFullWidth; u++ )
- {
- 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];
- i++;
- }
- }
- }
- else
+ S32 i = 0;
+ for( S32 u = 0; u < mFullWidth; u++ )
+ {
+ for( S32 v = 0; v < mFullHeight; v++ )
{
- S32 i = 0;
- for( S32 u = 0; u < mFullWidth; u++ )
- {
- 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];
- baked_image_data[4*i + 2] = baked_color_data[4*i + 2];
- baked_image_data[4*i + 3] = baked_color_data[4*i + 3]; // Use alpha, not bump
- 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++;
}
+ }
LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C;
compressedImage->setRate(0.f);
@@ -548,23 +457,6 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid,
delete baked_upload_data;
}
-void LLTexLayerSetBuffer::bindBumpTexture( U32 stage )
-{
- if( mBumpTex.notNull() )
- {
- gGL.getTexUnit(stage)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTex->getTexName());
- gGL.getTexUnit(0)->activate();
-
- mGLTexturep->updateBindStats(mFullWidth * mFullHeight * 4);
- }
- else
- {
- gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.getTexUnit(0)->activate();
- }
-}
-
-
//-----------------------------------------------------------------------------
// LLTexLayerSet
// An ordered set of texture layers that get composited into a single texture.
@@ -659,7 +551,6 @@ LLTexLayerSet::LLTexLayerSet(LLVOAvatarSelf* const avatar) :
mComposite( NULL ),
mAvatar( avatar ),
mUpdatesEnabled( FALSE ),
- mHasBump( FALSE ),
mInfo( NULL )
{
}
@@ -686,16 +577,25 @@ BOOL LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info)
iter != info->mLayerInfoList.end();
iter++)
{
- LLTexLayer* layer = new LLTexLayer( this );
- if (!layer->setInfo(*iter))
+ LLTexLayerInterface *layer = NULL;
+ if ( (*iter)->isUserSettable() )
+ {
+ layer = new LLTexLayerTemplate( this );
+ }
+ else
+ {
+ 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, NULL))
{
mInfo = NULL;
return FALSE;
}
if (!layer->isVisibilityMask())
{
- mLayerList.push_back( layer );
- }
+ mLayerList.push_back( layer );
+ }
else
{
mMaskLayerList.push_back(layer);
@@ -736,12 +636,12 @@ 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();
}
}
@@ -772,10 +672,22 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
BOOL render_morph = mAvatar->morphMaskNeedsUpdate(mBakedTexIndex);
+ // 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();
+ }
+
// composite color layers
for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
- LLTexLayer* layer = *iter;
+ LLTexLayerInterface* layer = *iter;
if (layer->getRenderPass() == LLTexLayer::RP_COLOR)
{
gGL.flush();
@@ -788,44 +700,13 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
}
}
- renderAlphaMaskTextures(width, height, false);
+ renderAlphaMaskTextures(x, y, width, height, false);
stop_glerror();
return success;
}
-BOOL LLTexLayerSet::renderBump( S32 x, S32 y, S32 width, S32 height )
-{
- BOOL success = TRUE;
-
- LLGLSUIDefault gls_ui;
- LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE);
-
- //static S32 bump_layer_count = 1;
-
- for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
- {
- LLTexLayer* layer = *iter;
- if (layer->getRenderPass() == LLTexLayer::RP_BUMP)
- {
-// success &= layer->render(x, y, width, height);
- }
- }
-
- // 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.setColorMask(false, true);
-
- gl_rect_2d_simple( width, height );
-
- gGL.setColorMask(true, true);
- stop_glerror();
-
- return success;
-}
BOOL LLTexLayerSet::isBodyRegion(const std::string& region) const
{
@@ -869,11 +750,9 @@ void LLTexLayerSet::createComposite()
// Composite other avatars at reduced resolution
if( !mAvatar->isSelf() )
{
- // TODO: replace with sanity check to ensure not called for non-self avatars
-// width /= 2;
-// height /= 2;
+ llerrs << "composites should not be created for non-self avatars!" << llendl;
}
- mComposite = new LLTexLayerSetBuffer( this, width, height, mHasBump );
+ mComposite = new LLTexLayerSetBuffer( this, width, height );
}
}
@@ -905,44 +784,21 @@ LLTexLayerSetBuffer* LLTexLayerSet::getComposite()
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;
- U8* alphaData = layer->getAlphaData();
- if (!alphaData && layer->hasAlphaParams())
- {
- LLColor4 net_color;
- layer->findNetColor( &net_color );
- // TODO: eliminate need for layer morph mask valid flag
- layer->invalidateMorphMasks();
- mAvatar->invalidateMorphMasks(mBakedTexIndex);
- layer->renderMorphMasks(mComposite->getOriginX(), mComposite->getOriginY(), width, height, net_color, render_morph);
- 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;
- }
- }
+ LLTexLayerInterface* layer = *iter;
+ layer->gatherAlphaMasks(data, mComposite->getOriginX(),mComposite->getOriginY(), width, height, render_morph);
}
// Set alpha back to that of our alpha masks.
- renderAlphaMaskTextures(width, height, true);
+ renderAlphaMaskTextures(mComposite->getOriginX(), mComposite->getOriginY(), width, height, true);
}
-void LLTexLayerSet::renderAlphaMaskTextures(S32 width, S32 height, bool forceClear)
+void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear)
{
const LLTexLayerSetInfo *info = getInfo();
@@ -986,9 +842,9 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 width, S32 height, bool forceCle
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(width, height);
+ layer->blendAlphaTexture(x,y,width, height);
gGL.flush();
}
@@ -1006,23 +862,6 @@ void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_
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;
-
- if (layer->getName().compare(name) == 0)
- {
- return layer;
- }
- }
- return NULL;
-}
-
//-----------------------------------------------------------------------------
// LLTexLayerInfo
@@ -1190,7 +1029,7 @@ BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar)
{
LLTexLayerParamColorInfo * color_info = *color_info_iter;
LLTexLayerParamColor* param_color = new LLTexLayerParamColor(avatar);
- if (!param_color->setInfo(color_info))
+ if (!param_color->setInfo(color_info, TRUE))
{
llwarns << "NULL TexLayer Color Param could not be added to visual param list. Deleting." << llendl;
delete param_color;
@@ -1204,7 +1043,7 @@ BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar)
{
LLTexLayerParamAlphaInfo * alpha_info = *alpha_info_iter;
LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha(avatar);
- if (!param_alpha->setInfo(alpha_info))
+ if (!param_alpha->setInfo(alpha_info, TRUE))
{
llwarns << "NULL TexLayer Alpha Param could not be added to visual param list. Deleting." << llendl;
delete param_alpha;
@@ -1215,6 +1054,138 @@ BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar)
return success;
}
+LLTexLayerInterface::LLTexLayerInterface(LLTexLayerSet* const layer_set):
+ mTexLayerSet( layer_set ),
+ mMorphMasksValid( FALSE ),
+ mStaticImageInvalid( FALSE ),
+ mInfo(NULL),
+ mHasMorph(FALSE)
+{
+}
+
+LLTexLayerInterface::LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable):
+ mTexLayerSet( layer.mTexLayerSet )
+{
+ // don't add visual params for cloned layers
+ setInfo(layer.getInfo(), wearable);
+
+ mHasMorph = layer.mHasMorph;
+}
+
+BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearable ) // This sets mInfo and calls initialization functions
+{
+ llassert(mInfo == NULL);
+ 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 );
+ }
+
+ return TRUE;
+}
+
+/*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)
+{
+ LLViewerVisualParam *result = NULL;
+ for (param_color_list_t::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::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:
@@ -1228,23 +1199,22 @@ BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar)
// * 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),
- mHasMorph(FALSE)
+LLTexLayer::LLTexLayer(LLTexLayerSet* const layer_set) :
+ LLTexLayerInterface( layer_set ),
+ mLocalTextureObject(NULL)
{
}
-LLTexLayer::LLTexLayer(const LLTexLayer &layer) :
- mTexLayerSet( layer.mTexLayerSet )
+LLTexLayer::LLTexLayer(const LLTexLayer &layer, LLWearable *wearable) :
+ LLTexLayerInterface( layer, wearable ),
+ mLocalTextureObject(NULL)
{
- setInfo(layer.getInfo());
-
-
- mHasMorph = layer.mHasMorph;
+}
+LLTexLayer::LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable) :
+ LLTexLayerInterface( layer_template, wearable ),
+ mLocalTextureObject(lto)
+{
}
LLTexLayer::~LLTexLayer()
@@ -1267,44 +1237,9 @@ LLTexLayer::~LLTexLayer()
// setInfo
//-----------------------------------------------------------------------------
-BOOL LLTexLayer::setInfo(const LLTexLayerInfo* info)
+BOOL LLTexLayer::setInfo(const LLTexLayerInfo* info, LLWearable* wearable )
{
- llassert(mInfo == NULL);
- mInfo = info;
- //mID = info->mID; // No ID
-
- 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++)
- {
- LLTexLayerParamColor* param_color = new LLTexLayerParamColor(this);
- if (!param_color->setInfo(*iter))
- {
- 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 = new LLTexLayerParamAlpha( this );
- if (!param_alpha->setInfo(*iter))
- {
- mInfo = NULL;
- return FALSE;
- }
- mParamAlphaList.push_back( param_alpha );
- }
-
- return TRUE;
+ return LLTexLayerInterface::setInfo(info, wearable);
}
//static
@@ -1312,12 +1247,12 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t &param_list, LL
{
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())
- {
+ {
case LLTexLayerParamColor::OP_ADD:
net_color += param_net;
break;
@@ -1330,13 +1265,14 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t &param_list, LL
default:
llassert(0);
break;
- }
+ }
}
net_color.clamp();
}
-void LLTexLayer::deleteCaches()
+/*virtual*/ void LLTexLayer::deleteCaches()
{
+ // 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++ )
{
@@ -1373,7 +1309,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph)
{
// 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 (!mHasMorph)
+/* if (!mHasMorph)
{
BOOL skip_layer = TRUE;
@@ -1394,7 +1330,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph)
{
return success;
}
- }
+ }//*/
renderMorphMasks(x, y, width, height, net_color, render_morph);
alpha_mask_specified = TRUE;
@@ -1414,7 +1350,19 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph)
{
{
LLViewerTexture* tex = NULL;
- if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &tex ) )
+ if (mLocalTextureObject && mLocalTextureObject->getImage())
+ {
+ tex = mLocalTextureObject->getImage();
+ if (mLocalTextureObject->getID() == IMG_DEFAULT_AVATAR)
+ {
+ tex = NULL;
+ }
+ }
+ else
+ {
+ llinfos << "lto not defined or image not defined: " << getInfo()->getLocalTexture() << " lto: " << mLocalTextureObject << llendl;
+ }
+// if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) )
{
if( tex )
{
@@ -1431,10 +1379,10 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph)
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
}
- else
- {
- success = FALSE;
- }
+// else
+// {
+// success = FALSE;
+// }
}
}
@@ -1484,12 +1432,13 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph)
U8* LLTexLayer::getAlphaData()
{
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 (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*)&param_weight, sizeof(F32));
}
@@ -1544,7 +1493,7 @@ BOOL LLTexLayer::findNetColor(LLColor4* net_color) const
return FALSE; // No need to draw a separate colored polygon
}
-BOOL LLTexLayer::blendAlphaTexture(S32 width, S32 height)
+BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height)
{
BOOL success = TRUE;
@@ -1569,17 +1518,14 @@ BOOL LLTexLayer::blendAlphaTexture(S32 width, S32 height)
{
if (getInfo()->mLocalTexture >=0 && getInfo()->mLocalTexture < TEX_NUM_INDICES)
{
- LLViewerTexture* tex = NULL;
- if (mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &tex))
+ LLViewerTexture* tex = mLocalTextureObject->getImage();
+ if (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;
- }
+ 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;
}
}
}
@@ -1587,6 +1533,10 @@ BOOL LLTexLayer::blendAlphaTexture(S32 width, S32 height)
return success;
}
+/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, BOOL render_morph)
+{
+ addAlphaMask(data, originX, originY, width, height, render_morph);
+}
BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, BOOL render_morph)
{
@@ -1627,23 +1577,20 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
// Accumulate the alpha component of the texture
if( getInfo()->mLocalTexture != -1 )
{
- LLViewerTexture* tex = NULL;
- if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &tex ) )
+ LLViewerTexture* tex = mLocalTextureObject->getImage();
+ if( tex && (tex->getComponents() == 4) )
{
- if( tex && (tex->getComponents() == 4) )
- {
- LLGLSNoAlphaTest gls_no_alpha_test;
+ LLGLSNoAlphaTest gls_no_alpha_test;
- LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode();
-
- gGL.getTexUnit(0)->bind(tex);
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode();
+
+ gGL.getTexUnit(0)->bind(tex);
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
- gl_rect_2d_simple_tex( width, height );
+ gl_rect_2d_simple_tex( width, height );
- gGL.getTexUnit(0)->setTextureAddressMode(old_mode);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- }
+ gGL.getTexUnit(0)->setTextureAddressMode(old_mode);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
else
{
@@ -1686,10 +1633,10 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
gGL.setColorMask(true, true);
- if (render_morph && mHasMorph)
+ if (render_morph && mHasMorph && 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 (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++)
@@ -1726,106 +1673,269 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
return success;
}
-// 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 )
+void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, BOOL render_morph)
{
- if (!in_data)
+ S32 size = width * height;
+ U8* alphaData = getAlphaData();
+ if (!alphaData && hasAlphaParams())
{
- return FALSE;
+ LLColor4 net_color;
+ findNetColor( &net_color );
+ // TODO: eliminate need for layer morph mask valid flag
+ invalidateMorphMasks();
+ renderMorphMasks(originX, originY, width, height, net_color, render_morph);
+ alphaData = getAlphaData();
}
- GLenum format_options[4] = { GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA };
- GLenum format = format_options[in_components-1];
- if( is_mask )
+ if (alphaData)
{
- llassert( 1 == in_components );
- format = GL_ALPHA;
+ 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;
+ }
}
+}
- if( (in_width != SCRATCH_TEX_WIDTH) || (in_height != SCRATCH_TEX_HEIGHT) )
+// private helper function
+LLUUID LLTexLayer::getUUID()
+{
+ LLUUID uuid;
+ if( getInfo()->mLocalTexture != -1 )
{
- LLGLSNoAlphaTest gls_no_alpha_test;
+ LLViewerTexture* tex = mLocalTextureObject->getImage();
+ if (tex)
+ {
+ uuid = mLocalTextureObject->getID();
+ }
+ }
+ if( !getInfo()->mStaticImageFileName.empty() )
+ {
+ LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask);
+ if( tex )
+ {
+ uuid = tex->getID();
+ }
+ }
+ return uuid;
+}
- 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 )
- {
- llassert( 1 == in_components );
- internal_format = GL_ALPHA8;
- }
-
- U32 name = 0;
- LLImageGL::generateTextures(1, &name );
- stop_glerror();
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, name);
- stop_glerror();
+//-----------------------------------------------------------------------------
+// LLTexLayerTemplate
+// A single texture layer, consisting of:
+// * color, consisting of either
+// * one or more color parameters (weighted colors)
+// * a reference to a global color
+// * a fixed color with non-zero alpha
+// * opaque white (the default)
+// * (optional) a texture defined by either
+// * a GUID
+// * a texture entry index (TE)
+// * (optional) one or more alpha parameters (weighted alpha textures)
+//-----------------------------------------------------------------------------
+LLTexLayerTemplate::LLTexLayerTemplate(LLTexLayerSet* layer_set) :
+ LLTexLayerInterface(layer_set)
+{
+}
- LLImageGL::setManualImage(
- GL_TEXTURE_2D, 0, internal_format,
- in_width, in_height,
- format, GL_UNSIGNED_BYTE, in_data );
- stop_glerror();
+LLTexLayerTemplate::LLTexLayerTemplate(const LLTexLayerTemplate &layer) :
+ LLTexLayerInterface(layer)
+{
+}
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+LLTexLayerTemplate::~LLTexLayerTemplate()
+{
+}
- gl_rect_2d_simple_tex( width, height );
+//-----------------------------------------------------------------------------
+// setInfo
+//-----------------------------------------------------------------------------
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+/*virtual*/ BOOL LLTexLayerTemplate::setInfo(const LLTexLayerInfo* info, LLWearable* wearable )
+{
+ return LLTexLayerInterface::setInfo(info, wearable);
+}
- LLImageGL::deleteTextures(1, &name );
- stop_glerror();
+U32 LLTexLayerTemplate::updateWearableCache()
+{
+ mWearableCache.clear();
+
+ S32 te = mInfo->mLocalTexture;
+ if (te == -1)
+ {
+ //this isn't a cloneable layer
+ return 0;
}
- else
+ EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te);
+ U32 num_wearables = gAgentWearables.getWearableCount(wearable_type);
+ U32 added = 0;
+ for (U32 i = 0; i < num_wearables; i++)
{
- LLGLSNoAlphaTest gls_no_alpha_test;
-
- if( !mTexLayerSet->getAvatar()->bindScratchTexture(format) )
+ LLWearable* wearable = gAgentWearables.getWearable(wearable_type, i);
+ if (!wearable)
{
- return FALSE;
+ continue;
}
+ mWearableCache.push_back(wearable);
+ added++;
+ }
+ return added;
+}
+LLTexLayer* LLTexLayerTemplate::getLayer(U32 i)
+{
+ if (mWearableCache.size() <= i || i < 0)
+ {
+ return NULL;
+ }
+ LLWearable *wearable = mWearableCache[i];
+ LLLocalTextureObject *lto = NULL;
+ LLTexLayer *layer = NULL;
+ if (wearable)
+ {
+ lto = wearable->getLocalTextureObject(mInfo->mLocalTexture);
+ }
+ if (lto)
+ {
+ layer = lto->getTexLayer(getName());
+ }
+ return layer;
+}
- glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, in_width, in_height, format, GL_UNSIGNED_BYTE, in_data );
- stop_glerror();
+/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph)
+{
+ BOOL success = TRUE;
+ updateWearableCache();
+ for (wearable_cache_t::const_iterator iter = mWearableCache.begin(); iter!= mWearableCache.end(); iter++)
+ {
+ LLWearable* wearable = NULL;
+ LLLocalTextureObject *lto = NULL;
+ LLTexLayer *layer = NULL;
+ wearable = *iter;
+ if (wearable)
+ {
+ lto = wearable->getLocalTextureObject(mInfo->mLocalTexture);
+ }
+ if (lto)
+ {
+ layer = lto->getTexLayer(getName());
+ }
+ if (layer)
+ {
+ wearable->writeToAvatar(FALSE, FALSE);
+ layer->setLTO(lto);
+ success &= layer->render(x,y,width,height,render_morph);
+ }
+ }
- gl_rect_2d_simple_tex( width, height );
+ return success;
+}
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+/*virtual*/ BOOL LLTexLayerTemplate::blendAlphaTexture( S32 x, S32 y, S32 width, S32 height) // Multiplies a single alpha texture against the frame buffer
+{
+ BOOL success = TRUE;
+ U32 num_wearables = updateWearableCache();
+ for (U32 i = 0; i < num_wearables; i++)
+ {
+ LLTexLayer *layer = getLayer(i);
+ if (layer)
+ {
+ success &= layer->blendAlphaTexture(x,y,width,height);
+ }
}
-
- return TRUE;
+ return success;
}
-void LLTexLayer::requestUpdate()
+/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, BOOL render_morph)
{
- mTexLayerSet->requestUpdate();
+ U32 num_wearables = updateWearableCache();
+ for (U32 i = 0; i < num_wearables; i++)
+ {
+ LLTexLayer *layer = getLayer(i);
+ if (layer)
+ {
+ layer->addAlphaMask(data, originX, originY, width, height, render_morph);
+ }
+ }
}
-const std::string& LLTexLayer::getName() const
+/*virtual*/ void LLTexLayerTemplate::setHasMorph(BOOL newval)
{
- return mInfo->mName;
+ mHasMorph = newval;
+ U32 num_wearables = updateWearableCache();
+ for (U32 i = 0; i < num_wearables; i++)
+ {
+ LLTexLayer *layer = getLayer(i);
+ if (layer)
+ {
+ layer->setHasMorph(newval);
+ }
+ }
}
-LLTexLayer::ERenderPass LLTexLayer::getRenderPass() const
+/*virtual*/ void LLTexLayerTemplate::deleteCaches()
{
- return mInfo->mRenderPass;
+ U32 num_wearables = updateWearableCache();
+ for (U32 i = 0; i < num_wearables; i++)
+ {
+ LLTexLayer *layer = getLayer(i);
+ if (layer)
+ {
+ layer->deleteCaches();
+ }
+ }
}
-const std::string& LLTexLayer::getGlobalColor() const
+
+
+
+//-----------------------------------------------------------------------------
+// finds a specific layer based on a passed in name
+//-----------------------------------------------------------------------------
+LLTexLayerInterface* LLTexLayerSet::findLayerByName(std::string name)
{
- return mInfo->mGlobalColor;
+ for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
+ {
+ LLTexLayerInterface* layer = *iter;
+
+ if (layer->getName().compare(name) == 0)
+ {
+ return layer;
+ }
+ }
+ for( layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++ )
+ {
+ LLTexLayerInterface* layer = *iter;
+
+ if (layer->getName().compare(name) == 0)
+ {
+ return layer;
+ }
+ }
+ return NULL;
}
-void LLTexLayer::invalidateMorphMasks()
+void LLTexLayerSet::cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable *wearable)
{
- mMorphMasksValid = FALSE;
+ // initialize all texlayers with this texture type for this LTO
+ for( LLTexLayerSet::layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
+ {
+ LLTexLayerTemplate* layer = (LLTexLayerTemplate*)*iter;
+ if (layer->getInfo()->getLocalTexture() == (S32) tex_index)
+ {
+ lto->addTexLayer(layer, wearable);
+ }
}
-
-BOOL LLTexLayer::isVisibilityMask() const
+ for( LLTexLayerSet::layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++ )
{
- return mInfo->mIsVisibilityMask;
+ LLTexLayerTemplate* layer = (LLTexLayerTemplate*)*iter;
+ if (layer->getInfo()->getLocalTexture() == (S32) tex_index)
+ {
+ lto->addTexLayer(layer, wearable);
+ }
+ }
}
-
//-----------------------------------------------------------------------------
// LLTexLayerStaticImageList
//-----------------------------------------------------------------------------