PageRenderTime 97ms CodeModel.GetById 20ms app.highlight 57ms RepoModel.GetById 13ms app.codeStats 1ms

/indra/newview/lltexlayerparams.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 568 lines | 426 code | 85 blank | 57 comment | 75 complexity | dc967244923e72da7e64620547707f61 MD5 | raw file
  1/** 
  2 * @file lltexlayerparams.cpp
  3 * @brief Texture layer parameters
  4 *
  5 * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "llviewerprecompiledheaders.h"
 28
 29#include "lltexlayerparams.h"
 30
 31#include "llagentcamera.h"
 32#include "llimagetga.h"
 33#include "lltexlayer.h"
 34#include "llvoavatarself.h"
 35#include "llwearable.h"
 36#include "llui.h"
 37
 38//-----------------------------------------------------------------------------
 39// LLTexLayerParam
 40//-----------------------------------------------------------------------------
 41LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) :
 42	mTexLayer(layer),
 43	mAvatar(NULL)
 44{
 45	if (mTexLayer != NULL)
 46	{
 47		mAvatar = mTexLayer->getTexLayerSet()->getAvatar();
 48	}
 49	else
 50	{
 51		llerrs << "LLTexLayerParam constructor passed with NULL reference for layer!" << llendl;
 52	}
 53}
 54
 55LLTexLayerParam::LLTexLayerParam(LLVOAvatar *avatar) :
 56	mTexLayer(NULL)
 57{
 58	mAvatar = avatar;
 59}
 60
 61
 62BOOL LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, BOOL add_to_avatar  )
 63{	
 64	LLViewerVisualParam::setInfo(info);
 65
 66	if (add_to_avatar)
 67	{
 68		mAvatar->addVisualParam( this);
 69	}
 70
 71	return TRUE;
 72}
 73
 74
 75//-----------------------------------------------------------------------------
 76// LLTexLayerParamAlpha
 77//-----------------------------------------------------------------------------
 78
 79// static 
 80LLTexLayerParamAlpha::param_alpha_ptr_list_t LLTexLayerParamAlpha::sInstances;
 81
 82// static 
 83void LLTexLayerParamAlpha::dumpCacheByteCount()
 84{
 85	S32 gl_bytes = 0;
 86	getCacheByteCount( &gl_bytes);
 87	llinfos << "Processed Alpha Texture Cache GL:" << (gl_bytes/1024) << "KB" << llendl;
 88}
 89
 90// static 
 91void LLTexLayerParamAlpha::getCacheByteCount(S32* gl_bytes)
 92{
 93	*gl_bytes = 0;
 94
 95	for (param_alpha_ptr_list_t::iterator iter = sInstances.begin();
 96		 iter != sInstances.end(); iter++)
 97	{
 98		LLTexLayerParamAlpha* instance = *iter;
 99		LLViewerTexture* tex = instance->mCachedProcessedTexture;
100		if (tex)
101		{
102			S32 bytes = (S32)tex->getWidth() * tex->getHeight() * tex->getComponents();
103
104			if (tex->hasGLTexture())
105			{
106				*gl_bytes += bytes;
107			}
108		}
109	}
110}
111
112LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer) :
113	LLTexLayerParam(layer),
114	mCachedProcessedTexture(NULL),
115	mNeedsCreateTexture(FALSE),
116	mStaticImageInvalid(FALSE),
117	mAvgDistortionVec(1.f, 1.f, 1.f),
118	mCachedEffectiveWeight(0.f)
119{
120	sInstances.push_front(this);
121}
122
123LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLVOAvatar* avatar) :
124	LLTexLayerParam(avatar),
125	mCachedProcessedTexture(NULL),
126	mNeedsCreateTexture(FALSE),
127	mStaticImageInvalid(FALSE),
128	mAvgDistortionVec(1.f, 1.f, 1.f),
129	mCachedEffectiveWeight(0.f)
130{
131	sInstances.push_front(this);
132}
133
134
135LLTexLayerParamAlpha::~LLTexLayerParamAlpha()
136{
137	deleteCaches();
138	sInstances.remove(this);
139}
140
141/*virtual*/ LLViewerVisualParam* LLTexLayerParamAlpha::cloneParam(LLWearable* wearable) const
142{
143	LLTexLayerParamAlpha *new_param = new LLTexLayerParamAlpha(mTexLayer);
144	*new_param = *this;
145	return new_param;
146}
147
148void LLTexLayerParamAlpha::deleteCaches()
149{
150	mStaticImageTGA = NULL; // deletes image
151	mCachedProcessedTexture = NULL;
152	mStaticImageRaw = NULL;
153	mNeedsCreateTexture = FALSE;
154}
155
156BOOL LLTexLayerParamAlpha::getMultiplyBlend() const
157{
158	return ((LLTexLayerParamAlphaInfo *)getInfo())->mMultiplyBlend; 	
159}
160
161void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL upload_bake)
162{
163	if (mIsAnimating || mTexLayer == NULL)
164	{
165		return;
166	}
167	F32 min_weight = getMinWeight();
168	F32 max_weight = getMaxWeight();
169	F32 new_weight = llclamp(weight, min_weight, max_weight);
170	U8 cur_u8 = F32_to_U8(mCurWeight, min_weight, max_weight);
171	U8 new_u8 = F32_to_U8(new_weight, min_weight, max_weight);
172	if (cur_u8 != new_u8)
173	{
174		mCurWeight = new_weight;
175
176		if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
177		{
178			if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures())
179			{
180				upload_bake = FALSE;
181			}
182			mAvatar->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake);
183			mTexLayer->invalidateMorphMasks();
184		}
185	}
186}
187
188void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL upload_bake)
189{ 
190	// do not animate dummy parameters
191	if (mIsDummy)
192	{
193		setWeight(target_value, upload_bake);
194		return;
195	}
196
197	mTargetWeight = target_value; 
198	setWeight(target_value, upload_bake); 
199	mIsAnimating = TRUE;
200	if (mNext)
201	{
202		mNext->setAnimationTarget(target_value, upload_bake);
203	}
204}
205
206void LLTexLayerParamAlpha::animate(F32 delta, BOOL upload_bake)
207{
208	if (mNext)
209	{
210		mNext->animate(delta, upload_bake);
211	}
212}
213
214BOOL LLTexLayerParamAlpha::getSkip() const
215{
216	if (!mTexLayer)
217	{
218		return TRUE;
219	}
220
221	const LLVOAvatar *avatar = mTexLayer->getTexLayerSet()->getAvatar();
222
223	if (((LLTexLayerParamAlphaInfo *)getInfo())->mSkipIfZeroWeight)
224	{
225		F32 effective_weight = (avatar->getSex() & getSex()) ? mCurWeight : getDefaultWeight();
226		if (is_approx_zero(effective_weight)) 
227		{
228			return TRUE;
229		}
230	}
231
232	LLWearableType::EType type = (LLWearableType::EType)getWearableType();
233	if ((type != LLWearableType::WT_INVALID) && !avatar->isWearingWearableType(type))
234	{
235		return TRUE;
236	}
237
238	return FALSE;
239}
240
241
242BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height)
243{
244	BOOL success = TRUE;
245
246	if (!mTexLayer)
247	{
248		return success;
249	}
250
251	F32 effective_weight = (mTexLayer->getTexLayerSet()->getAvatar()->getSex() & getSex()) ? mCurWeight : getDefaultWeight();
252	BOOL weight_changed = effective_weight != mCachedEffectiveWeight;
253	if (getSkip())
254	{
255		return success;
256	}
257
258	LLTexLayerParamAlphaInfo *info = (LLTexLayerParamAlphaInfo *)getInfo();
259	gGL.flush();
260	if (info->mMultiplyBlend)
261	{
262		gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO); // Multiplication: approximates a min() function
263	}
264	else
265	{
266		gGL.setSceneBlendType(LLRender::BT_ADD);  // Addition: approximates a max() function
267	}
268
269	if (!info->mStaticImageFileName.empty() && !mStaticImageInvalid)
270	{
271		if (mStaticImageTGA.isNull())
272		{
273			// Don't load the image file until we actually need it the first time.  Like now.
274			mStaticImageTGA = LLTexLayerStaticImageList::getInstance()->getImageTGA(info->mStaticImageFileName);  
275			// We now have something in one of our caches
276			LLTexLayerSet::sHasCaches |= mStaticImageTGA.notNull() ? TRUE : FALSE;
277
278			if (mStaticImageTGA.isNull())
279			{
280				llwarns << "Unable to load static file: " << info->mStaticImageFileName << llendl;
281				mStaticImageInvalid = TRUE; // don't try again.
282				return FALSE;
283			}
284		}
285
286		const S32 image_tga_width = mStaticImageTGA->getWidth();
287		const S32 image_tga_height = mStaticImageTGA->getHeight(); 
288		if (!mCachedProcessedTexture ||
289			(mCachedProcessedTexture->getWidth() != image_tga_width) ||
290			(mCachedProcessedTexture->getHeight() != image_tga_height) ||
291			(weight_changed))
292		{
293//			llinfos << "Building Cached Alpha: " << mName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << effective_weight << llendl;
294			mCachedEffectiveWeight = effective_weight;
295
296			if (!mCachedProcessedTexture)
297			{
298				mCachedProcessedTexture = LLViewerTextureManager::getLocalTexture(image_tga_width, image_tga_height, 1, FALSE);
299
300				// We now have something in one of our caches
301				LLTexLayerSet::sHasCaches |= mCachedProcessedTexture ? TRUE : FALSE;
302
303				mCachedProcessedTexture->setExplicitFormat(GL_ALPHA8, GL_ALPHA);
304			}
305
306			// Applies domain and effective weight to data as it is decoded. Also resizes the raw image if needed.
307			mStaticImageRaw = NULL;
308			mStaticImageRaw = new LLImageRaw;
309			mStaticImageTGA->decodeAndProcess(mStaticImageRaw, info->mDomain, effective_weight);
310			mNeedsCreateTexture = TRUE;			
311		}
312
313		if (mCachedProcessedTexture)
314		{
315			{
316				// Create the GL texture, and then hang onto it for future use.
317				if (mNeedsCreateTexture)
318				{
319					mCachedProcessedTexture->createGLTexture(0, mStaticImageRaw);
320					mNeedsCreateTexture = FALSE;
321					gGL.getTexUnit(0)->bind(mCachedProcessedTexture);
322					mCachedProcessedTexture->setAddressMode(LLTexUnit::TAM_CLAMP);
323				}
324
325				LLGLSNoAlphaTest gls_no_alpha_test;
326				gGL.getTexUnit(0)->bind(mCachedProcessedTexture);
327				gl_rect_2d_simple_tex(width, height);
328				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
329				stop_glerror();
330			}
331		}
332
333		// Don't keep the cache for other people's avatars
334		// (It's not really a "cache" in that case, but the logic is the same)
335		if (!mAvatar->isSelf())
336		{
337			mCachedProcessedTexture = NULL;
338		}
339	}
340	else
341	{
342		LLGLDisable no_alpha(GL_ALPHA_TEST);
343		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
344		gGL.color4f(0.f, 0.f, 0.f, effective_weight);
345		gl_rect_2d_simple(width, height);
346	}
347
348	return success;
349}
350
351//-----------------------------------------------------------------------------
352// LLTexLayerParamAlphaInfo
353//-----------------------------------------------------------------------------
354LLTexLayerParamAlphaInfo::LLTexLayerParamAlphaInfo() :
355	mMultiplyBlend(FALSE),
356	mSkipIfZeroWeight(FALSE),
357	mDomain(0.f)
358{
359}
360
361BOOL LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node)
362{
363	llassert(node->hasName("param") && node->getChildByName("param_alpha"));
364
365	if (!LLViewerVisualParamInfo::parseXml(node))
366		return FALSE;
367
368	LLXmlTreeNode* param_alpha_node = node->getChildByName("param_alpha");
369	if (!param_alpha_node)
370	{
371		return FALSE;
372	}
373
374	static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file");
375	if (param_alpha_node->getFastAttributeString(tga_file_string, mStaticImageFileName))
376	{
377		// Don't load the image file until it's actually needed.
378	}
379//	else
380//	{
381//		llwarns << "<param_alpha> element is missing tga_file attribute." << llendl;
382//	}
383	
384	static LLStdStringHandle multiply_blend_string = LLXmlTree::addAttributeString("multiply_blend");
385	param_alpha_node->getFastAttributeBOOL(multiply_blend_string, mMultiplyBlend);
386
387	static LLStdStringHandle skip_if_zero_string = LLXmlTree::addAttributeString("skip_if_zero");
388	param_alpha_node->getFastAttributeBOOL(skip_if_zero_string, mSkipIfZeroWeight);
389
390	static LLStdStringHandle domain_string = LLXmlTree::addAttributeString("domain");
391	param_alpha_node->getFastAttributeF32(domain_string, mDomain);
392
393	return TRUE;
394}
395
396
397
398
399LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayerInterface* layer) :
400	LLTexLayerParam(layer),
401	mAvgDistortionVec(1.f, 1.f, 1.f)
402{
403}
404
405LLTexLayerParamColor::LLTexLayerParamColor(LLVOAvatar *avatar) :
406	LLTexLayerParam(avatar),
407	mAvgDistortionVec(1.f, 1.f, 1.f)
408{
409}
410
411LLTexLayerParamColor::~LLTexLayerParamColor()
412{
413}
414
415/*virtual*/ LLViewerVisualParam* LLTexLayerParamColor::cloneParam(LLWearable* wearable) const
416{
417	LLTexLayerParamColor *new_param = new LLTexLayerParamColor(mTexLayer);
418	*new_param = *this;
419	return new_param;
420}
421
422LLColor4 LLTexLayerParamColor::getNetColor() const
423{
424	const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo();
425	
426	llassert(info->mNumColors >= 1);
427
428	F32 effective_weight = (mAvatar && (mAvatar->getSex() & getSex())) ? mCurWeight : getDefaultWeight();
429
430	S32 index_last = info->mNumColors - 1;
431	F32 scaled_weight = effective_weight * index_last;
432	S32 index_start = (S32) scaled_weight;
433	S32 index_end = index_start + 1;
434	if (index_start == index_last)
435	{
436		return info->mColors[index_last];
437	}
438	else
439	{
440		F32 weight = scaled_weight - index_start;
441		const LLColor4 *start = &info->mColors[ index_start ];
442		const LLColor4 *end   = &info->mColors[ index_end ];
443		return LLColor4((1.f - weight) * start->mV[VX] + weight * end->mV[VX],
444						(1.f - weight) * start->mV[VY] + weight * end->mV[VY],
445						(1.f - weight) * start->mV[VZ] + weight * end->mV[VZ],
446						(1.f - weight) * start->mV[VW] + weight * end->mV[VW]);
447	}
448}
449
450void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake)
451{
452	if (mIsAnimating)
453	{
454		return;
455	}
456
457	const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo();
458	F32 min_weight = getMinWeight();
459	F32 max_weight = getMaxWeight();
460	F32 new_weight = llclamp(weight, min_weight, max_weight);
461	U8 cur_u8 = F32_to_U8(mCurWeight, min_weight, max_weight);
462	U8 new_u8 = F32_to_U8(new_weight, min_weight, max_weight);
463	if (cur_u8 != new_u8)
464	{
465		mCurWeight = new_weight;
466
467		if (info->mNumColors <= 0)
468		{
469			// This will happen when we set the default weight the first time.
470			return;
471		}
472
473		if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
474		{
475			onGlobalColorChanged(upload_bake);
476			if (mTexLayer)
477			{
478				mAvatar->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake);
479			}
480		}
481
482//		llinfos << "param " << mName << " = " << new_weight << llendl;
483	}
484}
485
486void LLTexLayerParamColor::setAnimationTarget(F32 target_value, BOOL upload_bake)
487{ 
488	// set value first then set interpolating flag to ignore further updates
489	mTargetWeight = target_value; 
490	setWeight(target_value, upload_bake);
491	mIsAnimating = TRUE;
492	if (mNext)
493	{
494		mNext->setAnimationTarget(target_value, upload_bake);
495	}
496}
497
498void LLTexLayerParamColor::animate(F32 delta, BOOL upload_bake)
499{
500	if (mNext)
501	{
502		mNext->animate(delta, upload_bake);
503	}
504}
505
506//-----------------------------------------------------------------------------
507// LLTexLayerParamColorInfo
508//-----------------------------------------------------------------------------
509LLTexLayerParamColorInfo::LLTexLayerParamColorInfo() :
510	mOperation(LLTexLayerParamColor::OP_ADD),
511	mNumColors(0)
512{
513}
514
515BOOL LLTexLayerParamColorInfo::parseXml(LLXmlTreeNode *node)
516{
517	llassert(node->hasName("param") && node->getChildByName("param_color"));
518
519	if (!LLViewerVisualParamInfo::parseXml(node))
520		return FALSE;
521
522	LLXmlTreeNode* param_color_node = node->getChildByName("param_color");
523	if (!param_color_node)
524	{
525		return FALSE;
526	}
527
528	std::string op_string;
529	static LLStdStringHandle operation_string = LLXmlTree::addAttributeString("operation");
530	if (param_color_node->getFastAttributeString(operation_string, op_string))
531	{
532		LLStringUtil::toLower(op_string);
533		if		(op_string == "add") 		mOperation = LLTexLayerParamColor::OP_ADD;
534		else if	(op_string == "multiply")	mOperation = LLTexLayerParamColor::OP_MULTIPLY;
535		else if	(op_string == "blend")	    mOperation = LLTexLayerParamColor::OP_BLEND;
536	}
537
538	mNumColors = 0;
539
540	LLColor4U color4u;
541	for (LLXmlTreeNode* child = param_color_node->getChildByName("value");
542		 child;
543		 child = param_color_node->getNextNamedChild())
544	{
545		if ((mNumColors < MAX_COLOR_VALUES))
546		{
547			static LLStdStringHandle color_string = LLXmlTree::addAttributeString("color");
548			if (child->getFastAttributeColor4U(color_string, color4u))
549			{
550				mColors[ mNumColors ].setVec(color4u);
551				mNumColors++;
552			}
553		}
554	}
555	if (!mNumColors)
556	{
557		llwarns << "<param_color> is missing <value> sub-elements" << llendl;
558		return FALSE;
559	}
560
561	if ((mOperation == LLTexLayerParamColor::OP_BLEND) && (mNumColors != 1))
562	{
563		llwarns << "<param_color> with operation\"blend\" must have exactly one <value>" << llendl;
564		return FALSE;
565	}
566	
567	return TRUE;
568}