Commits

Scott Lawrence  committed f7ff29e Merge

DRTVWR-139: merge back 3.3.1-beta2 fixes

  • Participants
  • Parent commits c623bbc, b2f9214

Comments (0)

Files changed (436)

 glob:indra/newview/avatar_icons_cache.txt
 glob:indra/newview/avatar_lad.log
 glob:*.diff
+*.rej
 a01ef9bed28627f4ca543fbc1d70c79cc297a90f DRTVWR-118_3.2.9-beta2
 a01ef9bed28627f4ca543fbc1d70c79cc297a90f 3.2.9-beta2
 987425b1acf4752379b2e1eb20944b4b35d67a85 3.2.8-beta2
+d5f263687f43f278107363365938f0a214920a4b DRTVWR-119
+d5f263687f43f278107363365938f0a214920a4b 3.3.0-beta1
+5e8d2662f38a66eca6c591295f5880d47afc73f7 viewer-release-candidate
+5e8d2662f38a66eca6c591295f5880d47afc73f7 3.3.0-release
 d5f263687f43f278107363365938f0a214920a4b 3.3.0-start
 dffd0457ee0745de65bf95f0642a5c9e46b8e2f0 viewer-beta-candidate
 d5f263687f43f278107363365938f0a214920a4b DRTVWR-119
 d5f263687f43f278107363365938f0a214920a4b 3.3.0-beta1
 5e8d2662f38a66eca6c591295f5880d47afc73f7 viewer-release-candidate
 5e8d2662f38a66eca6c591295f5880d47afc73f7 3.3.0-release
-dffd0457ee0745de65bf95f0642a5c9e46b8e2f0 viewer-beta-candidate
-3e2fca4ed1a0dc9fe6d8a6664e71098bb035a367 viewer-beta-candidate
-3e2fca4ed1a0dc9fe6d8a6664e71098bb035a367 viewer-beta-candidate
+28b95a6a28dca3338d9a1f4f204b96678df9f6a5 viewer-beta-candidate
+b43cd25be49e3984ff5361cefad020e069131d98 3.3.1-start
+3e2fca4ed1a0dc9fe6d8a6664e71098bb035a367 DRTVWR-125
+3e2fca4ed1a0dc9fe6d8a6664e71098bb035a367 3.3.1-start
+28b95a6a28dca3338d9a1f4f204b96678df9f6a5 3.3.1-beta1
 1dc545e44617975da2a4a32fe303386c687a6ca1 viewer-beta-candidate
 1dc545e44617975da2a4a32fe303386c687a6ca1 3.3.1-beta2
 1dc545e44617975da2a4a32fe303386c687a6ca1 DRTVWR-139
 # Notifications - to configure email notices, add a setting like this:
 # <username>_<reponame>.email = <email-address>
 
+
 # =================================================================
 # Canonical viewer integration builds - Oz Linden
 # =================================================================

File autobuild.xml

             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>26aa7c367ffadd573f61a6a96f820f80</string>
+              <string>4a98d727561cd1f4ac5ee02907411df1</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/245988/arch/Darwin/installer/llqtwebkit-4.7.1-darwin-20111201.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/250147/arch/Darwin/installer/llqtwebkit-4.7.1-darwin-20120228.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>c05a33ee8b6f253b5a744596dfc3707d</string>
+              <string>f50e5f0cc880c55b3f0f7e67dc8f7221</string>
               <key>url</key>
-              <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-linux-qt4.6-20101013.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/250147/arch/Linux/installer/llqtwebkit-4.7.1-linux-20120228.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>270db8568a0c4bab266d98e1a820aec4</string>
+              <string>5e3cd6af397e853a963a6de40d440ff4</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/245988/arch/CYGWIN/installer/llqtwebkit-4.7.1-windows-20111201.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/250147/arch/CYGWIN/installer/llqtwebkit-4.7.1-windows-20120228.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
   end_section UpdateVer
 fi
 
-# Now retrieve the version for use in the version manager
-# First three parts only, $revision will be appended automatically.
-build_viewer_update_version_manager_version=`python scripts/get_version.py --viewer-version | sed 's/\.[0-9]*$//'`
-
 if [ -z "$AUTOBUILD" ]
 then
   export autobuild_dir="$here/../../../autobuild/bin/"

File doc/contributions.txt

 Fury Rosewood
 Gaberoonie Zanzibar
 Ganymedes Costagravas
+Geenz Spad
+	STORM-1823
 Gene Frostbite
 GeneJ Composer
 Geneko Nemeth
 	STORM-1796
 	STORM-1807
 	STORM-1808
+	STORM-637
+	STORM-1822
 	STORM-1809
 	STORM-1793
 	STORM-1810
 	OPEN-1
 	STORM-1087
 	STORM-1090
+	STORM-1828
 Nicoladie Gymnast
 Nounouch Hapmouche
 	VWR-238
 UsikuFarasi Kanarik
 Vadim Bigbear
 	VWR-2681
+Vaalith Jinn
+    STORM-64
 Vector Hastings
 	VWR-8726
 Veritas Raymaker

File indra/cmake/VisualLeakDetector.cmake

+# -*- cmake -*-
+
+if (VIEWER)
+
+  set(INCLUDE_VLD_CMAKE OFF CACHE BOOL "Build the Windows viewer with Visual Leak Detector turned on or off")
+
+  if (INCLUDE_VLD_CMAKE)
+
+    if (WINDOWS)
+      add_definitions(-DINCLUDE_VLD=1)
+    endif (WINDOWS)
+
+  endif (INCLUDE_VLD_CMAKE)
+
+endif (VIEWER)

File indra/cmake/WebKitLibPlugin.cmake

         QtNetwork
         QtGui
         QtCore
-        qgif
-        qjpeg
-        jpeg
+        jscore
+#        qgif
+#        qjpeg
+#        jpeg
         fontconfig
         X11
         Xrender

File indra/edit-me-to-trigger-new-build.txt

Empty file added.

File indra/llcharacter/llcharacter.h

 
 	virtual void addDebugText( const std::string& text ) = 0;
 
-	virtual const LLUUID&	getID() = 0;
+	virtual const LLUUID&	getID() const = 0;
 	//-------------------------------------------------------------------------
 	// End Interface
 	//-------------------------------------------------------------------------

