diff options
Diffstat (limited to 'indra')
93 files changed, 705 insertions, 2496 deletions
diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index 2cf86bb4fe..3f2fcce429 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -1577,7 +1577,12 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC } alpha_data = new U8[width * height]; mAlphaCache[cache_index] = alpha_data; - glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data); + + // nSight doesn't support use of glReadPixels + if (!LLRender::sNsightDebugSupport) + { + glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data); + } } getTexLayerSet()->getAvatarAppearance()->dirtyMesh(); diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index 049e962638..b3debf3550 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -57,10 +57,6 @@ U32Kilobytes LLMemory::sAllocatedPageSizeInKB(0); U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX); BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE; -#if __DEBUG_PRIVATE_MEM__ -LLPrivateMemoryPoolManager::mem_allocation_info_t LLPrivateMemoryPoolManager::sMemAllocationTracker; -#endif - void ll_assert_aligned_func(uintptr_t ptr,U32 alignment) { #if defined(LL_WINDOWS) && defined(LL_DEBUG_BUFFER_OVERRUN) @@ -154,17 +150,12 @@ void LLMemory::logMemoryInfo(BOOL update) if(update) { updateMemoryInfo() ; - LLPrivateMemoryPoolManager::getInstance()->updateStatistics() ; } LL_INFOS() << "Current allocated physical memory(KB): " << sAllocatedMemInKB << LL_ENDL ; LL_INFOS() << "Current allocated page size (KB): " << sAllocatedPageSizeInKB << LL_ENDL ; LL_INFOS() << "Current available physical memory(KB): " << sAvailPhysicalMemInKB << LL_ENDL ; LL_INFOS() << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << LL_ENDL ; - - LL_INFOS() << "--- private pool information -- " << LL_ENDL ; - LL_INFOS() << "Total reserved (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalReservedSize / 1024 << LL_ENDL ; - LL_INFOS() << "Total allocated (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalAllocatedSize / 1024 << LL_ENDL ; } //return 0: everything is normal; @@ -356,1729 +347,6 @@ U64 LLMemory::getCurrentRSS() #endif -//-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- -//minimum slot size and minimal slot size interval -const U32 ATOMIC_MEM_SLOT = 16 ; //bytes - -//minimum block sizes (page size) for small allocation, medium allocation, large allocation -const U32 MIN_BLOCK_SIZES[LLPrivateMemoryPool::SUPER_ALLOCATION] = {2 << 10, 4 << 10, 16 << 10} ; // - -//maximum block sizes for small allocation, medium allocation, large allocation -const U32 MAX_BLOCK_SIZES[LLPrivateMemoryPool::SUPER_ALLOCATION] = {64 << 10, 1 << 20, 4 << 20} ; - -//minimum slot sizes for small allocation, medium allocation, large allocation -const U32 MIN_SLOT_SIZES[LLPrivateMemoryPool::SUPER_ALLOCATION] = {ATOMIC_MEM_SLOT, 2 << 10, 512 << 10}; - -//maximum slot sizes for small allocation, medium allocation, large allocation -const U32 MAX_SLOT_SIZES[LLPrivateMemoryPool::SUPER_ALLOCATION] = {(2 << 10) - ATOMIC_MEM_SLOT, (512 - 2) << 10, 4 << 20}; - -//size of a block with multiple slots can not exceed CUT_OFF_SIZE -const U32 CUT_OFF_SIZE = (64 << 10) ; //64 KB - -//max number of slots in a block -const U32 MAX_NUM_SLOTS_IN_A_BLOCK = llmin(MIN_BLOCK_SIZES[0] / ATOMIC_MEM_SLOT, ATOMIC_MEM_SLOT * 8) ; - -//------------------------------------------------------------- -//align val to be integer times of ATOMIC_MEM_SLOT -U32 align(U32 val) -{ - U32 aligned = (val / ATOMIC_MEM_SLOT) * ATOMIC_MEM_SLOT ; - if(aligned < val) - { - aligned += ATOMIC_MEM_SLOT ; - } - - return aligned ; -} - -//------------------------------------------------------------- -//class LLPrivateMemoryPool::LLMemoryBlock -//------------------------------------------------------------- -// -//each memory block could fit for two page sizes: 0.75 * mSlotSize, which starts from the beginning of the memory chunk and grow towards the end of the -//the block; another is mSlotSize, which starts from the end of the block and grows towards the beginning of the block. -// -LLPrivateMemoryPool::LLMemoryBlock::LLMemoryBlock() -{ - //empty -} - -LLPrivateMemoryPool::LLMemoryBlock::~LLMemoryBlock() -{ - //empty -} - -//create and initialize a memory block -void LLPrivateMemoryPool::LLMemoryBlock::init(char* buffer, U32 buffer_size, U32 slot_size) -{ - mBuffer = buffer ; - mBufferSize = buffer_size ; - mSlotSize = slot_size ; - mTotalSlots = buffer_size / mSlotSize ; - - llassert_always(buffer_size / mSlotSize <= MAX_NUM_SLOTS_IN_A_BLOCK) ; //max number is 128 - - mAllocatedSlots = 0 ; - mDummySize = 0 ; - - //init the bit map. - //mark free bits - if(mTotalSlots > 32) //reserve extra space from mBuffer to store bitmap if needed. - { - mDummySize = ATOMIC_MEM_SLOT ; - mTotalSlots -= (mDummySize + mSlotSize - 1) / mSlotSize ; - mUsageBits = 0 ; - - S32 usage_bit_len = (mTotalSlots + 31) / 32 ; - - for(S32 i = 0 ; i < usage_bit_len - 1 ; i++) - { - *((U32*)mBuffer + i) = 0 ; - } - for(S32 i = usage_bit_len - 1 ; i < mDummySize / sizeof(U32) ; i++) - { - *((U32*)mBuffer + i) = 0xffffffff ; - } - - if(mTotalSlots & 31) - { - *((U32*)mBuffer + usage_bit_len - 2) = (0xffffffff << (mTotalSlots & 31)) ; - } - } - else//no extra bitmap space reserved - { - mUsageBits = 0 ; - if(mTotalSlots & 31) - { - mUsageBits = (0xffffffff << (mTotalSlots & 31)) ; - } - } - - mSelf = this ; - mNext = NULL ; - mPrev = NULL ; - - llassert_always(mTotalSlots > 0) ; -} - -//mark this block to be free with the memory [mBuffer, mBuffer + mBufferSize). -void LLPrivateMemoryPool::LLMemoryBlock::setBuffer(char* buffer, U32 buffer_size) -{ - mBuffer = buffer ; - mBufferSize = buffer_size ; - mSelf = NULL ; - mTotalSlots = 0 ; //set the block is free. -} - -//reserve a slot -char* LLPrivateMemoryPool::LLMemoryBlock::allocate() -{ - llassert_always(mAllocatedSlots < mTotalSlots) ; - - //find a free slot - U32* bits = NULL ; - U32 k = 0 ; - if(mUsageBits != 0xffffffff) - { - bits = &mUsageBits ; - } - else if(mDummySize > 0)//go to extra space - { - for(S32 i = 0 ; i < mDummySize / sizeof(U32); i++) - { - if(*((U32*)mBuffer + i) != 0xffffffff) - { - bits = (U32*)mBuffer + i ; - k = i + 1 ; - break ; - } - } - } - S32 idx = 0 ; - U32 tmp = *bits ; - for(; tmp & 1 ; tmp >>= 1, idx++) ; - - //set the slot reserved - if(!idx) - { - *bits |= 1 ; - } - else - { - *bits |= (1 << idx) ; - } - - mAllocatedSlots++ ; - - return mBuffer + mDummySize + (k * 32 + idx) * mSlotSize ; -} - -//free a slot -void LLPrivateMemoryPool::LLMemoryBlock::freeMem(void* addr) -{ - //bit index - uintptr_t idx = ((uintptr_t)addr - (uintptr_t)mBuffer - mDummySize) / mSlotSize ; - - U32* bits = &mUsageBits ; - if(idx >= 32) - { - bits = (U32*)mBuffer + (idx - 32) / 32 ; - } - - //reset the bit - if(idx & 31) - { - *bits &= ~(1 << (idx & 31)) ; - } - else - { - *bits &= ~1 ; - } - - mAllocatedSlots-- ; -} - -//for debug use: reset the entire bitmap. -void LLPrivateMemoryPool::LLMemoryBlock::resetBitMap() -{ - for(S32 i = 0 ; i < mDummySize / sizeof(U32) ; i++) - { - *((U32*)mBuffer + i) = 0 ; - } - mUsageBits = 0 ; -} -//------------------------------------------------------------------- -//class LLMemoryChunk -//-------------------------------------------------------------------- -LLPrivateMemoryPool::LLMemoryChunk::LLMemoryChunk() -{ - //empty -} - -LLPrivateMemoryPool::LLMemoryChunk::~LLMemoryChunk() -{ - //empty -} - -//create and init a memory chunk -void LLPrivateMemoryPool::LLMemoryChunk::init(char* buffer, U32 buffer_size, U32 min_slot_size, U32 max_slot_size, U32 min_block_size, U32 max_block_size) -{ - mBuffer = buffer ; - mBufferSize = buffer_size ; - mAlloatedSize = 0 ; - - mMetaBuffer = mBuffer + sizeof(LLMemoryChunk) ; - - mMinBlockSize = min_block_size; //page size - mMinSlotSize = min_slot_size; - mMaxSlotSize = max_slot_size ; - mBlockLevels = mMaxSlotSize / mMinSlotSize ; - mPartitionLevels = max_block_size / mMinBlockSize + 1 ; - - S32 max_num_blocks = (buffer_size - sizeof(LLMemoryChunk) - mBlockLevels * sizeof(LLMemoryBlock*) - mPartitionLevels * sizeof(LLMemoryBlock*)) / - (mMinBlockSize + sizeof(LLMemoryBlock)) ; - //meta data space - mBlocks = (LLMemoryBlock*)mMetaBuffer ; //space reserved for all memory blocks. - mAvailBlockList = (LLMemoryBlock**)((char*)mBlocks + sizeof(LLMemoryBlock) * max_num_blocks) ; - mFreeSpaceList = (LLMemoryBlock**)((char*)mAvailBlockList + sizeof(LLMemoryBlock*) * mBlockLevels) ; - - //data buffer, which can be used for allocation - mDataBuffer = (char*)mFreeSpaceList + sizeof(LLMemoryBlock*) * mPartitionLevels ; - - //alignmnet - mDataBuffer = mBuffer + align(mDataBuffer - mBuffer) ; - - //init - for(U32 i = 0 ; i < mBlockLevels; i++) - { - mAvailBlockList[i] = NULL ; - } - for(U32 i = 0 ; i < mPartitionLevels ; i++) - { - mFreeSpaceList[i] = NULL ; - } - - //assign the entire chunk to the first block - mBlocks[0].mPrev = NULL ; - mBlocks[0].mNext = NULL ; - mBlocks[0].setBuffer(mDataBuffer, buffer_size - (mDataBuffer - mBuffer)) ; - addToFreeSpace(&mBlocks[0]) ; - - mNext = NULL ; - mPrev = NULL ; -} - -//static -U32 LLPrivateMemoryPool::LLMemoryChunk::getMaxOverhead(U32 data_buffer_size, U32 min_slot_size, - U32 max_slot_size, U32 min_block_size, U32 max_block_size) -{ - //for large allocations, reserve some extra memory for meta data to avoid wasting much - if(data_buffer_size / min_slot_size < 64) //large allocations - { - U32 overhead = sizeof(LLMemoryChunk) + (data_buffer_size / min_block_size) * sizeof(LLMemoryBlock) + - sizeof(LLMemoryBlock*) * (max_slot_size / min_slot_size) + sizeof(LLMemoryBlock*) * (max_block_size / min_block_size + 1) ; - - //round to integer times of min_block_size - overhead = ((overhead + min_block_size - 1) / min_block_size) * min_block_size ; - return overhead ; - } - else - { - return 0 ; //do not reserve extra overhead if for small allocations - } -} - -char* LLPrivateMemoryPool::LLMemoryChunk::allocate(U32 size) -{ - if(mMinSlotSize > size) - { - size = mMinSlotSize ; - } - if(mAlloatedSize + size > mBufferSize - (mDataBuffer - mBuffer)) - { - return NULL ; //no enough space in this chunk. - } - - char* p = NULL ; - U32 blk_idx = getBlockLevel(size); - - LLMemoryBlock* blk = NULL ; - - //check if there is free block available - if(mAvailBlockList[blk_idx]) - { - blk = mAvailBlockList[blk_idx] ; - p = blk->allocate() ; - - if(blk->isFull()) - { - popAvailBlockList(blk_idx) ; - } - } - - //ask for a new block - if(!p) - { - blk = addBlock(blk_idx) ; - if(blk) - { - p = blk->allocate() ; - - if(blk->isFull()) - { - popAvailBlockList(blk_idx) ; - } - } - } - - //ask for space from larger blocks - if(!p) - { - for(S32 i = blk_idx + 1 ; i < mBlockLevels; i++) - { - if(mAvailBlockList[i]) - { - blk = mAvailBlockList[i] ; - p = blk->allocate() ; - - if(blk->isFull()) - { - popAvailBlockList(i) ; - } - break ; - } - } - } - - if(p && blk) - { - mAlloatedSize += blk->getSlotSize() ; - } - return p ; -} - -void LLPrivateMemoryPool::LLMemoryChunk::freeMem(void* addr) -{ - U32 blk_idx = getPageIndex((uintptr_t)addr) ; - LLMemoryBlock* blk = (LLMemoryBlock*)(mMetaBuffer + blk_idx * sizeof(LLMemoryBlock)) ; - blk = blk->mSelf ; - - bool was_full = blk->isFull() ; - blk->freeMem(addr) ; - mAlloatedSize -= blk->getSlotSize() ; - - if(blk->empty()) - { - removeBlock(blk) ; - } - else if(was_full) - { - addToAvailBlockList(blk) ; - } -} - -bool LLPrivateMemoryPool::LLMemoryChunk::empty() -{ - return !mAlloatedSize ; -} - -bool LLPrivateMemoryPool::LLMemoryChunk::containsAddress(const char* addr) const -{ - return (uintptr_t)mBuffer <= (uintptr_t)addr && (uintptr_t)mBuffer + mBufferSize > (uintptr_t)addr ; -} - -//debug use -void LLPrivateMemoryPool::LLMemoryChunk::dump() -{ -#if 0 - //sanity check - //for(S32 i = 0 ; i < mBlockLevels ; i++) - //{ - // LLMemoryBlock* blk = mAvailBlockList[i] ; - // while(blk) - // { - // blk_list.push_back(blk) ; - // blk = blk->mNext ; - // } - //} - for(S32 i = 0 ; i < mPartitionLevels ; i++) - { - LLMemoryBlock* blk = mFreeSpaceList[i] ; - while(blk) - { - blk_list.push_back(blk) ; - blk = blk->mNext ; - } - } - - std::sort(blk_list.begin(), blk_list.end(), LLMemoryBlock::CompareAddress()); - - U32 total_size = blk_list[0]->getBufferSize() ; - for(U32 i = 1 ; i < blk_list.size(); i++) - { - total_size += blk_list[i]->getBufferSize() ; - if((uintptr_t)blk_list[i]->getBuffer() < (uintptr_t)blk_list[i-1]->getBuffer() + blk_list[i-1]->getBufferSize()) - { - LL_ERRS() << "buffer corrupted." << LL_ENDL ; - } - } - - llassert_always(total_size + mMinBlockSize >= mBufferSize - ((uintptr_t)mDataBuffer - (uintptr_t)mBuffer)) ; - - U32 blk_num = (mBufferSize - (mDataBuffer - mBuffer)) / mMinBlockSize ; - for(U32 i = 0 ; i < blk_num ; ) - { - LLMemoryBlock* blk = &mBlocks[i] ; - if(blk->mSelf) - { - U32 end = blk->getBufferSize() / mMinBlockSize ; - for(U32 j = 0 ; j < end ; j++) - { - llassert_always(blk->mSelf == blk || !blk->mSelf) ; - } - i += end ; - } - else - { - LL_ERRS() << "gap happens" << LL_ENDL ; - } - } -#endif -#if 0 - LL_INFOS() << "---------------------------" << LL_ENDL ; - LL_INFOS() << "Chunk buffer: " << (uintptr_t)getBuffer() << " size: " << getBufferSize() << LL_ENDL ; - - LL_INFOS() << "available blocks ... " << LL_ENDL ; - for(S32 i = 0 ; i < mBlockLevels ; i++) - { - LLMemoryBlock* blk = mAvailBlockList[i] ; - while(blk) - { - LL_INFOS() << "blk buffer " << (uintptr_t)blk->getBuffer() << " size: " << blk->getBufferSize() << LL_ENDL ; - blk = blk->mNext ; - } - } - - LL_INFOS() << "free blocks ... " << LL_ENDL ; - for(S32 i = 0 ; i < mPartitionLevels ; i++) - { - LLMemoryBlock* blk = mFreeSpaceList[i] ; - while(blk) - { - LL_INFOS() << "blk buffer " << (uintptr_t)blk->getBuffer() << " size: " << blk->getBufferSize() << LL_ENDL ; - blk = blk->mNext ; - } - } -#endif -} - -//compute the size for a block, the size is round to integer times of mMinBlockSize. -U32 LLPrivateMemoryPool::LLMemoryChunk::calcBlockSize(U32 slot_size) -{ - // - //Note: we try to make a block to have 32 slots if the size is not over 32 pages - //32 is the number of bits of an integer in a 32-bit system - // - - U32 block_size; - U32 cut_off_size = llmin(CUT_OFF_SIZE, (U32)(mMinBlockSize << 5)) ; - - if((slot_size << 5) <= mMinBlockSize)//for small allocations, return one page - { - block_size = mMinBlockSize ; - } - else if(slot_size >= cut_off_size)//for large allocations, return one-slot block - { - block_size = (slot_size / mMinBlockSize) * mMinBlockSize ; - if(block_size < slot_size) - { - block_size += mMinBlockSize ; - } - } - else //medium allocations - { - if((slot_size << 5) >= cut_off_size) - { - block_size = cut_off_size ; - } - else - { - block_size = ((slot_size << 5) / mMinBlockSize) * mMinBlockSize ; - } - } - - llassert_always(block_size >= slot_size) ; - - return block_size ; -} - -//create a new block in the chunk -LLPrivateMemoryPool::LLMemoryBlock* LLPrivateMemoryPool::LLMemoryChunk::addBlock(U32 blk_idx) -{ - U32 slot_size = mMinSlotSize * (blk_idx + 1) ; - U32 preferred_block_size = calcBlockSize(slot_size) ; - U16 idx = getPageLevel(preferred_block_size); - LLMemoryBlock* blk = NULL ; - - if(mFreeSpaceList[idx])//if there is free slot for blk_idx - { - blk = createNewBlock(mFreeSpaceList[idx], preferred_block_size, slot_size, blk_idx) ; - } - else if(mFreeSpaceList[mPartitionLevels - 1]) //search free pool - { - blk = createNewBlock(mFreeSpaceList[mPartitionLevels - 1], preferred_block_size, slot_size, blk_idx) ; - } - else //search for other non-preferred but enough space slot. - { - S32 min_idx = 0 ; - if(slot_size > mMinBlockSize) - { - min_idx = getPageLevel(slot_size) ; - } - for(S32 i = (S32)idx - 1 ; i >= min_idx ; i--) //search the small slots first - { - if(mFreeSpaceList[i]) - { - U32 new_preferred_block_size = mFreeSpaceList[i]->getBufferSize(); - new_preferred_block_size = (new_preferred_block_size / mMinBlockSize) * mMinBlockSize ; //round to integer times of mMinBlockSize. - - //create a NEW BLOCK THERE. - if(new_preferred_block_size >= slot_size) //at least there is space for one slot. - { - - blk = createNewBlock(mFreeSpaceList[i], new_preferred_block_size, slot_size, blk_idx) ; - } - break ; - } - } - - if(!blk) - { - for(U16 i = idx + 1 ; i < mPartitionLevels - 1; i++) //search the large slots - { - if(mFreeSpaceList[i]) - { - //create a NEW BLOCK THERE. - blk = createNewBlock(mFreeSpaceList[i], preferred_block_size, slot_size, blk_idx) ; - break ; - } - } - } - } - - return blk ; -} - -//create a new block at the designed location -LLPrivateMemoryPool::LLMemoryBlock* LLPrivateMemoryPool::LLMemoryChunk::createNewBlock(LLMemoryBlock* blk, U32 buffer_size, U32 slot_size, U32 blk_idx) -{ - //unlink from the free space - removeFromFreeSpace(blk) ; - - //check the rest space - U32 new_free_blk_size = blk->getBufferSize() - buffer_size ; - if(new_free_blk_size < mMinBlockSize) //can not partition the memory into size smaller than mMinBlockSize - { - new_free_blk_size = 0 ; //discard the last small extra space. - } - - //add the rest space back to the free list - if(new_free_blk_size > 0) //blk still has free space - { - LLMemoryBlock* next_blk = blk + (buffer_size / mMinBlockSize) ; - next_blk->mPrev = NULL ; - next_blk->mNext = NULL ; - next_blk->setBuffer(blk->getBuffer() + buffer_size, new_free_blk_size) ; - addToFreeSpace(next_blk) ; - } - - blk->init(blk->getBuffer(), buffer_size, slot_size) ; - //insert to the available block list... - mAvailBlockList[blk_idx] = blk ; - - //mark the address map: all blocks covered by this block space pointing back to this block. - U32 end = (buffer_size / mMinBlockSize) ; - for(U32 i = 1 ; i < end ; i++) - { - (blk + i)->mSelf = blk ; - } - - return blk ; -} - -//delete a block, release the block to the free pool. -void LLPrivateMemoryPool::LLMemoryChunk::removeBlock(LLMemoryBlock* blk) -{ - //remove from the available block list - if(blk->mPrev) - { - blk->mPrev->mNext = blk->mNext ; - } - if(blk->mNext) - { - blk->mNext->mPrev = blk->mPrev ; - } - U32 blk_idx = getBlockLevel(blk->getSlotSize()); - if(mAvailBlockList[blk_idx] == blk) - { - mAvailBlockList[blk_idx] = blk->mNext ; - } - - blk->mNext = NULL ; - blk->mPrev = NULL ; - - //mark it free - blk->setBuffer(blk->getBuffer(), blk->getBufferSize()) ; - -#if 1 - //merge blk with neighbors if possible - if(blk->getBuffer() > mDataBuffer) //has the left neighbor - { - if((blk - 1)->mSelf->isFree()) - { - LLMemoryBlock* left_blk = (blk - 1)->mSelf ; - removeFromFreeSpace((blk - 1)->mSelf); - left_blk->setBuffer(left_blk->getBuffer(), left_blk->getBufferSize() + blk->getBufferSize()) ; - blk = left_blk ; - } - } - if(blk->getBuffer() + blk->getBufferSize() <= mBuffer + mBufferSize - mMinBlockSize) //has the right neighbor - { - U32 d = blk->getBufferSize() / mMinBlockSize ; - if((blk + d)->isFree()) - { - LLMemoryBlock* right_blk = blk + d ; - removeFromFreeSpace(blk + d) ; - blk->setBuffer(blk->getBuffer(), blk->getBufferSize() + right_blk->getBufferSize()) ; - } - } -#endif - - addToFreeSpace(blk) ; - - return ; -} - -//the top block in the list is full, pop it out of the list -void LLPrivateMemoryPool::LLMemoryChunk::popAvailBlockList(U32 blk_idx) -{ - if(mAvailBlockList[blk_idx]) - { - LLMemoryBlock* next = mAvailBlockList[blk_idx]->mNext ; - if(next) - { - next->mPrev = NULL ; - } - mAvailBlockList[blk_idx]->mPrev = NULL ; - mAvailBlockList[blk_idx]->mNext = NULL ; - mAvailBlockList[blk_idx] = next ; - } -} - -//add the block back to the free pool -void LLPrivateMemoryPool::LLMemoryChunk::addToFreeSpace(LLMemoryBlock* blk) -{ - llassert_always(!blk->mPrev) ; - llassert_always(!blk->mNext) ; - - U16 free_idx = blk->getBufferSize() / mMinBlockSize - 1; - - (blk + free_idx)->mSelf = blk ; //mark the end pointing back to the head. - free_idx = llmin(free_idx, (U16)(mPartitionLevels - 1)) ; - - blk->mNext = mFreeSpaceList[free_idx] ; - if(mFreeSpaceList[free_idx]) - { - mFreeSpaceList[free_idx]->mPrev = blk ; - } - mFreeSpaceList[free_idx] = blk ; - blk->mPrev = NULL ; - blk->mSelf = blk ; - - return ; -} - -//remove the space from the free pool -void LLPrivateMemoryPool::LLMemoryChunk::removeFromFreeSpace(LLMemoryBlock* blk) -{ - U16 free_idx = blk->getBufferSize() / mMinBlockSize - 1; - free_idx = llmin(free_idx, (U16)(mPartitionLevels - 1)) ; - - if(mFreeSpaceList[free_idx] == blk) - { - mFreeSpaceList[free_idx] = blk->mNext ; - } - if(blk->mPrev) - { - blk->mPrev->mNext = blk->mNext ; - } - if(blk->mNext) - { - blk->mNext->mPrev = blk->mPrev ; - } - blk->mNext = NULL ; - blk->mPrev = NULL ; - blk->mSelf = NULL ; - - return ; -} - -void LLPrivateMemoryPool::LLMemoryChunk::addToAvailBlockList(LLMemoryBlock* blk) -{ - llassert_always(!blk->mPrev) ; - llassert_always(!blk->mNext) ; - - U32 blk_idx = getBlockLevel(blk->getSlotSize()); - - blk->mNext = mAvailBlockList[blk_idx] ; - if(blk->mNext) - { - blk->mNext->mPrev = blk ; - } - blk->mPrev = NULL ; - mAvailBlockList[blk_idx] = blk ; - - return ; -} - -U32 LLPrivateMemoryPool::LLMemoryChunk::getPageIndex(uintptr_t addr) -{ - return (addr - (uintptr_t)mDataBuffer) / mMinBlockSize ; -} - -//for mAvailBlockList -U32 LLPrivateMemoryPool::LLMemoryChunk::getBlockLevel(U32 size) -{ - llassert(size >= mMinSlotSize && size <= mMaxSlotSize) ; - - //start from 0 - return (size + mMinSlotSize - 1) / mMinSlotSize - 1 ; -} - -//for mFreeSpaceList -U16 LLPrivateMemoryPool::LLMemoryChunk::getPageLevel(U32 size) -{ - //start from 0 - U16 level = size / mMinBlockSize - 1 ; - if(level >= mPartitionLevels) - { - level = mPartitionLevels - 1 ; - } - return level ; -} - -//------------------------------------------------------------------- -//class LLPrivateMemoryPool -//-------------------------------------------------------------------- -const U32 CHUNK_SIZE = 4 << 20 ; //4 MB -const U32 LARGE_CHUNK_SIZE = 4 * CHUNK_SIZE ; //16 MB -LLPrivateMemoryPool::LLPrivateMemoryPool(S32 type, U32 max_pool_size) : - mMutexp(NULL), - mReservedPoolSize(0), - mHashFactor(1), - mType(type), - mMaxPoolSize(max_pool_size) -{ - if(type == STATIC_THREADED || type == VOLATILE_THREADED) - { - mMutexp = new LLMutex(NULL) ; - } - - for(S32 i = 0 ; i < SUPER_ALLOCATION ; i++) - { - mChunkList[i] = NULL ; - } - - mNumOfChunks = 0 ; -} - -LLPrivateMemoryPool::~LLPrivateMemoryPool() -{ - destroyPool(); - delete mMutexp ; -} - -char* LLPrivateMemoryPool::allocate(U32 size) -{ - if(!size) - { - return NULL ; - } - - //if the asked size larger than MAX_BLOCK_SIZE, fetch from heap directly, the pool does not manage it - if(size >= CHUNK_SIZE) - { - return (char*)ll_aligned_malloc_16(size) ; - } - - char* p = NULL ; - - //find the appropriate chunk - S32 chunk_idx = getChunkIndex(size) ; - - lock() ; - - LLMemoryChunk* chunk = mChunkList[chunk_idx]; - while(chunk) - { - if((p = chunk->allocate(size))) - { - break ; - } - chunk = chunk->mNext ; - } - - //fetch new memory chunk - if(!p) - { - if(mReservedPoolSize + CHUNK_SIZE > mMaxPoolSize) - { - chunk = mChunkList[chunk_idx]; - while(chunk) - { - if((p = chunk->allocate(size))) - { - break ; - } - chunk = chunk->mNext ; - } - } - else - { - chunk = addChunk(chunk_idx) ; - if(chunk) - { - p = chunk->allocate(size) ; - } - } - } - - unlock() ; - - if(!p) //to get memory from the private pool failed, try the heap directly - { - static bool to_log = true ; - - if(to_log) - { - LL_WARNS() << "The memory pool overflows, now using heap directly!" << LL_ENDL ; - to_log = false ; - } - - return (char*)ll_aligned_malloc_16(size) ; - } - - return p ; -} - -void LLPrivateMemoryPool::freeMem(void* addr) -{ - if(!addr) - { - return ; - } - - lock() ; - - LLMemoryChunk* chunk = findChunk((char*)addr) ; - - if(!chunk) - { - ll_aligned_free_16(addr) ; //release from heap - } - else - { - chunk->freeMem(addr) ; - - if(chunk->empty()) - { - removeChunk(chunk) ; - } - } - - unlock() ; -} - -void LLPrivateMemoryPool::dump() -{ -} - -U32 LLPrivateMemoryPool::getTotalAllocatedSize() -{ - U32 total_allocated = 0 ; - - LLMemoryChunk* chunk ; - for(S32 i = 0 ; i < SUPER_ALLOCATION ; i++) - { - chunk = mChunkList[i]; - while(chunk) - { - total_allocated += chunk->getAllocatedSize() ; - chunk = chunk->mNext ; - } - } - - return total_allocated ; -} - -void LLPrivateMemoryPool::lock() -{ - if(mMutexp) - { - mMutexp->lock() ; - } -} - -void LLPrivateMemoryPool::unlock() -{ - if(mMutexp) - { - mMutexp->unlock() ; - } -} - -S32 LLPrivateMemoryPool::getChunkIndex(U32 size) -{ - S32 i ; - for(i = 0 ; size > MAX_SLOT_SIZES[i]; i++); - - llassert_always(i < SUPER_ALLOCATION); - - return i ; -} - -//destroy the entire pool -void LLPrivateMemoryPool::destroyPool() -{ - lock() ; - - if(mNumOfChunks > 0) - { - LL_WARNS() << "There is some memory not freed when destroy the memory pool!" << LL_ENDL ; - } - - mNumOfChunks = 0 ; - mChunkHashList.clear() ; - mHashFactor = 1 ; - for(S32 i = 0 ; i < SUPER_ALLOCATION ; i++) - { - mChunkList[i] = NULL ; - } - - unlock() ; -} - -bool LLPrivateMemoryPool::checkSize(U32 asked_size) -{ - if(mReservedPoolSize + asked_size > mMaxPoolSize) - { - LL_INFOS() << "Max pool size: " << mMaxPoolSize << LL_ENDL ; - LL_INFOS() << "Total reserved size: " << mReservedPoolSize + asked_size << LL_ENDL ; - LL_INFOS() << "Total_allocated Size: " << getTotalAllocatedSize() << LL_ENDL ; - - //LL_ERRS() << "The pool is overflowing..." << LL_ENDL ; - - return false ; - } - - return true ; -} - -LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::addChunk(S32 chunk_index) -{ - U32 preferred_size ; - U32 overhead ; - if(chunk_index < LARGE_ALLOCATION) - { - preferred_size = CHUNK_SIZE ; //4MB - overhead = LLMemoryChunk::getMaxOverhead(preferred_size, MIN_SLOT_SIZES[chunk_index], - MAX_SLOT_SIZES[chunk_index], MIN_BLOCK_SIZES[chunk_index], MAX_BLOCK_SIZES[chunk_index]) ; - } - else - { - preferred_size = LARGE_CHUNK_SIZE ; //16MB - overhead = LLMemoryChunk::getMaxOverhead(preferred_size, MIN_SLOT_SIZES[chunk_index], - MAX_SLOT_SIZES[chunk_index], MIN_BLOCK_SIZES[chunk_index], MAX_BLOCK_SIZES[chunk_index]) ; - } - - if(!checkSize(preferred_size + overhead)) - { - return NULL ; - } - - mReservedPoolSize += preferred_size + overhead ; - - char* buffer = (char*)ll_aligned_malloc_16(preferred_size + overhead) ; - if(!buffer) - { - return NULL ; - } - - LLMemoryChunk* chunk = new (buffer) LLMemoryChunk() ; - chunk->init(buffer, preferred_size + overhead, MIN_SLOT_SIZES[chunk_index], - MAX_SLOT_SIZES[chunk_index], MIN_BLOCK_SIZES[chunk_index], MAX_BLOCK_SIZES[chunk_index]) ; - - //add to the tail of the linked list - { - if(!mChunkList[chunk_index]) - { - mChunkList[chunk_index] = chunk ; - } - else - { - LLMemoryChunk* cur = mChunkList[chunk_index] ; - while(cur->mNext) - { - cur = cur->mNext ; - } - cur->mNext = chunk ; - chunk->mPrev = cur ; - } - } - - //insert into the hash table - addToHashTable(chunk) ; - - mNumOfChunks++; - - return chunk ; -} - -void LLPrivateMemoryPool::removeChunk(LLMemoryChunk* chunk) -{ - if(!chunk) - { - return ; - } - - //remove from the linked list - for(S32 i = 0 ; i < SUPER_ALLOCATION ; i++) - { - if(mChunkList[i] == chunk) - { - mChunkList[i] = chunk->mNext ; - } - } - - if(chunk->mPrev) - { - chunk->mPrev->mNext = chunk->mNext ; - } - if(chunk->mNext) - { - chunk->mNext->mPrev = chunk->mPrev ; - } - - //remove from the hash table - removeFromHashTable(chunk) ; - - mNumOfChunks--; - mReservedPoolSize -= chunk->getBufferSize() ; - - //release memory - ll_aligned_free_16(chunk->getBuffer()) ; -} - -U16 LLPrivateMemoryPool::findHashKey(const char* addr) -{ - return (((uintptr_t)addr) / CHUNK_SIZE) % mHashFactor ; -} - -LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::findChunk(const char* addr) -{ - U16 key = findHashKey(addr) ; - if(mChunkHashList.size() <= key) - { - return NULL ; - } - - return mChunkHashList[key].findChunk(addr) ; -} - -void LLPrivateMemoryPool::addToHashTable(LLMemoryChunk* chunk) -{ - static const U16 HASH_FACTORS[] = {41, 83, 193, 317, 419, 523, 719, 997, 1523, 0xFFFF}; - - U16 i ; - if(mChunkHashList.empty()) - { - mHashFactor = HASH_FACTORS[0] ; - rehash() ; - } - - U16 start_key = findHashKey(chunk->getBuffer()) ; - U16 end_key = findHashKey(chunk->getBuffer() + chunk->getBufferSize() - 1) ; - bool need_rehash = false ; - - if(mChunkHashList[start_key].hasElement(chunk)) - { - return; //already inserted. - } - need_rehash = mChunkHashList[start_key].add(chunk) ; - - if(start_key == end_key && !need_rehash) - { - return ; //done - } - - if(!need_rehash) - { - need_rehash = mChunkHashList[end_key].add(chunk) ; - } - - if(!need_rehash) - { - if(end_key < start_key) - { - need_rehash = fillHashTable(start_key + 1, mHashFactor, chunk) ; - if(!need_rehash) - { - need_rehash = fillHashTable(0, end_key, chunk) ; - } - } - else - { - need_rehash = fillHashTable(start_key + 1, end_key, chunk) ; - } - } - - if(need_rehash) - { - i = 0 ; - while(HASH_FACTORS[i] <= mHashFactor) i++; - - mHashFactor = HASH_FACTORS[i] ; - llassert_always(mHashFactor != 0xFFFF) ;//stop point to prevent endlessly recursive calls - - rehash() ; - } -} - -void LLPrivateMemoryPool::removeFromHashTable(LLMemoryChunk* chunk) -{ - U16 start_key = findHashKey(chunk->getBuffer()) ; - U16 end_key = findHashKey(chunk->getBuffer() + chunk->getBufferSize() - 1) ; - - mChunkHashList[start_key].remove(chunk) ; - if(start_key == end_key) - { - return ; //done - } - - mChunkHashList[end_key].remove(chunk) ; - - if(end_key < start_key) - { - for(U16 i = start_key + 1 ; i < mHashFactor; i++) - { - mChunkHashList[i].remove(chunk) ; - } - for(U16 i = 0 ; i < end_key; i++) - { - mChunkHashList[i].remove(chunk) ; - } - } - else - { - for(U16 i = start_key + 1 ; i < end_key; i++) - { - mChunkHashList[i].remove(chunk) ; - } - } -} - -void LLPrivateMemoryPool::rehash() -{ - LL_INFOS() << "new hash factor: " << mHashFactor << LL_ENDL ; - - mChunkHashList.clear() ; - mChunkHashList.resize(mHashFactor) ; - - LLMemoryChunk* chunk ; - for(U16 i = 0 ; i < SUPER_ALLOCATION ; i++) - { - chunk = mChunkList[i] ; - while(chunk) - { - addToHashTable(chunk) ; - chunk = chunk->mNext ; - } - } -} - -bool LLPrivateMemoryPool::fillHashTable(U16 start, U16 end, LLMemoryChunk* chunk) -{ - for(U16 i = start; i < end; i++) - { - if(mChunkHashList[i].add(chunk)) - { - return true ; - } - } - - return false ; -} - -//-------------------------------------------------------------------- -// class LLChunkHashElement -//-------------------------------------------------------------------- -LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::LLChunkHashElement::findChunk(const char* addr) -{ - if(mFirst && mFirst->containsAddress(addr)) - { - return mFirst ; - } - else if(mSecond && mSecond->containsAddress(addr)) - { - return mSecond ; - } - - return NULL ; -} - -//return false if successfully inserted to the hash slot. -bool LLPrivateMemoryPool::LLChunkHashElement::add(LLPrivateMemoryPool::LLMemoryChunk* chunk) -{ - llassert_always(!hasElement(chunk)) ; - - if(!mFirst) - { - mFirst = chunk ; - } - else if(!mSecond) - { - mSecond = chunk ; - } - else - { - return true ; //failed - } - - return false ; -} - -void LLPrivateMemoryPool::LLChunkHashElement::remove(LLPrivateMemoryPool::LLMemoryChunk* chunk) -{ - if(mFirst == chunk) - { - mFirst = NULL ; - } - else if(mSecond ==chunk) - { - mSecond = NULL ; - } - else - { - LL_ERRS() << "This slot does not contain this chunk!" << LL_ENDL ; - } -} - -//-------------------------------------------------------------------- -//class LLPrivateMemoryPoolManager -//-------------------------------------------------------------------- -LLPrivateMemoryPoolManager* LLPrivateMemoryPoolManager::sInstance = NULL ; -BOOL LLPrivateMemoryPoolManager::sPrivatePoolEnabled = FALSE ; -std::vector<LLPrivateMemoryPool*> LLPrivateMemoryPoolManager::sDanglingPoolList ; - -LLPrivateMemoryPoolManager::LLPrivateMemoryPoolManager(BOOL enabled, U32 max_pool_size) -{ - mPoolList.resize(LLPrivateMemoryPool::MAX_TYPES) ; - - for(S32 i = 0 ; i < LLPrivateMemoryPool::MAX_TYPES; i++) - { - mPoolList[i] = NULL ; - } - - sPrivatePoolEnabled = enabled ; - - const U32 MAX_POOL_SIZE = 256 * 1024 * 1024 ; //256 MB - mMaxPrivatePoolSize = llmax(max_pool_size, MAX_POOL_SIZE) ; -} - -LLPrivateMemoryPoolManager::~LLPrivateMemoryPoolManager() -{ - -#if __DEBUG_PRIVATE_MEM__ - if(!sMemAllocationTracker.empty()) - { - LL_WARNS() << "there is potential memory leaking here. The list of not freed memory blocks are from: " <<LL_ENDL ; - - S32 k = 0 ; - for(mem_allocation_info_t::iterator iter = sMemAllocationTracker.begin() ; iter != sMemAllocationTracker.end() ; ++iter) - { - LL_INFOS() << k++ << ", " << (uintptr_t)iter->first << " : " << iter->second << LL_ENDL ; - } - sMemAllocationTracker.clear() ; - } -#endif - -#if 0 - //all private pools should be released by their owners before reaching here. - for(S32 i = 0 ; i < LLPrivateMemoryPool::MAX_TYPES; i++) - { - llassert_always(!mPoolList[i]) ; - } - mPoolList.clear() ; - -#else - //forcefully release all memory - for(S32 i = 0 ; i < LLPrivateMemoryPool::MAX_TYPES; i++) - { - if(mPoolList[i]) - { - if(mPoolList[i]->isEmpty()) - { - delete mPoolList[i] ; - } - else - { - //can not delete this pool because it has alloacted memory to be freed. - //move it to the dangling list. - sDanglingPoolList.push_back(mPoolList[i]) ; - } - - mPoolList[i] = NULL ; - } - } - mPoolList.clear() ; -#endif -} - -//static -void LLPrivateMemoryPoolManager::initClass(BOOL enabled, U32 max_pool_size) -{ - llassert_always(!sInstance) ; - - sInstance = new LLPrivateMemoryPoolManager(enabled, max_pool_size) ; -} - -//static -LLPrivateMemoryPoolManager* LLPrivateMemoryPoolManager::getInstance() -{ - //if(!sInstance) - //{ - // sInstance = new LLPrivateMemoryPoolManager(FALSE) ; - //} - return sInstance ; -} - -//static -void LLPrivateMemoryPoolManager::destroyClass() -{ - if(sInstance) - { - delete sInstance ; - sInstance = NULL ; - } -} - -LLPrivateMemoryPool* LLPrivateMemoryPoolManager::newPool(S32 type) -{ - if(!sPrivatePoolEnabled) - { - return NULL ; - } - - if(!mPoolList[type]) - { - mPoolList[type] = new LLPrivateMemoryPool(type, mMaxPrivatePoolSize) ; - } - - return mPoolList[type] ; -} - -void LLPrivateMemoryPoolManager::deletePool(LLPrivateMemoryPool* pool) -{ - if(pool && pool->isEmpty()) - { - mPoolList[pool->getType()] = NULL ; - delete pool; - } -} - -//debug -void LLPrivateMemoryPoolManager::updateStatistics() -{ - mTotalReservedSize = 0 ; - mTotalAllocatedSize = 0 ; - - for(U32 i = 0; i < mPoolList.size(); i++) - { - if(mPoolList[i]) - { - mTotalReservedSize += mPoolList[i]->getTotalReservedSize() ; - mTotalAllocatedSize += mPoolList[i]->getTotalAllocatedSize() ; - } - } -} - -#if __DEBUG_PRIVATE_MEM__ -//static -char* LLPrivateMemoryPoolManager::allocate(LLPrivateMemoryPool* poolp, U32 size, const char* function, const int line) -{ - char* p ; - - if(!poolp) - { - p = (char*)ll_aligned_malloc_16(size) ; - } - else - { - p = poolp->allocate(size) ; - } - - if(p) - { - char num[16] ; - sprintf(num, " line: %d ", line) ; - std::string str(function) ; - str += num; - - sMemAllocationTracker[p] = str ; - } - - return p ; -} -#else -//static -char* LLPrivateMemoryPoolManager::allocate(LLPrivateMemoryPool* poolp, U32 size) -{ - if(poolp) - { - return poolp->allocate(size) ; - } - else - { - return (char*)ll_aligned_malloc_16(size) ; - } -} -#endif - -//static -void LLPrivateMemoryPoolManager::freeMem(LLPrivateMemoryPool* poolp, void* addr) -{ - if(!addr) - { - return ; - } - -#if __DEBUG_PRIVATE_MEM__ - sMemAllocationTracker.erase((char*)addr) ; -#endif - - if(poolp) - { - poolp->freeMem(addr) ; - } - else - { - if(!sPrivatePoolEnabled) - { - ll_aligned_free_16(addr) ; //private pool is disabled. - } - else if(!sInstance) //the private memory manager is destroyed, try the dangling list - { - for(S32 i = 0 ; i < sDanglingPoolList.size(); i++) - { - if(sDanglingPoolList[i]->findChunk((char*)addr)) - { - sDanglingPoolList[i]->freeMem(addr) ; - if(sDanglingPoolList[i]->isEmpty()) - { - delete sDanglingPoolList[i] ; - - if(i < sDanglingPoolList.size() - 1) - { - sDanglingPoolList[i] = sDanglingPoolList[sDanglingPoolList.size() - 1] ; - } - sDanglingPoolList.pop_back() ; - } - - addr = NULL ; - break ; - } - } - llassert_always(!addr) ; //addr should be release before hitting here! - } - else - { - LL_ERRS() << "private pool is used before initialized.!" << LL_ENDL ; - } - } -} - -//-------------------------------------------------------------------- -//class LLPrivateMemoryPoolTester -//-------------------------------------------------------------------- -#if 0 -LLPrivateMemoryPoolTester* LLPrivateMemoryPoolTester::sInstance = NULL ; -LLPrivateMemoryPool* LLPrivateMemoryPoolTester::sPool = NULL ; -LLPrivateMemoryPoolTester::LLPrivateMemoryPoolTester() -{ -} - -LLPrivateMemoryPoolTester::~LLPrivateMemoryPoolTester() -{ -} - -//static -LLPrivateMemoryPoolTester* LLPrivateMemoryPoolTester::getInstance() -{ - if(!sInstance) - { - sInstance = ::new LLPrivateMemoryPoolTester() ; - } - return sInstance ; -} - -//static -void LLPrivateMemoryPoolTester::destroy() -{ - if(sInstance) - { - ::delete sInstance ; - sInstance = NULL ; - } - - if(sPool) - { - LLPrivateMemoryPoolManager::getInstance()->deletePool(sPool) ; - sPool = NULL ; - } -} - -void LLPrivateMemoryPoolTester::run(S32 type) -{ - if(sPool) - { - LLPrivateMemoryPoolManager::getInstance()->deletePool(sPool) ; - } - sPool = LLPrivateMemoryPoolManager::getInstance()->newPool(type) ; - - //run the test - correctnessTest() ; - performanceTest() ; - //fragmentationtest() ; - - //release pool. - LLPrivateMemoryPoolManager::getInstance()->deletePool(sPool) ; - sPool = NULL ; -} - -void LLPrivateMemoryPoolTester::test(U32 min_size, U32 max_size, U32 stride, U32 times, - bool random_deletion, bool output_statistics) -{ - U32 levels = (max_size - min_size) / stride + 1 ; - char*** p ; - U32 i, j ; - U32 total_allocated_size = 0 ; - - //allocate space for p ; - if(!(p = ::new char**[times]) || !(*p = ::new char*[times * levels])) - { - LL_ERRS() << "memory initialization for p failed" << LL_ENDL ; - } - - //init - for(i = 0 ; i < times; i++) - { - p[i] = *p + i * levels ; - for(j = 0 ; j < levels; j++) - { - p[i][j] = NULL ; - } - } - - //allocation - U32 size ; - for(i = 0 ; i < times ; i++) - { - for(j = 0 ; j < levels; j++) - { - size = min_size + j * stride ; - p[i][j] = ALLOCATE_MEM(sPool, size) ; - - total_allocated_size+= size ; - - *(U32*)p[i][j] = i ; - *((U32*)p[i][j] + 1) = j ; - //p[i][j][size - 1] = '\0' ; //access the last element to verify the success of the allocation. - - //randomly release memory - if(random_deletion) - { - S32 k = rand() % levels ; - - if(p[i][k]) - { - llassert_always(*(U32*)p[i][k] == i && *((U32*)p[i][k] + 1) == k) ; - FREE_MEM(sPool, p[i][k]) ; - total_allocated_size -= min_size + k * stride ; - p[i][k] = NULL ; - } - } - } - } - - //output pool allocation statistics - if(output_statistics) - { - } - - //release all memory allocations - for(i = 0 ; i < times; i++) - { - for(j = 0 ; j < levels; j++) - { - if(p[i][j]) - { - llassert_always(*(U32*)p[i][j] == i && *((U32*)p[i][j] + 1) == j) ; - FREE_MEM(sPool, p[i][j]) ; - total_allocated_size -= min_size + j * stride ; - p[i][j] = NULL ; - } - } - } - - ::delete[] *p ; - ::delete[] p ; -} - -void LLPrivateMemoryPoolTester::testAndTime(U32 size, U32 times) -{ - LLTimer timer ; - - LL_INFOS() << " -**********************- " << LL_ENDL ; - LL_INFOS() << "test size: " << size << " test times: " << times << LL_ENDL ; - - timer.reset() ; - char** p = new char*[times] ; - - //using the customized memory pool - //allocation - for(U32 i = 0 ; i < times; i++) - { - p[i] = ALLOCATE_MEM(sPool, size) ; - if(!p[i]) - { - LL_ERRS() << "allocation failed" << LL_ENDL ; - } - } - //de-allocation - for(U32 i = 0 ; i < times; i++) - { - FREE_MEM(sPool, p[i]) ; - p[i] = NULL ; - } - LL_INFOS() << "time spent using customized memory pool: " << timer.getElapsedTimeF32() << LL_ENDL ; - - timer.reset() ; - - //using the standard allocator/de-allocator: - //allocation - for(U32 i = 0 ; i < times; i++) - { - p[i] = ::new char[size] ; - if(!p[i]) - { - LL_ERRS() << "allocation failed" << LL_ENDL ; - } - } - //de-allocation - for(U32 i = 0 ; i < times; i++) - { - ::delete[] p[i] ; - p[i] = NULL ; - } - LL_INFOS() << "time spent using standard allocator/de-allocator: " << timer.getElapsedTimeF32() << LL_ENDL ; - - delete[] p; -} - -void LLPrivateMemoryPoolTester::correctnessTest() -{ - //try many different sized allocation, and all kinds of edge cases, access the allocated memory - //to see if allocation is right. - - //edge case - char* p = ALLOCATE_MEM(sPool, 0) ; - FREE_MEM(sPool, p) ; - - //small sized - // [8 bytes, 2KB), each asks for 256 allocations and deallocations - test(8, 2040, 8, 256, true, true) ; - - //medium sized - //[2KB, 512KB), each asks for 16 allocations and deallocations - test(2048, 512 * 1024 - 2048, 2048, 16, true, true) ; - - //large sized - //[512KB, 4MB], each asks for 8 allocations and deallocations - test(512 * 1024, 4 * 1024 * 1024, 64 * 1024, 6, true, true) ; -} - -void LLPrivateMemoryPoolTester::performanceTest() -{ - U32 test_size[3] = {768, 3* 1024, 3* 1024 * 1024}; - - //small sized - testAndTime(test_size[0], 8) ; - - //medium sized - testAndTime(test_size[1], 8) ; - - //large sized - testAndTime(test_size[2], 8) ; -} - -void LLPrivateMemoryPoolTester::fragmentationtest() -{ - //for internal fragmentation statistics: - //every time when asking for a new chunk during correctness test, and performance test, - //print out the chunk usage statistices. -} -#endif //-------------------------------------------------------------------- #if defined(LL_WINDOWS) && defined(LL_DEBUG_BUFFER_OVERRUN) diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index c37967e10e..5b17d9e3a4 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -356,327 +356,6 @@ private: static BOOL sEnableMemoryFailurePrevention; }; -// -//class LLPrivateMemoryPool defines a private memory pool for an application to use, so the application does not -//need to access the heap directly fro each memory allocation. Throught this, the allocation speed is faster, -//and reduces virtaul address space gragmentation problem. -//Note: this class is thread-safe by passing true to the constructor function. However, you do not need to do this unless -//you are sure the memory allocation and de-allocation will happen in different threads. To make the pool thread safe -//increases allocation and deallocation cost. -// -class LL_COMMON_API LLPrivateMemoryPool -{ - friend class LLPrivateMemoryPoolManager ; - -public: - class LL_COMMON_API LLMemoryBlock //each block is devided into slots uniformly - { - public: - LLMemoryBlock() ; - ~LLMemoryBlock() ; - - void init(char* buffer, U32 buffer_size, U32 slot_size) ; - void setBuffer(char* buffer, U32 buffer_size) ; - - char* allocate() ; - void freeMem(void* addr) ; - - bool empty() {return !mAllocatedSlots;} - bool isFull() {return mAllocatedSlots == mTotalSlots;} - bool isFree() {return !mTotalSlots;} - - U32 getSlotSize()const {return mSlotSize;} - U32 getTotalSlots()const {return mTotalSlots;} - U32 getBufferSize()const {return mBufferSize;} - char* getBuffer() const {return mBuffer;} - - //debug use - void resetBitMap() ; - private: - char* mBuffer; - U32 mSlotSize ; //when the block is not initialized, it is the buffer size. - U32 mBufferSize ; - U32 mUsageBits ; - U8 mTotalSlots ; - U8 mAllocatedSlots ; - U8 mDummySize ; //size of extra bytes reserved for mUsageBits. - - public: - LLMemoryBlock* mPrev ; - LLMemoryBlock* mNext ; - LLMemoryBlock* mSelf ; - - struct CompareAddress - { - bool operator()(const LLMemoryBlock* const& lhs, const LLMemoryBlock* const& rhs) - { - return (uintptr_t)lhs->getBuffer() < (uintptr_t)rhs->getBuffer(); - } - }; - }; - - class LL_COMMON_API LLMemoryChunk //is divided into memory blocks. - { - public: - LLMemoryChunk() ; - ~LLMemoryChunk() ; - - void init(char* buffer, U32 buffer_size, U32 min_slot_size, U32 max_slot_size, U32 min_block_size, U32 max_block_size) ; - void setBuffer(char* buffer, U32 buffer_size) ; - - bool empty() ; - - char* allocate(U32 size) ; - void freeMem(void* addr) ; - - char* getBuffer() const {return mBuffer;} - U32 getBufferSize() const {return mBufferSize;} - U32 getAllocatedSize() const {return mAlloatedSize;} - - bool containsAddress(const char* addr) const; - - static U32 getMaxOverhead(U32 data_buffer_size, U32 min_slot_size, - U32 max_slot_size, U32 min_block_size, U32 max_block_size) ; - - void dump() ; - - private: - U32 getPageIndex(uintptr_t addr) ; - U32 getBlockLevel(U32 size) ; - U16 getPageLevel(U32 size) ; - LLMemoryBlock* addBlock(U32 blk_idx) ; - void popAvailBlockList(U32 blk_idx) ; - void addToFreeSpace(LLMemoryBlock* blk) ; - void removeFromFreeSpace(LLMemoryBlock* blk) ; - void removeBlock(LLMemoryBlock* blk) ; - void addToAvailBlockList(LLMemoryBlock* blk) ; - U32 calcBlockSize(U32 slot_size); - LLMemoryBlock* createNewBlock(LLMemoryBlock* blk, U32 buffer_size, U32 slot_size, U32 blk_idx) ; - - private: - LLMemoryBlock** mAvailBlockList ;//256 by mMinSlotSize - LLMemoryBlock** mFreeSpaceList; - LLMemoryBlock* mBlocks ; //index of blocks by address. - - char* mBuffer ; - U32 mBufferSize ; - char* mDataBuffer ; - char* mMetaBuffer ; - U32 mMinBlockSize ; - U32 mMinSlotSize ; - U32 mMaxSlotSize ; - U32 mAlloatedSize ; - U16 mBlockLevels; - U16 mPartitionLevels; - - public: - //form a linked list - LLMemoryChunk* mNext ; - LLMemoryChunk* mPrev ; - } ; - -private: - LLPrivateMemoryPool(S32 type, U32 max_pool_size) ; - ~LLPrivateMemoryPool() ; - - char *allocate(U32 size) ; - void freeMem(void* addr) ; - - void dump() ; - U32 getTotalAllocatedSize() ; - U32 getTotalReservedSize() {return mReservedPoolSize;} - S32 getType() const {return mType; } - bool isEmpty() const {return !mNumOfChunks; } - -private: - void lock() ; - void unlock() ; - S32 getChunkIndex(U32 size) ; - LLMemoryChunk* addChunk(S32 chunk_index) ; - bool checkSize(U32 asked_size) ; - void removeChunk(LLMemoryChunk* chunk) ; - U16 findHashKey(const char* addr); - void addToHashTable(LLMemoryChunk* chunk) ; - void removeFromHashTable(LLMemoryChunk* chunk) ; - void rehash() ; - bool fillHashTable(U16 start, U16 end, LLMemoryChunk* chunk) ; - LLMemoryChunk* findChunk(const char* addr) ; - - void destroyPool() ; - -public: - enum - { - SMALL_ALLOCATION = 0, //from 8 bytes to 2KB(exclusive), page size 2KB, max chunk size is 4MB. - MEDIUM_ALLOCATION, //from 2KB to 512KB(exclusive), page size 32KB, max chunk size 4MB - LARGE_ALLOCATION, //from 512KB to 4MB(inclusive), page size 64KB, max chunk size 16MB - SUPER_ALLOCATION //allocation larger than 4MB. - }; - - enum - { - STATIC = 0 , //static pool(each alllocation stays for a long time) without threading support - VOLATILE, //Volatile pool(each allocation stays for a very short time) without threading support - STATIC_THREADED, //static pool with threading support - VOLATILE_THREADED, //volatile pool with threading support - MAX_TYPES - }; //pool types - -private: - LLMutex* mMutexp ; - U32 mMaxPoolSize; - U32 mReservedPoolSize ; - - LLMemoryChunk* mChunkList[SUPER_ALLOCATION] ; //all memory chunks reserved by this pool, sorted by address - U16 mNumOfChunks ; - U16 mHashFactor ; - - S32 mType ; - - class LLChunkHashElement - { - public: - LLChunkHashElement() {mFirst = NULL ; mSecond = NULL ;} - - bool add(LLMemoryChunk* chunk) ; - void remove(LLMemoryChunk* chunk) ; - LLMemoryChunk* findChunk(const char* addr) ; - - bool empty() {return !mFirst && !mSecond; } - bool full() {return mFirst && mSecond; } - bool hasElement(LLMemoryChunk* chunk) {return mFirst == chunk || mSecond == chunk;} - - private: - LLMemoryChunk* mFirst ; - LLMemoryChunk* mSecond ; - }; - std::vector<LLChunkHashElement> mChunkHashList ; -}; - -class LL_COMMON_API LLPrivateMemoryPoolManager -{ -private: - LLPrivateMemoryPoolManager(BOOL enabled, U32 max_pool_size) ; - ~LLPrivateMemoryPoolManager() ; - -public: - static LLPrivateMemoryPoolManager* getInstance() ; - static void initClass(BOOL enabled, U32 pool_size) ; - static void destroyClass() ; - - LLPrivateMemoryPool* newPool(S32 type) ; - void deletePool(LLPrivateMemoryPool* pool) ; - -private: - std::vector<LLPrivateMemoryPool*> mPoolList ; - U32 mMaxPrivatePoolSize; - - static LLPrivateMemoryPoolManager* sInstance ; - static BOOL sPrivatePoolEnabled; - static std::vector<LLPrivateMemoryPool*> sDanglingPoolList ; -public: - //debug and statistics info. - void updateStatistics() ; - - U32 mTotalReservedSize ; - U32 mTotalAllocatedSize ; - -public: -#if __DEBUG_PRIVATE_MEM__ - static char* allocate(LLPrivateMemoryPool* poolp, U32 size, const char* function, const int line) ; - - typedef std::map<char*, std::string> mem_allocation_info_t ; - static mem_allocation_info_t sMemAllocationTracker; -#else - static char* allocate(LLPrivateMemoryPool* poolp, U32 size) ; -#endif - static void freeMem(LLPrivateMemoryPool* poolp, void* addr) ; -}; - -//------------------------------------------------------------------------------------- -#if __DEBUG_PRIVATE_MEM__ -#define ALLOCATE_MEM(poolp, size) LLPrivateMemoryPoolManager::allocate((poolp), (size), __FUNCTION__, __LINE__) -#else -#define ALLOCATE_MEM(poolp, size) LLPrivateMemoryPoolManager::allocate((poolp), (size)) -#endif -#define FREE_MEM(poolp, addr) LLPrivateMemoryPoolManager::freeMem((poolp), (addr)) -//------------------------------------------------------------------------------------- - -// -//the below singleton is used to test the private memory pool. -// -#if 0 -class LL_COMMON_API LLPrivateMemoryPoolTester -{ -private: - LLPrivateMemoryPoolTester() ; - ~LLPrivateMemoryPoolTester() ; - -public: - static LLPrivateMemoryPoolTester* getInstance() ; - static void destroy() ; - - void run(S32 type) ; - -private: - void correctnessTest() ; - void performanceTest() ; - void fragmentationtest() ; - - void test(U32 min_size, U32 max_size, U32 stride, U32 times, bool random_deletion, bool output_statistics) ; - void testAndTime(U32 size, U32 times) ; - -#if 0 -public: - void* operator new(size_t size) - { - return (void*)sPool->allocate(size) ; - } - void operator delete(void* addr) - { - sPool->freeMem(addr) ; - } - void* operator new[](size_t size) - { - return (void*)sPool->allocate(size) ; - } - void operator delete[](void* addr) - { - sPool->freeMem(addr) ; - } -#endif - -private: - static LLPrivateMemoryPoolTester* sInstance; - static LLPrivateMemoryPool* sPool ; - static LLPrivateMemoryPool* sThreadedPool ; -}; -#if 0 -//static -void* LLPrivateMemoryPoolTester::operator new(size_t size) -{ - return (void*)sPool->allocate(size) ; -} - -//static -void LLPrivateMemoryPoolTester::operator delete(void* addr) -{ - sPool->free(addr) ; -} - -//static -void* LLPrivateMemoryPoolTester::operator new[](size_t size) -{ - return (void*)sPool->allocate(size) ; -} - -//static -void LLPrivateMemoryPoolTester::operator delete[](void* addr) -{ - sPool->free(addr) ; -} -#endif -#endif // LLRefCount moved to llrefcount.h // LLPointer moved to llpointer.h diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index be54ed053b..26a4967659 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -51,6 +51,7 @@ // File constants static const int MAX_HDR_LEN = 20; +static const S32 UNZIP_LLSD_MAX_DEPTH = 96; static const char LEGACY_NON_HEADER[] = "<llsd>"; const std::string LLSD_BINARY_HEADER("LLSD/Binary"); const std::string LLSD_XML_HEADER("LLSD/XML"); @@ -317,11 +318,11 @@ LLSDParser::LLSDParser() LLSDParser::~LLSDParser() { } -S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes) +S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes, S32 max_depth) { mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true; mMaxBytesLeft = max_bytes; - return doParse(istr, data); + return doParse(istr, data, max_depth); } @@ -403,7 +404,7 @@ LLSDNotationParser::~LLSDNotationParser() { } // virtual -S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const +S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) const { // map: { string:object, string:object } // array: [ object, object, object ] @@ -418,6 +419,10 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const // binary: b##"ff3120ab1" | b(size)"raw data" char c; c = istr.peek(); + if (max_depth == 0) + { + return PARSE_FAILURE; + } while(isspace(c)) { // pop the whitespace. @@ -434,7 +439,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const { case '{': { - S32 child_count = parseMap(istr, data); + S32 child_count = parseMap(istr, data, max_depth - 1); if((child_count == PARSE_FAILURE) || data.isUndefined()) { parse_count = PARSE_FAILURE; @@ -453,7 +458,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const case '[': { - S32 child_count = parseArray(istr, data); + S32 child_count = parseArray(istr, data, max_depth - 1); if((child_count == PARSE_FAILURE) || data.isUndefined()) { parse_count = PARSE_FAILURE; @@ -658,7 +663,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const return parse_count; } -S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const +S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) const { // map: { string:object, string:object } map = LLSD::emptyMap(); @@ -693,7 +698,7 @@ S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const } putback(istr, c); LLSD child; - S32 count = doParse(istr, child); + S32 count = doParse(istr, child, max_depth); if(count > 0) { // There must be a value for every key, thus @@ -718,7 +723,7 @@ S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const return parse_count; } -S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array) const +S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array, S32 max_depth) const { // array: [ object, object, object ] array = LLSD::emptyArray(); @@ -737,7 +742,7 @@ S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array) const continue; } putback(istr, c); - S32 count = doParse(istr, child); + S32 count = doParse(istr, child, max_depth); if(PARSE_FAILURE == count) { return PARSE_FAILURE; @@ -869,7 +874,7 @@ LLSDBinaryParser::~LLSDBinaryParser() } // virtual -S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const +S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) const { /** * Undefined: '!'<br> @@ -893,12 +898,16 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const { return 0; } + if (max_depth == 0) + { + return PARSE_FAILURE; + } S32 parse_count = 1; switch(c) { case '{': { - S32 child_count = parseMap(istr, data); + S32 child_count = parseMap(istr, data, max_depth - 1); if((child_count == PARSE_FAILURE) || data.isUndefined()) { parse_count = PARSE_FAILURE; @@ -917,7 +926,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const case '[': { - S32 child_count = parseArray(istr, data); + S32 child_count = parseArray(istr, data, max_depth - 1); if((child_count == PARSE_FAILURE) || data.isUndefined()) { parse_count = PARSE_FAILURE; @@ -1098,7 +1107,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const return parse_count; } -S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const +S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) const { map = LLSD::emptyMap(); U32 value_nbo = 0; @@ -1128,7 +1137,7 @@ S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const } } LLSD child; - S32 child_count = doParse(istr, child); + S32 child_count = doParse(istr, child, max_depth); if(child_count > 0) { // There must be a value for every key, thus child_count @@ -1152,7 +1161,7 @@ S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const return parse_count; } -S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const +S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array, S32 max_depth) const { array = LLSD::emptyArray(); U32 value_nbo = 0; @@ -1168,7 +1177,7 @@ S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const while((c != ']') && (count < size) && istr.good()) { LLSD child; - S32 child_count = doParse(istr, child); + S32 child_count = doParse(istr, child, max_depth); if(PARSE_FAILURE == child_count) { return PARSE_FAILURE; @@ -2238,7 +2247,7 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is, return ZR_MEM_ERROR; } - if (!LLSDSerialize::fromBinary(data, istr, cur_size)) + if (!LLSDSerialize::fromBinary(data, istr, cur_size, UNZIP_LLSD_MAX_DEPTH)) { free(result); return ZR_PARSE_ERROR; @@ -2253,13 +2262,24 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is, //and trailers are different for the formats. U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 size ) { + if (size == 0) + { + LL_WARNS() << "No data to unzip." << LL_ENDL; + return NULL; + } + U8* result = NULL; U32 cur_size = 0; z_stream strm; const U32 CHUNK = 0x4000; - U8 *in = new U8[size]; + U8 *in = new(std::nothrow) U8[size]; + if (in == NULL) + { + LL_WARNS() << "Memory allocation failure." << LL_ENDL; + return NULL; + } is.read((char*) in, size); U8 out[CHUNK]; diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index 9f58d44fe7..8165410e80 100644 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -77,7 +77,7 @@ public: * @return Returns the number of LLSD objects parsed into * data. Returns PARSE_FAILURE (-1) on parse failure. */ - S32 parse(std::istream& istr, LLSD& data, S32 max_bytes); + S32 parse(std::istream& istr, LLSD& data, S32 max_bytes, S32 max_depth = -1); /** Like parse(), but uses a different call (istream.getline()) to read by lines * This API is better suited for XML, where the parse cannot tell @@ -103,10 +103,12 @@ protected: * caller. * @param istr The input stream. * @param data[out] The newly parse structured data. + * @param max_depth Max depth parser will check before exiting + * with parse error, -1 - unlimited. * @return Returns the number of LLSD objects parsed into * data. Returns PARSE_FAILURE (-1) on parse failure. */ - virtual S32 doParse(std::istream& istr, LLSD& data) const = 0; + virtual S32 doParse(std::istream& istr, LLSD& data, S32 max_depth = -1) const = 0; /** * @brief Virtual default function for resetting the parser @@ -241,10 +243,12 @@ protected: * caller. * @param istr The input stream. * @param data[out] The newly parse structured data. Undefined on failure. + * @param max_depth Max depth parser will check before exiting + * with parse error, -1 - unlimited. * @return Returns the number of LLSD objects parsed into * data. Returns PARSE_FAILURE (-1) on parse failure. */ - virtual S32 doParse(std::istream& istr, LLSD& data) const; + virtual S32 doParse(std::istream& istr, LLSD& data, S32 max_depth = -1) const; private: /** @@ -252,18 +256,20 @@ private: * * @param istr The input stream. * @param map The map to add the parsed data. + * @param max_depth Allowed parsing depth. * @return Returns The number of LLSD objects parsed into data. */ - S32 parseMap(std::istream& istr, LLSD& map) const; + S32 parseMap(std::istream& istr, LLSD& map, S32 max_depth) const; /** * @brief Parse an array from the istream. * * @param istr The input stream. * @param array The array to append the parsed data. + * @param max_depth Allowed parsing depth. * @return Returns The number of LLSD objects parsed into data. */ - S32 parseArray(std::istream& istr, LLSD& array) const; + S32 parseArray(std::istream& istr, LLSD& array, S32 max_depth) const; /** * @brief Parse a string from the istream and assign it to data. @@ -314,10 +320,12 @@ protected: * caller. * @param istr The input stream. * @param data[out] The newly parse structured data. + * @param max_depth Max depth parser will check before exiting + * with parse error, -1 - unlimited. * @return Returns the number of LLSD objects parsed into * data. Returns PARSE_FAILURE (-1) on parse failure. */ - virtual S32 doParse(std::istream& istr, LLSD& data) const; + virtual S32 doParse(std::istream& istr, LLSD& data, S32 max_depth = -1) const; /** * @brief Virtual default function for resetting the parser @@ -362,10 +370,12 @@ protected: * caller. * @param istr The input stream. * @param data[out] The newly parse structured data. + * @param max_depth Max depth parser will check before exiting + * with parse error, -1 - unlimited. * @return Returns the number of LLSD objects parsed into * data. Returns -1 on parse failure. */ - virtual S32 doParse(std::istream& istr, LLSD& data) const; + virtual S32 doParse(std::istream& istr, LLSD& data, S32 max_depth = -1) const; private: /** @@ -373,18 +383,20 @@ private: * * @param istr The input stream. * @param map The map to add the parsed data. + * @param max_depth Allowed parsing depth. * @return Returns The number of LLSD objects parsed into data. */ - S32 parseMap(std::istream& istr, LLSD& map) const; + S32 parseMap(std::istream& istr, LLSD& map, S32 max_depth) const; /** * @brief Parse an array from the istream. * * @param istr The input stream. * @param array The array to append the parsed data. + * @param max_depth Allowed parsing depth. * @return Returns The number of LLSD objects parsed into data. */ - S32 parseArray(std::istream& istr, LLSD& array) const; + S32 parseArray(std::istream& istr, LLSD& array, S32 max_depth) const; /** * @brief Parse a string from the istream and assign it to data. @@ -800,16 +812,16 @@ public: LLPointer<LLSDBinaryFormatter> f = new LLSDBinaryFormatter; return f->format(sd, str, LLSDFormatter::OPTIONS_NONE); } - static S32 fromBinary(LLSD& sd, std::istream& str, S32 max_bytes) + static S32 fromBinary(LLSD& sd, std::istream& str, S32 max_bytes, S32 max_depth = -1) { LLPointer<LLSDBinaryParser> p = new LLSDBinaryParser; - return p->parse(str, sd, max_bytes); + return p->parse(str, sd, max_bytes, max_depth); } - static LLSD fromBinary(std::istream& str, S32 max_bytes) + static LLSD fromBinary(std::istream& str, S32 max_bytes, S32 max_depth = -1) { LLPointer<LLSDBinaryParser> p = new LLSDBinaryParser; LLSD sd; - (void)p->parse(str, sd, max_bytes); + (void)p->parse(str, sd, max_bytes, max_depth); return sd; } }; diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index 8d72a1c329..6d0fe862b9 100644 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -917,7 +917,7 @@ void LLSDXMLParser::parsePart(const char *buf, int len) } // virtual -S32 LLSDXMLParser::doParse(std::istream& input, LLSD& data) const +S32 LLSDXMLParser::doParse(std::istream& input, LLSD& data, S32 max_depth) const { #ifdef XML_PARSER_PERFORMANCE_TESTS XML_Timer timer( &parseTime ); diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 4a76d15096..dca03cfe04 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -588,7 +588,6 @@ std::string LLImage::sLastErrorMessage; LLMutex* LLImage::sMutex = NULL; bool LLImage::sUseNewByteRange = false; S32 LLImage::sMinimalReverseByteRangePercent = 75; -LLPrivateMemoryPool* LLImageBase::sPrivatePoolp = NULL ; //static void LLImage::initClass(bool use_new_byte_range, S32 minimal_reverse_byte_range_percent) @@ -596,8 +595,6 @@ void LLImage::initClass(bool use_new_byte_range, S32 minimal_reverse_byte_range_ sUseNewByteRange = use_new_byte_range; sMinimalReverseByteRangePercent = minimal_reverse_byte_range_percent; sMutex = new LLMutex(NULL); - - LLImageBase::createPrivatePool() ; } //static @@ -605,8 +602,6 @@ void LLImage::cleanupClass() { delete sMutex; sMutex = NULL; - - LLImageBase::destroyPrivatePool() ; } //static @@ -644,25 +639,6 @@ LLImageBase::~LLImageBase() deleteData(); // virtual } -//static -void LLImageBase::createPrivatePool() -{ - if(!sPrivatePoolp) - { - sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(LLPrivateMemoryPool::STATIC_THREADED) ; - } -} - -//static -void LLImageBase::destroyPrivatePool() -{ - if(sPrivatePoolp) - { - LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp) ; - sPrivatePoolp = NULL ; - } -} - // virtual void LLImageBase::dump() { @@ -696,7 +672,7 @@ void LLImageBase::sanityCheck() // virtual void LLImageBase::deleteData() { - FREE_MEM(sPrivatePoolp, mData) ; + ll_aligned_free_16(mData); disclaimMem(mDataSize); mDataSize = 0; mData = NULL; @@ -736,7 +712,7 @@ U8* LLImageBase::allocateData(S32 size) if (!mBadBufferAllocation && (!mData || size != mDataSize)) { deleteData(); // virtual - mData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size); + mData = (U8*)ll_aligned_malloc_16(size); if (!mData) { LL_WARNS() << "Failed to allocate image data size [" << size << "]" << LL_ENDL; @@ -763,7 +739,7 @@ U8* LLImageBase::allocateData(S32 size) // virtual U8* LLImageBase::reallocateData(S32 size) { - U8 *new_datap = (U8*)ALLOCATE_MEM(sPrivatePoolp, size); + U8 *new_datap = (U8*)ll_aligned_malloc_16(size); if (!new_datap) { LL_WARNS() << "Out of memory in LLImageBase::reallocateData" << LL_ENDL; @@ -773,7 +749,7 @@ U8* LLImageBase::reallocateData(S32 size) { S32 bytes = llmin(mDataSize, size); memcpy(new_datap, mData, bytes); /* Flawfinder: ignore */ - FREE_MEM(sPrivatePoolp, mData) ; + ll_aligned_free_16(mData) ; } mData = new_datap; disclaimMem(mDataSize); @@ -1470,7 +1446,7 @@ bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data ) if (new_data_size > 0) { - U8 *new_data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), new_data_size); + U8 *new_data = (U8*)ll_aligned_malloc_16(new_data_size); if(NULL == new_data) { return false; @@ -2169,7 +2145,7 @@ void LLImageFormatted::appendData(U8 *data, S32 size) S32 newsize = cursize + size; reallocateData(newsize); memcpy(getData() + cursize, data, size); - FREE_MEM(LLImageBase::getPrivatePool(), data); + ll_aligned_free_16(data); } } } diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 958c9fad3d..8ec49d3f0f 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -71,7 +71,6 @@ const S32 HTTP_PACKET_SIZE = 1496; class LLImageFormatted; class LLImageRaw; class LLColor4U; -class LLPrivateMemoryPool; typedef enum e_image_codec { @@ -160,10 +159,6 @@ public: static F32 calc_download_priority(F32 virtual_size, F32 visible_area, S32 bytes_sent); static EImageCodec getCodecFromExtension(const std::string& exten); - - static void createPrivatePool() ; - static void destroyPrivatePool() ; - static LLPrivateMemoryPool* getPrivatePool() {return sPrivatePoolp;} //static LLTrace::MemStatHandle sMemStat; @@ -178,8 +173,6 @@ private: bool mBadBufferAllocation ; bool mAllowOverSize ; - - static LLPrivateMemoryPool* sPrivatePoolp ; }; // Raw representation of an image (used for textures, and other uncompressed formats diff --git a/indra/llimage/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp index 0ec83415a0..3a7319d765 100644 --- a/indra/llimage/llimagedxt.cpp +++ b/indra/llimage/llimagedxt.cpp @@ -430,7 +430,7 @@ bool LLImageDXT::convertToDXR() S32 nmips = calcNumMips(width,height); S32 total_bytes = getDataSize(); U8* olddata = getData(); - U8* newdata = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), total_bytes); + U8* newdata = (U8*)ll_aligned_malloc_16(total_bytes); if (!newdata) { LL_ERRS() << "Out of memory in LLImageDXT::convertToDXR()" << LL_ENDL; diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index c40df009d8..4bff21610f 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -368,7 +368,7 @@ bool LLImageJ2C::loadAndValidate(const std::string &filename) } else { - U8 *data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), file_size); + U8 *data = (U8*)ll_aligned_malloc_16(file_size); if (!data) { infile.close(); @@ -383,7 +383,7 @@ bool LLImageJ2C::loadAndValidate(const std::string &filename) if (s != APR_SUCCESS || (S32)bytes_read != file_size) { - FREE_MEM(LLImageBase::getPrivatePool(), data); + ll_aligned_free_16(data); setLastError("Unable to read entire file"); res = false; } diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 24f46d720b..648f9a8d93 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2921,28 +2921,54 @@ F32 LLVolume::sculptGetSurfaceArea() return area; } -// create placeholder shape -void LLVolume::sculptGeneratePlaceholder() +// create empty placeholder shape +void LLVolume::sculptGenerateEmptyPlaceholder() { S32 sizeS = mPathp->mPath.size(); S32 sizeT = mProfilep->mProfile.size(); - + S32 line = 0; - // for now, this is a sphere. for (S32 s = 0; s < sizeS; s++) { for (S32 t = 0; t < sizeT; t++) { S32 i = t + line; LLVector4a& pt = mMesh[i]; + + F32* p = pt.getF32ptr(); - - F32 u = (F32)s/(sizeS-1); - F32 v = (F32)t/(sizeT-1); + p[0] = 0; + p[1] = 0; + p[2] = 0; + + llassert(pt.isFinite3()); + } + line += sizeT; + } +} + +// create sphere placeholder shape +void LLVolume::sculptGenerateSpherePlaceholder() +{ + S32 sizeS = mPathp->mPath.size(); + S32 sizeT = mProfilep->mProfile.size(); + + S32 line = 0; + + for (S32 s = 0; s < sizeS; s++) + { + for (S32 t = 0; t < sizeT; t++) + { + S32 i = t + line; + LLVector4a& pt = mMesh[i]; + + + F32 u = (F32)s / (sizeS - 1); + F32 v = (F32)t / (sizeT - 1); const F32 RADIUS = (F32) 0.3; - + F32* p = pt.getF32ptr(); p[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS); @@ -2950,7 +2976,6 @@ void LLVolume::sculptGeneratePlaceholder() p[2] = (F32)(cos(F_PI * v) * RADIUS); llassert(pt.isFinite3()); - } line += sizeT; } @@ -3113,9 +3138,9 @@ void sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 detail, S32 } // sculpt replaces generate() for sculpted surfaces -void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level) +void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder) { - U8 sculpt_type = mParams.getSculptType(); + U8 sculpt_type = mParams.getSculptType(); BOOL data_is_empty = FALSE; @@ -3163,13 +3188,22 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA) { data_is_empty = TRUE; + visible_placeholder = true; } } } if (data_is_empty) { - sculptGeneratePlaceholder(); + if (visible_placeholder) + { + // Object should be visible since there will be nothing else to display + sculptGenerateSpherePlaceholder(); + } + else + { + sculptGenerateEmptyPlaceholder(); + } } diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index a8089f3709..4357b69b90 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -1059,7 +1059,7 @@ public: U32 mFaceMask; // bit array of which faces exist in this volume LLVector3 mLODScaleBias; // vector for biasing LOD based on scale - void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level); + void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder); void copyVolumeFaces(const LLVolume* volume); void copyFacesTo(std::vector<LLVolumeFace> &faces) const; void copyFacesFrom(const std::vector<LLVolumeFace> &faces); @@ -1068,7 +1068,8 @@ public: private: void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type); F32 sculptGetSurfaceArea(); - void sculptGeneratePlaceholder(); + void sculptGenerateEmptyPlaceholder(); + void sculptGenerateSpherePlaceholder(); void sculptCalcMeshResolution(U16 width, U16 height, U8 type, S32& s, S32& t); diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index 680017204c..f3fd4277ce 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -1085,6 +1085,8 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) } else if(message_name == "name_text") { + mHistoryBackAvailable = message.getValueBoolean("history_back_available"); + mHistoryForwardAvailable = message.getValueBoolean("history_forward_available"); mMediaName = message.getValue("name"); mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED); } diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index de26d19efc..ab668dc192 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -31,6 +31,9 @@ // Freetype stuff #include <ft2build.h> +#ifdef LL_WINDOWS +#include <freetype2\freetype\ftsystem.h> +#endif // For some reason, this won't work if it's not wrapped in the ifdef #ifdef FT_FREETYPE_H @@ -106,6 +109,10 @@ LLFontFreetype::LLFontFreetype() mAscender(0.f), mDescender(0.f), mLineHeight(0.f), +#ifdef LL_WINDOWS + pFileStream(NULL), + pFtStream(NULL), +#endif mIsFallback(FALSE), mFTFace(NULL), mRenderGlyphCount(0), @@ -127,10 +134,29 @@ LLFontFreetype::~LLFontFreetype() std::for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer()); mCharGlyphInfoMap.clear(); +#ifdef LL_WINDOWS + delete pFileStream; // closed by FT_Done_Face + delete pFtStream; +#endif delete mFontBitmapCachep; // mFallbackFonts cleaned up by LLPointer destructor } +#ifdef LL_WINDOWS +unsigned long ft_read_cb(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count) { + if (count <= 0) return count; + llifstream *file_stream = static_cast<llifstream *>(stream->descriptor.pointer); + file_stream->seekg(offset, std::ios::beg); + file_stream->read((char*)buffer, count); + return file_stream->gcount(); +} + +void ft_close_cb(FT_Stream stream) { + llifstream *file_stream = static_cast<llifstream *>(stream->descriptor.pointer); + file_stream->close(); +} +#endif + BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback) { // Don't leak face objects. This is also needed to deal with @@ -143,13 +169,55 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v int error; +#ifdef LL_WINDOWS + pFileStream = new llifstream(filename, std::ios::binary); + if (pFileStream->is_open()) + { + std::streampos beg = pFileStream->tellg(); + pFileStream->seekg(0, std::ios::end); + std::streampos end = pFileStream->tellg(); + std::size_t file_size = end - beg; + pFileStream->seekg(0, std::ios::beg); + + pFtStream = new LLFT_Stream(); + pFtStream->base = 0; + pFtStream->pos = 0; + pFtStream->size = file_size; + pFtStream->descriptor.pointer = pFileStream; + pFtStream->read = ft_read_cb; + pFtStream->close = ft_close_cb; + + FT_Open_Args args; + args.flags = FT_OPEN_STREAM; + args.stream = (FT_StreamRec*)pFtStream; + + error = FT_Open_Face(gFTLibrary, + &args, + 0, + &mFTFace); + } + else + { + delete pFileStream; + pFileStream = NULL; + return FALSE; + } +#else error = FT_New_Face( gFTLibrary, filename.c_str(), 0, - &mFTFace ); + &mFTFace); +#endif - if (error) + if (error) { +#ifdef LL_WINDOWS + pFileStream->close(); + delete pFileStream; + delete pFtStream; + pFileStream = NULL; + pFtStream = NULL; +#endif return FALSE; } @@ -166,6 +234,13 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v { // Clean up freetype libs. FT_Done_Face(mFTFace); +#ifdef LL_WINDOWS + pFileStream->close(); + delete pFileStream; + delete pFtStream; + pFileStream = NULL; + pFtStream = NULL; +#endif mFTFace = NULL; return FALSE; } diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h index a5ece42b88..aadebf5e70 100644 --- a/indra/llrender/llfontfreetype.h +++ b/indra/llrender/llfontfreetype.h @@ -40,6 +40,8 @@ // We'll forward declare the struct here. JC struct FT_FaceRec_; typedef struct FT_FaceRec_* LLFT_Face; +struct FT_StreamRec_; +typedef struct FT_StreamRec_ LLFT_Stream; class LLFontManager { @@ -159,6 +161,11 @@ private: LLFT_Face mFTFace; +#ifdef LL_WINDOWS + llifstream *pFileStream; + LLFT_Stream *pFtStream; +#endif + BOOL mIsFallback; font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars) diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index d003687415..3c829596ce 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -447,7 +447,7 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) if (!fontp->loadFace(font_path, extra_scale * point_size, LLFontGL::sVertDPI, LLFontGL::sHorizDPI, 2, is_fallback)) { - LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << *file_name_it << LL_ENDL; + LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << *file_name_it << " from path " << local_path << LL_ENDL; delete fontp; fontp = NULL; } diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 155c2402bd..35b6951779 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -1348,8 +1348,19 @@ void LLGLManager::initExtensions() if (mHasVertexShader) { LL_INFOS() << "initExtensions() VertexShader-related procs..." << LL_ENDL; + + // nSight doesn't support use of ARB funcs that have been normalized in the API + if (!LLRender::sNsightDebugSupport) + { glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocationARB"); glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocationARB"); + } + else + { + glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocation"); + glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocation"); + } + glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveAttribARB"); glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dARB"); glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dvARB"); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 76f28bb43f..65d6181920 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -49,6 +49,7 @@ U32 LLRender::sUICalls = 0; U32 LLRender::sUIVerts = 0; U32 LLTexUnit::sWhiteTexture = 0; bool LLRender::sGLCoreProfile = false; +bool LLRender::sNsightDebugSupport = false; static const U32 LL_NUM_TEXTURE_LAYERS = 32; static const U32 LL_NUM_LIGHT_UNITS = 8; diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index a67fb8da52..2573129fd3 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -438,7 +438,8 @@ public: static U32 sUICalls; static U32 sUIVerts; static bool sGLCoreProfile; - + static bool sNsightDebugSupport; + private: friend class LLLightState; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index f10301b42d..a55ca5ed9c 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -98,7 +98,6 @@ U32 LLVertexBuffer::sCurVAOName = 1; U32 LLVertexBuffer::sAllocatedIndexBytes = 0; U32 LLVertexBuffer::sIndexCount = 0; -LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL; U32 LLVertexBuffer::sBindCount = 0; U32 LLVertexBuffer::sSetCount = 0; S32 LLVertexBuffer::sCount = 0; @@ -191,6 +190,10 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed) if (mUsage != GL_DYNAMIC_COPY_ARB) { //data will be provided by application ret = (U8*) ll_aligned_malloc<64>(size); + if (!ret) + { + LL_ERRS() << "Failed to allocate for LLVBOPool buffer" << LL_ENDL; + } } } else @@ -859,11 +862,6 @@ void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping) { sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject; sDisableVBOMapping = sEnableVBOs && no_vbo_mapping; - - if (!sPrivatePoolp) - { - sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(LLPrivateMemoryPool::STATIC); - } } //static @@ -906,12 +904,6 @@ void LLVertexBuffer::cleanupClass() sStreamVBOPool.cleanup(); sDynamicVBOPool.cleanup(); sDynamicCopyVBOPool.cleanup(); - - if(sPrivatePoolp) - { - LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp); - sPrivatePoolp = NULL; - } } //---------------------------------------------------------------------------- @@ -1202,7 +1194,7 @@ bool LLVertexBuffer::createGLBuffer(U32 size) { static int gl_buffer_idx = 0; mGLBuffer = ++gl_buffer_idx; - mMappedData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size); + mMappedData = (U8*)ll_aligned_malloc_16(size); disclaimMem(mSize); mSize = size; claimMem(mSize); @@ -1244,7 +1236,7 @@ bool LLVertexBuffer::createGLIndices(U32 size) } else { - mMappedIndexData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size); + mMappedIndexData = (U8*)ll_aligned_malloc_16(size); static int gl_buffer_idx = 0; mGLIndices = ++gl_buffer_idx; mIndicesSize = size; @@ -1267,7 +1259,7 @@ void LLVertexBuffer::destroyGLBuffer() } else { - FREE_MEM(sPrivatePoolp, (void*) mMappedData); + ll_aligned_free_16((void*)mMappedData); mMappedData = NULL; mEmpty = true; } @@ -1287,7 +1279,7 @@ void LLVertexBuffer::destroyGLIndices() } else { - FREE_MEM(sPrivatePoolp, (void*) mMappedIndexData); + ll_aligned_free_16((void*)mMappedIndexData); mMappedIndexData = NULL; mEmpty = true; } diff --git a/indra/llui/llbadge.cpp b/indra/llui/llbadge.cpp index 15b6899d74..589b75ab5b 100644 --- a/indra/llui/llbadge.cpp +++ b/indra/llui/llbadge.cpp @@ -102,6 +102,7 @@ LLBadge::LLBadge(const LLBadge::Params& p) , mPaddingHoriz(p.padding_horiz) , mPaddingVert(p.padding_vert) , mParentScroller(NULL) + , mDrawAtParentTop(false) { if (mImage.isNull()) { @@ -307,7 +308,14 @@ void LLBadge::draw() // Compute y position if (mLocationOffsetVCenter == BADGE_OFFSET_NOT_SPECIFIED) { - badge_center_y = owner_rect.mBottom + owner_rect.getHeight() * mLocationPercentVCenter; + if(mDrawAtParentTop) + { + badge_center_y = owner_rect.mTop - badge_height * 0.5f - 1; + } + else + { + badge_center_y = owner_rect.mBottom + owner_rect.getHeight() * mLocationPercentVCenter; + } } else { diff --git a/indra/llui/llbadge.h b/indra/llui/llbadge.h index 4b21a71aaa..55f92e6e34 100644 --- a/indra/llui/llbadge.h +++ b/indra/llui/llbadge.h @@ -137,6 +137,8 @@ public: const std::string getLabel() const { return wstring_to_utf8str(mLabel); } void setLabel( const LLStringExplicit& label); + void setDrawAtParentTop(bool draw_at_top) { mDrawAtParentTop = draw_at_top;} + private: LLPointer< LLUIImage > mBorderImage; LLUIColor mBorderColor; @@ -164,6 +166,7 @@ private: F32 mPaddingVert; LLScrollContainer* mParentScroller; + bool mDrawAtParentTop; }; // Build time optimization, generate once in .cpp file diff --git a/indra/llui/llbadgeowner.cpp b/indra/llui/llbadgeowner.cpp index 55e64bb940..0557cd4375 100644 --- a/indra/llui/llbadgeowner.cpp +++ b/indra/llui/llbadgeowner.cpp @@ -64,6 +64,14 @@ void LLBadgeOwner::setBadgeVisibility(bool visible) } } +void LLBadgeOwner::setDrawBadgeAtTop(bool draw_at_top) +{ + if (mBadge) + { + mBadge->setDrawAtParentTop(draw_at_top); + } +} + void LLBadgeOwner::addBadgeToParentHolder() { LLView * owner_view = mBadgeOwnerView.get(); diff --git a/indra/llui/llbadgeowner.h b/indra/llui/llbadgeowner.h index 53c2de95c8..01ed95f3a3 100644 --- a/indra/llui/llbadgeowner.h +++ b/indra/llui/llbadgeowner.h @@ -45,6 +45,7 @@ public: bool hasBadgeHolderParent() const { return mHasBadgeHolderParent; }; void setBadgeVisibility(bool visible); + void setDrawBadgeAtTop(bool draw_at_top); private: diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index becb45fa79..bd6b00d38b 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -1630,12 +1630,12 @@ BOOL LLLineEditor::handleUnicodeCharHere(llwchar uni_char) BOOL LLLineEditor::canDoDelete() const { - return ( !mReadOnly && mText.length() > 0 && (!mPassDelete || (hasSelection() || (getCursor() < mText.length()))) ); + return ( !mReadOnly && (!mPassDelete || (hasSelection() || (getCursor() < mText.length()))) ); } void LLLineEditor::doDelete() { - if (canDoDelete()) + if (canDoDelete() && mText.length() > 0) { // Prepare for possible rollback LLLineEditorRollback rollback( this ); diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 7c1f4a4dca..212e27477b 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -1964,6 +1964,10 @@ BOOL LLScrollListCtrl::handleClick(S32 x, S32 y, MASK mask) LLScrollListCell* cellp = item->getColumn(column_index); cellp->setValue(item_value); cellp->onCommit(); + if (mLastSelected == NULL) + { + break; + } } } //FIXME: find a better way to signal cell changes diff --git a/indra/llui/lltrans.cpp b/indra/llui/lltrans.cpp index 4d4ff4236d..a1a8feedaa 100644 --- a/indra/llui/lltrans.cpp +++ b/indra/llui/lltrans.cpp @@ -36,6 +36,7 @@ #include <map> LLTrans::template_map_t LLTrans::sStringTemplates; +LLTrans::template_map_t LLTrans::sDefaultStringTemplates; LLStringUtil::format_map_t LLTrans::sDefaultArgs; struct StringDef : public LLInitParam::Block<StringDef> @@ -76,7 +77,7 @@ bool LLTrans::parseStrings(LLXMLNodePtr &root, const std::set<std::string>& defa LL_ERRS() << "Problem reading strings: " << xml_filename << LL_ENDL; return false; } - + static bool default_strings_init = false; sStringTemplates.clear(); sDefaultArgs.clear(); @@ -86,7 +87,10 @@ bool LLTrans::parseStrings(LLXMLNodePtr &root, const std::set<std::string>& defa { LLTransTemplate xml_template(it->name, it->value); sStringTemplates[xml_template.mName] = xml_template; - + if (!default_strings_init) + { + sDefaultStringTemplates[xml_template.mName] = xml_template; + } std::set<std::string>::const_iterator iter = default_args.find(xml_template.mName); if (iter != default_args.end()) { @@ -96,6 +100,7 @@ bool LLTrans::parseStrings(LLXMLNodePtr &root, const std::set<std::string>& defa sDefaultArgs[name] = xml_template.mText; } } + default_strings_init = true; return true; } @@ -138,12 +143,17 @@ bool LLTrans::parseLanguageStrings(LLXMLNodePtr &root) static LLTrace::BlockTimerStatHandle FTM_GET_TRANS("Translate string"); //static -std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& msg_args) +std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& msg_args, bool def_string) { // Don't care about time as much as call count. Make sure we're not // calling LLTrans::getString() in an inner loop. JC LL_RECORD_BLOCK_TIME(FTM_GET_TRANS); + if (def_string) + { + return getDefString(xml_desc, msg_args); + } + template_map_t::iterator iter = sStringTemplates.find(xml_desc); if (iter != sStringTemplates.end()) { @@ -161,13 +171,38 @@ std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil:: } } +//static +std::string LLTrans::getDefString(const std::string &xml_desc, const LLStringUtil::format_map_t& msg_args) +{ + template_map_t::iterator iter = sDefaultStringTemplates.find(xml_desc); + if (iter != sDefaultStringTemplates.end()) + { + std::string text = iter->second.mText; + LLStringUtil::format_map_t args = sDefaultArgs; + args.insert(msg_args.begin(), msg_args.end()); + LLStringUtil::format(text, args); + + return text; + } + else + { + LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL; + return "MissingString(" + xml_desc + ")"; + } +} + //static -std::string LLTrans::getString(const std::string &xml_desc, const LLSD& msg_args) +std::string LLTrans::getString(const std::string &xml_desc, const LLSD& msg_args, bool def_string) { // Don't care about time as much as call count. Make sure we're not // calling LLTrans::getString() in an inner loop. JC LL_RECORD_BLOCK_TIME(FTM_GET_TRANS); + if (def_string) + { + return getDefString(xml_desc, msg_args); + } + template_map_t::iterator iter = sStringTemplates.find(xml_desc); if (iter != sStringTemplates.end()) { @@ -182,6 +217,23 @@ std::string LLTrans::getString(const std::string &xml_desc, const LLSD& msg_args } } +//static +std::string LLTrans::getDefString(const std::string &xml_desc, const LLSD& msg_args) +{ + template_map_t::iterator iter = sDefaultStringTemplates.find(xml_desc); + if (iter != sDefaultStringTemplates.end()) + { + std::string text = iter->second.mText; + LLStringUtil::format(text, msg_args); + return text; + } + else + { + LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL; + return "MissingString(" + xml_desc + ")"; + } +} + //static bool LLTrans::findString(std::string &result, const std::string &xml_desc, const LLStringUtil::format_map_t& msg_args) { diff --git a/indra/llui/lltrans.h b/indra/llui/lltrans.h index a47ce94f08..9bd751fc78 100644 --- a/indra/llui/lltrans.h +++ b/indra/llui/lltrans.h @@ -76,8 +76,10 @@ public: * @param args A list of substrings to replace in the string * @returns Translated string */ - static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args); - static std::string getString(const std::string &xml_desc, const LLSD& args); + static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args, bool def_string = false); + static std::string getDefString(const std::string &xml_desc, const LLStringUtil::format_map_t& args); + static std::string getString(const std::string &xml_desc, const LLSD& args, bool def_string = false); + static std::string getDefString(const std::string &xml_desc, const LLSD& args); static bool findString(std::string &result, const std::string &xml_desc, const LLStringUtil::format_map_t& args); static bool findString(std::string &result, const std::string &xml_desc, const LLSD& args); @@ -92,7 +94,7 @@ public: * @param xml_desc String's description * @returns Translated string */ - static std::string getString(const std::string &xml_desc) + static std::string getString(const std::string &xml_desc, bool def_string = false) { LLStringUtil::format_map_t empty; return getString(xml_desc, empty); @@ -128,6 +130,7 @@ public: private: typedef std::map<std::string, LLTransTemplate > template_map_t; static template_map_t sStringTemplates; + static template_map_t sDefaultStringTemplates; static LLStringUtil::format_map_t sDefaultArgs; }; diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index c4a4c74d1e..cfbc5803c7 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -233,7 +233,7 @@ void LLDir_Win32::initAppDirs(const std::string &app_name, LL_WARNS() << "Couldn't create LL_PATH_CACHE dir " << getExpandedFilename(LL_PATH_CACHE,"") << LL_ENDL; } - mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "ca-bundle.crt"); + mCAFile = gDirUtilp->getExpandedFilename( LL_PATH_EXECUTABLE, "app_settings", "ca-bundle.crt" ); } U32 LLDir_Win32::countFilesInDir(const std::string &dirname, const std::string &mask) diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp index db0eac7031..d5bd1834c2 100644 --- a/indra/llvfs/llvfs.cpp +++ b/indra/llvfs/llvfs.cpp @@ -2120,7 +2120,11 @@ time_t LLVFS::creationTime() int errors = LLFile::stat(mDataFilename, &data_file_stat); if (0 == errors) { - return data_file_stat.st_ctime; + time_t creation_time = data_file_stat.st_ctime; +#if LL_DARWIN + creation_time = data_file_stat.st_birthtime; +#endif + return creation_time; } return 0; } diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 9fa07d1d34..6e3aba51cf 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -69,6 +69,10 @@ const F32 ICON_FLASH_TIME = 0.5f; #define WM_DPICHANGED 0x02E0 #endif +#ifndef USER_DEFAULT_SCREEN_DPI +#define USER_DEFAULT_SCREEN_DPI 96 // Win7 +#endif + extern BOOL gDebugWindowProc; LPWSTR gIconResource = IDI_APPLICATION; @@ -1545,7 +1549,10 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO (LLRender::sGLCoreProfile ? " core" : " compatibility") << " context." << LL_ENDL; done = true; - if (LLRender::sGLCoreProfile) + // force sNoFixedFunction iff we're trying to use nsight debugging which does not support many legacy API uses + + // nSight doesn't support use of legacy API funcs in the fixed function pipe + if (LLRender::sGLCoreProfile || LLRender::sNsightDebugSupport) { LLGLSLShader::sNoFixedFunction = true; } diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index f3d7762a08..4dbee12ea0 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -194,6 +194,8 @@ void MediaPluginCEF::onTitleChangeCallback(std::string title) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); message.setValue("name", title); + message.setValueBoolean("history_back_available", mCEFLib->canGoBack()); + message.setValueBoolean("history_forward_available", mCEFLib->canGoForward()); sendMessage(message); } diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index 8aabd6818b..af4cf26ac6 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -21,7 +21,7 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> - <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string> + <string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index dd07972249..756e4b6616 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2369,7 +2369,7 @@ <key>Value</key> <integer>0</integer> </map> - <key>DebugShowPrivateMem</key> + <key>DEPRECATED: DebugShowPrivateMem</key> <!-- deprecated (see MAINT-8091) --> <map> <key>Comment</key> <string>Show Private Mem Info</string> @@ -6408,10 +6408,10 @@ <key>Value</key> <real>600.0</real> </map> - <key>MemoryPrivatePoolEnabled</key> + <key>MemoryPrivatePoolEnabled</key> <!-- deprecated (see MAINT-8091) --> <map> <key>Comment</key> - <string>Enable the private memory pool management</string> + <string>DEPRECATED: Enable the private memory pool management</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -6419,10 +6419,10 @@ <key>Value</key> <integer>0</integer> </map> - <key>MemoryPrivatePoolSize</key> + <key>MemoryPrivatePoolSize</key> <!-- deprecated (see MAINT-8091) --> <map> <key>Comment</key> - <string>Size of the private memory pool in MB (min. value is 256)</string> + <string>DEPRECATED: Size of the private memory pool in MB (min. value is 256)</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -8631,7 +8631,19 @@ <key>Value</key> <integer>0</integer> </map> - + <key>RenderNsightDebugSupport</key> + <map> + <key>Comment</key> + <string> + Disable features which prevent nVidia nSight from being usable with SL. Requires restart. + </string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>RenderLocalLights</key> <map> <key>Comment</key> diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 0fb811a386..c0f88ef704 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1919,7 +1919,7 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id) } // Check whether it's the base outfit. - if (outfit_cat_id.isNull() || outfit_cat_id == getBaseOutfitUUID()) + if (outfit_cat_id.isNull()) { return false; } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 464e216cf0..a0750214a8 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -353,6 +353,8 @@ BOOL gCrashOnStartup = FALSE; BOOL gLLErrorActivated = FALSE; BOOL gLogoutInProgress = FALSE; +BOOL gSimulateMemLeak = FALSE; + //////////////////////////////////////////////////////////// // Internal globals... that should be removed. static std::string gArgs; @@ -581,6 +583,7 @@ static void settings_to_globals() LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize")); LLRender::sGLCoreProfile = gSavedSettings.getBOOL("RenderGLCoreProfile"); + LLRender::sNsightDebugSupport = gSavedSettings.getBOOL("RenderNsightDebugSupport"); LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO"); LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic"); LLImageGL::sCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures"); @@ -797,7 +800,6 @@ bool LLAppViewer::init() initMaxHeapSize() ; LLCoros::instance().setStackSize(gSavedSettings.getS32("CoroutineStackSize")); - LLPrivateMemoryPoolManager::initClass((BOOL)gSavedSettings.getBOOL("MemoryPrivatePoolEnabled"), (U32)gSavedSettings.getU32("MemoryPrivatePoolSize")*1024*1024) ; // write Google Breakpad minidump files to a per-run dump directory to avoid multiple viewer issues. std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, ""); mDumpPath = logdir; @@ -1318,13 +1320,49 @@ LLTrace::BlockTimerStatHandle FTM_FRAME("Frame"); bool LLAppViewer::frame() { + bool ret = false; + + if (gSimulateMemLeak) + { + try + { + ret = doFrame(); + } + catch (const LLContinueError&) + { + LOG_UNHANDLED_EXCEPTION(""); + } + catch (std::bad_alloc) + { + LLMemory::logMemoryInfo(TRUE); + LLFloaterMemLeak* mem_leak_instance = LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); + if (mem_leak_instance) + { + mem_leak_instance->stop(); + } + LL_WARNS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL; + } + } + else + { + try + { + ret = doFrame(); + } + catch (const LLContinueError&) + { + LOG_UNHANDLED_EXCEPTION(""); + } + } + + return ret; +} + +bool LLAppViewer::doFrame() +{ LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); LLSD newFrame; - //LLPrivateMemoryPoolTester::getInstance()->run(false) ; - //LLPrivateMemoryPoolTester::getInstance()->run(true) ; - //LLPrivateMemoryPoolTester::destroy() ; - LL_RECORD_BLOCK_TIME(FTM_FRAME); LLTrace::BlockTimer::processTimes(); LLTrace::get_frame_recording().nextPeriod(); @@ -1338,7 +1376,6 @@ bool LLAppViewer::frame() //check memory availability information checkMemory() ; - try { pingMainloopTimeout("Main:MiscNativeWindowEvents"); @@ -1362,12 +1399,15 @@ bool LLAppViewer::frame() } //memory leaking simulation - LLFloaterMemLeak* mem_leak_instance = - LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); - if(mem_leak_instance) + if (gSimulateMemLeak) { - mem_leak_instance->idle() ; - } + LLFloaterMemLeak* mem_leak_instance = + LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); + if (mem_leak_instance) + { + mem_leak_instance->idle(); + } + } // canonical per-frame event mainloop.post(newFrame); @@ -1542,60 +1582,13 @@ bool LLAppViewer::frame() pingMainloopTimeout("Main:End"); } } - catch (const LLContinueError&) - { - LOG_UNHANDLED_EXCEPTION(""); - } - catch(std::bad_alloc) - { - LLMemory::logMemoryInfo(TRUE) ; - - //stop memory leaking simulation - LLFloaterMemLeak* mem_leak_instance = - LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); - if(mem_leak_instance) - { - mem_leak_instance->stop() ; - LL_WARNS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ; - } - else - { - //output possible call stacks to log file. - LLError::LLCallStacks::print() ; - - LL_ERRS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ; - } - } - catch (...) - { - CRASH_ON_UNHANDLED_EXCEPTION(""); - } if (LLApp::isExiting()) { // Save snapshot for next time, if we made it through initialization if (STATE_STARTED == LLStartUp::getStartupState()) { - try - { - saveFinalSnapshot(); - } - catch(std::bad_alloc) - { - LL_WARNS() << "Bad memory allocation when saveFinalSnapshot() is called!" << LL_ENDL ; - - //stop memory leaking simulation - LLFloaterMemLeak* mem_leak_instance = - LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); - if(mem_leak_instance) - { - mem_leak_instance->stop() ; - } - } - catch (...) - { - CRASH_ON_UNHANDLED_EXCEPTION("saveFinalSnapshot()"); - } + saveFinalSnapshot(); } delete gServicePump; @@ -2078,9 +2071,6 @@ bool LLAppViewer::cleanup() LLMainLoopRepeater::instance().stop(); - //release all private memory pools. - LLPrivateMemoryPoolManager::destroyClass() ; - ll_close_fail_log(); LLError::LLCallStacks::cleanup(); @@ -3230,7 +3220,7 @@ LLSD LLAppViewer::getViewerInfo() const return info; } -std::string LLAppViewer::getViewerInfoString() const +std::string LLAppViewer::getViewerInfoString(bool default_string) const { std::ostringstream support; @@ -3240,7 +3230,7 @@ std::string LLAppViewer::getViewerInfoString() const LLStringUtil::format_map_t args; // allow the "Release Notes" URL label to be localized - args["ReleaseNotes"] = LLTrans::getString("ReleaseNotes"); + args["ReleaseNotes"] = LLTrans::getString("ReleaseNotes", default_string); for (LLSD::map_const_iterator ii(info.beginMap()), iend(info.endMap()); ii != iend; ++ii) @@ -3250,7 +3240,7 @@ std::string LLAppViewer::getViewerInfoString() const // Scalar value if (ii->second.isUndefined()) { - args[ii->first] = LLTrans::getString("none_text"); + args[ii->first] = LLTrans::getString("none_text", default_string); } else { @@ -3269,101 +3259,37 @@ std::string LLAppViewer::getViewerInfoString() const } // Now build the various pieces - support << LLTrans::getString("AboutHeader", args); + support << LLTrans::getString("AboutHeader", args, default_string); if (info.has("BUILD_CONFIG")) { - support << "\n" << LLTrans::getString("BuildConfig", args); + support << "\n" << LLTrans::getString("BuildConfig", args, default_string); } if (info.has("REGION")) { - support << "\n\n" << LLTrans::getString("AboutPosition", args); + support << "\n\n" << LLTrans::getString("AboutPosition", args, default_string); } - support << "\n\n" << LLTrans::getString("AboutSystem", args); + support << "\n\n" << LLTrans::getString("AboutSystem", args, default_string); support << "\n"; if (info.has("GRAPHICS_DRIVER_VERSION")) { - support << "\n" << LLTrans::getString("AboutDriver", args); + support << "\n" << LLTrans::getString("AboutDriver", args, default_string); } - support << "\n" << LLTrans::getString("AboutOGL", args); - support << "\n\n" << LLTrans::getString("AboutSettings", args); - support << "\n\n" << LLTrans::getString("AboutLibs", args); + support << "\n" << LLTrans::getString("AboutOGL", args, default_string); + support << "\n\n" << LLTrans::getString("AboutSettings", args, default_string); + support << "\n\n" << LLTrans::getString("AboutLibs", args, default_string); if (info.has("COMPILER")) { - support << "\n" << LLTrans::getString("AboutCompiler", args); + support << "\n" << LLTrans::getString("AboutCompiler", args, default_string); } if (info.has("PACKETS_IN")) { - support << '\n' << LLTrans::getString("AboutTraffic", args); + support << '\n' << LLTrans::getString("AboutTraffic", args, default_string); } // SLT timestamp LLSD substitution; substitution["datetime"] = (S32)time(NULL);//(S32)time_corrected(); - support << "\n" << LLTrans::getString("AboutTime", substitution); - - return support.str(); -} - -std::string LLAppViewer::getShortViewerInfoString() const -{ - std::ostringstream support; - LLSD info(getViewerInfo()); - - support << LLTrans::getString("APP_NAME") << " " << info["VIEWER_VERSION_STR"].asString(); - support << " (" << info["CHANNEL"].asString() << ")"; - if (info.has("BUILD_CONFIG")) - { - support << "\n" << "Build Configuration " << info["BUILD_CONFIG"].asString(); - } - if (info.has("REGION")) - { - support << "\n\n" << "You are at " << ll_vector3_from_sd(info["POSITION_LOCAL"]) << " in " << info["REGION"].asString(); - support << " located at " << info["HOSTNAME"].asString() << " (" << info["HOSTIP"].asString() << ")"; - support << "\n" << "SLURL: " << info["SLURL"].asString(); - support << "\n" << "(Global coordinates " << ll_vector3_from_sd(info["POSITION"]) << ")"; - support << "\n" << info["SERVER_VERSION"].asString(); - } - - support << "\n\n" << "CPU: " << info["CPU"].asString(); - support << "\n" << "Memory: " << info["MEMORY_MB"].asString() << " MB"; - support << "\n" << "OS: " << info["OS_VERSION"].asString(); - support << "\n" << "Graphics Card: " << info["GRAPHICS_CARD"].asString() << " (" << info["GRAPHICS_CARD_VENDOR"].asString() << ")"; - - if (info.has("GRAPHICS_DRIVER_VERSION")) - { - support << "\n" << "Windows Graphics Driver Version: " << info["GRAPHICS_DRIVER_VERSION"].asString(); - } - - support << "\n" << "OpenGL Version: " << info["OPENGL_VERSION"].asString(); - - support << "\n\n" << "Window size:" << info["WINDOW_WIDTH"].asString() << "x" << info["WINDOW_HEIGHT"].asString(); - support << "\n" << "Language: " << LLUI::getLanguage(); - support << "\n" << "Font Size Adjustment: " << info["FONT_SIZE_ADJUSTMENT"].asString() << "pt"; - support << "\n" << "UI Scaling: " << info["UI_SCALE"].asString(); - support << "\n" << "Draw distance: " << info["DRAW_DISTANCE"].asString(); - support << "\n" << "Bandwidth: " << info["NET_BANDWITH"].asString() << "kbit/s"; - support << "\n" << "LOD factor: " << info["LOD_FACTOR"].asString(); - support << "\n" << "Render quality: " << info["RENDER_QUALITY"].asString() << " / 7"; - support << "\n" << "ALM: " << info["GPU_SHADERS"].asString(); - support << "\n" << "Texture memory: " << info["TEXTURE_MEMORY"].asString() << "MB"; - support << "\n" << "VFS (cache) creation time: " << info["VFS_TIME"].asString(); - - support << "\n\n" << "J2C Decoder: " << info["J2C_VERSION"].asString(); - support << "\n" << "Audio Driver: " << info["AUDIO_DRIVER_VERSION"].asString(); - support << "\n" << "LLCEFLib/CEF: " << info["LLCEFLIB_VERSION"].asString(); - support << "\n" << "LibVLC: " << info["LIBVLC_VERSION"].asString(); - support << "\n" << "Voice Server: " << info["VOICE_VERSION"].asString(); - - if (info.has("PACKETS_IN")) - { - support << "\n" << "Packets Lost: " << info["PACKETS_LOST"].asInteger() << "/" << info["PACKETS_IN"].asInteger(); - F32 packets_pct = info["PACKETS_PCT"].asReal(); - support << " (" << ll_round(packets_pct, 0.001f) << "%)"; - } - - LLSD substitution; - substitution["datetime"] = (S32)time(NULL); - support << "\n" << LLTrans::getString("AboutTime", substitution); + support << "\n" << LLTrans::getString("AboutTime", substitution, default_string); return support.str(); } diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 6eb45d2495..e607b4a994 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -99,8 +99,7 @@ public: void setServerReleaseNotesURL(const std::string& url) { mServerReleaseNotesURL = url; } LLSD getViewerInfo() const; - std::string getViewerInfoString() const; - std::string getShortViewerInfoString() const; + std::string getViewerInfoString(bool default_string = false) const; // Report true if under the control of a debugger. A null-op default. virtual bool beingDebugged() { return false; } @@ -222,6 +221,8 @@ protected: private: + bool doFrame(); + void initMaxHeapSize(); bool initThreads(); // Initialize viewer threads, return false on failure. bool initConfiguration(); // Initialize settings from the command line/config file. @@ -396,4 +397,6 @@ extern LLUUID gBlackSquareID; extern BOOL gRandomizeFramerate; extern BOOL gPeriodicSlowFrame; +extern BOOL gSimulateMemLeak; + #endif // LL_LLAPPVIEWER_H diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp index 1de4102dba..43b01fa2f1 100644 --- a/indra/newview/llfacebookconnect.cpp +++ b/indra/newview/llfacebookconnect.cpp @@ -503,13 +503,10 @@ LLFacebookConnect::LLFacebookConnect() void LLFacebookConnect::openFacebookWeb(std::string url) { - // Open the URL in an internal browser window without navigation UI LLFloaterWebContent::Params p; p.url(url); p.show_chrome(true); - p.allow_address_entry(false); p.allow_back_forward_navigation(false); - p.trusted_content(true); p.clean_browser(true); LLFloater *floater = LLFloaterReg::showInstance("fbc_web", p); //the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems). diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 9219dd0279..34d0972d72 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -435,18 +435,22 @@ void LLFastTimerView::onClose(bool app_quitting) void saveChart(const std::string& label, const char* suffix, LLImageRaw* scratch) { - //read result back into raw image - glReadPixels(0, 0, 1024, 512, GL_RGB, GL_UNSIGNED_BYTE, scratch->getData()); + // disable use of glReadPixels which messes up nVidia nSight graphics debugging + if (!LLRender::sNsightDebugSupport) + { + //read result back into raw image + glReadPixels(0, 0, 1024, 512, GL_RGB, GL_UNSIGNED_BYTE, scratch->getData()); - //write results to disk - LLPointer<LLImagePNG> result = new LLImagePNG(); - result->encode(scratch, 0.f); + //write results to disk + LLPointer<LLImagePNG> result = new LLImagePNG(); + result->encode(scratch, 0.f); - std::string ext = result->getExtension(); - std::string filename = llformat("%s_%s.%s", label.c_str(), suffix, ext.c_str()); + std::string ext = result->getExtension(); + std::string filename = llformat("%s_%s.%s", label.c_str(), suffix, ext.c_str()); - std::string out_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, filename); - result->save(out_file); + std::string out_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, filename); + result->save(out_file); + } } //static diff --git a/indra/newview/llfilteredwearablelist.cpp b/indra/newview/llfilteredwearablelist.cpp index e67a6a2b77..2bfaa1e5bc 100644 --- a/indra/newview/llfilteredwearablelist.cpp +++ b/indra/newview/llfilteredwearablelist.cpp @@ -32,6 +32,7 @@ #include "llinventoryitemslist.h" #include "llinventorymodel.h" #include "llviewerinventory.h" +#include "lltrans.h" LLFilteredWearableListManager::LLFilteredWearableListManager(LLInventoryItemsList* list, LLInventoryCollectFunctor* collector) @@ -118,6 +119,11 @@ void LLFilteredWearableListManager::populateList() // Probably will also need to get items from Library (waiting for reply in EXT-6724). + if (item_array.empty() && gInventory.isCategoryComplete(gInventory.getRootFolderID())) + { + mWearableList->setNoItemsCommentText(LLTrans::getString("NoneFound")); + } + mWearableList->refreshList(item_array); } diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp index c0ca5b8cf8..d7d161f239 100644 --- a/indra/newview/llflickrconnect.cpp +++ b/indra/newview/llflickrconnect.cpp @@ -397,13 +397,10 @@ LLFlickrConnect::LLFlickrConnect() void LLFlickrConnect::openFlickrWeb(std::string url) { - // Open the URL in an internal browser window without navigation UI LLFloaterWebContent::Params p; p.url(url); p.show_chrome(true); - p.allow_address_entry(false); p.allow_back_forward_navigation(false); - p.trusted_content(true); p.clean_browser(true); LLFloater *floater = LLFloaterReg::showInstance("flickr_web", p); //the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems). diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index a9e4d752ac..0c2bb25e07 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -793,7 +793,7 @@ void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance) if (imagep) { - mVolume->sculpt(imagep->getWidth(), imagep->getHeight(), imagep->getComponents(), imagep->getData(), 0); + mVolume->sculpt(imagep->getWidth(), imagep->getHeight(), imagep->getComponents(), imagep->getData(), 0, false); } const LLVolumeFace &vf = mVolume->getVolumeFace(0); diff --git a/indra/newview/llfloatermemleak.cpp b/indra/newview/llfloatermemleak.cpp index 9edfe1e354..c43526acaf 100644 --- a/indra/newview/llfloatermemleak.cpp +++ b/indra/newview/llfloatermemleak.cpp @@ -42,6 +42,8 @@ U32 LLFloaterMemLeak::sTotalLeaked = 0 ; S32 LLFloaterMemLeak::sStatus = LLFloaterMemLeak::STOP ; BOOL LLFloaterMemLeak::sbAllocationFailed = FALSE ; +extern BOOL gSimulateMemLeak; + LLFloaterMemLeak::LLFloaterMemLeak(const LLSD& key) : LLFloater(key) { @@ -104,6 +106,7 @@ void LLFloaterMemLeak::release() sStatus = STOP ; sTotalLeaked = 0 ; sbAllocationFailed = FALSE ; + gSimulateMemLeak = FALSE; } void LLFloaterMemLeak::stop() @@ -140,8 +143,7 @@ void LLFloaterMemLeak::idle() } if(!p) { - sStatus = STOP ; - sbAllocationFailed = TRUE ; + stop(); } } @@ -181,6 +183,7 @@ void LLFloaterMemLeak::onChangeMaxMemLeaking() void LLFloaterMemLeak::onClickStart() { sStatus = START ; + gSimulateMemLeak = TRUE; } void LLFloaterMemLeak::onClickStop() diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index c0f5e63623..3a3660bb31 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -162,7 +162,8 @@ LLFloaterReporter::LLFloaterReporter(const LLSD& key) mPosition(), mCopyrightWarningSeen( FALSE ), mResourceDatap(new LLResourceData()), - mAvatarNameCacheConnection() + mAvatarNameCacheConnection(), + mSnapshotTimer() { } @@ -245,6 +246,12 @@ LLFloaterReporter::~LLFloaterReporter() void LLFloaterReporter::draw() { LLFloater::draw(); + static LLCachedControl<F32> screenshot_delay(gSavedSettings, "AbuseReportScreenshotDelay"); + if (mSnapshotTimer.getStarted() && mSnapshotTimer.getElapsedTimeF32() > screenshot_delay) + { + mSnapshotTimer.stop(); + takeNewSnapshot(); + } } void LLFloaterReporter::enableControls(BOOL enable) @@ -877,8 +884,7 @@ void LLFloaterReporter::onOpen(const LLSD& key) { childSetEnabled("send_btn", false); //Time delay to avoid UI artifacts. MAINT-7067 - doAfterInterval(boost::bind(&LLFloaterReporter::takeNewSnapshot,this), gSavedSettings.getF32("AbuseReportScreenshotDelay")); - + mSnapshotTimer.start(); } void LLFloaterReporter::onLoadScreenshotDialog(const LLSD& notification, const LLSD& response) @@ -950,6 +956,7 @@ void LLFloaterReporter::setPosBox(const LLVector3d &pos) void LLFloaterReporter::onClose(bool app_quitting) { + mSnapshotTimer.stop(); gSavedPerAccountSettings.setBOOL("PreviousScreenshotForReport", app_quitting); } diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h index decc01be98..f5ba63ce7f 100644 --- a/indra/newview/llfloaterreporter.h +++ b/indra/newview/llfloaterreporter.h @@ -149,6 +149,7 @@ private: LLPointer<LLImageRaw> mImageRaw; LLPointer<LLImageRaw> mPrevImageRaw; + LLFrameTimer mSnapshotTimer; }; #endif diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp index e20360066e..3e6fc3dc0d 100644 --- a/indra/newview/llfloatertopobjects.cpp +++ b/indra/newview/llfloatertopobjects.cpp @@ -236,7 +236,7 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data) && have_extended_data) { columns[column_num]["column"] = "memory"; - columns[column_num]["value"] = llformat("%0.0f", (script_memory / 1000.f)); + columns[column_num]["value"] = llformat("%0.0f", (script_memory / 1024.f)); columns[column_num++]["font"] = "SANSSERIF"; columns[column_num]["column"] = "URLs"; diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index dece3fc1ea..8a8d92d459 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -399,6 +399,9 @@ void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent } else if(event == MEDIA_EVENT_NAME_CHANGED ) { + // flags are sent with this event + mBtnBack->setEnabled(self->getHistoryBackAvailable()); + mBtnForward->setEnabled(self->getHistoryForwardAvailable()); std::string page_title = self->getMediaName(); // simulate browser behavior - title is empty, use the current URL if (mShowPageTitle) diff --git a/indra/newview/llfloaterwebprofile.cpp b/indra/newview/llfloaterwebprofile.cpp index a46f1d8af2..891bb90c0e 100644 --- a/indra/newview/llfloaterwebprofile.cpp +++ b/indra/newview/llfloaterwebprofile.cpp @@ -38,8 +38,10 @@ LLFloaterWebProfile::LLFloaterWebProfile(const Params& key) : void LLFloaterWebProfile::onOpen(const LLSD& key) { Params p(key); - p.show_chrome(false). - window_class("profile"); + p.show_chrome(true); + p.window_class("profile"); + p.allow_address_entry(false); + p.trusted_content(true); LLFloaterWebContent::onOpen(p); applyPreferredRect(); } diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 83f268818e..3c3b004d2c 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -549,10 +549,10 @@ void LLFloaterWorldMap::trackAvatar( const LLUUID& avatar_id, const std::string& getChild<LLUICtrl>("teleport_coordinate_z")->setValue(LLSD(200.f)); } // Don't re-request info if we already have it or we won't have it in time to teleport - if (mTrackedStatus != LLTracker::TRACKING_AVATAR || name != mTrackedAvatarName) + if (mTrackedStatus != LLTracker::TRACKING_AVATAR || avatar_id != mTrackedAvatarID) { mTrackedStatus = LLTracker::TRACKING_AVATAR; - mTrackedAvatarName = name; + mTrackedAvatarID = avatar_id; LLTracker::trackAvatar(avatar_id, name); } } diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index c5801c8819..fce945df6c 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -190,7 +190,7 @@ private: LLVector3d mTrackedLocation; LLTracker::ETrackingStatus mTrackedStatus; std::string mTrackedSimName; - std::string mTrackedAvatarName; + LLUUID mTrackedAvatarID; LLSLURL mSLURL; LLCtrlListInterface * mListFriendCombo; diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 63270e13fe..fc93181ef4 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -920,7 +920,7 @@ public: // unbind if (texUnit) { - texUnit->unbind(LLTexUnit::TT_TEXTURE); + texUnit->unbind(LLTexUnit::TT_TEXTURE); } // ensure that we delete these textures regardless of how we exit LLImageGL::deleteTextures(source.size(), &source[0]); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 3acfaeb049..67b51f11b3 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -6588,11 +6588,9 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) getClipboardEntries(true, items, disabled_items, flags); items.push_back(std::string("Wearable And Object Separator")); - items.push_back(std::string("Wearable Edit")); - bool modifiable = !gAgentWearables.isWearableModifiable(item->getUUID()); - if (((flags & FIRST_SELECTED_ITEM) == 0) || modifiable) + if (((flags & FIRST_SELECTED_ITEM) == 0) || (item && !gAgentWearables.isWearableModifiable(item->getUUID()))) { disabled_items.push_back(std::string("Wearable Edit")); } diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 9193613e9f..f64c39c3ad 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -153,7 +153,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const // we're showing all folders, overriding filter if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS) { - return true; + return !gInventory.isCategoryHidden(folder_id); } // when applying a filter, matching folders get their contents downloaded first diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 6a1ec9f991..60f470a938 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -342,6 +342,17 @@ LLViewerInventoryCategory* LLInventoryModel::getCategory(const LLUUID& id) const return category; } +bool LLInventoryModel::isCategoryHidden(const LLUUID& id) const +{ + const LLViewerInventoryCategory* category = getCategory(id); + if (category) + { + LLFolderType::EType cat_type = category->getPreferredType(); + return (cat_type == LLFolderType::FT_INBOX || cat_type == LLFolderType::FT_OUTBOX); + } + return false; +} + S32 LLInventoryModel::getItemCount() const { return mItemMap.size(); diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 01e0ed7e9b..576c5e9e20 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -316,7 +316,9 @@ public: // Copy content of all folders of type "type" into folder "id" and delete/purge the empty folders // Note : This method has been designed for FT_OUTBOX (aka Merchant Outbox) but can be used for other categories void consolidateForType(const LLUUID& id, LLFolderType::EType type); - + + bool isCategoryHidden(const LLUUID& id) const; + private: mutable LLPointer<LLViewerInventoryItem> mLastItem; // cache recent lookups diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index 4999318973..c03080beb8 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -400,12 +400,12 @@ void LLFloaterMove::initMovementMode() { initMovementMode = MM_FLY; } - setMovementMode(initMovementMode); + + mCurrentMode = initMovementMode; + bool hide_mode_buttons = (MM_FLY == mCurrentMode) || (isAgentAvatarValid() && gAgentAvatarp->isSitting()); - if (isAgentAvatarValid()) - { - showModeButtons(!gAgentAvatarp->isSitting()); - } + updateButtonsWithMovementMode(mCurrentMode); + showModeButtons(!hide_mode_buttons); } void LLFloaterMove::setModeTooltip(const EMovementMode mode) diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index c38d3ab140..dc3b153da2 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -1267,6 +1267,13 @@ LLUUID LLOutfitGallery::getDefaultPhoto() void LLOutfitGallery::onTexturePickerCommit(LLTextureCtrl::ETexturePickOp op, LLUUID id) { + LLUUID selected_outfit_id = getSelectedOutfitUUID(); + + if (selected_outfit_id.isNull()) + { + return; + } + LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); if (floaterp && op == LLTextureCtrl::TEXTURE_SELECT) @@ -1316,8 +1323,8 @@ void LLOutfitGallery::onTexturePickerCommit(LLTextureCtrl::ETexturePickOp op, LL return; } - checkRemovePhoto(getSelectedOutfitUUID()); - linkPhotoToOutfit(image_item_id, getSelectedOutfitUUID()); + checkRemovePhoto(selected_outfit_id); + linkPhotoToOutfit(image_item_id, selected_outfit_id); } } diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index e2157f985e..892fa385d7 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -1050,15 +1050,15 @@ bool LLOutfitContextMenu::onEnable(LLSD::String param) bool LLOutfitContextMenu::onVisible(LLSD::String param) { LLUUID outfit_cat_id = mUUIDs.back(); - bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == outfit_cat_id; if ("edit" == param) { + bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == outfit_cat_id; return is_worn; } else if ("wear_replace" == param) { - return !is_worn; + return true; } else if ("delete" == param) { diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index 2d2ba30e9b..f089faea09 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -139,6 +139,7 @@ void LLInboxFolderViewFolder::draw() if (!hasBadgeHolderParent()) { addBadgeToParentHolder(); + setDrawBadgeAtTop(true); } setBadgeVisibility(mFresh); diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 0bf4d48421..d0dea5d044 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -342,9 +342,9 @@ void LLPanelObject::getState( ) } // can move or rotate only linked group with move permissions, or sub-object with move and modify perms - BOOL enable_move = objectp->permMove() && !objectp->isPermanentEnforced() && ((root_objectp == NULL) || !root_objectp->isPermanentEnforced()) && !objectp->isAttachment() && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); + BOOL enable_move = objectp->permMove() && !objectp->isPermanentEnforced() && ((root_objectp == NULL) || !root_objectp->isPermanentEnforced()) && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); BOOL enable_scale = objectp->permMove() && !objectp->isPermanentEnforced() && ((root_objectp == NULL) || !root_objectp->isPermanentEnforced()) && objectp->permModify(); - BOOL enable_rotate = objectp->permMove() && !objectp->isPermanentEnforced() && ((root_objectp == NULL) || !root_objectp->isPermanentEnforced()) && ( (objectp->permModify() && !objectp->isAttachment()) || !gSavedSettings.getBOOL("EditLinkedParts")); + BOOL enable_rotate = objectp->permMove() && !objectp->isPermanentEnforced() && ((root_objectp == NULL) || !root_objectp->isPermanentEnforced()) && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); BOOL single_volume = (LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME )) @@ -1587,9 +1587,14 @@ void LLPanelObject::sendRotation(BOOL btn_down) { rotation = rotation * ~mRootObject->getRotationRegion(); } + + // To include avatars into movements and rotation + // If false, all children are selected anyway - move avatar + // If true, not all children are selected - save positions + bool individual_selection = gSavedSettings.getBOOL("EditLinkedParts"); std::vector<LLVector3>& child_positions = mObject->mUnselectedChildrenPositions ; std::vector<LLQuaternion> child_rotations; - if (mObject->isRootEdit()) + if (mObject->isRootEdit() && individual_selection) { mObject->saveUnselectedChildrenRotation(child_rotations) ; mObject->saveUnselectedChildrenPosition(child_positions) ; @@ -1599,8 +1604,8 @@ void LLPanelObject::sendRotation(BOOL btn_down) LLManip::rebuild(mObject) ; // for individually selected roots, we need to counterrotate all the children - if (mObject->isRootEdit()) - { + if (mObject->isRootEdit() && individual_selection) + { mObject->resetChildrenRotationAndPosition(child_rotations, child_positions) ; } diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index b5ee68ba25..c50f3477ad 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -696,6 +696,10 @@ void LLTaskInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) items.push_back(std::string("Task Open")); } items.push_back(std::string("Task Properties")); + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Task Properties")); + } if(isItemRenameable()) { items.push_back(std::string("Task Rename")); @@ -1017,6 +1021,10 @@ void LLTaskSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } } items.push_back(std::string("Task Properties")); + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Task Properties")); + } if(isItemRenameable()) { items.push_back(std::string("Task Rename")); @@ -1388,6 +1396,10 @@ void LLTaskMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } } items.push_back(std::string("Task Properties")); + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Task Properties")); + } if(isItemRenameable()) { items.push_back(std::string("Task Rename")); diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp index 3099a6e039..75c8765c5b 100644 --- a/indra/newview/llpanelwearing.cpp +++ b/indra/newview/llpanelwearing.cpp @@ -65,7 +65,7 @@ public: LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; registrar.add("Gear.Edit", boost::bind(&edit_outfit)); - registrar.add("Gear.TakeOff", boost::bind(&LLWearingGearMenu::onTakeOff, this)); + registrar.add("Gear.TakeOff", boost::bind(&LLPanelWearing::onRemoveItem, mPanelWearing)); registrar.add("Gear.Copy", boost::bind(&LLPanelWearing::copyToClipboard, mPanelWearing)); enable_registrar.add("Gear.OnEnable", boost::bind(&LLPanelWearing::isActionEnabled, mPanelWearing, _2)); @@ -79,13 +79,6 @@ public: private: - void onTakeOff() - { - uuid_vec_t selected_uuids; - mPanelWearing->getSelectedItemsUUIDs(selected_uuids); - LLAppearanceMgr::instance().removeItemsFromAvatar(selected_uuids); - } - LLToggleableMenu* mMenu; LLPanelWearing* mPanelWearing; }; @@ -343,7 +336,14 @@ bool LLPanelWearing::isActionEnabled(const LLSD& userdata) if (command_name == "take_off") { - return hasItemSelected() && canTakeOffSelected(); + if (mWearablesTab->isExpanded()) + { + return hasItemSelected() && canTakeOffSelected(); + } + else + { + return mTempItemsList->hasSelectedItem(); + } } return false; @@ -532,6 +532,21 @@ void LLPanelWearing::onRemoveAttachment() } } +void LLPanelWearing::onRemoveItem() +{ + if (mWearablesTab->isExpanded()) + { + uuid_vec_t selected_uuids; + getSelectedItemsUUIDs(selected_uuids); + LLAppearanceMgr::instance().removeItemsFromAvatar(selected_uuids); + } + else + { + onRemoveAttachment(); + } +} + + void LLPanelWearing::copyToClipboard() { std::string text; diff --git a/indra/newview/llpanelwearing.h b/indra/newview/llpanelwearing.h index c5cb79092a..715404a457 100644 --- a/indra/newview/llpanelwearing.h +++ b/indra/newview/llpanelwearing.h @@ -80,6 +80,7 @@ public: void onAccordionTabStateChanged(); void setAttachmentDetails(LLSD content); void requestAttachmentDetails(); + void onRemoveItem(); void onEditAttachment(); void onRemoveAttachment(); diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp index 08d734ddac..f48ce680fd 100644 --- a/indra/newview/llphysicsmotion.cpp +++ b/indra/newview/llphysicsmotion.cpp @@ -44,7 +44,9 @@ typedef std::map<std::string, std::string> controller_map_t; typedef std::map<std::string, F32> default_controller_map_t; #define MIN_REQUIRED_PIXEL_AREA_AVATAR_PHYSICS_MOTION 0.f -#define TIME_ITERATION_STEP 0.05f +// we use TIME_ITERATION_STEP_MAX in division operation, make sure this is a simple +// value and devision result won't end with repeated/recurring tail like 1.333(3) +#define TIME_ITERATION_STEP_MAX 0.05f // minimal step size will end up as 0.025 inline F64 llsgn(const F64 a) { @@ -480,7 +482,7 @@ BOOL LLPhysicsMotion::onUpdate(F32 time) if (!mParamDriver) return FALSE; - if (!mLastTime) + if (!mLastTime || mLastTime >= time) { mLastTime = time; return FALSE; @@ -561,14 +563,10 @@ BOOL LLPhysicsMotion::onUpdate(F32 time) // bounce at right (relatively) position. // Note: this doesn't look to be optimal, since it provides only "roughly same" behavior, but // irregularity at higher fps looks to be insignificant so it works good enough for low fps. - for (F32 time_iteration = 0; time_iteration <= time_delta; time_iteration += TIME_ITERATION_STEP) + U32 steps = (U32)(time_delta / TIME_ITERATION_STEP_MAX) + 1; + F32 time_iteration_step = time_delta / (F32)steps; //minimal step size ends up as 0.025 + for (U32 i = 0; i < steps; i++) { - F32 time_iteration_step = TIME_ITERATION_STEP; - if (time_iteration + TIME_ITERATION_STEP > time_delta) - { - time_iteration_step = time_delta-time_iteration; - } - // mPositon_local should be in normalized 0,1 range already. Just making sure... const F32 position_current_local = llclamp(mPosition_local, 0.0f, diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 6ecc4c7fb9..945f3c370c 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -2041,7 +2041,15 @@ void LLLiveLSLEditor::loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType mScriptEd->setScriptText(LLStringExplicit(&buffer[0]), TRUE); mScriptEd->makeEditorPristine(); - mScriptEd->setScriptName(getItem()->getName()); + + std::string script_name = DEFAULT_SCRIPT_NAME; + const LLInventoryItem* inv_item = getItem(); + + if(inv_item) + { + script_name = inv_item->getName(); + } + mScriptEd->setScriptName(script_name); } diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index 814cfde75d..a1dbbb307b 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -1275,7 +1275,7 @@ void LLSecAPIBasicHandler::init() // grab the application ca-bundle.crt file that contains the well-known certs shipped // with the product - std::string ca_file_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "ca-bundle.crt"); + std::string ca_file_path = gDirUtilp->getExpandedFilename( LL_PATH_EXECUTABLE, "app_settings", "ca-bundle.crt" ); LL_INFOS("SECAPI") << "Loading application certificate store from " << ca_file_path << LL_ENDL; LLPointer<LLBasicCertificateStore> app_ca_store = new LLBasicCertificateStore(ca_file_path); diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index dadf2f9701..2a0d961952 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -117,7 +117,7 @@ public: ~LLTextureCacheWorker() { llassert_always(!haveWork()); - FREE_MEM(LLImageBase::getPrivatePool(), mReadData); + ll_aligned_free_16(mReadData); } // override this interface @@ -237,7 +237,7 @@ bool LLTextureCacheLocalFileWorker::doRead() // << " Bytes: " << mDataSize << " Offset: " << mOffset // << " / " << mDataSize << LL_ENDL; mDataSize = 0; // failed - FREE_MEM(LLImageBase::getPrivatePool(), mReadData); + ll_aligned_free_16(mReadData); mReadData = NULL; } return true; @@ -252,7 +252,7 @@ bool LLTextureCacheLocalFileWorker::doRead() { mDataSize = local_size; } - mReadData = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), mDataSize); + mReadData = (U8*)ll_aligned_malloc_16(mDataSize); S32 bytes_read = LLAPRFile::readEx(mFileName, mReadData, mOffset, mDataSize, mCache->getLocalAPRFilePool()); @@ -262,7 +262,7 @@ bool LLTextureCacheLocalFileWorker::doRead() // << " Bytes: " << mDataSize << " Offset: " << mOffset // << " / " << mDataSize << LL_ENDL; mDataSize = 0; - FREE_MEM(LLImageBase::getPrivatePool(), mReadData); + ll_aligned_free_16(mReadData); mReadData = NULL; } else @@ -386,7 +386,7 @@ bool LLTextureCacheRemoteWorker::doRead() mDataSize = local_size; } // Allocate read buffer - mReadData = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), mDataSize); + mReadData = (U8*)ll_aligned_malloc_16(mDataSize); if (mReadData) { @@ -402,7 +402,7 @@ bool LLTextureCacheRemoteWorker::doRead() << " Bytes: " << mDataSize << " Offset: " << mOffset << " / " << mDataSize << LL_ENDL; mDataSize = 0; - FREE_MEM(LLImageBase::getPrivatePool(), mReadData); + ll_aligned_free_16(mReadData); mReadData = NULL; } else @@ -451,7 +451,7 @@ bool LLTextureCacheRemoteWorker::doRead() S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; size = llmin(size, mDataSize); // Allocate the read buffer - mReadData = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), size); + mReadData = (U8*)ll_aligned_malloc_16(size); if (mReadData) { S32 bytes_read = LLAPRFile::readEx(mCache->mHeaderDataFileName, @@ -461,7 +461,7 @@ bool LLTextureCacheRemoteWorker::doRead() LL_WARNS() << "LLTextureCacheWorker: " << mID << " incorrect number of bytes read from header: " << bytes_read << " / " << size << LL_ENDL; - FREE_MEM(LLImageBase::getPrivatePool(), mReadData); + ll_aligned_free_16(mReadData); mReadData = NULL; mDataSize = -1; // failed done = true; @@ -500,7 +500,7 @@ bool LLTextureCacheRemoteWorker::doRead() S32 data_offset, file_size, file_offset; // Reserve the whole data buffer first - U8* data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), mDataSize); + U8* data = (U8*)ll_aligned_malloc_16(mDataSize); if (data) { // Set the data file pointers taking the read offset into account. 2 cases: @@ -514,7 +514,7 @@ bool LLTextureCacheRemoteWorker::doRead() // Copy the raw data we've been holding from the header cache into the new sized buffer llassert_always(mReadData); memcpy(data, mReadData, data_offset); - FREE_MEM(LLImageBase::getPrivatePool(), mReadData); + ll_aligned_free_16(mReadData); mReadData = NULL; } else @@ -540,7 +540,7 @@ bool LLTextureCacheRemoteWorker::doRead() LL_WARNS() << "LLTextureCacheWorker: " << mID << " incorrect number of bytes read from body: " << bytes_read << " / " << file_size << LL_ENDL; - FREE_MEM(LLImageBase::getPrivatePool(), mReadData); + ll_aligned_free_16(mReadData); mReadData = NULL; mDataSize = -1; // failed done = true; @@ -550,7 +550,7 @@ bool LLTextureCacheRemoteWorker::doRead() { LL_WARNS() << "LLTextureCacheWorker: " << mID << " failed to allocate memory for reading: " << mDataSize << LL_ENDL; - FREE_MEM(LLImageBase::getPrivatePool(), mReadData); + ll_aligned_free_16(mReadData); mReadData = NULL; mDataSize = -1; // failed done = true; @@ -673,11 +673,11 @@ bool LLTextureCacheRemoteWorker::doWrite() { // We need to write a full record in the header cache so, if the amount of data is smaller // than a record, we need to transfer the data to a buffer padded with 0 and write that - U8* padBuffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), TEXTURE_CACHE_ENTRY_SIZE); + U8* padBuffer = (U8*)ll_aligned_malloc_16(TEXTURE_CACHE_ENTRY_SIZE); memset(padBuffer, 0, TEXTURE_CACHE_ENTRY_SIZE); // Init with zeros memcpy(padBuffer, mWriteData, mDataSize); // Copy the write buffer bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, padBuffer, offset, size, mCache->getLocalAPRFilePool()); - FREE_MEM(LLImageBase::getPrivatePool(), padBuffer); + ll_aligned_free_16(padBuffer); } else { @@ -783,7 +783,7 @@ void LLTextureCacheWorker::finishWork(S32 param, bool completed) } else { - FREE_MEM(LLImageBase::getPrivatePool(), mReadData); + ll_aligned_free_16(mReadData); mReadData = NULL; } } @@ -845,7 +845,7 @@ LLTextureCache::~LLTextureCache() writeUpdatedEntries() ; delete mFastCachep; delete mFastCachePoolp; - FREE_MEM(LLImageBase::getPrivatePool(), mFastCachePadBuffer); + ll_aligned_free_16(mFastCachePadBuffer); } ////////////////////////////////////////////////////////////////////////////// @@ -1983,10 +1983,10 @@ LLPointer<LLImageRaw> LLTextureCache::readFromFastCache(const LLUUID& id, S32& d } discardlevel = head[3]; - data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), image_size); + data = (U8*)ll_aligned_malloc_16(image_size); if(mFastCachep->read(data, image_size) != image_size) { - FREE_MEM(LLImageBase::getPrivatePool(), data); + ll_aligned_free_16(data); closeFastCache(); return NULL; } @@ -2078,7 +2078,7 @@ void LLTextureCache::openFastCache(bool first_time) { if(!mFastCachePadBuffer) { - mFastCachePadBuffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), TEXTURE_FAST_CACHE_ENTRY_SIZE); + mFastCachePadBuffer = (U8*)ll_aligned_malloc_16(TEXTURE_FAST_CACHE_ENTRY_SIZE); } mFastCachePoolp = new LLVolatileAPRPool(); if (LLAPRFile::isExist(mFastCacheFileName, mFastCachePoolp)) diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 1f7796e6d0..6fd90e4935 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1761,7 +1761,7 @@ bool LLTextureFetchWorker::doWork(S32 param) mRequestedOffset += src_offset; } - U8 * buffer = (U8 *)ALLOCATE_MEM(LLImageBase::getPrivatePool(), total_size); + U8 * buffer = (U8 *)ll_aligned_malloc_16(total_size); if (!buffer) { // abort. If we have no space for packet, we have not enough space to decode image @@ -2266,7 +2266,7 @@ bool LLTextureFetchWorker::processSimulatorPackets() if (buffer_size > cur_size) { /// We have new data - U8* buffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), buffer_size); + U8* buffer = (U8*)ll_aligned_malloc_16(buffer_size); S32 offset = 0; if (cur_size > 0 && mFirstPacket > 0) { @@ -5059,7 +5059,7 @@ void LLTextureFetchDebugger::callbackHTTP(FetchEntry & fetch, LLCore::HttpRespon //LL_INFOS(LOG_TXT) << "Fetch Debugger : got results for " << fetch.mID << ", data_size = " << data_size << ", received = " << fetch.mCurlReceivedSize << ", requested = " << fetch.mRequestedSize << ", partial = " << partial << LL_ENDL; if ((fetch.mCurlReceivedSize >= fetch.mRequestedSize) || !partial || (fetch.mRequestedSize == 600)) { - U8* d_buffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), data_size); + U8* d_buffer = (U8*)ll_aligned_malloc_16(data_size); if (ba) { ba->read(0, d_buffer, data_size); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index bd68d8c999..9fb53dc9ab 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1278,7 +1278,6 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target, if (gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) { is_in_trash = true; - remove_from_inventory = TRUE; } LLUUID source_id = from_task_inventory ? mSourceID : LLUUID::null; @@ -1806,7 +1805,6 @@ EAcceptance LLToolDragAndDrop::dad3dRezObjectOnLand( if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) { accept = ACCEPT_YES_SINGLE; - remove_inventory = TRUE; } if(drop) diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp index 9b7c13b57d..5d598aaebe 100644 --- a/indra/newview/lltwitterconnect.cpp +++ b/indra/newview/lltwitterconnect.cpp @@ -380,13 +380,10 @@ LLTwitterConnect::LLTwitterConnect() void LLTwitterConnect::openTwitterWeb(std::string url) { - // Open the URL in an internal browser window without navigation UI LLFloaterWebContent::Params p; p.url(url); p.show_chrome(true); - p.allow_address_entry(false); p.allow_back_forward_navigation(false); - p.trusted_content(true); p.clean_browser(true); LLFloater *floater = LLFloaterReg::showInstance("twitter_web", p); //the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems). diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 474f3de664..87ee2f4921 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -2029,7 +2029,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) // the correct way to deal with certs it to load ours from ca-bundle.crt and append them to the ones // Qt/WebKit loads from your system location. - std::string ca_path = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "ca-bundle.crt" ); + std::string ca_path = gDirUtilp->getExpandedFilename( LL_PATH_EXECUTABLE, "app_settings", "ca-bundle.crt" ); media_source->addCertificateFilePath( ca_path ); media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort")); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 5bbf5650ad..e973363e0f 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -8001,7 +8001,7 @@ void handle_report_bug(const LLSD& param) LLUIString url(param.asString()); LLStringUtil::format_map_t replace; - replace["[ENVIRONMENT]"] = LLURI::escape(LLAppViewer::instance()->getShortViewerInfoString()); + replace["[ENVIRONMENT]"] = LLURI::escape(LLAppViewer::instance()->getViewerInfoString(true)); LLSLURL location_url; LLAgentUI::buildSLURL(location_url); replace["[LOCATION]"] = LLURI::escape(location_url.getSLURLString()); diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp index 814060f4f2..998ae52fe0 100644 --- a/indra/newview/llviewerpartsource.cpp +++ b/indra/newview/llviewerpartsource.cpp @@ -40,6 +40,25 @@ #include "llworld.h" #include "pipeline.h" + +static LLVOAvatar* find_avatar(const LLUUID& id) +{ + LLViewerObject *obj = gObjectList.findObject(id); + while (obj && obj->isAttachment()) + { + obj = (LLViewerObject *)obj->getParent(); + } + + if (obj && obj->isAvatar()) + { + return (LLVOAvatar*)obj; + } + else + { + return NULL; + } +} + LLViewerPartSource::LLViewerPartSource(const U32 type) : mType(type), mOwnerUUID(LLUUID::null), @@ -113,6 +132,15 @@ void LLViewerPartSourceScript::update(const F32 dt) if( mIsSuspended ) return; + if (mOwnerAvatarp.isNull() && mOwnerUUID != LLUUID::null) + { + mOwnerAvatarp = find_avatar(mOwnerUUID); + } + if (mOwnerAvatarp.notNull() && LLVOAvatar::AV_DO_NOT_RENDER == mOwnerAvatarp->getVisualMuteSettings()) + { + return; + } + F32 old_update_time = mLastUpdateTime; mLastUpdateTime += dt; diff --git a/indra/newview/llviewerpartsource.h b/indra/newview/llviewerpartsource.h index 12e926173b..504229e81f 100644 --- a/indra/newview/llviewerpartsource.h +++ b/indra/newview/llviewerpartsource.h @@ -42,6 +42,7 @@ class LLViewerTexture; class LLViewerObject; class LLViewerPart; +class LLVOAvatar; class LLViewerPartSource : public LLRefCount { @@ -85,6 +86,7 @@ protected: F32 mLastUpdateTime; F32 mLastPartTime; LLUUID mOwnerUUID; + LLPointer<LLVOAvatar> mOwnerAvatarp; LLPointer<LLViewerTexture> mImagep; // Particle information U32 mPartFlags; // Flags for the particle diff --git a/indra/newview/llviewertextureanim.cpp b/indra/newview/llviewertextureanim.cpp index 9af92d7377..9603811066 100644 --- a/indra/newview/llviewertextureanim.cpp +++ b/indra/newview/llviewertextureanim.cpp @@ -146,6 +146,8 @@ S32 LLViewerTextureAnim::animateTextures(F32 &off_s, F32 &off_t, if (!(mMode & SMOOTH)) { frame_counter = (F32)llfloor(frame_counter + 0.01f); + // account for 0.01, we shouldn't step over full length + frame_counter = llmin(full_length - 1.f, frame_counter); } if (mMode & PING_PONG) diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 74deaffe16..e90b4ac86c 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -614,7 +614,7 @@ public: if (last_frame_recording.getSampleCount(LLPipeline::sStatBatchSize) > 0) { - addText(xpos, ypos, llformat("Batch min/max/mean: %d/%d/%d", last_frame_recording.getMin(LLPipeline::sStatBatchSize), last_frame_recording.getMax(LLPipeline::sStatBatchSize), last_frame_recording.getMean(LLPipeline::sStatBatchSize))); + addText(xpos, ypos, llformat("Batch min/max/mean: %d/%d/%d", (U32)last_frame_recording.getMin(LLPipeline::sStatBatchSize), (U32)last_frame_recording.getMax(LLPipeline::sStatBatchSize), (U32)last_frame_recording.getMean(LLPipeline::sStatBatchSize))); } ypos += y_inc; @@ -731,7 +731,8 @@ public: addText(xpos, ypos, "View Matrix"); ypos += y_inc; } - if (gSavedSettings.getBOOL("DebugShowColor")) + // disable use of glReadPixels which messes up nVidia nSight graphics debugging + if (gSavedSettings.getBOOL("DebugShowColor") && !LLRender::sNsightDebugSupport) { U8 color[4]; LLCoordGL coord = gViewerWindow->getCurrentMouse(); @@ -740,16 +741,6 @@ public: ypos += y_inc; } - if (gSavedSettings.getBOOL("DebugShowPrivateMem")) - { - LLPrivateMemoryPoolManager::getInstance()->updateStatistics() ; - addText(xpos, ypos, llformat("Total Reserved(KB): %d", LLPrivateMemoryPoolManager::getInstance()->mTotalReservedSize / 1024)); - ypos += y_inc; - - addText(xpos, ypos, llformat("Total Allocated(KB): %d", LLPrivateMemoryPoolManager::getInstance()->mTotalAllocatedSize / 1024)); - ypos += y_inc; - } - // only display these messages if we are actually rendering beacons at this moment if (LLPipeline::getRenderBeacons() && LLFloaterReg::instanceVisible("beacons")) { @@ -4727,36 +4718,39 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei { LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot"); } - - if (type == LLSnapshotModel::SNAPSHOT_TYPE_COLOR) + // disable use of glReadPixels when doing nVidia nSight graphics debugging + if (!LLRender::sNsightDebugSupport) { - glReadPixels( + if (type == LLSnapshotModel::SNAPSHOT_TYPE_COLOR) + { + glReadPixels( subimage_x_offset, out_y + subimage_y_offset, read_width, 1, GL_RGB, GL_UNSIGNED_BYTE, raw->getData() + output_buffer_offset ); - } - else // LLSnapshotModel::SNAPSHOT_TYPE_DEPTH - { - LLPointer<LLImageRaw> depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values - glReadPixels( - subimage_x_offset, out_y + subimage_y_offset, - read_width, 1, - GL_DEPTH_COMPONENT, GL_FLOAT, - depth_line_buffer->getData()// current output pixel is beginning of buffer... - ); - - for (S32 i = 0; i < (S32)read_width; i++) + } + else // LLSnapshotModel::SNAPSHOT_TYPE_DEPTH { - F32 depth_float = *(F32*)(depth_line_buffer->getData() + (i * sizeof(F32))); - - F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float * depth_conversion_factor_2)); - U8 depth_byte = F32_to_U8(linear_depth_float, LLViewerCamera::getInstance()->getNear(), LLViewerCamera::getInstance()->getFar()); - // write converted scanline out to result image - for (S32 j = 0; j < raw->getComponents(); j++) + LLPointer<LLImageRaw> depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values + glReadPixels( + subimage_x_offset, out_y + subimage_y_offset, + read_width, 1, + GL_DEPTH_COMPONENT, GL_FLOAT, + depth_line_buffer->getData()// current output pixel is beginning of buffer... + ); + + for (S32 i = 0; i < (S32)read_width; i++) { - *(raw->getData() + output_buffer_offset + (i * raw->getComponents()) + j) = depth_byte; + F32 depth_float = *(F32*)(depth_line_buffer->getData() + (i * sizeof(F32))); + + F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float * depth_conversion_factor_2)); + U8 depth_byte = F32_to_U8(linear_depth_float, LLViewerCamera::getInstance()->getNear(), LLViewerCamera::getInstance()->getFar()); + // write converted scanline out to result image + for (S32 j = 0; j < raw->getComponents(); j++) + { + *(raw->getData() + output_buffer_offset + (i * raw->getComponents()) + j) = depth_byte; + } } } } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index eae8f2cc56..652a447545 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5304,6 +5304,10 @@ LLUUID LLVOAvatar::remapMotionID(const LLUUID& id) if (use_new_walk_run) result = ANIM_AGENT_FEMALE_RUN_NEW; } + else if (id == ANIM_AGENT_SIT) + { + result = ANIM_AGENT_SIT_FEMALE; + } } else { diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 7b4d8ef329..d93cae992b 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1200,7 +1200,7 @@ void LLVOVolume::sculpt() mSculptTexture->updateBindStatsForTester() ; } } - getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level); + getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level, mSculptTexture->isMissingAsset()); //notify rebuild any other VOVolumes that reference this sculpty volume for (S32 i = 0; i < mSculptTexture->getNumVolumes(); ++i) @@ -2525,7 +2525,9 @@ void LLVOVolume::mediaNavigateBounceBack(U8 texture_index) LL_WARNS("MediaOnAPrim") << "FAILED to bounce back URL \"" << url << "\" -- unloading impl" << LL_ENDL; impl->setMediaFailed(true); } - else { + // Make sure we are not bouncing to url we came from + else if (impl->getCurrentMediaURL() != url) + { // Okay, navigate now LL_INFOS("MediaOnAPrim") << "bouncing back to URL: " << url << LL_ENDL; impl->navigateTo(url, "", false, true); diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 5fb3d62445..ee2270c323 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -645,7 +645,7 @@ LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p) setRightMouseDownCallback(boost::bind(&LLWearableItemsList::onRightClick, this, _2, _3)); } mWornIndicationEnabled = p.worn_indication_enabled; - setNoItemsCommentText(LLTrans::getString("NoneFound")); + setNoItemsCommentText(LLTrans::getString("LoadingData")); } // virtual diff --git a/indra/newview/skins/default/xui/da/floater_tos.xml b/indra/newview/skins/default/xui/da/floater_tos.xml index af9ee0bd06..bd8ecb92e9 100644 --- a/indra/newview/skins/default/xui/da/floater_tos.xml +++ b/indra/newview/skins/default/xui/da/floater_tos.xml @@ -8,7 +8,9 @@ </floater.string> <button label="Fortsæt" label_selected="Fortsæt" name="Continue"/> <button label="Annullér" label_selected="Annullér" name="Cancel"/> - <check_box label="Jeg er enig med "Terms of Service and Privacy Policy"" name="agree_chk"/> + <text name="agree_list"> + Jeg er enig med "Terms of Service and Privacy Policy" + </text> <text name="tos_heading"> Læs venligst følgende "Terms of Service and Privacy Policy" grundigt. For at fortsætte med at logge på [SECOND_LIFE], skal du acceptere aftale. </text> diff --git a/indra/newview/skins/default/xui/de/floater_tos.xml b/indra/newview/skins/default/xui/de/floater_tos.xml index 636c2629da..47551d2a82 100644 --- a/indra/newview/skins/default/xui/de/floater_tos.xml +++ b/indra/newview/skins/default/xui/de/floater_tos.xml @@ -12,10 +12,9 @@ <text name="external_tos_required"> Sie müssen sich unter https://my.secondlife.com anmelden und die Servicebedingungen akzeptieren, bevor Sie fortfahren können. Vielen Dank! </text> - <check_box label="Ich habe die" name="agree_chk"/> <text name="agree_list"> - Allgemeinen Geschäftsbedingungen, die Datenschutzrichtlinie sowie die Servicebedingungen inklusive der Anforderungen zur Streitschlichtung gelesen und akzeptiere diese. - </text> - <button label="Weiter" label_selected="Weiter" name="Continue"/> + Ich habe die Allgemeinen Geschäftsbedingungen, die Datenschutzrichtlinie sowie die Servicebedingungen inklusive der Anforderungen zur Streitschlichtung gelesen und akzeptiere diese. + </text> + <button label="Weiter" label_selected="Weiter" name="Continue" top_delta="45"/> <button label="Abbrechen" label_selected="Abbrechen" name="Cancel"/> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index 76adaad57c..e50747cb5f 100644 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -127,7 +127,7 @@ top_delta="0" width="31" /> <panel - height="154" + height="159" layout="topleft" follows="top|left" left="0" @@ -250,7 +250,7 @@ left="0" name="panel_container" default_panel_name="panel_snapshot_options" - top_pad="10" + top_pad="5" width="215"> <panel class="llpanelsnapshotoptions" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 92511167c0..fa15fb0657 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2373,16 +2373,6 @@ function="ToggleControl" parameter="DebugShowMemory" /> </menu_item_check> - <menu_item_check - label="Show Private Mem Info" - name="Show Private Mem Info"> - <menu_item_check.on_check - function="CheckControl" - parameter="DebugShowPrivateMem" /> - <menu_item_check.on_click - function="ToggleControl" - parameter="DebugShowPrivateMem" /> - </menu_item_check> <menu_item_separator/> diff --git a/indra/newview/skins/default/xui/es/floater_tos.xml b/indra/newview/skins/default/xui/es/floater_tos.xml index 412e0501a0..8d83eb5b24 100644 --- a/indra/newview/skins/default/xui/es/floater_tos.xml +++ b/indra/newview/skins/default/xui/es/floater_tos.xml @@ -12,10 +12,9 @@ <text name="external_tos_required"> Para poder proseguir, debes iniciar sesión en https://my.secondlife.com y aceptar las Condiciones del servicio. Gracias. </text> - <check_box label="He leído y acepto" name="agree_chk"/> <text name="agree_list"> - los Términos y Condiciones, la Política de privacidad y las Condiciones del servicio de Second Life, incluyendo los requerimientos para resolver disputas. - </text> + He leído y acepto los Términos y Condiciones, la Política de privacidad y las Condiciones del servicio de Second Life, incluyendo los requerimientos para resolver disputas. + </text> <button label="Continuar" label_selected="Continuar" name="Continue"/> <button label="Cancelar" label_selected="Cancelar" name="Cancel"/> </floater> diff --git a/indra/newview/skins/default/xui/fr/floater_tos.xml b/indra/newview/skins/default/xui/fr/floater_tos.xml index 124a8ffee2..4e359e6482 100644 --- a/indra/newview/skins/default/xui/fr/floater_tos.xml +++ b/indra/newview/skins/default/xui/fr/floater_tos.xml @@ -12,9 +12,8 @@ <text name="external_tos_required"> Vous devez vous rendre sur https://my.secondlife.com et vous connecter pour accepter les Conditions d’utilisation avant de pouvoir continuer. Merci ! </text> - <check_box label="J'ai lu et j'accepte" name="agree_chk"/> <text name="agree_list"> - les termes et conditions; la Politique de confidentialité et les Conditions d'utilisation de Second Life, y compris ls exigences de résolution des différends. + J'ai lu et j'accepte les termes et conditions; la Politique de confidentialité et les Conditions d'utilisation de Second Life, y compris ls exigences de résolution des différends. </text> <button label="Continuer" label_selected="Continuer" name="Continue"/> <button label="Annuler" label_selected="Annuler" name="Cancel"/> diff --git a/indra/newview/skins/default/xui/it/floater_tos.xml b/indra/newview/skins/default/xui/it/floater_tos.xml index 8fa74e0fca..0016df1882 100644 --- a/indra/newview/skins/default/xui/it/floater_tos.xml +++ b/indra/newview/skins/default/xui/it/floater_tos.xml @@ -12,10 +12,9 @@ <text name="external_tos_required"> Per continuare, visita https://my.secondlife.com e accedi per accettare i Termini del servizio. Grazie. </text> - <check_box label="Ho letto e sono d’accordo con" name="agree_chk"/> <text name="agree_list"> - i Termini e le Condizioni di Second Life, le clausole di riservatezza, i Termini del Servizio, compresi i requisiti per la risoluzione delle dispute. - </text> + Ho letto e sono d’accordo con i Termini e le Condizioni di Second Life, le clausole di riservatezza, i Termini del Servizio, compresi i requisiti per la risoluzione delle dispute. + </text> <button label="Continua" label_selected="Continua" name="Continue"/> <button label="Annulla" label_selected="Annulla" name="Cancel"/> </floater> diff --git a/indra/newview/skins/default/xui/ja/floater_tos.xml b/indra/newview/skins/default/xui/ja/floater_tos.xml index 28e51e6d63..8045a1f1f7 100644 --- a/indra/newview/skins/default/xui/ja/floater_tos.xml +++ b/indra/newview/skins/default/xui/ja/floater_tos.xml @@ -12,10 +12,9 @@ <text name="external_tos_required"> 操作を続けるに、https://my.secondlife.com に移動し、利用規約に同意する必要があります。 </text> - <check_box label="私は以下の内容を読み、同意します。" name="agree_chk"/> <text name="agree_list"> - Second Life の利用規約、プライバシーポリシー、およびサービス規約(紛争解決のための必要条件を含む)。 - </text> + 私は以下の内容を読み、同意します。Second Life の利用規約、プライバシーポリシー、およびサービス規約(紛争解決のための必要条件を含む)。 + </text> <button label="続行" label_selected="続行" name="Continue"/> <button label="取り消し" label_selected="取り消し" name="Cancel"/> </floater> diff --git a/indra/newview/skins/default/xui/pl/floater_tos.xml b/indra/newview/skins/default/xui/pl/floater_tos.xml index c3bc528d17..789c65a16e 100644 --- a/indra/newview/skins/default/xui/pl/floater_tos.xml +++ b/indra/newview/skins/default/xui/pl/floater_tos.xml @@ -5,7 +5,9 @@ </floater.string> <button label="Kontynuuj" label_selected="Kontynuuj" name="Continue" /> <button label="Anuluj" label_selected="Anuluj" name="Cancel" /> - <check_box label="Zgadzam się na Warunki korzystania z Usług (Terms of Service) i Politykę Prywatności (Privacy Policy)" name="agree_chk" /> + <text name="agree_list"> + Zgadzam się na Warunki korzystania z Usług (Terms of Service) i Politykę Prywatności (Privacy Policy) + </text> <text name="tos_heading"> Proszę dokładnie przeczytać Warunki korzystania z Usług (Terms of Service) i Politykę Prywatności (Privacy Policy). Musisz je zaakceptować, aby kontynuować logowanie. </text> diff --git a/indra/newview/skins/default/xui/pt/floater_tos.xml b/indra/newview/skins/default/xui/pt/floater_tos.xml index f8b2bc4aa7..09a90bc76c 100644 --- a/indra/newview/skins/default/xui/pt/floater_tos.xml +++ b/indra/newview/skins/default/xui/pt/floater_tos.xml @@ -12,10 +12,9 @@ <text name="external_tos_required"> Antes de continuar, você precisará visitar https://my.secondlife.com e fazer login para aceitar os Termos de Serviço. Obrigado! </text> - <check_box label="Li e concordo" name="agree_chk"/> <text name="agree_list"> - os Termos e condições, Política de privacidade e Termos de serviço do Second Life, incluindo as exigências para resolver disputas. - </text> + Li e concordo os Termos e condições, Política de privacidade e Termos de serviço do Second Life, incluindo as exigências para resolver disputas. + </text> <button label="Continuar" label_selected="Continuar" name="Continue"/> <button label="Cancelar" label_selected="Cancelar" name="Cancel"/> </floater> diff --git a/indra/newview/skins/default/xui/ru/floater_tos.xml b/indra/newview/skins/default/xui/ru/floater_tos.xml index 4c53fc9038..4cfdf5af70 100644 --- a/indra/newview/skins/default/xui/ru/floater_tos.xml +++ b/indra/newview/skins/default/xui/ru/floater_tos.xml @@ -12,10 +12,9 @@ <text name="external_tos_required"> Для продолжения перейдите на сайт https://my.secondlife.com, войдите и примите Условия обслуживания. Спасибо! </text> - <check_box label="Я прочитал и согласен с" name="agree_chk"/> <text name="agree_list"> - условия и положения по конфиденциальности Пользовательского соглашения, включая требования по разрешению разногласий. - </text> + Я прочитал и согласен с условиями и положениями по конфиденциальности Пользовательского соглашения, включая требования по разрешению разногласий. + </text> <button label="Продолжить" label_selected="Продолжить" name="Continue"/> <button label="Отмена" label_selected="Отмена" name="Cancel"/> </floater> diff --git a/indra/newview/skins/default/xui/tr/floater_tos.xml b/indra/newview/skins/default/xui/tr/floater_tos.xml index 249a0f691e..9c0249526a 100644 --- a/indra/newview/skins/default/xui/tr/floater_tos.xml +++ b/indra/newview/skins/default/xui/tr/floater_tos.xml @@ -12,9 +12,8 @@ <text name="external_tos_required"> Devam edebilmeniz için https://my.secondlife.com adresine gidip oturum açarak Hizmet Sözleşmesi'ni kabul etmeniz gerekir. Teşekkürler! </text> - <check_box label="Uyuşmazlıkların çözümü gerekliliklerini içeren Second Life Şartlar ve Koşulları, Gizlilik Politikası'nı ve Hizmet Koşulları'nı" name="agree_chk"/> <text name="agree_list"> - okudum ve kabul ediyorum. + Uyuşmazlıkların çözümü gerekliliklerini içeren Second Life Şartlar ve Koşulları, Gizlilik Politikası'nı ve Hizmet Koşulları'nı okudum ve kabul ediyorum. </text> <button label="Devam Et" label_selected="Devam Et" name="Continue"/> <button label="İptal" label_selected="İptal" name="Cancel"/> diff --git a/indra/newview/skins/default/xui/zh/floater_tos.xml b/indra/newview/skins/default/xui/zh/floater_tos.xml index 4e028c849f..cde6445e34 100644 --- a/indra/newview/skins/default/xui/zh/floater_tos.xml +++ b/indra/newview/skins/default/xui/zh/floater_tos.xml @@ -12,10 +12,9 @@ <text name="external_tos_required"> 你需先登入 https://my.secondlife.com 同意服務條款,才可繼續。 謝謝你! </text> - <check_box label="我已閱畢並同意" name="agree_chk"/> <text name="agree_list"> - Second Life使用條款、隱私政策、服務條款,包括解決爭端的規定途徑。 - </text> + 我已閱畢並同意 Second Life使用條款、隱私政策、服務條款,包括解決爭端的規定途徑。 + </text> <button label="繼續" label_selected="繼續" name="Continue"/> <button label="取消" label_selected="取消" name="Cancel"/> </floater> diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index e823228681..493bfac632 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -595,6 +595,9 @@ class WindowsManifest(ViewerManifest): self.path("featuretable.txt") self.path("ca-bundle.crt") + with self.prefix(src=pkgdir,dst="app_settings"): + self.path("ca-bundle.crt") + # Media plugins - CEF with self.prefix(src='../media_plugins/cef/%s' % self.args['configuration'], dst="llplugin"): self.path("media_plugin_cef.dll") @@ -1052,6 +1055,9 @@ open "%s" --args "$@" self.path("SecondLife.nib") self.path("ca-bundle.crt") + with self.prefix(src=pkgdir,dst="app_settings"): + self.path("ca-bundle.crt") + self.path("SecondLife.nib") # Translations @@ -1510,6 +1516,9 @@ class LinuxManifest(ViewerManifest): self.path("featuretable_linux.txt") self.path("ca-bundle.crt") + with self.prefix(src=pkgdir,dst="app_settings"): + self.path("ca-bundle.crt") + def package_finish(self): installer_name = self.installer_base_name() |