Commits

davep committed 75da2ee Merge

merge

Comments (0)

Files changed (121)

 28b95a6a28dca3338d9a1f4f204b96678df9f6a5 viewer-beta-candidate
 b43cd25be49e3984ff5361cefad020e069131d98 3.3.1-start
 3e2fca4ed1a0dc9fe6d8a6664e71098bb035a367 DRTVWR-125
+dffd0457ee0745de65bf95f0642a5c9e46b8e2f0 viewer-beta-candidate
+3e2fca4ed1a0dc9fe6d8a6664e71098bb035a367 viewer-beta-candidate
+3e2fca4ed1a0dc9fe6d8a6664e71098bb035a367 viewer-beta-candidate
 3e2fca4ed1a0dc9fe6d8a6664e71098bb035a367 3.3.1-start
 28b95a6a28dca3338d9a1f4f204b96678df9f6a5 3.3.1-beta1
 1dc545e44617975da2a4a32fe303386c687a6ca1 viewer-beta-candidate

indra/llcommon/llinitparam.h

File contents unchanged.

indra/llcommon/llsd.cpp

 		virtual LLSD::UUID		asUUID() const	{ return LLUUID(mValue); }
 		virtual LLSD::Date		asDate() const	{ return LLDate(mValue); }
 		virtual LLSD::URI		asURI() const	{ return LLURI(mValue); }
+		virtual int				size() const	{ return mValue.size(); }
 	};
 	
 	LLSD::Integer	ImplString::asInteger() const

indra/llcommon/llstrider.h

 	const LLStrider<Object>& operator =  (Object *first)    { mObjectp = first; return *this;}
 	void setStride (S32 skipBytes)	{ mSkip = (skipBytes ? skipBytes : sizeof(Object));}
 
+	LLStrider<Object> operator+(const S32& index) 
+	{
+		LLStrider<Object> ret;
+		ret.mBytep = mBytep + mSkip*index;
+		ret.mSkip = mSkip;
+
+		return ret;
+	}
+
 	void skip(const U32 index)     { mBytep += mSkip*index;}
 	U32 getSkip() const			   { return mSkip; }
 	Object* get()                  { return mObjectp; }
 	Object& operator *()           { return *mObjectp; }
 	Object* operator ++(int)       { Object* old = mObjectp; mBytep += mSkip; return old; }
 	Object* operator +=(int i)     { mBytep += mSkip*i; return mObjectp; }
+
 	Object& operator[](U32 index)  { return *(Object*)(mBytep + (mSkip * index)); }
 };
 

indra/llmath/llcoord.h

File contents unchanged.

indra/llmath/llvolume.h

 #include "llstrider.h"
 #include "v4coloru.h"
 #include "llrefcount.h"
+#include "llpointer.h"
 #include "llfile.h"
 
 //============================================================================
 	LLVector2*  mTexCoords;
 	U16* mIndices;
 
+	//vertex buffer filled in by LLFace to cache this volume face geometry in vram 
+	// (declared as a LLPointer to LLRefCount to avoid dependency on LLVertexBuffer)
+	mutable LLPointer<LLRefCount> mVertexBuffer; 
+
 	std::vector<S32>	mEdge;
 
 	//list of skin weights for rigged volumes

indra/llmessage/llsdmessagereader.cpp

 	case LLSD::TypeReal:
 		return sizeof(F64);
 	case LLSD::TypeString:
-		return llsd.asString().size();
+		return llsd.size();
 	case LLSD::TypeUUID:
 		return sizeof(LLUUID);
 	case LLSD::TypeDate:

indra/llrender/llcubemap.cpp

 		{
 			U32 texname = 0;
 			
-			LLImageGL::generateTextures(1, &texname);
+			LLImageGL::generateTextures(LLTexUnit::TT_CUBE_MAP, GL_RGB8, 1, &texname);
 
 			for (int i = 0; i < 6; i++)
 			{

indra/llrender/llgl.cpp

 PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv = NULL;
 PFNGLSAMPLEMASKIPROC glSampleMaski = NULL;
 
+//transform feedback (4.0 core)
+PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback = NULL;
+PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback = NULL;
+PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings = NULL;
+PFNGLBINDBUFFERRANGEPROC glBindBufferRange = NULL;
+
 //GL_ARB_debug_output
 PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB = NULL;
 PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB = NULL;
 	mHasDrawBuffers(FALSE),
 	mHasTextureRectangle(FALSE),
 	mHasTextureMultisample(FALSE),
+	mHasTransformFeedback(FALSE),
 	mMaxSampleMaskWords(0),
 	mMaxColorTextureSamples(0),
 	mMaxDepthTextureSamples(0),
 	parse_gl_version( &mDriverVersionMajor, 
 		&mDriverVersionMinor, 
 		&mDriverVersionRelease, 
-		&mDriverVersionVendorString );
+		&mDriverVersionVendorString,
+		&mGLVersionString);
 
 	mGLVersion = mDriverVersionMajor + mDriverVersionMinor * .1f;
 
 	mHasMultitexture = glh_init_extensions("GL_ARB_multitexture");
 	mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts);
 	mHasNVXMemInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts);
-	mHasMipMapGeneration = glh_init_extensions("GL_SGIS_generate_mipmap");
 	mHasSeparateSpecularColor = glh_init_extensions("GL_EXT_separate_specular_color");
 	mHasAnisotropic = glh_init_extensions("GL_EXT_texture_filter_anisotropic");
 	glh_init_extensions("GL_ARB_texture_cube_map");
 							ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts);
 #endif
 	
+	mHasMipMapGeneration = mHasFramebufferObject || mGLVersion >= 1.4f;
+
 	mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts);
 	mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts);
 	mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts);
 	mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts);
 	mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts);
+	mHasTransformFeedback = mGLVersion >= 4.f ? TRUE : FALSE;
 #if !LL_DARWIN
 	mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
 #endif
 		glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage3DMultisample");
 		glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv");
 		glSampleMaski = (PFNGLSAMPLEMASKIPROC) GLH_EXT_GET_PROC_ADDRESS("glSampleMaski");
-	}	
+	}
+	if (mHasTransformFeedback)
+	{
+		glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glBeginTransformFeedback");
+		glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glEndTransformFeedback");
+		glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackVaryings");
+		glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferRange");
+	}
 	if (mHasDebugOutput)
 	{
 		glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageControlARB");
 			case GL_COLOR_MATERIAL:
 			case GL_FOG:
 			case GL_LINE_STIPPLE:
+			case GL_POLYGON_STIPPLE:
 				mState = 0;
 				break;
 		}
 
 ////////////////////////////////////////////////////////////////////////////////
 
