summaryrefslogtreecommitdiff
path: root/indra/newview/llavatarrenderinfoaccountant.cpp
diff options
context:
space:
mode:
authorOz Linden <oz@lindenlab.com>2016-04-04 15:53:09 -0400
committerOz Linden <oz@lindenlab.com>2016-04-04 15:53:09 -0400
commit9be58e915a6c69de280ccabd3019e9ac40beed26 (patch)
treead6f8f1f754a865afb761d0f17744cc7e1ef8b74 /indra/newview/llavatarrenderinfoaccountant.cpp
parentab46c9226bd9048fa218f54bc8668594401529e7 (diff)
parent18928ea6c6f2830a0d45ec412c915eceff1b76b0 (diff)
merge with 4.0.3-release
Diffstat (limited to 'indra/newview/llavatarrenderinfoaccountant.cpp')
-rw-r--r--indra/newview/llavatarrenderinfoaccountant.cpp533
1 files changed, 244 insertions, 289 deletions
diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp
index 2760a97bda..2be3e8546f 100644
--- a/indra/newview/llavatarrenderinfoaccountant.cpp
+++ b/indra/newview/llavatarrenderinfoaccountant.cpp
@@ -28,17 +28,14 @@
// Precompiled header
#include "llviewerprecompiledheaders.h"
+// associated header
+#include "llavatarrenderinfoaccountant.h"
+#include "llavatarrendernotifier.h"
// STL headers
// std headers
// external library headers
// other Linden headers
#include "llcharacter.h"
-#include "httprequest.h"
-#include "httphandler.h"
-#include "httpresponse.h"
-#include "llcorehttputil.h"
-#include "llappcorehttp.h"
-#include "llavatarrendernotifier.h"
#include "lltimer.h"
#include "llviewercontrol.h"
#include "llviewermenu.h"
@@ -46,9 +43,10 @@
#include "llviewerregion.h"
#include "llvoavatar.h"
#include "llworld.h"
-// associated header
-#include "llavatarrenderinfoaccountant.h"
-
+#include "llhttpsdhandler.h"
+#include "httpheaders.h"
+#include "httpoptions.h"
+#include "llcorehttputil.h"
static const std::string KEY_AGENTS = "agents"; // map
static const std::string KEY_WEIGHT = "weight"; // integer
@@ -60,329 +58,286 @@ static const std::string KEY_IDENTIFIER = "identifier";
static const std::string KEY_MESSAGE = "message";
static const std::string KEY_ERROR = "error";
-
static const F32 SECS_BETWEEN_REGION_SCANS = 5.f; // Scan the region list every 5 seconds
static const F32 SECS_BETWEEN_REGION_REQUEST = 15.0; // Look for new avs every 15 seconds
static const F32 SECS_BETWEEN_REGION_REPORTS = 60.0; // Update each region every 60 seconds
-// The policy class for HTTP traffic; this is the right value for all capability requests.
-static LLCore::HttpRequest::policy_t http_policy(LLAppCoreHttp::AP_REPORTING);
-
-// Priority for HTTP requests. Use 0U.
-static LLCore::HttpRequest::priority_t http_priority(0U);
-
+//=========================================================================
LLAvatarRenderInfoAccountant::LLAvatarRenderInfoAccountant()
- : mHttpRequest(new LLCore::HttpRequest)
- , mHttpHeaders(new LLCore::HttpHeaders)
- , mHttpOptions(new LLCore::HttpOptions)
{
- mHttpOptions->setTransferTimeout(SECS_BETWEEN_REGION_SCANS);
-
- mHttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
- mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML);
}
LLAvatarRenderInfoAccountant::~LLAvatarRenderInfoAccountant()
{
- mHttpOptions->release();
- mHttpHeaders->release();
- // delete mHttpRequest; ???
}
-// HTTP responder class for GET request for avatar render weight information
-class LLAvatarRenderInfoGetHandler : public LLCore::HttpHandler
+
+void LLAvatarRenderInfoAccountant::avatarRenderInfoGetCoro(std::string url, U64 regionHandle)
{
-private:
- LOG_CLASS(LLAvatarRenderInfoGetHandler);
-
-public:
- LLAvatarRenderInfoGetHandler() : LLCore::HttpHandler()
- {
- }
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("AvatarRenderInfoAccountant", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+
+ LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+ if (!regionp)
+ {
+ LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render weight info received but region not found for "
+ << regionHandle << LL_ENDL;
+ return;
+ }
+
+ regionp->getRenderInfoRequestTimer().resetWithExpiry(SECS_BETWEEN_REGION_REQUEST);
+
+ LLSD httpResults = result["http_result"];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ LL_WARNS("AvatarRenderInfoAccountant") << "HTTP status, " << status.toTerseString() << LL_ENDL;
+ return;
+ }
+
+ if (result.has(KEY_AGENTS))
+ {
+ const LLSD & avatar_render_info = result[KEY_AGENTS];
+ if (avatar_render_info.isMap())
+ {
+ if ( avatar_render_info.has(KEY_REPORTING_COMPLEXITY_LIMIT)
+ && avatar_render_info.has(KEY_OVER_COMPLEXITY_LIMIT))
+ {
+ U32 reporting = avatar_render_info[KEY_REPORTING_COMPLEXITY_LIMIT].asInteger();
+ U32 overlimit = avatar_render_info[KEY_OVER_COMPLEXITY_LIMIT].asInteger();
- void onCompleted(LLCore::HttpHandle handle,
- LLCore::HttpResponse* response)
- {
- LLCore::HttpStatus status = response->getStatus();
- if (status)
+ LL_DEBUGS("AvatarRenderInfo") << "complexity limit: "<<reporting<<" reporting, "<<overlimit<<" over limit"<<LL_ENDL;
+
+ LLAvatarRenderNotifier::getInstance()->updateNotificationRegion(reporting, overlimit);
+ }
+
+ if (avatar_render_info.has(KEY_AGENTS))
{
- LL_DEBUGS("AvatarRenderInfo") << "response"<<LL_ENDL;
- LLSD avatar_render_info;
- if (LLCoreHttpUtil::responseToLLSD(response, false /* quiet logging */,
- avatar_render_info))
- {
- if (avatar_render_info.isMap())
- {
- if ( avatar_render_info.has(KEY_REPORTING_COMPLEXITY_LIMIT)
- && avatar_render_info.has(KEY_OVER_COMPLEXITY_LIMIT))
- {
- U32 reporting = avatar_render_info[KEY_REPORTING_COMPLEXITY_LIMIT].asInteger();
- U32 overlimit = avatar_render_info[KEY_OVER_COMPLEXITY_LIMIT].asInteger();
-
- LL_DEBUGS("AvatarRenderInfo") << "complexity limit: "<<reporting<<" reporting, "<<overlimit<<" over limit"<<LL_ENDL;
-
- LLAvatarRenderNotifier::getInstance()->updateNotificationRegion(reporting, overlimit);
+ const LLSD & agents = avatar_render_info[KEY_AGENTS];
+ if (agents.isMap())
+ {
+ for (LLSD::map_const_iterator agent_iter = agents.beginMap();
+ agent_iter != agents.endMap();
+ agent_iter++
+ )
+ {
+ LLUUID target_agent_id = LLUUID(agent_iter->first);
+ LLViewerObject* avatarp = gObjectList.findObject(target_agent_id);
+ if (avatarp && avatarp->isAvatar())
+ {
+ const LLSD & agent_info_map = agent_iter->second;
+ if (agent_info_map.isMap())
+ {
+ LL_DEBUGS("AvatarRenderInfo") << " Agent " << target_agent_id
+ << ": " << agent_info_map << LL_ENDL;
+
+ if (agent_info_map.has(KEY_WEIGHT))
+ {
+ ((LLVOAvatar *) avatarp)->setReportedVisualComplexity(agent_info_map[KEY_WEIGHT].asInteger());
+ }
+ }
+ else
+ {
+ LL_WARNS("AvatarRenderInfo") << "agent entry invalid"
+ << " agent " << target_agent_id
+ << " map " << agent_info_map
+ << LL_ENDL;
+ }
}
-
- if (avatar_render_info.has(KEY_AGENTS))
- {
- const LLSD & agents = avatar_render_info[KEY_AGENTS];
- if (agents.isMap())
- {
- for (LLSD::map_const_iterator agent_iter = agents.beginMap();
- agent_iter != agents.endMap();
- agent_iter++
- )
- {
- LLUUID target_agent_id = LLUUID(agent_iter->first);
- LLViewerObject* avatarp = gObjectList.findObject(target_agent_id);
- if (avatarp && avatarp->isAvatar())
- {
- const LLSD & agent_info_map = agent_iter->second;
- if (agent_info_map.isMap())
- {
- LL_DEBUGS("AvatarRenderInfo") << " Agent " << target_agent_id
- << ": " << agent_info_map << LL_ENDL;
-
- if (agent_info_map.has(KEY_WEIGHT))
- {
- ((LLVOAvatar *) avatarp)->setReportedVisualComplexity(agent_info_map[KEY_WEIGHT].asInteger());
- }
- }
- else
- {
- LL_WARNS("AvatarRenderInfo") << "agent entry invalid"
- << " agent " << target_agent_id
- << " map " << agent_info_map
- << LL_ENDL;
- }
- }
- else
- {
- LL_DEBUGS("AvatarRenderInfo") << "Unknown agent " << target_agent_id << LL_ENDL;
- }
- } // for agent_iter
- }
- else
- {
- LL_WARNS("AvatarRenderInfo") << "malformed get response agents avatar_render_info is not map" << LL_ENDL;
- }
- } // has "agents"
- else if (avatar_render_info.has(KEY_ERROR))
- {
- const LLSD & error = avatar_render_info[KEY_ERROR];
- LL_WARNS("AvatarRenderInfo") << "Avatar render info GET error: "
- << error[KEY_IDENTIFIER]
- << ": " << error[KEY_MESSAGE]
- << LL_ENDL;
- }
- else
- {
- LL_WARNS("AvatarRenderInfo") << "no agent key in get response" << LL_ENDL;
- }
- }
- else
- {
- LL_WARNS("AvatarRenderInfo") << "malformed get response is not map" << LL_ENDL;
- }
+ else
+ {
+ LL_DEBUGS("AvatarRenderInfo") << "Unknown agent " << target_agent_id << LL_ENDL;
+ }
+ } // for agent_iter
}
- else
- {
- LL_WARNS("AvatarRenderInfo") << "malformed get response parse failure" << LL_ENDL;
- }
+ else
+ {
+ LL_WARNS("AvatarRenderInfo") << "malformed get response agents avatar_render_info is not map" << LL_ENDL;
+ }
+ } // has "agents"
+ else if (avatar_render_info.has(KEY_ERROR))
+ {
+ const LLSD & error = avatar_render_info[KEY_ERROR];
+ LL_WARNS("AvatarRenderInfo") << "Avatar render info GET error: "
+ << error[KEY_IDENTIFIER]
+ << ": " << error[KEY_MESSAGE]
+ << LL_ENDL;
}
else
{
- // Something went wrong. Translate the status to
- // a meaningful message.
- LL_WARNS("AvatarRenderInfo") << "GET failed Status: "
- << status.toTerseString()
- << ", Reason: " << status.toString()
- << LL_ENDL;
- }
-
- delete this; // release the handler object
- }
-};
+ LL_WARNS("AvatarRenderInfo") << "no agent key in get response" << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_WARNS("AvatarRenderInfo") << "malformed get response is not map" << LL_ENDL;
+ }
+ } // has "agents"
+ else if (result.has(KEY_ERROR))
+ {
+ const LLSD & error = result[KEY_ERROR];
+ LL_WARNS() << "Avatar render info GET error: "
+ << error[KEY_IDENTIFIER]
+ << ": " << error[KEY_MESSAGE]
+ << " from region " << regionp->getName()
+ << LL_ENDL;
+ }
+}
-// HTTP responder class for POST request for avatar render weight information
-class LLAvatarRenderInfoPostHandler : public LLCore::HttpHandler
+//-------------------------------------------------------------------------
+void LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro(std::string url, U64 regionHandle)
{
- private:
- LOG_CLASS(LLAvatarRenderInfoPostHandler);
-
- public:
- LLAvatarRenderInfoPostHandler() : LLCore::HttpHandler()
- {
- }
-
- void onCompleted(LLCore::HttpHandle handle,
- LLCore::HttpResponse* response)
- {
- LLCore::HttpStatus status = response->getStatus();
- if (status)
- {
- LL_DEBUGS("AvatarRenderInfo") << "post succeeded" << LL_ENDL;
- }
- else
- {
- // Something went wrong. Translate the status to
- // a meaningful message.
- LL_WARNS("AvatarRenderInfo") << "POST failed Status: "
- << status.toTerseString()
- << ", Reason: " << status.toString()
- << LL_ENDL;
- }
-
- delete this; // release the handler object
- }
-};
-
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("AvatarRenderInfoAccountant", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+ LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+ if (!regionp)
+ {
+ LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render weight calculation but region not found for "
+ << regionHandle << LL_ENDL;
+ return;
+ }
+
+ LL_DEBUGS("AvatarRenderInfoAccountant")
+ << "Sending avatar render info for region " << regionp->getName()
+ << " to " << url << LL_ENDL;
+
+ U32 num_avs = 0;
+ // Build the render info to POST to the region
+ LLSD agents = LLSD::emptyMap();
+
+ std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+ while( iter != LLCharacter::sInstances.end() )
+ {
+ LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*iter);
+ if (avatar &&
+ avatar->getRezzedStatus() >= 2 && // Mostly rezzed (maybe without baked textures downloaded)
+ !avatar->isDead() && // Not dead yet
+ avatar->getObjectHost() == regionp->getHost()) // Ensure it's on the same region
+ {
+ avatar->calculateUpdateRenderComplexity(); // Make sure the numbers are up-to-date
+
+ LLSD info = LLSD::emptyMap();
+ U32 avatar_complexity = avatar->getVisualComplexity();
+ if (avatar_complexity > 0)
+ {
+ // the weight/complexity is unsigned, but LLSD only stores signed integers,
+ // so if it's over that (which would be ridiculously high), just store the maximum signed int value
+ info[KEY_WEIGHT] = (S32)(avatar_complexity < S32_MAX ? avatar_complexity : S32_MAX);
+ info[KEY_TOO_COMPLEX] = LLSD::Boolean(avatar->isTooComplex());
+ agents[avatar->getID().asString()] = info;
+
+ LL_DEBUGS("AvatarRenderInfo") << "Sending avatar render info for " << avatar->getID()
+ << ": " << info << LL_ENDL;
+ num_avs++;
+ }
+ }
+ iter++;
+ }
+
+ // Reset this regions timer, moving to longer intervals if there are lots of avatars around
+ regionp->getRenderInfoReportTimer().resetWithExpiry(SECS_BETWEEN_REGION_REPORTS + (2.f * num_avs));
+
+ if (num_avs == 0)
+ return; // nothing to report
+
+ LLSD report = LLSD::emptyMap();
+ report[KEY_AGENTS] = agents;
+
+ regionp = NULL;
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, report);
+
+ regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+ if (!regionp)
+ {
+ LL_INFOS("AvatarRenderInfoAccountant") << "Avatar render weight POST result received but region not found for "
+ << regionHandle << LL_ENDL;
+ return;
+ }
+
+ LLSD httpResults = result["http_result"];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+ if (!status)
+ {
+ LL_WARNS("AvatarRenderInfoAccountant") << "HTTP status, " << status.toTerseString() << LL_ENDL;
+ return;
+ }
+
+ if (result.isMap())
+ {
+ if (result.has(KEY_ERROR))
+ {
+ const LLSD & error = result[KEY_ERROR];
+ LL_WARNS("AvatarRenderInfoAccountant") << "POST error: "
+ << error[KEY_IDENTIFIER]
+ << ": " << error[KEY_MESSAGE]
+ << " from region " << regionp->getName()
+ << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS("AvatarRenderInfoAccountant")
+ << "POST result for region " << regionp->getName()
+ << ": " << result
+ << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_WARNS("AvatarRenderInfoAccountant") << "Malformed POST response from region '" << regionp->getName()
+ << LL_ENDL;
+ }
+}
// Send request for avatar weights in one region
// called when the mRenderInfoScanTimer expires (forced when entering a new region)
void LLAvatarRenderInfoAccountant::sendRenderInfoToRegion(LLViewerRegion * regionp)
{
- if ( regionp->getRenderInfoReportTimer().hasExpired() ) // Time to make request
+ std::string url = regionp->getCapability("AvatarRenderInfo");
+ if ( !url.empty() // we have the capability
+ && regionp->getRenderInfoReportTimer().hasExpired() // Time to make request)
+ )
{
- U32 num_avs = 0;
-
- std::string url = regionp->getCapability("AvatarRenderInfo");
- if (!url.empty())
- {
- // Build the render info to POST to the region
- LLSD agents = LLSD::emptyMap();
-
- std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- while( iter != LLCharacter::sInstances.end() )
- {
- LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*iter);
- if (avatar &&
- avatar->getRezzedStatus() >= 2 && // Mostly rezzed (maybe without baked textures downloaded)
- !avatar->isDead() && // Not dead yet
- avatar->getObjectHost() == regionp->getHost()) // Ensure it's on the same region
- {
- avatar->calculateUpdateRenderComplexity(); // Make sure the numbers are up-to-date
-
- LLSD info = LLSD::emptyMap();
- U32 avatar_complexity = avatar->getVisualComplexity();
- if (avatar_complexity > 0)
- {
- // the weight/complexity is unsigned, but LLSD only stores signed integers,
- // so if it's over that (which would be ridiculously high), just store the maximum signed int value
- info[KEY_WEIGHT] = (S32)(avatar_complexity < S32_MAX ? avatar_complexity : S32_MAX);
- info[KEY_TOO_COMPLEX] = LLSD::Boolean(avatar->isTooComplex());
- agents[avatar->getID().asString()] = info;
-
- LL_DEBUGS("AvatarRenderInfo") << "Sending avatar render info for " << avatar->getID()
- << ": " << info << LL_ENDL;
- num_avs++;
- }
- }
- iter++;
- }
-
- if (num_avs > 0)
- {
- LLSD report = LLSD::emptyMap();
- report[KEY_AGENTS] = agents;
-
- LLCore::HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
- LLAvatarRenderInfoPostHandler* handler = new LLAvatarRenderInfoPostHandler;
-
- handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest,
- http_policy,
- http_priority,
- url,
- report,
- mHttpOptions,
- mHttpHeaders,
- handler);
- if (LLCORE_HTTP_HANDLE_INVALID == handle)
- {
- LLCore::HttpStatus status(mHttpRequest->getStatus());
- LL_WARNS("AvatarRenderInfo") << "HTTP POST request failed"
- << " Status: " << status.toTerseString()
- << " Reason: '" << status.toString() << "'"
- << LL_ENDL;
- delete handler;
- }
- else
- {
- LL_DEBUGS("AvatarRenderInfo") << "Sent render costs for " << num_avs
- << " avatars to region " << regionp->getName()
- << LL_ENDL;
-
-
- }
- }
- else
- {
- LL_DEBUGS("AvatarRenderInfo") << "no agent info to send" << LL_ENDL;
- }
- }
- else
- {
- LL_WARNS("AvatarRenderInfo") << "AvatarRenderInfo cap is empty" << LL_ENDL;
- }
-
- // Reset this regions timer, moving to longer intervals if there are lots of avatars around
- regionp->getRenderInfoReportTimer().resetWithExpiry(SECS_BETWEEN_REGION_REPORTS + (2.f * num_avs));
+ std::string coroname =
+ LLCoros::instance().launch("LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro",
+ boost::bind(&LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro, url, regionp->getHandle()));
}
}
-
-
-
-// static
-// Send request for one region, no timer checks
+// Send request for avatar weights in one region
+// called when the mRenderInfoScanTimer expires (forced when entering a new region)
void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regionp)
{
- if (regionp->getRenderInfoRequestTimer().hasExpired())
+ std::string url = regionp->getCapability("AvatarRenderInfo");
+ if ( !url.empty()
+ && regionp->getRenderInfoRequestTimer().hasExpired()
+ )
{
- std::string url = regionp->getCapability("AvatarRenderInfo");
- if (!url.empty())
- {
-
- LLAvatarRenderInfoGetHandler* handler = new LLAvatarRenderInfoGetHandler;
- // First send a request to get the latest data
- LLCore::HttpHandle handle = mHttpRequest->requestGet(http_policy,
- http_priority,
- url,
- NULL,
- NULL,
- handler);
- if (LLCORE_HTTP_HANDLE_INVALID != handle)
- {
- LL_DEBUGS("AvatarRenderInfo") << "Requested avatar render info for region "
- << regionp->getName()
- << LL_ENDL;
- }
- else
- {
- LL_WARNS("AvatarRenderInfo") << "Failed to launch HTTP GET request. Try again."
- << LL_ENDL;
- delete handler;
- }
- }
- else
- {
- LL_WARNS("AvatarRenderInfo") << "no AvatarRenderInfo cap for " << regionp->getName() << LL_ENDL;
- }
-
- regionp->getRenderInfoRequestTimer().resetWithExpiry(SECS_BETWEEN_REGION_REQUEST);
+ LL_DEBUGS("AvatarRenderInfo")
+ << "Requesting avatar render info for region " << regionp->getName()
+ << " from " << url
+ << LL_ENDL;
+
+ // First send a request to get the latest data
+ std::string coroname =
+ LLCoros::instance().launch("LLAvatarRenderInfoAccountant::avatarRenderInfoGetCoro",
+ boost::bind(&LLAvatarRenderInfoAccountant::avatarRenderInfoGetCoro, url, regionp->getHandle()));
}
}
-
// static
// Called every frame - send render weight requests to every region
void LLAvatarRenderInfoAccountant::idle()
{
- mHttpRequest->update(0); // give any pending http operations a chance to call completion methods
-
if (mRenderInfoScanTimer.hasExpired())
{
LL_DEBUGS("AvatarRenderInfo") << "Scanning regions for render info updates"