diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index c4eaa57c2c2e38677dd6e2985788260268df3bc4..4f8b29e298279f9840e8598b06d55116f0522c42 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -122,6 +122,8 @@ LLViewerParcelMgr::LLViewerParcelMgr()
 	mHoverWestSouth(),
 	mHoverEastNorth(),
 	mTeleportInProgressPosition(),
+	mCollisionRegionHandle(0),
+	mCollisionUpdateSignal(nullptr),
 	mRenderCollision(FALSE),
 	mRenderSelection(TRUE),
 	mCollisionBanned(0),
@@ -137,10 +139,13 @@ LLViewerParcelMgr::LLViewerParcelMgr()
 	mHoverParcel = new LLParcel();
 	mCollisionParcel = new LLParcel();
 
-	mParcelsPerEdge = S32(	REGION_WIDTH_METERS / PARCEL_GRID_STEP_METERS );
+	mParcelsPerEdge = S32(8192.f / PARCEL_GRID_STEP_METERS); // 8192 is the maximum region size on Aurora
 	mHighlightSegments = new U8[(mParcelsPerEdge+1)*(mParcelsPerEdge+1)];
 	resetSegments(mHighlightSegments);
 
+	mCollisionBitmap = new U8[getCollisionBitmapSize()];
+	memset(mCollisionBitmap, 0, getCollisionBitmapSize());
+
 	mCollisionSegments = new U8[(mParcelsPerEdge+1)*(mParcelsPerEdge+1)];
 	resetSegments(mCollisionSegments);
 
@@ -160,12 +165,24 @@ LLViewerParcelMgr::LLViewerParcelMgr()
 		mAgentParcelOverlay[i] = 0;
 	}
 
+	mParcelsPerEdge = S32(REGION_WIDTH_METERS / PARCEL_GRID_STEP_METERS);
 	mTeleportInProgress = TRUE; // the initial parcel update is treated like teleport
 }
 
+void LLViewerParcelMgr::init(F32 region_size)
+{
+	mParcelsPerEdge = S32(region_size / PARCEL_GRID_STEP_METERS);
+}
 
 LLViewerParcelMgr::~LLViewerParcelMgr()
 {
+	if (mCollisionUpdateSignal)
+	{
+		mCollisionUpdateSignal->disconnect_all_slots();
+		delete mCollisionUpdateSignal;
+		mCollisionUpdateSignal = nullptr;
+	}
+
 	mCurrentParcelSelection->setParcel(NULL);
 	mCurrentParcelSelection = NULL;
 
@@ -187,6 +204,9 @@ LLViewerParcelMgr::~LLViewerParcelMgr()
 	delete[] mHighlightSegments;
 	mHighlightSegments = NULL;
 
+	delete[] mCollisionBitmap;
+	mCollisionBitmap = NULL;
+
 	delete[] mCollisionSegments;
 	mCollisionSegments = NULL;
 
@@ -899,7 +919,8 @@ void LLViewerParcelMgr::renderParcelCollision()
 		mRenderCollision = FALSE;
 	}
 
-	if (mRenderCollision && gSavedSettings.getBOOL("ShowBanLines"))
+	static LLCachedControl<bool> render_ban_line(gSavedSettings, "ShowBanLines");
+	if (mRenderCollision && render_ban_line)
 	{
 		LLViewerRegion* regionp = gAgent.getRegion();
 		if (regionp)
@@ -1490,8 +1511,7 @@ void LLViewerParcelMgr::processParcelOverlay(LLMessageSystem *msg, void **user)
 		return;
 	}
 