-void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific )
+void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific, std::string* version_string )
 {
 	// GL_VERSION returns a null-terminated string with the format: 
 	// <major>.<minor>[.<release>] [<vendor specific>]
 		return;
 	}
 
+	version_string->assign(version);
+
 	std::string ver_copy( version );
 	S32 len = (S32)strlen( version );	/* Flawfinder: ignore */
 	S32 i = 0;
 	gGL.matrixMode(LLRender::MM_MODELVIEW);
 }
 
+
+	
+LLGLSyncFence::LLGLSyncFence()
+{
+#ifdef GL_ARB_sync
+	mSync = 0;
+#endif
+}
+
+LLGLSyncFence::~LLGLSyncFence()
+{
+#ifdef GL_ARB_sync
+	if (mSync)
+	{
+		glDeleteSync(mSync);
+	}
+#endif
+}
+
+void LLGLSyncFence::placeFence()
+{
+#ifdef GL_ARB_sync
+	if (mSync)
+	{
+		glDeleteSync(mSync);
+	}
+	mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+#endif
+}
+
+bool LLGLSyncFence::isCompleted()
+{
+	bool ret = true;
+#ifdef GL_ARB_sync
+	if (mSync)
+	{
+		GLenum status = glClientWaitSync(mSync, 0, 1);
+		if (status == GL_TIMEOUT_EXPIRED)
+		{
+			ret = false;
+		}
+	}
+#endif
+	return ret;
+}
+
+void LLGLSyncFence::wait()
+{
+#ifdef GL_ARB_sync
+	if (mSync)
+	{
+		while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED)
+		{ //track the number of times we've waited here
+			static S32 waits = 0;
+			waits++;
+		}
+	}
+#endif
+}
+
+
+

indra/llrender/llgl.h

 	BOOL mHasDepthClamp;
 	BOOL mHasTextureRectangle;
 	BOOL mHasTextureMultisample;
+	BOOL mHasTransformFeedback;
 	S32 mMaxSampleMaskWords;
 	S32 mMaxColorTextureSamples;
 	S32 mMaxDepthTextureSamples;
 	S32 mGLSLVersionMajor;
 	S32 mGLSLVersionMinor;
 	std::string mDriverVersionVendorString;
+	std::string mGLVersionString;
 
 	S32 mVRAM; // VRAM in MB
 	S32 mGLMaxVertexRange;
 	virtual void updateGL() = 0;
 };
 
+const U32 FENCE_WAIT_TIME_NANOSECONDS = 1000;  //1 ms
+
+class LLGLFence
+{
+public:
+	virtual void placeFence() = 0;
+	virtual bool isCompleted() = 0;
+	virtual void wait() = 0;
+};
+
+class LLGLSyncFence : public LLGLFence
+{
+public:
+#ifdef GL_ARB_sync
+	GLsync mSync;
+#endif
+	
+	LLGLSyncFence();
+	virtual ~LLGLSyncFence();
+
+	void placeFence();
+	bool isCompleted();
+	void wait();
+};
+
 extern LLMatrix4 gGLObliqueProjectionInverse;
 
 #include "llglstates.h"
 
 void init_glstates();
 
-void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific );
+void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific, std::string* version_string );
 
 extern BOOL gClothRipple;
 extern BOOL gHeadlessClient;

indra/llrender/llglheaders.h

 extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
 extern PFNGLSAMPLEMASKIPROC glSampleMaski;
 
+//transform feedback (4.0 core)
+extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;
+extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
+extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
+extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
+
+
 #elif LL_WINDOWS
 //----------------------------------------------------------------------------
 // LL_WINDOWS
 extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
 extern PFNGLSAMPLEMASKIPROC glSampleMaski;
 
+//transform feedback (4.0 core)
+extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;
+extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
+extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
+extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
+
 //GL_ARB_debug_output
 extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB;
 extern PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB;

indra/llrender/llglslshader.cpp

 }
 
 BOOL LLGLSLShader::createShader(vector<string> * attributes,
-								vector<string> * uniforms)
+								vector<string> * uniforms,
+								U32 varying_count,
+								const char** varyings)
 {
 	//reloading, reset matrix hash values
 	for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i)
 		mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1);
 	}
 
+#ifdef GL_INTERLEAVED_ATTRIBS
+	if (varying_count > 0 && varyings)
+	{
+		glTransformFeedbackVaryings(mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS);
+	}
+#endif
+
 	// Map attributes and uniforms
 	if (success)
 	{

indra/llrender/llglslshader.h

 
 	void unload();
 	BOOL createShader(std::vector<std::string> * attributes,
-						std::vector<std::string> * uniforms);
+						std::vector<std::string> * uniforms,
+						U32 varying_count = 0,
+						const char** varyings = NULL);
 	BOOL attachObject(std::string object);
 	void attachObject(GLhandleARB object);
 	void attachObjects(GLhandleARB* objects = NULL, S32 count = 0);

indra/llrender/llimagegl.cpp

 //----------------------------------------------------------------------------
 const F32 MIN_TEXTURE_LIFETIME = 10.f;
 
+//which power of 2 is i?
+//assumes i is a power of 2 > 0
+U32 wpo2(U32 i);
+
 //statics
 
 U32 LLImageGL::sUniqueCount				= 0;
 S32 LLImageGL::sBoundTextureMemoryInBytes		= 0;
 S32 LLImageGL::sCurBoundTextureMemory	= 0;
 S32 LLImageGL::sCount					= 0;
-std::list<U32> LLImageGL::sDeadTextureList;
+LLImageGL::dead_texturelist_t LLImageGL::sDeadTextureList[LLTexUnit::TT_NONE];
+U32 LLImageGL::sCurTexName = 1;
 
 BOOL LLImageGL::sGlobalUseAnisotropic	= FALSE;
 F32 LLImageGL::sLastFrameTime			= 0.f;
 	mTarget = GL_TEXTURE_2D;
 	mBindTarget = LLTexUnit::TT_TEXTURE;
 	mHasMipMaps = false;
+	mMipLevels = -1;
 
 	mIsResident = 0;
 
 		is_compressed = true;
 	}
 