File indra/llcommon/llversionviewer.h

 
 const S32 LL_VERSION_MAJOR = 3;
 const S32 LL_VERSION_MINOR = 3;
-const S32 LL_VERSION_PATCH = 1;
+const S32 LL_VERSION_PATCH = 2;
 const S32 LL_VERSION_BUILD = 0;
 
 const char * const LL_CHANNEL = "Second Life Developer";

File indra/llimage/llimagepng.cpp

 
 	// Decode the PNG data and extract sizing information
 	LLPngWrapper pngWrapper;
+	if (!pngWrapper.isValidPng(getData()))
+	{
+		setLastError("LLImagePNG data does not have a valid PNG header!");
+		return FALSE;
+	}
+
 	LLPngWrapper::ImageInfo infop;
 	if (! pngWrapper.readPng(getData(), NULL, &infop))
 	{
 
 	// Decode the PNG data into the raw image
 	LLPngWrapper pngWrapper;
+	if (!pngWrapper.isValidPng(getData()))
+	{
+		setLastError("LLImagePNG data does not have a valid PNG header!");
+		return FALSE;
+	}
+
 	if (! pngWrapper.readPng(getData(), raw_image))
 	{
 		setLastError(pngWrapper.getErrorMessage());

File indra/llmath/llcoord.h

 #ifndef LL_LLCOORD_H
 #define LL_LLCOORD_H
 
+template<typename> class LLCoord;
+struct LL_COORD_TYPE_GL;
+struct LL_COORD_TYPE_WINDOW;
+struct LL_COORD_TYPE_SCREEN;
+
+typedef LLCoord<LL_COORD_TYPE_GL> LLCoordGL;
+typedef LLCoord<LL_COORD_TYPE_WINDOW> LLCoordWindow;
+typedef LLCoord<LL_COORD_TYPE_SCREEN> LLCoordScreen;
+
 struct LLCoordCommon
 {
 	LLCoordCommon(S32 x, S32 y) : mX(x), mY(y) {}
 
 	LLCoord():	mX(0), mY(0)
 	{}
-	LLCoord(S32 x, S32 y): mX(x), mY(y)
+	LLCoord(typename COORD_FRAME::value_t x, typename COORD_FRAME::value_t y): mX(x), mY(y)
 	{}
 
 	LLCoord(const LLCoordCommon& other)
 		return COORD_FRAME::convertToCommon();
 	}
 
-	void set(S32 x, S32 y) { mX = x; mY = y;}
+	void set(typename COORD_FRAME::value_t x, typename COORD_FRAME::value_t y) { mX = x; mY = y;}
 	bool operator==(const self_t& other) const { return mX == other.mX && mY == other.mY; }
 	bool operator!=(const self_t& other) const { return !(*this == other); }
 
+	static const self_t& getTypedCoords(const COORD_FRAME& self) { return static_cast<const self_t&>(self); }
+	static self_t& getTypedCoords(COORD_FRAME& self) { return static_cast<self_t&>(self); }
 };
 
 struct LL_COORD_TYPE_GL 
 
 	LLCoordCommon convertToCommon() const
 	{
-		const LLCoord<LL_COORD_TYPE_GL>& self = static_cast<const LLCoord<LL_COORD_TYPE_GL>&>(*this);
+		const LLCoordGL& self = LLCoordGL::getTypedCoords(*this);
 		return LLCoordCommon(self.mX, self.mY);
 	}
 
 	void convertFromCommon(const LLCoordCommon& from)
 	{
-		LLCoord<LL_COORD_TYPE_GL>& self = static_cast<LLCoord<LL_COORD_TYPE_GL>&>(*this);
+		LLCoordGL& self = LLCoordGL::getTypedCoords(*this);
 		self.mX = from.mX;
 		self.mY = from.mY;
 	}
 	void convertFromCommon(const LLCoordCommon& from);
 };
 
-typedef LLCoord<LL_COORD_TYPE_GL> LLCoordGL;
-typedef LLCoord<LL_COORD_TYPE_WINDOW> LLCoordWindow;
-typedef LLCoord<LL_COORD_TYPE_SCREEN> LLCoordScreen;
-
 #endif

File indra/llrender/llgl.cpp

 }
 #endif
 
+void parse_glsl_version(S32& major, S32& minor);
+
 void ll_init_fail_log(std::string filename)
 {
 	gFailLog.open(filename.c_str());
 PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB = NULL;
 PFNGLGETUNIFORMIVARBPROC glGetUniformivARB = NULL;
 PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB = NULL;
+PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer = NULL;
 
 #if LL_WINDOWS
 PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
 	mDriverVersionMinor(0),
 	mDriverVersionRelease(0),
 	mGLVersion(1.0f),
-		
+	mGLSLVersionMajor(0),
+	mGLSLVersionMinor(0),		
 	mVRAM(0),
 	mGLMaxVertexRange(0),
 	mGLMaxIndexRange(0)
 
 	mGLVersion = mDriverVersionMajor + mDriverVersionMinor * .1f;
 
+	if (mGLVersion >= 2.f)
+	{
+		parse_glsl_version(mGLSLVersionMajor, mGLSLVersionMinor);
+
+#if LL_DARWIN
+		//never use GLSL greater than 1.20 on OSX
+		if (mGLSLVersionMajor > 1 || mGLSLVersionMinor >= 30)
+		{
+			mGLSLVersionMajor = 1;
+			mGLSLVersionMinor = 20;
+		}
+#endif
+	}
+
 	// Trailing space necessary to keep "nVidia Corpor_ati_on" cards
 	// from being recognized as ATI.
 	if (mGLVendor.substr(0,4) == "ATI ")
 		glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4uivARB");
 		glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4usvARB");
 		glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribPointerARB");
+		glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribIPointer");
 		glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glEnableVertexAttribArrayARB");
 		glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDisableVertexAttribArrayARB");
 		glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramStringARB");
 	}
 }
 
