// This method should be called before each use of the mipmap (typically, before each draw), so that to let // the boost level of unused tiles to drop to 0 (BOOST_NONE). // Tiles that are accessed have had their boost level pushed to BOOST_MAP_VISIBLE so we can identify them. // The result of this strategy is that if a tile is not used during 2 consecutive loops, its boost level drops to 0. void LLWorldMipmap::equalizeBoostLevels() { #if DEBUG_TILES_STAT S32 nb_missing = 0; S32 nb_tiles = 0; S32 nb_visible = 0; #endif // DEBUG_TILES_STAT // For each level for (S32 level = 0; level < MAP_LEVELS; level++) { sublevel_tiles_t& level_mipmap = mWorldObjectsMipMap[level]; // For each tile for (sublevel_tiles_t::iterator iter = level_mipmap.begin(); iter != level_mipmap.end(); iter++) { LLPointer<LLViewerFetchedTexture> img = iter->second; S32 current_boost_level = img->getBoostLevel(); if (current_boost_level == LLGLTexture::BOOST_MAP_VISIBLE) { // If level was BOOST_MAP_VISIBLE, the tile has been used in the last draw so keep it high img->setBoostLevel(LLGLTexture::BOOST_MAP); } else { // If level was BOOST_MAP only (or anything else...), the tile wasn't used in the last draw // so we drop its boost level to BOOST_NONE. img->setBoostLevel(LLGLTexture::BOOST_NONE); } #if DEBUG_TILES_STAT // Increment some stats if compile option on nb_tiles++; if (current_boost_level == LLGLTexture::BOOST_MAP_VISIBLE) { nb_visible++; } if (img->isMissingAsset()) { nb_missing++; } #endif // DEBUG_TILES_STAT } } #if DEBUG_TILES_STAT LL_INFOS("World Map") << "LLWorldMipmap tile stats : total requested = " << nb_tiles << ", visible = " << nb_visible << ", missing = " << nb_missing << LL_ENDL; #endif // DEBUG_TILES_STAT }
void LLTextureBar::draw() { if (!mImagep) { return; } LLColor4 color; if (mImagep->getID() == LLAppViewer::getTextureFetch()->mDebugID) { color = LLColor4::cyan2; } else if (mHilite) { S32 idx = llclamp(mHilite,1,3); if (idx==1) color = LLColor4::orange; else if (idx==2) color = LLColor4::yellow; else color = LLColor4::pink2; } else if (mImagep->mDontDiscard) { color = LLColor4::green4; } else if (mImagep->getBoostLevel()) { color = LLColor4::magenta; } else if (mImagep->getDecodePriority() == 0.0f) { color = LLColor4::grey; color[VALPHA] = .7f; } else { color = LLColor4::white; color[VALPHA] = .7f; } // We need to draw: // The texture UUID or name // The progress bar for the texture, highlighted if it's being download // Various numerical stats. std::string tex_str; S32 left, right; S32 top = 0; S32 bottom = top + 6; LLColor4 clr; LLGLSUIDefault gls_ui; // Name, pixel_area, requested pixel area, decode priority std::string uuid_str; mImagep->mID.toString(uuid_str); uuid_str = uuid_str.substr(0,7); if (mTextureView->mOrderFetch) { tex_str = llformat("%s %7.0f %d(%d) 0x%08x(%8.0f)", uuid_str.c_str(), mImagep->mMaxVirtualSize, mImagep->mDesiredDiscardLevel, mImagep->mRequestedDiscardLevel, mImagep->mFetchPriority, mImagep->getDecodePriority()); } else { tex_str = llformat("%s %7.0f %d(%d) %8.0f(0x%08x)", uuid_str.c_str(), mImagep->mMaxVirtualSize, mImagep->mDesiredDiscardLevel, mImagep->mRequestedDiscardLevel, mImagep->getDecodePriority(), mImagep->mFetchPriority); } LLFontGL::sMonospace->renderUTF8(tex_str, 0, title_x1, getRect().getHeight(), color, LLFontGL::LEFT, LLFontGL::TOP); // State // Hack: mirrored from lltexturefetch.cpp struct { const std::string desc; LLColor4 color; } fetch_state_desc[] = { { "---", LLColor4::red }, // INVALID { "INI", LLColor4::white }, // INIT { "DSK", LLColor4::cyan }, // LOAD_FROM_TEXTURE_CACHE { "DSK", LLColor4::blue }, // CACHE_POST { "NET", LLColor4::green }, // LOAD_FROM_NETWORK { "SIM", LLColor4::green }, // LOAD_FROM_SIMULATOR { "URL", LLColor4::green2 },// LOAD_FROM_HTTP_GET_URL { "HTP", LLColor4::green }, // LOAD_FROM_HTTP_GET_DATA { "DEC", LLColor4::yellow },// DECODE_IMAGE { "DEC", LLColor4::yellow },// DECODE_IMAGE_UPDATE { "WRT", LLColor4::purple },// WRITE_TO_CACHE { "WRT", LLColor4::orange },// WAIT_ON_WRITE { "END", LLColor4::red }, // DONE #define LAST_STATE 12 { "CRE", LLColor4::magenta }, // LAST_STATE+1 { "FUL", LLColor4::green }, // LAST_STATE+2 { "BAD", LLColor4::red }, // LAST_STATE+3 { "MIS", LLColor4::red }, // LAST_STATE+4 { "---", LLColor4::white }, // LAST_STATE+5 }; const S32 fetch_state_desc_size = (S32)(sizeof(fetch_state_desc)/sizeof(fetch_state_desc[0])); S32 state = mImagep->mNeedsCreateTexture ? LAST_STATE+1 : mImagep->mFullyLoaded ? LAST_STATE+2 : mImagep->mMinDiscardLevel > 0 ? LAST_STATE+3 : mImagep->mIsMissingAsset ? LAST_STATE+4 : !mImagep->mIsFetching ? LAST_STATE+5 : mImagep->mFetchState; state = llclamp(state,0,fetch_state_desc_size-1); LLFontGL::sMonospace->renderUTF8(fetch_state_desc[state].desc, 0, title_x2, getRect().getHeight(), fetch_state_desc[state].color, LLFontGL::LEFT, LLFontGL::TOP); LLGLSNoTexture gls_no_texture; // Draw the progress bar. S32 bar_width = 100; S32 bar_left = 280; left = bar_left; right = left + bar_width; gGL.color4f(0.f, 0.f, 0.f, 0.75f); gl_rect_2d(left, top, right, bottom); F32 data_progress = mImagep->mDownloadProgress; if (data_progress > 0.0f) { // Downloaded bytes right = left + llfloor(data_progress * (F32)bar_width); if (right > left) { gGL.color4f(0.f, 0.f, 1.f, 0.75f); gl_rect_2d(left, top, right, bottom); } } S32 pip_width = 6; S32 pip_space = 14; S32 pip_x = title_x3 + pip_space/2; // Draw the packet pip F32 last_event = mImagep->mLastPacketTimer.getElapsedTimeF32(); if (last_event < 1.f) { clr = LLColor4::white; } else { last_event = mImagep->mRequestDeltaTime; if (last_event < 1.f) { clr = LLColor4::green; } else { last_event = mImagep->mFetchDeltaTime; if (last_event < 1.f) { clr = LLColor4::yellow; } } } if (last_event < 1.f) { clr.setAlpha(1.f - last_event); gGL.color4fv(clr.mV); gl_rect_2d(pip_x, top, pip_x + pip_width, bottom); } pip_x += pip_width + pip_space; // we don't want to show bind/resident pips for textures using the default texture if (mImagep->getHasGLTexture()) { // Draw the bound pip last_event = mImagep->sLastFrameTime - mImagep->mLastBindTime; if (last_event < 1.f) { clr = mImagep->getMissed() ? LLColor4::red : LLColor4::magenta1; clr.setAlpha(1.f - last_event); gGL.color4fv(clr.mV); gl_rect_2d(pip_x, top, pip_x + pip_width, bottom); } } pip_x += pip_width + pip_space; { LLGLSUIDefault gls_ui; // draw the packet data // { // std::string num_str = llformat("%3d/%3d", mImagep->mLastPacket+1, mImagep->mPackets); // LLFontGL::sMonospace->renderUTF8(num_str, 0, bar_left + 100, getRect().getHeight(), color, // LLFontGL::LEFT, LLFontGL::TOP); // } // draw the image size at the end { std::string num_str = llformat("%3dx%3d (%d) %7d", mImagep->getWidth(), mImagep->getHeight(), mImagep->getDiscardLevel(), mImagep->mTextureMemory); LLFontGL::sMonospace->renderUTF8(num_str, 0, title_x4, getRect().getHeight(), color, LLFontGL::LEFT, LLFontGL::TOP); } } }
void LLTextureView::draw() { if (!mFreezeView) { // LLViewerObject *objectp; // S32 te; for_each(mTextureBars.begin(), mTextureBars.end(), DeletePointer()); mTextureBars.clear(); delete mGLTexMemBar; mGLTexMemBar = 0; typedef std::multiset<decode_pair_t, compare_decode_pair > display_list_t; display_list_t display_image_list; if (mPrintList) { llinfos << "ID\tMEM\tBOOST\tPRI\tWIDTH\tHEIGHT\tDISCARD" << llendl; } for (LLViewerImageList::image_priority_list_t::iterator iter = gImageList.mImageList.begin(); iter != gImageList.mImageList.end(); ) { LLPointer<LLViewerImage> imagep = *iter++; S32 cur_discard = imagep->getDiscardLevel(); S32 desired_discard = imagep->mDesiredDiscardLevel; if (mPrintList) { llinfos << imagep->getID() << "\t" << imagep->mTextureMemory << "\t" << imagep->getBoostLevel() << "\t" << imagep->getDecodePriority() << "\t" << imagep->getWidth() << "\t" << imagep->getHeight() << "\t" << cur_discard << llendl; } #if 0 if (imagep->getDontDiscard()) { continue; } if (imagep->isMissingAsset()) { continue; } #endif #define HIGH_PRIORITY 100000000.f F32 pri; if (mOrderFetch) { pri = ((F32)imagep->mFetchPriority)/256.f; } else { pri = imagep->getDecodePriority(); } if (sDebugImages.find(imagep) != sDebugImages.end()) { pri += 4*HIGH_PRIORITY; } if (!mOrderFetch) { #if 1 if (pri < HIGH_PRIORITY && LLSelectMgr::getInstance()) { struct f : public LLSelectedTEFunctor { LLViewerImage* mImage; f(LLViewerImage* image) : mImage(image) {} virtual bool apply(LLViewerObject* object, S32 te) { return (mImage == object->getTEImage(te)); } } func(imagep); const bool firstonly = true; bool match = LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func, firstonly); if (match) { pri += 3*HIGH_PRIORITY; } } #endif #if 1 if (pri < HIGH_PRIORITY && (cur_discard< 0 || desired_discard < cur_discard)) { LLViewerObject *objectp = gHoverView->getLastHoverObject(); if (objectp) { S32 tex_count = objectp->getNumTEs(); for (S32 i = 0; i < tex_count; i++) { if (imagep == objectp->getTEImage(i)) { pri += 2*HIGH_PRIORITY; break; } } } } #endif #if 1 if (pri > 0.f && pri < HIGH_PRIORITY) { if (imagep->mLastPacketTimer.getElapsedTimeF32() < 1.f || imagep->mFetchDeltaTime < 0.25f) { pri += 1*HIGH_PRIORITY; } } #endif } if (pri > 0.0f) { display_image_list.insert(std::make_pair(pri, imagep)); } } if (mPrintList) { mPrintList = FALSE; } static S32 max_count = 50; S32 count = 0; for (display_list_t::iterator iter = display_image_list.begin(); iter != display_image_list.end(); iter++) { LLViewerImage* imagep = iter->second; S32 hilite = 0; F32 pri = iter->first; if (pri >= 1 * HIGH_PRIORITY) { hilite = (S32)((pri+1) / HIGH_PRIORITY) - 1; } if ((hilite || count < max_count-10) && (count < max_count)) { if (addBar(imagep, hilite)) { count++; } } } if (mOrderFetch) sortChildren(LLTextureBar::sort_fetch()); else sortChildren(LLTextureBar::sort()); mGLTexMemBar = new LLGLTexMemBar("gl texmem bar", this); addChild(mGLTexMemBar); reshape(getRect().getWidth(), getRect().getHeight(), TRUE); /* count = gImageList.getNumImages(); std::string info_string; info_string = llformat("Global Info:\nTexture Count: %d", count); mInfoTextp->setText(info_string); */ for (child_list_const_iter_t child_iter = getChildList()->begin(); child_iter != getChildList()->end(); ++child_iter) { LLView *viewp = *child_iter; if (viewp->getRect().mBottom < 0) { viewp->setVisible(FALSE); } } } LLContainerView::draw(); }
void LLTextureView::draw() { if (!mFreezeView) { // LLViewerObject *objectp; // S32 te; for_each(mTextureBars.begin(), mTextureBars.end(), KillView()); mTextureBars.clear(); if (mGLTexMemBar) { removeChild(mGLTexMemBar); mGLTexMemBar->die(); mGLTexMemBar = 0; } if (mAvatarTexBar) { removeChild(mAvatarTexBar); mAvatarTexBar->die(); mAvatarTexBar = 0; } typedef std::multiset<decode_pair_t, compare_decode_pair > display_list_t; display_list_t display_image_list; if (mPrintList) { llinfos << "ID\tMEM\tBOOST\tPRI\tWIDTH\tHEIGHT\tDISCARD" << llendl; } for (LLViewerTextureList::image_priority_list_t::iterator iter = gTextureList.mImageList.begin(); iter != gTextureList.mImageList.end(); ) { LLPointer<LLViewerFetchedTexture> imagep = *iter++; if(!imagep->hasFetcher()) { continue ; } S32 cur_discard = imagep->getDiscardLevel(); S32 desired_discard = imagep->mDesiredDiscardLevel; if (mPrintList) { S32 tex_mem = imagep->hasGLTexture() ? imagep->getTextureMemory() : 0 ; llinfos << imagep->getID() << "\t" << tex_mem << "\t" << imagep->getBoostLevel() << "\t" << imagep->getDecodePriority() << "\t" << imagep->getWidth() << "\t" << imagep->getHeight() << "\t" << cur_discard << llendl; } if (imagep->getID() == LLAppViewer::getTextureFetch()->mDebugID) { static S32 debug_count = 0; ++debug_count; // for breakpoints } F32 pri; if (mOrderFetch) { pri = ((F32)imagep->mFetchPriority)/256.f; } else { pri = imagep->getDecodePriority(); } pri = llclamp(pri, 0.0f, HIGH_PRIORITY-1.f); if (sDebugImages.find(imagep) != sDebugImages.end()) { pri += 4*HIGH_PRIORITY; } if (!mOrderFetch) { if (pri < HIGH_PRIORITY && LLSelectMgr::getInstance()) { struct f : public LLSelectedTEFunctor { LLViewerFetchedTexture* mImage; f(LLViewerFetchedTexture* image) : mImage(image) {} virtual bool apply(LLViewerObject* object, S32 te) { return (mImage == object->getTEImage(te)); } } func(imagep); const bool firstonly = true; bool match = LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func, firstonly); if (match) { pri += 3*HIGH_PRIORITY; } } if (pri < HIGH_PRIORITY && (cur_discard< 0 || desired_discard < cur_discard)) { LLSelectNode* hover_node = LLSelectMgr::instance().getHoverNode(); if (hover_node) { LLViewerObject *objectp = hover_node->getObject(); if (objectp) { S32 tex_count = objectp->getNumTEs(); for (S32 i = 0; i < tex_count; i++) { if (imagep == objectp->getTEImage(i)) { pri += 2*HIGH_PRIORITY; break; } } } } } if (pri > 0.f && pri < HIGH_PRIORITY) { if (imagep->mLastPacketTimer.getElapsedTimeF32() < 1.f || imagep->mFetchDeltaTime < 0.25f) { pri += 1*HIGH_PRIORITY; } } } if (pri > 0.0f) { display_image_list.insert(std::make_pair(pri, imagep)); } } if (mPrintList) { mPrintList = FALSE; } static S32 max_count = 50; S32 count = 0; mNumTextureBars = 0 ; for (display_list_t::iterator iter = display_image_list.begin(); iter != display_image_list.end(); iter++) { LLViewerFetchedTexture* imagep = iter->second; S32 hilite = 0; F32 pri = iter->first; if (pri >= 1 * HIGH_PRIORITY) { hilite = (S32)((pri+1) / HIGH_PRIORITY) - 1; } if ((hilite || count < max_count-10) && (count < max_count)) { if (addBar(imagep, hilite)) { count++; } } } if (mOrderFetch) sortChildren(LLTextureBar::sort_fetch()); else sortChildren(LLTextureBar::sort()); LLGLTexMemBar::Params tmbp; LLRect tmbr; tmbp.name("gl texmem bar"); tmbp.rect(tmbr); tmbp.follows.flags = FOLLOWS_LEFT|FOLLOWS_TOP; tmbp.texture_view(this); mGLTexMemBar = LLUICtrlFactory::create<LLGLTexMemBar>(tmbp); addChild(mGLTexMemBar); sendChildToFront(mGLTexMemBar); LLAvatarTexBar::Params atbp; LLRect atbr; atbp.name("gl avatartex bar"); atbp.texture_view(this); atbp.rect(atbr); mAvatarTexBar = LLUICtrlFactory::create<LLAvatarTexBar>(atbp); addChild(mAvatarTexBar); sendChildToFront(mAvatarTexBar); reshape(getRect().getWidth(), getRect().getHeight(), TRUE); LLUI::popMatrix(); LLUI::pushMatrix(); LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); for (child_list_const_iter_t child_iter = getChildList()->begin(); child_iter != getChildList()->end(); ++child_iter) { LLView *viewp = *child_iter; if (viewp->getRect().mBottom < 0) { viewp->setVisible(FALSE); } } } LLContainerView::draw(); }