-	S32 parcels_per_edge = LLViewerParcelMgr::getInstance()->mParcelsPerEdge;
-	S32 expected_size = parcels_per_edge * parcels_per_edge / PARCEL_OVERLAY_CHUNKS;
+	S32 expected_size = 1024;
 	if (packed_overlay_size != expected_size)
 	{
 		LL_WARNS() << "Got parcel overlay size " << packed_overlay_size
@@ -1558,6 +1578,11 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
     S32		other_clean_time = 0;
 
     LLViewerParcelMgr& parcel_mgr = LLViewerParcelMgr::instance();
+    LLViewerRegion* msg_region = LLWorld::getInstance()->getRegion(msg->getSender());
+    if(msg_region)
+        parcel_mgr.mParcelsPerEdge = S32(msg_region->getWidth() / PARCEL_GRID_STEP_METERS);
+    else
+        parcel_mgr.mParcelsPerEdge = S32(gAgent.getRegion()->getWidth() / PARCEL_GRID_STEP_METERS);
 
     msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_RequestResult, request_result);
     msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_SequenceID, sequence_id);
@@ -1853,18 +1878,16 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
 
 		}
 
-		S32 bitmap_size =	parcel_mgr.mParcelsPerEdge
-							* parcel_mgr.mParcelsPerEdge
-							/ 8;
-		U8* bitmap = new U8[ bitmap_size ];
-		msg->getBinaryDataFast(_PREHASH_ParcelData, _PREHASH_Bitmap, bitmap, bitmap_size);
+		msg->getBinaryDataFast(_PREHASH_ParcelData, _PREHASH_Bitmap, parcel_mgr.mCollisionBitmap, parcel_mgr.getCollisionBitmapSize());
 
 		parcel_mgr.resetSegments(parcel_mgr.mCollisionSegments);
-		parcel_mgr.writeSegmentsFromBitmap( bitmap, parcel_mgr.mCollisionSegments );
+		parcel_mgr.writeSegmentsFromBitmap(parcel_mgr.mCollisionBitmap, parcel_mgr.mCollisionSegments);
 
-		delete[] bitmap;
-		bitmap = NULL;
+		LLViewerRegion* pRegion = LLWorld::getInstance()->getRegion(msg->getSender());
+		parcel_mgr.mCollisionRegionHandle = (pRegion) ? pRegion->getHandle() : 0;
 
+		if (parcel_mgr.mCollisionUpdateSignal)
+			(*parcel_mgr.mCollisionUpdateSignal)(pRegion);
 	}
 	else if (sequence_id == HOVERED_PARCEL_SEQ_ID)
 	{
@@ -2691,6 +2714,13 @@ bool  LLViewerParcelMgr::getTeleportInProgress()
         || gAgent.getTeleportState() > LLAgent::TELEPORT_NONE; // For LOCAL, no mTeleportInProgress
 }
 
+boost::signals2::connection LLViewerParcelMgr::setCollisionUpdateCallback(const collision_update_signal_t::slot_type& cb)
+{
+	if (!mCollisionUpdateSignal)
+		mCollisionUpdateSignal = new collision_update_signal_t();
+	return mCollisionUpdateSignal->connect(cb); 
+}
+
 // [SL:KB] - Patch: Appearance-TeleportAttachKill | Checked: Catznip-4.0
 void LLViewerParcelMgr::onTeleportDone()
 {
diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index 0260aabbed0ccaea613db0b7ad83972bbded70d8..e93a80d3ad3aa3c4ca1078f981f155ad4c7e63ab 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -73,7 +73,7 @@ class LLParcelObserver
 	virtual void changed() = 0;
 };
 