+
+void parse_glsl_version(S32& major, S32& minor)
+{
+	// GL_SHADING_LANGUAGE_VERSION returns a null-terminated string with the format: 
+	// <major>.<minor>[.<release>] [<vendor specific>]
+
+	const char* version = (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION);
+	major = 0;
+	minor = 0;
+	
+	if( !version )
+	{
+		return;
+	}
+
+	std::string ver_copy( version );
+	S32 len = (S32)strlen( version );	/* Flawfinder: ignore */
+	S32 i = 0;
+	S32 start;
+	// Find the major version
+	start = i;
+	for( ; i < len; i++ )
+	{
+		if( '.' == version[i] )
+		{
+			break;
+		}
+	}
+	std::string major_str = ver_copy.substr(start,i-start);
+	LLStringUtil::convertToS32(major_str, major);
+
+	if( '.' == version[i] )
+	{
+		i++;
+	}
+
+	// Find the minor version
+	start = i;
+	for( ; i < len; i++ )
+	{
+		if( ('.' == version[i]) || isspace(version[i]) )
+		{
+			break;
+		}
+	}
+	std::string minor_str = ver_copy.substr(start,i-start);
+	LLStringUtil::convertToS32(minor_str, minor);
+}
+
 LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glh::matrix4f& modelview, const glh::matrix4f& projection, bool apply)
 {
 	mApply = apply;

File indra/llrender/llgl.h

 	S32 mDriverVersionMinor;
 	S32 mDriverVersionRelease;
 	F32 mGLVersion; // e.g = 1.4
+	S32 mGLSLVersionMajor;
+	S32 mGLSLVersionMinor;
 	std::string mDriverVersionVendorString;
 
 	S32 mVRAM; // VRAM in MB

File indra/llrender/llglheaders.h

 extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB;
 extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB;
 extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
+extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
 extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
 extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
 extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
 extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB;
 extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB;
 extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
+extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
 extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
 extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
 extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
 extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB;
 extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB;
 extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
+extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
 extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
 extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
 extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;

File indra/llrender/llglslshader.cpp

 		glGetAttachedObjectsARB(mProgramObject, 1024, &count, obj);
 		for (GLsizei i = 0; i < count; i++)
 		{
-			glDeleteObjectARB(obj[i]);
+#if !LL_DARWIN
+			if (glIsProgramARB(obj[i]))
+#endif
+			{
+				glDeleteObjectARB(obj[i]);
+			}
 		}
 
 		glDeleteObjectARB(mProgramObject);
 		return FALSE;
 	}
 
-	if (gGLManager.mGLVersion < 3.1f)
-	{ //attachShaderFeatures may have set the number of indexed texture channels, so set to 1 again
+	if (gGLManager.mGLSLVersionMajor < 2 && gGLManager.mGLSLVersionMinor < 3)
+	{ //indexed texture rendering requires GLSL 1.3 or later
+		//attachShaderFeatures may have set the number of indexed texture channels, so set to 1 again
 		mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1);
 	}
 

File indra/llrender/llshadermgr.cpp

 	GLcharARB* text[4096];
 	GLuint count = 0;
 
