llviewerimagelist.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include <sys/stat.h>
00035 
00036 #include "llviewerimagelist.h"
00037 #include "imageids.h"
00038 #include "llgl.h" // fot gathering stats from GL
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;  // Always update the highest N images each frame
00072 const S32 IMAGES_MAX_PACKET_UPDATES = 1; // Only send N packets of IMAGES_PER_REQUEST in a frame
00073 const F32 RESEND_IMAGE_REQUEST_TIME = 15.f; // seconds
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                 // Don't initialize GL stuff if we're not rendering.
00106                 return;
00107         }
00108 
00109         mUpdateStats = TRUE;
00110 
00111         // Update how much texture RAM we're allowed to use.
00112         updateMaxResidentTexMem();
00113 
00114         mMovieImageHasMips = FALSE;
00115 
00116         doPreloadImages();
00117 }
00118 
00119 
00120 void LLViewerImageList::doPreloadImages()
00121 {
00122         llinfos << "Preloading images..." << llendl;
00123 
00124         // Set the "missing asset" image
00125         LLViewerImage::sMissingAssetImagep = preloadImage("missing_asset.tga" , LLUUID::null, TRUE);
00126 
00127         // Set the "white" image
00128         LLViewerImage::sWhiteImagep = preloadImage("white.tga", LLUUID::null, TRUE);
00129 
00130         // Speeds up startup by 4-5 seconds. JC
00131         if (!gPreloadImages) return;
00132 
00133         // Images listed here are immediately decoded, before the login screen.
00134         // Since this slows down perceived viewer startup time, only include
00135         // images here for buttons/checkboxes/etc. that are immediately visible.
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);                          // <<<<<<< --- needed?
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); // decode preloaded images
00177         
00178         // These images are queued for decode during the login sequence, when
00179         // we have a progress bar.
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);     // particle systems
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                 // cache was purged, no point
00333                 return;
00334         }
00335         
00336         // Pre-fetch textures from last logout
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         // Write out list of currently loaded textures for precaching on startup
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; // avoid UI, baked, and other special images
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         // Clean up "loaded" callbacks.
00414         //
00415         mCallbackList.clear();
00416         mIRCallbackData.clear();
00417         
00418         // Clean up preloaded images
00419         mPreloadedImages.clear();
00420         
00421         // Flush all of the references
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 /* Vertical tab container button image IDs
00458 Seem to not decode when running app in debug.
00459 
00460 const LLUUID BAD_IMG_ONE("1097dcb3-aef9-8152-f471-431d840ea89e");
00461 const LLUUID BAD_IMG_TWO("bea77041-5835-1661-f298-47e2d32b7a70");
00462 */
00463 
00464 LLImageGL* LLViewerImageList::getUIImageByID(const LLUUID& image_id, BOOL clamped)
00465 {
00466         LLViewerImage* imagep = getImage(image_id, MIPMAP_FALSE, TRUE);
00467         // force a high resolution decode for all UI images (pulled this from LLTextEditor)
00468         // this might not make any difference
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                 // Never mind that this ignores image_set_id;
00507                 // getImage() will handle that later.
00508                 return getImage(IMG_DEFAULT, TRUE, TRUE);
00509         }
00510         
00511         // Try to load an image from the skins directory.
00512         // Fall back to loading from the VFS if not found.
00513 
00514         // First verify that the image exists in gViewerArt
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                         // We *know* that missing_asset.tga exists,
00522                         // but for paranoia's sake and to avoid infinite recursion, check anyway
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         // Now that we have verified that filename exists, load it and assign it to
00539         // the filename's UUID, or image_set_id if non null.
00540         if (image_set_id.notNull())
00541         {
00542                 image_id = image_set_id;
00543         }
00544         
00545         // Load the image
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         // Return the image with ID image_id
00567         // If the image is not found, creates new image and
00568         // enqueues a request for transmission
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                 // Might want to request from host other than where the agent is. JC
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         // IF the media image hasn't changed, do nothing
00670         if (mMovieImageUUID == uuid)
00671         {
00672                 return;
00673         }
00674         // If we have changed media uuid, restore the old one
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         // If the movie is playing, set the new media image
00686         if (active && !uuid.isNull())
00687         {
00688                 LLViewerImage* viewerImage = getImage( uuid );
00689                 if( viewerImage )
00690                 {
00691                         mMovieImageUUID = uuid;
00692                         // Can't use mipmaps for movies because they don't update the full image
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                 // Do stuff to handle callbacks, update priorities, etc.
00736                 bool res = image->doLoadedCallbacks();
00737                 if (res)
00738                 {
00739                         break; // only actually do one callback per frame
00740                 }
00741         }
00742         
00743         updateImagesMediaStreams();
00744         updateImagesUpdateStats();
00745 }
00746 
00747 void LLViewerImageList::updateImagesDecodePriorities()
00748 {
00749         // Update the decode priority for N images each frame
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; // safe to incrament now
00763 
00764                         //
00765                         // Flush formatted images using a lazy flush
00766                         //
00767                         const F32 LAZY_FLUSH_TIMEOUT = 30.f;
00768                         S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference
00769                         if (imagep->hasCallbacks())
00770                         {
00771                                 min_refs++; // Add an extra reference if we're on the loaded callback list
00772                         }
00773                         S32 num_refs = imagep->getNumRefs();
00774                         if (num_refs == min_refs)
00775                         {
00776                                 if (imagep->mLastReferencedTimer.getElapsedTimeF32() > LAZY_FLUSH_TIMEOUT)
00777                                 {
00778                                         // Remove the unused image from the image list
00779                                         deleteImage(imagep);
00780                                         imagep = NULL; // should destroy the image
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                         // Ignore < 20% difference
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 static U8 get_image_type(LLViewerImage* imagep, LLHost target_host)
00806 {
00807         // Having a target host implies this is a baked image.  I don't
00808         // believe that boost level has been set at this point. JC
00809         U8 type_from_host = (target_host.isOk() 
00810                                                         ? LLImageBase::TYPE_AVATAR_BAKE 
00811                                                         : LLImageBase::TYPE_NORMAL);
00812         S32 boost_level = imagep->getBoostLevel();
00813         U8 type_from_boost = ( (boost_level == LLViewerImage::BOOST_AVATAR_BAKED 
00814                                                         || boost_level == LLViewerImage::BOOST_AVATAR_BAKED_SELF)
00815                                                         ? LLImageBase::TYPE_AVATAR_BAKE 
00816                                                         : LLImageBase::TYPE_NORMAL);
00817         if (type_from_host == LLImageBase::TYPE_NORMAL
00818                 && type_from_boost == LLImageBase::TYPE_AVATAR_BAKE)
00819         {
00820                 llwarns << "TAT: get_image_type() type_from_host doesn't match type_from_boost"
00821                         << " host " << target_host
00822                         << " boost " << imagep->getBoostLevel()
00823                         << " imageid " << imagep->getID()
00824                         << llendl;
00825                 imagep->dump();
00826         }
00827         return type_from_host;
00828 }
00829 */
00830 
00831 F32 LLViewerImageList::updateImagesCreateTextures(F32 max_time)
00832 {
00833         if (gNoRender || gGLManager.mIsDisabled) return 0.0f;
00834         
00835         //
00836         // Create GL textures for all textures that need them (images which have been
00837         // decoded, but haven't been pushed into GL).
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         // Update the decode priority for N images each frame
00864         // Make a list with 32 high priority entries + 256 cycled entries
00865         const size_t max_priority_count = 32;
00866         const size_t max_update_count = 256;
00867 
00868         // 32 high priority entries
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         // 256 cycled entries
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                 // update media stream if required
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                                                         // destroy existing GL image
00934                                                         viewerImage->destroyGLTexture();
00935                                         
00936                                                         // set new size
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                                                 // Set the explicit format the instance wants
00949                                                 viewerImage->setExplicitFormat(renderer->getTextureFormatInternal(), 
00950                                                                                                            renderer->getTextureFormatPrimary(), 
00951                                                                                                            renderer->getTextureFormatType(),
00952                                                                                                            renderer->getTextureFormatSwapBytes());
00953                                                 // This should be redundant, but just in case:
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         // Update texture stats and priorities
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         // Update fetch (decode)
01021         for (image_priority_list_t::iterator iter = mImageList.begin();
01022                  iter != mImageList.end(); )
01023         {
01024                 LLViewerImage* imagep = *iter++;
01025                 imagep->updateFetch();
01026         }
01027         // Run threads
01028         S32 fetch_pending = 0;
01029         while (1)
01030         {
01031                 gTextureCache->update(1); // unpauses the texture cache thread
01032                 gImageDecodeThread->update(1); // unpauses the image thread
01033                 fetch_pending = gTextureFetch->update(1); // unpauses the texture fetch thread
01034                 if (fetch_pending == 0 || timer.getElapsedTimeF32() > max_time)
01035                 {
01036                         break;
01037                 }
01038         }
01039         // Update fetch again
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         // First, load the image.
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         // test to see if the encode and save worked.
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 // note: modifies the argument raw_image!!!!
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 //static
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) // max recommended setting
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         //llinfos << "*** DETECTED " << system_ram/(double)(1<<20) << " MB of system memory." << llendl; // TomY TESTING DNCI
01198         if (max == -2)
01199         {
01200                 max_vram = llmin(max_vram, (U32)(system_ram/2)); // max recommended setting
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, // 16MB
01228                                                                           0x2000000, // 32MB
01229                                                                           0x4000000, // 64MB
01230                                                                           0x8000000, // 128MB
01231                                                                           0x10000000, // 256MB
01232                                                                           0x20000000, // 512MB
01233                                                                         };
01234 
01235 const S32 VIDEO_CARD_FRAMEBUFFER_MEM = 0xC00000; // 12MB
01236 
01237 void LLViewerImageList::updateMaxResidentTexMem(S32 max, U32 fudge)
01238 {
01239         // Initialize the image pipeline VRAM settings
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); // recommended default
01245                 if (cur_setting >= 0 || max_setting != default_setting)
01246                 {
01247                         gSavedSettings.setS32("GraphicsCardMemorySetting", max_setting);
01248                         return; //listener will reenter this function
01249                 }
01250                 cur_setting = max_setting; // max_setting <= max
01251         }
01252         else if (cur_setting < 0)
01253         {
01254                 S32 default_setting = getMaxVideoRamSetting(-2); // recommended default
01255                 cur_setting = default_setting;
01256         }
01257         mVideoMemorySetting = cur_setting;
01258         // TODO: set available resident texture mem based on use by other subsystems
01259         // currently max(12MB, VRAM/4) assumed...
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 //      llinfos << "Graphics Card memory set to " << (VIDEO_CARD_MEM_SIZES[cur_setting]>>20)
01266 //                      << " MB" << llendl;
01267 }
01268 
01270 
01271 // static
01272 void LLViewerImageList::receiveImageHeader(LLMessageSystem *msg, void **user_data)
01273 {
01274         LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES);
01275 
01276         // Receive image header, copy into image object and decompresses 
01277         // if this is a one-packet image. 
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                 // msg->getSizeFast() is probably trying to tell us there
01310                 // was an error.
01311                 llerrs << "image header chunk size was negative: "
01312                        << data_size << llendl;
01313                 return;
01314         }
01315 
01316         // this buffer gets saved off in the packet list
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 // static
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         // Receives image packet, copy into image object,
01341         // checks if all packets received, decompresses if so. 
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         //llprintline("Start decode, image header...");
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                 // msg->getSizeFast() is probably trying to tell us there
01371                 // was an error.
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 // We've been that the asset server does not contain the requested image id.
01400 // static
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 //static
01417 const U32 SIXTEEN_MEG = 0x1000000;
01418 S32 LLViewerImageList::calcMaxTextureRAM()
01419 {
01420         // Decide the maximum amount of RAM we should allow the user to allocate to texture cache
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 

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