-class LLViewerParcelMgr : public LLSingleton<LLViewerParcelMgr>
+class LLViewerParcelMgr final : public LLSingleton<LLViewerParcelMgr>
 {
 	LLSINGLETON(LLViewerParcelMgr);
 	~LLViewerParcelMgr();
@@ -88,6 +88,7 @@ class LLViewerParcelMgr : public LLSingleton<LLViewerParcelMgr>
 	typedef boost::signals2::signal<void()> teleport_done_signal_t;
 // [/SL:KB]
 
+	void init(F32 region_size);
 	static void cleanupGlobals();
 
 	BOOL	selectionEmpty() const;
@@ -167,6 +168,13 @@ class LLViewerParcelMgr : public LLSingleton<LLViewerParcelMgr>
 
 	LLParcel*	getCollisionParcel() const;
 
+	const U8*	getCollisionBitmap() const { return mCollisionBitmap; }
+	size_t		getCollisionBitmapSize() const { return mParcelsPerEdge * mParcelsPerEdge / 8; }
+	U64			getCollisionRegionHandle() const { return mCollisionRegionHandle; }
+ 
+	typedef boost::signals2::signal<void (const LLViewerRegion*)> collision_update_signal_t;
+	boost::signals2::connection setCollisionUpdateCallback(const collision_update_signal_t::slot_type & cb);
+
 	// Can this agent build on the parcel he is on?
 	// Used for parcel property icons in nav bar.
 	bool	allowAgentBuild() const;
@@ -373,6 +381,9 @@ class LLViewerParcelMgr : public LLSingleton<LLViewerParcelMgr>
 	// Watch for pending collisions with a parcel you can't access.
 	// If it's coming, draw the parcel's boundaries.
 	LLParcel*					mCollisionParcel;
+	U8*							mCollisionBitmap;
+	U64							mCollisionRegionHandle;
+	collision_update_signal_t*	mCollisionUpdateSignal;
 	U8*							mCollisionSegments;
 	BOOL						mRenderCollision; 
 	BOOL						mRenderSelection;
diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp
index 89124ff207faaf53069556f783ba813668f941fc..922e0df8feb432b1702bddc7db5da26a6a4ea6cb 100644
--- a/indra/newview/llviewerparceloverlay.cpp
+++ b/indra/newview/llviewerparceloverlay.cpp
@@ -52,15 +52,18 @@
 
 const U8  OVERLAY_IMG_COMPONENTS = 4;
 
+LLViewerParcelOverlay::update_signal_t* LLViewerParcelOverlay::mUpdateSignal = NULL;
+
 LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_width_meters)
 :	mRegion( region ),
 	mParcelGridsPerEdge( S32( region_width_meters / PARCEL_GRID_STEP_METERS ) ),
+	mRegionSize(S32(region_width_meters)),
 	mDirty( FALSE ),
 	mTimeSinceLastUpdate(),
 	mOverlayTextureIdx(-1),
 	mVertexCount(0),