+	
+	
+	if (mUseMipMaps)
+	{
+		//set has mip maps to true before binding image so tex parameters get set properly
+		gGL.getTexUnit(0)->unbind(mBindTarget);
+		mHasMipMaps = true;
+		mTexOptionsDirty = true;
+		setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+	}
+	else
+	{
+		mHasMipMaps = false;
+	}
+	
 	llverify(gGL.getTexUnit(0)->bind(this));
 	
+	
 	if (mUseMipMaps)
 	{
 		if (data_hasmips)
 				S32 w = getWidth(d);
 				S32 h = getHeight(d);
 				S32 gl_level = d-mCurrentDiscardLevel;
+
+				mMipLevels = llmax(mMipLevels, gl_level);
+
 				if (d > mCurrentDiscardLevel)
 				{
 					data_in -= dataFormatBytes(mFormatPrimary, w, h); // see above comment
 		{
 			if (mAutoGenMips)
 			{
-				if (!gGLManager.mHasFramebufferObject)
-				{
-					glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_GENERATE_MIPMAP_SGIS, TRUE);
-				}
 				stop_glerror();
 				{
 // 					LLFastTimer t2(FTM_TEMP4);
 					S32 w = getWidth(mCurrentDiscardLevel);
 					S32 h = getHeight(mCurrentDiscardLevel);
 
+					mMipLevels = wpo2(llmax(w, h));
+
+					//use legacy mipmap generation mode
+					glTexParameteri(mTarget, GL_GENERATE_MIPMAP, GL_TRUE);
+					
 					LLImageGL::setManualImage(mTarget, 0, mFormatInternal,
 								 w, h, 
 								 mFormatPrimary, mFormatType,
 						stop_glerror();
 					}
 				}
-
-				if (gGLManager.mHasFramebufferObject)
-				{
-					glGenerateMipmap(LLTexUnit::getInternalType(mBindTarget));
-				}
 			}
 			else
 			{
 				// Create mips by hand
-				// about 30% faster than autogen on ATI 9800, 50% slower on nVidia 4800
 				// ~4x faster than gluBuild2DMipmaps
 				S32 width = getWidth(mCurrentDiscardLevel);
 				S32 height = getHeight(mCurrentDiscardLevel);
 				const U8* cur_mip_data = 0;
 				S32 prev_mip_size = 0;
 				S32 cur_mip_size = 0;
+				
+				mMipLevels = nummips;
+
 				for (int m=0; m<nummips; m++)
 				{
 					if (m==0)
 		{
 			llerrs << "Compressed Image has mipmaps but data does not (can not auto generate compressed mips)" << llendl;
 		}
-		mHasMipMaps = true;
 	}
 	else
 	{
+		mMipLevels = 0;
 		S32 w = getWidth();
 		S32 h = getHeight();
 		if (is_compressed)
 			}
 
 		}
-		mHasMipMaps = false;
 	}
 	stop_glerror();
 	mGLTextureCreated = true;
 }
 
 // static
-void LLImageGL::generateTextures(S32 numTextures, U32 *textures)
+void LLImageGL::generateTextures(LLTexUnit::eTextureType type, U32 format, S32 numTextures, U32 *textures)
 {
-	glGenTextures(numTextures, (GLuint*)textures);
+	bool empty = true;
+
+	dead_texturelist_t::iterator iter = sDeadTextureList[type].find(format);
+	
+	if (iter != sDeadTextureList[type].end())
+	{
+		empty = iter->second.empty();
+	}
+	
+	for (S32 i = 0; i < numTextures; ++i)
+	{
+		if (!empty)
+		{
+			textures[i] = iter->second.front();
+			iter->second.pop_front();
+			empty = iter->second.empty();
+		}
+		else
+		{
+			textures[i] = sCurTexName++;
+		}
+	}
 }
 
 // static
-void LLImageGL::deleteTextures(S32 numTextures, U32 *textures, bool immediate)
+void LLImageGL::deleteTextures(LLTexUnit::eTextureType type, U32 format, S32 mip_levels, S32 numTextures, U32 *textures, bool immediate)
 {
-	for (S32 i = 0; i < numTextures; i++)
+	if (gGLManager.mInited)
 	{
-		sDeadTextureList.push_back(textures[i]);
+		if (format == 0 ||  type == LLTexUnit::TT_CUBE_MAP || mip_levels == -1)
+		{ //unknown internal format or unknown number of mip levels, not safe to reuse
+			glDeleteTextures(numTextures, textures);
+		}
+		else
+		{
+			for (S32 i = 0; i < numTextures; ++i)
+			{ //remove texture from VRAM by setting its size to zero
+				for (S32 j = 0; j <= mip_levels; j++)
+				{
+					gGL.getTexUnit(0)->bindManual(type, textures[i]);
+
+					glTexImage2D(LLTexUnit::getInternalType(type), j, format, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+				}
+
+				llassert(std::find(sDeadTextureList[type][format].begin(),
+								   sDeadTextureList[type][format].end(), textures[i]) == 
+								   sDeadTextureList[type][format].end());
+
+				sDeadTextureList[type][format].push_back(textures[i]);
+			}	
+		}
 	}
-
-	if (immediate)
+	
+	/*if (immediate)
 	{
 		LLImageGL::deleteDeadTextures();
-	}
+	}*/
 }
 
 // static
 
 	if(mTexName)
 	{
-		glDeleteTextures(1, (reinterpret_cast<GLuint*>(&mTexName))) ;
+		LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, (reinterpret_cast<GLuint*>(&mTexName))) ;
 	}
 	