-	F32 version = gGLManager.mGLVersion;
+	S32 major_version = gGLManager.mGLSLVersionMajor;
+	S32 minor_version = gGLManager.mGLSLVersionMinor;
+	
+	if (major_version == 1 && minor_version < 30)
+	{
+		if (minor_version < 10)
+		{
+			//should NEVER get here -- if major version is 1 and minor version is less than 10, 
+			// viewer should never attempt to use shaders, continuing will result in undefined behavior
+			llerrs << "Unsupported GLSL Version." << llendl;
+		}
 
-//hack to never use GLSL > 1.20 on OSX
-#if LL_DARWIN
-	version = llmin(version, 2.9f);
-#endif
-
-	if (version < 2.1f)
-	{
-		text[count++] = strdup("#version 110\n");
-		text[count++] = strdup("#define ATTRIBUTE attribute\n");
-		text[count++] = strdup("#define VARYING varying\n");
-	}
-	else if (version < 3.3f)
-	{
-		//set version to 1.20
-		text[count++] = strdup("#version 120\n");
-		text[count++] = strdup("#define FXAA_GLSL_120 1\n");
-		text[count++] = strdup("#define FXAA_FAST_PIXEL_OFFSET 0\n");
-		text[count++] = strdup("#define ATTRIBUTE attribute\n");
-		text[count++] = strdup("#define VARYING varying\n");
+		if (minor_version <= 19)
+		{
+			text[count++] = strdup("#version 110\n");
+			text[count++] = strdup("#define ATTRIBUTE attribute\n");
+			text[count++] = strdup("#define VARYING varying\n");
+			text[count++] = strdup("#define VARYING_FLAT varying\n");
+		}
+		else if (minor_version <= 29)
+		{
+			//set version to 1.20
+			text[count++] = strdup("#version 120\n");
+			text[count++] = strdup("#define FXAA_GLSL_120 1\n");
+			text[count++] = strdup("#define FXAA_FAST_PIXEL_OFFSET 0\n");
+			text[count++] = strdup("#define ATTRIBUTE attribute\n");
+			text[count++] = strdup("#define VARYING varying\n");
+			text[count++] = strdup("#define VARYING_FLAT varying\n");
+		}
 	}
 	else
 	{  
-		if (version < 4.f)
+		if (major_version < 4)
 		{
 			//set version to 1.30
 			text[count++] = strdup("#version 130\n");
+
+			//some implementations of GLSL 1.30 require integer precision be explicitly declared
+			text[count++] = strdup("precision mediump int;\n");
+			text[count++] = strdup("precision highp float;\n");
 		}
 		else
 		{ //set version to 400
 		{ //"varying" state is "out" in a vertex program, "in" in a fragment program 
 			// ("varying" is deprecated after version 1.20)
 			text[count++] = strdup("#define VARYING out\n");
+			text[count++] = strdup("#define VARYING_FLAT flat out\n");
 		}
 		else
 		{
 			text[count++] = strdup("#define VARYING in\n");
+			text[count++] = strdup("#define VARYING_FLAT flat in\n");
 		}
 
 		//backwards compatibility with legacy texture lookup syntax
+		text[count++] = strdup("#define texture2D texture\n");
 		text[count++] = strdup("#define textureCube texture\n");
 		text[count++] = strdup("#define texture2DLod textureLod\n");
 		text[count++] = strdup("#define	shadow2D(a,b) vec2(texture(a,b))\n");
+
+		if (major_version > 1 || minor_version >= 40)
+		{ //GLSL 1.40 replaces texture2DRect et al with texture
+			text[count++] = strdup("#define texture2DRect texture\n");
+			text[count++] = strdup("#define shadow2DRect(a,b) vec2(texture(a,b))\n");
+		}
 	}
 
 	//copy preprocessor definitions into buffer
 		.
 		uniform sampler2D texN;
 		
-		VARYING float vary_texture_index;
+		VARYING_FLAT ivec4 vary_texture_index;
+
+		vec4 ret = vec4(1,0,1,1);
 
 		vec4 diffuseLookup(vec2 texcoord)
 		{
-			switch (int(vary_texture_index+0.25))
+			switch (vary_texture_index.r))
 			{
-				case 0: return texture2D(tex0, texcoord);
-				case 1: return texture2D(tex1, texcoord);
-				case 2: return texture2D(tex2, texcoord);
+				case 0: ret = texture2D(tex0, texcoord); break;
+				case 1: ret = texture2D(tex1, texcoord); break;
+				case 2: ret = texture2D(tex2, texcoord); break;
 				.
 				.
 				.
-				case N: return texture2D(texN, texcoord);
+				case N: return texture2D(texN, texcoord); break;
 			}
 
-			return vec4(0,0,0,0);
+			return ret;
 		}
 		*/
 
 
 		if (texture_index_channels > 1)
 		{
-			text[count++] = strdup("VARYING float vary_texture_index;\n");
+			text[count++] = strdup("VARYING_FLAT ivec4 vary_texture_index;\n");
 		}
 
 		text[count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n");
 			text[count++] = strdup("return texture2D(tex0, texcoord);\n");
 			text[count++] = strdup("}\n");
 		}
-		else if (gGLManager.mGLVersion >= 3.f)
-		{ 
-			text[count++] = strdup("\tswitch (int(vary_texture_index+0.25))\n");
+		else if (major_version > 1 || minor_version >= 30)
+		{  //switches are supported in GLSL 1.30 and later
+			text[count++] = strdup("\tvec4 ret = vec4(1,0,1,1);\n");
+			text[count++] = strdup("\tswitch (vary_texture_index.r)\n");
 			text[count++] = strdup("\t{\n");
 		
 			//switch body
 			for (S32 i = 0; i < texture_index_channels; ++i)
 			{
-				std::string case_str = llformat("\t\tcase %d: return texture2D(tex%d, texcoord);\n", i, i);
+				std::string case_str = llformat("\t\tcase %d: ret = texture2D(tex%d, texcoord); break;\n", i, i);
 				text[count++] = strdup(case_str.c_str());
 			}
 
 			text[count++] = strdup("\t}\n");
-			text[count++] = strdup("\treturn vec4(1,0,1,1);\n");
+			text[count++] = strdup("\treturn ret;\n");
 			text[count++] = strdup("}\n");
 		}
 		else
-		{
-			//switches aren't supported, make block that looks like:
-			/*
-				int ti = int(vary_texture_index+0.25);
-				if (ti == 0) return texture2D(tex0, texcoord);
-				if (ti == 1) return texture2D(tex1, texcoord);
-				.
-				.
-				.
-				if (ti == N) return texture2D(texN, texcoord);
-			*/
-				
-			text[count++] = strdup("int ti = int(vary_texture_index+0.25);\n");
-			for (S32 i = 0; i < texture_index_channels; ++i)
-			{
-				std::string if_str = llformat("if (ti == %d) return texture2D(tex%d, texcoord);\n", i, i);
-				text[count++] = strdup(if_str.c_str());
-			}
-
-			text[count++] = strdup("\treturn vec4(1,0,1,1);\n");
-			text[count++] = strdup("}\n");
-		}			
+		{ //should never get here.  Indexed texture rendering requires GLSL 1.30 or later 
+			// (for passing integers between vertex and fragment shaders)
+			llerrs << "Indexed texture rendering requires GLSL 1.30 or later." << llendl;
+		}
 	}
 
 	//copy file into memory
 	mReservedUniforms.push_back("magnification");
 	mReservedUniforms.push_back("max_cof");
 	mReservedUniforms.push_back("res_scale");
+	mReservedUniforms.push_back("dof_width");
+	mReservedUniforms.push_back("dof_height");
 
 	mReservedUniforms.push_back("depthMap");
 	mReservedUniforms.push_back("shadowMap0");

File indra/llrender/llshadermgr.h

 		DOF_MAGNIFICATION,
 		DOF_MAX_COF,
 		DOF_RES_SCALE,
+		DOF_WIDTH,
+		DOF_HEIGHT,
 
 		DEFERRED_DEPTH,
 		DEFERRED_SHADOW0,

File indra/llrender/llvertexbuffer.cpp

 	{
 		bool error = false;
 
+		if (gGLManager.mGLSLVersionMajor < 2 && gGLManager.mGLSLVersionMinor < 30)
+		{
+			//make sure texture index is disabled
+			data_mask = data_mask & ~MAP_TEXTURE_INDEX;
+		}
+
 		if (LLGLSLShader::sNoFixedFunction)
 		{
 			for (U32 i = 0; i < TYPE_MAX; ++i)
 		1, //TYPE_WEIGHT,
 		4, //TYPE_WEIGHT4,
 		4, //TYPE_CLOTHWEIGHT,
-		1, //TYPE_TEXTURE_INDEX
+		4, //TYPE_TEXTURE_INDEX
 	};
 
 	U32 attrib_type[] =
 		GL_FLOAT, //TYPE_WEIGHT,
 		GL_FLOAT, //TYPE_WEIGHT4,
 		GL_FLOAT, //TYPE_CLOTHWEIGHT,
-		GL_FLOAT, //TYPE_TEXTURE_INDEX
+		GL_UNSIGNED_BYTE, //TYPE_TEXTURE_INDEX
+	};
+
+	bool attrib_integer[] = 
+	{
+		false, //TYPE_VERTEX,
+		false, //TYPE_NORMAL,
+		false, //TYPE_TEXCOORD0,
+		false, //TYPE_TEXCOORD1,
+		false, //TYPE_TEXCOORD2,
+		false, //TYPE_TEXCOORD3,
+		false, //TYPE_COLOR,
+		false, //TYPE_EMISSIVE,
+		false, //TYPE_BINORMAL,
+		false, //TYPE_WEIGHT,
+		false, //TYPE_WEIGHT4,
+		false, //TYPE_CLOTHWEIGHT,
+		true, //TYPE_TEXTURE_INDEX
 	};
 
 	U32 attrib_normalized[] =
 		if (mTypeMask & (1 << i))
 		{
 			glEnableVertexAttribArrayARB(i);
-			glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i], attrib_normalized[i], sTypeSize[i], (void*) mOffsets[i]); 
+
+			if (attrib_integer[i])
+			{
+#if !LL_DARWIN
+				//glVertexattribIPointer requires GLSL 1.30 or later
+				if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30)
+				{
+					glVertexAttribIPointer(i, attrib_size[i], attrib_type[i], sTypeSize[i], (void*) mOffsets[i]); 
+				}
+#endif
+			}
+			else
+			{
+				glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i], attrib_normalized[i], sTypeSize[i], (void*) mOffsets[i]); 
+			}
 		}
 		else
 		{
 			void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]);
 			glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_TRUE,  LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
 		}
