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