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