-	glGenTextures(1, (GLuint*)&mTexName);
+
+	LLImageGL::generateTextures(mBindTarget, mFormatInternal, 1, &mTexName);
 	stop_glerror();
 	if (!mTexName)
 	{
 	}
 	else
 	{
-		LLImageGL::generateTextures(1, &mTexName);
+		LLImageGL::generateTextures(mBindTarget, mFormatInternal, 1, &mTexName);
 		stop_glerror();
 		{
 			llverify(gGL.getTexUnit(0)->bind(this));
 	{
 		sGlobalTextureMemoryInBytes -= mTextureMemory;
 
-		LLImageGL::deleteTextures(1, &old_name);
+		LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, &old_name);
 
 		stop_glerror();
 	}
 {
 	bool reset = false;
 
-	while (!sDeadTextureList.empty())
+	/*while (!sDeadTextureList.empty())
 	{
 		GLuint tex = sDeadTextureList.front();
 		sDeadTextureList.pop_front();
 		
 		glDeleteTextures(1, &tex);
 		stop_glerror();
-	}
+	}*/
 
 	if (reset)
 	{
 			mTextureMemory = 0;
 		}
 		
-		LLImageGL::deleteTextures(1, &mTexName);			
+		LLImageGL::deleteTextures(mBindTarget,  mFormatInternal, mMipLevels, 1, &mTexName);			
 		mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.
 		mTexName = 0;		
 		mGLTextureCreated = FALSE ;

indra/llrender/llimagegl.h

 {
 	friend class LLTexUnit;
 public:
-	static std::list<U32> sDeadTextureList;
+	static U32 sCurTexName;
 
+	//previously used but now available texture names
+	// sDeadTextureList[<usage>][<internal format>]
+	typedef std::map<U32, std::list<U32> > dead_texturelist_t;
+	static dead_texturelist_t sDeadTextureList[LLTexUnit::TT_NONE];
+
+	// These 2 functions replace glGenTextures() and glDeleteTextures()
+	static void generateTextures(LLTexUnit::eTextureType type, U32 format, S32 numTextures, U32 *textures);
+	static void deleteTextures(LLTexUnit::eTextureType type, U32 format, S32 mip_levels, S32 numTextures, U32 *textures, bool immediate = false);
 	static void deleteDeadTextures();
 
 	// Size calculation
 	void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;}
 	void setAllowCompression(bool allow) { mAllowCompression = allow; }
 
-	// These 3 functions currently wrap glGenTextures(), glDeleteTextures(), and glTexImage2D() 
-	// for tracking purposes and will be deprecated in the future
-	static void generateTextures(S32 numTextures, U32 *textures);
-	static void deleteTextures(S32 numTextures, U32 *textures, bool immediate = false);
 	static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression = true);
 
 	BOOL createGLTexture() ;
 	LLGLenum mTarget;		// Normally GL_TEXTURE2D, sometimes something else (ex. cube maps)
 	LLTexUnit::eTextureType mBindTarget;	// Normally TT_TEXTURE, sometimes something else (ex. cube maps)
 	bool mHasMipMaps;
-	
+	S32 mMipLevels;
+
 	LLGLboolean mIsResident;
 	
 	S8 mComponents;

indra/llrender/llrender.cpp

 
 	if (mIndex < 0) return;
 
+	//always flush and activate for consistency 
+	//   some code paths assume unbind always flushes and sets the active texture
+	gGL.flush();
+	activate();
+
 	// Disabled caching of binding state.
 	if (mCurrTexType == type)
 	{
-		gGL.flush();
-
-		activate();
 		mCurrTexture = 0;
 		if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE)
 		{
 	} 
 	else if (option >= TFO_BILINEAR)
 	{
-		glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+		if (mHasMipMaps)
+		{
+			glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+		}
+		else
+		{
+			glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+		}
 	}
 	else
 	{
-		glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+		if (mHasMipMaps)
+		{
+			glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+		}
+		else
+		{
+			glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+		}
 	}
 
 	if (gGLManager.mHasAnisotropic)

indra/llrender/llrendertarget.cpp

 LLRenderTarget::LLRenderTarget() :
 	mResX(0),
 	mResY(0),
-	mTex(0),
 	mFBO(0),
 	mDepth(0),
 	mStencil(0),
 	}
 
 	U32 tex;
-	LLImageGL::generateTextures(1, &tex);
+	LLImageGL::generateTextures(mUsage, color_fmt, 1, &tex);
 	gGL.getTexUnit(0)->bindManual(mUsage, tex);
 
 	stop_glerror();
 	}
 
 	mTex.push_back(tex);
+	mInternalFormat.push_back(color_fmt);
 
 	if (gDebugGL)
 	{ //bind and unbind to validate target
 	}
 	else
 	{
-		LLImageGL::generateTextures(1, &mDepth);
+		LLImageGL::generateTextures(mUsage, GL_DEPTH_COMPONENT24, 1, &mDepth);
 		gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
 		
 		U32 internal_type = LLTexUnit::getInternalType(mUsage);
 		}
 		else
 		{
-			LLImageGL::deleteTextures(1, &mDepth, true);
+			LLImageGL::deleteTextures(mUsage, 0, 0, 1, &mDepth, true);
 			stop_glerror();
 		}
 		mDepth = 0;
 	if (mTex.size() > 0)
 	{
 		sBytesAllocated -= mResX*mResY*4*mTex.size();
-		LLImageGL::deleteTextures(mTex.size(), &mTex[0], true);
+		LLImageGL::deleteTextures(mUsage, mInternalFormat[0], 0, mTex.size(), &mTex[0], true);
 		mTex.clear();
+		mInternalFormat.clear();
 	}
 	
 	mResX = mResY = 0;

indra/llrender/llrendertarget.h

 	U32 mResX;
 	U32 mResY;
 	std::vector<U32> mTex;
+	std::vector<U32> mInternalFormat;
 	U32 mFBO;
 	U32 mDepth;
 	bool mStencil;

indra/llrender/llshadermgr.cpp

 	mReservedUniforms.push_back("size");
 	mReservedUniforms.push_back("falloff");
 
+	mReservedUniforms.push_back("box_center");
+	mReservedUniforms.push_back("box_size");
+
 
 	mReservedUniforms.push_back("minLuminance");
 	mReservedUniforms.push_back("maxExtractAlpha");

indra/llrender/llshadermgr.h

 		LIGHT_CENTER,
 		LIGHT_SIZE,
 		LIGHT_FALLOFF,
+		BOX_CENTER,
+		BOX_SIZE,
 
 		GLOW_MIN_LUMINANCE,
 		GLOW_MAX_EXTRACT_ALPHA,

indra/llrender/llvertexbuffer.cpp

 #if LL_DARWIN
 #define LL_VBO_POOLING 1
 #else
-#define LL_VBO_POOLING 0
 #endif
-
 //Next Highest Power Of Two
 //helper function, returns first number > v that is a power of 2, or v if v is already a power of 2
 U32 nhpo2(U32 v)
 
 
 const U32 LL_VBO_BLOCK_SIZE = 2048;
+const U32 LL_VBO_POOL_MAX_SEED_SIZE = 256*1024;
 
 U32 vbo_block_size(U32 size)
 { //what block size will fit size?
 	return vbo_block_size(size)/LL_VBO_BLOCK_SIZE;
 }
 
