LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRegion *regionp, const LLUUID &uuid, const U32 local_id, const LLHost &sender) { LLMemType mt(LLMemType::MTYPE_OBJECT); LLFastTimer t(LLFastTimer::FTM_CREATE_OBJECT); LLUUID fullid; if (uuid == LLUUID::null) { fullid.generate(); } else { fullid = uuid; } LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp); if (!objectp) { // llwarns << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << " id:" << fullid << llendl; return NULL; } mUUIDObjectMap[fullid] = objectp; setUUIDAndLocal(fullid, local_id, gMessageSystem->getSenderIP(), gMessageSystem->getSenderPort()); mObjects.put(objectp); updateActive(objectp); return objectp; }
void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, void **user_data, const EObjectUpdateType update_type, bool cached, bool compressed) { LLFastTimer t(LLFastTimer::FTM_PROCESS_OBJECTS); LLVector3d camera_global = gAgent.getCameraPositionGlobal(); LLViewerObject *objectp; S32 num_objects; U32 local_id; LLPCode pcode = 0; LLUUID fullid; S32 i; // figure out which simulator these are from and get it's index // Coordinates in simulators are region-local // Until we get region-locality working on viewer we // have to transform to absolute coordinates. num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData); if (!cached && !compressed && update_type != OUT_FULL) { gTerseObjectUpdates += num_objects; S32 size; if (mesgsys->getReceiveCompressedSize()) { size = mesgsys->getReceiveCompressedSize(); } else { size = mesgsys->getReceiveSize(); } // llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl; } else { S32 size; if (mesgsys->getReceiveCompressedSize()) { size = mesgsys->getReceiveCompressedSize(); } else { size = mesgsys->getReceiveSize(); } // llinfos << "Received " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl; gFullObjectUpdates += num_objects; } U64 region_handle; mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); LLViewerRegion *regionp = gWorldPointer->getRegionFromHandle(region_handle); if (!regionp) { llwarns << "Object update from unknown region!" << llendl; return; } U8 compressed_dpbuffer[2048]; LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048); LLDataPacker *cached_dpp = NULL; for (i = 0; i < num_objects; i++) { LLTimer update_timer; BOOL justCreated = FALSE; if (cached) { U32 id; U32 crc; mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i); mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i); // Lookup data packer and add this id to cache miss lists if necessary. cached_dpp = regionp->getDP(id, crc); if (cached_dpp) { cached_dpp->reset(); cached_dpp->unpackUUID(fullid, "ID"); cached_dpp->unpackU32(local_id, "LocalID"); cached_dpp->unpackU8(pcode, "PCode"); } else { continue; // no data packer, skip this object } } else if (compressed) { U8 compbuffer[2048]; S32 uncompressed_length = 2048; S32 compressed_length; compressed_dp.reset(); U32 flags = 0; if (update_type != OUT_TERSE_IMPROVED) { mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); } if (flags & FLAGS_ZLIB_COMPRESSED) { compressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data); mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compbuffer, 0, i); uncompressed_length = 2048; uncompress(compressed_dpbuffer, (unsigned long *)&uncompressed_length, compbuffer, compressed_length); compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length); } else { uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data); mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i); compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length); } if (update_type != OUT_TERSE_IMPROVED) { compressed_dp.unpackUUID(fullid, "ID"); compressed_dp.unpackU32(local_id, "LocalID"); compressed_dp.unpackU8(pcode, "PCode"); } else { compressed_dp.unpackU32(local_id, "LocalID"); getUUIDFromLocal(fullid, local_id, gMessageSystem->getSenderIP(), gMessageSystem->getSenderPort()); if (fullid.isNull()) { //llwarns << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << llendl; mNumUnknownUpdates++; } } } else if (update_type != OUT_FULL) { mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); getUUIDFromLocal(fullid, local_id, gMessageSystem->getSenderIP(), gMessageSystem->getSenderPort()); if (fullid.isNull()) { //llwarns << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << llendl; mNumUnknownUpdates++; } } else { mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i); mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); // llinfos << "Full Update, obj " << local_id << ", global ID" << fullid << "from " << mesgsys->getSender() << llendl; } objectp = findObject(fullid); // This looks like it will break if the local_id of the object doesn't change // upon boundary crossing, but we check for region id matching later... if (objectp && (objectp->mLocalID != local_id)) { removeFromLocalIDTable(*objectp); setUUIDAndLocal(fullid, local_id, gMessageSystem->getSenderIP(), gMessageSystem->getSenderPort()); } if (!objectp) { if (compressed) { if (update_type == OUT_TERSE_IMPROVED) { // llinfos << "terse update for an unknown object:" << fullid << llendl; continue; } } else if (cached) { } else { if (update_type != OUT_FULL) { // llinfos << "terse update for an unknown object:" << fullid << llendl; continue; } mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_PCode, pcode, i); } #ifdef IGNORE_DEAD if (mDeadObjects.find(fullid) != mDeadObjects.end()) { mNumDeadObjectUpdates++; //llinfos << "update for a dead object:" << fullid << llendl; continue; } #endif objectp = createObject(pcode, regionp, fullid, local_id, gMessageSystem->getSender()); if (!objectp) { continue; } justCreated = TRUE; mNumNewObjects++; } else { if (objectp->getRegion() != regionp) { // Object has changed region! Update lookup tables, set region pointer. removeFromLocalIDTable(*objectp); setUUIDAndLocal(fullid, local_id, gMessageSystem->getSenderIP(), gMessageSystem->getSenderPort()); objectp->setRegion(regionp); } objectp->updateRegion(regionp); // for LLVOAvatar } if (objectp->isDead()) { llwarns << "Dead object " << objectp->mID << " in UUID map 1!" << llendl; } if (compressed) { if (update_type != OUT_TERSE_IMPROVED) { objectp->mLocalID = local_id; } processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated); if (update_type != OUT_TERSE_IMPROVED) { objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp); } } else if (cached) { objectp->mLocalID = local_id; processUpdateCore(objectp, user_data, i, update_type, cached_dpp, justCreated); } else { if (update_type == OUT_FULL) { objectp->mLocalID = local_id; } processUpdateCore(objectp, user_data, i, update_type, NULL, justCreated); } } LLVOAvatar::cullAvatarsByPixelArea(); }
void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, void **user_data, const EObjectUpdateType update_type, bool cached, bool compressed) { LLMemType mt(LLMemType::MTYPE_OBJECT_PROCESS_UPDATE); LLFastTimer t(FTM_PROCESS_OBJECTS); LLVector3d camera_global = gAgentCamera.getCameraPositionGlobal(); LLViewerObject *objectp; S32 num_objects; U32 local_id; LLPCode pcode = 0; LLUUID fullid; S32 i; // figure out which simulator these are from and get it's index // Coordinates in simulators are region-local // Until we get region-locality working on viewer we // have to transform to absolute coordinates. num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData); // I don't think this case is ever hit. TODO* Test this. if (!cached && !compressed && update_type != OUT_FULL) { //llinfos << "TEST: !cached && !compressed && update_type != OUT_FULL" << llendl; gTerseObjectUpdates += num_objects; S32 size; if (mesgsys->getReceiveCompressedSize()) { size = mesgsys->getReceiveCompressedSize(); } else { size = mesgsys->getReceiveSize(); } //llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl; } else { S32 size; if (mesgsys->getReceiveCompressedSize()) { size = mesgsys->getReceiveCompressedSize(); } else { size = mesgsys->getReceiveSize(); } // llinfos << "Received " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl; gFullObjectUpdates += num_objects; } U64 region_handle; mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle); if (!regionp) { llwarns << "Object update from unknown region! " << region_handle << llendl; return; } U8 compressed_dpbuffer[2048]; LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048); LLDataPacker *cached_dpp = NULL; #if LL_RECORD_VIEWER_STATS LLViewerStatsRecorder::instance()->beginObjectUpdateEvents(regionp); #endif for (i = 0; i < num_objects; i++) { // timer is unused? LLTimer update_timer; BOOL justCreated = FALSE; if (cached) { U32 id; U32 crc; mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i); mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i); // Lookup data packer and add this id to cache miss lists if necessary. U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE; cached_dpp = regionp->getDP(id, crc, cache_miss_type); if (cached_dpp) { // Cache Hit. cached_dpp->reset(); cached_dpp->unpackUUID(fullid, "ID"); cached_dpp->unpackU32(local_id, "LocalID"); cached_dpp->unpackU8(pcode, "PCode"); } else { // Cache Miss. #if LL_RECORD_VIEWER_STATS LLViewerStatsRecorder::instance()->recordCacheMissEvent(id, update_type, cache_miss_type); #endif continue; // no data packer, skip this object } } else if (compressed) { U8 compbuffer[2048]; S32 uncompressed_length = 2048; S32 compressed_length; compressed_dp.reset(); U32 flags = 0; if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? { mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); } // I don't think we ever use this flag from the server. DK 2010/12/09 if (flags & FLAGS_ZLIB_COMPRESSED) { //llinfos << "TEST: flags & FLAGS_ZLIB_COMPRESSED" << llendl; compressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data); mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compbuffer, 0, i); uncompressed_length = 2048; uncompress(compressed_dpbuffer, (unsigned long *)&uncompressed_length, compbuffer, compressed_length); compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length); } else { uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data); mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i); compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length); } if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? { compressed_dp.unpackUUID(fullid, "ID"); compressed_dp.unpackU32(local_id, "LocalID"); compressed_dp.unpackU8(pcode, "PCode"); } else { compressed_dp.unpackU32(local_id, "LocalID"); getUUIDFromLocal(fullid, local_id, gMessageSystem->getSenderIP(), gMessageSystem->getSenderPort()); if (fullid.isNull()) { // llwarns << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << ":" << gMessageSystem->getSenderPort() << llendl; mNumUnknownUpdates++; } } } else if (update_type != OUT_FULL) // !compressed, !OUT_FULL ==> OUT_FULL_CACHED only? { mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); getUUIDFromLocal(fullid, local_id, gMessageSystem->getSenderIP(), gMessageSystem->getSenderPort()); if (fullid.isNull()) { // llwarns << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << llendl; mNumUnknownUpdates++; } } else // OUT_FULL only? { mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i); mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); // llinfos << "Full Update, obj " << local_id << ", global ID" << fullid << "from " << mesgsys->getSender() << llendl; } objectp = findObject(fullid); // This looks like it will break if the local_id of the object doesn't change // upon boundary crossing, but we check for region id matching later... // Reset object local id and region pointer if things have changed if (objectp && ((objectp->mLocalID != local_id) || (objectp->getRegion() != regionp))) { //if (objectp->getRegion()) //{ // llinfos << "Local ID change: Removing object from table, local ID " << objectp->mLocalID // << ", id from message " << local_id << ", from " // << LLHost(objectp->getRegion()->getHost().getAddress(), objectp->getRegion()->getHost().getPort()) // << ", full id " << fullid // << ", objects id " << objectp->getID() // << ", regionp " << (U32) regionp << ", object region " << (U32) objectp->getRegion() // << llendl; //} removeFromLocalIDTable(objectp); setUUIDAndLocal(fullid, local_id, gMessageSystem->getSenderIP(), gMessageSystem->getSenderPort()); if (objectp->mLocalID != local_id) { // Update local ID in object with the one sent from the region objectp->mLocalID = local_id; } if (objectp->getRegion() != regionp) { // Object changed region, so update it objectp->updateRegion(regionp); // for LLVOAvatar } } if (!objectp) { if (compressed) { if (update_type == OUT_TERSE_IMPROVED) { // llinfos << "terse update for an unknown object (compressed):" << fullid << llendl; #if LL_RECORD_VIEWER_STATS LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type); #endif continue; } } else if (cached) // Cache hit only? { } else { if (update_type != OUT_FULL) { //llinfos << "terse update for an unknown object:" << fullid << llendl; #if LL_RECORD_VIEWER_STATS LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type); #endif continue; } mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_PCode, pcode, i); } #ifdef IGNORE_DEAD if (mDeadObjects.find(fullid) != mDeadObjects.end()) { mNumDeadObjectUpdates++; //llinfos << "update for a dead object:" << fullid << llendl; #if LL_RECORD_VIEWER_STATS LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type); #endif continue; } #endif objectp = createObject(pcode, regionp, fullid, local_id, gMessageSystem->getSender()); if (!objectp) { llinfos << "createObject failure for object: " << fullid << llendl; #if LL_RECORD_VIEWER_STATS LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type); #endif continue; } justCreated = TRUE; mNumNewObjects++; } // Gah, why bother spamming the log with messages we can't do // anything about?! -- TS #if 0 if (objectp->isDead()) { llwarns << "Dead object " << objectp->mID << " in UUID map 1!" << llendl; } #endif bool bCached = false; if (compressed) { if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? { objectp->mLocalID = local_id; } processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated); if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? { bCached = true; #if LL_RECORD_VIEWER_STATS LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp); LLViewerStatsRecorder::instance()->recordCacheFullUpdate(local_id, update_type, result, objectp); #else objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp); #endif } } else if (cached) // Cache hit only? { objectp->mLocalID = local_id; processUpdateCore(objectp, user_data, i, update_type, cached_dpp, justCreated); } else { if (update_type == OUT_FULL) { objectp->mLocalID = local_id; } processUpdateCore(objectp, user_data, i, update_type, NULL, justCreated); } #if LL_RECORD_VIEWER_STATS LLViewerStatsRecorder::instance()->recordObjectUpdateEvent(local_id, update_type, objectp); #endif objectp->setLastUpdateType(update_type); objectp->setLastUpdateCached(bCached); } #if LL_RECORD_VIEWER_STATS LLViewerStatsRecorder::instance()->endObjectUpdateEvents(); #endif LLVOAvatar::cullAvatarsByPixelArea(); }