From f8dc23fc84e624845181315bbadcbdc1f804c628 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Wed, 17 Mar 2010 12:39:39 -0600 Subject: fix for EXT-6093: crash at LLTextureCache::updateTextureEntryList[secondlife-bin lltexturecache.cpp:847]; EXT-5711: Some textures loading from cache seems jammed; EXT-5599: Viewer crashes consistently, in Linden Homes region. --- indra/newview/lltexturecache.cpp | 268 +++++++++++++++++++++++---------------- indra/newview/lltexturecache.h | 10 +- 2 files changed, 169 insertions(+), 109 deletions(-) (limited to 'indra') diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 49770030c6..48207dfd4d 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -550,7 +550,7 @@ bool LLTextureCacheRemoteWorker::doWrite() S32 cur_imagesize = 0; // Checks if this image is already in the entry list idx = mCache->getHeaderCacheEntry(mID, cur_imagesize); - if (idx >= 0 && (cur_imagesize >= 0)) + if (idx >= 0 && (cur_imagesize > 0)) { alreadyCached = true; // already there and non empty } @@ -846,9 +846,8 @@ bool LLTextureCache::updateTextureEntryList(const LLUUID& id, S32 bodysize) S32 idx = openAndReadEntry(id, entry, false); if (idx < 0) { - llwarns << "Failed to open entry: " << id << llendl; - removeHeaderCacheEntry(id); - LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool()); + llwarns << "Failed to open entry: " << id << llendl; + removeCachedTexture(id) ; return false; } else if (oldbodysize != entry.mBodySize) @@ -857,11 +856,7 @@ bool LLTextureCache::updateTextureEntryList(const LLUUID& id, S32 bodysize) llerrs << "Entry mismatch in mTextureSizeMap / mHeaderIDMap" << " idx=" << idx << " oldsize=" << oldbodysize << " entrysize=" << entry.mBodySize << llendl; } - entry.mBodySize = bodysize; - writeEntryAndClose(idx, entry); - - mTexturesSizeTotal -= oldbodysize; - mTexturesSizeTotal += bodysize; + updateEntry(idx, entry, entry.mImageSize, bodysize); if (mTexturesSizeTotal > sCacheMaxTexturesSize) { @@ -1002,7 +997,10 @@ LLAPRFile* LLTextureCache::openHeaderEntriesFile(bool readonly, S32 offset) llassert_always(mHeaderAPRFile == NULL); apr_int32_t flags = readonly ? APR_READ|APR_BINARY : APR_READ|APR_WRITE|APR_BINARY; mHeaderAPRFile = new LLAPRFile(mHeaderEntriesFileName, flags, getLocalAPRFilePool()); - mHeaderAPRFile->seek(APR_SET, offset); + if(offset > 0) + { + mHeaderAPRFile->seek(APR_SET, offset); + } return mHeaderAPRFile; } @@ -1034,8 +1032,7 @@ void LLTextureCache::writeEntriesHeader() } } -static S32 mHeaderEntriesMaxWriteIdx = 0; - +//mHeaderMutex is locked before calling this. S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create) { S32 idx = -1; @@ -1075,8 +1072,7 @@ S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create if (iter3 != mHeaderIDMap.end() && iter3->second >= 0) { idx = iter3->second; - mHeaderIDMap.erase(oldid); - mTexturesSizeMap.erase(oldid); + removeCachedTexture(oldid) ;//remove the existing cached texture to release the entry index. break; } } @@ -1086,22 +1082,9 @@ S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create } if (idx >= 0) { - // Set the header index - mHeaderIDMap[id] = idx; - llassert_always(mTexturesSizeMap.erase(id) == 0); - // Initialize the entry (will get written later) - entry.init(id, time(NULL)); - // Update Header - writeEntriesHeader(); - - //the new entry, write immediately. - // Write Entry - S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); - LLAPRFile* aprfile = openHeaderEntriesFile(false, offset); - S32 bytes_written = aprfile->write((void*)&entry, (S32)sizeof(Entry)); - llassert_always(bytes_written == sizeof(Entry)); - mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, idx); - closeHeaderEntriesFile(); + entry.mID = id ; + entry.mImageSize = -1 ; //mark it is a brand-new entry. + entry.mBodySize = 0 ; } } } @@ -1117,36 +1100,108 @@ S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create } else { - S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); - LLAPRFile* aprfile = openHeaderEntriesFile(true, offset); - S32 bytes_read = aprfile->read((void*)&entry, (S32)sizeof(Entry)); - llassert_always(bytes_read == sizeof(Entry)); - closeHeaderEntriesFile(); + readEntryFromHeaderImmediately(idx, entry) ; } - llassert_always(entry.mImageSize == 0 || entry.mImageSize == -1 || entry.mImageSize > entry.mBodySize); + llassert_always(entry.mImageSize > entry.mBodySize); } return idx; } -void LLTextureCache::writeEntryAndClose(S32 idx, Entry& entry) +//mHeaderMutex is locked before calling this. +void LLTextureCache::writeEntryToHeaderImmediately(S32 idx, Entry& entry, bool write_header) +{ + LLAPRFile* aprfile ; + S32 bytes_written ; + S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); + if(write_header) + { + aprfile = openHeaderEntriesFile(false, 0); + bytes_written = aprfile->write((U8*)&mHeaderEntriesInfo, sizeof(EntriesInfo)) ; + llassert_always(bytes_written == sizeof(EntriesInfo)); + mHeaderAPRFile->seek(APR_SET, offset); + } + else + { + aprfile = openHeaderEntriesFile(false, offset); + } + bytes_written = aprfile->write((void*)&entry, (S32)sizeof(Entry)); + llassert_always(bytes_written == sizeof(Entry)); + closeHeaderEntriesFile(); + mUpdatedEntryMap.erase(idx) ; +} + +//mHeaderMutex is locked before calling this. +void LLTextureCache::readEntryFromHeaderImmediately(S32 idx, Entry& entry) +{ + S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); + LLAPRFile* aprfile = openHeaderEntriesFile(true, offset); + S32 bytes_read = aprfile->read((void*)&entry, (S32)sizeof(Entry)); + llassert_always(bytes_read == sizeof(Entry)); + closeHeaderEntriesFile(); +} + +//mHeaderMutex is locked before calling this. +//update an existing entry time stamp, delay writing. +void LLTextureCache::updateEntryTimeStamp(S32 idx, Entry& entry) { + static const U32 MAX_ENTRIES_WITHOUT_TIME_STAMP = (U32)LLTextureCache::sCacheMaxEntries * 0.75f ; + + if(mHeaderEntriesInfo.mEntries < MAX_ENTRIES_WITHOUT_TIME_STAMP) + { + return ; //there are enough empty entry index space, no need to stamp time. + } + if (idx >= 0) { if (!mReadOnly) { - entry.mTime = time(NULL); - llassert_always(entry.mImageSize == 0 || entry.mImageSize == -1 || entry.mImageSize > entry.mBodySize); - if (entry.mBodySize > 0) + llassert_always(entry.mImageSize > entry.mBodySize); + + entry.mTime = time(NULL); + mUpdatedEntryMap[idx] = entry ; + } + } +} + +//mHeaderMutex is locked before calling this. +//update an existing entry, write to header file immediately. +void LLTextureCache::updateEntry(S32 idx, Entry& entry, S32 new_image_size, S32 new_body_size) +{ + llassert_always(new_image_size > -1) ; + + if(new_image_size == entry.mImageSize && new_body_size == entry.mBodySize) + { + updateEntryTimeStamp(idx, entry) ; //nothing changed. + } + else if (idx >= 0) + { + if (!mReadOnly) + { + llassert_always(new_image_size > new_body_size) ; + + bool update_header = false ; + if(entry.mImageSize < 0) //is a brand-new entry { - mTexturesSizeMap[entry.mID] = entry.mBodySize; - } - else if(mTexturesSizeMap.find(entry.mID) != mTexturesSizeMap.end() && mTexturesSizeMap[entry.mID] > 0) + mHeaderIDMap[entry.mID] = idx; + mTexturesSizeMap[entry.mID] = new_body_size ; + mTexturesSizeTotal += new_body_size ; + + // Update Header + update_header = true ; + } + else if (entry.mBodySize != new_body_size) { - llerrs << "mTexturesSizeMap / mHeaderIDMap corrupted." << llendl ; + //already in mHeaderIDMap. + mTexturesSizeMap[entry.mID] = new_body_size ; + mTexturesSizeTotal -= entry.mBodySize ; + mTexturesSizeTotal += new_body_size ; } -// llinfos << "Updating TE: " << idx << ": " << id << " Size: " << entry.mBodySize << " Time: " << entry.mTime << llendl; - mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, idx); - mUpdatedEntryMap[idx] = entry ; + entry.mTime = time(NULL); + entry.mImageSize = new_image_size ; + entry.mBodySize = new_body_size ; + +// llinfos << "Updating TE: " << idx << ": " << id << " Size: " << entry.mBodySize << " Time: " << entry.mTime << llendl; + writeEntryToHeaderImmediately(idx, entry, update_header) ; } } } @@ -1160,8 +1215,9 @@ U32 LLTextureCache::openAndReadEntries(std::vector& entries) mFreeList.clear(); mTexturesSizeTotal = 0; - LLAPRFile* aprfile = openHeaderEntriesFile(false, (S32)sizeof(EntriesInfo)); + LLAPRFile* aprfile = openHeaderEntriesFile(true, 0); updatedHeaderEntriesFile() ; + aprfile->seek(APR_SET, (S32)sizeof(EntriesInfo)); for (U32 idx=0; idx& entries) } entries.push_back(entry); // llinfos << "ENTRY: " << entry.mTime << " TEX: " << entry.mID << " IDX: " << idx << " Size: " << entry.mImageSize << llendl; - if (entry.mImageSize < 0) + if(entry.mImageSize > entry.mBodySize) { - mFreeList.insert(idx); + mHeaderIDMap[entry.mID] = idx; + mTexturesSizeMap[entry.mID] = entry.mBodySize; + mTexturesSizeTotal += entry.mBodySize; } else { - mHeaderIDMap[entry.mID] = idx; - if (entry.mBodySize > 0) - { - mTexturesSizeMap[entry.mID] = entry.mBodySize; - mTexturesSizeTotal += entry.mBodySize; - } - llassert_always(entry.mImageSize == 0 || entry.mImageSize > entry.mBodySize); + mFreeList.insert(idx); } } closeHeaderEntriesFile(); @@ -1207,7 +1259,6 @@ void LLTextureCache::writeEntriesAndClose(const std::vector& entries) S32 bytes_written = aprfile->write((void*)(&entries[idx]), (S32)sizeof(Entry)); llassert_always(bytes_written == sizeof(Entry)); } - mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, num_entries-1); closeHeaderEntriesFile(); } } @@ -1280,12 +1331,11 @@ void LLTextureCache::readHeaderCache() U32 empty_entries = 0; typedef std::pair lru_data_t; std::set lru; - std::set purge_list; + std::set purge_list; for (U32 i=0; i entry.mImageSize) { // Shouldn't happen, failsafe only - llwarns << "Bad entry: " << i << ": " << id << ": BodySize: " << entry.mBodySize << llendl; - purge_list.insert(entry.mID); - entry.mImageSize = -1; // empty/available + llwarns << "Bad entry: " << i << ": " << entry.mID << ": BodySize: " << entry.mBodySize << llendl; + purge_list.insert(i); } } } @@ -1315,14 +1364,9 @@ void LLTextureCache::readHeaderCache() { for (std::set::iterator iter = lru.begin(); iter != lru.end(); ++iter) { - S32 idx = iter->second; - if (entries[idx].mImageSize >= 0) - { - purge_list.insert(entries[idx].mID); - entries[idx].mImageSize = -1; - if (purge_list.size() >= entries_to_purge) - break; - } + purge_list.insert(iter->second); + if (purge_list.size() >= entries_to_purge) + break; } } llassert_always(purge_list.size() >= entries_to_purge); @@ -1332,9 +1376,7 @@ void LLTextureCache::readHeaderCache() S32 lru_entries = (S32)((F32)sCacheMaxEntries * TEXTURE_CACHE_LRU_SIZE); for (std::set::iterator iter = lru.begin(); iter != lru.end(); ++iter) { - S32 idx = iter->second; - const LLUUID& id = entries[idx].mID; - mLRU.insert(id); + mLRU.insert(entries[iter->second].mID); // llinfos << "LRU: " << iter->first << " : " << iter->second << llendl; if (--lru_entries <= 0) break; @@ -1343,12 +1385,9 @@ void LLTextureCache::readHeaderCache() if (purge_list.size() > 0) { - for (std::set::iterator iter = purge_list.begin(); iter != purge_list.end(); ++iter) + for (std::set::iterator iter = purge_list.begin(); iter != purge_list.end(); ++iter) { - const LLUUID& id = *iter; - bool res = removeHeaderCacheEntry(id); // sets entry size on disk to -1 - llassert_always(res); - LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool()); + removeEntry(*iter, entries[*iter], getTextureFileName(entries[*iter].mID)); } // If we removed any entries, we need to rebuild the entries list, // write the header, and call this again @@ -1356,13 +1395,14 @@ void LLTextureCache::readHeaderCache() for (U32 i=0; i=0) + if (entry.mImageSize > 0) { new_entries.push_back(entry); } } llassert_always(new_entries.size() <= sCacheMaxEntries); mHeaderEntriesInfo.mEntries = new_entries.size(); + writeEntriesHeader(); writeEntriesAndClose(new_entries); mHeaderMutex.unlock(); // unlock the mutex before calling again readHeaderCache(); // repeat with new entries file @@ -1370,7 +1410,7 @@ void LLTextureCache::readHeaderCache() } else { - writeEntriesAndClose(entries); + //entries are not changed, nothing here. } } } @@ -1435,7 +1475,6 @@ void LLTextureCache::purgeTextures(bool validate) U32 num_entries = openAndReadEntries(entries); if (!num_entries) { - writeEntriesAndClose(entries); return; // nothing to purge } @@ -1509,11 +1548,8 @@ void LLTextureCache::purgeTextures(bool validate) { purge_count++; LL_DEBUGS("TextureCache") << "PURGING: " << filename << LL_ENDL; - LLAPRFile::remove(filename, getLocalAPRFilePool()); + removeEntry(idx, entries[idx], filename) ; cache_size -= entries[idx].mBodySize; - mTexturesSizeTotal -= entries[idx].mBodySize; - entries[idx].mBodySize = 0; - mTexturesSizeMap.erase(entries[idx].mID); } } @@ -1568,7 +1604,7 @@ S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, S32& imagesize) if (idx >= 0) { imagesize = entry.mImageSize; - writeEntryAndClose(idx, entry); // updates time + updateEntryTimeStamp(idx, entry); // updates time } return idx; } @@ -1582,8 +1618,7 @@ S32 LLTextureCache::setHeaderCacheEntry(const LLUUID& id, S32 imagesize) S32 idx = openAndReadEntry(id, entry, true); if (idx >= 0) { - entry.mImageSize = imagesize; - writeEntryAndClose(idx, entry); + updateEntry(idx, entry, imagesize, entry.mBodySize); mHeaderMutex.unlock(); } else // retry @@ -1722,34 +1757,55 @@ void LLTextureCache::addCompleted(Responder* responder, bool success) ////////////////////////////////////////////////////////////////////////////// -// Called from MAIN thread (endWork()) -// Ensure that mHeaderMutex is locked first! -bool LLTextureCache::removeHeaderCacheEntry(const LLUUID& id) +//called after mHeaderMutex is locked. +void LLTextureCache::removeCachedTexture(const LLUUID& id) { - Entry entry; - S32 idx = openAndReadEntry(id, entry, false); - if (idx >= 0) + if(mTexturesSizeMap.find(id) != mTexturesSizeMap.end()) + { + mTexturesSizeTotal -= mTexturesSizeMap[id] ; + mTexturesSizeMap.erase(id); + } + mHeaderIDMap.erase(id); + LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool()); +} + +//called after mHeaderMutex is locked. +void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename) +{ + if(idx >= 0) //valid entry { entry.mImageSize = -1; entry.mBodySize = 0; - writeEntryAndClose(idx, entry); - mFreeList.insert(idx); - mHeaderIDMap.erase(id); - mTexturesSizeMap.erase(id); - return true; + mHeaderIDMap.erase(entry.mID); + mTexturesSizeMap.erase(entry.mID); + + mTexturesSizeTotal -= entry.mBodySize; + mFreeList.insert(idx); } - return false; + + LLAPRFile::remove(filename, getLocalAPRFilePool()); } -void LLTextureCache::removeFromCache(const LLUUID& id) +bool LLTextureCache::removeFromCache(const LLUUID& id) { //llwarns << "Removing texture from cache: " << id << llendl; + bool ret = false ; if (!mReadOnly) { - LLMutexLock lock(&mHeaderMutex); - removeHeaderCacheEntry(id); - LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool()); + lockHeaders() ; + + Entry entry; + S32 idx = openAndReadEntry(id, entry, false); + removeEntry(idx, entry, getTextureFileName(id)) ; + if (idx >= 0) + { + writeEntryToHeaderImmediately(idx, entry); + ret = true; + } + + unlockHeaders() ; } + return ret ; } ////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h index b840619c1f..ca8815ee7e 100644 --- a/indra/newview/lltexturecache.h +++ b/indra/newview/lltexturecache.h @@ -123,7 +123,7 @@ public: bool writeComplete(handle_t handle, bool abort = false); void prioritizeWrite(handle_t handle); - void removeFromCache(const LLUUID& id); + bool removeFromCache(const LLUUID& id); // For LLTextureCacheWorker::Responder LLTextureCacheWorker* getReader(handle_t handle); @@ -161,12 +161,16 @@ private: void readEntriesHeader(); void writeEntriesHeader(); S32 openAndReadEntry(const LLUUID& id, Entry& entry, bool create); - void writeEntryAndClose(S32 idx, Entry& entry); + void updateEntry(S32 idx, Entry& entry, S32 new_image_size, S32 new_body_size); + void updateEntryTimeStamp(S32 idx, Entry& entry) ; U32 openAndReadEntries(std::vector& entries); void writeEntriesAndClose(const std::vector& entries); + void readEntryFromHeaderImmediately(S32 idx, Entry& entry) ; + void writeEntryToHeaderImmediately(S32 idx, Entry& entry, bool write_header = false) ; + void removeEntry(S32 idx, Entry& entry, std::string& filename); + void removeCachedTexture(const LLUUID& id) ; S32 getHeaderCacheEntry(const LLUUID& id, S32& imagesize); S32 setHeaderCacheEntry(const LLUUID& id, S32 imagesize); - bool removeHeaderCacheEntry(const LLUUID& id); void writeUpdatedEntries() ; void updatedHeaderEntriesFile() ; void lockHeaders() { mHeaderMutex.lock(); } -- cgit v1.2.3 From 8e1f7ecaf3b1eebc1ca60ecb6e04412f39083d82 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Wed, 17 Mar 2010 14:43:17 -0600 Subject: more for lltexturecache.cpp: fix the crash due to deleting the entries header file after clearing the texture cache. --- indra/newview/lltexturecache.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'indra') diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 48207dfd4d..54ac3850fd 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -1020,6 +1020,12 @@ void LLTextureCache::readEntriesHeader() LLAPRFile::readEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), getLocalAPRFilePool()); } + else //create an empty entries header. + { + mHeaderEntriesInfo.mVersion = sHeaderCacheVersion ; + mHeaderEntriesInfo.mEntries = 0 ; + writeEntriesHeader() ; + } } void LLTextureCache::writeEntriesHeader() @@ -1438,6 +1444,7 @@ void LLTextureCache::purgeAllTextures(bool purge_directories) } if (purge_directories) { + gDirUtilp->deleteFilesInDir(mTexturesDirName,mask); LLFile::rmdir(mTexturesDirName); } } -- cgit v1.2.3 From 896b88063ed0e08362c9e277e7ef8aba5afef0db Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Wed, 17 Mar 2010 17:55:12 -0400 Subject: EXT-6252 : "Duplicate items (not links) in inventory are both displayed in bold as (worn) when only one is actually worn" Simple special-case fix for this specific issue, although I added a comment to llwearablelist.h that eventually the whole LLWearableList class will need some redesign. Core issue is that you can have multiple itemIDs pointing to the same assetID and LLWearableList doesn't account for this possibility during lookup-wearable-by-assetID operations. --- indra/newview/llagentwearables.cpp | 12 +++++++++++- indra/newview/llwearablelist.h | 6 ++++++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index ea10917901..65503d4998 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1702,6 +1702,16 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it LLWearable* old_wearable = getWearable(type, 0); if (old_wearable) { + // Special case where you're putting on a wearable that has the same assetID + // as the previous (e.g. wear a shirt then wear a copy of that shirt) since in this + // case old_wearable == new_wearable. + if (old_wearable == new_wearable) + { + old_wearable->setLabelUpdated(); + new_wearable->setName(new_item->getName()); + new_wearable->setItemID(new_item->getUUID()); + } + const LLUUID& old_item_id = getWearableItemID(type, 0); if ((old_wearable->getAssetID() == new_wearable->getAssetID()) && (old_item_id == new_item->getUUID())) @@ -1717,7 +1727,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it continue; } } - + new_wearable->setItemID(new_item->getUUID()); setWearable(type,0,new_wearable); } diff --git a/indra/newview/llwearablelist.h b/indra/newview/llwearablelist.h index cf1a9bddff..5e564ba953 100644 --- a/indra/newview/llwearablelist.h +++ b/indra/newview/llwearablelist.h @@ -39,6 +39,12 @@ #include "llassetstorage.h" // Globally constructed; be careful that there's no dependency with gAgent. +/* + BUG: mList's system of mapping between assetIDs and wearables is flawed + since LLWearable* has an associated itemID, and you can have multiple + inventory items pointing to the same asset (i.e. more than one ItemID + per assetID). EXT-6252 +*/ class LLWearableList : public LLSingleton { public: -- cgit v1.2.3 From 56ccf4d0befca4c98d1d13f757b515bde1d3e262 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Wed, 17 Mar 2010 16:41:28 -0600 Subject: fix for EXT-6420: crash at LLImageRaw::LLImageRaw [secondlife-bin llimage.cpp:271] --- indra/newview/llviewertexture.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 133b6ee8c9..dbbf0219c9 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -2262,11 +2262,14 @@ void LLViewerFetchedTexture::destroyRawImage() { sRawCount--; - if(mForceToSaveRawImage) + if(mIsRawImageValid) { - saveRawImage() ; - } - setCachedRawImage() ; + if(mForceToSaveRawImage) + { + saveRawImage() ; + } + setCachedRawImage() ; + } } mRawImage = NULL; -- cgit v1.2.3 From d9c64d221353cf4bfc1fffa69f3fc083e76f3b4c Mon Sep 17 00:00:00 2001 From: Richard Nelson Date: Wed, 17 Mar 2010 18:19:31 -0700 Subject: fix for radio item not being selected after picking internal browser reviewed by Callum --- indra/newview/skins/default/xui/en/panel_preferences_setup.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index a2b15a2b87..15f8b33f5b 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -273,7 +273,7 @@ layout="topleft" left="0" name="internal" - value="0" + value="" tool_tip="Use the built-in web browser for help, web links, etc. This browser opens as a new window inside [APP_NAME]." top="0" width="480" /> @@ -283,7 +283,7 @@ layout="topleft" left_delta="0" name="external" - value="1" + value="true" tool_tip="Use the default system web browser for help, web links, etc. Not recommended if running full screen." top_delta="20" width="480" /> -- cgit v1.2.3 From a3a4235a8904cf4d6e565c82d5d90d8a64c15180 Mon Sep 17 00:00:00 2001 From: Kent Quirk Date: Thu, 18 Mar 2010 09:22:34 -0400 Subject: EXT-6321 -- clicking on an event in the main map now invokes the event details floater instead of trying to do a search for the event. --- indra/newview/llworldmapview.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 5edf72d4ae..27757d19e5 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -45,6 +45,7 @@ #include "llagent.h" #include "llcallingcard.h" +#include "llcommandhandler.h" #include "llviewercontrol.h" #include "llfloatermap.h" #include "llfloaterworldmap.h" @@ -1726,7 +1727,10 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask ) id.toString(uuid_str); uuid_str = uuid_str.substr(28); sscanf(uuid_str.c_str(), "%X", &event_id); - LLFloaterReg::showInstance("search", LLSD().with("category", "events").with("id", event_id)); + // Invoke the event details floater if someone is clicking on an event. + LLSD params(LLSD::emptyArray()); + params.append(event_id); + LLCommandDispatcher::dispatch("event", params, LLSD(), NULL, true); break; } case MAP_ITEM_LAND_FOR_SALE: -- cgit v1.2.3