00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "imageids.h"
00035 #include "llagent.h"
00036 #include "llcrc.h"
00037 #include "lldir.h"
00038 #include "llglheaders.h"
00039 #include "llimagebmp.h"
00040 #include "llimagej2c.h"
00041 #include "llimagetga.h"
00042 #include "llpolymorph.h"
00043 #include "llquantize.h"
00044 #include "lltexlayer.h"
00045 #include "llui.h"
00046 #include "llvfile.h"
00047 #include "llviewerimagelist.h"
00048 #include "llviewerimagelist.h"
00049 #include "llviewerstats.h"
00050 #include "llviewerwindow.h"
00051 #include "llvoavatar.h"
00052 #include "llxmltree.h"
00053 #include "pipeline.h"
00054 #include "v4coloru.h"
00055 #include "viewer.h"
00056
00057
00058
00059
00060
00061
00062
00063 LLGradientPaletteList gGradientPaletteList;
00064
00065
00066 S32 LLTexLayerSetBuffer::sGLByteCount = 0;
00067 S32 LLTexLayerSetBuffer::sGLBumpByteCount = 0;
00068
00069
00070
00071
00072 LLBakedUploadData::LLBakedUploadData( LLVOAvatar* avatar, LLTexLayerSetBuffer* layerset_buffer ) :
00073 mAvatar( avatar ),
00074 mLayerSetBuffer( layerset_buffer )
00075 {
00076 mID.generate();
00077 for( S32 i = 0; i < WT_COUNT; i++ )
00078 {
00079 LLWearable* wearable = gAgent.getWearable( (EWearableType)i);
00080 if( wearable )
00081 {
00082 mWearableAssets[i] = wearable->getID();
00083 }
00084 }
00085 }
00086
00087
00088
00089
00090
00091 LLTexLayerSetBuffer::LLTexLayerSetBuffer( LLTexLayerSet* owner, S32 width, S32 height, BOOL has_bump )
00092 :
00093
00094 LLDynamicTexture( width, height, 4, LLDynamicTexture::ORDER_LAST, TRUE ),
00095 mNeedsUpdate( TRUE ),
00096 mNeedsUpload( FALSE ),
00097 mUploadPending( FALSE ),
00098 mTexLayerSet( owner ),
00099 mInitialized( FALSE ),
00100 mBumpTexName(0)
00101 {
00102 LLTexLayerSetBuffer::sGLByteCount += getSize();
00103
00104 if( has_bump )
00105 {
00106 LLGLSUIDefault gls_ui;
00107 glGenTextures(1, (GLuint*) &mBumpTexName);
00108
00109 LLImageGL::bindExternalTexture(mBumpTexName, 0, GL_TEXTURE_2D);
00110 stop_glerror();
00111
00112 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00113 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00114
00115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00117
00118 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
00119 stop_glerror();
00120
00121 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
00122
00123 LLImageGL::sGlobalTextureMemory += mWidth * mHeight * 4;
00124 LLTexLayerSetBuffer::sGLBumpByteCount += mWidth * mHeight * 4;
00125 }
00126 }
00127
00128 LLTexLayerSetBuffer::~LLTexLayerSetBuffer()
00129 {
00130 LLTexLayerSetBuffer::sGLByteCount -= getSize();
00131
00132 if( mBumpTexName )
00133 {
00134 glDeleteTextures(1, (GLuint*) &mBumpTexName);
00135 stop_glerror();
00136 mBumpTexName = 0;
00137
00138 LLImageGL::sGlobalTextureMemory -= mWidth * mHeight * 4;
00139 LLTexLayerSetBuffer::sGLBumpByteCount -= mWidth * mHeight * 4;
00140 }
00141 }
00142
00143
00144 void LLTexLayerSetBuffer::dumpTotalByteCount()
00145 {
00146 llinfos << "Composite System GL Buffers: " << (LLTexLayerSetBuffer::sGLByteCount/1024) << "KB" << llendl;
00147 llinfos << "Composite System GL Bump Buffers: " << (LLTexLayerSetBuffer::sGLBumpByteCount/1024) << "KB" << llendl;
00148 }
00149
00150 void LLTexLayerSetBuffer::requestUpdate()
00151 {
00152 mNeedsUpdate = TRUE;
00153
00154
00155
00156 mUploadID.setNull();
00157 }
00158
00159 void LLTexLayerSetBuffer::requestUpload()
00160 {
00161 if (!mNeedsUpload)
00162 {
00163 mNeedsUpload = TRUE;
00164 mUploadPending = TRUE;
00165 }
00166 }
00167
00168 void LLTexLayerSetBuffer::cancelUpload()
00169 {
00170 if (mNeedsUpload)
00171 {
00172 mNeedsUpload = FALSE;
00173 }
00174 mUploadPending = FALSE;
00175 }
00176
00177 void LLTexLayerSetBuffer::pushProjection()
00178 {
00179 glMatrixMode(GL_PROJECTION);
00180 glPushMatrix();
00181 glLoadIdentity();
00182 glOrtho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f);
00183
00184 glMatrixMode(GL_MODELVIEW);
00185 glPushMatrix();
00186 glLoadIdentity();
00187 }
00188
00189 void LLTexLayerSetBuffer::popProjection()
00190 {
00191 glMatrixMode(GL_PROJECTION);
00192 glPopMatrix();
00193
00194 glMatrixMode(GL_MODELVIEW);
00195 glPopMatrix();
00196 }
00197
00198 BOOL LLTexLayerSetBuffer::needsRender()
00199 {
00200 LLVOAvatar* avatar = mTexLayerSet->getAvatar();
00201 BOOL upload_now = mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal();
00202 BOOL needs_update = gAgent.mNumPendingQueries == 0 && (mNeedsUpdate || upload_now) && !avatar->mAppearanceAnimating;
00203 if (needs_update)
00204 {
00205 BOOL invalid_skirt = avatar->getBakedTE(mTexLayerSet) == LLVOAvatar::TEX_SKIRT_BAKED && !avatar->isWearingWearableType(WT_SKIRT);
00206 if (invalid_skirt)
00207 {
00208
00209
00210 needs_update = FALSE;
00211 cancelUpload();
00212 }
00213 else
00214 {
00215 needs_update &= (avatar->isSelf() || (avatar->isVisible() && !avatar->isCulled()));
00216 needs_update &= mTexLayerSet->isLocalTextureDataAvailable();
00217 }
00218 }
00219 return needs_update;
00220 }
00221
00222 void LLTexLayerSetBuffer::preRender(BOOL clear_depth)
00223 {
00224
00225 pushProjection();
00226
00227
00228 LLDynamicTexture::preRender(FALSE);
00229 }
00230
00231 void LLTexLayerSetBuffer::postRender(BOOL success)
00232 {
00233 popProjection();
00234
00235 LLDynamicTexture::postRender(success);
00236 }
00237
00238 BOOL LLTexLayerSetBuffer::render()
00239 {
00240 U8* baked_bump_data = NULL;
00241
00242
00243
00244 BOOL upload_now = (gAgent.mNumPendingQueries == 0 && mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal());
00245 BOOL success = TRUE;
00246
00247
00248 if( mBumpTexName )
00249 {
00250
00251 success &= mTexLayerSet->renderBump( mOrigin.mX, mOrigin.mY, mWidth, mHeight );
00252 stop_glerror();
00253
00254 if (success)
00255 {
00256 LLGLSUIDefault gls_ui;
00257
00258
00259 LLImageGL::bindExternalTexture( mBumpTexName, 0, GL_TEXTURE_2D );
00260 stop_glerror();
00261
00262 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mOrigin.mX, mOrigin.mY, mWidth, mHeight);
00263 stop_glerror();
00264
00265
00266 if( upload_now )
00267 {
00268 baked_bump_data = new U8[ mWidth * mHeight * 4 ];
00269 glReadPixels(mOrigin.mX, mOrigin.mY, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_bump_data );
00270 stop_glerror();
00271 }
00272 }
00273 }
00274
00275
00276 LLGLSUIDefault gls_ui;
00277 success &= mTexLayerSet->render( mOrigin.mX, mOrigin.mY, mWidth, mHeight );
00278
00279 if( upload_now )
00280 {
00281 if (!success)
00282 {
00283 delete [] baked_bump_data;
00284 llinfos << "Failed attempt to bake " << mTexLayerSet->getBodyRegion() << llendl;
00285 mUploadPending = FALSE;
00286 }
00287 else
00288 {
00289 readBackAndUpload(baked_bump_data);
00290 }
00291 }
00292
00293
00294
00295
00296 GLboolean mask[4];
00297 glGetBooleanv(GL_COLOR_WRITEMASK,mask);
00298 glColorMask(mask[0], mask[1], mask[2], GL_TRUE);
00299
00300
00301 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00302
00303
00304 mInitialized = TRUE;
00305 mNeedsUpdate = FALSE;
00306
00307 return success;
00308 }
00309
00310 BOOL LLTexLayerSetBuffer::updateImmediate()
00311 {
00312 mNeedsUpdate = TRUE;
00313 BOOL result = FALSE;
00314
00315 if (needsRender())
00316 {
00317 preRender(FALSE);
00318 result = render();
00319 postRender(result);
00320 }
00321
00322 return result;
00323 }
00324
00325 void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data)
00326 {
00327
00328 U8* baked_color_data = new U8[ mWidth * mHeight * 4 ];
00329
00330 glReadPixels(mOrigin.mX, mOrigin.mY, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_color_data );
00331 stop_glerror();
00332
00333 llinfos << "Baked " << mTexLayerSet->getBodyRegion() << llendl;
00334 gViewerStats->incStat(LLViewerStats::ST_TEX_BAKES);
00335
00336 llassert( gAgent.getAvatarObject() == mTexLayerSet->getAvatar() );
00337
00338
00339
00340
00341 mTexLayerSet->deleteCaches();
00342
00343 LLGLSUIDefault gls_ui;
00344
00345 LLPointer<LLImageRaw> baked_mask_image = new LLImageRaw(mWidth, mHeight, 1 );
00346 U8* baked_mask_data = baked_mask_image->getData();
00347
00348 mTexLayerSet->gatherAlphaMasks(baked_mask_data, mWidth, mHeight);
00349
00350
00351
00352
00353 const char* comment_text = NULL;
00354
00355 S32 baked_image_components = mBumpTexName ? 5 : 4;
00356 LLPointer<LLImageRaw> baked_image = new LLImageRaw( mWidth, mHeight, baked_image_components );
00357 U8* baked_image_data = baked_image->getData();
00358
00359 if( mBumpTexName )
00360 {
00361 comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM";
00362
00363
00364 if (mTexLayerSet->getBodyRegion() == "head")
00365 {
00366 S32 i = 0;
00367 for( S32 u = 0; u < mWidth; u++ )
00368 {
00369 for( S32 v = 0; v < mHeight; v++ )
00370 {
00371 baked_image_data[5*i + 0] = baked_color_data[4*i + 0];
00372 baked_image_data[5*i + 1] = baked_color_data[4*i + 1];
00373 baked_image_data[5*i + 2] = baked_color_data[4*i + 2];
00374 baked_image_data[5*i + 3] = baked_color_data[4*i + 3] < 255 ? baked_color_data[4*i + 3] : baked_bump_data[4*i];
00375 baked_image_data[5*i + 4] = baked_mask_data[i];
00376 i++;
00377 }
00378 }
00379 }
00380 else
00381 {
00382 S32 i = 0;
00383 for( S32 u = 0; u < mWidth; u++ )
00384 {
00385 for( S32 v = 0; v < mHeight; v++ )
00386 {
00387 baked_image_data[5*i + 0] = baked_color_data[4*i + 0];
00388 baked_image_data[5*i + 1] = baked_color_data[4*i + 1];
00389 baked_image_data[5*i + 2] = baked_color_data[4*i + 2];
00390 baked_image_data[5*i + 3] = baked_bump_data[4*i];
00391 baked_image_data[5*i + 4] = baked_mask_data[i];
00392 i++;
00393 }
00394 }
00395 }
00396 }
00397 else
00398 {
00399 if (mTexLayerSet->getBodyRegion() == "skirt")
00400 {
00401 S32 i = 0;
00402 for( S32 u = 0; u < mWidth; u++ )
00403 {
00404 for( S32 v = 0; v < mHeight; v++ )
00405 {
00406 baked_image_data[4*i + 0] = baked_color_data[4*i + 0];
00407 baked_image_data[4*i + 1] = baked_color_data[4*i + 1];
00408 baked_image_data[4*i + 2] = baked_color_data[4*i + 2];
00409 baked_image_data[4*i + 3] = baked_color_data[4*i + 3];
00410 i++;
00411 }
00412 }
00413 }
00414 else
00415 {
00416 S32 i = 0;
00417 for( S32 u = 0; u < mWidth; u++ )
00418 {
00419 for( S32 v = 0; v < mHeight; v++ )
00420 {
00421 baked_image_data[4*i + 0] = baked_color_data[4*i + 0];
00422 baked_image_data[4*i + 1] = baked_color_data[4*i + 1];
00423 baked_image_data[4*i + 2] = baked_color_data[4*i + 2];
00424 baked_image_data[4*i + 3] = baked_mask_data[i];
00425 i++;
00426 }
00427 }
00428 }
00429 }
00430
00431 LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C;
00432 compressedImage->setRate(0.f);
00433 LLTransactionID tid;
00434 LLAssetID asset_id;
00435 tid.generate();
00436 asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
00437
00438 BOOL res = false;
00439 if( compressedImage->encode(baked_image, comment_text))
00440 {
00441 res = LLVFile::writeFile(compressedImage->getData(), compressedImage->getDataSize(),
00442 gVFS, asset_id, LLAssetType::AT_TEXTURE);
00443 if (res)
00444 {
00445 LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C;
00446 BOOL valid = FALSE;
00447 S32 file_size;
00448 U8* data = LLVFile::readFile(gVFS, asset_id, LLAssetType::AT_TEXTURE, &file_size);
00449 if (data)
00450 {
00451 valid = integrity_test->validate(data, file_size);
00452 }
00453 else
00454 {
00455 integrity_test->setLastError("Unable to read entire file");
00456 }
00457
00458 if( valid )
00459 {
00460 LLBakedUploadData* baked_upload_data = new LLBakedUploadData( gAgent.getAvatarObject(), this );
00461 mUploadID = baked_upload_data->mID;
00462
00463 gAssetStorage->storeAssetData(tid,
00464 LLAssetType::AT_TEXTURE,
00465 LLTexLayerSetBuffer::onTextureUploadComplete,
00466 baked_upload_data,
00467 TRUE,
00468 FALSE,
00469 TRUE);
00470
00471 mNeedsUpload = FALSE;
00472 }
00473 else
00474 {
00475 mUploadPending = FALSE;
00476 llinfos << "unable to create baked upload file: corrupted" << llendl;
00477 LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE, LLVFile::WRITE);
00478 file.remove();
00479 }
00480 }
00481 }
00482 if (!res)
00483 {
00484 mUploadPending = FALSE;
00485 llinfos << "unable to create baked upload file" << llendl;
00486 }
00487
00488 delete [] baked_color_data;
00489 delete [] baked_bump_data;
00490 }
00491
00492
00493
00494 void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, void* userdata, S32 result, LLExtStat ext_status)
00495 {
00496 LLBakedUploadData* baked_upload_data = (LLBakedUploadData*)userdata;
00497
00498 LLVOAvatar* avatar = gAgent.getAvatarObject();
00499
00500 if (0 == result && avatar && !avatar->isDead())
00501 {
00502
00503 if( baked_upload_data->mAvatar == avatar )
00504 {
00505
00506 LLTexLayerSetBuffer* layerset_buffer = baked_upload_data->mLayerSetBuffer;
00507 layerset_buffer->mUploadPending = FALSE;
00508
00509 if (layerset_buffer->mUploadID.isNull())
00510 {
00511
00512
00513 layerset_buffer->requestUpload();
00514 }
00515 else if( baked_upload_data->mID == layerset_buffer->mUploadID )
00516 {
00517
00518 layerset_buffer->mUploadID.setNull();
00519
00520 if( result >= 0 )
00521 {
00522 LLVOAvatar::ETextureIndex baked_te = avatar->getBakedTE( layerset_buffer->mTexLayerSet );
00523 if( !gAgent.cameraCustomizeAvatar() )
00524 {
00525 avatar->setNewBakedTexture( baked_te, uuid );
00526 }
00527 else
00528 {
00529 llinfos << "LLTexLayerSetBuffer::onTextureUploadComplete() when in Customize Avatar" << llendl;
00530 }
00531 }
00532 else
00533 {
00534 llinfos << "Baked upload failed. Reason: " << result << llendl;
00535
00536 }
00537 }
00538 else
00539 {
00540 llinfos << "Received baked texture out of date, ignored." << llendl;
00541 }
00542
00543 avatar->dirtyMesh();
00544 }
00545 }
00546 else
00547 {
00548
00549
00550 llwarns << "Baked upload failed" << llendl;
00551 }
00552
00553 delete baked_upload_data;
00554 }
00555
00556
00557 void LLTexLayerSetBuffer::bindTexture()
00558 {
00559 if( mInitialized )
00560 {
00561 LLDynamicTexture::bindTexture();
00562 }
00563 else
00564 {
00565 gImageList.getImage(IMG_DEFAULT)->bind();
00566 }
00567 }
00568
00569 void LLTexLayerSetBuffer::bindBumpTexture( U32 stage )
00570 {
00571 if( mBumpTexName )
00572 {
00573 LLImageGL::bindExternalTexture(mBumpTexName, stage, GL_TEXTURE_2D);
00574
00575 if( mLastBindTime != LLImageGL::sLastFrameTime )
00576 {
00577 mLastBindTime = LLImageGL::sLastFrameTime;
00578 LLImageGL::updateBoundTexMem(mWidth * mHeight * 4);
00579 }
00580 }
00581 else
00582 {
00583 LLImageGL::unbindTexture(stage, GL_TEXTURE_2D);
00584 }
00585 }
00586
00587
00588
00589
00590
00591
00592
00593 LLTexLayerSetInfo::LLTexLayerSetInfo( )
00594 :
00595 mBodyRegion( "" ),
00596 mWidth( 512 ),
00597 mHeight( 512 ),
00598 mClearAlpha( TRUE )
00599 {
00600 }
00601
00602 LLTexLayerSetInfo::~LLTexLayerSetInfo( )
00603 {
00604 std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer());
00605 }
00606
00607 BOOL LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node)
00608 {
00609 llassert( node->hasName( "layer_set" ) );
00610 if( !node->hasName( "layer_set" ) )
00611 {
00612 return FALSE;
00613 }
00614
00615
00616 static LLStdStringHandle body_region_string = LLXmlTree::addAttributeString("body_region");
00617 if( !node->getFastAttributeString( body_region_string, mBodyRegion ) )
00618 {
00619 llwarns << "<layer_set> is missing body_region attribute" << llendl;
00620 return FALSE;
00621 }
00622
00623
00624 static LLStdStringHandle width_string = LLXmlTree::addAttributeString("width");
00625 if( !node->getFastAttributeS32( width_string, mWidth ) )
00626 {
00627 return FALSE;
00628 }
00629
00630 static LLStdStringHandle height_string = LLXmlTree::addAttributeString("height");
00631 if( !node->getFastAttributeS32( height_string, mHeight ) )
00632 {
00633 return FALSE;
00634 }
00635
00636
00637 static LLStdStringHandle alpha_tga_file_string = LLXmlTree::addAttributeString("alpha_tga_file");
00638 node->getFastAttributeString( alpha_tga_file_string, mStaticAlphaFileName );
00639
00640 static LLStdStringHandle clear_alpha_string = LLXmlTree::addAttributeString("clear_alpha");
00641 node->getFastAttributeBOOL( clear_alpha_string, mClearAlpha );
00642
00643
00644 for (LLXmlTreeNode* child = node->getChildByName( "layer" );
00645 child;
00646 child = node->getNextNamedChild())
00647 {
00648 LLTexLayerInfo* info = new LLTexLayerInfo();
00649 if( !info->parseXml( child ))
00650 {
00651 delete info;
00652 return FALSE;
00653 }
00654 mLayerInfoList.push_back( info );
00655 }
00656 return TRUE;
00657 }
00658
00659
00660
00661
00662
00663
00664 BOOL LLTexLayerSet::sHasCaches = FALSE;
00665
00666 LLTexLayerSet::LLTexLayerSet( LLVOAvatar* avatar )
00667 :
00668 mComposite( NULL ),
00669 mAvatar( avatar ),
00670 mUpdatesEnabled( FALSE ),
00671 mHasBump( FALSE ),
00672 mInfo( NULL )
00673 {
00674 }
00675
00676 LLTexLayerSet::~LLTexLayerSet()
00677 {
00678 std::for_each(mLayerList.begin(), mLayerList.end(), DeletePointer());
00679 delete mComposite;
00680 }
00681
00682
00683
00684
00685
00686 BOOL LLTexLayerSet::setInfo(LLTexLayerSetInfo *info)
00687 {
00688 llassert(mInfo == NULL);
00689 mInfo = info;
00690
00691
00692 LLTexLayerSetInfo::layer_info_list_t::iterator iter;
00693 mLayerList.reserve(info->mLayerInfoList.size());
00694 for (iter = info->mLayerInfoList.begin(); iter != info->mLayerInfoList.end(); iter++)
00695 {
00696 LLTexLayer* layer = new LLTexLayer( this );
00697 if (!layer->setInfo(*iter))
00698 {
00699 mInfo = NULL;
00700 return FALSE;
00701 }
00702 mLayerList.push_back( layer );
00703 }
00704
00705 requestUpdate();
00706
00707 stop_glerror();
00708
00709 return TRUE;
00710 }
00711
00712 #if 0 // obsolete
00713
00714
00715
00716
00717 BOOL LLTexLayerSet::parseData(LLXmlTreeNode* node)
00718 {
00719 LLTexLayerSetInfo *info = new LLTexLayerSetInfo;
00720
00721 if (!info->parseXml(node))
00722 {
00723 delete info;
00724 return FALSE;
00725 }
00726 if (!setInfo(info))
00727 {
00728 delete info;
00729 return FALSE;
00730 }
00731 return TRUE;
00732 }
00733 #endif
00734
00735 void LLTexLayerSet::deleteCaches()
00736 {
00737 for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
00738 {
00739 LLTexLayer* layer = *iter;
00740 layer->deleteCaches();
00741 }
00742 }
00743
00744
00745 BOOL LLTexLayerSet::isLocalTextureDataAvailable()
00746 {
00747 return mAvatar->isLocalTextureDataAvailable( this );
00748 }
00749
00750
00751
00752 BOOL LLTexLayerSet::isLocalTextureDataFinal()
00753 {
00754 return mAvatar->isLocalTextureDataFinal( this );
00755 }
00756
00757
00758 BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
00759 {
00760 BOOL success = TRUE;
00761
00762 LLGLSUIDefault gls_ui;
00763 LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE);
00764
00765
00766 for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
00767 {
00768 LLTexLayer* layer = *iter;
00769 if( layer->getRenderPass() == RP_COLOR )
00770 {
00771 success &= layer->render( x, y, width, height );
00772 }
00773 }
00774
00775
00776 if( !getInfo()->mStaticAlphaFileName.empty() )
00777 {
00778 LLGLSNoAlphaTest gls_no_alpha_test;
00779
00780
00781
00782 GLboolean mask[4];
00783 glGetBooleanv(GL_COLOR_WRITEMASK,mask);
00784
00785
00786 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE );
00787 glBlendFunc( GL_ONE, GL_ZERO );
00788
00789 {
00790 LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticAlphaFileName, TRUE );
00791 if( image_gl )
00792 {
00793 LLGLSUIDefault gls_ui;
00794 image_gl->bind();
00795 gl_rect_2d_simple_tex( width, height );
00796 }
00797 else
00798 {
00799 success = FALSE;
00800 }
00801 }
00802 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
00803
00804
00805
00806 glColorMask(mask[0], mask[1], mask[2], GL_TRUE);
00807
00808
00809
00810
00811 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00812 }
00813 else
00814 if( getInfo()->mClearAlpha )
00815 {
00816
00817 LLGLSNoTextureNoAlphaTest gls_no_alpha;
00818 glColor4f( 0.f, 0.f, 0.f, 1.f );
00819
00820
00821
00822 GLboolean mask[4];
00823 glGetBooleanv(GL_COLOR_WRITEMASK,mask);
00824
00825 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE );
00826
00827 gl_rect_2d_simple( width, height );
00828
00829
00830
00831 glColorMask(mask[0], mask[1], mask[2], GL_TRUE);
00832
00833
00834
00835 }
00836 stop_glerror();
00837
00838 return success;
00839 }
00840
00841 BOOL LLTexLayerSet::renderBump( S32 x, S32 y, S32 width, S32 height )
00842 {
00843 BOOL success = TRUE;
00844
00845 LLGLSUIDefault gls_ui;
00846 LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE);
00847
00848
00849
00850 for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
00851 {
00852 LLTexLayer* layer = *iter;
00853 if( layer->getRenderPass() == RP_BUMP )
00854 {
00855 success &= layer->render( x, y, width, height );
00856 }
00857 }
00858
00859
00860 LLGLSNoTextureNoAlphaTest gls_no_texture_no_alpha;
00861 glColor4f( 0.f, 0.f, 0.f, 1.f );
00862
00863
00864
00865 GLboolean mask[4];
00866 glGetBooleanv(GL_COLOR_WRITEMASK,mask);
00867
00868 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE );
00869
00870 gl_rect_2d_simple( width, height );
00871
00872
00873
00874 glColorMask(mask[0], mask[1], mask[2], GL_TRUE);
00875
00876
00877
00878 stop_glerror();
00879
00880 return success;
00881 }
00882
00883 void LLTexLayerSet::requestUpdate()
00884 {
00885 if( mUpdatesEnabled )
00886 {
00887 createComposite();
00888 mComposite->requestUpdate();
00889 }
00890 }
00891
00892 void LLTexLayerSet::requestUpload()
00893 {
00894 createComposite();
00895 mComposite->requestUpload();
00896 }
00897
00898 void LLTexLayerSet::cancelUpload()
00899 {
00900 if(mComposite)
00901 {
00902 mComposite->cancelUpload();
00903 }
00904 }
00905
00906 void LLTexLayerSet::createComposite()
00907 {
00908 if( !mComposite )
00909 {
00910 S32 width = mInfo->mWidth;
00911 S32 height = mInfo->mHeight;
00912
00913 if( !mAvatar->mIsSelf )
00914 {
00915 width /= 2;
00916 height /= 2;
00917 }
00918 mComposite = new LLTexLayerSetBuffer( this, width, height, mHasBump );
00919 }
00920 }
00921
00922 void LLTexLayerSet::destroyComposite()
00923 {
00924 if( mComposite )
00925 {
00926 delete mComposite;
00927 mComposite = NULL;
00928 }
00929 }
00930
00931 void LLTexLayerSet::setUpdatesEnabled( BOOL b )
00932 {
00933 mUpdatesEnabled = b;
00934 }
00935
00936
00937 void LLTexLayerSet::updateComposite()
00938 {
00939 createComposite();
00940 mComposite->updateImmediate();
00941 }
00942
00943 LLTexLayerSetBuffer* LLTexLayerSet::getComposite()
00944 {
00945 createComposite();
00946 return mComposite;
00947 }
00948
00949 void LLTexLayerSet::gatherAlphaMasks(U8 *data, S32 width, S32 height)
00950 {
00951 S32 size = width * height;
00952
00953 memset(data, 255, width * height);
00954
00955 for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
00956 {
00957 LLTexLayer* layer = *iter;
00958 U8* alphaData = layer->getAlphaData();
00959 if (!alphaData && layer->hasAlphaParams())
00960 {
00961 LLColor4 net_color;
00962 layer->findNetColor( &net_color );
00963 layer->invalidateMorphMasks();
00964 layer->renderAlphaMasks(mComposite->getOriginX(), mComposite->getOriginY(), width, height, &net_color);
00965 alphaData = layer->getAlphaData();
00966 }
00967 if (alphaData)
00968 {
00969 for( S32 i = 0; i < size; i++ )
00970 {
00971 U8 curAlpha = data[i];
00972 U16 resultAlpha = curAlpha;
00973 resultAlpha *= (alphaData[i] + 1);
00974 resultAlpha = resultAlpha >> 8;
00975 data[i] = (U8)resultAlpha;
00976 }
00977 }
00978 }
00979 }
00980
00981 void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components)
00982 {
00983 for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
00984 {
00985 LLTexLayer* layer = *iter;
00986 layer->applyMorphMask(tex_data, width, height, num_components);
00987 }
00988 }
00989
00990
00991
00992
00993 LLTexLayerInfo::LLTexLayerInfo( )
00994 :
00995 mWriteAllChannels( FALSE ),
00996 mRenderPass( RP_COLOR ),
00997 mFixedColor( 0.f, 0.f, 0.f, 0.f ),
00998 mLocalTexture( -1 ),
00999 mStaticImageIsMask( FALSE ),
01000 mUseLocalTextureAlphaOnly( FALSE )
01001 {
01002 }
01003
01004 LLTexLayerInfo::~LLTexLayerInfo( )
01005 {
01006 std::for_each(mColorInfoList.begin(), mColorInfoList.end(), DeletePointer());
01007 std::for_each(mAlphaInfoList.begin(), mAlphaInfoList.end(), DeletePointer());
01008 }
01009
01010 BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node)
01011 {
01012 llassert( node->hasName( "layer" ) );
01013
01014
01015 static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
01016 if( !node->getFastAttributeString( name_string, mName ) )
01017 {
01018 return FALSE;
01019 }
01020
01021 static LLStdStringHandle write_all_channels_string = LLXmlTree::addAttributeString("write_all_channels");
01022 node->getFastAttributeBOOL( write_all_channels_string, mWriteAllChannels );
01023
01024 LLString render_pass_name;
01025 static LLStdStringHandle render_pass_string = LLXmlTree::addAttributeString("render_pass");
01026 if( node->getFastAttributeString( render_pass_string, render_pass_name ) )
01027 {
01028 if( render_pass_name == "bump" )
01029 {
01030 mRenderPass = RP_BUMP;
01031 }
01032 }
01033
01034
01035
01036 static LLStdStringHandle global_color_string = LLXmlTree::addAttributeString("global_color");
01037 node->getFastAttributeString( global_color_string, mGlobalColor );
01038
01039
01040 LLColor4U color4u;
01041 static LLStdStringHandle fixed_color_string = LLXmlTree::addAttributeString("fixed_color");
01042 if( node->getFastAttributeColor4U( fixed_color_string, color4u ) )
01043 {
01044 mFixedColor.setVec( color4u );
01045 }
01046
01047
01048 for (LLXmlTreeNode* texture_node = node->getChildByName( "texture" );
01049 texture_node;
01050 texture_node = node->getNextNamedChild())
01051 {
01052 LLString local_texture;
01053 static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file");
01054 static LLStdStringHandle local_texture_string = LLXmlTree::addAttributeString("local_texture");
01055 static LLStdStringHandle file_is_mask_string = LLXmlTree::addAttributeString("file_is_mask");
01056 static LLStdStringHandle local_texture_alpha_only_string = LLXmlTree::addAttributeString("local_texture_alpha_only");
01057 if( texture_node->getFastAttributeString( tga_file_string, mStaticImageFileName ) )
01058 {
01059 texture_node->getFastAttributeBOOL( file_is_mask_string, mStaticImageIsMask );
01060 }
01061 else if( texture_node->getFastAttributeString( local_texture_string, local_texture ) )
01062 {
01063 texture_node->getFastAttributeBOOL( local_texture_alpha_only_string, mUseLocalTextureAlphaOnly );
01064
01065 if( "upper_shirt" == local_texture )
01066 {
01067 mLocalTexture = LLVOAvatar::LOCTEX_UPPER_SHIRT;
01068 }
01069 else if( "upper_bodypaint" == local_texture )
01070 {
01071 mLocalTexture = LLVOAvatar::LOCTEX_UPPER_BODYPAINT;
01072 }
01073 else if( "lower_pants" == local_texture )
01074 {
01075 mLocalTexture = LLVOAvatar::LOCTEX_LOWER_PANTS;
01076 }
01077 else if( "lower_bodypaint" == local_texture )
01078 {
01079 mLocalTexture = LLVOAvatar::LOCTEX_LOWER_BODYPAINT;
01080 }
01081 else if( "lower_shoes" == local_texture )
01082 {
01083 mLocalTexture = LLVOAvatar::LOCTEX_LOWER_SHOES;
01084 }
01085 else if( "head_bodypaint" == local_texture )
01086 {
01087 mLocalTexture = LLVOAvatar::LOCTEX_HEAD_BODYPAINT;
01088 }
01089 else if( "lower_socks" == local_texture )
01090 {
01091 mLocalTexture = LLVOAvatar::LOCTEX_LOWER_SOCKS;
01092 }
01093 else if( "upper_jacket" == local_texture )
01094 {
01095 mLocalTexture = LLVOAvatar::LOCTEX_UPPER_JACKET;
01096 }
01097 else if( "lower_jacket" == local_texture )
01098 {
01099 mLocalTexture = LLVOAvatar::LOCTEX_LOWER_JACKET;
01100 }
01101 else if( "upper_gloves" == local_texture )
01102 {
01103 mLocalTexture = LLVOAvatar::LOCTEX_UPPER_GLOVES;
01104 }
01105 else if( "upper_undershirt" == local_texture )
01106 {
01107 mLocalTexture = LLVOAvatar::LOCTEX_UPPER_UNDERSHIRT;
01108 }
01109 else if( "lower_underpants" == local_texture )
01110 {
01111 mLocalTexture = LLVOAvatar::LOCTEX_LOWER_UNDERPANTS;
01112 }
01113 else if( "eyes_iris" == local_texture )
01114 {
01115 mLocalTexture = LLVOAvatar::LOCTEX_EYES_IRIS;
01116 }
01117 else if( "skirt" == local_texture )
01118 {
01119 mLocalTexture = LLVOAvatar::LOCTEX_SKIRT;
01120 }
01121 else
01122 {
01123 llwarns << "<texture> element has invalid local_texure attribute: " << mName << " " << local_texture << llendl;
01124 return FALSE;
01125 }
01126 }
01127 else
01128 {
01129 llwarns << "<texture> element is missing a required attribute. " << mName << llendl;
01130 return FALSE;
01131 }
01132 }
01133
01134 for (LLXmlTreeNode* maskNode = node->getChildByName( "morph_mask" );
01135 maskNode;
01136 maskNode = node->getNextNamedChild())
01137 {
01138 LLString morph_name;
01139 static LLStdStringHandle morph_name_string = LLXmlTree::addAttributeString("morph_name");
01140 if (maskNode->getFastAttributeString(morph_name_string, morph_name))
01141 {
01142 BOOL invert = FALSE;
01143 static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert");
01144 maskNode->getFastAttributeBOOL(invert_string, invert);
01145 mMorphNameList.push_back(std::pair<LLString,BOOL>(morph_name,invert));
01146 }
01147 }
01148
01149
01150 for (LLXmlTreeNode* child = node->getChildByName( "param" );
01151 child;
01152 child = node->getNextNamedChild())
01153 {
01154 if( child->getChildByName( "param_color" ) )
01155 {
01156
01157 LLTexParamColorInfo* info = new LLTexParamColorInfo( );
01158 if (!info->parseXml(child))
01159 {
01160 delete info;
01161 return FALSE;
01162 }
01163 mColorInfoList.push_back( info );
01164 }
01165 else if( child->getChildByName( "param_alpha" ) )
01166 {
01167
01168 LLTexLayerParamAlphaInfo* info = new LLTexLayerParamAlphaInfo( );
01169 if (!info->parseXml(child))
01170 {
01171 delete info;
01172 return FALSE;
01173 }
01174 mAlphaInfoList.push_back( info );
01175 }
01176 }
01177
01178 return TRUE;
01179 }
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194 LLTexLayer::LLTexLayer( LLTexLayerSet* layer_set )
01195 :
01196 mTexLayerSet( layer_set ),
01197 mMorphMasksValid( FALSE ),
01198 mStaticImageInvalid( FALSE ),
01199 mInfo( NULL )
01200 {
01201 }
01202
01203 LLTexLayer::~LLTexLayer()
01204 {
01205
01206
01207
01208
01209
01210 for( alpha_cache_t::iterator iter = mAlphaCache.begin();
01211 iter != mAlphaCache.end(); iter++ )
01212 {
01213 U8* alpha_data = iter->second;
01214 delete [] alpha_data;
01215 }
01216 }
01217
01218
01219
01220
01221
01222 BOOL LLTexLayer::setInfo(LLTexLayerInfo* info)
01223 {
01224 llassert(mInfo == NULL);
01225 mInfo = info;
01226
01227
01228 if (info->mRenderPass == RP_BUMP)
01229 mTexLayerSet->setBump(TRUE);
01230
01231 {
01232 LLTexLayerInfo::morph_name_list_t::iterator iter;
01233 for (iter = mInfo->mMorphNameList.begin(); iter != mInfo->mMorphNameList.end(); iter++)
01234 {
01235
01236
01237
01238 LLPolyMorphTarget *morph_param;
01239 LLString *name = &(iter->first);
01240 morph_param = (LLPolyMorphTarget *)(getTexLayerSet()->getAvatar()->getVisualParam(name->c_str()));
01241 if (morph_param)
01242 {
01243 BOOL invert = iter->second;
01244 addMaskedMorph(morph_param, invert);
01245 }
01246 }
01247 }
01248
01249 {
01250 LLTexLayerInfo::color_info_list_t::iterator iter;
01251 mParamColorList.reserve(mInfo->mColorInfoList.size());
01252 for (iter = mInfo->mColorInfoList.begin(); iter != mInfo->mColorInfoList.end(); iter++)
01253 {
01254 LLTexParamColor* param_color = new LLTexParamColor( this );
01255 if (!param_color->setInfo(*iter))
01256 {
01257 mInfo = NULL;
01258 return FALSE;
01259 }
01260 mParamColorList.push_back( param_color );
01261 }
01262 }
01263 {
01264 LLTexLayerInfo::alpha_info_list_t::iterator iter;
01265 mParamAlphaList.reserve(mInfo->mAlphaInfoList.size());
01266 for (iter = mInfo->mAlphaInfoList.begin(); iter != mInfo->mAlphaInfoList.end(); iter++)
01267 {
01268 LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha( this );
01269 if (!param_alpha->setInfo(*iter))
01270 {
01271 mInfo = NULL;
01272 return FALSE;
01273 }
01274 mParamAlphaList.push_back( param_alpha );
01275 }
01276 }
01277
01278 return TRUE;
01279 }
01280
01281 #if 0 // obsolete
01282
01283
01284
01285 BOOL LLTexLayer::parseData( LLXmlTreeNode* node )
01286 {
01287 LLTexLayerInfo *info = new LLTexLayerInfo;
01288
01289 if (!info->parseXml(node))
01290 {
01291 delete info;
01292 return FALSE;
01293 }
01294 if (!setInfo(info))
01295 {
01296 delete info;
01297 return FALSE;
01298 }
01299 return TRUE;
01300 }
01301 #endif
01302
01303
01304
01305
01306 void LLTexLayer::deleteCaches()
01307 {
01308 for( alpha_list_t::iterator iter = mParamAlphaList.begin();
01309 iter != mParamAlphaList.end(); iter++ )
01310 {
01311 LLTexLayerParamAlpha* param = *iter;
01312 param->deleteCaches();
01313 }
01314 mStaticImageRaw = NULL;
01315 }
01316
01317 BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
01318 {
01319 LLGLEnable color_mat(GL_COLOR_MATERIAL);
01320 gPipeline.disableLights();
01321
01322 BOOL success = TRUE;
01323
01324 BOOL color_specified = FALSE;
01325 BOOL alpha_mask_specified = FALSE;
01326
01327 LLColor4 net_color;
01328 color_specified = findNetColor( &net_color );
01329
01330
01331 if( is_approx_zero( net_color.mV[VW] ) )
01332 {
01333 return success;
01334 }
01335
01336 alpha_list_t::iterator iter = mParamAlphaList.begin();
01337 if( iter != mParamAlphaList.end() )
01338 {
01339
01340
01341 if( mMaskedMorphs.empty() )
01342 {
01343 BOOL skip_layer = TRUE;
01344
01345 while( iter != mParamAlphaList.end() )
01346 {
01347 LLTexLayerParamAlpha* param = *iter;
01348
01349 if( !param->getSkip() )
01350 {
01351 skip_layer = FALSE;
01352 break;
01353 }
01354
01355 iter++;
01356 }
01357
01358 if( skip_layer )
01359 {
01360 return success;
01361 }
01362 }
01363
01364 renderAlphaMasks( x, y, width, height, &net_color );
01365 alpha_mask_specified = TRUE;
01366 glBlendFunc( GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA );
01367 }
01368
01369 glColor4fv( net_color.mV);
01370
01371 if( getInfo()->mWriteAllChannels )
01372 {
01373 glBlendFunc( GL_ONE, GL_ZERO );
01374 }
01375
01376 if( (getInfo()->mLocalTexture != -1) && !getInfo()->mUseLocalTextureAlphaOnly )
01377 {
01378 {
01379 LLImageGL* image_gl = NULL;
01380 if( mTexLayerSet->getAvatar()->getLocalTextureGL( getInfo()->mLocalTexture, &image_gl ) )
01381 {
01382 if( image_gl )
01383 {
01384 LLGLDisable alpha_test(getInfo()->mWriteAllChannels ? GL_ALPHA_TEST : 0);
01385
01386 BOOL old_clamps = image_gl->getClampS();
01387 BOOL old_clampt = image_gl->getClampT();
01388
01389 image_gl->bind();
01390 image_gl->setClamp(TRUE, TRUE);
01391
01392 gl_rect_2d_simple_tex( width, height );
01393
01394 image_gl->setClamp(old_clamps, old_clampt);
01395 image_gl->unbindTexture(0, GL_TEXTURE_2D);
01396 }
01397 }
01398 else
01399 {
01400 success = FALSE;
01401 }
01402 }
01403 }
01404
01405 if( !getInfo()->mStaticImageFileName.empty() )
01406 {
01407 {
01408 LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask );
01409 if( image_gl )
01410 {
01411 image_gl->bind();
01412 gl_rect_2d_simple_tex( width, height );
01413 image_gl->unbindTexture(0, GL_TEXTURE_2D);
01414 }
01415 else
01416 {
01417 success = FALSE;
01418 }
01419 }
01420 }
01421
01422 if( ((-1 == getInfo()->mLocalTexture) ||
01423 getInfo()->mUseLocalTextureAlphaOnly) &&
01424 getInfo()->mStaticImageFileName.empty() &&
01425 color_specified )
01426 {
01427 LLGLSNoTextureNoAlphaTest gls;
01428 glColor4fv( net_color.mV);
01429 gl_rect_2d_simple( width, height );
01430 }
01431
01432 if( alpha_mask_specified || getInfo()->mWriteAllChannels )
01433 {
01434
01435 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
01436 stop_glerror();
01437 }
01438
01439 if( !success )
01440 {
01441 llinfos << "LLTexLayer::render() partial: " << getInfo()->mName << llendl;
01442 }
01443 return success;
01444 }
01445
01446 U8* LLTexLayer::getAlphaData()
01447 {
01448 LLCRC alpha_mask_crc;
01449 const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID(getInfo()->mLocalTexture);
01450 alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES);
01451
01452 for( alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ )
01453 {
01454 LLTexLayerParamAlpha* param = *iter;
01455 F32 param_weight = param->getWeight();
01456 alpha_mask_crc.update((U8*)¶m_weight, sizeof(F32));
01457 }
01458
01459 U32 cache_index = alpha_mask_crc.getCRC();
01460
01461 alpha_cache_t::iterator iter2 = mAlphaCache.find(cache_index);
01462 return (iter2 == mAlphaCache.end()) ? 0 : iter2->second;
01463 }
01464
01465 BOOL LLTexLayer::findNetColor( LLColor4* net_color )
01466 {
01467
01468
01469
01470
01471
01472
01473 if( !mParamColorList.empty() )
01474 {
01475 if( !getGlobalColor().empty() )
01476 {
01477 net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getInfo()->mGlobalColor ) );
01478 }
01479 else
01480 if( getInfo()->mFixedColor.mV[VW] )
01481 {
01482 net_color->setVec( getInfo()->mFixedColor );
01483 }
01484 else
01485 {
01486 net_color->setVec( 0.f, 0.f, 0.f, 0.f );
01487 }
01488
01489 for( color_list_t::iterator iter = mParamColorList.begin();
01490 iter != mParamColorList.end(); iter++ )
01491 {
01492 LLTexParamColor* param = *iter;
01493 LLColor4 param_net = param->getNetColor();
01494 switch( param->getOperation() )
01495 {
01496 case OP_ADD:
01497 *net_color += param_net;
01498 break;
01499 case OP_MULTIPLY:
01500 net_color->mV[VX] *= param_net.mV[VX];
01501 net_color->mV[VY] *= param_net.mV[VY];
01502 net_color->mV[VZ] *= param_net.mV[VZ];
01503 net_color->mV[VW] *= param_net.mV[VW];
01504 break;
01505 case OP_BLEND:
01506 net_color->setVec( lerp(*net_color, param_net, param->getWeight()) );
01507 break;
01508 default:
01509 llassert(0);
01510 break;
01511 }
01512 }
01513 return TRUE;
01514 }
01515
01516 if( !getGlobalColor().empty() )
01517 {
01518 net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getGlobalColor() ) );
01519 return TRUE;
01520 }
01521
01522 if( getInfo()->mFixedColor.mV[VW] )
01523 {
01524 net_color->setVec( getInfo()->mFixedColor );
01525 return TRUE;
01526 }
01527
01528 net_color->setToWhite();
01529
01530 return FALSE;
01531 }
01532
01533
01534 BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4* colorp )
01535 {
01536 BOOL success = TRUE;
01537
01538 llassert( !mParamAlphaList.empty() );
01539
01540
01541
01542 GLboolean mask[4];
01543 glGetBooleanv(GL_COLOR_WRITEMASK,mask);
01544
01545 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE );
01546
01547 alpha_list_t::iterator iter = mParamAlphaList.begin();
01548 LLTexLayerParamAlpha* first_param = *iter;
01549
01550
01551 if( !first_param || !first_param->getMultiplyBlend() )
01552 {
01553 LLGLSNoTextureNoAlphaTest gls_no_texture_no_alpha_test;
01554
01555
01556 glBlendFunc( GL_ONE, GL_ZERO );
01557
01558 glColor4f( 0.f, 0.f, 0.f, 0.f );
01559 gl_rect_2d_simple( width, height );
01560 }
01561
01562
01563 LLGLSNoAlphaTest gls_no_alpha_test;
01564 glColor4f( 1.f, 1.f, 1.f, 1.f );
01565
01566 for( iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ )
01567 {
01568 LLTexLayerParamAlpha* param = *iter;
01569 success &= param->render( x, y, width, height );
01570 }
01571
01572
01573 glBlendFunc( GL_DST_ALPHA, GL_ZERO );
01574
01575
01576 if( getInfo()->mLocalTexture != -1 )
01577 {
01578 {
01579 LLImageGL* image_gl = NULL;
01580 if( mTexLayerSet->getAvatar()->getLocalTextureGL( getInfo()->mLocalTexture, &image_gl ) )
01581 {
01582 if( image_gl && (image_gl->getComponents() == 4) )
01583 {
01584 LLGLSNoAlphaTest gls_no_alpha_test;
01585
01586 BOOL old_clamps = image_gl->getClampS();
01587 BOOL old_clampt = image_gl->getClampT();
01588 image_gl->bind();
01589 image_gl->setClamp(TRUE, TRUE);
01590
01591 gl_rect_2d_simple_tex( width, height );
01592
01593 image_gl->setClamp(old_clamps, old_clampt);
01594 image_gl->unbindTexture(0, GL_TEXTURE_2D);
01595 }
01596 }
01597 else
01598 {
01599 success = FALSE;
01600 }
01601 }
01602 }
01603
01604 if( !getInfo()->mStaticImageFileName.empty() )
01605 {
01606 {
01607 LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask );
01608 if( image_gl )
01609 {
01610 if( (image_gl->getComponents() == 4) ||
01611 ( (image_gl->getComponents() == 1) && getInfo()->mStaticImageIsMask ) )
01612 {
01613 LLGLSNoAlphaTest gls_no_alpha_test;
01614 image_gl->bind();
01615 gl_rect_2d_simple_tex( width, height );
01616 image_gl->unbindTexture(0, GL_TEXTURE_2D);
01617 }
01618 }
01619 else
01620 {
01621 success = FALSE;
01622 }
01623 }
01624 }
01625
01626
01627
01628 if( colorp->mV[VW] != 1.f )
01629 {
01630 LLGLSNoTextureNoAlphaTest gls_no_texture_no_alpha_test;
01631 glColor4fv( colorp->mV );
01632 gl_rect_2d_simple( width, height );
01633 }
01634
01635
01636 LLGLSUIDefault gls_ui;
01637
01638
01639
01640 glColorMask(mask[0], mask[1], mask[2], GL_TRUE);
01641
01642
01643 if (!mMorphMasksValid && !mMaskedMorphs.empty())
01644 {
01645 LLCRC alpha_mask_crc;
01646 const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID(getInfo()->mLocalTexture);
01647 alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES);
01648
01649 for( alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ )
01650 {
01651 LLTexLayerParamAlpha* param = *iter;
01652 F32 param_weight = param->getWeight();
01653 alpha_mask_crc.update((U8*)¶m_weight, sizeof(F32));
01654 }
01655
01656 U32 cache_index = alpha_mask_crc.getCRC();
01657
01658 alpha_cache_t::iterator iter2 = mAlphaCache.find(cache_index);
01659 U8* alpha_data;
01660 if (iter2 != mAlphaCache.end())
01661 {
01662 alpha_data = iter2->second;
01663 }
01664 else
01665 {
01666
01667 S32 max_cache_entries = getTexLayerSet()->getAvatar()->mIsSelf ? 4 : 1;
01668 while ((S32)mAlphaCache.size() >= max_cache_entries)
01669 {
01670 iter2 = mAlphaCache.begin();
01671 alpha_data = iter2->second;
01672 delete [] alpha_data;
01673 mAlphaCache.erase(iter2);
01674 }
01675 alpha_data = new U8[width * height];
01676 mAlphaCache[cache_index] = alpha_data;
01677 glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data);
01678 }
01679
01680 getTexLayerSet()->getAvatar()->dirtyMesh();
01681
01682 mMorphMasksValid = TRUE;
01683
01684 for( morph_list_t::iterator iter3 = mMaskedMorphs.begin();
01685 iter3 != mMaskedMorphs.end(); iter3++ )
01686 {
01687 LLMaskedMorph* maskedMorph = &(*iter3);
01688 maskedMorph->mMorphTarget->applyMask(alpha_data, width, height, 1, maskedMorph->mInvert);
01689 }
01690 }
01691
01692 return success;
01693 }
01694
01695 void LLTexLayer::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components)
01696 {
01697 for( morph_list_t::iterator iter = mMaskedMorphs.begin();
01698 iter != mMaskedMorphs.end(); iter++ )
01699 {
01700 LLMaskedMorph* maskedMorph = &(*iter);
01701 maskedMorph->mMorphTarget->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert);
01702 }
01703 }
01704
01705
01706 BOOL LLTexLayer::renderImageRaw( U8* in_data, S32 in_width, S32 in_height, S32 in_components, S32 width, S32 height, BOOL is_mask )
01707 {
01708 if (!in_data)
01709 {
01710 return FALSE;
01711 }
01712 GLenum format_options[4] = { GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA };
01713 GLenum format = format_options[in_components-1];
01714 if( is_mask )
01715 {
01716 llassert( 1 == in_components );
01717 format = GL_ALPHA;
01718 }
01719
01720 if( (in_width != VOAVATAR_SCRATCH_TEX_WIDTH) || (in_height != VOAVATAR_SCRATCH_TEX_HEIGHT) )
01721 {
01722 LLGLSNoAlphaTest gls_no_alpha_test;
01723
01724 GLenum internal_format_options[4] = { GL_LUMINANCE8, GL_LUMINANCE8_ALPHA8, GL_RGB8, GL_RGBA8 };
01725 GLenum internal_format = internal_format_options[in_components-1];
01726 if( is_mask )
01727 {
01728 llassert( 1 == in_components );
01729 internal_format = GL_ALPHA8;
01730 }
01731
01732 GLuint name = 0;
01733 glGenTextures(1, &name );
01734 stop_glerror();
01735
01736 LLImageGL::bindExternalTexture( name, 0, GL_TEXTURE_2D );
01737 stop_glerror();
01738
01739 glTexImage2D(
01740 GL_TEXTURE_2D, 0, internal_format,
01741 in_width, in_height,
01742 0, format, GL_UNSIGNED_BYTE, in_data );
01743 stop_glerror();
01744
01745 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
01746 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
01747
01748 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
01749 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
01750
01751 gl_rect_2d_simple_tex( width, height );
01752
01753 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
01754
01755 glDeleteTextures(1, &name );
01756 stop_glerror();
01757 }
01758 else
01759 {
01760 LLGLSNoAlphaTest gls_no_alpha_test;
01761
01762 if( !mTexLayerSet->getAvatar()->bindScratchTexture(format) )
01763 {
01764 return FALSE;
01765 }
01766
01767 glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, in_width, in_height, format, GL_UNSIGNED_BYTE, in_data );
01768 stop_glerror();
01769
01770 gl_rect_2d_simple_tex( width, height );
01771
01772 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
01773 }
01774
01775 return TRUE;
01776 }
01777
01778 void LLTexLayer::requestUpdate()
01779 {
01780 mTexLayerSet->requestUpdate();
01781 }
01782
01783 void LLTexLayer::addMaskedMorph(LLPolyMorphTarget* morph_target, BOOL invert)
01784 {
01785 mMaskedMorphs.push_front(LLMaskedMorph(morph_target, invert));
01786 }
01787
01788 void LLTexLayer::invalidateMorphMasks()
01789 {
01790 mMorphMasksValid = FALSE;
01791 }
01792
01793
01794
01795
01796 LLTexLayerParamAlphaInfo::LLTexLayerParamAlphaInfo( )
01797 :
01798 mMultiplyBlend( FALSE ),
01799 mSkipIfZeroWeight( FALSE ),
01800 mDomain( 0.f )
01801 {
01802 }
01803
01804 BOOL LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node)
01805 {
01806 llassert( node->hasName( "param" ) && node->getChildByName( "param_alpha" ) );
01807
01808 if( !LLViewerVisualParamInfo::parseXml(node) )
01809 return FALSE;
01810
01811 LLXmlTreeNode* param_alpha_node = node->getChildByName( "param_alpha" );
01812 if( !param_alpha_node )
01813 {
01814 return FALSE;
01815 }
01816
01817 static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file");
01818 if( param_alpha_node->getFastAttributeString( tga_file_string, mStaticImageFileName ) )
01819 {
01820
01821 }
01822
01823
01824
01825
01826
01827 static LLStdStringHandle multiply_blend_string = LLXmlTree::addAttributeString("multiply_blend");
01828 param_alpha_node->getFastAttributeBOOL( multiply_blend_string, mMultiplyBlend );
01829
01830 static LLStdStringHandle skip_if_zero_string = LLXmlTree::addAttributeString("skip_if_zero");
01831 param_alpha_node->getFastAttributeBOOL( skip_if_zero_string, mSkipIfZeroWeight );
01832
01833 static LLStdStringHandle domain_string = LLXmlTree::addAttributeString("domain");
01834 param_alpha_node->getFastAttributeF32( domain_string, mDomain );
01835
01836 gGradientPaletteList.initPalette(mDomain);
01837
01838 return TRUE;
01839 }
01840
01841
01842
01843
01844
01845
01846 LLTexLayerParamAlpha::param_alpha_ptr_list_t LLTexLayerParamAlpha::sInstances;
01847
01848
01849 void LLTexLayerParamAlpha::dumpCacheByteCount()
01850 {
01851 S32 gl_bytes = 0;
01852 getCacheByteCount( &gl_bytes );
01853 llinfos << "Processed Alpha Texture Cache GL:" << (gl_bytes/1024) << "KB" << llendl;
01854 }
01855
01856
01857 void LLTexLayerParamAlpha::getCacheByteCount( S32* gl_bytes )
01858 {
01859 *gl_bytes = 0;
01860
01861 for( param_alpha_ptr_list_t::iterator iter = sInstances.begin();
01862 iter != sInstances.end(); iter++ )
01863 {
01864 LLTexLayerParamAlpha* instance = *iter;
01865 LLImageGL* image_gl = instance->mCachedProcessedImageGL;
01866 if( image_gl )
01867 {
01868 S32 bytes = (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents();
01869
01870 if( image_gl->getHasGLTexture() )
01871 {
01872 *gl_bytes += bytes;
01873 }
01874 }
01875 }
01876 }
01877
01878 LLTexLayerParamAlpha::LLTexLayerParamAlpha( LLTexLayer* layer )
01879 :
01880 mCachedProcessedImageGL( NULL ),
01881 mTexLayer( layer ),
01882 mNeedsCreateTexture( FALSE ),
01883 mStaticImageInvalid( FALSE ),
01884 mAvgDistortionVec(1.f, 1.f, 1.f),
01885 mCachedEffectiveWeight(0.f)
01886 {
01887 sInstances.push_front( this );
01888 }
01889
01890 LLTexLayerParamAlpha::~LLTexLayerParamAlpha()
01891 {
01892 deleteCaches();
01893 sInstances.remove( this );
01894 }
01895
01896
01897
01898
01899 BOOL LLTexLayerParamAlpha::setInfo(LLTexLayerParamAlphaInfo *info)
01900 {
01901 llassert(mInfo == NULL);
01902 if (info->mID < 0)
01903 return FALSE;
01904 mInfo = info;
01905 mID = info->mID;
01906
01907 mTexLayer->getTexLayerSet()->getAvatar()->addVisualParam( this );
01908 setWeight(getDefaultWeight(), FALSE );
01909
01910 return TRUE;
01911 }
01912
01913
01914
01915 void LLTexLayerParamAlpha::deleteCaches()
01916 {
01917 mStaticImageTGA = NULL;
01918 mCachedProcessedImageGL = NULL;
01919 mStaticImageRaw = NULL;
01920 mNeedsCreateTexture = FALSE;
01921 }
01922
01923 void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL set_by_user)
01924 {
01925 if (mIsAnimating)
01926 {
01927 return;
01928 }
01929 F32 min_weight = getMinWeight();
01930 F32 max_weight = getMaxWeight();
01931 F32 new_weight = llclamp(weight, min_weight, max_weight);
01932 U8 cur_u8 = F32_to_U8( mCurWeight, min_weight, max_weight );
01933 U8 new_u8 = F32_to_U8( new_weight, min_weight, max_weight );
01934 if( cur_u8 != new_u8)
01935 {
01936 mCurWeight = new_weight;
01937
01938 LLVOAvatar* avatar = mTexLayer->getTexLayerSet()->getAvatar();
01939 if( avatar->getSex() & getSex() )
01940 {
01941 avatar->invalidateComposite( mTexLayer->getTexLayerSet(), set_by_user );
01942 mTexLayer->invalidateMorphMasks();
01943 }
01944 }
01945 }
01946
01947 void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL set_by_user)
01948 {
01949 mTargetWeight = target_value;
01950 setWeight(target_value, set_by_user);
01951 mIsAnimating = TRUE;
01952 if (mNext)
01953 {
01954 mNext->setAnimationTarget(target_value, set_by_user);
01955 }
01956 }
01957
01958 void LLTexLayerParamAlpha::animate(F32 delta, BOOL set_by_user)
01959 {
01960 if (mNext)
01961 {
01962 mNext->animate(delta, set_by_user);
01963 }
01964 }
01965
01966 BOOL LLTexLayerParamAlpha::getSkip()
01967 {
01968 LLVOAvatar *avatar = mTexLayer->getTexLayerSet()->getAvatar();
01969
01970 if( getInfo()->mSkipIfZeroWeight )
01971 {
01972 F32 effective_weight = ( avatar->getSex() & getSex() ) ? mCurWeight : getDefaultWeight();
01973 if (is_approx_zero( effective_weight ))
01974 {
01975 return TRUE;
01976 }
01977 }
01978
01979 EWearableType type = (EWearableType)getWearableType();
01980 if( (type != WT_INVALID) && !avatar->isWearingWearableType( type ) )
01981 {
01982 return TRUE;
01983 }
01984
01985 return FALSE;
01986 }
01987
01988
01989 BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height )
01990 {
01991 BOOL success = TRUE;
01992
01993 F32 effective_weight = ( mTexLayer->getTexLayerSet()->getAvatar()->getSex() & getSex() ) ? mCurWeight : getDefaultWeight();
01994 BOOL weight_changed = effective_weight != mCachedEffectiveWeight;
01995 if( getSkip() )
01996 {
01997 return success;
01998 }
01999
02000 if( getInfo()->mMultiplyBlend )
02001 {
02002 glBlendFunc( GL_DST_ALPHA, GL_ZERO );
02003 }
02004 else
02005 {
02006 glBlendFunc( GL_ONE, GL_ONE );
02007 }
02008
02009 if( !getInfo()->mStaticImageFileName.empty() && !mStaticImageInvalid)
02010 {
02011 if( mStaticImageTGA.isNull() )
02012 {
02013
02014 mStaticImageTGA = gTexStaticImageList.getImageTGA( getInfo()->mStaticImageFileName );
02015
02016 LLTexLayerSet::sHasCaches |= mStaticImageTGA.notNull() ? TRUE : FALSE;
02017
02018 if( mStaticImageTGA.isNull() )
02019 {
02020 llwarns << "Unable to load static file: " << getInfo()->mStaticImageFileName << llendl;
02021 mStaticImageInvalid = TRUE;
02022 return FALSE;
02023 }
02024 }
02025
02026 const S32 image_tga_width = mStaticImageTGA->getWidth();
02027 const S32 image_tga_height = mStaticImageTGA->getHeight();
02028 if( !mCachedProcessedImageGL ||
02029 (mCachedProcessedImageGL->getWidth() != image_tga_width) ||
02030 (mCachedProcessedImageGL->getHeight() != image_tga_height) ||
02031 (weight_changed && !(gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))) )
02032 {
02033
02034 mCachedEffectiveWeight = effective_weight;
02035
02036 if( !mCachedProcessedImageGL )
02037 {
02038 mCachedProcessedImageGL = new LLImageGL( image_tga_width, image_tga_height, 1, FALSE);
02039
02040
02041 LLTexLayerSet::sHasCaches |= mCachedProcessedImageGL ? TRUE : FALSE;
02042
02043 if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))
02044 {
02045
02046 mCachedProcessedImageGL->setExplicitFormat( GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX );
02047 }
02048 else
02049 {
02050 mCachedProcessedImageGL->setExplicitFormat( GL_ALPHA8, GL_ALPHA );
02051 }
02052 }
02053
02054
02055 if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))
02056 {
02057 mStaticImageRaw = NULL;
02058 mStaticImageRaw = new LLImageRaw;
02059 mStaticImageTGA->decode(mStaticImageRaw);
02060 mNeedsCreateTexture = TRUE;
02061 }
02062 else
02063 {
02064 mStaticImageRaw = NULL;
02065 mStaticImageRaw = new LLImageRaw;
02066 mStaticImageTGA->decodeAndProcess( mStaticImageRaw, getInfo()->mDomain, effective_weight );
02067 mNeedsCreateTexture = TRUE;
02068 }
02069 }
02070
02071 if( mCachedProcessedImageGL )
02072 {
02073 {
02074 if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))
02075 {
02076 if( mNeedsCreateTexture )
02077 {
02078 mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw);
02079 mNeedsCreateTexture = FALSE;
02080
02081 mCachedProcessedImageGL->bind();
02082 mCachedProcessedImageGL->setClamp(TRUE, TRUE);
02083 }
02084
02085 LLGLSNoAlphaTest gls_no_alpha_test;
02086 mCachedProcessedImageGL->bind();
02087 gGradientPaletteList.setHardwarePalette( getInfo()->mDomain, effective_weight );
02088 gl_rect_2d_simple_tex( width, height );
02089 mCachedProcessedImageGL->unbindTexture(0, GL_TEXTURE_2D);
02090 }
02091 else
02092 {
02093
02094 if( mNeedsCreateTexture )
02095 {
02096 mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw);
02097 mNeedsCreateTexture = FALSE;
02098
02099 mCachedProcessedImageGL->bind();
02100 mCachedProcessedImageGL->setClamp(TRUE, TRUE);
02101 }
02102
02103 LLGLSNoAlphaTest gls_no_alpha_test;
02104 mCachedProcessedImageGL->bind();
02105 gl_rect_2d_simple_tex( width, height );
02106 mCachedProcessedImageGL->unbindTexture(0, GL_TEXTURE_2D);
02107 }
02108 stop_glerror();
02109 }
02110 }
02111
02112
02113
02114 if( !mTexLayer->getTexLayerSet()->getAvatar()->mIsSelf )
02115 {
02116 mCachedProcessedImageGL = NULL;
02117 }
02118 }
02119 else
02120 {
02121 LLGLSNoTextureNoAlphaTest gls_no_texture_no_alpha_test;
02122 glColor4f( 0.f, 0.f, 0.f, effective_weight );
02123 gl_rect_2d_simple( width, height );
02124 }
02125
02126 return success;
02127 }
02128
02129
02130
02131
02132
02133 LLTexGlobalColorInfo::LLTexGlobalColorInfo()
02134 {
02135 }
02136
02137
02138 LLTexGlobalColorInfo::~LLTexGlobalColorInfo()
02139 {
02140 for_each(mColorInfoList.begin(), mColorInfoList.end(), DeletePointer());
02141 }
02142
02143 BOOL LLTexGlobalColorInfo::parseXml(LLXmlTreeNode* node)
02144 {
02145
02146 static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
02147 if( !node->getFastAttributeString( name_string, mName ) )
02148 {
02149 llwarns << "<global_color> element is missing name attribute." << llendl;
02150 return FALSE;
02151 }
02152
02153 for (LLXmlTreeNode* child = node->getChildByName( "param" );
02154 child;
02155 child = node->getNextNamedChild())
02156 {
02157 if( child->getChildByName( "param_color" ) )
02158 {
02159
02160 LLTexParamColorInfo* info = new LLTexParamColorInfo();
02161 if (!info->parseXml(child))
02162 {
02163 delete info;
02164 return FALSE;
02165 }
02166 mColorInfoList.push_back( info );
02167 }
02168 }
02169 return TRUE;
02170 }
02171
02172
02173
02174
02175
02176 LLTexGlobalColor::LLTexGlobalColor( LLVOAvatar* avatar )
02177 :
02178 mAvatar( avatar ),
02179 mInfo( NULL )
02180 {
02181 }
02182
02183
02184 LLTexGlobalColor::~LLTexGlobalColor()
02185 {
02186
02187
02188 }
02189
02190 BOOL LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info)
02191 {
02192 llassert(mInfo == NULL);
02193 mInfo = info;
02194
02195
02196 LLTexGlobalColorInfo::color_info_list_t::iterator iter;
02197 mParamList.reserve(mInfo->mColorInfoList.size());
02198 for (iter = mInfo->mColorInfoList.begin(); iter != mInfo->mColorInfoList.end(); iter++)
02199 {
02200 LLTexParamColor* param_color = new LLTexParamColor( this );
02201 if (!param_color->setInfo(*iter))
02202 {
02203 mInfo = NULL;
02204 return FALSE;
02205 }
02206 mParamList.push_back( param_color );
02207 }
02208
02209 return TRUE;
02210 }
02211
02212
02213
02214 LLColor4 LLTexGlobalColor::getColor()
02215 {
02216
02217 if( !mParamList.empty() )
02218 {
02219 LLColor4 net_color( 0.f, 0.f, 0.f, 0.f );
02220
02221 for( param_list_t::iterator iter = mParamList.begin();
02222 iter != mParamList.end(); iter++ )
02223 {
02224 LLTexParamColor* param = *iter;
02225 LLColor4 param_net = param->getNetColor();
02226 switch( param->getOperation() )
02227 {
02228 case OP_ADD:
02229 net_color += param_net;
02230 break;
02231 case OP_MULTIPLY:
02232 net_color.mV[VX] *= param_net.mV[VX];
02233 net_color.mV[VY] *= param_net.mV[VY];
02234 net_color.mV[VZ] *= param_net.mV[VZ];
02235 net_color.mV[VW] *= param_net.mV[VW];
02236 break;
02237 case OP_BLEND:
02238 net_color = lerp(net_color, param_net, param->getWeight());
02239 break;
02240 default:
02241 llassert(0);
02242 break;
02243 }
02244 }
02245
02246 net_color.mV[VX] = llclampf( net_color.mV[VX] );
02247 net_color.mV[VY] = llclampf( net_color.mV[VY] );
02248 net_color.mV[VZ] = llclampf( net_color.mV[VZ] );
02249 net_color.mV[VW] = llclampf( net_color.mV[VW] );
02250
02251 return net_color;
02252 }
02253 return LLColor4( 1.f, 1.f, 1.f, 1.f );
02254 }
02255
02256
02257
02258
02259 LLTexParamColorInfo::LLTexParamColorInfo()
02260 :
02261 mOperation( OP_ADD ),
02262 mNumColors( 0 )
02263 {
02264 }
02265
02266 BOOL LLTexParamColorInfo::parseXml(LLXmlTreeNode *node)
02267 {
02268 llassert( node->hasName( "param" ) && node->getChildByName( "param_color" ) );
02269
02270 if (!LLViewerVisualParamInfo::parseXml(node))
02271 return FALSE;
02272
02273 LLXmlTreeNode* param_color_node = node->getChildByName( "param_color" );
02274 if( !param_color_node )
02275 {
02276 return FALSE;
02277 }
02278
02279 LLString op_string;
02280 static LLStdStringHandle operation_string = LLXmlTree::addAttributeString("operation");
02281 if( param_color_node->getFastAttributeString( operation_string, op_string ) )
02282 {
02283 LLString::toLower(op_string);
02284 if ( op_string == "add" ) mOperation = OP_ADD;
02285 else if ( op_string == "multiply" ) mOperation = OP_MULTIPLY;
02286 else if ( op_string == "blend" ) mOperation = OP_BLEND;
02287 }
02288
02289 mNumColors = 0;
02290
02291 LLColor4U color4u;
02292 for (LLXmlTreeNode* child = param_color_node->getChildByName( "value" );
02293 child;
02294 child = param_color_node->getNextNamedChild())
02295 {
02296 if( (mNumColors < MAX_COLOR_VALUES) )
02297 {
02298 static LLStdStringHandle color_string = LLXmlTree::addAttributeString("color");
02299 if( child->getFastAttributeColor4U( color_string, color4u ) )
02300 {
02301 mColors[ mNumColors ].setVec(color4u);
02302 mNumColors++;
02303 }
02304 }
02305 }
02306 if( !mNumColors )
02307 {
02308 llwarns << "<param_color> is missing <value> sub-elements" << llendl;
02309 return FALSE;
02310 }
02311
02312 if( (mOperation == OP_BLEND) && (mNumColors != 1) )
02313 {
02314 llwarns << "<param_color> with operation\"blend\" must have exactly one <value>" << llendl;
02315 return FALSE;
02316 }
02317
02318 return TRUE;
02319 }
02320
02321
02322
02323
02324 LLTexParamColor::LLTexParamColor( LLTexGlobalColor* tex_global_color )
02325 :
02326 mAvgDistortionVec(1.f, 1.f, 1.f),
02327 mTexGlobalColor( tex_global_color ),
02328 mTexLayer( NULL ),
02329 mAvatar( tex_global_color->getAvatar() )
02330 {
02331 }
02332
02333 LLTexParamColor::LLTexParamColor( LLTexLayer* layer )
02334 :
02335 mAvgDistortionVec(1.f, 1.f, 1.f),
02336 mTexGlobalColor( NULL ),
02337 mTexLayer( layer ),
02338 mAvatar( layer->getTexLayerSet()->getAvatar() )
02339 {
02340 }
02341
02342
02343 LLTexParamColor::~LLTexParamColor()
02344 {
02345 }
02346
02347
02348
02349
02350
02351 BOOL LLTexParamColor::setInfo(LLTexParamColorInfo *info)
02352 {
02353 llassert(mInfo == NULL);
02354 if (info->mID < 0)
02355 return FALSE;
02356 mID = info->mID;
02357 mInfo = info;
02358
02359 mAvatar->addVisualParam( this );
02360 setWeight( getDefaultWeight(), FALSE );
02361
02362 return TRUE;
02363 }
02364
02365 LLColor4 LLTexParamColor::getNetColor()
02366 {
02367 llassert( getInfo()->mNumColors >= 1 );
02368
02369 F32 effective_weight = ( mAvatar && (mAvatar->getSex() & getSex()) ) ? mCurWeight : getDefaultWeight();
02370
02371 S32 index_last = getInfo()->mNumColors - 1;
02372 F32 scaled_weight = effective_weight * index_last;
02373 S32 index_start = (S32) scaled_weight;
02374 S32 index_end = index_start + 1;
02375 if( index_start == index_last )
02376 {
02377 return getInfo()->mColors[index_last];
02378 }
02379 else
02380 {
02381 F32 weight = scaled_weight - index_start;
02382 const LLColor4 *start = &getInfo()->mColors[ index_start ];
02383 const LLColor4 *end = &getInfo()->mColors[ index_end ];
02384 return LLColor4(
02385 (1.f - weight) * start->mV[VX] + weight * end->mV[VX],
02386 (1.f - weight) * start->mV[VY] + weight * end->mV[VY],
02387 (1.f - weight) * start->mV[VZ] + weight * end->mV[VZ],
02388 (1.f - weight) * start->mV[VW] + weight * end->mV[VW] );
02389 }
02390 }
02391
02392 void LLTexParamColor::setWeight(F32 weight, BOOL set_by_user)
02393 {
02394 if (mIsAnimating)
02395 {
02396 return;
02397 }
02398 F32 min_weight = getMinWeight();
02399 F32 max_weight = getMaxWeight();
02400 F32 new_weight = llclamp(weight, min_weight, max_weight);
02401 U8 cur_u8 = F32_to_U8( mCurWeight, min_weight, max_weight );
02402 U8 new_u8 = F32_to_U8( new_weight, min_weight, max_weight );
02403 if( cur_u8 != new_u8)
02404 {
02405 mCurWeight = new_weight;
02406
02407 if( getInfo()->mNumColors <= 0 )
02408 {
02409
02410 return;
02411 }
02412
02413 if( mAvatar->getSex() & getSex() )
02414 {
02415 if( mTexGlobalColor )
02416 {
02417 mAvatar->onGlobalColorChanged( mTexGlobalColor, set_by_user );
02418 }
02419 else
02420 if( mTexLayer )
02421 {
02422 mAvatar->invalidateComposite( mTexLayer->getTexLayerSet(), set_by_user );
02423 }
02424 }
02425
02426 }
02427 }
02428
02429 void LLTexParamColor::setAnimationTarget(F32 target_value, BOOL set_by_user)
02430 {
02431
02432 mTargetWeight = target_value;
02433 setWeight(target_value, set_by_user);
02434 mIsAnimating = TRUE;
02435 if (mNext)
02436 {
02437 mNext->setAnimationTarget(target_value, set_by_user);
02438 }
02439 }
02440
02441 void LLTexParamColor::animate(F32 delta, BOOL set_by_user)
02442 {
02443 if (mNext)
02444 {
02445 mNext->animate(delta, set_by_user);
02446 }
02447 }
02448
02449
02450
02451
02452
02453
02454
02455 LLTexStaticImageList gTexStaticImageList;
02456 LLStringTable LLTexStaticImageList::sImageNames(16384);
02457
02458 LLTexStaticImageList::LLTexStaticImageList()
02459 :
02460 mGLBytes( 0 ),
02461 mTGABytes( 0 )
02462 {}
02463
02464 LLTexStaticImageList::~LLTexStaticImageList()
02465 {
02466 deleteCachedImages();
02467 }
02468
02469 void LLTexStaticImageList::dumpByteCount()
02470 {
02471 llinfos << "Avatar Static Textures " <<
02472 "KB GL:" << (mGLBytes / 1024) <<
02473 "KB TGA:" << (mTGABytes / 1024) << "KB" << llendl;
02474 }
02475
02476 void LLTexStaticImageList::deleteCachedImages()
02477 {
02478 if( mGLBytes || mTGABytes )
02479 {
02480 llinfos << "Clearing Static Textures " <<
02481 "KB GL:" << (mGLBytes / 1024) <<
02482 "KB TGA:" << (mTGABytes / 1024) << "KB" << llendl;
02483
02484
02485
02486 mStaticImageListTGA.clear();
02487 mStaticImageListGL.clear();
02488
02489 mGLBytes = 0;
02490 mTGABytes = 0;
02491 }
02492 }
02493
02494
02495
02496
02497
02498
02499
02500 LLImageTGA* LLTexStaticImageList::getImageTGA(const LLString& file_name)
02501 {
02502 const char *namekey = sImageNames.addString(file_name);
02503 image_tga_map_t::iterator iter = mStaticImageListTGA.find(namekey);
02504 if( iter != mStaticImageListTGA.end() )
02505 {
02506 return iter->second;
02507 }
02508 else
02509 {
02510 std::string path;
02511 path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name.c_str());
02512 LLPointer<LLImageTGA> image_tga = new LLImageTGA( path );
02513 if( image_tga->getDataSize() > 0 )
02514 {
02515 mStaticImageListTGA[ namekey ] = image_tga;
02516 mTGABytes += image_tga->getDataSize();
02517 return image_tga;
02518 }
02519 else
02520 {
02521 return NULL;
02522 }
02523 }
02524 }
02525
02526
02527
02528
02529
02530 LLImageGL* LLTexStaticImageList::getImageGL(const LLString& file_name, BOOL is_mask )
02531 {
02532 LLPointer<LLImageGL> image_gl;
02533 const char *namekey = sImageNames.addString(file_name);
02534
02535 image_gl_map_t::iterator iter = mStaticImageListGL.find(namekey);
02536 if( iter != mStaticImageListGL.end() )
02537 {
02538 image_gl = iter->second;
02539 }
02540 else
02541 {
02542 image_gl = new LLImageGL( FALSE );
02543 LLPointer<LLImageRaw> image_raw = new LLImageRaw;
02544 if( loadImageRaw( file_name, image_raw ) )
02545 {
02546 if( (image_raw->getComponents() == 1) && is_mask )
02547 {
02548
02549
02550 image_gl->setExplicitFormat( GL_ALPHA8, GL_ALPHA );
02551 }
02552 image_gl->createGLTexture(0, image_raw);
02553
02554 image_gl->bind();
02555 image_gl->setClamp(TRUE, TRUE);
02556
02557 mStaticImageListGL [ namekey ] = image_gl;
02558 mGLBytes += (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents();
02559 }
02560 else
02561 {
02562 image_gl = NULL;
02563 }
02564 }
02565
02566 return image_gl;
02567 }
02568
02569
02570
02571 BOOL LLTexStaticImageList::loadImageRaw( const LLString& file_name, LLImageRaw* image_raw )
02572 {
02573 BOOL success = FALSE;
02574 std::string path;
02575 path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name.c_str());
02576 LLPointer<LLImageTGA> image_tga = new LLImageTGA( path );
02577 if( image_tga->getDataSize() > 0 )
02578 {
02579
02580 success = image_tga->decode( image_raw );
02581 }
02582
02583 return success;
02584 }
02585
02586
02587
02588
02589 LLMaskedMorph::LLMaskedMorph( LLPolyMorphTarget *morph_target, BOOL invert ) : mMorphTarget(morph_target), mInvert(invert)
02590 {
02591 morph_target->addPendingMorphMask();
02592 }
02593
02594
02595
02596
02597
02598
02599 LLGradientPaletteList::~LLGradientPaletteList()
02600 {
02601
02602 for( palette_map_t::iterator iter = mPaletteMap.begin();
02603 iter != mPaletteMap.end(); iter++ )
02604 {
02605 U8* data = iter->second;
02606 delete []data;
02607 }
02608 }
02609
02610 void LLGradientPaletteList::initPalette(F32 domain)
02611 {
02612 palette_map_t::iterator iter = mPaletteMap.find( domain );
02613 if( iter == mPaletteMap.end() )
02614 {
02615 U8 *palette = new U8[512 * 4];
02616 mPaletteMap[domain] = palette;
02617 S32 ramp_start = 255 - llfloor(domain * 255.f);
02618 S32 ramp_end = 255;
02619 F32 ramp_factor = (ramp_end == ramp_start) ? 0.f : (255.f / ((F32)ramp_end - (F32)ramp_start));
02620
02621
02622
02623 for (S32 i = 0; i < 512; i++)
02624 {
02625 palette[(i * 4) + 1] = 0;
02626 palette[(i * 4) + 2] = 0;
02627 if (i <= ramp_start)
02628 {
02629 palette[(i * 4)] = 0;
02630 palette[(i * 4) + 3] = 0;
02631 }
02632 else if (i < ramp_end)
02633 {
02634 palette[(i * 4)] = llfloor(((F32)i - (F32)ramp_start) * ramp_factor);
02635 palette[(i * 4) + 3] = llfloor(((F32)i - (F32)ramp_start) * ramp_factor);
02636 }
02637 else
02638 {
02639 palette[(i * 4)] = 255;
02640 palette[(i * 4) + 3] = 255;
02641 }
02642 }
02643 }
02644 }
02645
02646 void LLGradientPaletteList::setHardwarePalette( F32 domain, F32 effective_weight )
02647 {
02648 palette_map_t::iterator iter = mPaletteMap.find( domain );
02649 if( iter != mPaletteMap.end() )
02650 {
02651 U8* palette = iter->second;
02652 set_palette( palette + llfloor(effective_weight * (255.f * (1.f - domain))) * 4);
02653 }
02654 else
02655 {
02656 llwarns << "LLGradientPaletteList::setHardwarePalette() missing domain " << domain << llendl;
02657 }
02658 }