00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include <sys/stat.h>
00035 
00036 #include "llviewerimagelist.h"
00037 #include "imageids.h"
00038 #include "llgl.h" 
00039 #include "llimagegl.h"
00040 #include "llimagebmp.h"
00041 #include "llimagej2c.h"
00042 #include "llimagetga.h"
00043 #include "llimagejpeg.h"
00044 #include "llimagepng.h"
00045 #include "llmediaengine.h"
00046 
00047 #include "llsdserialize.h"
00048 #include "llsys.h"
00049 #include "llvfs.h"
00050 #include "llvfile.h"
00051 #include "llvfsthread.h"
00052 #include "message.h"
00053 
00054 #include "llagent.h"
00055 #include "lltexturecache.h"
00056 #include "lltexturefetch.h"
00057 #include "llviewercontrol.h"
00058 #include "llviewerimage.h"
00059 #include "llviewerregion.h"
00060 #include "pipeline.h"
00061 #include "viewer.h"
00062 
00064 
00065 void (*LLViewerImageList::sUUIDCallback)(void **, const LLUUID&) = NULL;
00066 
00067 U32 LLViewerImageList::sTextureBits = 0;
00068 U32 LLViewerImageList::sTexturePackets = 0;
00069 
00070 const S32 IMAGES_PER_REQUEST = 42;
00071 const S32 IMAGES_MIN_UPDATES = 4;  
00072 const S32 IMAGES_MAX_PACKET_UPDATES = 1; 
00073 const F32 RESEND_IMAGE_REQUEST_TIME = 15.f; 
00074 
00075 LLViewerImageList gImageList;
00076 
00077 S32 LLViewerImageList::sNumImages = 0;
00078 LLStat LLViewerImageList::sNumImagesStat(32, TRUE);
00079 LLStat LLViewerImageList::sNumRawImagesStat(32, TRUE);
00080 LLStat LLViewerImageList::sGLTexMemStat(32, TRUE);
00081 LLStat LLViewerImageList::sGLBoundMemStat(32, TRUE);
00082 LLStat LLViewerImageList::sRawMemStat(32, TRUE);
00083 LLStat LLViewerImageList::sFormattedMemStat(32, TRUE);
00084 
00086 
00087 LLViewerImageList::LLViewerImageList() 
00088         : LLImageProviderInterface(),
00089           mForceResetTextureStats(FALSE),
00090           mUpdateStats(FALSE),
00091           mMaxResidentTexMem(0),
00092           mVideoMemorySetting(0),
00093           mMovieImageHasMips(FALSE)     
00094 {
00095 }
00096 
00097 void LLViewerImageList::init()
00098 {
00099         sNumImages = 0;
00100         mMaxResidentTexMem = 0;
00101         mVideoMemorySetting = 0;
00102 
00103         if (gNoRender)
00104         {
00105                 
00106                 return;
00107         }
00108 
00109         mUpdateStats = TRUE;
00110 
00111         
00112         updateMaxResidentTexMem();
00113 
00114         mMovieImageHasMips = FALSE;
00115 
00116         doPreloadImages();
00117 }
00118 
00119 
00120 void LLViewerImageList::doPreloadImages()
00121 {
00122         llinfos << "Preloading images..." << llendl;
00123 
00124         
00125         LLViewerImage::sMissingAssetImagep = preloadImage("missing_asset.tga" , LLUUID::null, TRUE);
00126 
00127         
00128         LLViewerImage::sWhiteImagep = preloadImage("white.tga", LLUUID::null, TRUE);
00129 
00130         
00131         if (!gPreloadImages) return;
00132 
00133         
00134         
00135         
00136         preloadImage("button_disabled_32x128.tga", LLUUID::null, FALSE);
00137         preloadImage("button_enabled_32x128.tga", LLUUID::null, FALSE);
00138         preloadImage("button_enabled_selected_32x128.tga", LLUUID::null, FALSE);
00139         preloadImage("checkbox_disabled_false.tga", LLUUID::null, FALSE);
00140         preloadImage("checkbox_disabled_true.tga", LLUUID::null, FALSE);
00141         preloadImage("checkbox_enabled_false.tga", LLUUID::null, FALSE);
00142         preloadImage("checkbox_enabled_true.tga", LLUUID::null, FALSE);
00143         preloadImage("close_in_blue.tga", LLUUID::null, FALSE);
00144         preloadImage("combobox_arrow.tga", LLUUID::null, FALSE);
00145         preloadImage("minimize.tga", LLUUID::null, FALSE);
00146         preloadImage("minimize_pressed.tga", LLUUID::null, FALSE);
00147         preloadImage("radio_active_false.tga", LLUUID::null, FALSE);
00148         preloadImage("radio_active_true.tga", LLUUID::null, FALSE);
00149         preloadImage("radio_inactive_false.tga", LLUUID::null, FALSE);
00150         preloadImage("radio_inactive_true.tga", LLUUID::null, FALSE);
00151         preloadImage("resize_handle_bottom_right_blue.tga", LLUUID::null, FALSE);
00152         preloadImage("rounded_square.tga", LLUUID::null, FALSE);
00153         preloadImage("rounded_square_soft.tga", LLUUID::null, FALSE);
00154         preloadImage("scrollbutton_down_in_blue.tga", LLUUID::null, FALSE);
00155         preloadImage("scrollbutton_down_out_blue.tga", LLUUID::null, FALSE);
00156         preloadImage("scrollbutton_left_in_blue.tga", LLUUID::null, FALSE);
00157         preloadImage("scrollbutton_left_out_blue.tga", LLUUID::null, FALSE);
00158         preloadImage("scrollbutton_right_in_blue.tga", LLUUID::null, FALSE);
00159         preloadImage("scrollbutton_right_out_blue.tga", LLUUID::null, FALSE);
00160         preloadImage("scrollbutton_up_in_blue.tga", LLUUID::null, FALSE);
00161         preloadImage("scrollbutton_up_out_blue.tga", LLUUID::null, FALSE);
00162         preloadImage("spin_down_in_blue.tga", LLUUID::null, FALSE);
00163         preloadImage("spin_down_out_blue.tga", LLUUID::null, FALSE);
00164         preloadImage("spin_up_in_blue.tga", LLUUID::null, FALSE);
00165         preloadImage("spin_up_out_blue.tga", LLUUID::null, FALSE);
00166         preloadImage("square_btn_32x128.tga", LLUUID::null, FALSE);
00167         preloadImage("square_btn_selected_32x128.tga", LLUUID::null, FALSE);
00168         preloadImage("startup_logo.tga", LLUUID::null, FALSE);                          
00169         preloadImage("tab_bottom_blue.tga", LLUUID::null, FALSE);
00170         preloadImage("tab_bottom_selected_blue.tga", LLUUID::null, FALSE);
00171         preloadImage("tab_left.tga", LLUUID::null, FALSE);
00172         preloadImage("tab_left_selected.tga", LLUUID::null, FALSE);
00173         preloadImage("tab_top_blue.tga", LLUUID::null, FALSE);
00174         preloadImage("tab_top_selected_blue.tga", LLUUID::null, FALSE);
00175         
00176         decodeAllImages(2.f); 
00177         
00178         
00179         
00180         preloadImage("active_voice_tab.tga", LLUUID::null, FALSE);
00181         preloadImage("button_anim_pause.tga", LLUUID::null, FALSE);
00182         preloadImage("button_anim_pause_selected.tga", LLUUID::null, FALSE);
00183         preloadImage("button_anim_play.tga", LLUUID::null, FALSE);
00184         preloadImage("button_anim_play_selected.tga", LLUUID::null, FALSE);
00185         preloadImage("button_anim_stop.tga", LLUUID::null, FALSE);
00186         preloadImage("button_anim_stop_selected.tga", LLUUID::null, FALSE);
00187         preloadImage("crosshairs.tga", LLUUID::null, FALSE);
00188         preloadImage("direction_arrow.tga", LLUUID::null, FALSE);
00189         preloadImage("eyes.tga", LLUUID::null, TRUE);
00190         preloadImage("foot_shadow.tga", LLUUID::null, TRUE);
00191         preloadImage("hair.tga", LLUUID::null, TRUE);
00192         preloadImage("icon_for_sale.tga", LLUUID::null, FALSE);
00193         preloadImage("icon_popular.tga", LLUUID::null, FALSE);
00194         preloadImage("icon_top_pick.tga", LLUUID::null, FALSE);
00195         preloadImage("img_shot.tga", IMG_SHOT, TRUE);
00196         preloadImage("img_smoke_poof.tga", IMG_SMOKE_POOF, TRUE);
00197         preloadImage("inv_folder_animation.tga", LLUUID::null, FALSE);
00198         preloadImage("inv_folder_bodypart.tga", LLUUID::null, FALSE);
00199         preloadImage("inv_folder_callingcard.tga", LLUUID::null, FALSE);
00200         preloadImage("inv_folder_clothing.tga", LLUUID::null, FALSE);
00201         preloadImage("inv_folder_gesture.tga", LLUUID::null, FALSE);
00202         preloadImage("inv_folder_landmark.tga", LLUUID::null, FALSE);
00203         preloadImage("inv_folder_lostandfound.tga", LLUUID::null, FALSE);
00204         preloadImage("inv_folder_notecard.tga", LLUUID::null, FALSE);
00205         preloadImage("inv_folder_object.tga", LLUUID::null, FALSE);
00206         preloadImage("inv_folder_plain_closed.tga", LLUUID::null, FALSE);
00207         preloadImage("inv_folder_script.tga", LLUUID::null, FALSE);
00208         preloadImage("inv_folder_snapshot.tga", LLUUID::null, FALSE);
00209         preloadImage("inv_folder_sound.tga", LLUUID::null, FALSE);
00210         preloadImage("inv_folder_texture.tga", LLUUID::null, FALSE);
00211         preloadImage("inv_folder_trash.tga", LLUUID::null, FALSE);
00212         preloadImage("inv_item_animation.tga", LLUUID::null, FALSE);
00213         preloadImage("inv_item_bodypart.tga", LLUUID::null, FALSE);
00214         preloadImage("inv_item_callingcard_offline.tga", LLUUID::null, FALSE);
00215         preloadImage("inv_item_callingcard_online.tga", LLUUID::null, FALSE);
00216         preloadImage("inv_item_eyes.tga", LLUUID::null, FALSE);
00217         preloadImage("inv_item_gesture.tga", LLUUID::null, FALSE);
00218         preloadImage("inv_item_gloves.tga", LLUUID::null, FALSE);
00219         preloadImage("inv_item_hair.tga", LLUUID::null, FALSE);
00220         preloadImage("inv_item_jacket.tga", LLUUID::null, FALSE);
00221         preloadImage("inv_item_landmark.tga", LLUUID::null, FALSE);
00222         preloadImage("inv_item_landmark_visited.tga", LLUUID::null, FALSE);
00223         preloadImage("inv_item_notecard.tga", LLUUID::null, FALSE);
00224         preloadImage("inv_item_object.tga", LLUUID::null, FALSE);
00225         preloadImage("inv_item_object_multi.tga", LLUUID::null, FALSE);
00226         preloadImage("inv_item_pants.tga", LLUUID::null, FALSE);
00227         preloadImage("inv_item_script.tga", LLUUID::null, FALSE);
00228         preloadImage("inv_item_shape.tga", LLUUID::null, FALSE);
00229         preloadImage("inv_item_shirt.tga", LLUUID::null, FALSE);
00230         preloadImage("inv_item_shoes.tga", LLUUID::null, FALSE);
00231         preloadImage("inv_item_skirt.tga", LLUUID::null, FALSE);
00232         preloadImage("inv_item_snapshot.tga", LLUUID::null, FALSE);
00233         preloadImage("inv_item_socks.tga", LLUUID::null, FALSE);
00234         preloadImage("inv_item_sound.tga", LLUUID::null, FALSE);
00235         preloadImage("inv_item_texture.tga", LLUUID::null, FALSE);
00236         preloadImage("inv_item_underpants.tga", LLUUID::null, FALSE);
00237         preloadImage("inv_item_undershirt.tga", LLUUID::null, FALSE);
00238         preloadImage("lag_status_critical.tga", LLUUID::null, FALSE);
00239         preloadImage("lag_status_good.tga", LLUUID::null, FALSE);
00240         preloadImage("lag_status_warning.tga", LLUUID::null, FALSE);
00241         preloadImage("legend.tga", LLUUID::null, FALSE);
00242         preloadImage("map_avatar_16.tga", LLUUID::null, FALSE);
00243         preloadImage("map_avatar_8.tga", LLUUID::null, FALSE);
00244         preloadImage("map_avatar_above_8.tga", LLUUID::null, FALSE);
00245         preloadImage("map_avatar_below_8.tga", LLUUID::null, FALSE);
00246         preloadImage("map_avatar_you_8.tga", LLUUID::null, FALSE);
00247         preloadImage("map_event.tga", LLUUID::null, FALSE);
00248         preloadImage("map_event_mature.tga", LLUUID::null, FALSE);
00249         preloadImage("map_home.tga", LLUUID::null, FALSE);
00250         preloadImage("map_infohub.tga", LLUUID::null, FALSE);
00251         preloadImage("map_telehub.tga", LLUUID::null, FALSE);
00252         preloadImage("map_track_16.tga", LLUUID::null, FALSE);
00253         preloadImage("media_icon.tga", LLUUID::null, FALSE);
00254         preloadImage("music_icon.tga", LLUUID::null, FALSE);
00255         preloadImage("noentrylines.tga", LLUUID::null, TRUE);
00256         preloadImage("noentrypasslines.tga", LLUUID::null, TRUE);
00257         preloadImage("notify_tip_icon.tga", LLUUID::null, FALSE);
00258         preloadImage("notify_caution_icon.tga", LLUUID::null, FALSE);
00259         preloadImage("notify_box_icon.tga", LLUUID::null, FALSE);
00260         preloadImage("object_cone.tga", LLUUID::null, FALSE);
00261         preloadImage("object_cone_active.tga", LLUUID::null, FALSE);
00262         preloadImage("object_cube.tga", LLUUID::null, FALSE);
00263         preloadImage("object_cube_active.tga", LLUUID::null, FALSE);
00264         preloadImage("object_cylinder.tga", LLUUID::null, FALSE);
00265         preloadImage("object_cylinder_active.tga", LLUUID::null, FALSE);
00266         preloadImage("object_grass.tga", LLUUID::null, FALSE);
00267         preloadImage("object_grass_active.tga", LLUUID::null, FALSE);
00268         preloadImage("object_hemi_cone.tga", LLUUID::null, FALSE);
00269         preloadImage("object_hemi_cone_active.tga", LLUUID::null, FALSE);
00270         preloadImage("object_hemi_cylinder.tga", LLUUID::null, FALSE);
00271         preloadImage("object_hemi_cylinder_active.tga", LLUUID::null, FALSE);
00272         preloadImage("object_hemi_sphere.tga", LLUUID::null, FALSE);
00273         preloadImage("object_hemi_sphere_active.tga", LLUUID::null, FALSE);
00274         preloadImage("object_prism.tga", LLUUID::null, FALSE);
00275         preloadImage("object_prism_active.tga", LLUUID::null, FALSE);
00276         preloadImage("object_pyramid.tga", LLUUID::null, FALSE);
00277         preloadImage("object_pyramid_active.tga", LLUUID::null, FALSE);
00278         preloadImage("object_ring.tga", LLUUID::null, FALSE);
00279         preloadImage("object_ring_active.tga", LLUUID::null, FALSE);
00280         preloadImage("object_sphere.tga", LLUUID::null, FALSE);
00281         preloadImage("object_sphere_active.tga", LLUUID::null, FALSE);
00282         preloadImage("object_tetrahedron.tga", LLUUID::null, FALSE);
00283         preloadImage("object_tetrahedron_active.tga", LLUUID::null, FALSE);
00284         preloadImage("object_torus.tga", LLUUID::null, FALSE);
00285         preloadImage("object_torus_active.tga", LLUUID::null, FALSE);
00286         preloadImage("object_tree.tga", LLUUID::null, FALSE);
00287         preloadImage("object_tree_active.tga", LLUUID::null, FALSE);
00288         preloadImage("object_tube.tga", LLUUID::null, FALSE);
00289         preloadImage("object_tube_active.tga", LLUUID::null, FALSE);
00290         preloadImage("pixiesmall.tga", LLUUID::null, TRUE);     
00291         preloadImage("script_error.tga", LLUUID::null, TRUE);
00292         preloadImage("silhouette.tga", LLUUID::null, TRUE);
00293         preloadImage("status_build.tga", LLUUID::null, FALSE);
00294         preloadImage("status_buy_currency.tga", LLUUID::null, FALSE);
00295         preloadImage("status_buy_currency_pressed.tga", LLUUID::null, FALSE);
00296         preloadImage("status_buy_land.tga", LLUUID::null, FALSE);
00297         preloadImage("status_buy_land_pressed.tga", LLUUID::null, FALSE);
00298         preloadImage("status_fly.tga", LLUUID::null, FALSE);
00299         preloadImage("status_health.tga", LLUUID::null, FALSE);
00300         preloadImage("status_scripts.tga", LLUUID::null, FALSE);
00301         preloadImage("tool_dozer.tga", LLUUID::null, FALSE);
00302         preloadImage("tool_dozer_active.tga", LLUUID::null, FALSE);
00303         preloadImage("tool_zoom.tga", LLUUID::null, FALSE);
00304         preloadImage("tool_zoom_active.tga", LLUUID::null, FALSE);
00305         preloadImage("volume_icon.tga", LLUUID::null, FALSE);
00306         preloadImage("icn_active-speakers-dot-lvl0.tga", LLUUID::null, FALSE);
00307         preloadImage("icn_active-speakers-dot-lvl1.tga", LLUUID::null, FALSE);
00308         preloadImage("icn_active-speakers-dot-lvl2.tga", LLUUID::null, FALSE);
00309         preloadImage("icn_active-speakers-typing1.tga", LLUUID::null, FALSE);
00310         preloadImage("icn_active-speakers-typing2.tga", LLUUID::null, FALSE);
00311         preloadImage("icn_active-speakers-typing3.tga", LLUUID::null, FALSE);
00312         preloadImage("icn_voice_ptt-off.tga", LLUUID::null, FALSE);
00313         preloadImage("icn_voice_ptt-on.tga", LLUUID::null, FALSE);
00314         preloadImage("icn_voice_ptt-on-lvl1.tga", LLUUID::null, FALSE);
00315         preloadImage("icn_voice_ptt-on-lvl2.tga", LLUUID::null, FALSE);
00316         preloadImage("icn_voice_ptt-on-lvl3.tga", LLUUID::null, FALSE);
00317         preloadImage("lag_status_good.tga", LLUUID::null, FALSE);
00318         preloadImage("lag_status_warning.tga", LLUUID::null, FALSE);
00319         preloadImage("lag_status_critical.tga", LLUUID::null, FALSE);
00320 }
00321 
00322 static std::string get_texture_list_name()
00323 {
00324         BOOL login_last = gSavedSettings.getBOOL("LoginLastLocation");
00325         return std::string("texture_list_") + (login_last?"last":"home") + ".xml";
00326 }
00327 
00328 void LLViewerImageList::doPrefetchImages()
00329 {
00330         if (gPurgeCache)
00331         {
00332                 
00333                 return;
00334         }
00335         
00336         
00337         LLSD imagelist;
00338         std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, get_texture_list_name());
00339         llifstream file;
00340         file.open(filename.c_str());
00341         if (file.is_open())
00342         {
00343                 LLSDSerialize::fromXML(imagelist, file);
00344         }
00345         for (LLSD::array_iterator iter = imagelist.beginArray();
00346                  iter != imagelist.endArray(); ++iter)
00347         {
00348                 LLSD imagesd = *iter;
00349                 LLUUID uuid = imagesd["uuid"];
00350                 S32 pixel_area = imagesd["area"];
00351                 LLViewerImage* image = getImage(uuid, MIPMAP_TRUE, FALSE);
00352                 if (image)
00353                 {
00354                         image->addTextureStats((F32)pixel_area);
00355                 }
00356         }
00357 
00358         
00359 }
00360 
00362 
00363 LLViewerImageList::~LLViewerImageList()
00364 {
00365         llassert(mIRCallbackData.empty());
00366 }
00367 
00368 void LLViewerImageList::shutdown()
00369 {
00370         
00371         typedef std::set<std::pair<S32,LLViewerImage*> > image_area_list_t;
00372         image_area_list_t image_area_list;
00373         for (image_priority_list_t::iterator iter = mImageList.begin();
00374                  iter != mImageList.end(); ++iter)
00375         {
00376                 LLViewerImage* image = *iter;
00377                 if (!image->getUseDiscard() ||
00378                         image->needsAux() ||
00379                         image->getTargetHost() != LLHost::invalid)
00380                 {
00381                         continue; 
00382                 }
00383                 S32 desired = image->getDesiredDiscardLevel();
00384                 if (desired >= 0 && desired < MAX_DISCARD_LEVEL)
00385                 {
00386                         S32 pixel_area = image->getWidth(desired) * image->getHeight(desired);
00387                         image_area_list.insert(std::make_pair(pixel_area, image));
00388                 }
00389         }
00390         
00391         LLSD imagelist;
00392         const S32 max_count = 1000;
00393         S32 count = 0;
00394         for (image_area_list_t::reverse_iterator riter = image_area_list.rbegin();
00395                  riter != image_area_list.rend(); ++riter)
00396         {
00397                 LLViewerImage* image = riter->second;
00398                 imagelist[count]["area"] = riter->first;
00399                 imagelist[count]["uuid"] = image->getID();
00400                 if (++count >= max_count)
00401                         break;
00402         }
00403 
00404         if (count > 0 && !gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "").empty())
00405         {
00406                 std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, get_texture_list_name());
00407                 llofstream file;
00408                 file.open(filename.c_str());
00409                 LLSDSerialize::toPrettyXML(imagelist, file);
00410         }
00411         
00412         
00413         
00414         
00415         mCallbackList.clear();
00416         mIRCallbackData.clear();
00417         
00418         
00419         mPreloadedImages.clear();
00420         
00421         
00422         mLoadingStreamList.clear();
00423         mCreateTextureList.clear();
00424 
00425         mUUIDMap.clear();
00426 
00427         mImageList.clear();
00428 }
00429 
00430 void LLViewerImageList::dump()
00431 {
00432         llinfos << "LLViewerImageList::dump()" << llendl;
00433         for (image_priority_list_t::iterator it = mImageList.begin(); it != mImageList.end(); ++it)
00434         {
00435                 LLViewerImage* image = *it;
00436 
00437                 llinfos << "priority " << image->getDecodePriority()
00438                         << " boost " << image->getBoostLevel()
00439                         << " size " << image->getWidth() << "x" << image->getHeight()
00440                         << " discard " << image->getDiscardLevel()
00441                         << " desired " << image->getDesiredDiscardLevel()
00442                         << " http://asset.siva.lindenlab.com/" << image->getID() << ".texture"
00443                         << llendl;
00444         }
00445 }
00446 
00447 void LLViewerImageList::destroyGL(BOOL save_state)
00448 {
00449         LLImageGL::destroyGL(save_state);
00450 }
00451 
00452 void LLViewerImageList::restoreGL()
00453 {
00454         LLImageGL::restoreGL();
00455 }
00456 
00457 
00458 
00459 
00460 
00461 
00462 
00463 
00464 LLImageGL* LLViewerImageList::getUIImageByID(const LLUUID& image_id, BOOL clamped)
00465 {
00466         LLViewerImage* imagep = getImage(image_id, MIPMAP_FALSE, TRUE);
00467         
00468         
00469         imagep->setBoostLevel(LLViewerImage::BOOST_UI);
00470         LLViewerImage::bindTexture(imagep);
00471         imagep->setClamp(clamped, clamped);
00472         imagep->unbindTexture(0, GL_TEXTURE_2D);
00473 
00474         return (LLImageGL*)imagep;
00475 }
00476 
00478 
00479 LLViewerImage* LLViewerImageList::preloadImage(const LLString& filename, const LLUUID &image_set_id, BOOL use_mips)
00480 {
00481         LLViewerImage* image = getImage(filename, image_set_id, use_mips, TRUE);
00482         image->dontDiscard();
00483         mPreloadedImages.push_back(image);
00484         return image;
00485 }
00486 
00488 
00489 LLViewerImage* LLViewerImageList::getImage(const LLString& filename,
00490                                                                                    const LLUUID &image_set_id,
00491                                                                                    BOOL usemipmaps,
00492                                                                                    BOOL level_immediate)
00493 {
00494         return getImageFromFile(filename, image_set_id, usemipmaps, level_immediate, 0, 0);
00495 }
00496 
00497 LLViewerImage* LLViewerImageList::getImageFromFile(const LLString& filename,
00498                                                                                                    const LLUUID &image_set_id,
00499                                                                                                    BOOL usemipmaps,
00500                                                                                                    BOOL level_immediate,
00501                                                                                                    LLGLint internal_format,
00502                                                                                                    LLGLenum primary_format)
00503 {
00504         if (gNoRender)
00505         {
00506                 
00507                 
00508                 return getImage(IMG_DEFAULT, TRUE, TRUE);
00509         }
00510         
00511         
00512         
00513 
00514         
00515         LLUUID image_id = LLUUID( gViewerArt.getString(filename.c_str()) );
00516         if (image_id.isNull())
00517         {
00518                 llwarns << "Unable to find image " << filename << " in gViewerArt" << llendl;
00519                 if (image_set_id.notNull())
00520                 {
00521                         
00522                         
00523                         image_id = LLUUID(gViewerArt.getString("missing_asset.tga"));
00524                         if (image_id.isNull())
00525                         {
00526                                 llerrs << "Missing missing_asset.tga!" << llendl;
00527                         }
00528                         return getImageFromFile(LLString("missing_asset.tga"), image_set_id,
00529                                                                         usemipmaps, level_immediate,
00530                                                                         internal_format, primary_format);
00531                 }
00532                 else
00533                 {
00534                         return (getImage(IMG_DEFAULT, TRUE, TRUE));
00535                 }
00536         }
00537 
00538         
00539         
00540         if (image_set_id.notNull())
00541         {
00542                 image_id = image_set_id;
00543         }
00544         
00545         
00546         LLViewerImage* imagep = getImageFromUUID(image_id, usemipmaps, level_immediate, 
00547                                                                                          internal_format, primary_format, LLHost());
00548 
00549         return imagep;
00550 }
00551 
00552 LLViewerImage* LLViewerImageList::getImage(const LLUUID &image_id,
00553                                                                                    BOOL usemipmaps,
00554                                                                                    BOOL level_immediate)
00555 {
00556         return getImageFromUUID(image_id, usemipmaps, level_immediate, 0, 0, LLHost());
00557 }
00558 
00559 LLViewerImage* LLViewerImageList::getImageFromUUID(const LLUUID &image_id,
00560                                                                                                    BOOL usemipmaps,
00561                                                                                                    BOOL level_immediate,
00562                                                                                                    LLGLint internal_format,
00563                                                                                                    LLGLenum primary_format,
00564                                                                                                    LLHost request_from_host)
00565 {
00566         
00567         
00568         
00569 
00570         if ((&image_id == NULL) || image_id.isNull())
00571         {
00572                 return (getImage(IMG_DEFAULT, TRUE, TRUE));
00573         }
00574 
00575         LLPointer<LLViewerImage> imagep = hasImage(image_id);
00576 
00577         if (imagep.isNull())
00578         {
00579                 imagep = new LLViewerImage(image_id, usemipmaps);
00580                 
00581                 imagep->setTargetHost(request_from_host);
00582 
00583                 if (internal_format && primary_format)
00584                 {
00585                         imagep->setExplicitFormat(internal_format, primary_format);
00586                 }
00587 
00588                 addImage(imagep);
00589 
00590                 if (level_immediate)
00591                 {
00592                         imagep->dontDiscard();
00593                         imagep->setBoostLevel(LLViewerImage::BOOST_UI);
00594                 }
00595         }
00596         
00597         return imagep;
00598 }
00599 
00600 LLViewerImage *LLViewerImageList::hasImage(const LLUUID &image_id)
00601 {
00602         uuid_map_t::iterator iter = mUUIDMap.find(image_id);
00603         if(iter == mUUIDMap.end())
00604                 return NULL;
00605         return iter->second;
00606 }
00607 
00608 void LLViewerImageList::addImageToList(LLViewerImage *image)
00609 {
00610         llassert(image);
00611         if (image->mInImageList)
00612         {
00613                 llerrs << "LLViewerImageList::addImageToList - Image already in list" << llendl;
00614         }
00615         llverify((mImageList.insert(image)).second == true);
00616         image->mInImageList = TRUE;
00617 }
00618 
00619 void LLViewerImageList::removeImageFromList(LLViewerImage *image)
00620 {
00621         llassert(image);
00622         if (!image->mInImageList)
00623         {
00624                 llerrs << "LLViewerImageList::removeImageFromList - Image not in list" << llendl;
00625         }
00626         llverify(mImageList.erase(image) == 1);
00627         image->mInImageList = FALSE;
00628 }
00629 
00630 void LLViewerImageList::addImage(LLViewerImage *new_image)
00631 {
00632         if (!new_image)
00633         {
00634                 llwarning("No image to add to image list", 0);
00635                 return;
00636         }
00637         LLUUID image_id = new_image->getID();
00638 
00639         LLViewerImage *image = hasImage(image_id);
00640         if (image)
00641         {
00642                 llerrs << "Image with ID " << image_id << " already in list" << llendl;
00643         }
00644         sNumImages++;
00645         
00646         addImageToList(new_image);
00647         mUUIDMap[image_id] = new_image;
00648 }
00649 
00650 
00651 void LLViewerImageList::deleteImage(LLViewerImage *image)
00652 {
00653         if( image)
00654         {
00655                 if (image->hasCallbacks())
00656                 {
00657                         mCallbackList.erase((LLViewerImage*)image);
00658                 }
00659                 llverify(mUUIDMap.erase(image->getID()) == 1);
00660                 sNumImages--;
00661                 removeImageFromList(image);
00662         }
00663 }
00664 
00666 
00667 void LLViewerImageList::updateMovieImage(const LLUUID& uuid, BOOL active)
00668 {
00669         
00670         if (mMovieImageUUID == uuid)
00671         {
00672                 return;
00673         }
00674         
00675         if (!mMovieImageUUID.isNull())
00676         {
00677                 LLViewerImage* oldImage = getImage( mMovieImageUUID );
00678                 if (oldImage)
00679                 {
00680                         oldImage->reinit(mMovieImageHasMips);
00681                         oldImage->mIsMediaTexture = FALSE;
00682                 }
00683                 mMovieImageUUID.setNull();
00684         }
00685         
00686         if (active && !uuid.isNull())
00687         {
00688                 LLViewerImage* viewerImage = getImage( uuid );
00689                 if( viewerImage )
00690                 {
00691                         mMovieImageUUID = uuid;
00692                         
00693                         mMovieImageHasMips = viewerImage->getUseMipMaps();
00694                         viewerImage->reinit(FALSE);
00695                         viewerImage->mIsMediaTexture = TRUE;
00696                 }
00697         }
00698 }
00699 
00701 
00702 void LLViewerImageList::dirtyImage(LLViewerImage *image)
00703 {
00704         mDirtyTextureList.insert(image);
00705 }
00706 
00708 
00709 void LLViewerImageList::updateImages(F32 max_time)
00710 {
00711         sNumImagesStat.addValue(sNumImages);
00712         sNumRawImagesStat.addValue(LLImageRaw::sRawImageCount);
00713         sGLTexMemStat.addValue(LLImageGL::sGlobalTextureMemory/(1024.f*1024.f));
00714         sGLBoundMemStat.addValue(LLImageGL::sBoundTextureMemory/(1024.f*1024.f));
00715         sRawMemStat.addValue(LLImageRaw::sGlobalRawMemory/(1024.f*1024.f));
00716         sFormattedMemStat.addValue(LLImageFormatted::sGlobalFormattedMemory/(1024.f*1024.f));
00717 
00718         updateImagesDecodePriorities();
00719         max_time -= updateImagesFetchTextures(max_time);
00720         max_time = llmax(max_time, 0.001f);
00721         max_time -= updateImagesCreateTextures(max_time);
00722         max_time = llmax(max_time, 0.001f);
00723 
00724         if (!mDirtyTextureList.empty())
00725         {
00726                 LLFastTimer t(LLFastTimer::FTM_IMAGE_MARK_DIRTY);
00727                 gPipeline.dirtyPoolObjectTextures(mDirtyTextureList);
00728                 mDirtyTextureList.clear();
00729         }
00730 
00731         for (image_list_t::iterator iter = mCallbackList.begin();
00732                  iter != mCallbackList.end(); )
00733         {
00734                 LLViewerImage* image = *iter++;
00735                 
00736                 bool res = image->doLoadedCallbacks();
00737                 if (res)
00738                 {
00739                         break; 
00740                 }
00741         }
00742         
00743         updateImagesMediaStreams();
00744         updateImagesUpdateStats();
00745 }
00746 
00747 void LLViewerImageList::updateImagesDecodePriorities()
00748 {
00749         
00750         {
00751                 const size_t max_update_count = 256;
00752                 S32 update_counter = llmin(max_update_count, mUUIDMap.size()/10);
00753                 uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateUUID);
00754                 while(update_counter > 0)
00755                 {
00756                         if (iter == mUUIDMap.end())
00757                         {
00758                                 iter = mUUIDMap.begin();
00759                         }
00760                         mLastUpdateUUID = iter->first;
00761                         LLPointer<LLViewerImage> imagep = iter->second;
00762                         ++iter; 
00763 
00764                         
00765                         
00766                         
00767                         const F32 LAZY_FLUSH_TIMEOUT = 30.f;
00768                         S32 min_refs = 3; 
00769                         if (imagep->hasCallbacks())
00770                         {
00771                                 min_refs++; 
00772                         }
00773                         S32 num_refs = imagep->getNumRefs();
00774                         if (num_refs == min_refs)
00775                         {
00776                                 if (imagep->mLastReferencedTimer.getElapsedTimeF32() > LAZY_FLUSH_TIMEOUT)
00777                                 {
00778                                         
00779                                         deleteImage(imagep);
00780                                         imagep = NULL; 
00781                                         continue;
00782                                 }
00783                         }
00784                         else
00785                         {
00786                                 imagep->mLastReferencedTimer.reset();
00787                         }
00788                         
00789                         imagep->processTextureStats();
00790                         F32 old_priority = imagep->getDecodePriority();
00791                         F32 decode_priority = imagep->calcDecodePriority();
00792                         
00793                         if ((decode_priority < old_priority * .8f || decode_priority > old_priority * 1.25f))
00794                         {
00795                                 removeImageFromList(imagep);
00796                                 imagep->setDecodePriority(decode_priority);
00797                                 addImageToList(imagep);
00798                         }
00799                         update_counter--;
00800                 }
00801         }
00802 }
00803 
00804 
00805 
00806 
00807 
00808 
00809 
00810 
00811 
00812 
00813 
00814 
00815 
00816 
00817 
00818 
00819 
00820 
00821 
00822 
00823 
00824 
00825 
00826 
00827 
00828 
00829 
00830 
00831 F32 LLViewerImageList::updateImagesCreateTextures(F32 max_time)
00832 {
00833         if (gNoRender || gGLManager.mIsDisabled) return 0.0f;
00834         
00835         
00836         
00837         
00838         
00839         LLFastTimer t(LLFastTimer::FTM_IMAGE_CREATE);
00840 
00841         LLTimer create_timer;
00842         image_list_t::iterator enditer = mCreateTextureList.begin();
00843         for (image_list_t::iterator iter = mCreateTextureList.begin();
00844                  iter != mCreateTextureList.end();)
00845         {
00846                 image_list_t::iterator curiter = iter++;
00847                 enditer = iter;
00848                 LLViewerImage *imagep = *curiter;
00849                 imagep->createTexture();
00850                 if (create_timer.getElapsedTimeF32() > max_time)
00851                 {
00852                         break;
00853                 }
00854         }
00855         mCreateTextureList.erase(mCreateTextureList.begin(), enditer);
00856         return create_timer.getElapsedTimeF32();
00857 }
00858 
00859 F32 LLViewerImageList::updateImagesFetchTextures(F32 max_time)
00860 {
00861         LLTimer image_op_timer;
00862         
00863         
00864         
00865         const size_t max_priority_count = 32;
00866         const size_t max_update_count = 256;
00867 
00868         
00869         std::set<LLViewerImage*> entries;
00870         size_t update_counter = llmin(max_priority_count, mImageList.size());
00871         image_priority_list_t::iterator iter1 = mImageList.begin();
00872         while(update_counter > 0)
00873         {
00874                 entries.insert(*iter1);
00875                 ++iter1;
00876                 update_counter--;
00877         }
00878         
00879         
00880         update_counter = llmin(max_update_count, mUUIDMap.size());
00881         uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchUUID);
00882         while(update_counter > 0)
00883         {
00884                 if (iter2 == mUUIDMap.end())
00885                 {
00886                         iter2 = mUUIDMap.begin();
00887                 }
00888                 mLastFetchUUID = iter2->first;
00889                 entries.insert(iter2->second);
00890                 ++iter2;
00891                 update_counter--;
00892         }
00893 
00894         S32 min_count = max_priority_count + max_update_count/4;
00895         for (std::set<LLViewerImage*>::iterator iter3 = entries.begin();
00896                  iter3 != entries.end(); )
00897         {
00898                 LLPointer<LLViewerImage> imagep = *iter3++;
00899 
00900                 imagep->updateFetch();
00901                 if (min_count <= 0 && image_op_timer.getElapsedTimeF32() > max_time)
00902                 {
00903                         break;
00904                 }
00905                 min_count--;
00906         }
00907         return image_op_timer.getElapsedTimeF32();
00908 }
00909 
00910 void LLViewerImageList::updateImagesMediaStreams()
00911 {
00912         if (gNoRender || gGLManager.mIsDisabled) return;
00913         
00914                 
00915                 LLMediaEngine* media_engine = LLMediaEngine::getInstance();
00916                 if (media_engine)
00917                 {
00918                         if ( media_engine->update() )
00919                         {
00920                                 LLUUID media_uuid = media_engine->getImageUUID();
00921                                 updateMovieImage(media_uuid, TRUE);
00922                                 if (!media_uuid.isNull())
00923                                 {
00924                                         LLViewerImage* viewerImage = getImage( media_uuid );
00925                                         if( viewerImage )
00926                                         {
00927                                                 LLMediaBase* renderer = media_engine->getMediaRenderer();
00928                                                 if ((renderer->getTextureWidth() != viewerImage->getWidth()) ||
00929                                                         (renderer->getTextureHeight() != viewerImage->getHeight()) ||
00930                                                         (renderer->getTextureDepth() != viewerImage->getComponents()) ||
00931                                                         (viewerImage->getHasGLTexture() == FALSE))
00932                                                 {
00933                                                         
00934                                                         viewerImage->destroyGLTexture();
00935                                         
00936                                                         
00937                                                         viewerImage->setSize( renderer->getTextureWidth(),
00938                                                                                                   renderer->getTextureHeight(),
00939                                                                                                   renderer->getTextureDepth() );
00940 
00941                                                         LLPointer<LLImageRaw> raw = new LLImageRaw(renderer->getTextureWidth(),
00942                                                                                                                                            renderer->getTextureHeight(),
00943                                                                                                                                            renderer->getTextureDepth());
00944                                                         raw->clear(0x7f,0x7f,0x7f,0xff);
00945                                                         viewerImage->createGLTexture(0, raw);
00946                                                 }
00947 
00948                                                 
00949                                                 viewerImage->setExplicitFormat(renderer->getTextureFormatInternal(), 
00950                                                                                                            renderer->getTextureFormatPrimary(), 
00951                                                                                                            renderer->getTextureFormatType(),
00952                                                                                                            renderer->getTextureFormatSwapBytes());
00953                                                 
00954                                                 viewerImage->setUseMipMaps(FALSE);
00955 
00956                                                 LLImageRaw* rawImage = media_engine->getImageRaw();
00957                                                 if ( rawImage )
00958                                                 {
00959                                                         viewerImage->setSubImage(rawImage, 0, 0,
00960                                                                                                          renderer->getMediaWidth(),
00961                                                                                                          renderer->getMediaHeight());
00962                                                 }
00963                                         }
00964                                         else
00965                                         {
00966                                                 llwarns << "MediaEngine update unable to get viewer image for GL texture" << llendl;
00967                                         }
00968                                 }
00969                         }
00970                         else
00971                         {
00972                                 LLUUID media_uuid = media_engine->getImageUUID();
00973                                 updateMovieImage(media_uuid, FALSE);
00974                         }
00975                 }
00976 }
00977 
00978 void LLViewerImageList::updateImagesUpdateStats()
00979 {
00980         if (mUpdateStats)
00981         {
00982                 for (image_priority_list_t::iterator iter = mImageList.begin();
00983                          iter != mImageList.end(); )
00984                 {
00985                         LLViewerImage* imagep = *iter++;
00986                         imagep->resetTextureStats(mForceResetTextureStats);
00987                 }
00988                 mUpdateStats = FALSE;
00989                 mForceResetTextureStats = FALSE;
00990         }
00991 }
00992 
00993 void LLViewerImageList::decodeAllImages(F32 max_time)
00994 {
00995         LLTimer timer;
00996         if(gNoRender) return;
00997 
00998         
00999         std::vector<LLPointer<LLViewerImage> > image_list;
01000         for (image_priority_list_t::iterator iter = mImageList.begin();
01001                  iter != mImageList.end(); )
01002         {
01003                 LLViewerImage* imagep = *iter++;
01004                 image_list.push_back(imagep);
01005                 imagep->mInImageList = FALSE;
01006         }
01007         mImageList.clear();
01008         for (std::vector<LLPointer<LLViewerImage> >::iterator iter = image_list.begin();
01009                  iter != image_list.end(); ++iter)
01010         {
01011                 LLViewerImage* imagep = *iter;
01012                 imagep->processTextureStats();
01013                 F32 decode_priority = imagep->calcDecodePriority();
01014                 imagep->setDecodePriority(decode_priority);
01015                 mImageList.insert(imagep);
01016                 imagep->mInImageList = TRUE;
01017         }
01018         image_list.clear();
01019         
01020         
01021         for (image_priority_list_t::iterator iter = mImageList.begin();
01022                  iter != mImageList.end(); )
01023         {
01024                 LLViewerImage* imagep = *iter++;
01025                 imagep->updateFetch();
01026         }
01027         
01028         S32 fetch_pending = 0;
01029         while (1)
01030         {
01031                 gTextureCache->update(1); 
01032                 gImageDecodeThread->update(1); 
01033                 fetch_pending = gTextureFetch->update(1); 
01034                 if (fetch_pending == 0 || timer.getElapsedTimeF32() > max_time)
01035                 {
01036                         break;
01037                 }
01038         }
01039         
01040         for (image_priority_list_t::iterator iter = mImageList.begin();
01041                  iter != mImageList.end(); )
01042         {
01043                 LLViewerImage* imagep = *iter++;
01044                 imagep->updateFetch();
01045         }
01046         max_time -= timer.getElapsedTimeF32();
01047         max_time = llmax(max_time, .01f);
01048         F32 create_time = updateImagesCreateTextures(max_time);
01049 
01050         llinfos << "decodeAllImages() took " << timer.getElapsedTimeF32() << " seconds. " 
01051                 << " fetch_pending " << fetch_pending
01052                 << " create_time " << create_time
01053                 << llendl;
01054 }
01055 
01056 
01057 BOOL LLViewerImageList::createUploadFile(const LLString& filename,
01058                                                                                  const LLString& out_filename,
01059                                                                                  const U8 codec)
01060 {
01061         
01062         LLPointer<LLImageRaw> raw_image = new LLImageRaw;
01063 
01064         switch (codec)
01065         {
01066           case IMG_CODEC_BMP:
01067           {
01068                   LLPointer<LLImageBMP> bmp_image = new LLImageBMP;
01069 
01070                   if (!bmp_image->load(filename))
01071                   {
01072                           return FALSE;
01073                   }
01074 
01075                   if (!bmp_image->decode(raw_image))
01076                   {
01077                           return FALSE;
01078                   }
01079           }
01080           break;
01081           case IMG_CODEC_TGA:
01082           {
01083                   LLPointer<LLImageTGA> tga_image = new LLImageTGA;
01084 
01085                   if (!tga_image->load(filename))
01086                   {
01087                           return FALSE;
01088                   }
01089 
01090                   if (!tga_image->decode(raw_image))
01091                   {
01092                           return FALSE;
01093                   }
01094 
01095                   if(   (tga_image->getComponents() != 3) &&
01096                                 (tga_image->getComponents() != 4) )
01097                   {
01098                           tga_image->setLastError( "Image files with less than 3 or more than 4 components are not supported." );
01099                           return FALSE;
01100                   }
01101           }
01102           break;
01103           case IMG_CODEC_JPEG:
01104           {
01105                   LLPointer<LLImageJPEG> jpeg_image = new LLImageJPEG;
01106 
01107                   if (!jpeg_image->load(filename))
01108                   {
01109                           return FALSE;
01110                   }
01111 
01112                   if (!jpeg_image->decode(raw_image))
01113                   {
01114                           return FALSE;
01115                   }
01116           }
01117           break;
01118           case IMG_CODEC_PNG:
01119           {
01120                   LLPointer<LLImagePNG> png_image = new LLImagePNG;
01121 
01122                   if (!png_image->load(filename))
01123                   {
01124                           return FALSE;
01125                   }
01126 
01127                   if (!png_image->decode(raw_image))
01128                   {
01129                           return FALSE;
01130                   }
01131           }
01132           break;
01133           default:
01134                 return FALSE;
01135         }
01136 
01137         LLPointer<LLImageJ2C> compressedImage = convertToUploadFile(raw_image);
01138 
01139         if( !compressedImage->save(out_filename) )
01140         {
01141                 llinfos << "Couldn't create output file " << out_filename << llendl;
01142                 return FALSE;
01143         }
01144 
01145         
01146         LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C;
01147         if( !integrity_test->loadAndValidate( out_filename ) )
01148         {
01149                 llinfos << "Image: " << out_filename << " is corrupt." << llendl;
01150                 return FALSE;
01151         }
01152 
01153         return TRUE;
01154 }
01155 
01156 
01157 LLPointer<LLImageJ2C> LLViewerImageList::convertToUploadFile(LLPointer<LLImageRaw> raw_image)
01158 {
01159         raw_image->biasedScaleToPowerOfTwo(LLViewerImage::MAX_IMAGE_SIZE_DEFAULT);
01160         LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C();
01161         compressedImage->setRate(0.f);
01162         
01163         if (gSavedSettings.getBOOL("LosslessJ2CUpload") &&
01164                 (raw_image->getWidth() <= LL_IMAGE_REZ_LOSSLESS_CUTOFF) &&
01165                 (raw_image->getHeight() <= LL_IMAGE_REZ_LOSSLESS_CUTOFF))
01166                 compressedImage->setReversible(TRUE);
01167         
01168         compressedImage->encode(raw_image);
01169 
01170         return compressedImage;
01171 }
01172 
01173 
01174 S32 LLViewerImageList::getMaxVideoRamSetting(S32 max)
01175 {
01176         const U32 vram_settings[] = { 16, 32, 64, 128, 256, 512 };
01177         const S32 num_vram_settings = sizeof(vram_settings) / sizeof(vram_settings[0]);
01178 
01179         U32 max_vram;
01180         if (gGLManager.mVRAM != 0)
01181         {
01182                 max_vram = (llmax(gGLManager.mVRAM,16)) << 20;
01183         }
01184         else
01185         {
01186                 if (max == -2) 
01187                 {
01188                         max_vram = 128 << 20;
01189                 }
01190                 else
01191                 {
01192                         max_vram = 512 << 20;
01193                 }
01194                 llwarns << "VRAM amount not detected, defaulting to " << max_vram/(double)(1<<20) << " MB" << llendl;
01195         }
01196         U32 system_ram = gSysMemory.getPhysicalMemoryClamped();
01197         
01198         if (max == -2)
01199         {
01200                 max_vram = llmin(max_vram, (U32)(system_ram/2)); 
01201         }
01202         else
01203         {
01204                 max_vram = llmin(max_vram, (U32)((F32)system_ram/1.5f));
01205         }
01206 
01207         S32 idx;
01208         for (idx=0; idx < num_vram_settings; idx++)
01209         {
01210                 if (idx == max)
01211                         break;
01212                 if ((vram_settings[idx] << 20) > max_vram)
01213                 {
01214                         idx--;
01215                         break;
01216                 }
01217         }
01218 
01219         if( idx == num_vram_settings )
01220         {
01221                 idx = num_vram_settings - 1;
01222         }
01223 
01224         return idx;
01225 }
01226 
01227 const S32 VIDEO_CARD_MEM_SIZES[6] = { 0x1000000, 
01228                                                                           0x2000000, 
01229                                                                           0x4000000, 
01230                                                                           0x8000000, 
01231                                                                           0x10000000, 
01232                                                                           0x20000000, 
01233                                                                         };
01234 
01235 const S32 VIDEO_CARD_FRAMEBUFFER_MEM = 0xC00000; 
01236 
01237 void LLViewerImageList::updateMaxResidentTexMem(S32 max, U32 fudge)
01238 {
01239         
01240         S32 cur_setting = gSavedSettings.getS32("GraphicsCardMemorySetting");
01241         S32 max_setting = getMaxVideoRamSetting(max);
01242         if (max >= 0 && max != cur_setting)
01243         {
01244                 S32 default_setting = getMaxVideoRamSetting(-2); 
01245                 if (cur_setting >= 0 || max_setting != default_setting)
01246                 {
01247                         gSavedSettings.setS32("GraphicsCardMemorySetting", max_setting);
01248                         return; 
01249                 }
01250                 cur_setting = max_setting; 
01251         }
01252         else if (cur_setting < 0)
01253         {
01254                 S32 default_setting = getMaxVideoRamSetting(-2); 
01255                 cur_setting = default_setting;
01256         }
01257         mVideoMemorySetting = cur_setting;
01258         
01259         
01260 
01261         S32 vram_amt = VIDEO_CARD_MEM_SIZES[cur_setting];
01262         S32 fb_mem = llmax(VIDEO_CARD_FRAMEBUFFER_MEM, vram_amt/4);
01263         mMaxResidentTexMem = vram_amt - fb_mem - fudge;
01264         
01265 
01266 
01267 }
01268 
01270 
01271 
01272 void LLViewerImageList::receiveImageHeader(LLMessageSystem *msg, void **user_data)
01273 {
01274         LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES);
01275 
01276         
01277         
01278 
01279         LLUUID id;
01280 
01281         char ip_string[256];
01282         u32_to_ip_string(msg->getSenderIP(),ip_string);
01283 
01284         if (msg->getReceiveCompressedSize())
01285         {
01286                 gImageList.sTextureBits += msg->getReceiveCompressedSize() * 8;
01287         }
01288         else
01289         {
01290                 gImageList.sTextureBits += msg->getReceiveSize() * 8;
01291         }
01292         gImageList.sTexturePackets++;
01293 
01294         U8 codec;
01295         U16 packets;
01296         U32 totalbytes;
01297         msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id);
01298         msg->getU8Fast(_PREHASH_ImageID, _PREHASH_Codec, codec);
01299         msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packets, packets);
01300         msg->getU32Fast(_PREHASH_ImageID, _PREHASH_Size, totalbytes);
01301 
01302         S32 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data); 
01303         if (!data_size)
01304         {
01305                 return;
01306         }
01307         if (data_size < 0)
01308         {
01309                 
01310                 
01311                 llerrs << "image header chunk size was negative: "
01312                        << data_size << llendl;
01313                 return;
01314         }
01315 
01316         
01317         U8 *data = new U8[data_size];
01318         msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size);
01319 
01320         LLViewerImage *image = gImageList.getImage(id);
01321         if (!image)
01322         {
01323                 delete [] data;
01324                 return;
01325         }
01326         image->mLastPacketTimer.reset();
01327         bool res = gTextureFetch->receiveImageHeader(msg->getSender(), id, codec, packets, totalbytes, data_size, data);
01328         if (!res)
01329         {
01330                 delete[] data;
01331         }
01332 }
01333 
01334 
01335 void LLViewerImageList::receiveImagePacket(LLMessageSystem *msg, void **user_data)
01336 {
01337         LLMemType mt1(LLMemType::MTYPE_APPFMTIMAGE);
01338         LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES);
01339         
01340         
01341         
01342 
01343         LLUUID id;
01344         U16 packet_num;
01345 
01346         char ip_string[256];
01347         u32_to_ip_string(msg->getSenderIP(),ip_string);
01348 
01349         if (msg->getReceiveCompressedSize())
01350         {
01351                 gImageList.sTextureBits += msg->getReceiveCompressedSize() * 8;
01352         }
01353         else
01354         {
01355                 gImageList.sTextureBits += msg->getReceiveSize() * 8;
01356         }
01357         gImageList.sTexturePackets++;
01358 
01359         
01360         msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id);
01361         msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packet, packet_num);
01362         S32 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data); 
01363 
01364         if (!data_size)
01365         {
01366                 return;
01367         }
01368         if (data_size < 0)
01369         {
01370                 
01371                 
01372                 llerrs << "image data chunk size was negative: "
01373                        << data_size << llendl;
01374                 return;
01375         }
01376         if (data_size > MTUBYTES)
01377         {
01378                 llerrs << "image data chunk too large: " << data_size << " bytes" << llendl;
01379                 return;
01380         }
01381         U8 *data = new U8[data_size];
01382         msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size);
01383 
01384         LLViewerImage *image = gImageList.getImage(id);
01385         if (!image)
01386         {
01387                 delete [] data;
01388                 return;
01389         }
01390         image->mLastPacketTimer.reset();
01391         bool res = gTextureFetch->receiveImagePacket(msg->getSender(), id, packet_num, data_size, data);
01392         if (!res)
01393         {
01394                 delete[] data;
01395         }
01396 }
01397 
01398 
01399 
01400 
01401 void LLViewerImageList::processImageNotInDatabase(LLMessageSystem *msg,void **user_data)
01402 {
01403         LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES);
01404         LLUUID image_id;
01405         msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, image_id);
01406 
01407         LLViewerImage* image = gImageList.hasImage( image_id );
01408         if( image )
01409         {
01410                 image->setIsMissingAsset();
01411         }
01412 }
01413 
01415 
01416 
01417 const U32 SIXTEEN_MEG = 0x1000000;
01418 S32 LLViewerImageList::calcMaxTextureRAM()
01419 {
01420         
01421         LLMemoryInfo memory_info;
01422         U32 available_memory = memory_info.getPhysicalMemoryClamped();
01423         
01424         clamp_rescale((F32)available_memory,
01425                                  (F32)(SIXTEEN_MEG * 16),
01426                                  (F32)U32_MAX,
01427                                  (F32)(SIXTEEN_MEG * 4),
01428                                  (F32)(U32_MAX >> 1));
01429         return available_memory;
01430 }
01431