-		if (data_mask & MAP_TEXTURE_INDEX)
+		if (data_mask & MAP_TEXTURE_INDEX && 
+				(gGLManager.mGLSLVersionMajor >= 2 || gGLManager.mGLSLVersionMinor >= 30)) //indexed texture rendering requires GLSL 1.30 or later
 		{
+#if !LL_DARWIN
 			S32 loc = TYPE_TEXTURE_INDEX;
 			void *ptr = (void*) (base + mOffsets[TYPE_VERTEX] + 12);
-			glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
+			glVertexAttribIPointer(loc, 4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
+#endif
 		}
 		if (data_mask & MAP_VERTEX)
 		{

File indra/llui/llclipboard.cpp

 #include "llview.h"
 #include "llwindow.h"
 
-// Global singleton
-LLClipboard gClipboard;
-
-
-LLClipboard::LLClipboard()
+LLClipboard::LLClipboard() :
+	mGeneration(0)
 {
-	mSourceItem = NULL;
+	reset();
 }
 
-
 LLClipboard::~LLClipboard()
 {
+	reset();
 }
 
-
-void LLClipboard::copyFromSubstring(const LLWString &src, S32 pos, S32 len, const LLUUID& source_id )
+void LLClipboard::reset()
 {
-	mSourceID = source_id;
-	mString = src.substr(pos, len);
-	LLView::getWindow()->copyTextToClipboard( mString );
+	// Increment the clipboard count
+	mGeneration++;
+	// Clear the clipboard
+	mObjects.clear();
+	mCutMode = false;
+	mString = LLWString();
 }
 
-void LLClipboard::copyFromString(const LLWString &src, const LLUUID& source_id )
+// Copy the input uuid to the LL clipboard
+bool LLClipboard::copyToClipboard(const LLUUID& src, const LLAssetType::EType type)
 {
-	mSourceID = source_id;
-	mString = src;
-	LLView::getWindow()->copyTextToClipboard( mString );
+	reset();
+	return addToClipboard(src, type);
 }
 
-const LLWString& LLClipboard::getPasteWString( LLUUID* source_id )
+// Add the input uuid to the LL clipboard
+// Convert the uuid to string and concatenate that string to the system clipboard if legit
+bool LLClipboard::addToClipboard(const LLUUID& src, const LLAssetType::EType type)
 {
-	if( mSourceID.notNull() )
+	bool res = false;
+	if (src.notNull())
 	{
-		LLWString temp_string;
-		LLView::getWindow()->pasteTextFromClipboard(temp_string);
-
-		if( temp_string != mString )
+		res = true;
+		if (LLAssetType::lookupIsAssetIDKnowable(type))
 		{
-			mSourceID.setNull();
-			mString = temp_string;
+			LLWString source = utf8str_to_wstring(src.asString());
+			res = addToClipboard(source, 0, source.size());
+		}
+		if (res)
+		{
+			mObjects.push_back(src);
+			mGeneration++;
 		}
 	}
-	else
-	{
-		LLView::getWindow()->pasteTextFromClipboard(mString);
-	}
-
-	if( source_id )
-	{
-		*source_id = mSourceID;
-	}
-
-	return mString;
+	return res;
 }
 
-
-BOOL LLClipboard::canPasteString() const
+bool LLClipboard::pasteFromClipboard(std::vector<LLUUID>& inv_objects) const
 {
-	return LLView::getWindow()->isClipboardTextAvailable();
+	bool res = false;
+	S32 count = mObjects.size();
+	if (count > 0)
+	{
+		res = true;
+		inv_objects.clear();
+		for (S32 i = 0; i < count; i++)
+		{
+			inv_objects.push_back(mObjects[i]);
+		}
+	}
+	return res;
 }
 
-
-void LLClipboard::copyFromPrimarySubstring(const LLWString &src, S32 pos, S32 len, const LLUUID& source_id )
+// Returns true if the LL Clipboard has pasteable items in it
+bool LLClipboard::hasContents() const
 {
-	mSourceID = source_id;
-	mString = src.substr(pos, len);
-	LLView::getWindow()->copyTextToPrimary( mString );
+	return (mObjects.size() > 0);
 }
 
-
-const LLWString& LLClipboard::getPastePrimaryWString( LLUUID* source_id )
+// Returns true if the input uuid is in the list of clipboard objects
+bool LLClipboard::isOnClipboard(const LLUUID& object) const
 {
-	if( mSourceID.notNull() )
-	{
-		LLWString temp_string;
-		LLView::getWindow()->pasteTextFromPrimary(temp_string);
-
-		if( temp_string != mString )
-		{
-			mSourceID.setNull();
-			mString = temp_string;
-		}
-	}
-	else
-	{
-		LLView::getWindow()->pasteTextFromPrimary(mString);
-	}
-
-	if( source_id )
-	{
-		*source_id = mSourceID;
-	}
-
-	return mString;
+	std::vector<LLUUID>::const_iterator iter = std::find(mObjects.begin(), mObjects.end(), object);
+	return (iter != mObjects.end());
 }
 
-
-BOOL LLClipboard::canPastePrimaryString() const
+// Copy the input string to the LL and the system clipboard
+bool LLClipboard::copyToClipboard(const LLWString &src, S32 pos, S32 len, bool use_primary)
 {
-	return LLView::getWindow()->isPrimaryTextAvailable();
+	return addToClipboard(src, pos, len, use_primary);
 }
 
-void LLClipboard::setSourceObject(const LLUUID& source_id, LLAssetType::EType type) 
+// Concatenate the input string to the LL and the system clipboard
+bool LLClipboard::addToClipboard(const LLWString &src, S32 pos, S32 len, bool use_primary)
 {
-	mSourceItem = new LLInventoryObject (source_id, LLUUID::null, type, "");
+	mString = src.substr(pos, len);
+	return (use_primary ? LLView::getWindow()->copyTextToPrimary(mString) : LLView::getWindow()->copyTextToClipboard(mString));
 }
+
+// Copy the System clipboard to the output string.
+// Manage the LL Clipboard / System clipboard consistency
+bool LLClipboard::pasteFromClipboard(LLWString &dst, bool use_primary)
+{
+	bool res = (use_primary ? LLView::getWindow()->pasteTextFromPrimary(dst) : LLView::getWindow()->pasteTextFromClipboard(dst));
+	if (res)
+	{
+		mString = dst;
+	}
+	return res;
+}
+
+// Return true if there's something on the System clipboard
+bool LLClipboard::isTextAvailable(bool use_primary) const
+{
+	return (use_primary ? LLView::getWindow()->isPrimaryTextAvailable() : LLView::getWindow()->isClipboardTextAvailable());
+}
+

File indra/llui/llclipboard.h

 #ifndef LL_LLCLIPBOARD_H
 #define LL_LLCLIPBOARD_H
 
+#include <boost/function.hpp>
 
 #include "llstring.h"
 #include "lluuid.h"
 #include "stdenums.h"
+#include "llsingleton.h"
+#include "llassettype.h"
 #include "llinventory.h"
 
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLClipboard
+//
+// This class is used to cut/copy/paste text strings and inventory items around 
+// the world. Use LLClipboard::instance().method() to use its methods.
+// Note that the text and UUIDs are loosely coupled only. There are few cases
+// where the viewer does offer a serialized version of the UUID on the clipboard.
+// In those case, the text is overridden when copying/cutting the item. 
+// In all other cases, the text and the UUIDs are very much independent.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-class LLClipboard
+class LLClipboard : public LLSingleton<LLClipboard>
 {
 public:
 	LLClipboard();
 	~LLClipboard();
+	
+	// Clears the clipboard
+	void reset();
+	// Returns the state of the clipboard so client can know if it has been modified (comparing with tracked state)
+	int	getGeneration() const { return mGeneration; }
 
-	/* We support two flavors of clipboard.  The default is the explicitly
-	   copy-and-pasted clipboard.  The second is the so-called 'primary' clipboard
-	   which is implicitly copied upon selection on platforms which expect this
-	   (i.e. X11/Linux). */
+	// Text strings management:
+	// ------------------------
+	// We support two flavors of text clipboards. The default is the explicitly
+	// copy-and-pasted clipboard. The second is the so-called 'primary' clipboard
+	// which is implicitly copied upon selection on platforms which expect this
+	// (i.e. X11/Linux, Mac).
+	bool copyToClipboard(const LLWString& src, S32 pos, S32 len, bool use_primary = false);
+	bool addToClipboard(const LLWString& src, S32 pos, S32 len, bool use_primary = false);
+	bool pasteFromClipboard(LLWString& dst, bool use_primary = false);
+	bool isTextAvailable(bool use_primary = false) const;
+	
+	// Object list management:
+	// -----------------------
+	// Clears and adds one single object to the clipboard
+	bool copyToClipboard(const LLUUID& src, const LLAssetType::EType type = LLAssetType::AT_NONE);
+	// Adds one object to the current list of objects on the clipboard
+	bool addToClipboard(const LLUUID& src, const LLAssetType::EType type = LLAssetType::AT_NONE);
+	// Gets a copy of the objects on the clipboard
+	bool pasteFromClipboard(std::vector<LLUUID>& inventory_objects) const;
+	
+	bool hasContents() const;										// True if the clipboard has pasteable objects
+	bool isOnClipboard(const LLUUID& object) const;					// True if the input object uuid is on the clipboard
 
-	void		copyFromSubstring(const LLWString &copy_from, S32 pos, S32 len, const LLUUID& source_id = LLUUID::null );
-	void		copyFromString(const LLWString &copy_from, const LLUUID& source_id = LLUUID::null );
-	BOOL		canPasteString() const;
-	const LLWString&	getPasteWString(LLUUID* source_id = NULL);
+	bool isCutMode() const { return mCutMode; }
+	void setCutMode(bool mode) { mCutMode = mode; mGeneration++; }
 
-	void		copyFromPrimarySubstring(const LLWString &copy_from, S32 pos, S32 len, const LLUUID& source_id = LLUUID::null );
-	BOOL		canPastePrimaryString() const;
-	const LLWString&	getPastePrimaryWString(LLUUID* source_id = NULL);	
-
-	// Support clipboard for object known only by their uuid and asset type
-	void		  setSourceObject(const LLUUID& source_id, LLAssetType::EType type);
-	const LLInventoryObject* getSourceObject() { return mSourceItem; }
-	
 private:
-	LLUUID      mSourceID;
-	LLWString	mString;
-	LLInventoryObject* mSourceItem;
+	std::vector<LLUUID> mObjects;		// Objects on the clipboard. Can be empty while mString contains something licit (e.g. text from chat)
+	LLWString mString;					// The text string. If mObjects is not empty, this string is reflecting them (UUIDs for the moment) if the asset type is knowable.
+	bool mCutMode;						// This is a convenience flag for the viewer.
+	int mGeneration;					// Incremented when the clipboard changes so that interested parties can check for changes on the clipboard.	
 };
 
-
-// Global singleton
-extern LLClipboard gClipboard;
-
-
 #endif  // LL_LLCLIPBOARD_H

File indra/llui/llfloater.cpp

 {
 	void TypeValues<LLFloaterEnums::EOpenPositioning>::declareValues()
 	{
-		declare("none",       LLFloaterEnums::OPEN_POSITIONING_NONE);
-		declare("cascading",  LLFloaterEnums::OPEN_POSITIONING_CASCADING);
-		declare("centered",   LLFloaterEnums::OPEN_POSITIONING_CENTERED);
-		declare("specified",  LLFloaterEnums::OPEN_POSITIONING_SPECIFIED);
+		declare("relative",   LLFloaterEnums::POSITIONING_RELATIVE);
+		declare("cascading",  LLFloaterEnums::POSITIONING_CASCADING);
+		declare("centered",   LLFloaterEnums::POSITIONING_CENTERED);
+		declare("specified",  LLFloaterEnums::POSITIONING_SPECIFIED);
 	}
 }
 
 	save_visibility("save_visibility", false),
 	can_dock("can_dock", false),
 	show_title("show_title", true),
-	open_positioning("open_positioning", LLFloaterEnums::OPEN_POSITIONING_NONE),
-	specified_left("specified_left"),
-	specified_bottom("specified_bottom"),
+	positioning("positioning", LLFloaterEnums::POSITIONING_RELATIVE),
 	header_height("header_height", 0),
 	legacy_header_height("legacy_header_height", 0),
 	close_image("close_image"),
 	mCanClose(p.can_close),
 	mDragOnLeft(p.can_drag_on_left),
 	mResizable(p.can_resize),
-	mOpenPositioning(p.open_positioning),
-	mSpecifiedLeft(p.specified_left),
-	mSpecifiedBottom(p.specified_bottom),
+	mPositioning(p.positioning),
 	mMinWidth(p.min_width),
 	mMinHeight(p.min_height),
 	mHeaderHeight(p.header_height),
 
 void LLFloater::storeRectControl()
 {
-	if( mRectControl.size() > 1 )
+	if (!mRectControl.empty())
 	{
 		getControlGroup()->setRect( mRectControl, getRect() );
 	}
+	if (!mPosXControl.empty() && mPositioning == LLFloaterEnums::POSITIONING_RELATIVE)
+	{
+		getControlGroup()->setF32( mPosXControl, mPosition.mX );
+	}
+	if (!mPosYControl.empty() && mPositioning == LLFloaterEnums::POSITIONING_RELATIVE)
+	{
+		getControlGroup()->setF32( mPosYControl, mPosition.mY );
+	}
 }
 
 void LLFloater::storeVisibilityControl()
 	}
 }
 