-	mVertexArray(NULL),
-	mColorArray(NULL)
+	mVertexArray(nullptr),
+	mColorArray(nullptr)
 //	mTexCoordArray(NULL),
 {
 	// Create a texture to hold color information.
@@ -81,7 +84,7 @@ LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_
 	{
 		raw[i] = 0;
 	}
-	//mTexture->setSubImage(mImageRaw, 0, 0, mParcelGridsPerEdge, mParcelGridsPerEdge);
+	mTexture->setSubImage(mImageRaw, 0, 0, mParcelGridsPerEdge, mParcelGridsPerEdge);
 
 	// Create storage for ownership information from simulator
 	// and initialize it.
@@ -97,6 +100,13 @@ LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_
 
 LLViewerParcelOverlay::~LLViewerParcelOverlay()
 {
+	if (mUpdateSignal)
+	{
+		mUpdateSignal->disconnect_all_slots();
+		delete mUpdateSignal;
+		mUpdateSignal = nullptr;
+	}
+
 	delete[] mOwnership;
 	mOwnership = NULL;
 
@@ -426,7 +436,8 @@ void LLViewerParcelOverlay::uncompressLandOverlay(S32 chunk, U8 *packed_overlay)
 {
 	// Unpack the message data into the ownership array
 	S32	size	= mParcelGridsPerEdge * mParcelGridsPerEdge;
-	S32 chunk_size = size / PARCEL_OVERLAY_CHUNKS;
+	S32 mParcelOverLayChunks = mRegionSize * mRegionSize / (128 * 128);
+	S32 chunk_size = size / mParcelOverLayChunks;
 
 	memcpy(mOwnership + chunk*chunk_size, packed_overlay, chunk_size);		/*Flawfinder: ignore*/
 
@@ -870,6 +881,8 @@ void LLViewerParcelOverlay::idleUpdate(bool force_update)
 		{
 			updateOverlayTexture();
 			updatePropertyLines();
+			if (mUpdateSignal)
+				(*mUpdateSignal)(mRegion);
 			mTimeSinceLastUpdate.reset();
 		}
 	}
@@ -1019,3 +1032,10 @@ S32 LLViewerParcelOverlay::renderPropertyLines	()
 
 	return drawn;
 }
+
+boost::signals2::connection LLViewerParcelOverlay::setUpdateCallback(const update_signal_t::slot_type& cb)
+{
+	if (!mUpdateSignal)
+		mUpdateSignal = new update_signal_t();
+	return mUpdateSignal->connect(cb); 
+}
diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h
index e30dbf17b3ee01ce867e4979f2c324e1dc7ab2fc..922548744bf0df2b6be88ab43b0bf5b480a16665 100644
--- a/indra/newview/llviewerparceloverlay.h
+++ b/indra/newview/llviewerparceloverlay.h
@@ -41,7 +41,7 @@ class LLVector3;
 class LLColor4U;
 class LLVector2;
 
-class LLViewerParcelOverlay : public LLGLUpdate
+class LLViewerParcelOverlay final : public LLGLUpdate
 {
 public:
 	LLViewerParcelOverlay(LLViewerRegion* region, F32 region_width_meters);
@@ -66,6 +66,7 @@ class LLViewerParcelOverlay : public LLGLUpdate
 
 	BOOL			isBuildCameraAllowed(const LLVector3& pos) const;
 	F32				getOwnedRatio() const;
+	const U8*		getOwnership() const { return mOwnership; }
 
 	// Returns the number of vertices drawn
 	S32				renderPropertyLines();
@@ -81,7 +82,10 @@ class LLViewerParcelOverlay : public LLGLUpdate
 	void	setDirty();
 
 	void	idleUpdate(bool update_now = false);
-	void	updateGL();
+	void	updateGL() override;
+
+	typedef boost::signals2::signal<void (const LLViewerRegion*)> update_signal_t;
+	static boost::signals2::connection setUpdateCallback(const update_signal_t::slot_type & cb);
 
 private:
 	// This is in parcel rows and columns, not grid rows and columns
@@ -104,6 +108,7 @@ class LLViewerParcelOverlay : public LLGLUpdate
 	LLViewerRegion*	mRegion;
 
 	S32				mParcelGridsPerEdge;
+	S32				mRegionSize;
 
 	LLPointer<LLViewerTexture> mTexture;
 	LLPointer<LLImageRaw> mImageRaw;
@@ -121,6 +126,8 @@ class LLViewerParcelOverlay : public LLGLUpdate
 	S32				mVertexCount;
 	F32*			mVertexArray;
 	U8*				mColorArray;
+
+	static update_signal_t* mUpdateSignal;
 };
 
 #endif
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 54fe1cdf23f6dd2060d26e0007823587eaf511bd..60c616e9209833f7ee1bf75a495c7250572b9ad6 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -81,6 +81,7 @@
 #include "llcorehttputil.h"
 #include "llcallstack.h"
 #include "llsettingsdaycycle.h"
+#include "llviewerparcelmgr.h"
 
 #ifdef LL_WINDOWS
 	#pragma warning(disable:4355)
@@ -590,7 +591,8 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
 					mImpl->mOriginGlobal,
 					mWidth);
 
-	mParcelOverlay = new LLViewerParcelOverlay(this, region_width_meters);
+	mParcelOverlay = new LLViewerParcelOverlay(this, mWidth);
+	LLViewerParcelMgr::getInstance()->init(mWidth);
 
 	setOriginGlobal(from_region_handle(handle));
 	calculateCenterGlobal();