lltexlayer.cpp

Go to the documentation of this file.
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 //#include "../tools/imdebug/imdebug.h"
00058 
00059 
00060 // SJB: We really always want to use the GL cache;
00061 // let GL page textures in and out of video RAM instead of trying to do so by hand.
00062 
00063 LLGradientPaletteList gGradientPaletteList;
00064 
00065 // static
00066 S32 LLTexLayerSetBuffer::sGLByteCount = 0;
00067 S32 LLTexLayerSetBuffer::sGLBumpByteCount = 0;
00068 
00069 //-----------------------------------------------------------------------------
00070 // LLBakedUploadData()
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 // LLTexLayerSetBuffer
00089 // The composite image that a LLTexLayerSet writes to.  Each LLTexLayerSet has one.
00090 //-----------------------------------------------------------------------------
00091 LLTexLayerSetBuffer::LLTexLayerSetBuffer( LLTexLayerSet* owner, S32 width, S32 height, BOOL has_bump )
00092         :
00093         // ORDER_LAST => must render these after the hints are created.
00094         LLDynamicTexture( width, height, 4, LLDynamicTexture::ORDER_LAST, TRUE ), 
00095         mNeedsUpdate( TRUE ),
00096         mNeedsUpload( FALSE ),
00097         mUploadPending( FALSE ), // Not used for any logic here, just to sync sending of updates
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 // static
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         // If we're in the middle of uploading a baked texture, we don't care about it any more.
00155         // When it's downloaded, ignore it.
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                         // we were trying to create a skirt texture
00209                         // but we're no longer wearing a skirt...
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         // Set up an ortho projection
00225         pushProjection();
00226         
00227         // keep depth buffer, we don't need to clear it
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         // do we need to upload, and do we have sufficient data to create an uploadable composite?
00243         // When do we upload the texture if gAgent.mNumPendingQueries is non-zero?
00244         BOOL upload_now = (gAgent.mNumPendingQueries == 0 && mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal());
00245         BOOL success = TRUE;
00246 
00247         // Composite bump
00248         if( mBumpTexName )
00249         {
00250                 // Composite the bump data
00251                 success &= mTexLayerSet->renderBump( mOrigin.mX, mOrigin.mY, mWidth, mHeight );
00252                 stop_glerror();
00253 
00254                 if (success)
00255                 {
00256                         LLGLSUIDefault gls_ui;
00257 
00258                         // read back into texture (this is done externally for the color data)
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                         // if we need to upload the data, read it back into a buffer
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         // Composite the color data
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         // reset GL state
00295         glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
00296         gGL.blendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );  
00297 
00298         // we have valid texture data now
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         // pointers for storing data to upload
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         // We won't need our caches since we're baked now.  (Techically, we won't 
00334         // really be baked until this image is sent to the server and the Avatar
00335         // Appearance message is received.)
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 //      imdebug("lum b=8 w=%d h=%d %p", mWidth, mHeight, baked_mask_data);
00345 
00346 
00347         // writes into baked_color_data
00348         const char* comment_text = NULL;
00349 
00350         S32 baked_image_components = mBumpTexName ? 5 : 4; // red green blue [bump] clothing
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"; // 5 channels: rgb, heightfield/alpha, mask
00357 
00358                 // Hide the alpha for the eyelashes in a corner of the bump map
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];  // Use alpha, not bump
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); // integrity_test will delete 'data'
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,         // temp_file
00463                                                                                           FALSE,        // is_priority
00464                                                                                           TRUE);        // store_local
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 // static
00489 void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, void* userdata, S32 result, LLExtStat ext_status) // StoreAssetData callback (not fixed)
00490 {
00491         LLBakedUploadData* baked_upload_data = (LLBakedUploadData*)userdata;
00492 
00493         LLVOAvatar* avatar = gAgent.getAvatarObject();
00494 
00495         if (0 == result && avatar && !avatar->isDead())
00496         {
00497                 // Sanity check: only the user's avatar should be uploading textures.
00498                 if( baked_upload_data->mAvatar == avatar )
00499                 {
00500                         // Because the avatar is still valid, it's layerset buffers should be valid also.
00501                         LLTexLayerSetBuffer* layerset_buffer = baked_upload_data->mLayerSetBuffer;
00502                         layerset_buffer->mUploadPending = FALSE;
00503                         
00504                         if (layerset_buffer->mUploadID.isNull())
00505                         {
00506                                 // The upload got canceled, we should be in the process of baking a new texture
00507                                 // so request an upload with the new data
00508                                 layerset_buffer->requestUpload();
00509                         }
00510                         else if( baked_upload_data->mID == layerset_buffer->mUploadID )
00511                         {
00512                                 // This is the upload we're currently waiting for.
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                                         // *FIX: retry upload after n seconds, asset server could be busy
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                 // Baked texture failed to upload, but since we didn't set the new baked texture, it means that they'll
00544                 // try and rebake it at some point in the future (after login?)
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 // LLTexLayerSet
00585 // An ordered set of texture layers that get composited into a single texture.
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         // body_region
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         // width, height
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         // Optional alpha component to apply after all compositing is complete.
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         // <layer>
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 // LLTexLayerSet
00656 // An ordered set of texture layers that get composited into a single texture.
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 // setInfo
00679 //-----------------------------------------------------------------------------
00680 
00681 BOOL LLTexLayerSet::setInfo(LLTexLayerSetInfo *info)
00682 {
00683         llassert(mInfo == NULL);
00684         mInfo = info;
00685         //mID = info->mID; // No ID
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 // parseData
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 // Returns TRUE if at least one packet of data has been received for each of the textures that this layerset depends on.
00740 BOOL LLTexLayerSet::isLocalTextureDataAvailable()
00741 {
00742         return mAvatar->isLocalTextureDataAvailable( this );
00743 }
00744 
00745 
00746 // Returns TRUE if all of the data for the textures that this layerset depends on have arrived.
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         // composite color layers
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         // (Optionally) replace alpha with a single component image from a tga file.
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                 // Set the alpha channel to one (clean up after previous blending)
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         //static S32 bump_layer_count = 1;
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         // Set the alpha channel to one (clean up after previous blending)
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                 // Composite other avatars at reduced resolution
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 // LLTexLayerInfo
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         // name attribute
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         // Note: layers can have either a "global_color" attrib, a "fixed_color" attrib, or a <param_color> child.
01001         // global color attribute (optional)
01002         static LLStdStringHandle global_color_string = LLXmlTree::addAttributeString("global_color");
01003         node->getFastAttributeString( global_color_string, mGlobalColor );
01004 
01005         // color attribute (optional)
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                 // <texture> optional sub-element
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         // <param> optional sub-element (color or alpha params)
01116         for (LLXmlTreeNode* child = node->getChildByName( "param" );
01117                  child;
01118                  child = node->getNextNamedChild())
01119         {
01120                 if( child->getChildByName( "param_color" ) )
01121                 {
01122                         // <param><param_color/></param>
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                         // <param><param_alpha/></param>
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 // LLTexLayer
01149 // A single texture layer, consisting of:
01150 //              * color, consisting of either
01151 //                      * one or more color parameters (weighted colors)
01152 //                      * a reference to a global color
01153 //                      * a fixed color with non-zero alpha
01154 //                      * opaque white (the default)
01155 //              * (optional) a texture defined by either
01156 //                      * a GUID
01157 //                      * a texture entry index (TE)
01158 //              * (optional) one or more alpha parameters (weighted alpha textures)
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         // mParamAlphaList and mParamColorList are LLViewerVisualParam's and get
01172         // deleted with ~LLCharacter()
01173         //std::for_each(mParamAlphaList.begin(), mParamAlphaList.end(), DeletePointer());
01174         //std::for_each(mParamColorList.begin(), mParamColorList.end(), DeletePointer());
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 // setInfo
01186 //-----------------------------------------------------------------------------
01187 
01188 BOOL LLTexLayer::setInfo(LLTexLayerInfo* info)
01189 {
01190         llassert(mInfo == NULL);
01191         mInfo = info;
01192         //mID = info->mID; // No ID
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                         // *FIX: we assume that the referenced visual param is a
01202                         // morph target, need a better way of actually looking
01203                         // this up.
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 // parseData
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         // If you can't see the layer, don't render it.
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                 // If we have alpha masks, but we're skipping all of them, skip the whole layer.
01306                 // However, we can't do this optimization if we have morph masks that need updating.
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                 // Restore standard blend func value
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*)&param_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         // Color is either:
01437         //      * one or more color parameters (weighted colors)  (which may make use of a global color or fixed color)
01438         //      * a reference to a global color
01439         //      * a fixed color with non-zero alpha
01440         //      * opaque white (the default)
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; // No need to draw a separate colored polygon
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         // Note: if the first param is a mulitply, multiply against the current buffer's alpha
01515         if( !first_param || !first_param->getMultiplyBlend() )
01516         {
01517                 LLGLSNoTextureNoAlphaTest gls_no_texture_no_alpha_test;
01518         
01519                 // Clear the alpha
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         // Accumulate alphas
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         // Approximates a min() function
01538         gGL.flush();
01539         gGL.blendFunc( GL_DST_ALPHA, GL_ZERO );
01540 
01541         // Accumulate the alpha component of the texture
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         // Draw a rectangle with the layer color to multiply the alpha by that color's alpha.
01593         // Note: we're still using gGL.blendFunc( GL_DST_ALPHA, GL_ZERO );
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*)&param_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                         // clear out a slot if we have filled our cache
01630                         S32 max_cache_entries = getTexLayerSet()->getAvatar()->mIsSelf ? 4 : 1;
01631                         while ((S32)mAlphaCache.size() >= max_cache_entries)
01632                         {
01633                                 iter2 = mAlphaCache.begin(); // arbitrarily grab the first entry
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 // Returns TRUE on success.
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 // LLTexLayerParamAlphaInfo
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                 // Don't load the image file until it's actually needed.
01784         }
01785 //      else
01786 //      {
01787 //              llwarns << "<param_alpha> element is missing tga_file attribute." << llendl;
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 // LLTexLayerParamAlpha
01806 //-----------------------------------------------------------------------------
01807 
01808 // static 
01809 LLTexLayerParamAlpha::param_alpha_ptr_list_t LLTexLayerParamAlpha::sInstances;
01810 
01811 // static 
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 // static 
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 // setInfo()
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; // deletes image
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 ); // Multiplication: approximates a min() function
01967         }
01968         else
01969         {
01970                 gGL.blendFunc( GL_ONE, GL_ONE );  // Addition: approximates a max() function
01971         }
01972 
01973         if( !getInfo()->mStaticImageFileName.empty() && !mStaticImageInvalid)
01974         {
01975                 if( mStaticImageTGA.isNull() )
01976                 {
01977                         // Don't load the image file until we actually need it the first time.  Like now.
01978                         mStaticImageTGA = gTexStaticImageList.getImageTGA( getInfo()->mStaticImageFileName );  
01979                         // We now have something in one of our caches
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; // don't try again.
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 //                      llinfos << "Building Cached Alpha: " << mName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << effective_weight << llendl;
01998                         mCachedEffectiveWeight = effective_weight;
01999 
02000                         if( !mCachedProcessedImageGL )
02001                         {
02002                                 mCachedProcessedImageGL = new LLImageGL( image_tga_width, image_tga_height, 1, FALSE);
02003 
02004                                 // We now have something in one of our caches
02005                                 LLTexLayerSet::sHasCaches |= mCachedProcessedImageGL ? TRUE : FALSE;
02006 
02007                                 if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))
02008                                 {
02009                                         // interpret luminance values as color index table
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                         // Applies domain and effective weight to data as it is decoded. Also resizes the raw image if needed.
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                                         // Create the GL texture, and then hang onto it for future use.
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                 // Don't keep the cache for other people's avatars
02077                 // (It's not really a "cache" in that case, but the logic is the same)
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 // LLTexGlobalColorInfo
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         // name attribute
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         // <param> sub-element
02117         for (LLXmlTreeNode* child = node->getChildByName( "param" );
02118                  child;
02119                  child = node->getNextNamedChild())
02120         {
02121                 if( child->getChildByName( "param_color" ) )
02122                 {
02123                         // <param><param_color/></param>
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 // LLTexGlobalColor
02138 //-----------------------------------------------------------------------------
02139 
02140 LLTexGlobalColor::LLTexGlobalColor( LLVOAvatar* avatar )
02141         :
02142         mAvatar( avatar ),
02143         mInfo( NULL )
02144 {
02145 }
02146 
02147 
02148 LLTexGlobalColor::~LLTexGlobalColor()
02149 {
02150         // mParamList are LLViewerVisualParam's and get deleted with ~LLCharacter()
02151         //std::for_each(mParamList.begin(), mParamList.end(), DeletePointer());
02152 }
02153 
02154 BOOL LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info)
02155 {
02156         llassert(mInfo == NULL);
02157         mInfo = info;
02158         //mID = info->mID; // No ID
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         // Sum of color params
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 // LLTexParamColorInfo
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 // LLTexParamColor
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 // setInfo()
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                         // This will happen when we set the default weight the first time.
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 //              llinfos << "param " << mName << " = " << new_weight << llendl;
02390         }
02391 }
02392 
02393 void LLTexParamColor::setAnimationTarget(F32 target_value, BOOL set_by_user)
02394 { 
02395         // set value first then set interpolating flag to ignore further updates
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 // LLTexStaticImageList
02416 //-----------------------------------------------------------------------------
02417 
02418 // static
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                 //mStaticImageLists uses LLPointers, clear() will cause deletion
02449                 
02450                 mStaticImageListTGA.clear();
02451                 mStaticImageListGL.clear();
02452                 
02453                 mGLBytes = 0;
02454                 mTGABytes = 0;
02455         }
02456 }
02457 
02458 // Note: in general, for a given image image we'll call either getImageTga() or getImageGL().
02459 // We call getImageTga() if the image is used as an alpha gradient.
02460 // Otherwise, we call getImageGL()
02461 
02462 // Returns an LLImageTGA that contains the encoded data from a tga file named file_name.
02463 // Caches the result to speed identical subsequent requests.
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 // Returns a GL Image (without a backing ImageRaw) that contains the decoded data from a tga file named file_name.
02493 // Caches the result to speed identical subsequent requests.
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                                 // Note: these are static, unchanging images so it's ok to assume
02513                                 // that once an image is a mask it's always a mask.
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 // Reads a .tga file, decodes it, and puts the decoded data in image_raw.
02534 // Returns TRUE if successful.
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                 // Copy data from tga to raw.
02544                 success = image_tga->decode( image_raw );
02545         }
02546 
02547         return success;
02548 }
02549 
02550 //-----------------------------------------------------------------------------
02551 // LLMaskedMorph()
02552 //-----------------------------------------------------------------------------
02553 LLMaskedMorph::LLMaskedMorph( LLPolyMorphTarget *morph_target, BOOL invert ) : mMorphTarget(morph_target), mInvert(invert)
02554 {
02555         morph_target->addPendingMorphMask();
02556 }
02557 
02558 
02559 //-----------------------------------------------------------------------------
02560 // LLGradientPaletteList
02561 //-----------------------------------------------------------------------------
02562 
02563 LLGradientPaletteList::~LLGradientPaletteList()
02564 {
02565         // Note: can't just call deleteAllData() because the data values are arrays.
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                 // *TODO: move conditionals outside of loop, since this really
02586                 // is just a sequential process.
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 }

Generated on Fri May 16 08:34:03 2008 for SecondLife by  doxygen 1.5.5