-LLRect LLFloater::getSavedRect() const
-{
-	LLRect rect;
-
-	if (mRectControl.size() > 1)
-	{
-		rect = getControlGroup()->getRect(mRectControl);
-	}
-
-	return rect;
-}
-
-bool LLFloater::hasSavedRect() const
-{
-	return !getSavedRect().isEmpty();
-}
-
 // static
 std::string LLFloater::getControlName(const std::string& name, const LLSD& key)
 {
 	{
 		if (!applyRectControl())
 		{
-			applyPositioning(other);
+			applyPositioning(other, true);
 		}
 	}
 }
 {
 	bool saved_rect = false;
 
+	LLRect screen_rect = calcScreenRect();
+	mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert();
+	
 	LLFloater* last_in_group = LLFloaterReg::getLastFloaterInGroup(mInstanceName);
 	if (last_in_group && last_in_group != this)
 	{
 		// other floaters in our group, position ourselves relative to them and don't save the rect
 		mRectControl.clear();
-		mOpenPositioning = LLFloaterEnums::OPEN_POSITIONING_CASCADE_GROUP;
+		mPositioning = LLFloaterEnums::POSITIONING_CASCADE_GROUP;
 	}
-	else if (mRectControl.size() > 1)
+	else
 	{
-		// If we have a saved rect, use it
-		const LLRect& rect = getControlGroup()->getRect(mRectControl);
-		saved_rect = rect.notEmpty();
-		if (saved_rect)
+		bool rect_specified = false;
+		if (!mRectControl.empty())
 		{
-			setOrigin(rect.mLeft, rect.mBottom);
-
-			if (mResizable)
+			// If we have a saved rect, use it
+			const LLRect& rect = getControlGroup()->getRect(mRectControl);
+			if (rect.notEmpty()) saved_rect = true;
+			if (saved_rect)
 			{
-				reshape(llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight()));
+				setOrigin(rect.mLeft, rect.mBottom);
+
+				if (mResizable)
+				{
+					reshape(llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight()));
+				}
+				mPositioning = LLFloaterEnums::POSITIONING_RELATIVE;
+				LLRect screen_rect = calcScreenRect();
+				mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert();
+				rect_specified = true;
 			}
 		}