+const U32 LL_VBO_POOL_SEED_COUNT = vbo_block_index(LL_VBO_POOL_MAX_SEED_SIZE);
 
 
 //============================================================================
 
 U32 LLVBOPool::sBytesPooled = 0;
 U32 LLVBOPool::sIndexBytesPooled = 0;
+U32 LLVBOPool::sCurGLName = 1;
+
+std::list<U32> LLVertexBuffer::sAvailableVAOName;
+U32 LLVertexBuffer::sCurVAOName = 1;
+
 U32 LLVertexBuffer::sAllocatedIndexBytes = 0;
 U32 LLVertexBuffer::sIndexCount = 0;
 
 bool LLVertexBuffer::sUseVAO = false;
 bool LLVertexBuffer::sPreferStreamDraw = false;
 
-const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000;  //1 ms
 
-class LLGLSyncFence : public LLGLFence
+U32 LLVBOPool::genBuffer()
 {
-public:
-#ifdef GL_ARB_sync
-	GLsync mSync;
-#endif
-	
-	LLGLSyncFence()
+	U32 ret = 0;
+
+	if (mGLNamePool.empty())
 	{
-#ifdef GL_ARB_sync
-		mSync = 0;
-#endif
+		ret = sCurGLName++;
+	}
+	else
+	{
+		ret = mGLNamePool.front();
+		mGLNamePool.pop_front();
 	}
 
-	virtual ~LLGLSyncFence()
+	return ret;
+}
+
+void LLVBOPool::deleteBuffer(U32 name)
+{
+	if (gGLManager.mInited)
 	{
-#ifdef GL_ARB_sync
-		if (mSync)
-		{
-			glDeleteSync(mSync);
-		}
-#endif
+		LLVertexBuffer::unbind();
+
+		glBindBufferARB(mType, name);
+		glBufferDataARB(mType, 0, NULL, mUsage);
+
+		llassert(std::find(mGLNamePool.begin(), mGLNamePool.end(), name) == mGLNamePool.end());
+
+		mGLNamePool.push_back(name);
+
+		glBindBufferARB(mType, 0);
 	}
+}
 
-	void placeFence()
-	{
-#ifdef GL_ARB_sync
-		if (mSync)
-		{
-			glDeleteSync(mSync);
-		}
-		mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
-#endif
-	}
 
-	void wait()
-	{
-#ifdef GL_ARB_sync
-		if (mSync)
-		{
-			while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED)
-			{ //track the number of times we've waited here
-				static S32 waits = 0;
-				waits++;
-			}
-		}
-#endif
-	}
+LLVBOPool::LLVBOPool(U32 vboUsage, U32 vboType)
+: mUsage(vboUsage), mType(vboType)
+{
+	mMissCount.resize(LL_VBO_POOL_SEED_COUNT);
+	std::fill(mMissCount.begin(), mMissCount.end(), 0);
+}
 
-
-};
-
-
-volatile U8* LLVBOPool::allocate(U32& name, U32 size)
+volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed)
 {
 	llassert(vbo_block_size(size) == size);
 	
 	volatile U8* ret = NULL;
 
-#if LL_VBO_POOLING
-
 	U32 i = vbo_block_index(size);
 
 	if (mFreeList.size() <= i)
 		mFreeList.resize(i+1);
 	}
 
-	if (mFreeList[i].empty())
+	if (mFreeList[i].empty() || for_seed)
 	{
 		//make a new buffer
-		glGenBuffersARB(1, &name);
+		name = genBuffer();
+		
 		glBindBufferARB(mType, name);
 
+		if (!for_seed && i < LL_VBO_POOL_SEED_COUNT)
+		{ //record this miss
+			mMissCount[i]++;	
+		}
+
 		if (mType == GL_ARRAY_BUFFER_ARB)
 		{
 			LLVertexBuffer::sAllocatedBytes += size;
 		}
 
 		glBindBufferARB(mType, 0);
+
+		if (for_seed)
+		{ //put into pool for future use
+			llassert(mFreeList.size() > i);
+
+			Record rec;
+			rec.mGLName = name;
+			rec.mClientData = ret;
+	
+			if (mType == GL_ARRAY_BUFFER_ARB)
+			{
+				sBytesPooled += size;
+			}
+			else
+			{
+				sIndexBytesPooled += size;
+			}
+			mFreeList[i].push_back(rec);
+		}
 	}
 	else
 	{
 
 		mFreeList[i].pop_front();
 	}
-#else //no pooling
-
-	glGenBuffersARB(1, &name);
-	glBindBufferARB(mType, name);
-
-	if (mType == GL_ARRAY_BUFFER_ARB)
-	{
-		LLVertexBuffer::sAllocatedBytes += size;
-	}
-	else
-	{
-		LLVertexBuffer::sAllocatedIndexBytes += size;
-	}
-
-	if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)
-	{
-		glBufferDataARB(mType, size, 0, mUsage);
-		ret = (U8*) ll_aligned_malloc_16(size);
-	}
-	else
-	{ //always use a true hint of static draw when allocating non-client-backed buffers
-		glBufferDataARB(mType, size, 0, GL_STATIC_DRAW_ARB);
-	}
-
-	glBindBufferARB(mType, 0);
-
-#endif
 
 	return ret;
 }
 {
 	llassert(vbo_block_size(size) == size);
 
-#if LL_VBO_POOLING
-
-	U32 i = vbo_block_index(size);
-
-	llassert(mFreeList.size() > i);
-
-	Record rec;
-	rec.mGLName = name;
-	rec.mClientData = buffer;
-	
-	if (buffer == NULL)
-	{
-		glDeleteBuffersARB(1, &rec.mGLName);
-	}
-	else
-	{
-		if (mType == GL_ARRAY_BUFFER_ARB)
-		{
-			sBytesPooled += size;
-		}
-		else
-		{
-			sIndexBytesPooled += size;
-		}
-		mFreeList[i].push_back(rec);
-	}
-#else //no pooling
-	glDeleteBuffersARB(1, &name);
+	deleteBuffer(name);
 	ll_aligned_free_16((U8*) buffer);
 
 	if (mType == GL_ARRAY_BUFFER_ARB)
 	{
 		LLVertexBuffer::sAllocatedIndexBytes -= size;
 	}
-#endif
 }
 
