From c405cd379a736722740ac241d36bcffb88c236c2 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 30 Jan 2025 00:50:49 +0200 Subject: #3488 Avoid reading meshes from disk when not nessesary LLMeshHeaderHandler preallocates file with empty data, there is no point reading large empty sections so write presense flags at the start of the file --- indra/newview/llappviewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index c770b7c917..00624ebc6a 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -4145,7 +4145,7 @@ U32 LLAppViewer::getTextureCacheVersion() U32 LLAppViewer::getDiskCacheVersion() { // Viewer disk cache version intorduced in Simple Cache Viewer, change if the cache format changes. - const U32 DISK_CACHE_VERSION = 1; + const U32 DISK_CACHE_VERSION = 2; return DISK_CACHE_VERSION ; } -- cgit v1.3 From b84f3ff6b129cd71955bcb1fc885491b7002f87f Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sun, 10 Nov 2024 12:21:34 +0200 Subject: viewer#2780 Speed up terrain loading on teleport Terrain was arriving and processing too late resulting in issues like "Lower terrain material incorrectly shown momentarily" --- indra/newview/llappviewer.cpp | 14 ++++++++++++++ indra/newview/llviewermessage.cpp | 3 ++- indra/newview/llviewertexturelist.cpp | 14 ++++++++++++-- 3 files changed, 28 insertions(+), 3 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 00624ebc6a..52bea875d9 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -4785,6 +4785,20 @@ void LLAppViewer::idle() if (gTeleportDisplay) { + if (gAgent.getTeleportState() == LLAgent::TELEPORT_ARRIVING) + { + // Teleported, but waiting for things to load, start processing surface data + { + LL_RECORD_BLOCK_TIME(FTM_NETWORK); + gVLManager.unpackData(); + } + { + LL_RECORD_BLOCK_TIME(FTM_REGION_UPDATE); + const F32 max_region_update_time = .001f; // 1ms + LLWorld::getInstance()->updateRegions(max_region_update_time); + } + } + return; } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 1d4828fd33..0c702b24c1 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3147,7 +3147,8 @@ void send_agent_update(bool force_send, bool send_reliable) LL_PROFILE_ZONE_SCOPED; llassert(!gCubeSnapshot); - if (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE) + if (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE + && gAgent.getTeleportState() != LLAgent::TELEPORT_ARRIVING) { // We don't care if they want to send an agent update, they're not allowed // until the target simulator is ready to receive them diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 0b79c2d8e0..868dde05db 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -30,6 +30,7 @@ #include "llviewertexturelist.h" +#include "llagent.h" #include "llgl.h" // fot gathering stats from GL #include "llimagegl.h" #include "llimagebmp.h" @@ -815,10 +816,19 @@ void LLViewerTextureList::updateImages(F32 max_time) clearFetchingRequests(); gPipeline.clearRebuildGroups(); cleared = true; + return; } - return; + // ARRIVING is a delay to let things decode, cache and process, + // so process textures like normal despite gTeleportDisplay + if (gAgent.getTeleportState() != LLAgent::TELEPORT_ARRIVING) + { + return; + } + } + else + { + cleared = false; } - cleared = false; LLAppViewer::getTextureFetch()->setTextureBandwidth((F32)LLTrace::get_frame_recording().getPeriodMeanPerSec(LLStatViewer::TEXTURE_NETWORK_DATA_RECEIVED).value()); -- cgit v1.3 From 6d0b0a77eed584c6bcf77f6cd5fdbdbf89a987d7 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 18 Feb 2025 11:38:52 -0800 Subject: drain UDP socket to avoid dropped packets (#3565) drain UDP socket in idleNetwork() to avoid dropped packets --- indra/llappearance/llavatarappearance.cpp | 1 - indra/llmessage/llpacketbuffer.cpp | 26 +- indra/llmessage/llpacketbuffer.h | 12 +- indra/llmessage/llpacketring.cpp | 444 ++++++++++++++---------------- indra/llmessage/llpacketring.h | 79 +++--- indra/llmessage/message.cpp | 13 +- indra/llmessage/message.h | 3 + indra/llmessage/net.cpp | 10 +- indra/newview/llappviewer.cpp | 61 ++-- indra/newview/llappviewer.h | 1 - indra/newview/llstartup.cpp | 15 - 11 files changed, 310 insertions(+), 355 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 95d55c835f..3d66809ed6 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -799,7 +799,6 @@ void LLAvatarAppearance::buildCharacter() bool status = loadAvatar(); stop_glerror(); -// gPrintMessagesThisFrame = true; LL_DEBUGS() << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << LL_ENDL; if (!status) diff --git a/indra/llmessage/llpacketbuffer.cpp b/indra/llmessage/llpacketbuffer.cpp index dc5c7a73cb..0b04a560be 100644 --- a/indra/llmessage/llpacketbuffer.cpp +++ b/indra/llmessage/llpacketbuffer.cpp @@ -32,8 +32,6 @@ #include "lltimer.h" #include "llhost.h" -/////////////////////////////////////////////////////////// - LLPacketBuffer::LLPacketBuffer(const LLHost &host, const char *datap, const S32 size) : mHost(host) { mSize = 0; @@ -41,7 +39,7 @@ LLPacketBuffer::LLPacketBuffer(const LLHost &host, const char *datap, const S32 if (size > NET_BUFFER_SIZE) { - LL_ERRS() << "Sending packet > " << NET_BUFFER_SIZE << " of size " << size << LL_ENDL; + LL_ERRS() << "Constructing packet with size=" << size << " > " << NET_BUFFER_SIZE << LL_ENDL; } else { @@ -51,7 +49,6 @@ LLPacketBuffer::LLPacketBuffer(const LLHost &host, const char *datap, const S32 mSize = size; } } - } LLPacketBuffer::LLPacketBuffer (S32 hSocket) @@ -59,18 +56,29 @@ LLPacketBuffer::LLPacketBuffer (S32 hSocket) init(hSocket); } -/////////////////////////////////////////////////////////// - LLPacketBuffer::~LLPacketBuffer () { } -/////////////////////////////////////////////////////////// - -void LLPacketBuffer::init (S32 hSocket) +void LLPacketBuffer::init(S32 hSocket) { mSize = receive_packet(hSocket, mData); mHost = ::get_sender(); mReceivingIF = ::get_receiving_interface(); } +void LLPacketBuffer::init(const char* buffer, S32 data_size, const LLHost& host) +{ + if (data_size > NET_BUFFER_SIZE) + { + LL_ERRS() << "Initializing packet with size=" << data_size << " > " << NET_BUFFER_SIZE << LL_ENDL; + } + else + { + memcpy(mData, buffer, data_size); + mSize = data_size; + mHost = host; + mReceivingIF = ::get_receiving_interface(); + } +} + diff --git a/indra/llmessage/llpacketbuffer.h b/indra/llmessage/llpacketbuffer.h index a2d2973fb0..ac4012d330 100644 --- a/indra/llmessage/llpacketbuffer.h +++ b/indra/llmessage/llpacketbuffer.h @@ -35,20 +35,22 @@ class LLPacketBuffer { public: LLPacketBuffer(const LLHost &host, const char *datap, const S32 size); - LLPacketBuffer(S32 hSocket); // receive a packet + LLPacketBuffer(S32 hSocket); // receive a packet ~LLPacketBuffer(); S32 getSize() const { return mSize; } const char *getData() const { return mData; } LLHost getHost() const { return mHost; } LLHost getReceivingInterface() const { return mReceivingIF; } + void init(S32 hSocket); + void init(const char* buffer, S32 data_size, const LLHost& host); protected: - char mData[NET_BUFFER_SIZE]; // packet data /* Flawfinder : ignore */ - S32 mSize; // size of buffer in bytes - LLHost mHost; // source/dest IP and port - LLHost mReceivingIF; // source/dest IP and port + char mData[NET_BUFFER_SIZE]; // packet data /* Flawfinder : ignore */ + S32 mSize; // size of buffer in bytes + LLHost mHost; // source/dest IP and port + LLHost mReceivingIF; // source/dest IP and port }; #endif diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp index be838770a8..ae5a2168db 100644 --- a/indra/llmessage/llpacketring.cpp +++ b/indra/llmessage/llpacketring.cpp @@ -1,6 +1,6 @@ /** * @file llpacketring.cpp - * @brief implementation of LLPacketRing class for a packet. + * @brief implementation of LLPacketRing class. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code @@ -43,329 +43,301 @@ #include "message.h" #include "u64.h" -/////////////////////////////////////////////////////////// -LLPacketRing::LLPacketRing () : - mUseInThrottle(false), - mUseOutThrottle(false), - mInThrottle(256000.f), - mOutThrottle(64000.f), - mActualBitsIn(0), - mActualBitsOut(0), - mMaxBufferLength(64000), - mInBufferLength(0), - mOutBufferLength(0), - mDropPercentage(0.0f), - mPacketsToDrop(0x0) +constexpr S16 MAX_BUFFER_RING_SIZE = 1024; +constexpr S16 DEFAULT_BUFFER_RING_SIZE = 256; + +LLPacketRing::LLPacketRing () + : mPacketRing(DEFAULT_BUFFER_RING_SIZE, nullptr) { + LLHost invalid_host; + for (size_t i = 0; i < mPacketRing.size(); ++i) + { + mPacketRing[i] = new LLPacketBuffer(invalid_host, nullptr, 0); + } } -/////////////////////////////////////////////////////////// LLPacketRing::~LLPacketRing () { - cleanup(); + for (auto packet : mPacketRing) + { + delete packet; + } + mPacketRing.clear(); + mNumBufferedPackets = 0; + mNumBufferedBytes = 0; + mHeadIndex = 0; } -/////////////////////////////////////////////////////////// -void LLPacketRing::cleanup () +S32 LLPacketRing::receivePacket (S32 socket, char *datap) { - LLPacketBuffer *packetp; + bool drop = computeDrop(); + return (mNumBufferedPackets > 0) ? + receiveOrDropBufferedPacket(datap, drop) : + receiveOrDropPacket(socket, datap, drop); +} - while (!mReceiveQueue.empty()) +bool send_packet_helper(int socket, const char * datap, S32 data_size, LLHost host) +{ + if (!LLProxy::isSOCKSProxyEnabled()) { - packetp = mReceiveQueue.front(); - delete packetp; - mReceiveQueue.pop(); + return send_packet(socket, datap, data_size, host.getAddress(), host.getPort()); } - while (!mSendQueue.empty()) - { - packetp = mSendQueue.front(); - delete packetp; - mSendQueue.pop(); - } -} + char headered_send_buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; -/////////////////////////////////////////////////////////// -void LLPacketRing::dropPackets (U32 num_to_drop) -{ - mPacketsToDrop += num_to_drop; -} + proxywrap_t *socks_header = static_cast(static_cast(&headered_send_buffer)); + socks_header->rsv = 0; + socks_header->addr = host.getAddress(); + socks_header->port = htons(host.getPort()); + socks_header->atype = ADDRESS_IPV4; + socks_header->frag = 0; -/////////////////////////////////////////////////////////// -void LLPacketRing::setDropPercentage (F32 percent_to_drop) -{ - mDropPercentage = percent_to_drop; -} + memcpy(headered_send_buffer + SOCKS_HEADER_SIZE, datap, data_size); -void LLPacketRing::setUseInThrottle(const bool use_throttle) -{ - mUseInThrottle = use_throttle; + return send_packet( socket, + headered_send_buffer, + data_size + SOCKS_HEADER_SIZE, + LLProxy::getInstance()->getUDPProxy().getAddress(), + LLProxy::getInstance()->getUDPProxy().getPort()); } -void LLPacketRing::setUseOutThrottle(const bool use_throttle) +bool LLPacketRing::sendPacket(int socket, const char * datap, S32 data_size, LLHost host) { - mUseOutThrottle = use_throttle; + mActualBytesOut += data_size; + return send_packet_helper(socket, datap, data_size, host); } -void LLPacketRing::setInBandwidth(const F32 bps) +void LLPacketRing::dropPackets (U32 num_to_drop) { - mInThrottle.setRate(bps); + mPacketsToDrop += num_to_drop; } -void LLPacketRing::setOutBandwidth(const F32 bps) +void LLPacketRing::setDropPercentage (F32 percent_to_drop) { - mOutThrottle.setRate(bps); + mDropPercentage = percent_to_drop; } -/////////////////////////////////////////////////////////// -S32 LLPacketRing::receiveFromRing (S32 socket, char *datap) -{ - if (mInThrottle.checkOverflow(0)) - { - // We don't have enough bandwidth, don't give them a packet. - return 0; - } - - LLPacketBuffer *packetp = NULL; - if (mReceiveQueue.empty()) +bool LLPacketRing::computeDrop() +{ + bool drop= (mDropPercentage > 0.0f && (ll_frand(100.f) < mDropPercentage)); + if (drop) { - // No packets on the queue, don't give them any. - return 0; + ++mPacketsToDrop; } - - S32 packet_size = 0; - packetp = mReceiveQueue.front(); - mReceiveQueue.pop(); - packet_size = packetp->getSize(); - if (packetp->getData() != NULL) + if (mPacketsToDrop > 0) { - memcpy(datap, packetp->getData(), packet_size); /*Flawfinder: ignore*/ + --mPacketsToDrop; + drop = true; } - // need to set sender IP/port!! - mLastSender = packetp->getHost(); - mLastReceivingIF = packetp->getReceivingInterface(); - delete packetp; - - this->mInBufferLength -= packet_size; - - // Adjust the throttle - mInThrottle.throttleOverflow(packet_size * 8.f); - return packet_size; + return drop; } -/////////////////////////////////////////////////////////// -S32 LLPacketRing::receivePacket (S32 socket, char *datap) +S32 LLPacketRing::receiveOrDropPacket(S32 socket, char *datap, bool drop) { S32 packet_size = 0; - // If using the throttle, simulate a limited size input buffer. - if (mUseInThrottle) + // pull straight from socket + if (LLProxy::isSOCKSProxyEnabled()) { - bool done = false; - - // push any current net packet (if any) onto delay ring - while (!done) + char buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; /* Flawfinder ignore */ + packet_size = receive_packet(socket, buffer); + if (packet_size > 0) { - LLPacketBuffer *packetp; - packetp = new LLPacketBuffer(socket); - - if (packetp->getSize()) - { - mActualBitsIn += packetp->getSize() * 8; - - // Fake packet loss - if (mDropPercentage && (ll_frand(100.f) < mDropPercentage)) - { - mPacketsToDrop++; - } - - if (mPacketsToDrop) - { - delete packetp; - packetp = NULL; - packet_size = 0; - mPacketsToDrop--; - } - } + mActualBytesIn += packet_size; + } - // If we faked packet loss, then we don't have a packet - // to use for buffer overflow testing - if (packetp) + if (packet_size > SOCKS_HEADER_SIZE) + { + if (drop) { - if (mInBufferLength + packetp->getSize() > mMaxBufferLength) - { - // Toss it. - LL_WARNS() << "Throwing away packet, overflowing buffer" << LL_ENDL; - delete packetp; - packetp = NULL; - } - else if (packetp->getSize()) - { - mReceiveQueue.push(packetp); - mInBufferLength += packetp->getSize(); - } - else - { - delete packetp; - packetp = NULL; - done = true; - } + packet_size = 0; } else - { - // No packetp, keep going? - no packetp == faked packet loss - } - } - - // Now, grab data off of the receive queue according to our - // throttled bandwidth settings. - packet_size = receiveFromRing(socket, datap); - } - else - { - // no delay, pull straight from net - if (LLProxy::isSOCKSProxyEnabled()) - { - U8 buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; - packet_size = receive_packet(socket, static_cast(static_cast(buffer))); - - if (packet_size > SOCKS_HEADER_SIZE) { // *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6) - memcpy(datap, buffer + SOCKS_HEADER_SIZE, packet_size - SOCKS_HEADER_SIZE); + packet_size -= SOCKS_HEADER_SIZE; // The unwrapped packet size + memcpy(datap, buffer + SOCKS_HEADER_SIZE, packet_size); proxywrap_t * header = static_cast(static_cast(buffer)); mLastSender.setAddress(header->addr); mLastSender.setPort(ntohs(header->port)); - - packet_size -= SOCKS_HEADER_SIZE; // The unwrapped packet size - } - else - { - packet_size = 0; + mLastReceivingIF = ::get_receiving_interface(); } } else { - packet_size = receive_packet(socket, datap); - mLastSender = ::get_sender(); + packet_size = 0; } - - mLastReceivingIF = ::get_receiving_interface(); - - if (packet_size) // did we actually get a packet? + } + else + { + packet_size = receive_packet(socket, datap); + if (packet_size > 0) { - if (mDropPercentage && (ll_frand(100.f) < mDropPercentage)) + mActualBytesIn += packet_size; + if (drop) { - mPacketsToDrop++; + packet_size = 0; } - - if (mPacketsToDrop) + else { - packet_size = 0; - mPacketsToDrop--; + mLastSender = ::get_sender(); + mLastReceivingIF = ::get_receiving_interface(); } } } - return packet_size; } -bool LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LLHost host) +S32 LLPacketRing::receiveOrDropBufferedPacket(char *datap, bool drop) { - bool status = true; - if (!mUseOutThrottle) + assert(mNumBufferedPackets > 0); + S32 packet_size = 0; + + S16 ring_size = (S16)(mPacketRing.size()); + S16 packet_index = (mHeadIndex + ring_size - mNumBufferedPackets) % ring_size; + LLPacketBuffer* packet = mPacketRing[packet_index]; + packet_size = packet->getSize(); + mLastSender = packet->getHost(); + mLastReceivingIF = packet->getReceivingInterface(); + + --mNumBufferedPackets; + mNumBufferedBytes -= packet_size; + if (mNumBufferedPackets == 0) { - return sendPacketImpl(h_socket, send_buffer, buf_size, host ); + assert(mNumBufferedBytes == 0); + } + + if (!drop) + { + assert(packet_size > 0); + memcpy(datap, packet->getData(), packet_size); } else { - mActualBitsOut += buf_size * 8; - LLPacketBuffer *packetp = NULL; - // See if we've got enough throttle to send a packet. - while (!mOutThrottle.checkOverflow(0.f)) - { - // While we have enough bandwidth, send a packet from the queue or the current packet + packet_size = 0; + } + return packet_size; +} + +S32 LLPacketRing::bufferInboundPacket(S32 socket) +{ + if (mNumBufferedPackets == mPacketRing.size() && mNumBufferedPackets < MAX_BUFFER_RING_SIZE) + { + expandRing(); + } - S32 packet_size = 0; - if (!mSendQueue.empty()) + LLPacketBuffer* packet = mPacketRing[mHeadIndex]; + S32 old_packet_size = packet->getSize(); + S32 packet_size = 0; + if (LLProxy::isSOCKSProxyEnabled()) + { + char buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; /* Flawfinder ignore */ + packet_size = receive_packet(socket, buffer); + if (packet_size > 0) + { + mActualBytesIn += packet_size; + if (packet_size > SOCKS_HEADER_SIZE) { - // Send a packet off of the queue - LLPacketBuffer *packetp = mSendQueue.front(); - mSendQueue.pop(); + // *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6) - mOutBufferLength -= packetp->getSize(); - packet_size = packetp->getSize(); + proxywrap_t * header = static_cast(static_cast(buffer)); + LLHost sender; + sender.setAddress(header->addr); + sender.setPort(ntohs(header->port)); - status = sendPacketImpl(h_socket, packetp->getData(), packet_size, packetp->getHost()); + packet_size -= SOCKS_HEADER_SIZE; // The unwrapped packet size + packet->init(buffer + SOCKS_HEADER_SIZE, packet_size, sender); - delete packetp; - // Update the throttle - mOutThrottle.throttleOverflow(packet_size * 8.f); + mHeadIndex = (mHeadIndex + 1) % (S16)(mPacketRing.size()); + if (mNumBufferedPackets < MAX_BUFFER_RING_SIZE) + { + ++mNumBufferedPackets; + mNumBufferedBytes += packet_size; + } + else + { + // we overwrote an older packet + mNumBufferedBytes += packet_size - old_packet_size; + } } else { - // If the queue's empty, we can just send this packet right away. - status = sendPacketImpl(h_socket, send_buffer, buf_size, host ); - packet_size = buf_size; - - // Update the throttle - mOutThrottle.throttleOverflow(packet_size * 8.f); - - // This was the packet we're sending now, there are no other packets - // that we need to send - return status; + packet_size = 0; } - - } - - // We haven't sent the incoming packet, add it to the queue - if (mOutBufferLength + buf_size > mMaxBufferLength) - { - // Nuke this packet, we overflowed the buffer. - // Toss it. - LL_WARNS() << "Throwing away outbound packet, overflowing buffer" << LL_ENDL; } - else + } + else + { + packet->init(socket); + packet_size = packet->getSize(); + if (packet_size > 0) { - static LLTimer queue_timer; - if ((mOutBufferLength > 4192) && queue_timer.getElapsedTimeF32() > 1.f) + mActualBytesIn += packet_size; + + mHeadIndex = (mHeadIndex + 1) % (S16)(mPacketRing.size()); + if (mNumBufferedPackets < MAX_BUFFER_RING_SIZE) { - // Add it to the queue - LL_INFOS() << "Outbound packet queue " << mOutBufferLength << " bytes" << LL_ENDL; - queue_timer.reset(); + ++mNumBufferedPackets; + mNumBufferedBytes += packet_size; + } + else + { + // we overwrote an older packet + mNumBufferedBytes += packet_size - old_packet_size; } - packetp = new LLPacketBuffer(host, send_buffer, buf_size); - - mOutBufferLength += packetp->getSize(); - mSendQueue.push(packetp); } } - - return status; + return packet_size; } -bool LLPacketRing::sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host) +S32 LLPacketRing::drainSocket(S32 socket) { - - if (!LLProxy::isSOCKSProxyEnabled()) + // drain into buffer + S32 packet_size = 1; + S32 num_loops = 0; + S32 old_num_packets = mNumBufferedPackets; + while (packet_size > 0) { - return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort()); + packet_size = bufferInboundPacket(socket); + ++num_loops; } + S32 num_dropped_packets = (num_loops - 1 + old_num_packets) - mNumBufferedPackets; + if (num_dropped_packets > 0) + { + LL_WARNS("Messaging") << "dropped " << num_dropped_packets << " UDP packets" << LL_ENDL; + } + return (S32)(mNumBufferedPackets); +} - char headered_send_buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; +bool LLPacketRing::expandRing() +{ + // compute larger size + constexpr S16 BUFFER_RING_EXPANSION = 256; + S16 old_size = (S16)(mPacketRing.size()); + S16 new_size = llmin(old_size + BUFFER_RING_EXPANSION, MAX_BUFFER_RING_SIZE); + if (new_size == old_size) + { + // mPacketRing is already maxed out + return false; + } - proxywrap_t *socks_header = static_cast(static_cast(&headered_send_buffer)); - socks_header->rsv = 0; - socks_header->addr = host.getAddress(); - socks_header->port = htons(host.getPort()); - socks_header->atype = ADDRESS_IPV4; - socks_header->frag = 0; + // make a larger ring and copy packet pointers + std::vector new_ring(new_size, nullptr); + for (S16 i = 0; i < old_size; ++i) + { + S16 j = (mHeadIndex + i) % old_size; + new_ring[i] = mPacketRing[j]; + } - memcpy(headered_send_buffer + SOCKS_HEADER_SIZE, send_buffer, buf_size); + // allocate new packets for the remainder of new_ring + LLHost invalid_host; + for (S16 i = old_size; i < new_size; ++i) + { + new_ring[i] = new LLPacketBuffer(invalid_host, nullptr, 0); + } - return send_packet( h_socket, - headered_send_buffer, - buf_size + SOCKS_HEADER_SIZE, - LLProxy::getInstance()->getUDPProxy().getAddress(), - LLProxy::getInstance()->getUDPProxy().getPort()); + // swap the rings and reset mHeadIndex + mPacketRing.swap(new_ring); + mHeadIndex = mNumBufferedPackets; + return true; } diff --git a/indra/llmessage/llpacketring.h b/indra/llmessage/llpacketring.h index f0e95f8524..0dff2c63b1 100644 --- a/indra/llmessage/llpacketring.h +++ b/indra/llmessage/llpacketring.h @@ -25,16 +25,14 @@ * $/LicenseInfo$ */ -#ifndef LL_LLPACKETRING_H -#define LL_LLPACKETRING_H +#pragma once -#include +#include #include "llhost.h" #include "llpacketbuffer.h" -#include "llproxy.h" #include "llthrottle.h" -#include "net.h" + class LLPacketRing { @@ -42,60 +40,65 @@ public: LLPacketRing(); ~LLPacketRing(); - void cleanup(); + // receive one packet: either buffered or from the socket + S32 receivePacket (S32 socket, char *datap); + + // send one packet + bool sendPacket(int h_socket, const char * send_buffer, S32 buf_size, LLHost host); + + // drains packets from socket and returns final mNumBufferedPackets + S32 drainSocket(S32 socket); void dropPackets(U32); void setDropPercentage (F32 percent_to_drop); - void setUseInThrottle(const bool use_throttle); - void setUseOutThrottle(const bool use_throttle); - void setInBandwidth(const F32 bps); - void setOutBandwidth(const F32 bps); - S32 receivePacket (S32 socket, char *datap); - S32 receiveFromRing (S32 socket, char *datap); - bool sendPacket(int h_socket, char * send_buffer, S32 buf_size, LLHost host); + inline LLHost getLastSender() const; + inline LLHost getLastReceivingInterface() const; - inline LLHost getLastSender(); - inline LLHost getLastReceivingInterface(); + S32 getActualInBytes() const { return mActualBytesIn; } + S32 getActualOutBytes() const { return mActualBytesOut; } + S32 getAndResetActualInBits() { S32 bits = mActualBytesIn * 8; mActualBytesIn = 0; return bits;} + S32 getAndResetActualOutBits() { S32 bits = mActualBytesOut * 8; mActualBytesOut = 0; return bits;} - S32 getAndResetActualInBits() { S32 bits = mActualBitsIn; mActualBitsIn = 0; return bits;} - S32 getAndResetActualOutBits() { S32 bits = mActualBitsOut; mActualBitsOut = 0; return bits;} + S32 getNumBufferedPackets() const { return (S32)(mNumBufferedPackets); } + S32 getNumBufferedBytes() const { return mNumBufferedBytes; } protected: - bool mUseInThrottle; - bool mUseOutThrottle; + // returns 'true' if we should intentionally drop a packet + bool computeDrop(); - // For simulating a lower-bandwidth connection - BPS - LLThrottle mInThrottle; - LLThrottle mOutThrottle; + // returns packet_size of received packet, zero or less if no packet found + S32 receiveOrDropPacket(S32 socket, char *datap, bool drop); + S32 receiveOrDropBufferedPacket(char *datap, bool drop); - S32 mActualBitsIn; - S32 mActualBitsOut; - S32 mMaxBufferLength; // How much data can we queue up before dropping data. - S32 mInBufferLength; // Current incoming buffer length - S32 mOutBufferLength; // Current outgoing buffer length + // returns packet_size of packet buffered + S32 bufferInboundPacket(S32 socket); - F32 mDropPercentage; // % of packets to drop - U32 mPacketsToDrop; // drop next n packets + // returns 'true' if ring was expanded + bool expandRing(); - std::queue mReceiveQueue; - std::queue mSendQueue; +protected: + std::vector mPacketRing; + S16 mHeadIndex { 0 }; + S16 mNumBufferedPackets { 0 }; + S32 mNumBufferedBytes { 0 }; + + S32 mActualBytesIn { 0 }; + S32 mActualBytesOut { 0 }; + F32 mDropPercentage { 0.0f }; // % of inbound packets to drop + U32 mPacketsToDrop { 0 }; // drop next inbound n packets + // These are the sender and receiving_interface for the last packet delivered by receivePacket() LLHost mLastSender; LLHost mLastReceivingIF; - -private: - bool sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host); }; -inline LLHost LLPacketRing::getLastSender() +inline LLHost LLPacketRing::getLastSender() const { return mLastSender; } -inline LLHost LLPacketRing::getLastReceivingInterface() +inline LLHost LLPacketRing::getLastReceivingInterface() const { return mLastReceivingIF; } - -#endif diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index cfa5178fc6..c130b7a6db 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -656,8 +656,7 @@ bool LLMessageSystem::checkMessages(LockMessageChecker&, S64 frame_count ) // UseCircuitCode is allowed in even from an invalid circuit, so that // we can toss circuits around. - if( - valid_packet && + else if ( !cdp && (mTemplateMessageReader->getMessageName() != _PREHASH_UseCircuitCode)) @@ -667,8 +666,7 @@ bool LLMessageSystem::checkMessages(LockMessageChecker&, S64 frame_count ) valid_packet = false; } - if( - valid_packet && + if ( valid_packet && cdp && !cdp->getTrusted() && mTemplateMessageReader->isTrusted()) @@ -680,7 +678,7 @@ bool LLMessageSystem::checkMessages(LockMessageChecker&, S64 frame_count ) valid_packet = false; } - if( valid_packet ) + if ( valid_packet ) { logValidMsg(cdp, host, recv_reliable, recv_resent, acks>0 ); valid_packet = mTemplateMessageReader->readMessage(buffer, host); @@ -821,6 +819,11 @@ void LLMessageSystem::processAcks(LockMessageChecker&, F32 collect_time) } } +S32 LLMessageSystem::drainUdpSocket() +{ + return mPacketRing.drainSocket(mSocket); +} + void LLMessageSystem::copyMessageReceivedToSend() { // NOTE: babbage: switch builder to match reader to avoid diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h index b4b0d94021..1844d5e7cd 100644 --- a/indra/llmessage/message.h +++ b/indra/llmessage/message.h @@ -417,6 +417,9 @@ public: bool checkMessages(LockMessageChecker&, S64 frame_count = 0 ); void processAcks(LockMessageChecker&, F32 collect_time = 0.f); + // returns total number of buffered packets after the drain + S32 drainUdpSocket(); + bool isMessageFast(const char *msg); bool isMessage(const char *msg) { diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp index f153c938cf..2be5a9e5b6 100644 --- a/indra/llmessage/net.cpp +++ b/indra/llmessage/net.cpp @@ -76,14 +76,8 @@ static U32 gsnReceivingIFAddr = INVALID_HOST_IP_ADDRESS; // Address to which dat const char* LOOPBACK_ADDRESS_STRING = "127.0.0.1"; const char* BROADCAST_ADDRESS_STRING = "255.255.255.255"; -#if LL_DARWIN - // macOS returns an error when trying to set these to 400000. Smaller values succeed. - const int SEND_BUFFER_SIZE = 200000; - const int RECEIVE_BUFFER_SIZE = 200000; -#else // LL_DARWIN - const int SEND_BUFFER_SIZE = 400000; - const int RECEIVE_BUFFER_SIZE = 400000; -#endif // LL_DARWIN +const int SEND_BUFFER_SIZE = 200000; +const int RECEIVE_BUFFER_SIZE = 800000; // universal functions (cross-platform) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 52bea875d9..ba474d3f39 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -350,8 +350,6 @@ LLVector3 gRelativeWindVec(0.0, 0.0, 0.0); U32 gPacketsIn = 0; -bool gPrintMessagesThisFrame = false; - bool gRandomizeFramerate = false; bool gPeriodicSlowFrame = false; @@ -1495,9 +1493,9 @@ bool LLAppViewer::doFrame() { LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df pauseMainloopTimeout"); - pingMainloopTimeout("Main:Sleep"); + pingMainloopTimeout("Main:Sleep"); - pauseMainloopTimeout(); + pauseMainloopTimeout(); } // Sleep and run background threads @@ -5217,12 +5215,9 @@ void LLAppViewer::idleNameCache() // Handle messages, and all message related stuff // -#define TIME_THROTTLE_MESSAGES -#ifdef TIME_THROTTLE_MESSAGES -#define CHECK_MESSAGES_DEFAULT_MAX_TIME .020f // 50 ms = 50 fps (just for messages!) +constexpr F32 CHECK_MESSAGES_DEFAULT_MAX_TIME = 0.020f; // 50 ms = 50 fps (just for messages!) static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME; -#endif static LLTrace::BlockTimerStatHandle FTM_IDLE_NETWORK("Idle Network"); static LLTrace::BlockTimerStatHandle FTM_MESSAGE_ACKS("Message Acks"); @@ -5249,6 +5244,7 @@ void LLAppViewer::idleNetwork() F32 total_time = 0.0f; { + bool needs_drain = false; LockMessageChecker lmc(gMessageSystem); while (lmc.checkAllMessages(frame_count, gServicePump)) { @@ -5265,50 +5261,41 @@ void LLAppViewer::idleNetwork() if (total_decoded > MESSAGE_MAX_PER_FRAME) { + needs_drain = true; break; } -#ifdef TIME_THROTTLE_MESSAGES // Prevent slow packets from completely destroying the frame rate. // This usually happens due to clumps of avatars taking huge amount // of network processing time (which needs to be fixed, but this is // a good limit anyway). total_time = check_message_timer.getElapsedTimeF32(); if (total_time >= CheckMessagesMaxTime) + { + needs_drain = true; break; -#endif + } + } + if (needs_drain || gMessageSystem->mPacketRing.getNumBufferedPackets() > 0) + { + // Rather than allow packets to silently backup on the socket + // we drain them into our own buffer so we know how many exist. + S32 num_buffered_packets = gMessageSystem->drainUdpSocket(); + if (num_buffered_packets > 0) + { + // Increase CheckMessagesMaxTime so that we will eventually catch up + CheckMessagesMaxTime *= 1.035f; // 3.5% ~= 2x in 20 frames, ~8x in 60 frames + } + } + else + { + // Reset CheckMessagesMaxTime to default value + CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME; } // Handle per-frame message system processing. lmc.processAcks(gSavedSettings.getF32("AckCollectTime")); } - -#ifdef TIME_THROTTLE_MESSAGES - if (total_time >= CheckMessagesMaxTime) - { - // Increase CheckMessagesMaxTime so that we will eventually catch up - CheckMessagesMaxTime *= 1.035f; // 3.5% ~= x2 in 20 frames, ~8x in 60 frames - } - else - { - // Reset CheckMessagesMaxTime to default value - CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME; - } -#endif - - // Decode enqueued messages... - S32 remaining_possible_decodes = MESSAGE_MAX_PER_FRAME - total_decoded; - - if( remaining_possible_decodes <= 0 ) - { - LL_INFOS() << "Maxed out number of messages per frame at " << MESSAGE_MAX_PER_FRAME << LL_ENDL; - } - - if (gPrintMessagesThisFrame) - { - LL_INFOS() << "Decoded " << total_decoded << " msgs this frame!" << LL_ENDL; - gPrintMessagesThisFrame = false; - } } add(LLStatViewer::NUM_NEW_OBJECTS, gObjectList.mNumNewObjects); diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 4ce4259ed8..a253f06d14 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -400,7 +400,6 @@ extern std::string gLastVersionChannel; extern LLVector3 gWindVec; extern LLVector3 gRelativeWindVec; extern U32 gPacketsIn; -extern bool gPrintMessagesThisFrame; extern bool gRandomizeFramerate; extern bool gPeriodicSlowFrame; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index b32b80331a..5f6c5e1e15 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -623,21 +623,6 @@ bool idle_startup() F32 dropPercent = gSavedSettings.getF32("PacketDropPercentage"); msg->mPacketRing.setDropPercentage(dropPercent); - - F32 inBandwidth = gSavedSettings.getF32("InBandwidth"); - F32 outBandwidth = gSavedSettings.getF32("OutBandwidth"); - if (inBandwidth != 0.f) - { - LL_DEBUGS("AppInit") << "Setting packetring incoming bandwidth to " << inBandwidth << LL_ENDL; - msg->mPacketRing.setUseInThrottle(true); - msg->mPacketRing.setInBandwidth(inBandwidth); - } - if (outBandwidth != 0.f) - { - LL_DEBUGS("AppInit") << "Setting packetring outgoing bandwidth to " << outBandwidth << LL_ENDL; - msg->mPacketRing.setUseOutThrottle(true); - msg->mPacketRing.setOutBandwidth(outBandwidth); - } } LL_INFOS("AppInit") << "Message System Initialized." << LL_ENDL; -- cgit v1.3 From b52842ee2a328d80834f9a62c1b130ec757b9a03 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 26 Feb 2025 10:24:19 -0800 Subject: theoretical earlier start to asset downloads during startup (#3589) * process UDP packets earlier in startup sequence * call lazyAttach() when nonzero pending attachments --- indra/newview/llappviewer.cpp | 5 +- indra/newview/llappviewer.h | 2 +- indra/newview/llstartup.cpp | 272 +++++++++++++++++++++++------------------- indra/newview/llvoavatar.cpp | 5 +- 4 files changed, 153 insertions(+), 131 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 241dbeaae5..18ad19f6bc 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -349,8 +349,6 @@ std::string gLastVersionChannel; LLVector3 gWindVec(3.0, 3.0, 0.0); LLVector3 gRelativeWindVec(0.0, 0.0, 0.0); -U32 gPacketsIn = 0; - bool gRandomizeFramerate = false; bool gPeriodicSlowFrame = false; @@ -359,6 +357,7 @@ bool gLLErrorActivated = false; bool gLogoutInProgress = false; bool gSimulateMemLeak = false; +bool gDoDisconnect = false; // We don't want anyone, especially threads working on the graphics pipeline, // to have to block due to this WorkQueue being full. @@ -372,7 +371,6 @@ const std::string MARKER_FILE_NAME("SecondLife.exec_marker"); const std::string START_MARKER_FILE_NAME("SecondLife.start_marker"); const std::string ERROR_MARKER_FILE_NAME("SecondLife.error_marker"); const std::string LOGOUT_MARKER_FILE_NAME("SecondLife.logout_marker"); -static bool gDoDisconnect = false; static std::string gLaunchFileOnQuit; // Used on Win32 for other apps to identify our window (eg, win_setup) @@ -5393,7 +5391,6 @@ void LLAppViewer::idleNetwork() } total_decoded++; - gPacketsIn++; if (total_decoded > MESSAGE_MAX_PER_FRAME) { diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 832d61101a..ad42c4a6f1 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -411,10 +411,10 @@ extern std::string gLastVersionChannel; extern LLVector3 gWindVec; extern LLVector3 gRelativeWindVec; -extern U32 gPacketsIn; extern bool gRandomizeFramerate; extern bool gPeriodicSlowFrame; +extern bool gDoDisconnect; extern bool gSimulateMemLeak; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 5cd27352de..eb0e9ef4bc 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -297,16 +297,62 @@ void callback_cache_name(const LLUUID& id, const std::string& full_name, bool is // exported functionality // +void do_startup_frame() +{ + // Until after STATE_AGENT_SEND we don't get very many UDP packets to poll the socket, + // and after STATE_PRECACHE the LLAppViewer::idleNetwork() will do UDP processing, + // so we only bother to process between those two states. + EStartupState state = LLStartUp::getStartupState(); + if (state > STATE_AGENT_SEND && state < STATE_PRECACHE) + { + // drain the UDP socket... + U64 t0 = totalTime(); + constexpr U64 MAX_STARTUP_FRAME_TIME = 2000; // usec + constexpr U64 MAX_STARTUP_FRAME_MESSAGES = 100; + S32 num_messages = 0; + bool needs_drain = false; + LockMessageChecker lmc(gMessageSystem); + while (lmc.checkAllMessages(gFrameCount, gServicePump)) + { + if (gDoDisconnect) + { + // We're disconnecting, don't process any more messages from the server + // We're usually disconnecting due to either network corruption or a + // server going down, so this is OK. + break; + } + if (++num_messages >= MAX_STARTUP_FRAME_MESSAGES + || (totalTime() - t0) > MAX_STARTUP_FRAME_TIME) + { + needs_drain = true; + break; + } + } + if (needs_drain || gMessageSystem->mPacketRing.getNumBufferedPackets() > 0) + { + gMessageSystem->drainUdpSocket(); + } + lmc.processAcks(); + } + // ...then call display_startup() + display_startup(); +} + void pump_idle_startup_network(void) { + // while there are message to process: + // process one then call display_startup() + S32 num_messages = 0; { LockMessageChecker lmc(gMessageSystem); while (lmc.checkAllMessages(gFrameCount, gServicePump)) { display_startup(); + ++num_messages; } lmc.processAcks(); } + // finally call one last display_startup() display_startup(); } @@ -728,7 +774,7 @@ bool idle_startup() LL_DEBUGS("AppInit") << "STATE_BROWSER_INIT" << LL_ENDL; std::string msg = LLTrans::getString("LoginInitializingBrowser"); set_startup_status(0.03f, msg.c_str(), gAgent.mMOTD.c_str()); - display_startup(); + do_startup_frame(); // LLViewerMedia::initBrowser(); LLStartUp::setStartupState( STATE_LOGIN_SHOW ); return false; @@ -793,7 +839,7 @@ bool idle_startup() LL_DEBUGS("AppInit") << "FirstLoginThisInstall off" << LL_ENDL; } } - display_startup(); + do_startup_frame(); LLStartUp::setStartupState( STATE_LOGIN_WAIT ); // Wait for user input } else @@ -824,7 +870,7 @@ bool idle_startup() } LL_DEBUGS("AppInit") << "PeekMessage processed" << LL_ENDL; #endif - display_startup(); + do_startup_frame(); timeout.reset(); return false; } @@ -839,7 +885,7 @@ bool idle_startup() // Don't do anything. Wait for the login view to call the login_callback, // which will push us to the next state. - // display() function will be the one to run display_startup() + // display() function will be the one to run do_startup_frame() // Sleep so we don't spin the CPU ms_sleep(1); return false; @@ -1021,7 +1067,7 @@ bool idle_startup() auth_desc = LLTrans::getString("LoginInProgress"); set_startup_status(progress, auth_desc, auth_message); progress += 0.02f; - display_startup(); + do_startup_frame(); // Setting initial values... LLLoginInstance* login = LLLoginInstance::getInstance(); @@ -1058,7 +1104,7 @@ bool idle_startup() emsg << LLTrans::getString("LoginFailedHeader") << "\n"; if(LLLoginInstance::getInstance()->authFailure()) { - LL_INFOS("LLStartup") << "Login failed, LLLoginInstance::getResponse(): " + LL_INFOS("LLStartUp") << "Login failed, LLLoginInstance::getResponse(): " << LLLoginInstance::getInstance()->getResponse() << LL_ENDL; LLSD response = LLLoginInstance::getInstance()->getResponse(); // Still have error conditions that may need some @@ -1130,7 +1176,7 @@ bool idle_startup() // If optional was skipped this case shouldn't // be reached. - LL_INFOS("LLStartup") << "Forcing a quit due to update." << LL_ENDL; + LL_INFOS("LLStartUp") << "Forcing a quit due to update." << LL_ENDL; LLLoginInstance::getInstance()->disconnect(); LLAppViewer::instance()->forceQuit(); } @@ -1158,7 +1204,7 @@ bool idle_startup() } catch (LLCertException &cert_exception) { - LL_WARNS("LLStartup", "SECAPI") << "Caught " << cert_exception.what() << " certificate expception on getCertificate("<< response["certificate"] << ")" << LL_ENDL; + LL_WARNS("LLStartUp", "SECAPI") << "Caught " << cert_exception.what() << " certificate expception on getCertificate("<< response["certificate"] << ")" << LL_ENDL; LLSD args; args["REASON"] = LLTrans::getString(cert_exception.what()); @@ -1210,7 +1256,7 @@ bool idle_startup() // notificatioin message. LLSD args; args["ERROR_MESSAGE"] = emsg.str(); - LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL; + LL_INFOS("LLStartUp") << "Notification: " << args << LL_ENDL; LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done); } } @@ -1233,7 +1279,7 @@ bool idle_startup() { LLSD args; args["ERROR_MESSAGE"] = emsg.str(); - LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL; + LL_INFOS("LLStartUp") << "Notification: " << args << LL_ENDL; LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done); transition_back_to_login_panel(emsg.str()); show_connect_box = true; @@ -1249,71 +1295,71 @@ bool idle_startup() if (STATE_WORLD_INIT == LLStartUp::getStartupState()) { set_startup_status(0.30f, LLTrans::getString("LoginInitializingWorld"), gAgent.mMOTD); - display_startup(); + do_startup_frame(); // We should have an agent id by this point. llassert(!(gAgentID == LLUUID::null)); // Finish agent initialization. (Requires gSavedSettings, builds camera) gAgent.init(); - display_startup(); + do_startup_frame(); gAgentCamera.init(); - display_startup(); - display_startup(); + do_startup_frame(); + do_startup_frame(); // Since we connected, save off the settings so the user doesn't have to // type the name/password again if we crash. gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), true); LLUIColorTable::instance().saveUserSettings(); - display_startup(); + do_startup_frame(); // // Initialize classes w/graphics stuff. // LLSurface::initClasses(); - display_startup(); + do_startup_frame(); - display_startup(); + do_startup_frame(); LLDrawable::initClass(); - display_startup(); + do_startup_frame(); // init the shader managers LLPostProcess::initClass(); - display_startup(); + do_startup_frame(); LLAvatarAppearance::initClass("avatar_lad.xml","avatar_skeleton.xml"); - display_startup(); + do_startup_frame(); LLViewerObject::initVOClasses(); - display_startup(); + do_startup_frame(); // Initialize all our tools. Must be done after saved settings loaded. // NOTE: This also is where gToolMgr used to be instantiated before being turned into a singleton. LLToolMgr::getInstance()->initTools(); - display_startup(); + do_startup_frame(); // Pre-load floaters, like the world map, that are slow to spawn // due to XML complexity. gViewerWindow->initWorldUI(); - display_startup(); + do_startup_frame(); // This is where we used to initialize gWorldp. Original comment said: // World initialization must be done after above window init // User might have overridden far clip LLWorld::getInstance()->setLandFarClip(gAgentCamera.mDrawDistance); - display_startup(); + do_startup_frame(); // Before we create the first region, we need to set the agent's mOriginGlobal // This is necessary because creating objects before this is set will result in a // bad mPositionAgent cache. gAgent.initOriginGlobal(from_region_handle(gFirstSimHandle)); - display_startup(); + do_startup_frame(); LLWorld::getInstance()->addRegion(gFirstSimHandle, gFirstSim); - display_startup(); + do_startup_frame(); LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle); LL_INFOS("AppInit") << "Adding initial simulator " << regionp->getOriginGlobal() << LL_ENDL; @@ -1322,18 +1368,18 @@ bool idle_startup() << gFirstSimSeedCap << LL_ENDL; regionp->setSeedCapability(gFirstSimSeedCap); LL_DEBUGS("AppInit") << "Waiting for seed grant ...." << LL_ENDL; - display_startup(); + do_startup_frame(); // Set agent's initial region to be the one we just created. gAgent.setRegion(regionp); - display_startup(); + do_startup_frame(); // Set agent's initial position, which will be read by LLVOAvatar when the avatar // object is created. I think this must be done after setting the region. JC gAgent.setPositionAgent(agent_start_position_region); - display_startup(); + do_startup_frame(); LLStartUp::initExperiences(); - display_startup(); + do_startup_frame(); // If logging should be enebled, turns it on and loads history from disk // Note: does not happen on init of singleton because preferences can use @@ -1354,7 +1400,7 @@ bool idle_startup() { LLStartUp::multimediaInit(); LLStartUp::setStartupState( STATE_FONT_INIT ); - display_startup(); + do_startup_frame(); return false; } @@ -1363,7 +1409,7 @@ bool idle_startup() { LLStartUp::fontInit(); LLStartUp::setStartupState( STATE_SEED_GRANTED_WAIT ); - display_startup(); + do_startup_frame(); return false; } @@ -1435,7 +1481,7 @@ bool idle_startup() set_startup_status(0.4f, LLTrans::getString("LoginRequestSeedCapGrant"), gAgent.mMOTD.c_str()); } } - display_startup(); + do_startup_frame(); return false; } @@ -1446,7 +1492,7 @@ bool idle_startup() //--------------------------------------------------------------------- if (STATE_SEED_CAP_GRANTED == LLStartUp::getStartupState()) { - display_startup(); + do_startup_frame(); // These textures are not warrantied to be cached, so needs // to hapen with caps granted @@ -1455,9 +1501,9 @@ bool idle_startup() // will init images, should be done with caps, but before gSky.init() LLEnvironment::getInstance()->initSingleton(); - display_startup(); + do_startup_frame(); update_texture_fetch(); - display_startup(); + do_startup_frame(); if ( gViewerWindow != NULL) { // This isn't the first logon attempt, so show the UI @@ -1465,15 +1511,15 @@ bool idle_startup() } gLoginMenuBarView->setVisible( false ); gLoginMenuBarView->setEnabled( false ); - display_startup(); + do_startup_frame(); // direct logging to the debug console's line buffer LLError::logToFixedBuffer(gDebugView->mDebugConsolep); - display_startup(); + do_startup_frame(); // set initial visibility of debug console gDebugView->mDebugConsolep->setVisible(gSavedSettings.getBOOL("ShowDebugConsole")); - display_startup(); + do_startup_frame(); // // Set message handlers @@ -1482,23 +1528,23 @@ bool idle_startup() // register callbacks for messages. . . do this after initial handshake to make sure that we don't catch any unwanted register_viewer_callbacks(gMessageSystem); - display_startup(); + do_startup_frame(); // Debugging info parameters gMessageSystem->setMaxMessageTime( 0.5f ); // Spam if decoding all msgs takes more than 500 ms - display_startup(); + do_startup_frame(); #ifndef LL_RELEASE_FOR_DOWNLOAD gMessageSystem->setTimeDecodes( true ); // Time the decode of each msg gMessageSystem->setTimeDecodesSpamThreshold( 0.05f ); // Spam if a single msg takes over 50ms to decode #endif - display_startup(); + do_startup_frame(); gXferManager->registerCallbacks(gMessageSystem); - display_startup(); + do_startup_frame(); LLStartUp::initNameCache(); - display_startup(); + do_startup_frame(); // update the voice settings *after* gCacheName initialization // so that we can construct voice UI that relies on the name cache @@ -1506,7 +1552,7 @@ bool idle_startup() { LLVoiceClient::getInstance()->updateSettings(); } - display_startup(); + do_startup_frame(); // create a container's instance for start a controlling conversation windows // by the voice's events @@ -1527,12 +1573,12 @@ bool idle_startup() // register null callbacks for audio until the audio system is initialized gMessageSystem->setHandlerFuncFast(_PREHASH_SoundTrigger, null_message_callback, NULL); gMessageSystem->setHandlerFuncFast(_PREHASH_AttachedSound, null_message_callback, NULL); - display_startup(); + do_startup_frame(); //reset statistics LLViewerStats::instance().resetStats(); - display_startup(); + do_startup_frame(); // // Set up region and surface defaults // @@ -1557,7 +1603,7 @@ bool idle_startup() LLViewerCamera::getInstance()->setAspect(gViewerWindow->getWorldViewAspectRatio()); // Initialize FOV LLViewerCamera::getInstance()->setDefaultFOV(gSavedSettings.getF32("CameraAngle")); - display_startup(); + do_startup_frame(); // Move agent to starting location. The position handed to us by // the space server is in global coordinates, but the agent frame @@ -1568,7 +1614,7 @@ bool idle_startup() gAgent.resetAxes(gAgentStartLookAt); gAgentCamera.stopCameraAnimation(); gAgentCamera.resetCamera(); - display_startup(); + do_startup_frame(); // Initialize global class data needed for surfaces (i.e. textures) LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL; @@ -1579,7 +1625,7 @@ bool idle_startup() LLGLState::checkStates(); - display_startup(); + do_startup_frame(); LL_DEBUGS("AppInit") << "Decoding images..." << LL_ENDL; // For all images pre-loaded into viewer cache, init @@ -1593,12 +1639,12 @@ bool idle_startup() { F32 frac = (F32)i / (F32)DECODE_TIME_SEC; set_startup_status(0.45f + frac*0.1f, LLTrans::getString("LoginDecodingImages"), gAgent.mMOTD); - display_startup(); + do_startup_frame(); gTextureList.decodeAllImages(1.f); } LLStartUp::setStartupState( STATE_WORLD_WAIT ); - display_startup(); + do_startup_frame(); // JC - Do this as late as possible to increase likelihood Purify // will run. @@ -1627,7 +1673,7 @@ bool idle_startup() NULL); timeout.reset(); - display_startup(); + do_startup_frame(); return false; } @@ -1654,7 +1700,7 @@ bool idle_startup() { LL_DEBUGS("AppInit") << "Connecting to region..." << LL_ENDL; set_startup_status(0.60f, LLTrans::getString("LoginConnectingToRegion"), gAgent.mMOTD); - display_startup(); + do_startup_frame(); // register with the message system so it knows we're // expecting this message LLMessageSystem* msg = gMessageSystem; @@ -1668,7 +1714,7 @@ bool idle_startup() gAssetStorage->setUpstream(regionp->getHost()); gCacheName->setUpstream(regionp->getHost()); } - display_startup(); + do_startup_frame(); // Create login effect // But not on first login, because you can't see your avatar then @@ -1683,7 +1729,7 @@ bool idle_startup() LLStartUp::setStartupState( STATE_AGENT_WAIT ); // Go to STATE_AGENT_WAIT timeout.reset(); - display_startup(); + do_startup_frame(); return false; } @@ -1692,35 +1738,13 @@ bool idle_startup() //--------------------------------------------------------------------- if (STATE_AGENT_WAIT == LLStartUp::getStartupState()) { - { - LockMessageChecker lmc(gMessageSystem); - while (lmc.checkAllMessages(gFrameCount, gServicePump)) - { - if (gAgentMovementCompleted) - { - // Sometimes we have more than one message in the - // queue. break out of this loop and continue - // processing. If we don't, then this could skip one - // or more login steps. - break; - } - else - { - LL_DEBUGS("AppInit") << "Awaiting AvatarInitComplete, got " - << gMessageSystem->getMessageName() << LL_ENDL; - } - display_startup(); - } - lmc.processAcks(); - } - - display_startup(); + do_startup_frame(); if (gAgentMovementCompleted) { LLStartUp::setStartupState( STATE_INVENTORY_SEND ); } - display_startup(); + do_startup_frame(); if (!gAgentMovementCompleted && timeout.getElapsedTimeF32() > STATE_AGENT_WAIT_TIMEOUT) { @@ -1753,7 +1777,7 @@ bool idle_startup() if (STATE_INVENTORY_SEND == LLStartUp::getStartupState()) { LL_PROFILE_ZONE_NAMED("State inventory send") - display_startup(); + do_startup_frame(); // request mute list LL_INFOS() << "Requesting Mute List" << LL_ENDL; @@ -1763,12 +1787,12 @@ bool idle_startup() LL_INFOS() << "Requesting Money Balance" << LL_ENDL; LLStatusBar::sendMoneyBalanceRequest(); - display_startup(); + do_startup_frame(); // Inform simulator of our language preference LLAgentLanguage::update(); - display_startup(); + do_startup_frame(); // unpack thin inventory LLSD response = LLLoginInstance::getInstance()->getResponse(); //bool dump_buffer = false; @@ -1783,7 +1807,7 @@ bool idle_startup() gInventory.setLibraryRootFolderID(id.asUUID()); } } - display_startup(); + do_startup_frame(); LLSD inv_lib_owner = response["inventory-lib-owner"]; if(inv_lib_owner.isDefined()) @@ -1795,9 +1819,9 @@ bool idle_startup() gInventory.setLibraryOwnerID(LLUUID(id.asUUID())); } } - display_startup(); + do_startup_frame(); LLStartUp::setStartupState(STATE_INVENTORY_SKEL); - display_startup(); + do_startup_frame(); return false; } @@ -1816,7 +1840,7 @@ bool idle_startup() LL_WARNS("AppInit") << "Problem loading inventory-skel-lib" << LL_ENDL; } } - display_startup(); + do_startup_frame(); LLSD inv_skeleton = response["inventory-skeleton"]; if (inv_skeleton.isDefined()) @@ -1827,9 +1851,9 @@ bool idle_startup() LL_WARNS("AppInit") << "Problem loading inventory-skel-targets" << LL_ENDL; } } - display_startup(); + do_startup_frame(); LLStartUp::setStartupState(STATE_INVENTORY_SEND2); - display_startup(); + do_startup_frame(); return false; } @@ -1875,7 +1899,7 @@ bool idle_startup() list[agent_id] = new LLRelationship(given_rights, has_rights, false); } LLAvatarTracker::instance().addBuddyList(list); - display_startup(); + do_startup_frame(); } bool show_hud = false; @@ -1903,7 +1927,7 @@ bool idle_startup() //} } } - display_startup(); + do_startup_frame(); // Either we want to show tutorial because this is the first login // to a Linden Help Island or the user quit with the tutorial @@ -1912,21 +1936,21 @@ bool idle_startup() { LLFloaterReg::showInstance("hud", LLSD(), false); } - display_startup(); + do_startup_frame(); LLSD event_notifications = response["event_notifications"]; if(event_notifications.isDefined()) { gEventNotifier.load(event_notifications); } - display_startup(); + do_startup_frame(); LLSD classified_categories = response["classified_categories"]; if(classified_categories.isDefined()) { LLClassifiedInfo::loadCategories(classified_categories); } - display_startup(); + do_startup_frame(); // This method MUST be called before gInventory.findCategoryUUIDForType because of // gInventory.mIsAgentInvUsable is set to true in the gInventory.buildParentChildMap. @@ -1945,7 +1969,7 @@ bool idle_startup() LLInventoryModelBackgroundFetch::instance().start(); gInventory.createCommonSystemCategories(); LLStartUp::setStartupState(STATE_INVENTORY_CALLBACKS ); - display_startup(); + do_startup_frame(); return false; } @@ -1957,7 +1981,7 @@ bool idle_startup() { if (!LLInventoryModel::isSysFoldersReady()) { - display_startup(); + do_startup_frame(); return false; } @@ -1982,7 +2006,7 @@ bool idle_startup() gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null); gInventory.notifyObservers(); - display_startup(); + do_startup_frame(); // set up callbacks LL_INFOS() << "Registering Callbacks" << LL_ENDL; @@ -1993,18 +2017,18 @@ bool idle_startup() LLAvatarTracker::instance().registerCallbacks(msg); LL_INFOS() << " Landmark" << LL_ENDL; LLLandmark::registerCallbacks(msg); - display_startup(); + do_startup_frame(); // request all group information LL_INFOS() << "Requesting Agent Data" << LL_ENDL; gAgent.sendAgentDataUpdateRequest(); - display_startup(); + do_startup_frame(); // Create the inventory views LL_INFOS() << "Creating Inventory Views" << LL_ENDL; LLFloaterReg::getInstance("inventory"); - display_startup(); + do_startup_frame(); LLStartUp::setStartupState( STATE_MISC ); - display_startup(); + do_startup_frame(); return false; } @@ -2054,7 +2078,7 @@ bool idle_startup() gSavedSettings.setBOOL("ShowStartLocation", true); } - display_startup(); + do_startup_frame(); // Load stored local environment if needed. LLEnvironment::instance().loadFromSettings(); @@ -2062,7 +2086,7 @@ bool idle_startup() // *TODO : Uncomment that line once the whole grid migrated to SLM and suppress it from LLAgent::handleTeleportFinished() (llagent.cpp) //check_merchant_status(); - display_startup(); + do_startup_frame(); if (gSavedSettings.getBOOL("HelpFloaterOpen")) { @@ -2070,7 +2094,7 @@ bool idle_startup() LLViewerHelp::instance().showTopic(""); } - display_startup(); + do_startup_frame(); // We're successfully logged in. gSavedSettings.setBOOL("FirstLoginThisInstall", false); @@ -2079,12 +2103,12 @@ bool idle_startup() LLFloaterGridStatus::getInstance()->startGridStatusTimer(); - display_startup(); + do_startup_frame(); - display_startup(); + do_startup_frame(); // JC: Initializing audio requests many sounds for download. init_audio(); - display_startup(); + do_startup_frame(); // JC: Initialize "active" gestures. This may also trigger // many gesture downloads, if this is the user's first @@ -2122,7 +2146,7 @@ bool idle_startup() LLGestureMgr::instance().startFetch(); } gDisplaySwapBuffers = true; - display_startup(); + do_startup_frame(); LLMessageSystem* msg = gMessageSystem; msg->setHandlerFuncFast(_PREHASH_SoundTrigger, process_sound_trigger); @@ -2200,10 +2224,10 @@ bool idle_startup() } } - display_startup(); + do_startup_frame(); //DEV-17797. get null folder. Any items found here moved to Lost and Found LLInventoryModelBackgroundFetch::instance().findLostItems(); - display_startup(); + do_startup_frame(); LLStartUp::setStartupState( STATE_PRECACHE ); timeout.reset(); @@ -2212,7 +2236,7 @@ bool idle_startup() if (STATE_PRECACHE == LLStartUp::getStartupState()) { - display_startup(); + do_startup_frame(); F32 timeout_frac = timeout.getElapsedTimeF32()/PRECACHING_DELAY; // We now have an inventory skeleton, so if this is a user's first @@ -2238,7 +2262,7 @@ bool idle_startup() callAfterCOFFetch(set_flags_and_update_appearance); } - display_startup(); + do_startup_frame(); // wait precache-delay and for agent's avatar or a lot longer. if ((timeout_frac > 1.f) && isAgentAvatarValid()) @@ -2263,7 +2287,7 @@ bool idle_startup() set_startup_status(0.60f + 0.30f * timeout_frac, LLTrans::getString("LoginPrecaching"), gAgent.mMOTD.c_str()); - display_startup(); + do_startup_frame(); } return true; @@ -2291,7 +2315,7 @@ bool idle_startup() LLStartUp::setStartupState( STATE_CLEANUP ); } - display_startup(); + do_startup_frame(); if (gAgent.isOutfitChosen() && (wearables_time > MAX_WEARABLES_TIME)) { @@ -2332,7 +2356,7 @@ bool idle_startup() if (STATE_CLEANUP == LLStartUp::getStartupState()) { set_startup_status(1.0, "", ""); - display_startup(); + do_startup_frame(); if (!mBenefitsSuccessfullyInit) { @@ -2353,7 +2377,7 @@ bool idle_startup() //gViewerWindow->revealIntroPanel(); gViewerWindow->setStartupComplete(); gViewerWindow->setProgressCancelButtonVisible(false); - display_startup(); + do_startup_frame(); // We're not away from keyboard, even though login might have taken // a while. JC @@ -2385,7 +2409,7 @@ bool idle_startup() // LLUserAuth::getInstance()->reset(); LLStartUp::setStartupState( STATE_STARTED ); - display_startup(); + do_startup_frame(); // Unmute audio if desired and setup volumes. // This is a not-uncommon crash site, so surround it with @@ -2401,7 +2425,7 @@ bool idle_startup() LLAgentPicksInfo::getInstance()->requestNumberOfPicks(); - display_startup(); + do_startup_frame(); llassert(LLPathfindingManager::getInstance() != NULL); LLPathfindingManager::getInstance()->initSystem(); @@ -3006,9 +3030,7 @@ std::string LLStartUp::startupStateToString(EStartupState state) // static void LLStartUp::setStartupState( EStartupState state ) { - LL_INFOS("AppInit") << "Startup state changing from " << - getStartupStateString() << " to " << - startupStateToString(state) << LL_ENDL; + LL_INFOS("AppInit") << getStartupStateString() << " --> " << startupStateToString(state) << LL_ENDL; getPhases().stopPhase(getStartupStateString()); gStartupState = state; @@ -3072,7 +3094,7 @@ void LLStartUp::multimediaInit() LL_DEBUGS("AppInit") << "Initializing Multimedia...." << LL_ENDL; std::string msg = LLTrans::getString("LoginInitializingMultimedia"); set_startup_status(0.42f, msg.c_str(), gAgent.mMOTD.c_str()); - display_startup(); + do_startup_frame(); } void LLStartUp::fontInit() @@ -3080,7 +3102,7 @@ void LLStartUp::fontInit() LL_DEBUGS("AppInit") << "Initializing fonts...." << LL_ENDL; std::string msg = LLTrans::getString("LoginInitializingFonts"); set_startup_status(0.45f, msg.c_str(), gAgent.mMOTD.c_str()); - display_startup(); + do_startup_frame(); LLFontGL::loadDefaultFonts(); } @@ -3777,14 +3799,14 @@ bool process_login_success_response() { // We got an answer from the grid -> use that for map for the current session gSavedSettings.setString("CurrentMapServerURL", map_server_url); - LL_INFOS("LLStartup") << "map-server-url : we got an answer from the grid : " << map_server_url << LL_ENDL; + LL_INFOS("LLStartUp") << "map-server-url : we got an answer from the grid : " << map_server_url << LL_ENDL; } else { // No answer from the grid -> use the default setting for current session map_server_url = gSavedSettings.getString("MapServerURL"); gSavedSettings.setString("CurrentMapServerURL", map_server_url); - LL_INFOS("LLStartup") << "map-server-url : no map-server-url answer, we use the default setting for the map : " << map_server_url << LL_ENDL; + LL_INFOS("LLStartUp") << "map-server-url : no map-server-url answer, we use the default setting for the map : " << map_server_url << LL_ENDL; } // Default male and female avatars allowing the user to choose their avatar on first login. diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 51991c1261..40312b7f4e 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2794,7 +2794,10 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) } // attach objects that were waiting for a drawable - lazyAttach(); + if (!mPendingAttachment.empty()) + { + lazyAttach(); + } // animate the character // store off last frame's root position to be consistent with camera position -- cgit v1.3