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

Generated on Thu Jul 1 06:09:16 2010 for Second Life Viewer by  doxygen 1.4.7