aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/lltexlayer.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/lltexlayer.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/lltexlayer.cpp')
-rw-r--r--linden/indra/newview/lltexlayer.cpp2860
1 files changed, 2860 insertions, 0 deletions
diff --git a/linden/indra/newview/lltexlayer.cpp b/linden/indra/newview/lltexlayer.cpp
new file mode 100644
index 0000000..0292417
--- /dev/null
+++ b/linden/indra/newview/lltexlayer.cpp
@@ -0,0 +1,2860 @@
1/**
2 * @file lltexlayer.cpp
3 * @brief A texture layer. Used for avatars.
4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#include "imageids.h"
31#include "llagent.h"
32#include "llcrc.h"
33#include "lldir.h"
34#include "llglheaders.h"
35#include "llimagebmp.h"
36#include "llimagej2c.h"
37#include "llimagetga.h"
38#include "llpolymorph.h"
39#include "llquantize.h"
40#include "lltexlayer.h"
41#include "llui.h"
42#include "llvfile.h"
43#include "llviewerimagelist.h"
44#include "llviewerimagelist.h"
45#include "llviewerstats.h"
46#include "llviewerwindow.h"
47#include "llvoavatar.h"
48#include "llxmltree.h"
49#include "pipeline.h"
50#include "v4coloru.h"
51#include "viewer.h"
52
53//#include "../tools/imdebug/imdebug.h"
54
55
56// SJB: We really always want to use the GL cache;
57// let GL page textures in and out of video RAM instead of trying to do so by hand.
58// const U32 USE_AVATAR_GL_CACHE_THRESHOLD = 1024 * 1024 * 35; // 35 MB
59BOOL gUseAvatarGLCache = TRUE; //FALSE;
60
61LLGradientPaletteList gGradientPaletteList;
62
63// static
64S32 LLTexLayerSetBuffer::sGLByteCount = 0;
65S32 LLTexLayerSetBuffer::sGLBumpByteCount = 0;
66
67//-----------------------------------------------------------------------------
68// LLBakedUploadData()
69//-----------------------------------------------------------------------------
70LLBakedUploadData::LLBakedUploadData( LLVOAvatar* avatar, LLTexLayerSetBuffer* layerset_buffer ) :
71 mAvatar( avatar ),
72 mLayerSetBuffer( layerset_buffer )
73{
74 mID.generate();
75 for( S32 i = 0; i < WT_COUNT; i++ )
76 {
77 LLWearable* wearable = gAgent.getWearable( (EWearableType)i);
78 if( wearable )
79 {
80 mWearableAssets[i] = wearable->getID();
81 }
82 }
83}
84
85//-----------------------------------------------------------------------------
86// LLTexLayerSetBuffer
87// The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one.
88//-----------------------------------------------------------------------------
89LLTexLayerSetBuffer::LLTexLayerSetBuffer( LLTexLayerSet* owner, S32 width, S32 height, BOOL has_bump )
90 :
91 // ORDER_LAST => must render these after the hints are created.
92 LLDynamicTexture( width, height, 4, LLDynamicTexture::ORDER_LAST, TRUE ),
93 mNeedsUpdate( TRUE ),
94 mNeedsUpload( FALSE ),
95 mUploadPending( FALSE ), // Not used for any logic here, just to sync sending of updates
96 mTexLayerSet( owner ),
97 mInitialized( FALSE ),
98 mBumpTexName(0)
99{
100 LLTexLayerSetBuffer::sGLByteCount += getSize();
101
102 if( has_bump )
103 {
104 LLGLSUIDefault gls_ui;
105 glGenTextures(1, (GLuint*) &mBumpTexName);
106
107 LLImageGL::bindExternalTexture(mBumpTexName, 0, GL_TEXTURE_2D);
108 stop_glerror();
109
110 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
111 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
112
113 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
115
116 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
117 stop_glerror();
118
119 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
120
121 LLImageGL::sGlobalTextureMemory += mWidth * mHeight * 4;
122 LLTexLayerSetBuffer::sGLBumpByteCount += mWidth * mHeight * 4;
123 }
124}
125
126LLTexLayerSetBuffer::~LLTexLayerSetBuffer()
127{
128 LLTexLayerSetBuffer::sGLByteCount -= getSize();
129
130 if( mBumpTexName )
131 {
132 glDeleteTextures(1, (GLuint*) &mBumpTexName);
133 stop_glerror();
134 mBumpTexName = 0;
135
136 LLImageGL::sGlobalTextureMemory -= mWidth * mHeight * 4;
137 LLTexLayerSetBuffer::sGLBumpByteCount -= mWidth * mHeight * 4;
138 }
139}
140
141// static
142void LLTexLayerSetBuffer::dumpTotalByteCount()
143{
144 llinfos << "Composite System GL Buffers: " << (LLTexLayerSetBuffer::sGLByteCount/1024) << "KB" << llendl;
145 llinfos << "Composite System GL Bump Buffers: " << (LLTexLayerSetBuffer::sGLBumpByteCount/1024) << "KB" << llendl;
146}
147
148void LLTexLayerSetBuffer::requestUpdate()
149{
150 mNeedsUpdate = TRUE;
151
152 // If we're in the middle of uploading a baked texture, we don't care about it any more.
153 // When it's downloaded, ignore it.
154 mUploadID.setNull();
155}
156
157void LLTexLayerSetBuffer::requestUpload()
158{
159 if (!mNeedsUpload)
160 {
161 mNeedsUpload = TRUE;
162 mUploadPending = TRUE;
163 }
164}
165
166void LLTexLayerSetBuffer::cancelUpload()
167{
168 if (mNeedsUpload)
169 {
170 mNeedsUpload = FALSE;
171 }
172 mUploadPending = FALSE;
173}
174
175void LLTexLayerSetBuffer::pushProjection()
176{
177 glMatrixMode(GL_PROJECTION);
178 glPushMatrix();
179 glLoadIdentity();
180 glOrtho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f);
181
182 glMatrixMode(GL_MODELVIEW);
183 glPushMatrix();
184 glLoadIdentity();
185}
186
187void LLTexLayerSetBuffer::popProjection()
188{
189 glMatrixMode(GL_PROJECTION);
190 glPopMatrix();
191
192 glMatrixMode(GL_MODELVIEW);
193 glPopMatrix();
194}
195
196BOOL LLTexLayerSetBuffer::needsRender()
197{
198 LLVOAvatar* avatar = mTexLayerSet->getAvatar();
199 BOOL upload_now = mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal();
200 BOOL needs_update = gAgent.mNumPendingQueries == 0 && (mNeedsUpdate || upload_now) && !avatar->mAppearanceAnimating;
201 if (needs_update)
202 {
203 BOOL invalid_skirt = avatar->getBakedTE(mTexLayerSet) == LLVOAvatar::TEX_SKIRT_BAKED && !avatar->isWearingWearableType(WT_SKIRT);
204 if (invalid_skirt)
205 {
206 // we were trying to create a skirt texture
207 // but we're no longer wearing a skirt...
208 needs_update = FALSE;
209 cancelUpload();
210 }
211 else
212 {
213 needs_update &= (avatar->isSelf() || (avatar->isVisible() && !avatar->isCulled()));
214 needs_update &= mTexLayerSet->isLocalTextureDataAvailable();
215 }
216 }
217 return needs_update;
218}
219
220void LLTexLayerSetBuffer::preRender(BOOL clear_depth)
221{
222 // Set up an ortho projection
223 pushProjection();
224
225 // keep depth buffer, we don't need to clear it
226 LLDynamicTexture::preRender(FALSE);
227}
228
229void LLTexLayerSetBuffer::postRender(BOOL success)
230{
231 popProjection();
232
233 LLDynamicTexture::postRender(success);
234}
235
236BOOL LLTexLayerSetBuffer::render()
237{
238 U8* baked_bump_data = NULL;
239
240// gUseAvatarGLCache = ( gImageList.getMaxResidentTexMem() > USE_AVATAR_GL_CACHE_THRESHOLD );
241
242 // do we need to upload, and do we have sufficient data to create an uploadable composite?
243 // When do we upload the texture if gAgent.mNumPendingQueries is non-zero?
244 BOOL upload_now = (gAgent.mNumPendingQueries == 0 && mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal());
245 BOOL success = TRUE;
246
247 // Composite bump
248 if( mBumpTexName )
249 {
250 // Composite the bump data
251 success &= mTexLayerSet->renderBump( mOrigin.mX, mOrigin.mY, mWidth, mHeight );
252 stop_glerror();
253
254 if (success)
255 {
256 LLGLSUIDefault gls_ui;
257
258 // read back into texture (this is done externally for the color data)
259 LLImageGL::bindExternalTexture( mBumpTexName, 0, GL_TEXTURE_2D );
260 stop_glerror();
261
262 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mOrigin.mX, mOrigin.mY, mWidth, mHeight);
263 stop_glerror();
264
265 // if we need to upload the data, read it back into a buffer
266 if( upload_now )
267 {
268 baked_bump_data = new U8[ mWidth * mHeight * 4 ];
269 glReadPixels(mOrigin.mX, mOrigin.mY, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_bump_data );
270 stop_glerror();
271 }
272 }
273 }
274
275 // Composite the color data
276 LLGLSUIDefault gls_ui;
277 success &= mTexLayerSet->render( mOrigin.mX, mOrigin.mY, mWidth, mHeight );
278
279 if( upload_now )
280 {
281 if (!success)
282 {
283 delete baked_bump_data;
284 llinfos << "Failed attempt to bake " << mTexLayerSet->getBodyRegion() << llendl;
285 mUploadPending = FALSE;
286 }
287 else
288 {
289 readBackAndUpload(baked_bump_data);
290 }
291 }
292
293 // reset GL state
294 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
295 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
296
297 // we have valid texture data now
298 mInitialized = TRUE;
299 mNeedsUpdate = FALSE;
300
301 return success;
302}
303
304BOOL LLTexLayerSetBuffer::updateImmediate()
305{
306 mNeedsUpdate = TRUE;
307 BOOL result = FALSE;
308
309 if (needsRender())
310 {
311 preRender(FALSE);
312 result = render();
313 postRender(result);
314 }
315
316 return result;
317}
318
319void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data)
320{
321 // pointers for storing data to upload
322 U8* baked_color_data = new U8[ mWidth * mHeight * 4 ];
323
324 glReadPixels(mOrigin.mX, mOrigin.mY, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_color_data );
325 stop_glerror();
326
327 llinfos << "Baked " << mTexLayerSet->getBodyRegion() << llendl;
328 gViewerStats->incStat(LLViewerStats::ST_TEX_BAKES);
329
330 llassert( gAgent.getAvatarObject() == mTexLayerSet->getAvatar() );
331
332 // We won't need our caches since we're baked now. (Techically, we won't
333 // really be baked until this image is sent to the server and the Avatar
334 // Appearance message is received.)
335 mTexLayerSet->deleteCaches();
336
337 LLGLSUIDefault gls_ui;
338
339 LLPointer<LLImageRaw> baked_mask_image = new LLImageRaw(mWidth, mHeight, 1 );
340 U8* baked_mask_data = baked_mask_image->getData();
341
342 mTexLayerSet->gatherAlphaMasks(baked_mask_data, mWidth, mHeight);
343// imdebug("lum b=8 w=%d h=%d %p", mWidth, mHeight, baked_mask_data);
344
345
346 // writes into baked_color_data
347 const char* comment_text = NULL;
348
349 S32 baked_image_components = mBumpTexName ? 5 : 4; // red green blue [bump] clothing
350 LLPointer<LLImageRaw> baked_image = new LLImageRaw( mWidth, mHeight, baked_image_components );
351 U8* baked_image_data = baked_image->getData();
352
353 if( mBumpTexName )
354 {
355 comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // 5 channels: rgb, heightfield/alpha, mask
356
357 // Hide the alpha for the eyelashes in a corner of the bump map
358 if (mTexLayerSet->getBodyRegion() == "head")
359 {
360 S32 i = 0;
361 for( S32 u = 0; u < mWidth; u++ )
362 {
363 for( S32 v = 0; v < mHeight; v++ )
364 {
365 baked_image_data[5*i + 0] = baked_color_data[4*i + 0];
366 baked_image_data[5*i + 1] = baked_color_data[4*i + 1];
367 baked_image_data[5*i + 2] = baked_color_data[4*i + 2];
368 baked_image_data[5*i + 3] = baked_color_data[4*i + 3] < 255 ? baked_color_data[4*i + 3] : baked_bump_data[4*i];
369 baked_image_data[5*i + 4] = baked_mask_data[i];
370 i++;
371 }
372 }
373 }
374 else
375 {
376 S32 i = 0;
377 for( S32 u = 0; u < mWidth; u++ )
378 {
379 for( S32 v = 0; v < mHeight; v++ )
380 {
381 baked_image_data[5*i + 0] = baked_color_data[4*i + 0];
382 baked_image_data[5*i + 1] = baked_color_data[4*i + 1];
383 baked_image_data[5*i + 2] = baked_color_data[4*i + 2];
384 baked_image_data[5*i + 3] = baked_bump_data[4*i];
385 baked_image_data[5*i + 4] = baked_mask_data[i];
386 i++;
387 }
388 }
389 }
390 }
391 else
392 {
393 if (mTexLayerSet->getBodyRegion() == "skirt")
394 {
395 S32 i = 0;
396 for( S32 u = 0; u < mWidth; u++ )
397 {
398 for( S32 v = 0; v < mHeight; v++ )
399 {
400 baked_image_data[4*i + 0] = baked_color_data[4*i + 0];
401 baked_image_data[4*i + 1] = baked_color_data[4*i + 1];
402 baked_image_data[4*i + 2] = baked_color_data[4*i + 2];
403 baked_image_data[4*i + 3] = baked_color_data[4*i + 3]; // Use alpha, not bump
404 i++;
405 }
406 }
407 }
408 else
409 {
410 S32 i = 0;
411 for( S32 u = 0; u < mWidth; u++ )
412 {
413 for( S32 v = 0; v < mHeight; v++ )
414 {
415 baked_image_data[4*i + 0] = baked_color_data[4*i + 0];
416 baked_image_data[4*i + 1] = baked_color_data[4*i + 1];
417 baked_image_data[4*i + 2] = baked_color_data[4*i + 2];
418 baked_image_data[4*i + 3] = baked_mask_data[i];
419 i++;
420 }
421 }
422 }
423 }
424
425 LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C;
426 compressedImage->setRate(0.f);
427 LLTransactionID tid;
428 LLAssetID asset_id;
429 tid.generate();
430 asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
431
432 BOOL res = false;
433 if( compressedImage->encode(baked_image, comment_text))
434 {
435 res = LLVFile::writeFile(compressedImage->getData(), compressedImage->getDataSize(),
436 gVFS, asset_id, LLAssetType::AT_TEXTURE);
437 if (res)
438 {
439 LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C;
440 BOOL valid = FALSE;
441 S32 file_size;
442 U8* data = LLVFile::readFile(gVFS, asset_id, LLAssetType::AT_TEXTURE, &file_size);
443 if (data)
444 {
445 valid = integrity_test->validate(data, file_size); // integrity_test will delete 'data'
446 }
447 else
448 {
449 integrity_test->setLastError("Unable to read entire file");
450 }
451
452 if( valid )
453 {
454 LLBakedUploadData* baked_upload_data = new LLBakedUploadData( gAgent.getAvatarObject(), this );
455 mUploadID = baked_upload_data->mID;
456
457 gAssetStorage->storeAssetData(tid,
458 LLAssetType::AT_TEXTURE,
459 LLTexLayerSetBuffer::onTextureUploadComplete,
460 baked_upload_data,
461 TRUE, // temp_file
462 FALSE, // is_priority
463 TRUE); // store_local
464
465 mNeedsUpload = FALSE;
466 }
467 else
468 {
469 mUploadPending = FALSE;
470 llinfos << "unable to create baked upload file: corrupted" << llendl;
471 LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE, LLVFile::WRITE);
472 file.remove();
473 }
474 }
475 }
476 if (!res)
477 {
478 mUploadPending = FALSE;
479 llinfos << "unable to create baked upload file" << llendl;
480 }
481
482 delete [] baked_color_data;
483 delete [] baked_bump_data;
484}
485
486
487// static
488void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, void* userdata, S32 result) // StoreAssetData callback (not fixed)
489{
490 LLBakedUploadData* baked_upload_data = (LLBakedUploadData*)(U32)userdata;
491
492 LLVOAvatar* avatar = gAgent.getAvatarObject();
493
494 if (0 == result && avatar && !avatar->isDead())
495 {
496 // Sanity check: only the user's avatar should be uploading textures.
497 if( baked_upload_data->mAvatar == avatar )
498 {
499 // Because the avatar is still valid, it's layerset buffers should be valid also.
500 LLTexLayerSetBuffer* layerset_buffer = baked_upload_data->mLayerSetBuffer;
501 layerset_buffer->mUploadPending = FALSE;
502
503 if (layerset_buffer->mUploadID.isNull())
504 {
505 // The upload got canceled, we should be in the process of baking a new texture
506 // so request an upload with the new data
507 layerset_buffer->requestUpload();
508 }
509 else if( baked_upload_data->mID == layerset_buffer->mUploadID )
510 {
511 // This is the upload we're currently waiting for.
512 layerset_buffer->mUploadID.setNull();
513
514 if( result >= 0 )
515 {
516 LLVOAvatar::ETextureIndex baked_te = avatar->getBakedTE( layerset_buffer->mTexLayerSet );
517 if( !gAgent.cameraCustomizeAvatar() )
518 {
519 avatar->setNewBakedTexture( baked_te, uuid );
520 }
521 else
522 {
523 llinfos << "LLTexLayerSetBuffer::onTextureUploadComplete() when in Customize Avatar" << llendl;
524 }
525 }
526 else
527 {
528 llinfos << "Baked upload failed. Reason: " << result << llendl;
529 // *FIX: retry upload after n seconds, asset server could be busy
530 }
531 }
532 else
533 {
534 llinfos << "Received baked texture out of date, ignored." << llendl;
535 }
536
537 avatar->dirtyMesh();
538 }
539 }
540 else
541 {
542 // Baked texture failed to upload, but since we didn't set the new baked texture, it means that they'll
543 // try and rebake it at some point in the future (after login?)
544 llwarns << "Baked upload failed" << llendl;
545 }
546
547 delete baked_upload_data;
548}
549
550
551void LLTexLayerSetBuffer::bindTexture()
552{
553 if( mInitialized )
554 {
555 LLDynamicTexture::bindTexture();
556 }
557 else
558 {
559 gImageList.getImage(IMG_DEFAULT)->bind();
560 }
561}
562
563void LLTexLayerSetBuffer::bindBumpTexture( U32 stage )
564{
565 if( mBumpTexName )
566 {
567 LLImageGL::bindExternalTexture(mBumpTexName, stage, GL_TEXTURE_2D);
568
569 if( mLastBindTime != LLImageGL::sLastFrameTime )
570 {
571 mLastBindTime = LLImageGL::sLastFrameTime;
572 LLImageGL::updateBoundTexMem(mWidth * mHeight * 4);
573 }
574 }
575 else
576 {
577 LLImageGL::unbindTexture(stage, GL_TEXTURE_2D);
578 }
579}
580
581
582//-----------------------------------------------------------------------------
583// LLTexLayerSet
584// An ordered set of texture layers that get composited into a single texture.
585//-----------------------------------------------------------------------------
586
587LLTexLayerSetInfo::LLTexLayerSetInfo( )
588 :
589 mBodyRegion( "" ),
590 mWidth( 512 ),
591 mHeight( 512 ),
592 mClearAlpha( TRUE )
593{
594}
595
596LLTexLayerSetInfo::~LLTexLayerSetInfo( )
597{
598 std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer());
599}
600
601BOOL LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node)
602{
603 llassert( node->hasName( "layer_set" ) );
604 if( !node->hasName( "layer_set" ) )
605 {
606 return FALSE;
607 }
608
609 // body_region
610 static LLStdStringHandle body_region_string = LLXmlTree::addAttributeString("body_region");
611 if( !node->getFastAttributeString( body_region_string, mBodyRegion ) )
612 {
613 llwarns << "<layer_set> is missing body_region attribute" << llendl;
614 return FALSE;
615 }
616
617 // width, height
618 static LLStdStringHandle width_string = LLXmlTree::addAttributeString("width");
619 if( !node->getFastAttributeS32( width_string, mWidth ) )
620 {
621 return FALSE;
622 }
623
624 static LLStdStringHandle height_string = LLXmlTree::addAttributeString("height");
625 if( !node->getFastAttributeS32( height_string, mHeight ) )
626 {
627 return FALSE;
628 }
629
630 // Optional alpha component to apply after all compositing is complete.
631 static LLStdStringHandle alpha_tga_file_string = LLXmlTree::addAttributeString("alpha_tga_file");
632 node->getFastAttributeString( alpha_tga_file_string, mStaticAlphaFileName );
633
634 static LLStdStringHandle clear_alpha_string = LLXmlTree::addAttributeString("clear_alpha");
635 node->getFastAttributeBOOL( clear_alpha_string, mClearAlpha );
636
637 // <layer>
638 for (LLXmlTreeNode* child = node->getChildByName( "layer" );
639 child;
640 child = node->getNextNamedChild())
641 {
642 LLTexLayerInfo* info = new LLTexLayerInfo();
643 if( !info->parseXml( child ))
644 {
645 delete info;
646 return FALSE;
647 }
648 mLayerInfoList.push_back( info );
649 }
650 return TRUE;
651}
652
653//-----------------------------------------------------------------------------
654// LLTexLayerSet
655// An ordered set of texture layers that get composited into a single texture.
656//-----------------------------------------------------------------------------
657
658BOOL LLTexLayerSet::sHasCaches = FALSE;
659
660LLTexLayerSet::LLTexLayerSet( LLVOAvatar* avatar )
661 :
662 mComposite( NULL ),
663 mAvatar( avatar ),
664 mUpdatesEnabled( FALSE ),
665 mHasBump( FALSE ),
666 mInfo( NULL )
667{
668}
669
670LLTexLayerSet::~LLTexLayerSet()
671{
672 std::for_each(mLayerList.begin(), mLayerList.end(), DeletePointer());
673 delete mComposite;
674}
675
676//-----------------------------------------------------------------------------
677// setInfo
678//-----------------------------------------------------------------------------
679
680BOOL LLTexLayerSet::setInfo(LLTexLayerSetInfo *info)
681{
682 llassert(mInfo == NULL);
683 mInfo = info;
684 //mID = info->mID; // No ID
685
686 LLTexLayerSetInfo::layer_info_list_t::iterator iter;
687 mLayerList.reserve(info->mLayerInfoList.size());
688 for (iter = info->mLayerInfoList.begin(); iter != info->mLayerInfoList.end(); iter++)
689 {
690 LLTexLayer* layer = new LLTexLayer( this );
691 if (!layer->setInfo(*iter))
692 {
693 mInfo = NULL;
694 return FALSE;
695 }
696 mLayerList.push_back( layer );
697 }
698
699 requestUpdate();
700
701 stop_glerror();
702
703 return TRUE;
704}
705
706#if 0 // obsolete
707//-----------------------------------------------------------------------------
708// parseData
709//-----------------------------------------------------------------------------
710
711BOOL LLTexLayerSet::parseData(LLXmlTreeNode* node)
712{
713 LLTexLayerSetInfo *info = new LLTexLayerSetInfo;
714
715 if (!info->parseXml(node))
716 {
717 delete info;
718 return FALSE;
719 }
720 if (!setInfo(info))
721 {
722 delete info;
723 return FALSE;
724 }
725 return TRUE;
726}
727#endif
728
729void LLTexLayerSet::deleteCaches()
730{
731 for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
732 {
733 LLTexLayer* layer = *iter;
734 layer->deleteCaches();
735 }
736}
737
738// Returns TRUE if at least one packet of data has been received for each of the textures that this layerset depends on.
739BOOL LLTexLayerSet::isLocalTextureDataAvailable()
740{
741 return mAvatar->isLocalTextureDataAvailable( this );
742}
743
744
745// Returns TRUE if all of the data for the textures that this layerset depends on have arrived.
746BOOL LLTexLayerSet::isLocalTextureDataFinal()
747{
748 return mAvatar->isLocalTextureDataFinal( this );
749}
750
751
752BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
753{
754 BOOL success = TRUE;
755
756 LLGLSUIDefault gls_ui;
757 LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE);
758
759 // composite color layers
760 for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
761 {
762 LLTexLayer* layer = *iter;
763 if( layer->getRenderPass() == RP_COLOR )
764 {
765 success &= layer->render( x, y, width, height );
766 }
767 }
768
769 // (Optionally) replace alpha with a single component image from a tga file.
770 if( !getInfo()->mStaticAlphaFileName.empty() )
771 {
772 LLGLSNoAlphaTest gls_no_alpha_test;
773 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE );
774 glBlendFunc( GL_ONE, GL_ZERO );
775
776 if( gUseAvatarGLCache )
777 {
778 LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticAlphaFileName, TRUE );
779 if( image_gl )
780 {
781 LLGLSUIDefault gls_ui;
782 image_gl->bind();
783 gl_rect_2d_simple_tex( width, height );
784 }
785 else
786 {
787 success = FALSE;
788 }
789 }
790 else
791 {
792 LLImageRaw* image_raw = gTexStaticImageList.getImageRaw( getInfo()->mStaticAlphaFileName );
793 if( image_raw )
794 {
795 GLenum format = GL_ALPHA;
796 if( mAvatar->bindScratchTexture(format) )
797 {
798 glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, image_raw->getWidth(), image_raw->getHeight(), format, GL_UNSIGNED_BYTE, image_raw->getData() );
799 stop_glerror();
800
801 gl_rect_2d_simple_tex( width, height );
802 }
803 else
804 {
805 success = FALSE;
806 }
807 }
808 else
809 {
810 success = FALSE;
811 }
812 }
813 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
814
815 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
816 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
817 }
818 else
819 if( getInfo()->mClearAlpha )
820 {
821 // Set the alpha channel to one (clean up after previous blending)
822 LLGLSNoTextureNoAlphaTest gls_no_alpha;
823 glColor4f( 0.f, 0.f, 0.f, 1.f );
824 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE );
825
826 gl_rect_2d_simple( width, height );
827
828 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
829 }
830 stop_glerror();
831
832 return success;
833}
834
835BOOL LLTexLayerSet::renderBump( S32 x, S32 y, S32 width, S32 height )
836{
837 BOOL success = TRUE;
838
839 LLGLSUIDefault gls_ui;
840 LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE);
841
842 //static S32 bump_layer_count = 1;
843
844 for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
845 {
846 LLTexLayer* layer = *iter;
847 if( layer->getRenderPass() == RP_BUMP )
848 {
849 success &= layer->render( x, y, width, height );
850 }
851 }
852
853 // Set the alpha channel to one (clean up after previous blending)
854 LLGLSNoTextureNoAlphaTest gls_no_texture_no_alpha;
855 glColor4f( 0.f, 0.f, 0.f, 1.f );
856 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE );
857
858 gl_rect_2d_simple( width, height );
859
860 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
861 stop_glerror();
862
863 return success;
864}
865
866void LLTexLayerSet::requestUpdate()
867{
868 if( mUpdatesEnabled )
869 {
870 createComposite();
871 mComposite->requestUpdate();
872 }
873}
874
875void LLTexLayerSet::requestUpload()
876{
877 createComposite();
878 mComposite->requestUpload();
879}
880
881void LLTexLayerSet::cancelUpload()
882{
883 if(mComposite)
884 {
885 mComposite->cancelUpload();
886 }
887}
888
889void LLTexLayerSet::createComposite()
890{
891 if( !mComposite )
892 {
893 S32 width = mInfo->mWidth;
894 S32 height = mInfo->mHeight;
895 // Composite other avatars at reduced resolution
896 if( !mAvatar->mIsSelf )
897 {
898 width /= 2;
899 height /= 2;
900 }
901 mComposite = new LLTexLayerSetBuffer( this, width, height, mHasBump );
902 }
903}
904
905void LLTexLayerSet::destroyComposite()
906{
907 if( mComposite )
908 {
909 delete mComposite;
910 mComposite = NULL;
911 }
912}
913
914void LLTexLayerSet::setUpdatesEnabled( BOOL b )
915{
916 mUpdatesEnabled = b;
917}
918
919
920void LLTexLayerSet::updateComposite()
921{
922 createComposite();
923 mComposite->updateImmediate();
924}
925
926LLTexLayerSetBuffer* LLTexLayerSet::getComposite()
927{
928 createComposite();
929 return mComposite;
930}
931
932void LLTexLayerSet::gatherAlphaMasks(U8 *data, S32 width, S32 height)
933{
934 S32 size = width * height;
935
936 memset(data, 255, width * height);
937
938 for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
939 {
940 LLTexLayer* layer = *iter;
941 U8* alphaData = layer->getAlphaData();
942 if (!alphaData && layer->hasAlphaParams())
943 {
944 LLColor4 net_color;
945 layer->findNetColor( &net_color );
946 layer->invalidateMorphMasks();
947 layer->renderAlphaMasks(mComposite->getOriginX(), mComposite->getOriginY(), width, height, &net_color);
948 alphaData = layer->getAlphaData();
949 }
950 if (alphaData)
951 {
952 for( S32 i = 0; i < size; i++ )
953 {
954 U8 curAlpha = data[i];
955 U16 resultAlpha = curAlpha;
956 resultAlpha *= (alphaData[i] + 1);
957 resultAlpha = resultAlpha >> 8;
958 data[i] = (U8)resultAlpha;
959 }
960 }
961 }
962}
963
964void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components)
965{
966 for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
967 {
968 LLTexLayer* layer = *iter;
969 layer->applyMorphMask(tex_data, width, height, num_components);
970 }
971}
972
973//-----------------------------------------------------------------------------
974// LLTexLayerInfo
975//-----------------------------------------------------------------------------
976LLTexLayerInfo::LLTexLayerInfo( )
977 :
978 mWriteAllChannels( FALSE ),
979 mRenderPass( RP_COLOR ),
980 mFixedColor( 0.f, 0.f, 0.f, 0.f ),
981 mLocalTexture( -1 ),
982 mStaticImageIsMask( FALSE ),
983 mUseLocalTextureAlphaOnly( FALSE )
984{
985}
986
987LLTexLayerInfo::~LLTexLayerInfo( )
988{
989 std::for_each(mColorInfoList.begin(), mColorInfoList.end(), DeletePointer());
990 std::for_each(mAlphaInfoList.begin(), mAlphaInfoList.end(), DeletePointer());
991}
992
993BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node)
994{
995 llassert( node->hasName( "layer" ) );
996
997 // name attribute
998 static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
999 if( !node->getFastAttributeString( name_string, mName ) )
1000 {
1001 return FALSE;
1002 }
1003
1004 static LLStdStringHandle write_all_channels_string = LLXmlTree::addAttributeString("write_all_channels");
1005 node->getFastAttributeBOOL( write_all_channels_string, mWriteAllChannels );
1006
1007 LLString render_pass_name;
1008 static LLStdStringHandle render_pass_string = LLXmlTree::addAttributeString("render_pass");
1009 if( node->getFastAttributeString( render_pass_string, render_pass_name ) )
1010 {
1011 if( render_pass_name == "bump" )
1012 {
1013 mRenderPass = RP_BUMP;
1014 }
1015 }
1016
1017 // Note: layers can have either a "global_color" attrib, a "fixed_color" attrib, or a <param_color> child.
1018 // global color attribute (optional)
1019 static LLStdStringHandle global_color_string = LLXmlTree::addAttributeString("global_color");
1020 node->getFastAttributeString( global_color_string, mGlobalColor );
1021
1022 // color attribute (optional)
1023 LLColor4U color4u;
1024 static LLStdStringHandle fixed_color_string = LLXmlTree::addAttributeString("fixed_color");
1025 if( node->getFastAttributeColor4U( fixed_color_string, color4u ) )
1026 {
1027 mFixedColor.setVec( color4u );
1028 }
1029
1030 // <texture> optional sub-element
1031 for (LLXmlTreeNode* texture_node = node->getChildByName( "texture" );
1032 texture_node;
1033 texture_node = node->getNextNamedChild())
1034 {
1035 LLString local_texture;
1036 static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file");
1037 static LLStdStringHandle local_texture_string = LLXmlTree::addAttributeString("local_texture");
1038 static LLStdStringHandle file_is_mask_string = LLXmlTree::addAttributeString("file_is_mask");
1039 static LLStdStringHandle local_texture_alpha_only_string = LLXmlTree::addAttributeString("local_texture_alpha_only");
1040 if( texture_node->getFastAttributeString( tga_file_string, mStaticImageFileName ) )
1041 {
1042 texture_node->getFastAttributeBOOL( file_is_mask_string, mStaticImageIsMask );
1043 }
1044 else if( texture_node->getFastAttributeString( local_texture_string, local_texture ) )
1045 {
1046 texture_node->getFastAttributeBOOL( local_texture_alpha_only_string, mUseLocalTextureAlphaOnly );
1047
1048 if( "upper_shirt" == local_texture )
1049 {
1050 mLocalTexture = LLVOAvatar::LOCTEX_UPPER_SHIRT;
1051 }
1052 else if( "upper_bodypaint" == local_texture )
1053 {
1054 mLocalTexture = LLVOAvatar::LOCTEX_UPPER_BODYPAINT;
1055 }
1056 else if( "lower_pants" == local_texture )
1057 {
1058 mLocalTexture = LLVOAvatar::LOCTEX_LOWER_PANTS;
1059 }
1060 else if( "lower_bodypaint" == local_texture )
1061 {
1062 mLocalTexture = LLVOAvatar::LOCTEX_LOWER_BODYPAINT;
1063 }
1064 else if( "lower_shoes" == local_texture )
1065 {
1066 mLocalTexture = LLVOAvatar::LOCTEX_LOWER_SHOES;
1067 }
1068 else if( "head_bodypaint" == local_texture )
1069 {
1070 mLocalTexture = LLVOAvatar::LOCTEX_HEAD_BODYPAINT;
1071 }
1072 else if( "lower_socks" == local_texture )
1073 {
1074 mLocalTexture = LLVOAvatar::LOCTEX_LOWER_SOCKS;
1075 }
1076 else if( "upper_jacket" == local_texture )
1077 {
1078 mLocalTexture = LLVOAvatar::LOCTEX_UPPER_JACKET;
1079 }
1080 else if( "lower_jacket" == local_texture )
1081 {
1082 mLocalTexture = LLVOAvatar::LOCTEX_LOWER_JACKET;
1083 }
1084 else if( "upper_gloves" == local_texture )
1085 {
1086 mLocalTexture = LLVOAvatar::LOCTEX_UPPER_GLOVES;
1087 }
1088 else if( "upper_undershirt" == local_texture )
1089 {
1090 mLocalTexture = LLVOAvatar::LOCTEX_UPPER_UNDERSHIRT;
1091 }
1092 else if( "lower_underpants" == local_texture )
1093 {
1094 mLocalTexture = LLVOAvatar::LOCTEX_LOWER_UNDERPANTS;
1095 }
1096 else if( "eyes_iris" == local_texture )
1097 {
1098 mLocalTexture = LLVOAvatar::LOCTEX_EYES_IRIS;
1099 }
1100 else if( "skirt" == local_texture )
1101 {
1102 mLocalTexture = LLVOAvatar::LOCTEX_SKIRT;
1103 }
1104 else
1105 {
1106 llwarns << "<texture> element has invalid local_texure attribute: " << mName << " " << local_texture << llendl;
1107 return FALSE;
1108 }
1109 }
1110 else
1111 {
1112 llwarns << "<texture> element is missing a required attribute. " << mName << llendl;
1113 return FALSE;
1114 }
1115 }
1116
1117 for (LLXmlTreeNode* maskNode = node->getChildByName( "morph_mask" );
1118 maskNode;
1119 maskNode = node->getNextNamedChild())
1120 {
1121 LLString morph_name;
1122 static LLStdStringHandle morph_name_string = LLXmlTree::addAttributeString("morph_name");
1123 if (maskNode->getFastAttributeString(morph_name_string, morph_name))
1124 {
1125 BOOL invert = FALSE;
1126 static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert");
1127 maskNode->getFastAttributeBOOL(invert_string, invert);
1128 mMorphNameList.push_back(std::pair<LLString,BOOL>(morph_name,invert));
1129 }
1130 }
1131
1132 // <param> optional sub-element (color or alpha params)
1133 for (LLXmlTreeNode* child = node->getChildByName( "param" );
1134 child;
1135 child = node->getNextNamedChild())
1136 {
1137 if( child->getChildByName( "param_color" ) )
1138 {
1139 // <param><param_color/></param>
1140 LLTexParamColorInfo* info = new LLTexParamColorInfo( );
1141 if (!info->parseXml(child))
1142 {
1143 delete info;
1144 return FALSE;
1145 }
1146 mColorInfoList.push_back( info );
1147 }
1148 else if( child->getChildByName( "param_alpha" ) )
1149 {
1150 // <param><param_alpha/></param>
1151 LLTexLayerParamAlphaInfo* info = new LLTexLayerParamAlphaInfo( );
1152 if (!info->parseXml(child))
1153 {
1154 delete info;
1155 return FALSE;
1156 }
1157 mAlphaInfoList.push_back( info );
1158 }
1159 }
1160
1161 return TRUE;
1162}
1163
1164//-----------------------------------------------------------------------------
1165// LLTexLayer
1166// A single texture layer, consisting of:
1167// * color, consisting of either
1168// * one or more color parameters (weighted colors)
1169// * a reference to a global color
1170// * a fixed color with non-zero alpha
1171// * opaque white (the default)
1172// * (optional) a texture defined by either
1173// * a GUID
1174// * a texture entry index (TE)
1175// * (optional) one or more alpha parameters (weighted alpha textures)
1176//-----------------------------------------------------------------------------
1177LLTexLayer::LLTexLayer( LLTexLayerSet* layer_set )
1178 :
1179 mTexLayerSet( layer_set ),
1180 mMorphMasksValid( FALSE ),
1181 mStaticImageInvalid( FALSE ),
1182 mInfo( NULL )
1183{
1184}
1185
1186LLTexLayer::~LLTexLayer()
1187{
1188 // mParamAlphaList and mParamColorList are LLViewerVisualParam's and get
1189 // deleted with ~LLCharacter()
1190 //std::for_each(mParamAlphaList.begin(), mParamAlphaList.end(), DeletePointer());
1191 //std::for_each(mParamColorList.begin(), mParamColorList.end(), DeletePointer());
1192
1193 for( alpha_cache_t::iterator iter = mAlphaCache.begin();
1194 iter != mAlphaCache.end(); iter++ )
1195 {
1196 U8* alpha_data = iter->second;
1197 delete [] alpha_data;
1198 }
1199}
1200
1201//-----------------------------------------------------------------------------
1202// setInfo
1203//-----------------------------------------------------------------------------
1204
1205BOOL LLTexLayer::setInfo(LLTexLayerInfo* info)
1206{
1207 llassert(mInfo == NULL);
1208 mInfo = info;
1209 //mID = info->mID; // No ID
1210
1211 if (info->mRenderPass == RP_BUMP)
1212 mTexLayerSet->setBump(TRUE);
1213
1214 {
1215 LLTexLayerInfo::morph_name_list_t::iterator iter;
1216 for (iter = mInfo->mMorphNameList.begin(); iter != mInfo->mMorphNameList.end(); iter++)
1217 {
1218 // *FIX: we assume that the referenced visual param is a
1219 // morph target, need a better way of actually looking
1220 // this up.
1221 LLPolyMorphTarget *morph_param;
1222 LLString *name = &(iter->first);
1223 morph_param = (LLPolyMorphTarget *)(getTexLayerSet()->getAvatar()->getVisualParam(name->c_str()));
1224 if (morph_param)
1225 {
1226 BOOL invert = iter->second;
1227 addMaskedMorph(morph_param, invert);
1228 }
1229 }
1230 }
1231
1232 {
1233 LLTexLayerInfo::color_info_list_t::iterator iter;
1234 mParamColorList.reserve(mInfo->mColorInfoList.size());
1235 for (iter = mInfo->mColorInfoList.begin(); iter != mInfo->mColorInfoList.end(); iter++)
1236 {
1237 LLTexParamColor* param_color = new LLTexParamColor( this );
1238 if (!param_color->setInfo(*iter))
1239 {
1240 mInfo = NULL;
1241 return FALSE;
1242 }
1243 mParamColorList.push_back( param_color );
1244 }
1245 }
1246 {
1247 LLTexLayerInfo::alpha_info_list_t::iterator iter;
1248 mParamAlphaList.reserve(mInfo->mAlphaInfoList.size());
1249 for (iter = mInfo->mAlphaInfoList.begin(); iter != mInfo->mAlphaInfoList.end(); iter++)
1250 {
1251 LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha( this );
1252 if (!param_alpha->setInfo(*iter))
1253 {
1254 mInfo = NULL;
1255 return FALSE;
1256 }
1257 mParamAlphaList.push_back( param_alpha );
1258 }
1259 }
1260
1261 return TRUE;
1262}
1263
1264#if 0 // obsolete
1265//-----------------------------------------------------------------------------
1266// parseData
1267//-----------------------------------------------------------------------------
1268BOOL LLTexLayer::parseData( LLXmlTreeNode* node )
1269{
1270 LLTexLayerInfo *info = new LLTexLayerInfo;
1271
1272 if (!info->parseXml(node))
1273 {
1274 delete info;
1275 return FALSE;
1276 }
1277 if (!setInfo(info))
1278 {
1279 delete info;
1280 return FALSE;
1281 }
1282 return TRUE;
1283}
1284#endif
1285
1286//-----------------------------------------------------------------------------
1287
1288
1289BOOL LLTexLayer::loadStaticImageRaw()
1290{
1291 if( mStaticImageRaw.isNull() && !mStaticImageInvalid)
1292 {
1293 mStaticImageRaw = gTexStaticImageList.getImageRaw( getInfo()->mStaticImageFileName );
1294 // We now have something in one of our caches
1295 LLTexLayerSet::sHasCaches |= mStaticImageRaw.notNull() ? TRUE : FALSE;
1296 if( mStaticImageRaw.isNull() )
1297 {
1298 llwarns << "Unable to load static file: " << getInfo()->mStaticImageFileName << llendl;
1299 mStaticImageInvalid = TRUE; // don't try again.
1300 return FALSE;
1301 }
1302 }
1303 return TRUE;
1304}
1305
1306void LLTexLayer::deleteCaches()
1307{
1308 for( alpha_list_t::iterator iter = mParamAlphaList.begin();
1309 iter != mParamAlphaList.end(); iter++ )
1310 {
1311 LLTexLayerParamAlpha* param = *iter;
1312 param->deleteCaches();
1313 }
1314 mStaticImageRaw = NULL;
1315}
1316
1317BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
1318{
1319 LLGLEnable color_mat(GL_COLOR_MATERIAL);
1320 gPipeline.disableLights();
1321
1322 BOOL success = TRUE;
1323
1324 BOOL color_specified = FALSE;
1325 BOOL alpha_mask_specified = FALSE;
1326
1327 LLColor4 net_color;
1328 color_specified = findNetColor( &net_color );
1329
1330 // If you can't see the layer, don't render it.
1331 if( is_approx_zero( net_color.mV[VW] ) )
1332 {
1333 return success;
1334 }
1335
1336 alpha_list_t::iterator iter = mParamAlphaList.begin();
1337 if( iter != mParamAlphaList.end() )
1338 {
1339 // If we have alpha masks, but we're skipping all of them, skip the whole layer.
1340 // However, we can't do this optimization if we have morph masks that need updating.
1341 if( mMaskedMorphs.empty() )
1342 {
1343 BOOL skip_layer = TRUE;
1344
1345 while( iter != mParamAlphaList.end() )
1346 {
1347 LLTexLayerParamAlpha* param = *iter;
1348
1349 if( !param->getSkip() )
1350 {
1351 skip_layer = FALSE;
1352 break;
1353 }
1354
1355 iter++;
1356 }
1357
1358 if( skip_layer )
1359 {
1360 return success;
1361 }
1362 }
1363
1364 renderAlphaMasks( x, y, width, height, &net_color );
1365 alpha_mask_specified = TRUE;
1366 glBlendFunc( GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA );
1367 }
1368
1369 glColor4fv( net_color.mV);
1370
1371 if( getInfo()->mWriteAllChannels )
1372 {
1373 glBlendFunc( GL_ONE, GL_ZERO );
1374 }
1375
1376 if( (getInfo()->mLocalTexture != -1) && !getInfo()->mUseLocalTextureAlphaOnly )
1377 {
1378 if( gUseAvatarGLCache )
1379 {
1380 LLImageGL* image_gl = NULL;
1381 if( mTexLayerSet->getAvatar()->getLocalTextureGL( getInfo()->mLocalTexture, &image_gl ) )
1382 {
1383 if( image_gl )
1384 {
1385 LLGLDisable alpha_test(getInfo()->mWriteAllChannels ? GL_ALPHA_TEST : 0);
1386
1387 BOOL old_clamps = image_gl->getClampS();
1388 BOOL old_clampt = image_gl->getClampT();
1389
1390 image_gl->bind();
1391 image_gl->setClamp(TRUE, TRUE);
1392
1393 gl_rect_2d_simple_tex( width, height );
1394
1395 image_gl->setClamp(old_clamps, old_clampt);
1396 image_gl->unbindTexture(0, GL_TEXTURE_2D);
1397 }
1398 }
1399 else
1400 {
1401 success = FALSE;
1402 }
1403 }
1404 else
1405 {
1406 LLPointer<LLImageRaw> image_raw = new LLImageRaw;
1407 if( mTexLayerSet->getAvatar()->getLocalTextureRaw( getInfo()->mLocalTexture, image_raw ) )
1408 {
1409 success &= renderImageRaw( image_raw->getData(),
1410 image_raw->getWidth(),
1411 image_raw->getHeight(),
1412 image_raw->getComponents(),
1413 width,
1414 height,
1415 FALSE );
1416 }
1417 else
1418 {
1419 success = FALSE;
1420 }
1421 }
1422 }
1423
1424 if( !getInfo()->mStaticImageFileName.empty() )
1425 {
1426 if( gUseAvatarGLCache )
1427 {
1428 LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask );
1429 if( image_gl )
1430 {
1431 image_gl->bind();
1432 gl_rect_2d_simple_tex( width, height );
1433 image_gl->unbindTexture(0, GL_TEXTURE_2D);
1434 }
1435 else
1436 {
1437 success = FALSE;
1438 }
1439 }
1440 else
1441 {
1442 // Don't load the image file until we actually need it the first time. Like now.
1443 if (!loadStaticImageRaw())
1444 {
1445 success = FALSE;
1446 }
1447 if( mStaticImageRaw.notNull() )
1448 {
1449 success &= renderImageRaw(
1450 mStaticImageRaw->getData(),
1451 mStaticImageRaw->getWidth(),
1452 mStaticImageRaw->getHeight(),
1453 mStaticImageRaw->getComponents(), width, height, getInfo()->mStaticImageIsMask );
1454 }
1455 else
1456 {
1457 success = FALSE;
1458 }
1459 }
1460 }
1461
1462 if( ((-1 == getInfo()->mLocalTexture) ||
1463 getInfo()->mUseLocalTextureAlphaOnly) &&
1464 getInfo()->mStaticImageFileName.empty() &&
1465 color_specified )
1466 {
1467 LLGLSNoTextureNoAlphaTest gls;
1468 glColor4fv( net_color.mV);
1469 gl_rect_2d_simple( width, height );
1470 }
1471
1472 if( alpha_mask_specified || getInfo()->mWriteAllChannels )
1473 {
1474 // Restore standard blend func value
1475 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1476 stop_glerror();
1477 }
1478
1479 if( !success )
1480 {
1481 llinfos << "LLTexLayer::render() partial: " << getInfo()->mName << llendl;
1482 }
1483 return success;
1484}
1485
1486U8* LLTexLayer::getAlphaData()
1487{
1488 LLCRC alpha_mask_crc;
1489 const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID(getInfo()->mLocalTexture);
1490 alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES);
1491
1492 for( alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ )
1493 {
1494 LLTexLayerParamAlpha* param = *iter;
1495 F32 param_weight = param->getWeight();
1496 alpha_mask_crc.update((U8*)&param_weight, sizeof(F32));
1497 }
1498
1499 U32 cache_index = alpha_mask_crc.getCRC();
1500
1501 alpha_cache_t::iterator iter2 = mAlphaCache.find(cache_index);
1502 return (iter2 == mAlphaCache.end()) ? 0 : iter2->second;
1503}
1504
1505BOOL LLTexLayer::findNetColor( LLColor4* net_color )
1506{
1507 // Color is either:
1508 // * one or more color parameters (weighted colors) (which may make use of a global color or fixed color)
1509 // * a reference to a global color
1510 // * a fixed color with non-zero alpha
1511 // * opaque white (the default)
1512
1513 if( !mParamColorList.empty() )
1514 {
1515 if( !getGlobalColor().empty() )
1516 {
1517 net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getInfo()->mGlobalColor ) );
1518 }
1519 else
1520 if( getInfo()->mFixedColor.mV[VW] )
1521 {
1522 net_color->setVec( getInfo()->mFixedColor );
1523 }
1524 else
1525 {
1526 net_color->setVec( 0.f, 0.f, 0.f, 0.f );
1527 }
1528
1529 for( color_list_t::iterator iter = mParamColorList.begin();
1530 iter != mParamColorList.end(); iter++ )
1531 {
1532 LLTexParamColor* param = *iter;
1533 LLColor4 param_net = param->getNetColor();
1534 switch( param->getOperation() )
1535 {
1536 case OP_ADD:
1537 *net_color += param_net;
1538 break;
1539 case OP_MULTIPLY:
1540 net_color->mV[VX] *= param_net.mV[VX];
1541 net_color->mV[VY] *= param_net.mV[VY];
1542 net_color->mV[VZ] *= param_net.mV[VZ];
1543 net_color->mV[VW] *= param_net.mV[VW];
1544 break;
1545 case OP_BLEND:
1546 net_color->setVec( lerp(*net_color, param_net, param->getWeight()) );
1547 break;
1548 default:
1549 llassert(0);
1550 break;
1551 }
1552 }
1553 return TRUE;
1554 }
1555
1556 if( !getGlobalColor().empty() )
1557 {
1558 net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getGlobalColor() ) );
1559 return TRUE;
1560 }
1561
1562 if( getInfo()->mFixedColor.mV[VW] )
1563 {
1564 net_color->setVec( getInfo()->mFixedColor );
1565 return TRUE;
1566 }
1567
1568 net_color->setToWhite();
1569
1570 return FALSE; // No need to draw a separate colored polygon
1571}
1572
1573
1574BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4* colorp )
1575{
1576 BOOL success = TRUE;
1577
1578 llassert( !mParamAlphaList.empty() );
1579
1580 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE );
1581
1582 alpha_list_t::iterator iter = mParamAlphaList.begin();
1583 LLTexLayerParamAlpha* first_param = *iter;
1584
1585 // Note: if the first param is a mulitply, multiply against the current buffer's alpha
1586 if( !first_param || !first_param->getMultiplyBlend() )
1587 {
1588 LLGLSNoTextureNoAlphaTest gls_no_texture_no_alpha_test;
1589
1590 // Clear the alpha
1591 glBlendFunc( GL_ONE, GL_ZERO );
1592
1593 glColor4f( 0.f, 0.f, 0.f, 0.f );
1594 gl_rect_2d_simple( width, height );
1595 }
1596
1597 // Accumulate alphas
1598 LLGLSNoAlphaTest gls_no_alpha_test;
1599 glColor4f( 1.f, 1.f, 1.f, 1.f );
1600
1601 for( iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ )
1602 {
1603 LLTexLayerParamAlpha* param = *iter;
1604 success &= param->render( x, y, width, height );
1605 }
1606
1607 // Approximates a min() function
1608 glBlendFunc( GL_DST_ALPHA, GL_ZERO );
1609
1610 // Accumulate the alpha component of the texture
1611 if( getInfo()->mLocalTexture != -1 )
1612 {
1613 if( gUseAvatarGLCache )
1614 {
1615 LLImageGL* image_gl = NULL;
1616 if( mTexLayerSet->getAvatar()->getLocalTextureGL( getInfo()->mLocalTexture, &image_gl ) )
1617 {
1618 if( image_gl && (image_gl->getComponents() == 4) )
1619 {
1620 LLGLSNoAlphaTest gls_no_alpha_test;
1621
1622 BOOL old_clamps = image_gl->getClampS();
1623 BOOL old_clampt = image_gl->getClampT();
1624 image_gl->bind();
1625 image_gl->setClamp(TRUE, TRUE);
1626
1627 gl_rect_2d_simple_tex( width, height );
1628
1629 image_gl->setClamp(old_clamps, old_clampt);
1630 image_gl->unbindTexture(0, GL_TEXTURE_2D);
1631 }
1632 }
1633 else
1634 {
1635 success = FALSE;
1636 }
1637 }
1638 else
1639 {
1640 LLPointer<LLImageRaw> image_raw = new LLImageRaw;
1641 if( mTexLayerSet->getAvatar()->getLocalTextureRaw( getInfo()->mLocalTexture, image_raw ) )
1642 {
1643 if(image_raw->getComponents() == 4)
1644 {
1645 success &= renderImageRaw(
1646 image_raw->getData(),
1647 image_raw->getWidth(),
1648 image_raw->getHeight(),
1649 image_raw->getComponents(), width, height, FALSE );
1650 }
1651 }
1652 else
1653 {
1654 success = FALSE;
1655 }
1656 }
1657 }
1658
1659 if( !getInfo()->mStaticImageFileName.empty() )
1660 {
1661 if( gUseAvatarGLCache )
1662 {
1663 LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask );
1664 if( image_gl )
1665 {
1666 if( (image_gl->getComponents() == 4) ||
1667 ( (image_gl->getComponents() == 1) && getInfo()->mStaticImageIsMask ) )
1668 {
1669 LLGLSNoAlphaTest gls_no_alpha_test;
1670 image_gl->bind();
1671 gl_rect_2d_simple_tex( width, height );
1672 image_gl->unbindTexture(0, GL_TEXTURE_2D);
1673 }
1674 }
1675 else
1676 {
1677 success = FALSE;
1678 }
1679 }
1680 else
1681 {
1682 // Don't load the image file until we actually need it the first time. Like now.
1683 if (!loadStaticImageRaw())
1684 {
1685 success = FALSE;
1686 }
1687
1688 if( mStaticImageRaw.notNull() )
1689 {
1690 if( (mStaticImageRaw->getComponents() == 4) ||
1691 ( (mStaticImageRaw->getComponents() == 1) && getInfo()->mStaticImageIsMask ) )
1692 {
1693 success &= renderImageRaw(
1694 mStaticImageRaw->getData(),
1695 mStaticImageRaw->getWidth(),
1696 mStaticImageRaw->getHeight(),
1697 mStaticImageRaw->getComponents(), width, height, getInfo()->mStaticImageIsMask );
1698 }
1699 }
1700 else
1701 {
1702 success = FALSE;
1703 }
1704 }
1705 }
1706
1707 // Draw a rectangle with the layer color to multiply the alpha by that color's alpha.
1708 // Note: we're still using glBlendFunc( GL_DST_ALPHA, GL_ZERO );
1709 if( colorp->mV[VW] != 1.f )
1710 {
1711 LLGLSNoTextureNoAlphaTest gls_no_texture_no_alpha_test;
1712 glColor4fv( colorp->mV );
1713 gl_rect_2d_simple( width, height );
1714 }
1715
1716
1717 LLGLSUIDefault gls_ui;
1718
1719 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
1720
1721 if (!mMorphMasksValid && !mMaskedMorphs.empty())
1722 {
1723 LLCRC alpha_mask_crc;
1724 const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID(getInfo()->mLocalTexture);
1725 alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES);
1726
1727 for( alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ )
1728 {
1729 LLTexLayerParamAlpha* param = *iter;
1730 F32 param_weight = param->getWeight();
1731 alpha_mask_crc.update((U8*)&param_weight, sizeof(F32));
1732 }
1733
1734 U32 cache_index = alpha_mask_crc.getCRC();
1735
1736 alpha_cache_t::iterator iter2 = mAlphaCache.find(cache_index);
1737 U8* alpha_data;
1738 if (iter2 != mAlphaCache.end())
1739 {
1740 alpha_data = iter2->second;
1741 }
1742 else
1743 {
1744 // clear out a slot if we have filled our cache
1745 S32 max_cache_entries = getTexLayerSet()->getAvatar()->mIsSelf ? 4 : 1;
1746 while ((S32)mAlphaCache.size() >= max_cache_entries)
1747 {
1748 iter2 = mAlphaCache.begin(); // arbitrarily grab the first entry
1749 alpha_data = iter2->second;
1750 delete [] alpha_data;
1751 mAlphaCache.erase(iter2);
1752 }
1753 alpha_data = new U8[width * height];
1754 mAlphaCache[cache_index] = alpha_data;
1755 glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data);
1756 }
1757
1758 getTexLayerSet()->getAvatar()->dirtyMesh();
1759
1760 mMorphMasksValid = TRUE;
1761
1762 for( morph_list_t::iterator iter3 = mMaskedMorphs.begin();
1763 iter3 != mMaskedMorphs.end(); iter3++ )
1764 {
1765 LLMaskedMorph* maskedMorph = &(*iter3);
1766 maskedMorph->mMorphTarget->applyMask(alpha_data, width, height, 1, maskedMorph->mInvert);
1767 }
1768 }
1769
1770 return success;
1771}
1772
1773void LLTexLayer::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components)
1774{
1775 for( morph_list_t::iterator iter = mMaskedMorphs.begin();
1776 iter != mMaskedMorphs.end(); iter++ )
1777 {
1778 LLMaskedMorph* maskedMorph = &(*iter);
1779 maskedMorph->mMorphTarget->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert);
1780 }
1781}
1782
1783// Returns TRUE on success.
1784BOOL LLTexLayer::renderImageRaw( U8* in_data, S32 in_width, S32 in_height, S32 in_components, S32 width, S32 height, BOOL is_mask )
1785{
1786 if (!in_data)
1787 {
1788 return FALSE;
1789 }
1790 GLenum format_options[4] = { GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA };
1791 GLenum format = format_options[in_components-1];
1792 if( is_mask )
1793 {
1794 llassert( 1 == in_components );
1795 format = GL_ALPHA;
1796 }
1797
1798 if( (in_width != VOAVATAR_SCRATCH_TEX_WIDTH) || (in_height != VOAVATAR_SCRATCH_TEX_HEIGHT) )
1799 {
1800 LLGLSNoAlphaTest gls_no_alpha_test;
1801
1802 GLenum internal_format_options[4] = { GL_LUMINANCE8, GL_LUMINANCE8_ALPHA8, GL_RGB8, GL_RGBA8 };
1803 GLenum internal_format = internal_format_options[in_components-1];
1804 if( is_mask )
1805 {
1806 llassert( 1 == in_components );
1807 internal_format = GL_ALPHA8;
1808 }
1809
1810 GLuint name = 0;
1811 glGenTextures(1, &name );
1812 stop_glerror();
1813
1814 LLImageGL::bindExternalTexture( name, 0, GL_TEXTURE_2D );
1815 stop_glerror();
1816
1817 glTexImage2D(
1818 GL_TEXTURE_2D, 0, internal_format,
1819 in_width, in_height,
1820 0, format, GL_UNSIGNED_BYTE, in_data );
1821 stop_glerror();
1822
1823 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1824 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1825
1826 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1827 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1828
1829 gl_rect_2d_simple_tex( width, height );
1830
1831 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
1832
1833 glDeleteTextures(1, &name );
1834 stop_glerror();
1835 }
1836 else
1837 {
1838 LLGLSNoAlphaTest gls_no_alpha_test;
1839
1840 if( !mTexLayerSet->getAvatar()->bindScratchTexture(format) )
1841 {
1842 return FALSE;
1843 }
1844
1845 glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, in_width, in_height, format, GL_UNSIGNED_BYTE, in_data );
1846 stop_glerror();
1847
1848 gl_rect_2d_simple_tex( width, height );
1849
1850 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
1851 }
1852
1853 return TRUE;
1854}
1855
1856void LLTexLayer::requestUpdate()
1857{
1858 mTexLayerSet->requestUpdate();
1859}
1860
1861void LLTexLayer::addMaskedMorph(LLPolyMorphTarget* morph_target, BOOL invert)
1862{
1863 mMaskedMorphs.push_front(LLMaskedMorph(morph_target, invert));
1864}
1865
1866void LLTexLayer::invalidateMorphMasks()
1867{
1868 mMorphMasksValid = FALSE;
1869}
1870
1871//-----------------------------------------------------------------------------
1872// LLTexLayerParamAlphaInfo
1873//-----------------------------------------------------------------------------
1874LLTexLayerParamAlphaInfo::LLTexLayerParamAlphaInfo( )
1875 :
1876 mMultiplyBlend( FALSE ),
1877 mSkipIfZeroWeight( FALSE ),
1878 mDomain( 0.f )
1879{
1880}
1881
1882BOOL LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node)
1883{
1884 llassert( node->hasName( "param" ) && node->getChildByName( "param_alpha" ) );
1885
1886 if( !LLViewerVisualParamInfo::parseXml(node) )
1887 return FALSE;
1888
1889 LLXmlTreeNode* param_alpha_node = node->getChildByName( "param_alpha" );
1890 if( !param_alpha_node )
1891 {
1892 return FALSE;
1893 }
1894
1895 static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file");
1896 if( param_alpha_node->getFastAttributeString( tga_file_string, mStaticImageFileName ) )
1897 {
1898 // Don't load the image file until it's actually needed.
1899 }
1900// else
1901// {
1902// llwarns << "<param_alpha> element is missing tga_file attribute." << llendl;
1903// }
1904
1905 static LLStdStringHandle multiply_blend_string = LLXmlTree::addAttributeString("multiply_blend");
1906 param_alpha_node->getFastAttributeBOOL( multiply_blend_string, mMultiplyBlend );
1907
1908 static LLStdStringHandle skip_if_zero_string = LLXmlTree::addAttributeString("skip_if_zero");
1909 param_alpha_node->getFastAttributeBOOL( skip_if_zero_string, mSkipIfZeroWeight );
1910
1911 static LLStdStringHandle domain_string = LLXmlTree::addAttributeString("domain");
1912 param_alpha_node->getFastAttributeF32( domain_string, mDomain );
1913
1914 gGradientPaletteList.initPalette(mDomain);
1915
1916 return TRUE;
1917}
1918
1919//-----------------------------------------------------------------------------
1920// LLTexLayerParamAlpha
1921//-----------------------------------------------------------------------------
1922
1923// static
1924LLTexLayerParamAlpha::param_alpha_ptr_list_t LLTexLayerParamAlpha::sInstances;
1925
1926// static
1927void LLTexLayerParamAlpha::dumpCacheByteCount()
1928{
1929 S32 gl_bytes = 0;
1930 getCacheByteCount( &gl_bytes );
1931 llinfos << "Processed Alpha Texture Cache GL:" << (gl_bytes/1024) << "KB" << llendl;
1932}
1933
1934// static
1935void LLTexLayerParamAlpha::getCacheByteCount( S32* gl_bytes )
1936{
1937 *gl_bytes = 0;
1938
1939 for( param_alpha_ptr_list_t::iterator iter = sInstances.begin();
1940 iter != sInstances.end(); iter++ )
1941 {
1942 LLTexLayerParamAlpha* instance = *iter;
1943 LLImageGL* image_gl = instance->mCachedProcessedImageGL;
1944 if( image_gl )
1945 {
1946 S32 bytes = (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents();
1947
1948 if( image_gl->getHasGLTexture() )
1949 {
1950 *gl_bytes += bytes;
1951 }
1952 }
1953 }
1954}
1955
1956LLTexLayerParamAlpha::LLTexLayerParamAlpha( LLTexLayer* layer )
1957 :
1958 mCachedProcessedImageGL( NULL ),
1959 mTexLayer( layer ),
1960 mNeedsCreateTexture( FALSE ),
1961 mStaticImageInvalid( FALSE ),
1962 mAvgDistortionVec(1.f, 1.f, 1.f),
1963 mCachedEffectiveWeight(0.f)
1964{
1965 sInstances.push_front( this );
1966}
1967
1968LLTexLayerParamAlpha::~LLTexLayerParamAlpha()
1969{
1970 deleteCaches();
1971 sInstances.remove( this );
1972}
1973
1974//-----------------------------------------------------------------------------
1975// setInfo()
1976//-----------------------------------------------------------------------------
1977BOOL LLTexLayerParamAlpha::setInfo(LLTexLayerParamAlphaInfo *info)
1978{
1979 llassert(mInfo == NULL);
1980 if (info->mID < 0)
1981 return FALSE;
1982 mInfo = info;
1983 mID = info->mID;
1984
1985 mTexLayer->getTexLayerSet()->getAvatar()->addVisualParam( this );
1986 setWeight(getDefaultWeight(), FALSE );
1987
1988 return TRUE;
1989}
1990
1991//-----------------------------------------------------------------------------
1992
1993void LLTexLayerParamAlpha::deleteCaches()
1994{
1995 mStaticImageTGA = NULL; // deletes image
1996 mCachedProcessedImageGL = NULL;
1997 mStaticImageRaw = NULL;
1998 mNeedsCreateTexture = FALSE;
1999}
2000
2001void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL set_by_user)
2002{
2003 if (mIsAnimating)
2004 {
2005 return;
2006 }
2007 F32 min_weight = getMinWeight();
2008 F32 max_weight = getMaxWeight();
2009 F32 new_weight = llclamp(weight, min_weight, max_weight);
2010 U8 cur_u8 = F32_to_U8( mCurWeight, min_weight, max_weight );
2011 U8 new_u8 = F32_to_U8( new_weight, min_weight, max_weight );
2012 if( cur_u8 != new_u8)
2013 {
2014 mCurWeight = new_weight;
2015
2016 LLVOAvatar* avatar = mTexLayer->getTexLayerSet()->getAvatar();
2017 if( avatar->getSex() & getSex() )
2018 {
2019 avatar->invalidateComposite( mTexLayer->getTexLayerSet(), set_by_user );
2020 mTexLayer->invalidateMorphMasks();
2021 }
2022 }
2023}
2024
2025void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL set_by_user)
2026{
2027 mTargetWeight = target_value;
2028 setWeight(target_value, set_by_user);
2029 mIsAnimating = TRUE;
2030 if (mNext)
2031 {
2032 mNext->setAnimationTarget(target_value, set_by_user);
2033 }
2034}
2035
2036void LLTexLayerParamAlpha::animate(F32 delta, BOOL set_by_user)
2037{
2038 if (mNext)
2039 {
2040 mNext->animate(delta, set_by_user);
2041 }
2042}
2043
2044BOOL LLTexLayerParamAlpha::getSkip()
2045{
2046 LLVOAvatar *avatar = mTexLayer->getTexLayerSet()->getAvatar();
2047
2048 if( getInfo()->mSkipIfZeroWeight )
2049 {
2050 F32 effective_weight = ( avatar->getSex() & getSex() ) ? mCurWeight : getDefaultWeight();
2051 if (is_approx_zero( effective_weight ))
2052 {
2053 return TRUE;
2054 }
2055 }
2056
2057 EWearableType type = (EWearableType)getWearableType();
2058 if( (type != WT_INVALID) && !avatar->isWearingWearableType( type ) )
2059 {
2060 return TRUE;
2061 }
2062
2063 return FALSE;
2064}
2065
2066
2067BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height )
2068{
2069 BOOL success = TRUE;
2070
2071 F32 effective_weight = ( mTexLayer->getTexLayerSet()->getAvatar()->getSex() & getSex() ) ? mCurWeight : getDefaultWeight();
2072 BOOL weight_changed = effective_weight != mCachedEffectiveWeight;
2073 if( getSkip() )
2074 {
2075 return success;
2076 }
2077
2078 if( getInfo()->mMultiplyBlend )
2079 {
2080 glBlendFunc( GL_DST_ALPHA, GL_ZERO ); // Multiplication: approximates a min() function
2081 }
2082 else
2083 {
2084 glBlendFunc( GL_ONE, GL_ONE ); // Addition: approximates a max() function
2085 }
2086
2087 if( !getInfo()->mStaticImageFileName.empty() && !mStaticImageInvalid)
2088 {
2089 if( mStaticImageTGA.isNull() )
2090 {
2091 // Don't load the image file until we actually need it the first time. Like now.
2092 mStaticImageTGA = gTexStaticImageList.getImageTGA( getInfo()->mStaticImageFileName );
2093 // We now have something in one of our caches
2094 LLTexLayerSet::sHasCaches |= mStaticImageTGA.notNull() ? TRUE : FALSE;
2095
2096 if( mStaticImageTGA.isNull() )
2097 {
2098 llwarns << "Unable to load static file: " << getInfo()->mStaticImageFileName << llendl;
2099 mStaticImageInvalid = TRUE; // don't try again.
2100 return FALSE;
2101 }
2102 }
2103
2104 const S32 image_tga_width = mStaticImageTGA->getWidth();
2105 const S32 image_tga_height = mStaticImageTGA->getHeight();
2106 if( !mCachedProcessedImageGL ||
2107 (mCachedProcessedImageGL->getWidth() != image_tga_width) ||
2108 (mCachedProcessedImageGL->getHeight() != image_tga_height) ||
2109 (weight_changed && !(gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))) ||
2110 (!gUseAvatarGLCache) )
2111 {
2112// llinfos << "Building Cached Alpha: " << mName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << effective_weight << llendl;
2113 mCachedEffectiveWeight = effective_weight;
2114
2115 if( !mCachedProcessedImageGL )
2116 {
2117 mCachedProcessedImageGL = new LLImageGL( image_tga_width, image_tga_height, 1, FALSE);
2118
2119 // We now have something in one of our caches
2120 LLTexLayerSet::sHasCaches |= mCachedProcessedImageGL ? TRUE : FALSE;
2121
2122 if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))
2123 {
2124 // interpret luminance values as color index table
2125 mCachedProcessedImageGL->setExplicitFormat( GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX );
2126 }
2127 else
2128 {
2129 mCachedProcessedImageGL->setExplicitFormat( GL_ALPHA8, GL_ALPHA );
2130 }
2131 }
2132
2133 // Applies domain and effective weight to data as it is decoded. Also resizes the raw image if needed.
2134 if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))
2135 {
2136 mStaticImageRaw = NULL;
2137 mStaticImageRaw = new LLImageRaw;
2138 mStaticImageTGA->decode(mStaticImageRaw);
2139 mNeedsCreateTexture = TRUE;
2140 }
2141 else
2142 {
2143 mStaticImageRaw = NULL;
2144 mStaticImageRaw = new LLImageRaw;
2145 mStaticImageTGA->decodeAndProcess( mStaticImageRaw, getInfo()->mDomain, effective_weight );
2146 mNeedsCreateTexture = TRUE;
2147 }
2148 }
2149
2150 if( mCachedProcessedImageGL )
2151 {
2152 if( gUseAvatarGLCache ) // 64 MB
2153 {
2154 if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))
2155 {
2156 if( mNeedsCreateTexture )
2157 {
2158 mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw);
2159 mNeedsCreateTexture = FALSE;
2160
2161 mCachedProcessedImageGL->bind();
2162 mCachedProcessedImageGL->setClamp(TRUE, TRUE);
2163 }
2164
2165 LLGLSNoAlphaTest gls_no_alpha_test;
2166 mCachedProcessedImageGL->bind();
2167 gGradientPaletteList.setHardwarePalette( getInfo()->mDomain, effective_weight );
2168 gl_rect_2d_simple_tex( width, height );
2169 mCachedProcessedImageGL->unbindTexture(0, GL_TEXTURE_2D);
2170 }
2171 else
2172 {
2173 // Create the GL texture, and then hang onto it for future use.
2174 if( mNeedsCreateTexture )
2175 {
2176 mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw);
2177 mNeedsCreateTexture = FALSE;
2178
2179 mCachedProcessedImageGL->bind();
2180 mCachedProcessedImageGL->setClamp(TRUE, TRUE);
2181 }
2182
2183 LLGLSNoAlphaTest gls_no_alpha_test;
2184 mCachedProcessedImageGL->bind();
2185 gl_rect_2d_simple_tex( width, height );
2186 mCachedProcessedImageGL->unbindTexture(0, GL_TEXTURE_2D);
2187 }
2188 stop_glerror();
2189 }
2190 else
2191 {
2192 if( (mCachedProcessedImageGL->getWidth() != VOAVATAR_SCRATCH_TEX_WIDTH) ||
2193 (mCachedProcessedImageGL->getHeight() != VOAVATAR_SCRATCH_TEX_HEIGHT) )
2194 {
2195 if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))
2196 {
2197 mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw);
2198
2199 LLGLSNoAlphaTest gls_no_alpha_test;
2200
2201 mCachedProcessedImageGL->bind();
2202 mCachedProcessedImageGL->setClamp(TRUE, TRUE);
2203
2204 gGradientPaletteList.setHardwarePalette( getInfo()->mDomain, effective_weight );
2205 gl_rect_2d_simple_tex( width, height );
2206 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
2207 mCachedProcessedImageGL->destroyGLTexture();
2208 }
2209 else
2210 {
2211 // Create the GL texture, bind it and draw a rect, and then immediately destroy it.
2212 mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw);
2213
2214 LLGLSNoAlphaTest gls_no_alpha_test;
2215
2216 mCachedProcessedImageGL->bind();
2217 mCachedProcessedImageGL->setClamp(TRUE, TRUE);
2218
2219 gl_rect_2d_simple_tex( width, height );
2220
2221 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
2222
2223 mCachedProcessedImageGL->destroyGLTexture();
2224 }
2225 stop_glerror();
2226 }
2227 else
2228 {
2229 if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))
2230 {
2231 // Write into a pre-existing GL Image, and then bind and render that.
2232 // Faster than creating a new GL Image and then destroying it.
2233 if( mTexLayer->getTexLayerSet()->getAvatar()->bindScratchTexture( GL_COLOR_INDEX ) )
2234 {
2235 glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0,
2236 mCachedProcessedImageGL->getWidth(),
2237 mCachedProcessedImageGL->getHeight(),
2238 GL_COLOR_INDEX, GL_UNSIGNED_BYTE,
2239 mStaticImageRaw->getData() );
2240 stop_glerror();
2241
2242 LLGLSNoAlphaTest gls_no_alpha_test;
2243 gGradientPaletteList.setHardwarePalette( getInfo()->mDomain, effective_weight );
2244 gl_rect_2d_simple_tex( width, height );
2245
2246 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
2247 }
2248 else
2249 {
2250 success = FALSE;
2251 }
2252 }
2253 else
2254 {
2255 // Write into a pre-existing GL Image, and then bind and render that.
2256 // Faster than creating a new GL Image and then destroying it.
2257 if( mTexLayer->getTexLayerSet()->getAvatar()->bindScratchTexture( GL_ALPHA ) )
2258 {
2259 glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0,
2260 mCachedProcessedImageGL->getWidth(),
2261 mCachedProcessedImageGL->getHeight(),
2262 GL_ALPHA, GL_UNSIGNED_BYTE,
2263 mStaticImageRaw->getData() );
2264 stop_glerror();
2265
2266 LLGLSNoAlphaTest gls_no_alpha_test;
2267 gl_rect_2d_simple_tex( width, height );
2268
2269 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
2270 }
2271 else
2272 {
2273 success = FALSE;
2274 }
2275 }
2276 }
2277 }
2278 }
2279
2280 // Don't keep the cache for other people's avatars
2281 // (It's not really a "cache" in that case, but the logic is the same)
2282 if( !mTexLayer->getTexLayerSet()->getAvatar()->mIsSelf )
2283 {
2284 mCachedProcessedImageGL = NULL;
2285 }
2286 }
2287 else
2288 {
2289 LLGLSNoTextureNoAlphaTest gls_no_texture_no_alpha_test;
2290 glColor4f( 0.f, 0.f, 0.f, effective_weight );
2291 gl_rect_2d_simple( width, height );
2292 }
2293
2294 return success;
2295}
2296
2297//-----------------------------------------------------------------------------
2298// LLTexGlobalColorInfo
2299//-----------------------------------------------------------------------------
2300
2301LLTexGlobalColorInfo::LLTexGlobalColorInfo()
2302{
2303}
2304
2305
2306LLTexGlobalColorInfo::~LLTexGlobalColorInfo()
2307{
2308 for_each(mColorInfoList.begin(), mColorInfoList.end(), DeletePointer());
2309}
2310
2311BOOL LLTexGlobalColorInfo::parseXml(LLXmlTreeNode* node)
2312{
2313 // name attribute
2314 static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
2315 if( !node->getFastAttributeString( name_string, mName ) )
2316 {
2317 llwarns << "<global_color> element is missing name attribute." << llendl;
2318 return FALSE;
2319 }
2320 // <param> sub-element
2321 for (LLXmlTreeNode* child = node->getChildByName( "param" );
2322 child;
2323 child = node->getNextNamedChild())
2324 {
2325 if( child->getChildByName( "param_color" ) )
2326 {
2327 // <param><param_color/></param>
2328 LLTexParamColorInfo* info = new LLTexParamColorInfo();
2329 if (!info->parseXml(child))
2330 {
2331 delete info;
2332 return FALSE;
2333 }
2334 mColorInfoList.push_back( info );
2335 }
2336 }
2337 return TRUE;
2338}
2339
2340//-----------------------------------------------------------------------------
2341// LLTexGlobalColor
2342//-----------------------------------------------------------------------------
2343
2344LLTexGlobalColor::LLTexGlobalColor( LLVOAvatar* avatar )
2345 :
2346 mAvatar( avatar ),
2347 mInfo( NULL )
2348{
2349}
2350
2351
2352LLTexGlobalColor::~LLTexGlobalColor()
2353{
2354 // mParamList are LLViewerVisualParam's and get deleted with ~LLCharacter()
2355 //std::for_each(mParamList.begin(), mParamList.end(), DeletePointer());
2356}
2357
2358BOOL LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info)
2359{
2360 llassert(mInfo == NULL);
2361 mInfo = info;
2362 //mID = info->mID; // No ID
2363
2364 LLTexGlobalColorInfo::color_info_list_t::iterator iter;
2365 mParamList.reserve(mInfo->mColorInfoList.size());
2366 for (iter = mInfo->mColorInfoList.begin(); iter != mInfo->mColorInfoList.end(); iter++)
2367 {
2368 LLTexParamColor* param_color = new LLTexParamColor( this );
2369 if (!param_color->setInfo(*iter))
2370 {
2371 mInfo = NULL;
2372 return FALSE;
2373 }
2374 mParamList.push_back( param_color );
2375 }
2376
2377 return TRUE;
2378}
2379
2380//-----------------------------------------------------------------------------
2381
2382LLColor4 LLTexGlobalColor::getColor()
2383{
2384 // Sum of color params
2385 if( !mParamList.empty() )
2386 {
2387 LLColor4 net_color( 0.f, 0.f, 0.f, 0.f );
2388
2389 for( param_list_t::iterator iter = mParamList.begin();
2390 iter != mParamList.end(); iter++ )
2391 {
2392 LLTexParamColor* param = *iter;
2393 LLColor4 param_net = param->getNetColor();
2394 switch( param->getOperation() )
2395 {
2396 case OP_ADD:
2397 net_color += param_net;
2398 break;
2399 case OP_MULTIPLY:
2400 net_color.mV[VX] *= param_net.mV[VX];
2401 net_color.mV[VY] *= param_net.mV[VY];
2402 net_color.mV[VZ] *= param_net.mV[VZ];
2403 net_color.mV[VW] *= param_net.mV[VW];
2404 break;
2405 case OP_BLEND:
2406 net_color = lerp(net_color, param_net, param->getWeight());
2407 break;
2408 default:
2409 llassert(0);
2410 break;
2411 }
2412 }
2413
2414 net_color.mV[VX] = llclampf( net_color.mV[VX] );
2415 net_color.mV[VY] = llclampf( net_color.mV[VY] );
2416 net_color.mV[VZ] = llclampf( net_color.mV[VZ] );
2417 net_color.mV[VW] = llclampf( net_color.mV[VW] );
2418
2419 return net_color;
2420 }
2421 return LLColor4( 1.f, 1.f, 1.f, 1.f );
2422}
2423
2424//-----------------------------------------------------------------------------
2425// LLTexParamColorInfo
2426//-----------------------------------------------------------------------------
2427LLTexParamColorInfo::LLTexParamColorInfo()
2428 :
2429 mOperation( OP_ADD ),
2430 mNumColors( 0 )
2431{
2432}
2433
2434BOOL LLTexParamColorInfo::parseXml(LLXmlTreeNode *node)
2435{
2436 llassert( node->hasName( "param" ) && node->getChildByName( "param_color" ) );
2437
2438 if (!LLViewerVisualParamInfo::parseXml(node))
2439 return FALSE;
2440
2441 LLXmlTreeNode* param_color_node = node->getChildByName( "param_color" );
2442 if( !param_color_node )
2443 {
2444 return FALSE;
2445 }
2446
2447 LLString op_string;
2448 static LLStdStringHandle operation_string = LLXmlTree::addAttributeString("operation");
2449 if( param_color_node->getFastAttributeString( operation_string, op_string ) )
2450 {
2451 LLString::toLower(op_string);
2452 if ( op_string == "add" ) mOperation = OP_ADD;
2453 else if ( op_string == "multiply" ) mOperation = OP_MULTIPLY;
2454 else if ( op_string == "blend" ) mOperation = OP_BLEND;
2455 }
2456
2457 mNumColors = 0;
2458
2459 LLColor4U color4u;
2460 for (LLXmlTreeNode* child = param_color_node->getChildByName( "value" );
2461 child;
2462 child = param_color_node->getNextNamedChild())
2463 {
2464 if( (mNumColors < MAX_COLOR_VALUES) )
2465 {
2466 static LLStdStringHandle color_string = LLXmlTree::addAttributeString("color");
2467 if( child->getFastAttributeColor4U( color_string, color4u ) )
2468 {
2469 mColors[ mNumColors ].setVec(color4u);
2470 mNumColors++;
2471 }
2472 }
2473 }
2474 if( !mNumColors )
2475 {
2476 llwarns << "<param_color> is missing <value> sub-elements" << llendl;
2477 return FALSE;
2478 }
2479
2480 if( (mOperation == OP_BLEND) && (mNumColors != 1) )
2481 {
2482 llwarns << "<param_color> with operation\"blend\" must have exactly one <value>" << llendl;
2483 return FALSE;
2484 }
2485
2486 return TRUE;
2487}
2488
2489//-----------------------------------------------------------------------------
2490// LLTexParamColor
2491//-----------------------------------------------------------------------------
2492LLTexParamColor::LLTexParamColor( LLTexGlobalColor* tex_global_color )
2493 :
2494 mAvgDistortionVec(1.f, 1.f, 1.f),
2495 mTexGlobalColor( tex_global_color ),
2496 mTexLayer( NULL ),
2497 mAvatar( tex_global_color->getAvatar() )
2498{
2499}
2500
2501LLTexParamColor::LLTexParamColor( LLTexLayer* layer )
2502 :
2503 mAvgDistortionVec(1.f, 1.f, 1.f),
2504 mTexGlobalColor( NULL ),
2505 mTexLayer( layer ),
2506 mAvatar( layer->getTexLayerSet()->getAvatar() )
2507{
2508}
2509
2510
2511LLTexParamColor::~LLTexParamColor()
2512{
2513}
2514
2515//-----------------------------------------------------------------------------
2516// setInfo()
2517//-----------------------------------------------------------------------------
2518
2519BOOL LLTexParamColor::setInfo(LLTexParamColorInfo *info)
2520{
2521 llassert(mInfo == NULL);
2522 if (info->mID < 0)
2523 return FALSE;
2524 mID = info->mID;
2525 mInfo = info;
2526
2527 mAvatar->addVisualParam( this );
2528 setWeight( getDefaultWeight(), FALSE );
2529
2530 return TRUE;
2531}
2532
2533LLColor4 LLTexParamColor::getNetColor()
2534{
2535 llassert( getInfo()->mNumColors >= 1 );
2536
2537 F32 effective_weight = ( mAvatar && (mAvatar->getSex() & getSex()) ) ? mCurWeight : getDefaultWeight();
2538
2539 S32 index_last = getInfo()->mNumColors - 1;
2540 F32 scaled_weight = effective_weight * index_last;
2541 S32 index_start = (S32) scaled_weight;
2542 S32 index_end = index_start + 1;
2543 if( index_start == index_last )
2544 {
2545 return getInfo()->mColors[index_last];
2546 }
2547 else
2548 {
2549 F32 weight = scaled_weight - index_start;
2550 const LLColor4 *start = &getInfo()->mColors[ index_start ];
2551 const LLColor4 *end = &getInfo()->mColors[ index_end ];
2552 return LLColor4(
2553 (1.f - weight) * start->mV[VX] + weight * end->mV[VX],
2554 (1.f - weight) * start->mV[VY] + weight * end->mV[VY],
2555 (1.f - weight) * start->mV[VZ] + weight * end->mV[VZ],
2556 (1.f - weight) * start->mV[VW] + weight * end->mV[VW] );
2557 }
2558}
2559
2560void LLTexParamColor::setWeight(F32 weight, BOOL set_by_user)
2561{
2562 if (mIsAnimating)
2563 {
2564 return;
2565 }
2566 F32 min_weight = getMinWeight();
2567 F32 max_weight = getMaxWeight();
2568 F32 new_weight = llclamp(weight, min_weight, max_weight);
2569 U8 cur_u8 = F32_to_U8( mCurWeight, min_weight, max_weight );
2570 U8 new_u8 = F32_to_U8( new_weight, min_weight, max_weight );
2571 if( cur_u8 != new_u8)
2572 {
2573 mCurWeight = new_weight;
2574
2575 if( getInfo()->mNumColors <= 0 )
2576 {
2577 // This will happen when we set the default weight the first time.
2578 return;
2579 }
2580
2581 if( mAvatar->getSex() & getSex() )
2582 {
2583 if( mTexGlobalColor )
2584 {
2585 mAvatar->onGlobalColorChanged( mTexGlobalColor, set_by_user );
2586 }
2587 else
2588 if( mTexLayer )
2589 {
2590 mAvatar->invalidateComposite( mTexLayer->getTexLayerSet(), set_by_user );
2591 }
2592 }
2593// llinfos << "param " << mName << " = " << new_weight << llendl;
2594 }
2595}
2596
2597void LLTexParamColor::setAnimationTarget(F32 target_value, BOOL set_by_user)
2598{
2599 // set value first then set interpolating flag to ignore further updates
2600 mTargetWeight = target_value;
2601 setWeight(target_value, set_by_user);
2602 mIsAnimating = TRUE;
2603 if (mNext)
2604 {
2605 mNext->setAnimationTarget(target_value, set_by_user);
2606 }
2607}
2608
2609void LLTexParamColor::animate(F32 delta, BOOL set_by_user)
2610{
2611 if (mNext)
2612 {
2613 mNext->animate(delta, set_by_user);
2614 }
2615}
2616
2617
2618//-----------------------------------------------------------------------------
2619// LLTexStaticImageList
2620//-----------------------------------------------------------------------------
2621
2622// static
2623LLTexStaticImageList gTexStaticImageList;
2624LLStringTable LLTexStaticImageList::sImageNames(16384);
2625
2626LLTexStaticImageList::LLTexStaticImageList()
2627 :
2628 mRawBytes( 0 ),
2629 mGLBytes( 0 ),
2630 mTGABytes( 0 )
2631{}
2632
2633LLTexStaticImageList::~LLTexStaticImageList()
2634{
2635 deleteCachedImages();
2636}
2637
2638void LLTexStaticImageList::dumpByteCount()
2639{
2640 llinfos << "Avatar Static Textures " <<
2641 " Raw:" << (mRawBytes / 1024) <<
2642 "KB GL:" << (mGLBytes / 1024) <<
2643 "KB TGA:" << (mTGABytes / 1024) << "KB" << llendl;
2644}
2645
2646void LLTexStaticImageList::deleteCachedImages()
2647{
2648 if( mRawBytes || mGLBytes || mTGABytes )
2649 {
2650 llinfos << "Clearing Static Textures " <<
2651 " Raw:" << (mRawBytes / 1024) <<
2652 "KB GL:" << (mGLBytes / 1024) <<
2653 "KB TGA:" << (mTGABytes / 1024) << "KB" << llendl;
2654
2655 //mStaticImageLists uses LLPointers, clear() will cause deletion
2656
2657 mStaticImageListRaw.clear();
2658 mStaticImageListTGA.clear();
2659 mStaticImageListGL.clear();
2660
2661 mRawBytes = 0;
2662 mGLBytes = 0;
2663 mTGABytes = 0;
2664 }
2665}
2666
2667// Note: in general, for a given image image we'll call either getImageTga(), getImageRaw() or getImageGL().
2668// We call getImageTga() if the image is used as an alpha gradient.
2669// Otherwise, we call getImageRaw() if we have 32 MB or less of video RAM or less and getImageGL() if we have
2670// more video RAM than that.
2671
2672// Returns an LLImageTGA that contains the encoded data from a tga file named file_name.
2673// Caches the result to speed identical subsequent requests.
2674LLImageTGA* LLTexStaticImageList::getImageTGA(const LLString& file_name)
2675{
2676 const char *namekey = sImageNames.addString(file_name);
2677 image_tga_map_t::iterator iter = mStaticImageListTGA.find(namekey);
2678 if( iter != mStaticImageListTGA.end() )
2679 {
2680 return iter->second;
2681 }
2682 else
2683 {
2684 std::string path;
2685 path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name.c_str());
2686 LLPointer<LLImageTGA> image_tga = new LLImageTGA( path );
2687 if( image_tga->getDataSize() > 0 )
2688 {
2689 mStaticImageListTGA[ namekey ] = image_tga;
2690 mTGABytes += image_tga->getDataSize();
2691 return image_tga;
2692 }
2693 else
2694 {
2695 return NULL;
2696 }
2697 }
2698}
2699
2700
2701
2702// Returns an LLImageRaw that contains the decoded data from a tga file named file_name.
2703// Caches the result to speed identical subsequent requests.
2704LLImageRaw* LLTexStaticImageList::getImageRaw(const LLString& file_name)
2705{
2706 LLPointer<LLImageRaw> image_raw;
2707 const char *namekey = sImageNames.addString(file_name);
2708 image_raw_map_t::iterator iter = mStaticImageListRaw.find(namekey);
2709 if( iter != mStaticImageListRaw.end() )
2710 {
2711 image_raw = iter->second;
2712 }
2713 else
2714 {
2715 image_raw = new LLImageRaw();
2716 if( loadImageRaw( file_name, image_raw ) )
2717 {
2718 mStaticImageListRaw[ namekey ] = image_raw;
2719 mRawBytes += image_raw->getDataSize();
2720 }
2721 else
2722 {
2723 image_raw = NULL;
2724 }
2725 }
2726
2727 return image_raw;
2728}
2729
2730// Returns a GL Image (without a backing ImageRaw) that contains the decoded data from a tga file named file_name.
2731// Caches the result to speed identical subsequent requests.
2732LLImageGL* LLTexStaticImageList::getImageGL(const LLString& file_name, BOOL is_mask )
2733{
2734 LLPointer<LLImageGL> image_gl;
2735 const char *namekey = sImageNames.addString(file_name);
2736
2737 image_gl_map_t::iterator iter = mStaticImageListGL.find(namekey);
2738 if( iter != mStaticImageListGL.end() )
2739 {
2740 image_gl = iter->second;
2741 }
2742 else
2743 {
2744 image_gl = new LLImageGL( FALSE );
2745 LLPointer<LLImageRaw> image_raw = new LLImageRaw;
2746 if( loadImageRaw( file_name, image_raw ) )
2747 {
2748 if( (image_raw->getComponents() == 1) && is_mask )
2749 {
2750 // Note: these are static, unchanging images so it's ok to assume
2751 // that once an image is a mask it's always a mask.
2752 image_gl->setExplicitFormat( GL_ALPHA8, GL_ALPHA );
2753 }
2754 image_gl->createGLTexture(0, image_raw);
2755
2756 image_gl->bind();
2757 image_gl->setClamp(TRUE, TRUE);
2758
2759 mStaticImageListGL [ namekey ] = image_gl;
2760 mGLBytes += (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents();
2761 }
2762 else
2763 {
2764 image_gl = NULL;
2765 }
2766 }
2767
2768 return image_gl;
2769}
2770
2771// Reads a .tga file, decodes it, and puts the decoded data in image_raw.
2772// Returns TRUE if successful.
2773BOOL LLTexStaticImageList::loadImageRaw( const LLString& file_name, LLImageRaw* image_raw )
2774{
2775 BOOL success = FALSE;
2776 std::string path;
2777 path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name.c_str());
2778 LLPointer<LLImageTGA> image_tga = new LLImageTGA( path );
2779 if( image_tga->getDataSize() > 0 )
2780 {
2781 // Copy data from tga to raw.
2782 success = image_tga->decode( image_raw );
2783 }
2784
2785 return success;
2786}
2787
2788//-----------------------------------------------------------------------------
2789// LLMaskedMorph()
2790//-----------------------------------------------------------------------------
2791LLMaskedMorph::LLMaskedMorph( LLPolyMorphTarget *morph_target, BOOL invert ) : mMorphTarget(morph_target), mInvert(invert)
2792{
2793 morph_target->addPendingMorphMask();
2794}
2795
2796
2797//-----------------------------------------------------------------------------
2798// LLGradientPaletteList
2799//-----------------------------------------------------------------------------
2800
2801LLGradientPaletteList::~LLGradientPaletteList()
2802{
2803 // Note: can't just call deleteAllData() because the data values are arrays.
2804 for( palette_map_t::iterator iter = mPaletteMap.begin();
2805 iter != mPaletteMap.end(); iter++ )
2806 {
2807 U8* data = iter->second;
2808 delete []data;
2809 }
2810}
2811
2812void LLGradientPaletteList::initPalette(F32 domain)
2813{
2814 palette_map_t::iterator iter = mPaletteMap.find( domain );
2815 if( iter == mPaletteMap.end() )
2816 {
2817 U8 *palette = new U8[512 * 4];
2818 mPaletteMap[domain] = palette;
2819 S32 ramp_start = 255 - llfloor(domain * 255.f);
2820 S32 ramp_end = 255;
2821 F32 ramp_factor = (ramp_end == ramp_start) ? 0.f : (255.f / ((F32)ramp_end - (F32)ramp_start));
2822
2823 // *TODO: move conditionals outside of loop, since this really
2824 // is just a sequential process.
2825 for (S32 i = 0; i < 512; i++)
2826 {
2827 palette[(i * 4) + 1] = 0;
2828 palette[(i * 4) + 2] = 0;
2829 if (i <= ramp_start)
2830 {
2831 palette[(i * 4)] = 0;
2832 palette[(i * 4) + 3] = 0;
2833 }
2834 else if (i < ramp_end)
2835 {
2836 palette[(i * 4)] = llfloor(((F32)i - (F32)ramp_start) * ramp_factor);
2837 palette[(i * 4) + 3] = llfloor(((F32)i - (F32)ramp_start) * ramp_factor);
2838 }
2839 else
2840 {
2841 palette[(i * 4)] = 255;
2842 palette[(i * 4) + 3] = 255;
2843 }
2844 }
2845 }
2846}
2847
2848void LLGradientPaletteList::setHardwarePalette( F32 domain, F32 effective_weight )
2849{
2850 palette_map_t::iterator iter = mPaletteMap.find( domain );
2851 if( iter != mPaletteMap.end() )
2852 {
2853 U8* palette = iter->second;
2854 set_palette( palette + llfloor(effective_weight * (255.f * (1.f - domain))) * 4);
2855 }
2856 else
2857 {
2858 llwarns << "LLGradientPaletteList::setHardwarePalette() missing domain " << domain << llendl;
2859 }
2860}