+void LLVBOPool::seedPool()
+{
+	U32 dummy_name = 0;
+
+	if (mFreeList.size() < LL_VBO_POOL_SEED_COUNT)
+	{
+		mFreeList.resize(LL_VBO_POOL_SEED_COUNT);
+	}
+
+	for (U32 i = 0; i < LL_VBO_POOL_SEED_COUNT; i++)
+	{
+		if (mMissCount[i] > mFreeList[i].size())
+		{ 
+			U32 size = i*LL_VBO_BLOCK_SIZE;
+		
+			S32 count = mMissCount[i] - mFreeList[i].size();
+			for (U32 j = 0; j < count; ++j)
+			{
+				allocate(dummy_name, size, true);
+			}
+		}
+	}
+}
+
+
 void LLVBOPool::cleanup()
 {
-	U32 size = 1;
+	U32 size = LL_VBO_BLOCK_SIZE;
 
 	for (U32 i = 0; i < mFreeList.size(); ++i)
 	{
 		{
 			Record& r = l.front();
 
-			glDeleteBuffersARB(1, &r.mGLName);
-
+			deleteBuffer(r.mGLName);
+			
 			if (r.mClientData)
 			{
 				ll_aligned_free_16((void*) r.mClientData);
 			}
 		}
 
-		size *= 2;
+		size += LL_VBO_BLOCK_SIZE;
 	}
+
+	//reset miss counts
+	std::fill(mMissCount.begin(), mMissCount.end(), 0);
 }
 
 
 	GL_LINE_LOOP,
 };
 
+//static
+U32 LLVertexBuffer::getVAOName()
+{
+	U32 ret = 0;
+
+	if (!sAvailableVAOName.empty())
+	{
+		ret = sAvailableVAOName.front();
+		sAvailableVAOName.pop_front();
+	}
+	else
+	{
+#ifdef GL_ARB_vertex_array_object
+		glGenVertexArrays(1, &ret);
+#endif
+	}
+
+	return ret;		
+}
+
+//static
+void LLVertexBuffer::releaseVAOName(U32 name)
+{
+	sAvailableVAOName.push_back(name);
+}
+
+
+//static
+void LLVertexBuffer::seedPools()
+{
+	sStreamVBOPool.seedPool();
+	sDynamicVBOPool.seedPool();
+	sStreamIBOPool.seedPool();
+	sDynamicIBOPool.seedPool();
+}
 
 //static
 void LLVertexBuffer::setupClientArrays(U32 data_mask)
 	if (mGLArray)
 	{
 #if GL_ARB_vertex_array_object
-		glDeleteVertexArrays(1, &mGLArray);
+		releaseVAOName(mGLArray);
 #endif
 	}
 
 
 	llassert(nverts >= 0);
 
-	if (nverts >= 65535)
+	if (nverts > 65536)
 	{
 		llwarns << "Vertex buffer overflow!" << llendl;
-		nverts = 65535;
+		nverts = 65536;
 	}
 
 	U32 needed_size = calcOffsets(mTypeMask, mOffsets, nverts);
 		if (gGLManager.mHasVertexArrayObject && useVBOs() && (LLRender::sGLCoreProfile || sUseVAO))
 		{
 #if GL_ARB_vertex_array_object
-			glGenVertexArrays(1, &mGLArray);
+			mGLArray = getVAOName();
 #endif
 			setupVertexArray();
 		}
 	}
 }
 
+// bind for transform feedback (quick 'n dirty)
+void LLVertexBuffer::bindForFeedback(U32 channel, U32 type, U32 index, U32 count)
+{
+#ifdef GL_TRANSFORM_FEEDBACK_BUFFER
+	U32 offset = mOffsets[type] + sTypeSize[type]*index;
+	U32 size= (sTypeSize[type]*count);
+	glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, channel, mGLBuffer, offset, size);
+#endif
+}
+
 // Set for rendering
 void LLVertexBuffer::setBuffer(U32 data_mask)
 {
 	stop_glerror();
 	volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData;
 
-	/*if ((data_mask & mTypeMask) != data_mask)
+	if (gDebugGL && ((data_mask & mTypeMask) != data_mask))
 	{
 		llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl;
-	}*/
+	}
 
 	if (LLGLSLShader::sNoFixedFunction)
 	{

indra/llrender/llvertexbuffer.h

 	static U32 sBytesPooled;
 	static U32 sIndexBytesPooled;
 	
-	LLVBOPool(U32 vboUsage, U32 vboType)
-		: mUsage(vboUsage)
-		, mType(vboType)
-	{}
+	static U32 sCurGLName;
 
+	LLVBOPool(U32 vboUsage, U32 vboType);
+		
 	const U32 mUsage;
 	const U32 mType;
 
 	//size MUST be a power of 2
-	volatile U8* allocate(U32& name, U32 size);
+	volatile U8* allocate(U32& name, U32 size, bool for_seed = false);
 	
 	//size MUST be the size provided to allocate that returned the given name
 	void release(U32 name, volatile U8* buffer, U32 size);
 	
+	//batch allocate buffers to be provided to the application on demand
+	void seedPool();
+
 	//destroy all records in mFreeList
 	void cleanup();
 
+	U32 genBuffer();
+	void deleteBuffer(U32 name);
+
 	class Record
 	{
 	public:
 		volatile U8* mClientData;
 	};
 
+	std::list<U32> mGLNamePool;
+
 	typedef std::list<Record> record_list_t;
 	std::vector<record_list_t> mFreeList;
+	std::vector<U32> mMissCount;
+
 };
 
-class LLGLFence
-{
-public:
-	virtual void placeFence() = 0;
-	virtual void wait() = 0;
-};
 
 //============================================================================
 // base class 
 	static LLVBOPool sStreamIBOPool;
 	static LLVBOPool sDynamicIBOPool;
 
+	static std::list<U32> sAvailableVAOName;
+	static U32 sCurVAOName;
+
 	static bool	sUseStreamDraw;
 	static bool sUseVAO;
 	static bool	sPreferStreamDraw;
 
+	static void seedPools();
+
+	static U32 getVAOName();
+	static void releaseVAOName(U32 name);
+
 	static void initClass(bool use_vbo, bool no_vbo_mapping);
 	static void cleanupClass();
 	static void setupClientArrays(U32 data_mask);
+	static void pushPositions(U32 mode, const LLVector4a* pos, U32 count);
 	static void drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm);
 	static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp);
 
 	void 	destroyGLIndices();
 	void	updateNumVerts(S32 nverts);
 	void	updateNumIndices(S32 nindices); 