+
+		LLControlVariablePtr x_control = getControlGroup()->getControl(mPosXControl);
+		LLControlVariablePtr y_control = getControlGroup()->getControl(mPosYControl);
+		if (x_control.notNull() 
+			&& y_control.notNull()
+			&& !x_control->isDefault()
+			&& !y_control->isDefault())
+		{
+			mPosition.mX = x_control->getValue().asReal();
+			mPosition.mY = y_control->getValue().asReal();
+			mPositioning = LLFloaterEnums::POSITIONING_RELATIVE;
+			applyRelativePosition();
+
+			saved_rect = true;
+		}
+
+		// remember updated position
+		if (rect_specified)
+		{
+			storeRectControl();
+		}
 	}
 
+	if (saved_rect)
+	{
+		// propagate any derived positioning data back to settings file
+		storeRectControl();
+	}
+
+
 	return saved_rect;
 }
 
 	return docked;
 }
 
-void LLFloater::applyPositioning(LLFloater* other)
+void LLFloater::applyPositioning(LLFloater* other, bool on_open)
 {
 	// Otherwise position according to the positioning code
-	switch (mOpenPositioning)
+	switch (mPositioning)
 	{
-	case LLFloaterEnums::OPEN_POSITIONING_CENTERED:
+	case LLFloaterEnums::POSITIONING_CENTERED:
 		center();
 		break;
 
-	case LLFloaterEnums::OPEN_POSITIONING_SPECIFIED:
+	case LLFloaterEnums::POSITIONING_SPECIFIED:
+		break;
+
+	case LLFloaterEnums::POSITIONING_CASCADING:
+		if (!on_open)
 		{
-			// Translate relative to snap rect
-			setOrigin(mSpecifiedLeft, mSpecifiedBottom);
-			const LLRect& snap_rect = gFloaterView->getSnapRect();
-			translate(snap_rect.mLeft, snap_rect.mBottom);
-			translateIntoRect(snap_rect);
+			applyRelativePosition();
+		}
+		// fall through
+	case LLFloaterEnums::POSITIONING_CASCADE_GROUP:
+		if (on_open)
+		{
+			if (other != NULL && other != this)
+			{
+				stackWith(*other);
+			}
+			else
+			{
+				static const U32 CASCADING_FLOATER_HOFFSET = 0;
+				static const U32 CASCADING_FLOATER_VOFFSET = 0;
+			
+				const LLRect& snap_rect = gFloaterView->getSnapRect();
+
+				const S32 horizontal_offset = CASCADING_FLOATER_HOFFSET;
+				const S32 vertical_offset = snap_rect.getHeight() - CASCADING_FLOATER_VOFFSET;
+
+				S32 rect_height = getRect().getHeight();
+				setOrigin(horizontal_offset, vertical_offset - rect_height);
+
+				translate(snap_rect.mLeft, snap_rect.mBottom);
+			}
+			setFollows(FOLLOWS_TOP | FOLLOWS_LEFT);
 		}
 		break;
 
-	case LLFloaterEnums::OPEN_POSITIONING_CASCADE_GROUP:
-	case LLFloaterEnums::OPEN_POSITIONING_CASCADING:
-		if (other != NULL && other != this)
+	case LLFloaterEnums::POSITIONING_RELATIVE:
 		{
-			stackWith(*other);
+			applyRelativePosition();
+
+			break;
 		}
-		else
-		{
-			static const U32 CASCADING_FLOATER_HOFFSET = 0;
-			static const U32 CASCADING_FLOATER_VOFFSET = 0;
-			
-			const LLRect& snap_rect = gFloaterView->getSnapRect();
-
-			const S32 horizontal_offset = CASCADING_FLOATER_HOFFSET;
-			const S32 vertical_offset = snap_rect.getHeight() - CASCADING_FLOATER_VOFFSET;
-
-			S32 rect_height = getRect().getHeight();
-			setOrigin(horizontal_offset, vertical_offset - rect_height);
-
-			translate(snap_rect.mLeft, snap_rect.mBottom);
-			translateIntoRect(snap_rect);
-		}
-		break;
-
-	case LLFloaterEnums::OPEN_POSITIONING_NONE:
 	default:
 		// Do nothing
 		break;
 	if (by_user && !isMinimized())
 	{
 		storeRectControl();
-		mOpenPositioning = LLFloaterEnums::OPEN_POSITIONING_NONE;
+		mPositioning = LLFloaterEnums::POSITIONING_RELATIVE;
+		LLRect screen_rect = calcScreenRect();
+		mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert();
 	}
 
 	// if not minimized, adjust all snapped dependents to new shape
 
 		// Reshape *after* setting mMinimized
 		reshape( mExpandedRect.getWidth(), mExpandedRect.getHeight(), TRUE );
+		applyPositioning(NULL, false);
 	}
 
 	make_ui_sound("UISndWindowClose");
 		if (mDocked)
 		{
 			setMinimized(FALSE);
-			mOpenPositioning = LLFloaterEnums::OPEN_POSITIONING_NONE;
+			mPositioning = LLFloaterEnums::POSITIONING_RELATIVE;
 		}
 
 		updateTitleButtons();
 		self->openFloater(self->getKey());
 		
 		// only force position for floaters that don't have that data saved
-		if (self->mRectControl.size() <= 1)
+		if (self->mRectControl.empty())
 		{
 			new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - floater_header_size - 5, self->getRect().getWidth(), self->getRect().getHeight());
 			self->setRect(new_rect);
 	mSnapOffsetBottom(0),
 	mSnapOffsetRight(0)
 {
+	mSnapView = getHandle();
 }
 
 // By default, adjust vertical.
 void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent)
 {
-	S32 old_right = mLastSnapRect.mRight;
-	S32 old_top = mLastSnapRect.mTop;
-
 	LLView::reshape(width, height, called_from_parent);
 
-	S32 new_right = getSnapRect().mRight;
-	S32 new_top = getSnapRect().mTop;
-
 	mLastSnapRect = getSnapRect();
 
 	for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
 			continue;
 		}
 
-		if (!floaterp->isMinimized())
+		if (!floaterp->isMinimized() && floaterp->getCanDrag())
 		{
-			LLRect r = floaterp->getRect();
-
-			// Compute absolute distance from each edge of screen
-			S32 left_offset = llabs(r.mLeft - 0);
-			S32 right_offset = llabs(old_right - r.mRight);
-
-			S32 top_offset = llabs(old_top - r.mTop);
-			S32 bottom_offset = llabs(r.mBottom - 0);
-
-			S32 translate_x = 0;
-			S32 translate_y = 0;
-
-			if (left_offset > right_offset)
-			{
-				translate_x = new_right - old_right;
-			}
-
-			if (top_offset < bottom_offset)
-			{
-				translate_y = new_top - old_top;
-			}
+			LLRect old_rect = floaterp->getRect();
+			floaterp->applyPositioning(NULL, false);
+			LLRect new_rect = floaterp->getRect();
+
+			//LLRect r = floaterp->getRect();
+
+			//// Compute absolute distance from each edge of screen
+			//S32 left_offset = llabs(r.mLeft - 0);
+			//S32 right_offset = llabs(old_right - r.mRight);
+
+			//S32 top_offset = llabs(old_top - r.mTop);
+			//S32 bottom_offset = llabs(r.mBottom - 0);
+
+			S32 translate_x = new_rect.mLeft - old_rect.mLeft;
+			S32 translate_y = new_rect.mBottom - old_rect.mBottom;
+
+			//if (left_offset > right_offset)
+			//{
+			//	translate_x = new_right - old_right;
+			//}
+
+			//if (top_offset < bottom_offset)
+			//{
+			//	translate_y = new_top - old_top;
+			//}
 
 			// don't reposition immovable floaters
-			if (floaterp->getCanDrag())
-			{
-				floaterp->translate(translate_x, translate_y);
-			}
+			//if (floaterp->getCanDrag())
+			//{
+			//	floaterp->translate(translate_x, translate_y);
+			//}
 			BOOST_FOREACH(LLHandle<LLFloater> dependent_floater, floaterp->mDependents)
 			{
 				if (dependent_floater.get())