-	bool	useVBOs() const;
 	void	unmapBuffer();
 		
 public:
 	volatile U8*		mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range);
 	volatile U8*		mapIndexBuffer(S32 index, S32 count, bool map_range);
 
+	void bindForFeedback(U32 channel, U32 type, U32 index, U32 count);
+
 	// set for rendering
 	virtual void	setBuffer(U32 data_mask); 	// calls  setupVertexBuffer() if data_mask is not 0
 	void flush(); //flush pending data to GL memory
 	bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
 	bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
 	bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+	bool getTextureIndexStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
 	bool getEmissiveStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
 	bool getWeightStrider(LLStrider<F32>& strider, S32 index=0, S32 count = -1, bool map_range = false);
 	bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
 	bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
 	
 
+	bool useVBOs() const;
 	bool isEmpty() const					{ return mEmpty; }
 	bool isLocked() const					{ return mVertexLocked || mIndexLocked; }
 	S32 getNumVerts() const					{ return mNumVerts; }

indra/llui/llfloater.cpp

File contents unchanged.

indra/llui/llscrollcontainer.cpp

 		{
 			*show_h_scrollbar = TRUE;
 			*visible_height -= scrollbar_size;
-
+			// Note: Do *not* recompute *show_v_scrollbar here because with
 			// The view inside the scroll container should not be extended
 			// to container's full height to ensure the correct computation
 			// of *show_v_scrollbar after subtracting horizontal scrollbar_size.
 
-			// Must retest now that visible_height has changed
 			if( !*show_v_scrollbar && ((doc_height - *visible_height) > 1) )
 			{
 				*show_v_scrollbar = TRUE;

indra/llui/lltextbase.cpp

 	if (getLength() >= S32(mMaxTextByteLength / 4))
 	{	
 		// Have to check actual byte size
-		LLWString text(getWText());
-		S32 utf8_byte_size = wstring_utf8_length(text);
+		S32 utf8_byte_size = 0;
+		LLSD value = getViewModel()->getValue();
+		if (value.type() == LLSD::TypeString)
+		{
+			// save a copy for strings.
+			utf8_byte_size = value.size();
+		}
+		else
+		{
+			// non string LLSDs need explicit conversion to string
+			utf8_byte_size = value.asString().size();
+		}
+
 		if ( utf8_byte_size > mMaxTextByteLength )
 		{
 			// Truncate safely in UTF-8
-			std::string temp_utf8_text = wstring_to_utf8str(text);
+			std::string temp_utf8_text = value.asString();
 			temp_utf8_text = utf8str_truncate( temp_utf8_text, mMaxTextByteLength );
 			LLWString text = utf8str_to_wstring( temp_utf8_text );
 			// remove extra bit of current string, to preserve formatting, etc.
 
 S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::segment_vec_t* segments )
 {
-	LLWString text(getWText());
-	S32 old_len = text.length();		// length() returns character length
+	S32 old_len = getLength();		// length() returns character length
 	S32 insert_len = wstr.length();
 
 	pos = getEditableIndex(pos, true);
 		}
 	}
 
-	text.insert(pos, wstr);
-	getViewModel()->setDisplay(text);
+	getViewModel()->getEditableDisplay().insert(pos, wstr);
 
 	if ( truncate() )
 	{
 
 S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)
 {
-	LLWString text(getWText());
 	segment_set_t::iterator seg_iter = getSegIterContaining(pos);
 	while(seg_iter != mSegments.end())
 	{
 		++seg_iter;
 	}
 
-	text.erase(pos, length);
-	getViewModel()->setDisplay(text);
+	getViewModel()->getEditableDisplay().erase(pos, length);
 
 	// recreate default segment in case we erased everything
 	createDefaultSegment();
 	{
 		return 0;
 	}
-	LLWString text(getWText());
-	text[pos] = wc;
-	getViewModel()->setDisplay(text);
+	getViewModel()->getEditableDisplay()[pos] = wc;
 
 	onValueChange(pos, pos + 1);
 	needsReflow(pos);
 	}
 }
 
+static LLFastTimer::DeclareTimer FTM_PARSE_HTML("Parse HTML");
+
 void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params)
 {
 	LLStyle::Params style_params(input_params);
 	S32 part = (S32)LLTextParser::WHOLE;
 	if (mParseHTML && !style_params.is_link) // Don't search for URLs inside a link segment (STORM-358).
 	{
+		LLFastTimer _(FTM_PARSE_HTML);
 		S32 start=0,end=0;
 		LLUrlMatch match;
 		std::string text = new_text;
 	}
 }
 
+static LLFastTimer::DeclareTimer FTM_APPEND_TEXT("Append Text");
+
 void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params)
 {
+	LLFastTimer _(FTM_APPEND_TEXT);
 	if (new_text.empty()) 
 		return;
 

indra/llui/lltextbox.cpp

 
 LLSD LLTextBox::getValue() const
 {
-	return LLSD(getText());
+	return getViewModel()->getValue();
 }
 
 BOOL LLTextBox::setTextArg( const std::string& key, const LLStringExplicit& text )

indra/llui/llui.cpp

 
 	gGL.flush();
 	glLineWidth(2.5f);
-	glLineStipple(2, 0x3333 << shift);
+
+	if (!LLGLSLShader::sNoFixedFunction)
+	{
+		glLineStipple(2, 0x3333 << shift);
+	}
 
 	gGL.begin(LLRender::LINES);
 	{

indra/llui/llviewmodel.h

 	// New functions
     /// Get the stored value in string form
     const LLWString& getDisplay() const { return mDisplay; }
+	LLWString& getEditableDisplay() { mDirty = true; mUpdateFromDisplay = true; return mDisplay; }
 
     /**
      * Set the display string directly (see LLTextEditor). What the user is

indra/llwindow/llwindowwin32.cpp

 							 U32 fsaa_samples)
 	: LLWindow(callbacks, fullscreen, flags)
 {
+	
+	//MAINT-516 -- force a load of opengl32.dll just in case windows went sideways 
+	LoadLibrary(L"opengl32.dll");
+
 	mFSAASamples = fsaa_samples;
 	mIconResource = gIconResource;
 	mOverrideAspectRatio = 0.f;

indra/newview/app_settings/settings.xml

       <key>Value</key>
       <integer>1</integer>
     </map>
-    <key>ApplyTextureImmediately</key>
+    <key>TextureLivePreview</key>
     <map>
       <key>Comment</key>
       <string>Preview selections in texture picker immediately</string>
         <key>Value</key>
         <integer>0</integer>
     </map>
+    <key>InventoryInboxToggleState</key>
+    <map>
+        <key>Comment</key>
+        <string>Stores the open/closed state of inventory Received items panel</string>
+        <key>Persist</key>
+        <integer>1</integer>
+        <key>Type</key>
+        <string>Boolean</string>
+        <key>Value</key>
+        <integer>0</integer>
+    </map>
 	<key>InventoryLinking</key>
 	<map>
 		<key>Comment</key>
     <key>WebContentWindowLimit</key>
     <map>
       <key>Comment</key>
-      <string>Maximum number of web brower windows that can be open at once in the Web content floater (0 for no limit)</string>
+      <string>Maximum number of web browser windows that can be open at once in the Web content floater (0 for no limit)</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
     <real>0</real>
   </map>
 
+  <key>RenderDepthPrePass</key>
+  <map>
+    <key>Comment</key>
+    <string>EXPERIMENTAL: Prime the depth buffer with simple prim geometry before rendering with textures.</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
+  
   <key>RenderDepthOfField</key>
   <map>
     <key>Comment</key>
     <key>RenderUseVAO</key>
     <map>
       <key>Comment</key>
-      <string>Use GL Vertex Array Objects</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>0</integer>
-    </map>
-    <key>RenderVBOMappingDisable</key>
+      <string>[EXPERIMENTAL] Use GL Vertex Array Objects</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+  <key>RenderUseTransformFeedback</key>
+  <map>
+    <key>Comment</key>
+    <string>[EXPERIMENTAL] Use transform feedback shaders for LoD updates</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
+
+  <key>RenderVBOMappingDisable</key>
     <map>
       <key>Comment</key>
       <string>Disable VBO glMapBufferARB</string>
       <key>Value</key>
       <integer>1</integer>
     </map>
+  <key>RenderSynchronousOcclusion</key>
+  <map>
+    <key>Comment</key>
+    <string>Don't let occlusion queries get more than one frame behind (block until they complete).</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>1</integer>
+  </map>
     <key>RenderDelayVBUpdate</key>
     <map>
       <key>Comment</key>

indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl

 #define frag_color gl_FragColor
 #endif
 
+uniform float minimum_alpha;
+
 uniform sampler2DRect depthMap;
 uniform sampler2D diffuseMap;
 
 	
 	vec4 diff= texture2D(diffuseMap,vary_texcoord0.xy);
 
+	if (diff.a < minimum_alpha)
+	{
+		discard;
+	}
+
 	vec4 col = vec4(vary_ambient + vary_directional.rgb, 1.0);
 	vec4 color = diff * col;
 	
+	
 	color.rgb = atmosLighting(color.rgb);
 
 	color.rgb = scaleSoftClip(color.rgb);

indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl

 
 uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
 uniform float sun_wash;
-uniform int proj_shadow_idx;
-uniform float shadow_fade;
 
 uniform vec3 center;
 uniform vec3 color;
 		discard;
 	}
 		
-	vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0;
+	vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
+	norm = vec3((norm.xy-0.5)*2.0, norm.z);
 	
 	norm = normalize(norm);
 	float l_dist = -dot(lv, proj_n);

indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl

 uniform vec3 env_mat[3];
 uniform float sun_wash;
 
-uniform vec3 center;
 uniform vec3 color;
 uniform float falloff;
 uniform float size;
 
 VARYING vec4 vary_fragcoord;
+VARYING vec3 trans_center;
+
 uniform vec2 screen_res;
 
 uniform mat4 inv_proj;
 	frag.xy *= screen_res;
 	
 	vec3 pos = getPosition(frag.xy).xyz;
-	vec3 lv = center.xyz-pos;
+	vec3 lv = trans_center.xyz-pos;
 	float dist2 = dot(lv,lv);
 	dist2 /= size;
 	if (dist2 > 1.0)

indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl

  */
 
 uniform mat4 modelview_projection_matrix;
+uniform mat4 modelview_matrix;
 
 ATTRIBUTE vec3 position;
 
+uniform vec3 center;
+uniform float size;
+
 VARYING vec4 vary_fragcoord;
+VARYING vec3 trans_center;
 
 void main()
 {
 	//transform vertex
-	vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
+	vec3 p = position*sqrt(size)+center;
+	vec4 pos = modelview_projection_matrix * vec4(p.xyz, 1.0);
 	vary_fragcoord = pos;
-		
+	trans_center = (modelview_matrix*vec4(center.xyz, 1.0)).xyz;
 	gl_Position = pos;
 }

indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl

+/** 
+ * @file shadowCubeV.glsl
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2007, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+uniform mat4 modelview_projection_matrix;
+
+ATTRIBUTE vec3 position;
+
+VARYING vec4 post_pos;
+
+uniform vec3 box_center;
+uniform vec3 box_size;
+
+void main()
+{
+	//transform vertex
+	vec3 p = position*box_size+box_center;
+	vec4 pos = modelview_projection_matrix*vec4(p.xyz, 1.0);
+	
+	post_pos = pos;
+	
+	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+}

indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl

  */
 
  
-#extension GL_ARB_texture_rectangle : enable
-
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_color;
 #else
 #define frag_color gl_FragColor
 #endif
 
+//class 1 -- no shadows
+
+#extension GL_ARB_texture_rectangle : enable
+
 uniform sampler2DRect diffuseRect;
 uniform sampler2DRect specularRect;
 uniform sampler2DRect depthMap;
 uniform sampler2DRect normalMap;
+uniform samplerCube environmentMap;
 uniform sampler2D noiseMap;
 uniform sampler2D projectionMap;
 
 uniform float proj_focus; //distance from plane to begin blurring
 uniform float proj_lod;  //(number of mips in proj map)
 uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambient_lod;
 uniform float proj_ambiance;
 uniform float near_clip;
 uniform float far_clip;
 uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
 uniform float sun_wash;
 
-uniform vec3 center;
 uniform vec3 color;
 uniform float falloff;
 uniform float size;
 
 VARYING vec4 vary_fragcoord;
+VARYING vec3 trans_center;
+
 uniform vec2 screen_res;
 
 uniform mat4 inv_proj;
 
+vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
+{
+	vec4 ret = texture2DLod(projectionMap, tc, lod);
+	
+	vec2 dist = tc-vec2(0.5);
+	
+	float det = max(1.0-lod/(proj_lod*0.5), 0.0);
+	
+	float d = dot(dist,dist);
+