diff options
116 files changed, 4050 insertions, 1837 deletions
| @@ -287,6 +287,9 @@ d5f263687f43f278107363365938f0a214920a4b 3.3.0-beta1  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 diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index e295e3c621..8276ec836a 100644 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp @@ -269,6 +269,7 @@ namespace  		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 diff --git a/indra/llcommon/llstrider.h b/indra/llcommon/llstrider.h index f4c43bac61..ed9284d2c5 100644 --- a/indra/llcommon/llstrider.h +++ b/indra/llcommon/llstrider.h @@ -44,6 +44,15 @@ public:  	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; } @@ -51,6 +60,7 @@ public:  	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)); }  }; diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 76cf9de613..2e6f9e2f71 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -54,6 +54,7 @@ class LLVolumeTriangle;  #include "llstrider.h"  #include "v4coloru.h"  #include "llrefcount.h" +#include "llpointer.h"  #include "llfile.h"  //============================================================================ @@ -919,6 +920,10 @@ public:  	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 diff --git a/indra/llmessage/llsdmessagereader.cpp b/indra/llmessage/llsdmessagereader.cpp index 3d8ca2ad9f..a6fccd2a56 100644 --- a/indra/llmessage/llsdmessagereader.cpp +++ b/indra/llmessage/llsdmessagereader.cpp @@ -276,7 +276,7 @@ S32 getElementSize(const LLSD& llsd)  	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: diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index 45a3b18179..362452d837 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -81,7 +81,7 @@ void LLCubeMap::initGL()  		{  			U32 texname = 0; -			LLImageGL::generateTextures(1, &texname); +			LLImageGL::generateTextures(LLTexUnit::TT_CUBE_MAP, GL_RGB8, 1, &texname);  			for (int i = 0; i < 6; i++)  			{ diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 628a8d6131..0b56b3889c 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -249,6 +249,12 @@ PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample = NULL;  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; @@ -421,6 +427,7 @@ LLGLManager::LLGLManager() :  	mHasDrawBuffers(FALSE),  	mHasTextureRectangle(FALSE),  	mHasTextureMultisample(FALSE), +	mHasTransformFeedback(FALSE),  	mMaxSampleMaskWords(0),  	mMaxColorTextureSamples(0),  	mMaxDepthTextureSamples(0), @@ -558,7 +565,8 @@ bool LLGLManager::initGL()  	parse_gl_version( &mDriverVersionMajor,   		&mDriverVersionMinor,   		&mDriverVersionRelease,  -		&mDriverVersionVendorString ); +		&mDriverVersionVendorString, +		&mGLVersionString);  	mGLVersion = mDriverVersionMajor + mDriverVersionMinor * .1f; @@ -938,7 +946,6 @@ void LLGLManager::initExtensions()  	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"); @@ -963,11 +970,14 @@ void LLGLManager::initExtensions()  							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 @@ -1207,7 +1217,14 @@ void LLGLManager::initExtensions()  		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"); @@ -1964,6 +1981,7 @@ LLGLState::LLGLState(LLGLenum state, S32 enabled) :  			case GL_COLOR_MATERIAL:  			case GL_FOG:  			case GL_LINE_STIPPLE: +			case GL_POLYGON_STIPPLE:  				mState = 0;  				break;  		} @@ -2052,7 +2070,7 @@ void LLGLManager::initGLStates()  //////////////////////////////////////////////////////////////////////////////// -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>] @@ -2068,6 +2086,8 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor  		return;  	} +	version_string->assign(version); +  	std::string ver_copy( version );  	S32 len = (S32)strlen( version );	/* Flawfinder: ignore */  	S32 i = 0; @@ -2429,3 +2449,65 @@ LLGLSquashToFarClip::~LLGLSquashToFarClip()  	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 +} + + + diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 5a33c98708..964495a3ab 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -104,6 +104,7 @@ public:  	BOOL mHasDepthClamp;  	BOOL mHasTextureRectangle;  	BOOL mHasTextureMultisample; +	BOOL mHasTransformFeedback;  	S32 mMaxSampleMaskWords;  	S32 mMaxColorTextureSamples;  	S32 mMaxDepthTextureSamples; @@ -141,6 +142,7 @@ public:  	S32 mGLSLVersionMajor;  	S32 mGLSLVersionMinor;  	std::string mDriverVersionVendorString; +	std::string mGLVersionString;  	S32 mVRAM; // VRAM in MB  	S32 mGLMaxVertexRange; @@ -417,13 +419,38 @@ public:  	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; diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index d61ec707f0..a0727b8686 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -528,6 +528,13 @@ extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;  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 @@ -759,6 +766,12 @@ extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;  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; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 4b7e639aed..7cbf39096e 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -129,7 +129,9 @@ void LLGLSLShader::unload()  }  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) @@ -172,6 +174,13 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,  		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)  	{ diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 7873fe3c4e..5c68cb46eb 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -76,7 +76,9 @@ public:  	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); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index c04a3f6b41..659d3ca409 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -42,6 +42,10 @@  //----------------------------------------------------------------------------  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; @@ -50,7 +54,8 @@ S32 LLImageGL::sGlobalTextureMemoryInBytes		= 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; @@ -416,6 +421,7 @@ void LLImageGL::init(BOOL usemipmaps)  	mTarget = GL_TEXTURE_2D;  	mBindTarget = LLTexUnit::TT_TEXTURE;  	mHasMipMaps = false; +	mMipLevels = -1;  	mIsResident = 0; @@ -606,8 +612,24 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  		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) @@ -620,6 +642,9 @@ void LLImageGL::setImage(const U8* data_in, BOOL 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 @@ -662,10 +687,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  		{  			if (mAutoGenMips)  			{ -				if (!gGLManager.mHasFramebufferObject) -				{ -					glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_GENERATE_MIPMAP_SGIS, TRUE); -				}  				stop_glerror();  				{  // 					LLFastTimer t2(FTM_TEMP4); @@ -679,6 +700,11 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  					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, @@ -694,16 +720,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  						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); @@ -713,6 +733,9 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  				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) @@ -777,10 +800,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  		{  			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) @@ -812,7 +835,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  			}  		} -		mHasMipMaps = false;  	}  	stop_glerror();  	mGLTextureCreated = true; @@ -1025,23 +1047,65 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_  }  // 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()); -	if (immediate) +				sDeadTextureList[type][format].push_back(textures[i]); +			}	 +		} +	} +	 +	/*if (immediate)  	{  		LLImageGL::deleteDeadTextures(); -	} +	}*/  }  // static @@ -1166,10 +1230,11 @@ BOOL LLImageGL::createGLTexture()  	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)  	{ @@ -1282,7 +1347,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_  	}  	else  	{ -		LLImageGL::generateTextures(1, &mTexName); +		LLImageGL::generateTextures(mBindTarget, mFormatInternal, 1, &mTexName);  		stop_glerror();  		{  			llverify(gGL.getTexUnit(0)->bind(this)); @@ -1327,7 +1392,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_  	{  		sGlobalTextureMemoryInBytes -= mTextureMemory; -		LLImageGL::deleteTextures(1, &old_name); +		LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, &old_name);  		stop_glerror();  	} @@ -1456,7 +1521,7 @@ void LLImageGL::deleteDeadTextures()  {  	bool reset = false; -	while (!sDeadTextureList.empty()) +	/*while (!sDeadTextureList.empty())  	{  		GLuint tex = sDeadTextureList.front();  		sDeadTextureList.pop_front(); @@ -1478,7 +1543,7 @@ void LLImageGL::deleteDeadTextures()  		glDeleteTextures(1, &tex);  		stop_glerror(); -	} +	}*/  	if (reset)  	{ @@ -1496,7 +1561,7 @@ void LLImageGL::destroyGLTexture()  			mTextureMemory = 0;  		} -		LLImageGL::deleteTextures(1, &mTexName);			 +		LLImageGL::deleteTextures(mBindTarget,  mFormatInternal, mMipLevels, 1, &mTexName);			  		mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.  		mTexName = 0;		  		mGLTextureCreated = FALSE ; diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index f34b9fa91a..e118c28c1b 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -45,8 +45,16 @@ class LLImageGL : public LLRefCount  {  	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 @@ -96,10 +104,6 @@ public:  	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() ; @@ -217,7 +221,8 @@ protected:  	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; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 93bac4c779..348c1eb1b7 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -408,12 +408,14 @@ void LLTexUnit::unbind(eTextureType type)  	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)  		{ @@ -464,11 +466,25 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio  	}   	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) diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 780f1dc484..99f0da330c 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -55,7 +55,6 @@ bool LLRenderTarget::sUseFBO = false;  LLRenderTarget::LLRenderTarget() :  	mResX(0),  	mResY(0), -	mTex(0),  	mFBO(0),  	mDepth(0),  	mStencil(0), @@ -135,7 +134,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)  	}  	U32 tex; -	LLImageGL::generateTextures(1, &tex); +	LLImageGL::generateTextures(mUsage, color_fmt, 1, &tex);  	gGL.getTexUnit(0)->bindManual(mUsage, tex);  	stop_glerror(); @@ -193,6 +192,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)  	}  	mTex.push_back(tex); +	mInternalFormat.push_back(color_fmt);  	if (gDebugGL)  	{ //bind and unbind to validate target @@ -217,7 +217,7 @@ bool LLRenderTarget::allocateDepth()  	}  	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); @@ -294,7 +294,7 @@ void LLRenderTarget::release()  		}  		else  		{ -			LLImageGL::deleteTextures(1, &mDepth, true); +			LLImageGL::deleteTextures(mUsage, 0, 0, 1, &mDepth, true);  			stop_glerror();  		}  		mDepth = 0; @@ -326,8 +326,9 @@ void LLRenderTarget::release()  	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; diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index 2735ab21c5..8360458840 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -142,6 +142,7 @@ protected:  	U32 mResX;  	U32 mResY;  	std::vector<U32> mTex; +	std::vector<U32> mInternalFormat;  	U32 mFBO;  	U32 mDepth;  	bool mStencil; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 5a6e6cab3e..d3b2d9fa74 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1026,6 +1026,9 @@ void LLShaderMgr::initAttribsAndUniforms()  	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"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index f792faa8f0..7a16b7c20f 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -97,6 +97,8 @@ public:  		LIGHT_CENTER,  		LIGHT_SIZE,  		LIGHT_FALLOFF, +		BOX_CENTER, +		BOX_SIZE,  		GLOW_MIN_LUMINANCE,  		GLOW_MAX_EXTRACT_ALPHA, diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 823c6b9dc5..953546a36f 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -41,9 +41,7 @@  #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) @@ -71,6 +69,7 @@ U32 wpo2(U32 i)  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? @@ -83,6 +82,7 @@ U32 vbo_block_index(U32 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);  //============================================================================ @@ -95,6 +95,11 @@ LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_  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; @@ -119,69 +124,55 @@ bool LLVertexBuffer::sUseStreamDraw = true;  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() -	{ -#ifdef GL_ARB_sync -		mSync = 0; -#endif -	} +	U32 ret = 0; -	virtual ~LLGLSyncFence() +	if (mGLNamePool.empty())  	{ -#ifdef GL_ARB_sync -		if (mSync) -		{ -			glDeleteSync(mSync); -		} -#endif +		ret = sCurGLName++;  	} - -	void placeFence() +	else  	{ -#ifdef GL_ARB_sync -		if (mSync) -		{ -			glDeleteSync(mSync); -		} -		mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); -#endif +		ret = mGLNamePool.front(); +		mGLNamePool.pop_front();  	} -	void wait() +	return ret; +} + +void LLVBOPool::deleteBuffer(U32 name) +{ +	if (gGLManager.mInited)  	{ -#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 -	} +		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); +	} +} -}; +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) @@ -189,12 +180,18 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size)  		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; @@ -215,6 +212,25 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 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  	{ @@ -232,33 +248,6 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size)  		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;  } @@ -267,50 +256,47 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)  {  	llassert(vbo_block_size(size) == size); -#if LL_VBO_POOLING - -	U32 i = vbo_block_index(size); - -	llassert(mFreeList.size() > i); +	deleteBuffer(name); +	ll_aligned_free_16((U8*) buffer); -	Record rec; -	rec.mGLName = name; -	rec.mClientData = buffer; -	 -	if (buffer == NULL) +	if (mType == GL_ARRAY_BUFFER_ARB)  	{ -		glDeleteBuffersARB(1, &rec.mGLName); +		LLVertexBuffer::sAllocatedBytes -= size;  	}  	else  	{ -		if (mType == GL_ARRAY_BUFFER_ARB) -		{ -			sBytesPooled += size; -		} -		else -		{ -			sIndexBytesPooled += size; -		} -		mFreeList[i].push_back(rec); +		LLVertexBuffer::sAllocatedIndexBytes -= size;  	} -#else //no pooling -	glDeleteBuffersARB(1, &name); -	ll_aligned_free_16((U8*) buffer); +} -	if (mType == GL_ARRAY_BUFFER_ARB) +void LLVBOPool::seedPool() +{ +	U32 dummy_name = 0; + +	if (mFreeList.size() < LL_VBO_POOL_SEED_COUNT)  	{ -		LLVertexBuffer::sAllocatedBytes -= size; +		mFreeList.resize(LL_VBO_POOL_SEED_COUNT);  	} -	else + +	for (U32 i = 0; i < LL_VBO_POOL_SEED_COUNT; i++)  	{ -		LLVertexBuffer::sAllocatedIndexBytes -= size; +		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); +			} +		}  	} -#endif  } +  void LLVBOPool::cleanup()  { -	U32 size = 1; +	U32 size = LL_VBO_BLOCK_SIZE;  	for (U32 i = 0; i < mFreeList.size(); ++i)  	{ @@ -320,8 +306,8 @@ void LLVBOPool::cleanup()  		{  			Record& r = l.front(); -			glDeleteBuffersARB(1, &r.mGLName); - +			deleteBuffer(r.mGLName); +			  			if (r.mClientData)  			{  				ll_aligned_free_16((void*) r.mClientData); @@ -341,8 +327,11 @@ void LLVBOPool::cleanup()  			}  		} -		size *= 2; +		size += LL_VBO_BLOCK_SIZE;  	} + +	//reset miss counts +	std::fill(mMissCount.begin(), mMissCount.end(), 0);  } @@ -376,6 +365,41 @@ U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] =  	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) @@ -985,7 +1009,7 @@ LLVertexBuffer::~LLVertexBuffer()  	if (mGLArray)  	{  #if GL_ARB_vertex_array_object -		glDeleteVertexArrays(1, &mGLArray); +		releaseVAOName(mGLArray);  #endif  	} @@ -1211,10 +1235,10 @@ void LLVertexBuffer::updateNumVerts(S32 nverts)  	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); @@ -1270,7 +1294,7 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)  		if (gGLManager.mHasVertexArrayObject && useVBOs() && (LLRender::sGLCoreProfile || sUseVAO))  		{  #if GL_ARB_vertex_array_object -			glGenVertexArrays(1, &mGLArray); +			mGLArray = getVAOName();  #endif  			setupVertexArray();  		} @@ -2140,6 +2164,16 @@ void LLVertexBuffer::flush()  	}  } +// 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)  { @@ -2291,10 +2325,10 @@ void LLVertexBuffer::setupVertexBuffer(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)  	{ diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 7477dec3ad..11fa4ab6a0 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -57,23 +57,28 @@ public:  	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: @@ -81,17 +86,15 @@ 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   class LLPrivateMemoryPool; @@ -125,13 +128,22 @@ public:  	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); @@ -208,7 +220,6 @@ protected:  	void 	destroyGLIndices();  	void	updateNumVerts(S32 nverts);  	void	updateNumIndices(S32 nindices);  -	bool	useVBOs() const;  	void	unmapBuffer();  public: @@ -218,6 +229,8 @@ 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 @@ -240,12 +253,14 @@ public:  	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; } diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index 9b7e30bb04..2fd187a526 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -389,12 +389,11 @@ void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height  		{  			*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; diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 661ec589d7..3815eec447 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -291,12 +291,23 @@ bool LLTextBase::truncate()  	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. @@ -728,8 +739,7 @@ void LLTextBase::drawText()  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); @@ -789,8 +799,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s  		}  	} -	text.insert(pos, wstr); -	getViewModel()->setDisplay(text); +	getViewModel()->getEditableDisplay().insert(pos, wstr);  	if ( truncate() )  	{ @@ -805,7 +814,6 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s  S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)  { -	LLWString text(getWText());  	segment_set_t::iterator seg_iter = getSegIterContaining(pos);  	while(seg_iter != mSegments.end())  	{ @@ -851,8 +859,7 @@ S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)  		++seg_iter;  	} -	text.erase(pos, length); -	getViewModel()->setDisplay(text); +	getViewModel()->getEditableDisplay().erase(pos, length);  	// recreate default segment in case we erased everything  	createDefaultSegment(); @@ -869,9 +876,7 @@ S32 LLTextBase::overwriteCharNoUndo(S32 pos, llwchar wc)  	{  		return 0;  	} -	LLWString text(getWText()); -	text[pos] = wc; -	getViewModel()->setDisplay(text); +	getViewModel()->getEditableDisplay()[pos] = wc;  	onValueChange(pos, pos + 1);  	needsReflow(pos); @@ -1914,6 +1919,8 @@ static LLUIImagePtr image_from_icon_name(const std::string& icon_name)  	}  } +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); @@ -1922,6 +1929,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para  	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; @@ -1988,8 +1996,11 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para  	}  } +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; diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 6a905b7ec0..11cfa1d263 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -150,7 +150,7 @@ S32 LLTextBox::getTextPixelHeight()  LLSD LLTextBox::getValue() const  { -	return LLSD(getText()); +	return getViewModel()->getValue();  }  BOOL LLTextBox::setTextArg( const std::string& key, const LLStringExplicit& text ) diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index b5e27616b7..87bf518aa1 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -831,7 +831,11 @@ void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LL  	gGL.flush();  	glLineWidth(2.5f); -	glLineStipple(2, 0x3333 << shift); + +	if (!LLGLSLShader::sNoFixedFunction) +	{ +		glLineStipple(2, 0x3333 << shift); +	}  	gGL.begin(LLRender::LINES);  	{ diff --git a/indra/llui/llviewmodel.h b/indra/llui/llviewmodel.h index 763af5d8a2..ef2e314799 100644 --- a/indra/llui/llviewmodel.h +++ b/indra/llui/llviewmodel.h @@ -102,6 +102,7 @@ public:  	// 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 diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index e07fbddb94..6f0d90be06 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -367,6 +367,10 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,  							 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; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 2f6811c26f..5e50bd6e01 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -148,7 +148,7 @@        <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> @@ -4304,6 +4304,17 @@          <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> @@ -7274,7 +7285,7 @@      <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> @@ -8093,6 +8104,18 @@      <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> @@ -9172,7 +9195,7 @@      <key>RenderUseVAO</key>      <map>        <key>Comment</key> -      <string>Use GL Vertex Array Objects</string> +      <string>[EXPERIMENTAL] Use GL Vertex Array Objects</string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key> @@ -9180,7 +9203,19 @@        <key>Value</key>        <integer>0</integer>      </map> -    <key>RenderVBOMappingDisable</key> +  <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> @@ -12228,6 +12263,17 @@        <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> diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl index cb87b754b4..1113a9845b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl @@ -31,6 +31,8 @@ out vec4 frag_color;  #define frag_color gl_FragColor  #endif +uniform float minimum_alpha; +  uniform sampler2DRect depthMap;  uniform sampler2D diffuseMap; @@ -70,9 +72,15 @@ void main()  	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); diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl index 75de47614c..bff87cb6aa 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl @@ -55,8 +55,6 @@ uniform float far_clip;  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; @@ -143,7 +141,8 @@ void main()  		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); diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index 19800a8b8e..f671d5b750 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -42,12 +42,13 @@ uniform sampler2DRect depthMap;  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; @@ -74,7 +75,7 @@ void main()  	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) diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl index cb14e6d4e8..9491421236 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl @@ -24,16 +24,22 @@   */  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;  } diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl new file mode 100644 index 0000000000..6195e2f1ec --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl @@ -0,0 +1,44 @@ +/**  + * @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); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl index 7ed8ed3370..cca63872de 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl @@ -24,18 +24,21 @@   */ -#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; @@ -46,6 +49,7 @@ uniform vec3 proj_n;  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; @@ -53,19 +57,66 @@ 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); +		 +	ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); +	 +	return ret; +} + +vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) +{ +	vec4 ret = texture2DLod(projectionMap, tc, lod); +	 +	vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); +	 +	float det = min(lod/(proj_lod*0.5), 1.0); +	 +	float d = min(dist.x, dist.y); +	 +	float edge = 0.25*det; +		 +	ret *= clamp(d/edge, 0.0, 1.0); +	 +	return ret; +} + +vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) +{ +	vec4 ret = texture2DLod(projectionMap, tc, lod); +	 +	vec2 dist = tc-vec2(0.5); +	 +	float d = dot(dist,dist); +		 +	ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0); +	 +	return ret; +} + +  vec4 getPosition(vec2 pos_screen)  { -	float depth = texture2DRect(depthMap, pos_screen.xy).a; +	float depth = texture2DRect(depthMap, pos_screen.xy).r;  	vec2 sc = pos_screen.xy*2.0;  	sc /= screen_res;  	sc -= vec2(1.0,1.0); @@ -84,16 +135,16 @@ void main()  	frag.xy *= screen_res;  	vec3 pos = getPosition(frag.xy).xyz; -	vec3 lv = center.xyz-pos.xyz; +	vec3 lv = trans_center.xyz-pos.xyz;  	float dist2 = dot(lv,lv);  	dist2 /= size;  	if (dist2 > 1.0)  	{  		discard;  	} -	 +		  	vec3 norm = texture2DRect(normalMap, frag.xy).xyz; -	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm +	norm = vec3((norm.xy-0.5)*2.0, norm.z);  	norm = normalize(norm);  	float l_dist = -dot(lv, proj_n); @@ -107,7 +158,11 @@ void main()  	proj_tc.xyz /= proj_tc.w;  	float fa = falloff+1.0; -	float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); +	float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0); +	if (dist_atten <= 0.0) +	{ +		discard; +	}  	lv = proj_origin-pos.xyz;  	lv = normalize(lv); @@ -125,32 +180,32 @@ void main()  		proj_tc.y > 0.0)  	{  		float lit = 0.0; +		float amb_da = proj_ambiance; +		  		if (da > 0.0)  		{  			float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);  			float lod = diff * proj_lod; -			vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); +			vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);  			vec3 lcol = color.rgb * plcol.rgb * plcol.a;  			lit = da * dist_atten * noise;  			col = lcol*lit*diff_tex; +			amb_da += (da*0.5)*proj_ambiance;  		} -		float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); -		float lod = diff * proj_lod; -		vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod); -		//float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0)); -		float amb_da = proj_ambiance; -		 +		//float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); +		vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); +							  		amb_da += (da*da*0.5+0.5)*proj_ambiance; -			 +				  		amb_da *= dist_atten * noise; -		 +			  		amb_da = min(amb_da, 1.0-lit); -		 +			  		col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;  	} @@ -168,18 +223,22 @@ void main()  		{  			vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; -			vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz; +			vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));  			if (stc.z > 0.0)  			{ -				stc.xy /= stc.z+proj_near; -					 +				stc.xy /= stc.w; + +				float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0); +				 +				stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); +								  				if (stc.x < 1.0 &&  					stc.y < 1.0 &&  					stc.x > 0.0 &&  					stc.y > 0.0)  				{ -					vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); +					vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);  					col += dist_atten*scol.rgb*color.rgb*scol.a*spec.rgb;  				}  			} diff --git a/indra/newview/app_settings/shaders/class1/interface/clipF.glsl b/indra/newview/app_settings/shaders/class1/interface/clipF.glsl new file mode 100644 index 0000000000..ac2bc8703b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/clipF.glsl @@ -0,0 +1,46 @@ +/**  + * @file debugF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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$ + */ + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif + +uniform vec4 color; +uniform vec4 clip_plane; + +VARYING vec3 vary_position; + + +void main()  +{ +	if (dot(vary_position,clip_plane.xyz)+clip_plane.w < 0.0) +	{ +		discard; +	} + +	frag_color = color; +} diff --git a/indra/newview/app_settings/shaders/class1/interface/clipV.glsl b/indra/newview/app_settings/shaders/class1/interface/clipV.glsl new file mode 100644 index 0000000000..e376b25a71 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/clipV.glsl @@ -0,0 +1,38 @@ +/**  + * @file debugV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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; +uniform mat4 modelview_matrix; + +ATTRIBUTE vec3 position; + +VARYING vec3 vary_position; + +void main() +{ +	vary_position = (modelview_matrix*vec4(position.xyz,1.0)).xyz; +	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); +} + diff --git a/indra/newview/app_settings/shaders/class1/interface/occlusionCubeV.glsl b/indra/newview/app_settings/shaders/class1/interface/occlusionCubeV.glsl new file mode 100644 index 0000000000..5c479d27a9 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/occlusionCubeV.glsl @@ -0,0 +1,38 @@ +/**  + * @file occlusionCubeV.glsl + * + * $LicenseInfo:firstyear=2007&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; + +uniform vec3 box_center; +uniform vec3 box_size; + +void main() +{ +	vec3 p = position*box_size+box_center; +	gl_Position = modelview_projection_matrix * vec4(p.xyz, 1.0); +} + diff --git a/indra/newview/app_settings/shaders/class1/transform/binormalV.glsl b/indra/newview/app_settings/shaders/class1/transform/binormalV.glsl new file mode 100644 index 0000000000..44f1aa34a0 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/transform/binormalV.glsl @@ -0,0 +1,36 @@ +/** + * @file binormalV.glsl + * + * $LicenseInfo:firstyear=2007&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 mat3 normal_matrix; + +ATTRIBUTE vec3 binormal; + +VARYING vec4 binormal_out; + +void main() +{ +	binormal_out = vec4(normal_matrix * binormal, 0.0); +} + diff --git a/indra/newview/app_settings/shaders/class1/transform/colorV.glsl b/indra/newview/app_settings/shaders/class1/transform/colorV.glsl new file mode 100644 index 0000000000..59c4a7d895 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/transform/colorV.glsl @@ -0,0 +1,36 @@ +/** + * @file colorV.glsl + * + * $LicenseInfo:firstyear=2007&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 int color_in; + +ATTRIBUTE vec3 position; + +VARYING int color_out; + +void main() +{ +	color_out = color_in; +} + diff --git a/indra/newview/app_settings/shaders/class1/transform/normalV.glsl b/indra/newview/app_settings/shaders/class1/transform/normalV.glsl new file mode 100644 index 0000000000..a213aa0ae8 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/transform/normalV.glsl @@ -0,0 +1,36 @@ +/** + * @file normalV.glsl + * + * $LicenseInfo:firstyear=2007&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 mat3 normal_matrix; + +ATTRIBUTE vec3 normal; + +VARYING vec4 normal_out; + +void main() +{ +	normal_out = vec4(normalize(normal_matrix * normal), 0.0); +} + diff --git a/indra/newview/app_settings/shaders/class1/transform/positionV.glsl b/indra/newview/app_settings/shaders/class1/transform/positionV.glsl new file mode 100644 index 0000000000..01eed18de4 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/transform/positionV.glsl @@ -0,0 +1,40 @@ +/** + * @file positionV.glsl + * + * $LicenseInfo:firstyear=2007&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_matrix; + +uniform int texture_index_in; + +ATTRIBUTE vec3 position; + +VARYING vec3 position_out; +VARYING int texture_index_out; + +void main() +{ +	texture_index_out = texture_index_in; +	position_out = (modelview_matrix*vec4(position, 1.0)).xyz; +} + diff --git a/indra/newview/app_settings/shaders/class1/transform/texcoordV.glsl b/indra/newview/app_settings/shaders/class1/transform/texcoordV.glsl new file mode 100644 index 0000000000..0e074f3cec --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/transform/texcoordV.glsl @@ -0,0 +1,35 @@ +/** + * @file texcoordV.glsl + * + * $LicenseInfo:firstyear=2007&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$ + */ + + +ATTRIBUTE vec2 texcoord0; + +VARYING vec2 texcoord_out; + +void main() +{ +	texcoord_out = texcoord0; +} + diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl index ba6f3ace53..2093fc37dc 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl @@ -31,6 +31,8 @@ out vec4 frag_color;  #define frag_color gl_FragColor  #endif +uniform float minimum_alpha; +  uniform sampler2DRectShadow shadowMap0;  uniform sampler2DRectShadow shadowMap1;  uniform sampler2DRectShadow shadowMap2; @@ -97,6 +99,13 @@ void main()  	float shadow = 0.0;  	vec4 pos = vec4(vary_position, 1.0); +	vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy); + +	if (diff.a < minimum_alpha) +	{ +		discard; +	} +	  	vec4 spos = pos;  	if (spos.z > -shadow_clip.w) @@ -164,8 +173,6 @@ void main()  		shadow = 1.0;  	} -	vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy); -  	vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, 1.0);  	vec4 color = diff * col; diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index 99a277fbfc..ab077d9e02 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -31,8 +31,6 @@ out vec4 frag_color;  #define frag_color gl_FragColor  #endif -VARYING vec4 vertex_color; -  uniform sampler2DRect diffuseRect;  uniform sampler2DRect specularRect;  uniform sampler2DRect depthMap; @@ -49,6 +47,7 @@ uniform vec3 proj_n;  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; @@ -58,16 +57,65 @@ uniform float sun_wash;  uniform int proj_shadow_idx;  uniform float shadow_fade; -VARYING vec4 vary_light; +uniform float size; +uniform vec3 color; +uniform float falloff; +VARYING vec3 trans_center;  VARYING vec4 vary_fragcoord;  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); +		 +	ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); +	 +	return ret; +} + +vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) +{ +	vec4 ret = texture2DLod(projectionMap, tc, lod); +	 +	vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); +	 +	float det = min(lod/(proj_lod*0.5), 1.0); +	 +	float d = min(dist.x, dist.y); +	 +	float edge = 0.25*det; +		 +	ret *= clamp(d/edge, 0.0, 1.0); +	 +	return ret; +} + +vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) +{ +	vec4 ret = texture2DLod(projectionMap, tc, lod); +	 +	vec2 dist = tc-vec2(0.5); +	 +	float d = dot(dist,dist); +		 +	ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0); +	 +	return ret; +} + +  vec4 getPosition(vec2 pos_screen)  { -	float depth = texture2DRect(depthMap, pos_screen.xy).a; +	float depth = texture2DRect(depthMap, pos_screen.xy).r;  	vec2 sc = pos_screen.xy*2.0;  	sc /= screen_res;  	sc -= vec2(1.0,1.0); @@ -85,6 +133,15 @@ void main()  	frag.xyz = frag.xyz*0.5+0.5;  	frag.xy *= screen_res; +	vec3 pos = getPosition(frag.xy).xyz; +	vec3 lv = trans_center.xyz-pos.xyz; +	float dist2 = dot(lv,lv); +	dist2 /= size; +	if (dist2 > 1.0) +	{ +		discard; +	} +	  	float shadow = 1.0;  	if (proj_shadow_idx >= 0) @@ -96,15 +153,6 @@ void main()  		shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0);  	} -	vec3 pos = getPosition(frag.xy).xyz; -	vec3 lv = vary_light.xyz-pos.xyz; -	float dist2 = dot(lv,lv); -	dist2 /= vary_light.w; -	if (dist2 > 1.0) -	{ -		discard; -	} -	  	vec3 norm = texture2DRect(normalMap, frag.xy).xyz;  	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm @@ -119,8 +167,12 @@ void main()  	proj_tc.xyz /= proj_tc.w; -	float fa = vertex_color.a+1.0; -	float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); +	float fa = falloff+1.0; +	float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0); +	if (dist_atten <= 0.0) +	{ +		discard; +	}  	lv = proj_origin-pos.xyz;  	lv = normalize(lv); @@ -138,37 +190,33 @@ void main()  		proj_tc.y > 0.0)  	{  		float lit = 0.0; +		float amb_da = proj_ambiance; +		  		if (da > 0.0)  		{  			float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);  			float lod = diff * proj_lod; -			vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); +			vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); -			vec3 lcol = vertex_color.rgb * plcol.rgb * plcol.a; +			vec3 lcol = color.rgb * plcol.rgb * plcol.a;  			lit = da * dist_atten * noise;  			col = lcol*lit*diff_tex*shadow; -		} -		 -		float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); -		float lod = diff * proj_lod; -		vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod); -		//float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0)); -		float amb_da = proj_ambiance; -		if (da > 0.0) -		{  			amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;  		} +		//float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); +		vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); +							  		amb_da += (da*da*0.5+0.5)*proj_ambiance; -			 +				  		amb_da *= dist_atten * noise; -		 +			  		amb_da = min(amb_da, 1.0-lit); -		 -		col += amb_da*vertex_color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; +			 +		col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;  	} @@ -185,19 +233,23 @@ void main()  		{  			vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; -			vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz; +			vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));  			if (stc.z > 0.0)  			{ -				stc.xy /= stc.z+proj_near; -					 +				stc.xy /= stc.w; + +				float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0); +				 +				stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); +								  				if (stc.x < 1.0 &&  					stc.y < 1.0 &&  					stc.x > 0.0 &&  					stc.y > 0.0)  				{ -					vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); -					col += dist_atten*scol.rgb*vertex_color.rgb*scol.a*spec.rgb*shadow; +					vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); +					col += dist_atten*scol.rgb*color.rgb*scol.a*spec.rgb*shadow;  				}  			}  		} diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index e8a109e661..eeb632acaf 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -520,6 +520,7 @@ Disregard128DefaultDrawDistance	1	0  list ATIOldDriver  RenderAvatarVP				0	0  RenderAvatarCloth			0	0 +RenderVBOEnable				1	0  // ATI cards generally perform better when not using VBOs for streaming data diff --git a/indra/newview/featuretable_xp.txt b/indra/newview/featuretable_xp.txt index 398a64378e..a945f7a693 100644 --- a/indra/newview/featuretable_xp.txt +++ b/indra/newview/featuretable_xp.txt @@ -517,6 +517,7 @@ Disregard128DefaultDrawDistance	1	0  list ATIOldDriver  RenderAvatarVP				0	0  RenderAvatarCloth			0	0 +RenderVBOEnable				1	0  // ATI cards generally perform better when not using VBOs for streaming data diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b4d205adb5..efa24796e5 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1165,6 +1165,8 @@ void LLAppViewer::checkMemory()  static LLFastTimer::DeclareTimer FTM_MESSAGES("System Messages");  static LLFastTimer::DeclareTimer FTM_SLEEP("Sleep"); +static LLFastTimer::DeclareTimer FTM_YIELD("Yield"); +  static LLFastTimer::DeclareTimer FTM_TEXTURE_CACHE("Texture Cache");  static LLFastTimer::DeclareTimer FTM_DECODE("Image Decode");  static LLFastTimer::DeclareTimer FTM_VFS("VFS Thread"); @@ -1350,6 +1352,7 @@ bool LLAppViewer::mainLoop()  				// yield some time to the os based on command line option  				if(mYieldTime >= 0)  				{ +					LLFastTimer t(FTM_YIELD);  					ms_sleep(mYieldTime);  				} diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index f530d10ddc..84e73e96fa 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -495,7 +495,7 @@ protected:  	void showInfoCtrl()  	{ -		if (mAvatarID.isNull() || mFrom.empty() || SYSTEM_FROM == mFrom) return; +		if (mAvatarID.isNull() || mFrom.empty() || CHAT_SOURCE_SYSTEM == mSourceType) return;  		if (!sInfoCtrl)  		{ @@ -689,8 +689,11 @@ void LLChatHistory::clear()  	mLastFromID = LLUUID::null;  } +static LLFastTimer::DeclareTimer FTM_APPEND_MESSAGE("Append Chat Message"); +  void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LLStyle::Params& input_append_params)  { +	LLFastTimer _(FTM_APPEND_MESSAGE);  	bool use_plain_text_chat_history = args["use_plain_text_chat_history"].asBoolean();  	llassert(mEditor); @@ -783,7 +786,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  			timestamp_style.color(timestamp_color);  			timestamp_style.readonly_color(timestamp_color);  		} -		mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getText().size() != 0, timestamp_style); +		mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getLength() != 0, timestamp_style);  		if (utf8str_trim(chat.mFromName).size() != 0)  		{ @@ -842,7 +845,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		else  		{  			view = getHeader(chat, style_params, args); -			if (mEditor->getText().size() == 0) +			if (mEditor->getLength() == 0)  				p.top_pad = 0;  			else  				p.top_pad = mTopHeaderPad; diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 21b21c152a..98246162f0 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -450,7 +450,7 @@ void LLDrawable::makeStatic(BOOL warning_enabled)  {  	if (isState(ACTIVE))  	{ -		clearState(ACTIVE); +		clearState(ACTIVE | ANIMATED_CHILD);  		if (mParent.notNull() && mParent->isActive() && warning_enabled)  		{ @@ -538,9 +538,9 @@ F32 LLDrawable::updateXform(BOOL undamped)  			target_rot = new_rot;  			target_scale = new_scale;  		} -		else +		else if (mVObjp->getAngularVelocity().isExactlyZero())  		{ -			// snap to final position +			// snap to final position (only if no target omega is applied)  			dist_squared = 0.0f;  			if (getVOVolume() && !isRoot())  			{ //child prim snapping to some position, needs a rebuild @@ -549,15 +549,25 @@ F32 LLDrawable::updateXform(BOOL undamped)  		}  	} -	if ((mCurrentScale != target_scale) || -		(!isRoot() &&  -		 (dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED ||  -		 !mVObjp->getAngularVelocity().isExactlyZero() || -		 target_pos != mXform.getPosition() || -		 target_rot != mXform.getRotation()))) -	{ //child prim moving or scale change requires immediate rebuild +	LLVector3 vec = mCurrentScale-target_scale; +	 +	if (vec*vec > MIN_INTERPOLATE_DISTANCE_SQUARED) +	{ //scale change requires immediate rebuild +		mCurrentScale = target_scale;  		gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);  	} +	else if (!isRoot() &&  +		 (!mVObjp->getAngularVelocity().isExactlyZero() || +			dist_squared > 0.f)) +	{ //child prim moving relative to parent, tag as needing to be rendered atomically and rebuild +		dist_squared = 1.f; //keep this object on the move list +		if (!isState(LLDrawable::ANIMATED_CHILD)) +		{			 +			setState(LLDrawable::ANIMATED_CHILD); +			gPipeline.markRebuild(this, LLDrawable::REBUILD_ALL, TRUE); +			mVObjp->dirtySpatialGroup(); +		} +	}  	else if (!getVOVolume() && !isAvatar())  	{  		movePartition(); @@ -568,9 +578,7 @@ F32 LLDrawable::updateXform(BOOL undamped)  	mXform.setRotation(target_rot);  	mXform.setScale(LLVector3(1,1,1)); //no scale in drawable transforms (IT'S A RULE!)  	mXform.updateMatrix(); -	 -	mCurrentScale = target_scale; -	 +  	if (mSpatialBridge)  	{  		gPipeline.markMoved(mSpatialBridge, FALSE); @@ -596,7 +604,11 @@ void LLDrawable::moveUpdatePipeline(BOOL moved)  	// Update the face centers.  	for (S32 i = 0; i < getNumFaces(); i++)  	{ -		getFace(i)->updateCenterAgent(); +		LLFace* face = getFace(i); +		if (face) +		{ +			face->updateCenterAgent(); +		}  	}  } @@ -651,7 +663,6 @@ BOOL LLDrawable::updateMoveUndamped()  	}  	mVObjp->clearChanged(LLXform::MOVED); -	  	return TRUE;  } @@ -727,7 +738,8 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update)  				for (S32 i = 0; i < getNumFaces(); i++)  				{  					LLFace* facep = getFace(i); -					if (force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA) +					if (facep &&  +						(force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA))  					{  						LLVector4a box;  						box.setSub(facep->mExtents[1], facep->mExtents[0]); @@ -826,13 +838,16 @@ void LLDrawable::shiftPos(const LLVector4a &shift_vector)  		for (S32 i = 0; i < getNumFaces(); i++)  		{  			LLFace *facep = getFace(i); -			facep->mCenterAgent += LLVector3(shift_vector.getF32ptr()); -			facep->mExtents[0].add(shift_vector); -			facep->mExtents[1].add(shift_vector); -			 -			if (!volume && facep->hasGeometry()) +			if (facep)  			{ -				facep->clearVertexBuffer(); +				facep->mCenterAgent += LLVector3(shift_vector.getF32ptr()); +				facep->mExtents[0].add(shift_vector); +				facep->mExtents[1].add(shift_vector); +			 +				if (!volume && facep->hasGeometry()) +				{ +					facep->clearVertexBuffer(); +				}  			}  		} @@ -954,7 +969,10 @@ void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp)  		for (S32 i = 0; i < getNumFaces(); ++i)  		{  			LLFace* facep = getFace(i); -			facep->clearVertexBuffer(); +			if (facep) +			{ +				facep->clearVertexBuffer(); +			}  		}  	} @@ -1529,10 +1547,10 @@ BOOL LLDrawable::isAnimating() const  		return TRUE;  	} -	if (!isRoot() && !mVObjp->getAngularVelocity().isExactlyZero()) -	{ +	/*if (!isRoot() && !mVObjp->getAngularVelocity().isExactlyZero()) +	{ //target omega  		return TRUE; -	} +	}*/  	return FALSE;  } diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index e268640a21..e2064b79f8 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -277,6 +277,7 @@ public:  		HAS_ALPHA		= 0x04000000,  		RIGGED			= 0x08000000,  		PARTITION_MOVE	= 0x10000000, +		ANIMATED_CHILD  = 0x20000000,  	} EDrawableFlags;  private: //aligned members @@ -333,12 +334,14 @@ inline LLFace* LLDrawable::getFace(const S32 i) const  	if ((U32) i >= mFaces.size())  	{ -		llerrs << "Invalid face index." << llendl; +		llwarns << "Invalid face index." << llendl; +		return NULL;  	}  	if (!mFaces[i])  	{ -		llerrs << "Null face found." << llendl; +		llwarns << "Null face found." << llendl; +		return NULL;  	}  	return mFaces[i]; diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 5b62dbc560..5f2a982ed3 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -405,6 +405,12 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)  			{  				LLDrawInfo& params = **k; +				if ((params.mVertexBuffer->getTypeMask() & mask) != mask) +				{ //FIXME! +					llwarns << "Missing required components, skipping render batch." << llendl; +					continue; +				} +  				LLRenderPass::applyModelMatrix(params); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 0103373fd2..ace3a20bbb 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -261,7 +261,9 @@ void LLDrawPoolAvatar::beginPostDeferredAlpha()  	sRenderingSkinned = TRUE;  	gPipeline.bindDeferredShader(*sVertexProgram); -	 + +	sVertexProgram->setMinimumAlpha(0.2f); +  	sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);  } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 4108d69e82..49a20d5ef9 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -44,11 +44,14 @@  #include "llsky.h"  #include "llviewercamera.h"  #include "llviewertexturelist.h" +#include "llvopartgroup.h"  #include "llvosky.h"  #include "llvovolume.h"  #include "pipeline.h"  #include "llviewerregion.h"  #include "llviewerwindow.h" +#include "llviewershadermgr.h" +  #define LL_MAX_INDICES_COUNT 1000000 @@ -56,7 +59,6 @@ BOOL LLFace::sSafeRenderSelect = TRUE; // FALSE  #define DOTVEC(a,b) (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2]) -  /*  For each vertex, given:  	B - binormal @@ -161,7 +163,15 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)  	mGeomCount		= 0;  	mGeomIndex		= 0;  	mIndicesCount	= 0; -	mIndicesIndex	= 0; +	if (drawablep->getRenderType() == LLPipeline::RENDER_TYPE_PARTICLES || +		drawablep->getRenderType() == LLPipeline::RENDER_TYPE_HUD_PARTICLES) +	{ //indicate to LLParticlePartition that this particle is uninitialized +		mIndicesIndex = 0xFFFFFFFF; +	} +	else +	{ +		mIndicesIndex	= 0; +	}  	mIndexInTex = 0;  	mTexture		= NULL;  	mTEOffset		= -1; @@ -177,12 +187,6 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)  	mFaceColor = LLColor4(1,0,0,1); -	mLastVertexBuffer = mVertexBuffer; -	mLastGeomCount = mGeomCount; -	mLastGeomIndex = mGeomIndex; -	mLastIndicesCount = mIndicesCount; -	mLastIndicesIndex = mIndicesIndex; -  	mImportanceToCamera = 0.f ;  	mBoundingSphereRadius = 0.0f ; @@ -203,6 +207,15 @@ void LLFace::destroy()  		mTexture->removeFace(this) ;  	} +	if (mDrawablep.notNull() && +		(mDrawablep->getRenderType() == LLPipeline::RENDER_TYPE_PARTICLES || +		mDrawablep->getRenderType() == LLPipeline::RENDER_TYPE_HUD_PARTICLES) && +		mIndicesIndex != 0xFFFFFFFF) +	{ +		LLVOPartGroup::freeVBSlot(getGeomIndex()/4); +		mIndicesIndex = 0xFFFFFFFF; +	} +  	if (mDrawPoolp)  	{  		if (this->isState(LLFace::RIGGED) && mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR) @@ -372,7 +385,6 @@ void LLFace::setSize(S32 num_vertices, S32 num_indices, bool align)  		mGeomCount    = num_vertices;  		mIndicesCount = num_indices;  		mVertexBuffer = NULL; -		mLastVertexBuffer = NULL;  	}  	llassert(verify()); @@ -765,12 +777,6 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,  		LLMatrix4a mat_normal;  		mat_normal.loadu(mat_normal_in); -		//if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) -		//{ //vertex buffer no longer valid -		//	mVertexBuffer = NULL; -		//	mLastVertexBuffer = NULL; -		//} -  		//VECTORIZE THIS  		LLVector4a min,max; @@ -1032,30 +1038,13 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to,  LLVector2* res_st_offs  void LLFace::updateRebuildFlags()  { -	if (!mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) -	{ -		BOOL moved = TRUE; -		if (mLastVertexBuffer == mVertexBuffer &&  -			!mVertexBuffer->isEmpty()) -		{	//this face really doesn't need to be regenerated, try real hard not to do so -			if (mLastGeomCount == mGeomCount && -				mLastGeomIndex == mGeomIndex && -				mLastIndicesCount == mIndicesCount && -				mLastIndicesIndex == mIndicesIndex) -			{ //data is in same location in vertex buffer -				moved = FALSE; -			} -		} -		mLastMoveTime = gFrameTimeSeconds; -		 -		if (moved) -		{ -			mDrawablep->setState(LLDrawable::REBUILD_VOLUME); -		} +	if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) +	{ //this rebuild is zero overhead (direct consequence of some change that affects this face) +		mLastUpdateTime = gFrameTimeSeconds;  	}  	else -	{ -		mLastUpdateTime = gFrameTimeSeconds; +	{ //this rebuild is overhead (side effect of some change that does not affect this face) +		mLastMoveTime = gFrameTimeSeconds;  	}  } @@ -1094,6 +1083,73 @@ bool LLFace::canRenderAsMask()  } +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_VOLUME("Volume VB Cache"); + +//static  +void LLFace::cacheFaceInVRAM(const LLVolumeFace& vf) +{ +	LLFastTimer t(FTM_FACE_GEOM_VOLUME); +	U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | +				LLVertexBuffer::MAP_BINORMAL | LLVertexBuffer::MAP_NORMAL; +	 +	if (vf.mWeights) +	{ +		mask |= LLVertexBuffer::MAP_WEIGHT4; +	} + +	LLVertexBuffer* buff = new LLVertexBuffer(mask, GL_STATIC_DRAW_ARB); +	vf.mVertexBuffer = buff; + +	buff->allocateBuffer(vf.mNumVertices, 0, true); + +	LLStrider<LLVector4a> f_vert; +	LLStrider<LLVector3> f_binorm; +	LLStrider<LLVector3> f_norm; +	LLStrider<LLVector2> f_tc; + +	buff->getBinormalStrider(f_binorm); +	buff->getVertexStrider(f_vert); +	buff->getNormalStrider(f_norm); +	buff->getTexCoord0Strider(f_tc); + +	for (U32 i = 0; i < vf.mNumVertices; ++i) +	{ +		*f_vert++ = vf.mPositions[i]; +		(*f_binorm++).set(vf.mBinormals[i].getF32ptr()); +		*f_tc++ = vf.mTexCoords[i]; +		(*f_norm++).set(vf.mNormals[i].getF32ptr()); +	} + +	if (vf.mWeights) +	{ +		LLStrider<LLVector4> f_wght; +		buff->getWeight4Strider(f_wght); +		for (U32 i = 0; i < vf.mNumVertices; ++i) +		{ +			(*f_wght++).set(vf.mWeights[i].getF32ptr()); +		} +	} + +	buff->flush(); +} + +//helper function for pushing primitives for transform shaders and cleaning up +//uninitialized data on the tail, plus tracking number of expected primitives +void push_for_transform(LLVertexBuffer* buff, U32 source_count, U32 dest_count) +{ +	if (source_count > 0 && dest_count >= source_count) //protect against possible U32 wrapping +	{ +		//push source primitives +		buff->drawArrays(LLRender::POINTS, 0, source_count); +		U32 tail = dest_count-source_count; +		for (U32 i = 0; i < tail; ++i) +		{ //copy last source primitive into each element in tail +			buff->drawArrays(LLRender::POINTS, source_count-1, 1); +		} +		gPipeline.mTransformFeedbackPrimitives += dest_count; +	} +} +  static LLFastTimer::DeclareTimer FTM_FACE_GET_GEOM("Face Geom");  static LLFastTimer::DeclareTimer FTM_FACE_GEOM_POSITION("Position");  static LLFastTimer::DeclareTimer FTM_FACE_GEOM_NORMAL("Normal"); @@ -1111,7 +1167,6 @@ static LLFastTimer::DeclareTimer FTM_FACE_TEX_DEFAULT("Default");  static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK("Quick");  static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_NO_XFORM("No Xform");  static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_XFORM("Xform"); -  static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_PLANAR("Quick Planar");  BOOL LLFace::getGeometryVolume(const LLVolume& volume, @@ -1144,9 +1199,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  					<< " VF Num Indices: " << num_indices  					<< " Indices Index: " << mIndicesIndex  					<< " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl; -			llwarns	<< "Last Indices Count: " << mLastIndicesCount -					<< " Last Indices Index: " << mLastIndicesIndex -					<< " Face Index: " << f +			llwarns	<< " Face Index: " << f  					<< " Pool Type: " << mPoolType << llendl;  			return FALSE;  		} @@ -1284,17 +1337,10 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  	LLMatrix4a mat_normal;  	mat_normal.loadu(mat_norm_in); -	//if it's not fullbright and has no normals, bake sunlight based on face normal -	//bool bake_sunlight = !getTextureEntry()->getFullbright() && -	//  !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); -  	F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0; - +	bool do_xform = false;  	if (rebuild_tcoord)  	{ -		LLFastTimer t(FTM_FACE_GEOM_TEXTURE); -		bool do_xform; -			  		if (tep)  		{  			r  = tep->getRotation(); @@ -1323,599 +1369,759 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		{  			do_xform = false;  		} +	} +	 +	static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback"); + +#ifdef GL_TRANSFORM_FEEDBACK_BUFFER +	if (use_transform_feedback && +		gTransformPositionProgram.mProgramObject && //transform shaders are loaded +		mVertexBuffer->useVBOs() && //target buffer is in VRAM +		!rebuild_weights && //TODO: add support for weights +		!volume.isUnique()) //source volume is NOT flexi +	{ //use transform feedback to pack vertex buffer + +		LLVertexBuffer* buff = (LLVertexBuffer*) vf.mVertexBuffer.get(); + +		if (vf.mVertexBuffer.isNull() || buff->getNumVerts() != vf.mNumVertices) +		{ +			mVObjp->getVolume()->genBinormals(f); +			LLFace::cacheFaceInVRAM(vf); +			buff = (LLVertexBuffer*) vf.mVertexBuffer.get(); +		}		 + +		LLGLSLShader* cur_shader = LLGLSLShader::sCurBoundShaderPtr; +		 +		gGL.pushMatrix(); +		gGL.loadMatrix((GLfloat*) mat_vert_in.mMatrix); + +		if (rebuild_pos) +		{ +			LLFastTimer t(FTM_FACE_GEOM_POSITION); +			gTransformPositionProgram.bind(); + +			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_VERTEX, mGeomIndex, mGeomCount); + +			U8 index = mTextureIndex < 255 ? mTextureIndex : 0; + +			S32 val = 0; +			U8* vp = (U8*) &val; +			vp[0] = index; +			vp[1] = 0; +			vp[2] = 0; +			vp[3] = 0; +			 +			gTransformPositionProgram.uniform1i("texture_index_in", val); +			glBeginTransformFeedback(GL_POINTS); +			buff->setBuffer(LLVertexBuffer::MAP_VERTEX); + +			push_for_transform(buff, vf.mNumVertices, mGeomCount); + +			glEndTransformFeedback(); +		} + +		if (rebuild_color) +		{ +			LLFastTimer t(FTM_FACE_GEOM_COLOR); +			gTransformColorProgram.bind(); +			 +			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_COLOR, mGeomIndex, mGeomCount); + +			S32 val = *((S32*) color.mV); + +			gTransformColorProgram.uniform1i("color_in", val); +			glBeginTransformFeedback(GL_POINTS); +			buff->setBuffer(LLVertexBuffer::MAP_VERTEX); +			push_for_transform(buff, vf.mNumVertices, mGeomCount); +			glEndTransformFeedback(); +		} + +		if (rebuild_emissive) +		{ +			LLFastTimer t(FTM_FACE_GEOM_EMISSIVE); +			gTransformColorProgram.bind(); +			 +			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_EMISSIVE, mGeomIndex, mGeomCount); + +			U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255); + +			S32 glow32 = glow | +						 (glow << 8) | +						 (glow << 16) | +						 (glow << 24); + +			gTransformColorProgram.uniform1i("color_in", glow32); +			glBeginTransformFeedback(GL_POINTS); +			buff->setBuffer(LLVertexBuffer::MAP_VERTEX); +			push_for_transform(buff, vf.mNumVertices, mGeomCount); +			glEndTransformFeedback(); +		} + +		if (rebuild_normal) +		{ +			LLFastTimer t(FTM_FACE_GEOM_NORMAL); +			gTransformNormalProgram.bind(); +			 +			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_NORMAL, mGeomIndex, mGeomCount); -		//bump setup -		LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f ); -		LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f); -		LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f); +			glBeginTransformFeedback(GL_POINTS); +			buff->setBuffer(LLVertexBuffer::MAP_NORMAL); +			push_for_transform(buff, vf.mNumVertices, mGeomCount); +			glEndTransformFeedback(); +		} -		LLQuaternion bump_quat; -		if (mDrawablep->isActive()) +		if (rebuild_binormal)  		{ -			bump_quat = LLQuaternion(mDrawablep->getRenderMatrix()); +			LLFastTimer t(FTM_FACE_GEOM_BINORMAL); +			gTransformBinormalProgram.bind(); +			 +			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_BINORMAL, mGeomIndex, mGeomCount); +						 +			glBeginTransformFeedback(GL_POINTS); +			buff->setBuffer(LLVertexBuffer::MAP_BINORMAL); +			push_for_transform(buff, vf.mNumVertices, mGeomCount); +			glEndTransformFeedback();  		} -		 -		if (bump_code) + +		if (rebuild_tcoord)  		{ -			mVObjp->getVolume()->genBinormals(f); -			F32 offset_multiple;  -			switch( bump_code ) -			{ -				case BE_NO_BUMP: -				offset_multiple = 0.f; -				break; -				case BE_BRIGHTNESS: -				case BE_DARKNESS: -				if( mTexture.notNull() && mTexture->hasGLTexture()) -				{ -					// Offset by approximately one texel -					S32 cur_discard = mTexture->getDiscardLevel(); -					S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() ); -					max_size <<= cur_discard; -					const F32 ARTIFICIAL_OFFSET = 2.f; -					offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; -				} -				else -				{ -					offset_multiple = 1.f/256; -				} -				break; +			LLFastTimer t(FTM_FACE_GEOM_TEXTURE); +			gTransformTexCoordProgram.bind(); +			 +			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD0, mGeomIndex, mGeomCount); +						 +			glBeginTransformFeedback(GL_POINTS); +			buff->setBuffer(LLVertexBuffer::MAP_TEXCOORD0); +			push_for_transform(buff, vf.mNumVertices, mGeomCount); +			glEndTransformFeedback(); -				default:  // Standard bumpmap textures.  Assumed to be 256x256 -				offset_multiple = 1.f / 256; -				break; -			} +			bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); -			F32 s_scale = 1.f; -			F32 t_scale = 1.f; -			if( tep ) +			if (do_bump)  			{ -				tep->getScale( &s_scale, &t_scale ); -			} -			// Use the nudged south when coming from above sun angle, such -			// that emboss mapping always shows up on the upward faces of cubes when  -			// it's noon (since a lot of builders build with the sun forced to noon). -			LLVector3   sun_ray  = gSky.mVOSkyp->mBumpSunDir; -			LLVector3   moon_ray = gSky.getMoonDirection(); -			LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; - -			bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV); -			bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV); +				mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD1, mGeomIndex, mGeomCount); +				glBeginTransformFeedback(GL_POINTS); +				buff->setBuffer(LLVertexBuffer::MAP_TEXCOORD0); +				push_for_transform(buff, vf.mNumVertices, mGeomCount); +				glEndTransformFeedback(); +			}				  		} -		U8 texgen = getTextureEntry()->getTexGen(); -		if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT) -		{ //planar texgen needs binormals -			mVObjp->getVolume()->genBinormals(f); +		glBindBufferARB(GL_TRANSFORM_FEEDBACK_BUFFER, 0); + +		gGL.popMatrix(); + +		if (cur_shader) +		{ +			cur_shader->bind();  		} +	} +	else +#endif +	{ +		//if it's not fullbright and has no normals, bake sunlight based on face normal +		//bool bake_sunlight = !getTextureEntry()->getFullbright() && +		//  !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); -		U8 tex_mode = 0; -	 -		if (isState(TEXTURE_ANIM)) +		if (rebuild_tcoord)  		{ -			LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp;	 -			tex_mode = vobj->mTexAnimMode; +			LLFastTimer t(FTM_FACE_GEOM_TEXTURE); +									 +			//bump setup +			LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f ); +			LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f); +			LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f); -			if (!tex_mode) +			LLQuaternion bump_quat; +			if (mDrawablep->isActive())  			{ -				clearState(TEXTURE_ANIM); +				bump_quat = LLQuaternion(mDrawablep->getRenderMatrix());  			} -			else +		 +			if (bump_code)  			{ -				os = ot = 0.f; -				r = 0.f; -				cos_ang = 1.f; -				sin_ang = 0.f; -				ms = mt = 1.f; +				mVObjp->getVolume()->genBinormals(f); +				F32 offset_multiple;  +				switch( bump_code ) +				{ +					case BE_NO_BUMP: +					offset_multiple = 0.f; +					break; +					case BE_BRIGHTNESS: +					case BE_DARKNESS: +					if( mTexture.notNull() && mTexture->hasGLTexture()) +					{ +						// Offset by approximately one texel +						S32 cur_discard = mTexture->getDiscardLevel(); +						S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() ); +						max_size <<= cur_discard; +						const F32 ARTIFICIAL_OFFSET = 2.f; +						offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; +					} +					else +					{ +						offset_multiple = 1.f/256; +					} +					break; -				do_xform = false; +					default:  // Standard bumpmap textures.  Assumed to be 256x256 +					offset_multiple = 1.f / 256; +					break; +				} + +				F32 s_scale = 1.f; +				F32 t_scale = 1.f; +				if( tep ) +				{ +					tep->getScale( &s_scale, &t_scale ); +				} +				// Use the nudged south when coming from above sun angle, such +				// that emboss mapping always shows up on the upward faces of cubes when  +				// it's noon (since a lot of builders build with the sun forced to noon). +				LLVector3   sun_ray  = gSky.mVOSkyp->mBumpSunDir; +				LLVector3   moon_ray = gSky.getMoonDirection(); +				LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; + +				bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV); +				bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV);  			} -			if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) -			{ //don't override texture transform during tc bake -				tex_mode = 0; +			U8 texgen = getTextureEntry()->getTexGen(); +			if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT) +			{ //planar texgen needs binormals +				mVObjp->getVolume()->genBinormals(f);  			} -		} -		LLVector4a scalea; -		scalea.load3(scale.mV); +			U8 tex_mode = 0; +	 +			if (isState(TEXTURE_ANIM)) +			{ +				LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp;	 +				tex_mode = vobj->mTexAnimMode; + +				if (!tex_mode) +				{ +					clearState(TEXTURE_ANIM); +				} +				else +				{ +					os = ot = 0.f; +					r = 0.f; +					cos_ang = 1.f; +					sin_ang = 0.f; +					ms = mt = 1.f; + +					do_xform = false; +				} + +				if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) +				{ //don't override texture transform during tc bake +					tex_mode = 0; +				} +			} -		bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); -		bool do_tex_mat = tex_mode && mTextureMatrix; +			LLVector4a scalea; +			scalea.load3(scale.mV); -		if (!in_atlas && !do_bump) -		{ //not in atlas or not bump mapped, might be able to do a cheap update -			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount); +			bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); +			bool do_tex_mat = tex_mode && mTextureMatrix; -			if (texgen != LLTextureEntry::TEX_GEN_PLANAR) -			{ -				LLFastTimer t(FTM_FACE_TEX_QUICK); -				if (!do_tex_mat) +			if (!in_atlas && !do_bump) +			{ //not in atlas or not bump mapped, might be able to do a cheap update +				mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount); + +				if (texgen != LLTextureEntry::TEX_GEN_PLANAR)  				{ -					if (!do_xform) -					{ -						LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM); -						LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); -					} -					else +					LLFastTimer t(FTM_FACE_TEX_QUICK); +					if (!do_tex_mat)  					{ -						LLFastTimer t(FTM_FACE_TEX_QUICK_XFORM); -						F32* dst = (F32*) tex_coords.get(); -						LLVector4a* src = (LLVector4a*) vf.mTexCoords; +						if (!do_xform) +						{ +							LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM); +							LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); +						} +						else +						{ +							LLFastTimer t(FTM_FACE_TEX_QUICK_XFORM); +							F32* dst = (F32*) tex_coords.get(); +							LLVector4a* src = (LLVector4a*) vf.mTexCoords; -						LLVector4a trans; -						trans.splat(-0.5f); +							LLVector4a trans; +							trans.splat(-0.5f); -						LLVector4a rot0; -						rot0.set(cos_ang, -sin_ang, cos_ang, -sin_ang); +							LLVector4a rot0; +							rot0.set(cos_ang, -sin_ang, cos_ang, -sin_ang); -						LLVector4a rot1; -						rot1.set(sin_ang, cos_ang, sin_ang, cos_ang); +							LLVector4a rot1; +							rot1.set(sin_ang, cos_ang, sin_ang, cos_ang); -						LLVector4a scale; -						scale.set(ms, mt, ms, mt); +							LLVector4a scale; +							scale.set(ms, mt, ms, mt); -						LLVector4a offset; -						offset.set(os+0.5f, ot+0.5f, os+0.5f, ot+0.5f); +							LLVector4a offset; +							offset.set(os+0.5f, ot+0.5f, os+0.5f, ot+0.5f); -						LLVector4Logical mask; -						mask.clear(); -						mask.setElement<2>(); -						mask.setElement<3>(); +							LLVector4Logical mask; +							mask.clear(); +							mask.setElement<2>(); +							mask.setElement<3>(); -						U32 count = num_vertices/2 + num_vertices%2; +							U32 count = num_vertices/2 + num_vertices%2; -						for (S32 i = 0; i < count; i++) +							for (S32 i = 0; i < count; i++) +							{	 +								LLVector4a res = *src++; +								xform4a(res, trans, mask, rot0, rot1, offset, scale); +								res.store4a(dst); +								dst += 4; +							} +						} +					} +					else +					{ //do tex mat, no texgen, no atlas, no bump +						for (S32 i = 0; i < num_vertices; i++)  						{	 -							LLVector4a res = *src++; -							xform4a(res, trans, mask, rot0, rot1, offset, scale); -							res.store4a(dst); -							dst += 4; +							LLVector2 tc(vf.mTexCoords[i]); +							//LLVector4a& norm = vf.mNormals[i]; +							//LLVector4a& center = *(vf.mCenter); + +							LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); +							tmp = tmp * *mTextureMatrix; +							tc.mV[0] = tmp.mV[0]; +							tc.mV[1] = tmp.mV[1]; +							*tex_coords++ = tc;	  						}  					}  				}  				else -				{ //do tex mat, no texgen, no atlas, no bump -					for (S32 i = 0; i < num_vertices; i++) -					{	 -						LLVector2 tc(vf.mTexCoords[i]); -						//LLVector4a& norm = vf.mNormals[i]; -						//LLVector4a& center = *(vf.mCenter); - -						LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); -						tmp = tmp * *mTextureMatrix; -						tc.mV[0] = tmp.mV[0]; -						tc.mV[1] = tmp.mV[1]; -						*tex_coords++ = tc;	 -					} -				} -			} -			else -			{ //no bump, no atlas, tex gen planar -				LLFastTimer t(FTM_FACE_TEX_QUICK_PLANAR); -				if (do_tex_mat) -				{ -					for (S32 i = 0; i < num_vertices; i++) -					{	 -						LLVector2 tc(vf.mTexCoords[i]); -						LLVector4a& norm = vf.mNormals[i]; -						LLVector4a& center = *(vf.mCenter); -						LLVector4a vec = vf.mPositions[i];	 -						vec.mul(scalea); -						planarProjection(tc, norm, center, vec); +				{ //no bump, no atlas, tex gen planar +					LLFastTimer t(FTM_FACE_TEX_QUICK_PLANAR); +					if (do_tex_mat) +					{ +						for (S32 i = 0; i < num_vertices; i++) +						{	 +							LLVector2 tc(vf.mTexCoords[i]); +							LLVector4a& norm = vf.mNormals[i]; +							LLVector4a& center = *(vf.mCenter); +							LLVector4a vec = vf.mPositions[i];	 +							vec.mul(scalea); +							planarProjection(tc, norm, center, vec); -						LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); -						tmp = tmp * *mTextureMatrix; -						tc.mV[0] = tmp.mV[0]; -						tc.mV[1] = tmp.mV[1]; +							LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); +							tmp = tmp * *mTextureMatrix; +							tc.mV[0] = tmp.mV[0]; +							tc.mV[1] = tmp.mV[1]; -						*tex_coords++ = tc;	 +							*tex_coords++ = tc;	 +						}  					} -				} -				else -				{ -					for (S32 i = 0; i < num_vertices; i++) -					{	 -						LLVector2 tc(vf.mTexCoords[i]); -						LLVector4a& norm = vf.mNormals[i]; -						LLVector4a& center = *(vf.mCenter); -						LLVector4a vec = vf.mPositions[i];	 -						vec.mul(scalea); -						planarProjection(tc, norm, center, vec); +					else +					{ +						for (S32 i = 0; i < num_vertices; i++) +						{	 +							LLVector2 tc(vf.mTexCoords[i]); +							LLVector4a& norm = vf.mNormals[i]; +							LLVector4a& center = *(vf.mCenter); +							LLVector4a vec = vf.mPositions[i];	 +							vec.mul(scalea); +							planarProjection(tc, norm, center, vec); -						xform(tc, cos_ang, sin_ang, os, ot, ms, mt); +							xform(tc, cos_ang, sin_ang, os, ot, ms, mt); -						*tex_coords++ = tc;	 +							*tex_coords++ = tc;	 +						}  					}  				} -			} -			if (map_range) -			{ -				mVertexBuffer->flush(); +				if (map_range) +				{ +					mVertexBuffer->flush(); +				}  			} -		} -		else -		{ //either bump mapped or in atlas, just do the whole expensive loop -			LLFastTimer t(FTM_FACE_TEX_DEFAULT); -			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, map_range); +			else +			{ //either bump mapped or in atlas, just do the whole expensive loop +				LLFastTimer t(FTM_FACE_TEX_DEFAULT); +				mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, map_range); -			std::vector<LLVector2> bump_tc; +				std::vector<LLVector2> bump_tc; -			for (S32 i = 0; i < num_vertices; i++) -			{	 -				LLVector2 tc(vf.mTexCoords[i]); +				for (S32 i = 0; i < num_vertices; i++) +				{	 +					LLVector2 tc(vf.mTexCoords[i]); -				LLVector4a& norm = vf.mNormals[i]; +					LLVector4a& norm = vf.mNormals[i]; -				LLVector4a& center = *(vf.mCenter); +					LLVector4a& center = *(vf.mCenter); -				if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) -				{ -					LLVector4a vec = vf.mPositions[i]; +					if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) +					{ +						LLVector4a vec = vf.mPositions[i]; -					vec.mul(scalea); +						vec.mul(scalea); -					switch (texgen) +						switch (texgen) +						{ +							case LLTextureEntry::TEX_GEN_PLANAR: +								planarProjection(tc, norm, center, vec); +								break; +							case LLTextureEntry::TEX_GEN_SPHERICAL: +								sphericalProjection(tc, norm, center, vec); +								break; +							case LLTextureEntry::TEX_GEN_CYLINDRICAL: +								cylindricalProjection(tc, norm, center, vec); +								break; +							default: +								break; +						}		 +					} + +					if (tex_mode && mTextureMatrix)  					{ -						case LLTextureEntry::TEX_GEN_PLANAR: -							planarProjection(tc, norm, center, vec); +						LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); +						tmp = tmp * *mTextureMatrix; +						tc.mV[0] = tmp.mV[0]; +						tc.mV[1] = tmp.mV[1]; +					} +					else +					{ +						xform(tc, cos_ang, sin_ang, os, ot, ms, mt); +					} + +					if(in_atlas) +					{ +						// +						//manually calculate tex-coord per vertex for varying address modes. +						//should be removed if shader can handle this. +						// + +						S32 int_part = 0 ; +						switch(mTexture->getAddressMode()) +						{ +						case LLTexUnit::TAM_CLAMP: +							if(tc.mV[0] < 0.f) +							{ +								tc.mV[0] = 0.f ; +							} +							else if(tc.mV[0] > 1.f) +							{ +								tc.mV[0] = 1.f; +							} + +							if(tc.mV[1] < 0.f) +							{ +								tc.mV[1] = 0.f ; +							} +							else if(tc.mV[1] > 1.f) +							{ +								tc.mV[1] = 1.f; +							}  							break; -						case LLTextureEntry::TEX_GEN_SPHERICAL: -							sphericalProjection(tc, norm, center, vec); +						case LLTexUnit::TAM_MIRROR: +							if(tc.mV[0] < 0.f) +							{ +								tc.mV[0] = -tc.mV[0] ; +							} +							int_part = (S32)tc.mV[0] ; +							if(int_part & 1) //odd number +							{ +								tc.mV[0] = int_part + 1 - tc.mV[0] ; +							} +							else //even number +							{ +								tc.mV[0] -= int_part ; +							} + +							if(tc.mV[1] < 0.f) +							{ +								tc.mV[1] = -tc.mV[1] ; +							} +							int_part = (S32)tc.mV[1] ; +							if(int_part & 1) //odd number +							{ +								tc.mV[1] = int_part + 1 - tc.mV[1] ; +							} +							else //even number +							{ +								tc.mV[1] -= int_part ; +							}  							break; -						case LLTextureEntry::TEX_GEN_CYLINDRICAL: -							cylindricalProjection(tc, norm, center, vec); +						case LLTexUnit::TAM_WRAP: +							if(tc.mV[0] > 1.f) +								tc.mV[0] -= (S32)(tc.mV[0] - 0.00001f) ; +							else if(tc.mV[0] < -1.f) +								tc.mV[0] -= (S32)(tc.mV[0] + 0.00001f) ; + +							if(tc.mV[1] > 1.f) +								tc.mV[1] -= (S32)(tc.mV[1] - 0.00001f) ; +							else if(tc.mV[1] < -1.f) +								tc.mV[1] -= (S32)(tc.mV[1] + 0.00001f) ; + +							if(tc.mV[0] < 0.f) +							{ +								tc.mV[0] = 1.0f + tc.mV[0] ; +							} +							if(tc.mV[1] < 0.f) +							{ +								tc.mV[1] = 1.0f + tc.mV[1] ; +							}  							break;  						default:  							break; -					}		 -				} +						} +				 +						tc.mV[0] = tcoord_xoffset + tcoord_xscale * tc.mV[0] ; +						tc.mV[1] = tcoord_yoffset + tcoord_yscale * tc.mV[1] ; +					} +				 -				if (tex_mode && mTextureMatrix) -				{ -					LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); -					tmp = tmp * *mTextureMatrix; -					tc.mV[0] = tmp.mV[0]; -					tc.mV[1] = tmp.mV[1]; +					*tex_coords++ = tc; +					if (do_bump) +					{ +						bump_tc.push_back(tc); +					}  				} -				else + +				if (map_range)  				{ -					xform(tc, cos_ang, sin_ang, os, ot, ms, mt); +					mVertexBuffer->flush();  				} -				if(in_atlas) +				if (do_bump)  				{ -					// -					//manually calculate tex-coord per vertex for varying address modes. -					//should be removed if shader can handle this. -					// - -					S32 int_part = 0 ; -					switch(mTexture->getAddressMode()) +					mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex, mGeomCount, map_range); +		 +					for (S32 i = 0; i < num_vertices; i++)  					{ -					case LLTexUnit::TAM_CLAMP: -						if(tc.mV[0] < 0.f) -						{ -							tc.mV[0] = 0.f ; -						} -						else if(tc.mV[0] > 1.f) -						{ -							tc.mV[0] = 1.f; -						} - -						if(tc.mV[1] < 0.f) -						{ -							tc.mV[1] = 0.f ; -						} -						else if(tc.mV[1] > 1.f) -						{ -							tc.mV[1] = 1.f; -						} -						break; -					case LLTexUnit::TAM_MIRROR: -						if(tc.mV[0] < 0.f) -						{ -							tc.mV[0] = -tc.mV[0] ; -						} -						int_part = (S32)tc.mV[0] ; -						if(int_part & 1) //odd number -						{ -							tc.mV[0] = int_part + 1 - tc.mV[0] ; -						} -						else //even number +						LLVector4a tangent; +						tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]); + +						LLMatrix4a tangent_to_object; +						tangent_to_object.setRows(tangent, vf.mBinormals[i], vf.mNormals[i]); +						LLVector4a t; +						tangent_to_object.rotate(binormal_dir, t); +						LLVector4a binormal; +						mat_normal.rotate(t, binormal); +						 +						//VECTORIZE THIS +						if (mDrawablep->isActive())  						{ -							tc.mV[0] -= int_part ; +							LLVector3 t; +							t.set(binormal.getF32ptr()); +							t *= bump_quat; +							binormal.load3(t.mV);  						} -						if(tc.mV[1] < 0.f) -						{ -							tc.mV[1] = -tc.mV[1] ; -						} -						int_part = (S32)tc.mV[1] ; -						if(int_part & 1) //odd number -						{ -							tc.mV[1] = int_part + 1 - tc.mV[1] ; -						} -						else //even number -						{ -							tc.mV[1] -= int_part ; -						} -						break; -					case LLTexUnit::TAM_WRAP: -						if(tc.mV[0] > 1.f) -							tc.mV[0] -= (S32)(tc.mV[0] - 0.00001f) ; -						else if(tc.mV[0] < -1.f) -							tc.mV[0] -= (S32)(tc.mV[0] + 0.00001f) ; - -						if(tc.mV[1] > 1.f) -							tc.mV[1] -= (S32)(tc.mV[1] - 0.00001f) ; -						else if(tc.mV[1] < -1.f) -							tc.mV[1] -= (S32)(tc.mV[1] + 0.00001f) ; - -						if(tc.mV[0] < 0.f) -						{ -							tc.mV[0] = 1.0f + tc.mV[0] ; -						} -						if(tc.mV[1] < 0.f) -						{ -							tc.mV[1] = 1.0f + tc.mV[1] ; -						} -						break; -					default: -						break; +						binormal.normalize3fast(); +						LLVector2 tc = bump_tc[i]; +						tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() ); +					 +						*tex_coords2++ = tc;  					} -				 -					tc.mV[0] = tcoord_xoffset + tcoord_xscale * tc.mV[0] ; -					tc.mV[1] = tcoord_yoffset + tcoord_yscale * tc.mV[1] ; -				} -				 - -				*tex_coords++ = tc; -				if (do_bump) -				{ -					bump_tc.push_back(tc); -				} -			} - -			if (map_range) -			{ -				mVertexBuffer->flush(); -			} -			if (do_bump) -			{ -				mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex, mGeomCount, map_range); -		 -				for (S32 i = 0; i < num_vertices; i++) -				{ -					LLVector4a tangent; -					tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]); - -					LLMatrix4a tangent_to_object; -					tangent_to_object.setRows(tangent, vf.mBinormals[i], vf.mNormals[i]); -					LLVector4a t; -					tangent_to_object.rotate(binormal_dir, t); -					LLVector4a binormal; -					mat_normal.rotate(t, binormal); -						 -					//VECTORIZE THIS -					if (mDrawablep->isActive()) +					if (map_range)  					{ -						LLVector3 t; -						t.set(binormal.getF32ptr()); -						t *= bump_quat; -						binormal.load3(t.mV); +						mVertexBuffer->flush();  					} - -					binormal.normalize3fast(); -					LLVector2 tc = bump_tc[i]; -					tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() ); -					 -					*tex_coords2++ = tc; -				} - -				if (map_range) -				{ -					mVertexBuffer->flush();  				}  			}  		} -	} -	if (rebuild_pos) -	{ -		LLFastTimer t(FTM_FACE_GEOM_POSITION); -		llassert(num_vertices > 0); +		if (rebuild_pos) +		{ +			LLFastTimer t(FTM_FACE_GEOM_POSITION); +			llassert(num_vertices > 0); -		mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range); +			mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range); -		LLMatrix4a mat_vert; -		mat_vert.loadu(mat_vert_in); +			LLMatrix4a mat_vert; +			mat_vert.loadu(mat_vert_in); -		LLVector4a* src = vf.mPositions; -		volatile F32* dst = (volatile F32*) vert.get(); +			LLVector4a* src = vf.mPositions; +			volatile F32* dst = (volatile F32*) vert.get(); -		volatile F32* end = dst+num_vertices*4; -		LLVector4a res; +			volatile F32* end = dst+num_vertices*4; +			LLVector4a res; -		LLVector4a texIdx; +			LLVector4a texIdx; -		U8 index = mTextureIndex < 255 ? mTextureIndex : 0; +			U8 index = mTextureIndex < 255 ? mTextureIndex : 0; -		F32 val = 0.f; -		U8* vp = (U8*) &val; -		vp[0] = index; -		vp[1] = 0; -		vp[2] = 0; -		vp[3] = 0; +			F32 val = 0.f; +			U8* vp = (U8*) &val; +			vp[0] = index; +			vp[1] = 0; +			vp[2] = 0; +			vp[3] = 0; -		llassert(index <= LLGLSLShader::sIndexedTextureChannels-1); +			llassert(index <= LLGLSLShader::sIndexedTextureChannels-1); -		LLVector4Logical mask; -		mask.clear(); -		mask.setElement<3>(); +			LLVector4Logical mask; +			mask.clear(); +			mask.setElement<3>(); -		texIdx.set(0,0,0,val); +			texIdx.set(0,0,0,val); -		{ -			LLFastTimer t(FTM_FACE_POSITION_STORE); -			LLVector4a tmp; - -			do -			{	 -				mat_vert.affineTransform(*src++, res); -				tmp.setSelectWithMask(mask, texIdx, res); -				tmp.store4a((F32*) dst); -				dst += 4; +			{ +				LLFastTimer t(FTM_FACE_POSITION_STORE); +				LLVector4a tmp; + +				do +				{	 +					mat_vert.affineTransform(*src++, res); +					tmp.setSelectWithMask(mask, texIdx, res); +					tmp.store4a((F32*) dst); +					dst += 4; +				} +				while(dst < end);  			} -			while(dst < end); -		} -		{ -			LLFastTimer t(FTM_FACE_POSITION_PAD); -			S32 aligned_pad_vertices = mGeomCount - num_vertices; -			res.set(res[0], res[1], res[2], 0.f); +			{ +				LLFastTimer t(FTM_FACE_POSITION_PAD); +				S32 aligned_pad_vertices = mGeomCount - num_vertices; +				res.set(res[0], res[1], res[2], 0.f); -			while (aligned_pad_vertices > 0) +				while (aligned_pad_vertices > 0) +				{ +					--aligned_pad_vertices; +					res.store4a((F32*) dst); +					dst += 4; +				} +			} + +			if (map_range)  			{ -				--aligned_pad_vertices; -				res.store4a((F32*) dst); -				dst += 4; +				mVertexBuffer->flush();  			}  		} -		if (map_range) -		{ -			mVertexBuffer->flush(); -		} -	} -	if (rebuild_normal) -	{ -		LLFastTimer t(FTM_FACE_GEOM_NORMAL); -		mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range); -		F32* normals = (F32*) norm.get(); +		if (rebuild_normal) +		{ +			LLFastTimer t(FTM_FACE_GEOM_NORMAL); +			mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range); +			F32* normals = (F32*) norm.get(); -		for (S32 i = 0; i < num_vertices; i++) -		{	 -			LLVector4a normal; -			mat_normal.rotate(vf.mNormals[i], normal); -			normal.normalize3fast(); -			normal.store4a(normals); -			normals += 4; -		} +			for (S32 i = 0; i < num_vertices; i++) +			{	 +				LLVector4a normal; +				mat_normal.rotate(vf.mNormals[i], normal); +				normal.normalize3fast(); +				normal.store4a(normals); +				normals += 4; +			} -		if (map_range) -		{ -			mVertexBuffer->flush(); +			if (map_range) +			{ +				mVertexBuffer->flush(); +			}  		} -	} -	if (rebuild_binormal) -	{ -		LLFastTimer t(FTM_FACE_GEOM_BINORMAL); -		mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range); -		F32* binormals = (F32*) binorm.get(); +		if (rebuild_binormal) +		{ +			LLFastTimer t(FTM_FACE_GEOM_BINORMAL); +			mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range); +			F32* binormals = (F32*) binorm.get(); -		for (S32 i = 0; i < num_vertices; i++) -		{	 -			LLVector4a binormal; -			mat_normal.rotate(vf.mBinormals[i], binormal); -			binormal.normalize3fast(); -			binormal.store4a(binormals); -			binormals += 4; -		} +			for (S32 i = 0; i < num_vertices; i++) +			{	 +				LLVector4a binormal; +				mat_normal.rotate(vf.mBinormals[i], binormal); +				binormal.normalize3fast(); +				binormal.store4a(binormals); +				binormals += 4; +			} -		if (map_range) -		{ -			mVertexBuffer->flush(); +			if (map_range) +			{ +				mVertexBuffer->flush(); +			}  		} -	} -	if (rebuild_weights && vf.mWeights) -	{ -		LLFastTimer t(FTM_FACE_GEOM_WEIGHTS); -		mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range); -		F32* weights = (F32*) wght.get(); -		LLVector4a::memcpyNonAliased16(weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); -		if (map_range) +		if (rebuild_weights && vf.mWeights)  		{ -			mVertexBuffer->flush(); +			LLFastTimer t(FTM_FACE_GEOM_WEIGHTS); +			mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range); +			F32* weights = (F32*) wght.get(); +			LLVector4a::memcpyNonAliased16(weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); +			if (map_range) +			{ +				mVertexBuffer->flush(); +			}  		} -	} -	if (rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_COLOR) ) -	{ -		LLFastTimer t(FTM_FACE_GEOM_COLOR); -		mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount, map_range); +		if (rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_COLOR) ) +		{ +			LLFastTimer t(FTM_FACE_GEOM_COLOR); +			mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount, map_range); -		LLVector4a src; +			LLVector4a src; -		U32 vec[4]; -		vec[0] = vec[1] = vec[2] = vec[3] = color.mAll; +			U32 vec[4]; +			vec[0] = vec[1] = vec[2] = vec[3] = color.mAll; -		src.loadua((F32*) vec); +			src.loadua((F32*) vec); -		F32* dst = (F32*) colors.get(); -		S32 num_vecs = num_vertices/4; -		if (num_vertices%4 > 0) -		{ -			++num_vecs; -		} +			F32* dst = (F32*) colors.get(); +			S32 num_vecs = num_vertices/4; +			if (num_vertices%4 > 0) +			{ +				++num_vecs; +			} -		for (S32 i = 0; i < num_vecs; i++) -		{	 -			src.store4a(dst); -			dst += 4; -		} +			for (S32 i = 0; i < num_vecs; i++) +			{	 +				src.store4a(dst); +				dst += 4; +			} -		if (map_range) -		{ -			mVertexBuffer->flush(); +			if (map_range) +			{ +				mVertexBuffer->flush(); +			}  		} -	} -	if (rebuild_emissive) -	{ -		LLFastTimer t(FTM_FACE_GEOM_EMISSIVE); -		LLStrider<LLColor4U> emissive; -		mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount, map_range); +		if (rebuild_emissive) +		{ +			LLFastTimer t(FTM_FACE_GEOM_EMISSIVE); +			LLStrider<LLColor4U> emissive; +			mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount, map_range); -		U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255); +			U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255); -		LLVector4a src; +			LLVector4a src; -		U32 glow32 = glow | -					 (glow << 8) | -					 (glow << 16) | -					 (glow << 24); +			U32 glow32 = glow | +						 (glow << 8) | +						 (glow << 16) | +						 (glow << 24); -		U32 vec[4]; -		vec[0] = vec[1] = vec[2] = vec[3] = glow32; +			U32 vec[4]; +			vec[0] = vec[1] = vec[2] = vec[3] = glow32; -		src.loadua((F32*) vec); +			src.loadua((F32*) vec); -		F32* dst = (F32*) emissive.get(); -		S32 num_vecs = num_vertices/4; -		if (num_vertices%4 > 0) -		{ -			++num_vecs; -		} +			F32* dst = (F32*) emissive.get(); +			S32 num_vecs = num_vertices/4; +			if (num_vertices%4 > 0) +			{ +				++num_vecs; +			} -		for (S32 i = 0; i < num_vecs; i++) -		{	 -			src.store4a(dst); -			dst += 4; -		} +			for (S32 i = 0; i < num_vecs; i++) +			{	 +				src.store4a(dst); +				dst += 4; +			} -		if (map_range) -		{ -			mVertexBuffer->flush(); +			if (map_range) +			{ +				mVertexBuffer->flush(); +			}  		}  	} +  	if (rebuild_tcoord)  	{  		mTexExtents[0].setVec(0,0); @@ -1932,12 +2138,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  	} -	mLastVertexBuffer = mVertexBuffer; -	mLastGeomCount = mGeomCount; -	mLastGeomIndex = mGeomIndex; -	mLastIndicesCount = mIndicesCount; -	mLastIndicesIndex = mIndicesIndex; -  	return TRUE;  } @@ -2516,7 +2716,6 @@ void LLFace::setVertexBuffer(LLVertexBuffer* buffer)  void LLFace::clearVertexBuffer()  {  	mVertexBuffer = NULL; -	mLastVertexBuffer = NULL;  }  //static diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 82e4ab61b7..76ea5c853a 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -83,6 +83,8 @@ public:  	static void initClass(); +	static void cacheFaceInVRAM(const LLVolumeFace& vf); +  public:  	LLFace(LLDrawable* drawablep, LLViewerObject* objp)   { init(drawablep, objp); }  	~LLFace()  { destroy(); } @@ -222,7 +224,7 @@ public:  	//vertex buffer tracking  	void setVertexBuffer(LLVertexBuffer* buffer); -	void clearVertexBuffer(); //sets mVertexBuffer and mLastVertexBuffer to NULL +	void clearVertexBuffer(); //sets mVertexBuffer to NULL  	LLVertexBuffer* getVertexBuffer()	const	{ return mVertexBuffer; }  	U32 getRiggedVertexBufferDataMask() const;  	S32 getRiggedIndex(U32 type) const; @@ -255,8 +257,7 @@ public:  private:  	LLPointer<LLVertexBuffer> mVertexBuffer; -	LLPointer<LLVertexBuffer> mLastVertexBuffer; -	 +		  	U32			mState;  	LLFacePool*	mDrawPoolp;  	U32			mPoolType; @@ -269,12 +270,6 @@ private:  	U32			mIndicesIndex;		// index into draw pool for indices (yeah, I know!)  	S32         mIndexInTex ; -	//previous rebuild's geometry info -	U16			mLastGeomCount; -	U16			mLastGeomIndex; -	U32			mLastIndicesCount; -	U32			mLastIndicesIndex; -  	LLXformMatrix* mXform;  	LLPointer<LLViewerTexture> mTexture;  	LLPointer<LLDrawable> mDrawablep; diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 575b613ccf..4cbc9cab4a 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -1191,7 +1191,7 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata)  	}  	else if (action == "paste")  	{ -		pastFromClipboard(); +		pasteFromClipboard();  	}  	else if (action == "delete")  	{ @@ -1239,7 +1239,7 @@ BOOL LLFavoritesBarCtrl::isClipboardPasteable() const  	return TRUE;  } -void LLFavoritesBarCtrl::pastFromClipboard() const +void LLFavoritesBarCtrl::pasteFromClipboard() const  {  	LLInventoryModel* model = &gInventory;  	if(model && isClipboardPasteable()) diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 2f75b3bb0e..447d30f1f4 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -90,7 +90,7 @@ protected:  	bool enableSelected(const LLSD& userdata);  	void doToSelected(const LLSD& userdata);  	BOOL isClipboardPasteable() const; -	void pastFromClipboard() const; +	void pasteFromClipboard() const;  	void showDropDownMenu(); diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index 32a533570a..11edb60712 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -368,7 +368,7 @@ void LLVolumeImplFlexible::doFlexibleUpdate()  	LLPath *path = &volume->getPath();  	if ((mSimulateRes == 0 || !mInitialized) && mVO->mDrawable->isVisible())   	{ -		mVO->markForUpdate(TRUE); +		//mVO->markForUpdate(TRUE);  		if (!doIdleUpdate(gAgent, *LLWorld::getInstance(), 0.0))  		{  			return;	// we did not get updated or initialized, proceeding without can be dangerous @@ -729,7 +729,11 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable)  	else if (!mUpdated || rotated)  	{  		volume->mDrawable->setState(LLDrawable::REBUILD_POSITION); -		volume->dirtyMesh(); +		LLSpatialGroup* group = volume->mDrawable->getSpatialGroup(); +		if (group) +		{ +			group->dirtyMesh(); +		}  		volume->genBBoxes(isVolumeGlobal());  	} @@ -814,15 +818,17 @@ LLQuaternion LLVolumeImplFlexible::getEndRotation()  }//------------------------------------------------------------------ -void LLVolumeImplFlexible::updateRelativeXform() +void LLVolumeImplFlexible::updateRelativeXform(bool force_identity)  {  	LLQuaternion delta_rot;  	LLVector3 delta_pos, delta_scale;  	LLVOVolume* vo = (LLVOVolume*) mVO; +	bool use_identity = vo->mDrawable->isSpatialRoot() || force_identity; +  	//matrix from local space to parent relative/global space -	delta_rot = vo->mDrawable->isSpatialRoot() ? LLQuaternion() : vo->mDrawable->getRotation(); -	delta_pos = vo->mDrawable->isSpatialRoot() ? LLVector3(0,0,0) : vo->mDrawable->getPosition(); +	delta_rot = use_identity ? LLQuaternion() : vo->mDrawable->getRotation(); +	delta_pos = use_identity ? LLVector3(0,0,0) : vo->mDrawable->getPosition();  	delta_scale = LLVector3(1,1,1);  	// Vertex transform (4x4) diff --git a/indra/newview/llflexibleobject.h b/indra/newview/llflexibleobject.h index fef43d464d..371d6a0773 100644 --- a/indra/newview/llflexibleobject.h +++ b/indra/newview/llflexibleobject.h @@ -89,7 +89,7 @@ class LLVolumeImplFlexible : public LLVolumeInterface  		bool isVolumeGlobal() const { return true; }  		bool isActive() const { return true; }  		const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const; -		void updateRelativeXform(); +		void updateRelativeXform(bool force_identity);  		void doFlexibleUpdate(); // Called to update the simulation  		void doFlexibleRebuild(); // Called to rebuild the geometry  		void preRebuild(); diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index ac33a05f42..fa0ad20fdb 100644 --- a/indra/newview/llfloaterbvhpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -1124,9 +1124,13 @@ BOOL	LLPreviewAnimation::render()  		LLVertexBuffer::unbind();  		LLGLDepthTest gls_depth(GL_TRUE); -		LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); -		avatarp->dirtyMesh(); -		avatarPoolp->renderAvatars(avatarp);  // renders only one avatar +		LLFace* face = avatarp->mDrawable->getFace(0); +		if (face) +		{ +			LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)face->getPool(); +			avatarp->dirtyMesh(); +			avatarPoolp->renderAvatars(avatarp);  // renders only one avatar +		}  	}  	gGL.color4f(1,1,1,1); diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 92ee8ddac6..6b2492d927 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -704,9 +704,13 @@ BOOL LLImagePreviewAvatar::render()  		// make sure alpha=0 shows avatar material color  		LLGLDisable no_blend(GL_BLEND); -		LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); -		gPipeline.enableLightsPreview(); -		avatarPoolp->renderAvatars(avatarp);  // renders only one avatar +		LLFace* face = avatarp->mDrawable->getFace(0); +		if (face) +		{ +			LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)face->getPool(); +			gPipeline.enableLightsPreview(); +			avatarPoolp->renderAvatars(avatarp);  // renders only one avatar +		}  	}  	gGL.popUIMatrix(); diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index c503f70789..61da99fe3a 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -1886,6 +1886,7 @@ BOOL LLPanelLandOptions::postBuild()  		mSnapshotCtrl->setCommitCallback( onCommitAny, this );  		mSnapshotCtrl->setAllowNoTexture ( TRUE );  		mSnapshotCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); +		mSnapshotCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);  		mSnapshotCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);  	}  	else diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 4b8beba546..0a5171245a 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -396,7 +396,6 @@ mCalculateBtn(NULL)  	sInstance = this;  	mLastMouseX = 0;  	mLastMouseY = 0; -	mGLName = 0;  	mStatusLock = new LLMutex(NULL);  	mModelPreview = NULL; @@ -538,11 +537,6 @@ LLFloaterModelPreview::~LLFloaterModelPreview()  		delete mModelPreview;  	} -	if (mGLName) -	{ -		LLImageGL::deleteTextures(1, &mGLName ); -	} -  	delete mStatusLock;  	mStatusLock = NULL;  } diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index c522e6f734..ab319c30d5 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -256,7 +256,6 @@ protected:  	S32				mLastMouseX;  	S32				mLastMouseY;  	LLRect			mPreviewRect; -	U32				mGLName;  	static S32		sUploadAmount;  	std::set<LLPointer<DecompRequest> > mCurRequest; diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 1fa194ab19..9ce64a630f 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -562,7 +562,6 @@ void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent)  	{  		width = scroll_rect.getWidth();  	} -  	LLView::reshape(width, height, called_from_parent);  	mReshapeSignal(mSelectedItems, FALSE);  } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index b86c453d61..fd0c6f8c3c 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3008,8 +3008,6 @@ void LLFolderBridge::pasteFromClipboard()  			}  		} -		const LLUUID parent_id(mUUID); -  		for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin();  			 iter != objects.end();  			 ++iter) diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 8092f3bf36..6e23d7c701 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -822,6 +822,11 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)  			{  				parent_id = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);  				new_item->setParent(parent_id); +				LLInventoryModel::update_list_t update; +				LLInventoryModel::LLCategoryUpdate new_folder(parent_id, 1); +				update.push_back(new_folder); +				accountForUpdate(update); +  			}  			item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, parent_id);  			if(item_array) diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 3a88fbd96d..f8088d04b4 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -60,6 +60,7 @@  #include "llworld.h"  #include "llui.h"  #include "pipeline.h" +#include "llviewershadermgr.h"  const S32 NUM_AXES = 3;  const S32 MOUSE_DRAG_SLOP = 2;       // pixels @@ -1580,7 +1581,11 @@ void LLManipTranslate::renderSnapGuides()  					LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER);  					LLGLEnable stipple(GL_LINE_STIPPLE);  					gGL.flush(); -					glLineStipple(1, 0x3333); + +					if (!LLGLSLShader::sNoFixedFunction) +					{ +						glLineStipple(1, 0x3333); +					}  					switch (mManipPart)  					{ @@ -1645,17 +1650,28 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal,  											 LLQuaternion grid_rotation,   											 LLColor4 inner_color)  { -	if (!gSavedSettings.getBOOL("GridCrossSections")) +	if (!gSavedSettings.getBOOL("GridCrossSections") || !LLGLSLShader::sNoFixedFunction)  	{  		return;  	} +	 +	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + +	  	U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_ALPHA, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY };  	U32 num_types = LL_ARRAY_SIZE(types);  	GLuint stencil_mask = 0xFFFFFFFF;  	//stencil in volumes +  	gGL.flush(); + +	if (shader) +	{ +		gClipProgram.bind(); +	} +		  	{  		glStencilMask(stencil_mask);  		glClearStencil(1); @@ -1666,6 +1682,7 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal,  		glStencilFunc(GL_ALWAYS, 0, stencil_mask);  		gGL.setColorMask(false, false);  		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +  		gGL.diffuseColor4f(1,1,1,1);  		//setup clip plane @@ -1675,10 +1692,12 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal,  			normal = -normal;  		}  		F32 d = -(selection_center * normal); -		F64 plane[] = { normal.mV[0], normal.mV[1], normal.mV[2], d }; -		LLGLEnable clip(GL_CLIP_PLANE0); -		glClipPlane(GL_CLIP_PLANE0, plane); +		glh::vec4f plane(normal.mV[0], normal.mV[1], normal.mV[2], d ); + +		gGL.getModelviewMatrix().inverse().mult_vec_matrix(plane); +		gClipProgram.uniform4fv("clip_plane", 1, plane.v); +		  		BOOL particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES);  		BOOL clouds = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS); @@ -1729,6 +1748,11 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal,  	F32 sz = mGridSizeMeters;  	F32 tiles = sz; +	if (shader) +	{ +		shader->bind(); +	} +  	//draw volume/plane intersections  	{  		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index c899e8991e..bc7f522848 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -1659,7 +1659,7 @@ void LLMeshUploadThread::requestWholeModelFee()  		mCurlRequest->process();  		//sleep for 10ms to prevent eating a whole core  		apr_sleep(10000); -	} while (mCurlRequest->getQueued() > 0); +	} while (!LLApp::isQuitting() && mCurlRequest->getQueued() > 0);  	delete mCurlRequest;  	mCurlRequest = NULL; diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 03404e816b..d58d6d536c 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -574,6 +574,7 @@ static void init_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const L                  texture_ctrl->setAllowNoTexture(entry->mAllowNoTexture);                  // Don't allow (no copy) or (notransfer) textures to be selected.                  texture_ctrl->setImmediateFilterPermMask(PERM_NONE); +                texture_ctrl->setDnDFilterPermMask(PERM_NONE);                  texture_ctrl->setNonImmediateFilterPermMask(PERM_NONE);          }  } diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 7301b305b2..3e29805446 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -38,6 +38,7 @@  #include "llfontgl.h"  // project includes +#include "llagentdata.h"  #include "llbutton.h"  #include "llcheckboxctrl.h"  #include "llcolorswatch.h" @@ -46,6 +47,7 @@  #include "llface.h"  #include "lllineeditor.h"  #include "llmediaentry.h" +#include "llnotificationsutil.h"  #include "llresmgr.h"  #include "llselectmgr.h"  #include "llspinctrl.h" @@ -104,27 +106,11 @@ BOOL	LLPanelFace::postBuild()  		mTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelTexture, this, _2) );  		mTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectTexture, this, _2) );  		mTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2)); +		mTextureCtrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onTextureSelectionChanged, this, _1));  		mTextureCtrl->setFollowsTop();  		mTextureCtrl->setFollowsLeft(); -		// Don't allow (no copy) or (no transfer) textures to be selected during immediate mode -		mTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); -		// Allow any texture to be used during non-immediate mode. -		mTextureCtrl->setNonImmediateFilterPermMask(PERM_NONE); -		LLAggregatePermissions texture_perms; -		if (LLSelectMgr::getInstance()->selectGetAggregateTexturePermissions(texture_perms)) -		{ -			BOOL can_copy =  -				texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_EMPTY ||  -				texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_ALL; -			BOOL can_transfer =  -				texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_EMPTY ||  -				texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_ALL; -			mTextureCtrl->setCanApplyImmediately(can_copy && can_transfer); -		} -		else -		{ -			mTextureCtrl->setCanApplyImmediately(FALSE); -		} +		mTextureCtrl->setImmediateFilterPermMask(PERM_NONE); +		mTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);  	}  	mColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch"); @@ -595,28 +581,6 @@ void LLPanelFace::getState()  		} -		LLAggregatePermissions texture_perms; -		if(texture_ctrl) -		{ -// 			texture_ctrl->setValid( editable ); -		 -			if (LLSelectMgr::getInstance()->selectGetAggregateTexturePermissions(texture_perms)) -			{ -				BOOL can_copy =  -					texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_EMPTY ||  -					texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_ALL; -				BOOL can_transfer =  -					texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_EMPTY ||  -					texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_ALL; -				texture_ctrl->setCanApplyImmediately(can_copy && can_transfer); -			} -			else -			{ -				texture_ctrl->setCanApplyImmediately(FALSE); -			} -		} - -  		// planar align  		bool align_planar = false;  		bool identical_planar_aligned = false; @@ -1190,3 +1154,35 @@ void LLPanelFace::onCommitPlanarAlign(LLUICtrl* ctrl, void* userdata)  	self->sendTextureInfo();  } +void LLPanelFace::onTextureSelectionChanged(LLInventoryItem* itemp) +{ +	LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("texture control"); +	if (texture_ctrl) +	{ +		LLUUID obj_owner_id; +		std::string obj_owner_name; +		LLSelectMgr::instance().selectGetOwner(obj_owner_id, obj_owner_name); + +		LLSaleInfo sale_info; +		LLSelectMgr::instance().selectGetSaleInfo(sale_info); + +		bool can_copy = itemp->getPermissions().allowCopyBy(gAgentID); // do we have perm to copy this texture? +		bool can_transfer = itemp->getPermissions().allowOperationBy(PERM_TRANSFER, gAgentID); // do we have perm to transfer this texture? +		bool is_object_owner = gAgentID == obj_owner_id; // does object for which we are going to apply texture belong to the agent? +		bool not_for_sale = !sale_info.isForSale(); // is object for which we are going to apply texture not for sale? + +		if (can_copy && can_transfer) +		{ +			texture_ctrl->setCanApply(true, true); +			return; +		} + +		// if texture has (no-transfer) attribute it can be applied only for object which we own and is not for sale +		texture_ctrl->setCanApply(false, can_transfer ? true : is_object_owner && not_for_sale); + +		if (gSavedSettings.getBOOL("TextureLivePreview")) +		{ +			LLNotificationsUtil::add("LivePreviewUnavailable"); +		} +	} +} diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 42be9b257f..3b5a9b1398 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -91,6 +91,15 @@ protected:  	static void		onClickAutoFix(void*);  	static F32      valueGlow(LLViewerObject* object, S32 face); +private: + +	/* +	 * Checks whether the selected texture from the LLFloaterTexturePicker can be applied to the currently selected object. +	 * If agent selects texture which is not allowed to be applied for the currently selected object, +	 * all controls of the floater texture picker which allow to apply the texture will be disabled. +	 */ +	void onTextureSelectionChanged(LLInventoryItem* itemp); +  };  #endif diff --git a/indra/newview/llpanellandmedia.cpp b/indra/newview/llpanellandmedia.cpp index b3adfac8a2..26cd3ff1c1 100644 --- a/indra/newview/llpanellandmedia.cpp +++ b/indra/newview/llpanellandmedia.cpp @@ -85,6 +85,7 @@ BOOL LLPanelLandMedia::postBuild()  	mMediaTextureCtrl->setCommitCallback( onCommitAny, this );  	mMediaTextureCtrl->setAllowNoTexture ( TRUE );  	mMediaTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); +	mMediaTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);  	mMediaTextureCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);  	mMediaAutoScaleCheck = getChild<LLCheckBoxCtrl>("media_auto_scale"); diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 1f77e7a602..7dfe529b73 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -245,6 +245,7 @@ BOOL	LLPanelObject::postBuild()  		mCtrlSculptTexture->setDropCallback( boost::bind(&LLPanelObject::onDropSculpt, this, _2 ));  		// Don't allow (no copy) or (no transfer) textures to be selected during immediate mode  		mCtrlSculptTexture->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); +		mCtrlSculptTexture->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);  		// Allow any texture to be used during non-immediate mode.  		mCtrlSculptTexture->setNonImmediateFilterPermMask(PERM_NONE);  		LLAggregatePermissions texture_perms; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index eec2c0a521..a55565909f 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1508,6 +1508,49 @@ struct LLSelectMgrSendFunctor : public LLSelectedObjectFunctor  	}  }; +void LLObjectSelection::applyNoCopyTextureToTEs(LLViewerInventoryItem* item) +{ +	if (!item) +	{ +		return; +	} +	LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(item->getAssetUUID()); + +	for (iterator iter = begin(); iter != end(); ++iter) +	{ +		LLSelectNode* node = *iter; +		LLViewerObject* object = (*iter)->getObject(); +		if (!object) +		{ +			continue; +		} + +		S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces()); +		bool texture_copied = false; +		for (S32 te = 0; te < num_tes; ++te) +		{ +			if (node->isTESelected(te)) +			{ +				//(no-copy) textures must be moved to the object's inventory only once +				// without making any copies +				if (!texture_copied) +				{ +					LLToolDragAndDrop::handleDropTextureProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null); +					texture_copied = true; +				} + +				// apply texture for the selected faces +				LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT ); +				object->setTEImage(te, image); +				dialog_refresh_all(); + +				// send the update to the simulator +				object->sendTEUpdate(); +			} +		} +	} +} +  //-----------------------------------------------------------------------------  // selectionSetImage()  //----------------------------------------------------------------------------- @@ -1559,8 +1602,18 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid)  			}  			return true;  		} -	} setfunc(item, imageid); -	getSelection()->applyToTEs(&setfunc); +	}; + +	if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())) +	{ +		getSelection()->applyNoCopyTextureToTEs(item); +	} +	else +	{ +		f setfunc(item, imageid); +		getSelection()->applyToTEs(&setfunc); +	} +  	struct g : public LLSelectedObjectFunctor  	{ @@ -5583,7 +5636,7 @@ void pushWireframe(LLDrawable* drawable)  			for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)  			{  				const LLVolumeFace& face = volume->getVolumeFace(i); -				LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, face.mTexCoords, face.mNumIndices, face.mIndices); +				LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, NULL, face.mNumIndices, face.mIndices);  			}  		} @@ -5610,7 +5663,7 @@ void LLSelectNode::renderOneWireframe(const LLColor4& color)  	if (shader)  	{ -		gHighlightProgram.bind(); +		gDebugProgram.bind();  	}  	gGL.matrixMode(LLRender::MM_MODELVIEW); diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 87ada5ac6b..94606b9fba 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -307,6 +307,15 @@ public:  	bool applyToRootNodes(LLSelectedNodeFunctor* func, bool firstonly = false);  	bool applyToNodes(LLSelectedNodeFunctor* func, bool firstonly = false); +	/* +	 * Used to apply (no-copy) textures to the selected object or +	 * selected face/faces of the object. +	 * This method moves (no-copy) texture to the object's inventory +	 * and doesn't make copy of the texture for each face. +	 * Then this only texture is used for all selected faces. +	 */ +	void applyNoCopyTextureToTEs(LLViewerInventoryItem* item); +  	ESelectType getSelectType() const { return mSelectType; }  private: diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 8e62b79d7f..325a2d3004 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -85,12 +85,32 @@ static F32 sCurMaxTexPriority = 1.f;  class LLOcclusionQueryPool : public LLGLNamePool  { +public: +	LLOcclusionQueryPool() +	{ +		mCurQuery = 1; +	} +  protected: + +	std::list<GLuint> mAvailableName; +	GLuint mCurQuery; +		  	virtual GLuint allocateName()  	{ -		GLuint name; -		glGenQueriesARB(1, &name); -		return name; +		GLuint ret = 0; + +		if (!mAvailableName.empty()) +		{ +			ret = mAvailableName.front(); +			mAvailableName.pop_front(); +		} +		else +		{ +			ret = mCurQuery++; +		} + +		return ret;  	}  	virtual void releaseName(GLuint name) @@ -98,7 +118,8 @@ protected:  #if LL_TRACK_PENDING_OCCLUSION_QUERIES  		LLSpatialGroup::sPendingQueries.erase(name);  #endif -		glDeleteQueriesARB(1, &name); +		llassert(std::find(mAvailableName.begin(), mAvailableName.end(), name) == mAvailableName.end()); +		mAvailableName.push_back(name);  	}  }; @@ -259,79 +280,39 @@ U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector4a& center)  	return (U8*) (sOcclusionIndices+cypher*8);  } - -static LLFastTimer::DeclareTimer FTM_BUILD_OCCLUSION("Build Occlusion"); - -void LLSpatialGroup::buildOcclusion() +//create a vertex buffer for efficiently rendering cubes +LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage)  { -	//if (mOcclusionVerts.isNull()) -	{ -		mOcclusionVerts = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX,  -			LLVertexBuffer::sUseStreamDraw ? mBufferUsage : 0); //if GL has a hard time with VBOs, don't use them for occlusion culling. -		mOcclusionVerts->allocateBuffer(8, 64, true); -	 -		LLStrider<U16> idx; -		mOcclusionVerts->getIndexStrider(idx); -		for (U32 i = 0; i < 64; i++) -		{ -			*idx++ = sOcclusionIndices[i]; -		} -	} +	LLVertexBuffer* ret = new LLVertexBuffer(type_mask, usage); -	LLVector4a fudge; -	fudge.splat(SG_OCCLUSION_FUDGE); - -	LLVector4a r; -	r.setAdd(mBounds[1], fudge); +	ret->allocateBuffer(8, 64, true);  	LLStrider<LLVector3> pos; -	 -	{ -		LLFastTimer t(FTM_BUILD_OCCLUSION); -		mOcclusionVerts->getVertexStrider(pos); -	} +	LLStrider<U16> idx; -	{ -		LLVector4a* v = (LLVector4a*) pos.get(); +	ret->getVertexStrider(pos); +	ret->getIndexStrider(idx); -		const LLVector4a& c = mBounds[0]; -		const LLVector4a& s = r; -		 -		static const LLVector4a octant[] = -		{ -			LLVector4a(-1.f, -1.f, -1.f), -			LLVector4a(-1.f, -1.f, 1.f), -			LLVector4a(-1.f, 1.f, -1.f), -			LLVector4a(-1.f, 1.f, 1.f), - -			LLVector4a(1.f, -1.f, -1.f), -			LLVector4a(1.f, -1.f, 1.f), -			LLVector4a(1.f, 1.f, -1.f), -			LLVector4a(1.f, 1.f, 1.f), -		}; - -		//vertex positions are encoded so the 3 bits of their vertex index  -		//correspond to their axis facing, with bit position 3,2,1 matching -		//axis facing x,y,z, bit set meaning positive facing, bit clear  -		//meaning negative facing -		 -		for (S32 i = 0; i < 8; ++i) -		{ -			LLVector4a p; -			p.setMul(s, octant[i]); -			p.add(c); -			v[i] = p; -		} -	} -	 +	pos[0] = LLVector3(-1,-1,-1); +	pos[1] = LLVector3(-1,-1, 1); +	pos[2] = LLVector3(-1, 1,-1); +	pos[3] = LLVector3(-1, 1, 1); +	pos[4] = LLVector3( 1,-1,-1); +	pos[5] = LLVector3( 1,-1, 1); +	pos[6] = LLVector3( 1, 1,-1); +	pos[7] = LLVector3( 1, 1, 1); + +	for (U32 i = 0; i < 64; i++)  	{ -		mOcclusionVerts->flush(); -		LLVertexBuffer::unbind(); +		idx[i] = sOcclusionIndices[i];  	} -	clearState(LLSpatialGroup::OCCLUSION_DIRTY); +	ret->flush(); + +	return ret;  } +static LLFastTimer::DeclareTimer FTM_BUILD_OCCLUSION("Build Occlusion");  BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group); @@ -394,8 +375,6 @@ LLSpatialGroup::~LLSpatialGroup()  		}  	} -	mOcclusionVerts = NULL; -  	LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);  	clearDrawMap();  	clearAtlasList() ; @@ -687,6 +666,11 @@ void LLSpatialGroup::rebuildGeom()  	if (!isDead())  	{  		mSpatialPartition->rebuildGeom(this); + +		if (isState(LLSpatialGroup::MESH_DIRTY)) +		{ +			gPipeline.markMeshDirty(this); +		}  	}  } @@ -699,6 +683,9 @@ void LLSpatialGroup::rebuildMesh()  }  static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt"); +static LLFastTimer::DeclareTimer FTM_ADD_GEOMETRY_COUNT("Add Geometry"); +static LLFastTimer::DeclareTimer FTM_CREATE_VB("Create VB"); +static LLFastTimer::DeclareTimer FTM_GET_GEOMETRY("Get Geometry");  void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)  { @@ -720,27 +707,36 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)  	//get geometry count  	U32 index_count = 0;  	U32 vertex_count = 0; -	 -	addGeometryCount(group, vertex_count, index_count); + +	{ +		LLFastTimer t(FTM_ADD_GEOMETRY_COUNT); +		addGeometryCount(group, vertex_count, index_count); +	}  	if (vertex_count > 0 && index_count > 0)  	{ //create vertex buffer containing volume geometry for this node -		group->mBuilt = 1.f; -		if (group->mVertexBuffer.isNull() || -			!group->mVertexBuffer->isWriteable() || -			(group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs))  		{ -			group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage); -			group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true); -			stop_glerror(); +			LLFastTimer t(FTM_CREATE_VB); +			group->mBuilt = 1.f; +			if (group->mVertexBuffer.isNull() || +				!group->mVertexBuffer->isWriteable() || +				(group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs)) +			{ +				group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage); +				group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true); +				stop_glerror(); +			} +			else +			{ +				group->mVertexBuffer->resizeBuffer(vertex_count, index_count); +				stop_glerror(); +			}  		} -		else +  		{ -			group->mVertexBuffer->resizeBuffer(vertex_count, index_count); -			stop_glerror(); +			LLFastTimer t(FTM_GET_GEOMETRY); +			getGeometry(group);  		} -		 -		getGeometry(group);  	}  	else  	{ @@ -932,11 +928,6 @@ void LLSpatialGroup::shift(const LLVector4a &offset)  		setState(GEOM_DIRTY);  		gPipeline.markRebuild(this, TRUE);  	} - -	if (mOcclusionVerts.notNull()) -	{ -		setState(OCCLUSION_DIRTY); -	}  }  class LLSpatialSetState : public LLSpatialGroup::OctreeTraveler @@ -1235,8 +1226,6 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :  		mVisible[i] = 0;  	} -	mOcclusionVerts = NULL; -  	mRadius = 1;  	mPixelArea = 1024.f;  } @@ -1465,10 +1454,14 @@ void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNo  	unbound();  } -void LLSpatialGroup::destroyGL()  +void LLSpatialGroup::destroyGL(bool keep_occlusion)   {  	setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY); -	gPipeline.markRebuild(this, TRUE); + +	if (!keep_occlusion) +	{ //going to need a rebuild +		gPipeline.markRebuild(this, TRUE); +	}  	mLastUpdateTime = gFrameTimeSeconds;  	mVertexBuffer = NULL; @@ -1476,16 +1469,18 @@ void LLSpatialGroup::destroyGL()  	clearDrawMap(); -	for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) +	if (!keep_occlusion)  	{ -		if (mOcclusionQuery[i]) +		for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)  		{ -			sQueryPool.release(mOcclusionQuery[i]); -			mOcclusionQuery[i] = 0; +			if (mOcclusionQuery[i]) +			{ +				sQueryPool.release(mOcclusionQuery[i]); +				mOcclusionQuery[i] = 0; +			}  		}  	} -	mOcclusionVerts = NULL;  	for (LLSpatialGroup::element_iter i = getData().begin(); i != getData().end(); ++i)  	{ @@ -1493,7 +1488,10 @@ void LLSpatialGroup::destroyGL()  		for (S32 j = 0; j < drawable->getNumFaces(); j++)  		{  			LLFace* facep = drawable->getFace(j); -			facep->clearVertexBuffer(); +			if (facep) +			{ +				facep->clearVertexBuffer(); +			}  		}  	}  } @@ -1556,15 +1554,13 @@ BOOL LLSpatialGroup::rebound()  		mBounds[1].mul(0.5f);  	} -	setState(OCCLUSION_DIRTY); -	  	clearState(DIRTY);  	return TRUE;  }  static LLFastTimer::DeclareTimer FTM_OCCLUSION_READBACK("Readback Occlusion"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_WAIT("Wait"); +static LLFastTimer::DeclareTimer FTM_OCCLUSION_WAIT("Occlusion Wait");  void LLSpatialGroup::checkOcclusion()  { @@ -1584,7 +1580,9 @@ void LLSpatialGroup::checkOcclusion()  			{  				glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available); -				if (mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount) +				static LLCachedControl<bool> wait_for_query(gSavedSettings, "RenderSynchronousOcclusion"); + +				if (wait_for_query && mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount)  				{ //query was issued last frame, wait until it's available  					S32 max_loop = 1024;  					LLFastTimer t(FTM_OCCLUSION_WAIT); @@ -1635,7 +1633,9 @@ void LLSpatialGroup::checkOcclusion()  				else  				{  					assert_states_valid(this); +					  					setOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); +					  					assert_states_valid(this);  				} @@ -1690,12 +1690,6 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)  						mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate();  					} -					if (mOcclusionVerts.isNull() || isState(LLSpatialGroup::OCCLUSION_DIRTY)) -					{ -						LLFastTimer t(FTM_OCCLUSION_BUILD); -						buildOcclusion(); -					} -					  					// Depth clamp all water to avoid it being culled as a result of being  					// behind the far clip plane, and in the case of edge water to avoid  					// it being culled while still visible. @@ -1726,10 +1720,13 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)  							glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]);					  						} -						{ -							LLFastTimer t(FTM_OCCLUSION_SET_BUFFER); -							mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX); -						} +						LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; +						llassert(shader); + +						shader->uniform3fv(LLShaderMgr::BOX_CENTER, 1, mBounds[0].getF32ptr()); +						shader->uniform3f(LLShaderMgr::BOX_SIZE, mBounds[1][0]+SG_OCCLUSION_FUDGE,  +																 mBounds[1][1]+SG_OCCLUSION_FUDGE,  +																 mBounds[1][2]+SG_OCCLUSION_FUDGE);  						if (!use_depth_clamp && mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER)  						{ @@ -1738,12 +1735,12 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)  							LLGLSquashToFarClip squash(glh_get_current_projection(), 1);  							if (camera->getOrigin().isExactlyZero())  							{ //origin is invalid, draw entire box -								mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); -								mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8);				 +								gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); +								gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8);				  							}  							else  							{ -								mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0])); +								gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0]));  							}  						}  						else @@ -1751,12 +1748,12 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)  							LLFastTimer t(FTM_OCCLUSION_DRAW);  							if (camera->getOrigin().isExactlyZero())  							{ //origin is invalid, draw entire box -								mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); -								mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8);				 +								gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); +								gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8);				  							}  							else  							{ -								mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0])); +								gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0]));  							}  						} @@ -2480,18 +2477,21 @@ void pushVerts(LLSpatialGroup* group, U32 mask)  void pushVerts(LLFace* face, U32 mask)  { -	llassert(face->verify()); +	if (face) +	{ +		llassert(face->verify()); -	LLVertexBuffer* buffer = face->getVertexBuffer(); +		LLVertexBuffer* buffer = face->getVertexBuffer(); -	if (buffer && (face->getGeomCount() >= 3)) -	{ -		buffer->setBuffer(mask); -		U16 start = face->getGeomStart(); -		U16 end = start + face->getGeomCount()-1; -		U32 count = face->getIndicesCount(); -		U16 offset = face->getIndicesStart(); -		buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); +		if (buffer && (face->getGeomCount() >= 3)) +		{ +			buffer->setBuffer(mask); +			U16 start = face->getGeomStart(); +			U16 end = start + face->getGeomCount()-1; +			U32 count = face->getIndicesCount(); +			U16 offset = face->getIndicesStart(); +			buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); +		}  	}  } @@ -2628,7 +2628,7 @@ void renderOctree(LLSpatialGroup* group)  				for (S32 j = 0; j < drawable->getNumFaces(); j++)  				{  					LLFace* face = drawable->getFace(j); -					if (face->getVertexBuffer()) +					if (face && face->getVertexBuffer())  					{  						if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f)  						{ @@ -2757,19 +2757,6 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera)  			gGL.diffuseColor4f(0.f, 0.75f, 0.f, 0.5f);  			pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX);  		} -		/*else if (camera && group->mOcclusionVerts.notNull()) -		{ -			LLVertexBuffer::unbind(); -			group->mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX); -			 -			gGL.diffuseColor4f(1.0f, 0.f, 0.f, 0.5f); -			group->mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, group->mBounds[0])); -			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -			 -			gGL.diffuseColor4f(1.0f, 1.f, 1.f, 1.0f); -			group->mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, group->mBounds[0])); -			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -		}*/  	}  } @@ -2999,15 +2986,17 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)  	for (S32 i = 0; i < drawable->getNumFaces(); i++)  	{  		LLFace* facep = drawable->getFace(i); +		if (facep) +		{ +			ext = facep->mExtents; -		ext = facep->mExtents; - -		pos.setAdd(ext[0], ext[1]); -		pos.mul(0.5f); -		size.setSub(ext[1], ext[0]); -		size.mul(0.5f); +			pos.setAdd(ext[0], ext[1]); +			pos.mul(0.5f); +			size.setSub(ext[1], ext[0]); +			size.mul(0.5f); -		drawBoxOutline(pos,size); +			drawBoxOutline(pos,size); +		}  	}  	//render drawable bounding box @@ -3499,18 +3488,21 @@ void renderPhysicsShapes(LLSpatialGroup* group)  				for (S32 i = 0; i < drawable->getNumFaces(); ++i)  				{  					LLFace* face = drawable->getFace(i); -					LLVertexBuffer* buff = face->getVertexBuffer(); -					if (buff) +					if (face)  					{ -						glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +						LLVertexBuffer* buff = face->getVertexBuffer(); +						if (buff) +						{ +							glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -						buff->setBuffer(LLVertexBuffer::MAP_VERTEX); -						gGL.diffuseColor3f(0.2f, 0.5f, 0.3f); -						buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); +							buff->setBuffer(LLVertexBuffer::MAP_VERTEX); +							gGL.diffuseColor3f(0.2f, 0.5f, 0.3f); +							buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); -						gGL.diffuseColor3f(0.2f, 1.f, 0.3f); -						glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -						buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); +							gGL.diffuseColor3f(0.2f, 1.f, 0.3f); +							glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +							buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); +						}  					}  				}  			} @@ -3534,6 +3526,7 @@ void renderTexturePriority(LLDrawable* drawable)  		//LLViewerTexture* imagep = facep->getTexture();  		//if (imagep) +		if (facep)  		{  			//F32 vsize = imagep->mMaxVirtualSize; @@ -3586,7 +3579,11 @@ void renderPoints(LLDrawable* drawablep)  		gGL.diffuseColor3f(1,1,1);  		for (S32 i = 0; i < drawablep->getNumFaces(); i++)  		{ -			gGL.vertex3fv(drawablep->getFace(i)->mCenterLocal.mV); +			LLFace * face = drawablep->getFace(i); +			if (face) +			{ +				gGL.vertex3fv(face->mCenterLocal.mV); +			}  		}  		gGL.end();  	} @@ -3767,7 +3764,11 @@ void renderLights(LLDrawable* drawablep)  		for (S32 i = 0; i < drawablep->getNumFaces(); i++)  		{ -			pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX); +			LLFace * face = drawablep->getFace(i); +			if (face) +			{ +				pushVerts(face, LLVertexBuffer::MAP_VERTEX); +			}  		}  		const LLVector4a* ext = drawablep->getSpatialExtents(); @@ -4169,18 +4170,21 @@ public:  				for (U32 i = 0; i < drawable->getNumFaces(); ++i)  				{  					LLFace* facep = drawable->getFace(i); -					U8 index = facep->getTextureIndex(); -					if (facep->mDrawInfo) +					if (facep)  					{ -						if (index < 255) +						U8 index = facep->getTextureIndex(); +						if (facep->mDrawInfo)  						{ -							if (facep->mDrawInfo->mTextureList.size() <= index) -							{ -								llerrs << "Face texture index out of bounds." << llendl; -							} -							else if (facep->mDrawInfo->mTextureList[index] != facep->getTexture()) +							if (index < 255)  							{ -								llerrs << "Face texture index incorrect." << llendl; +								if (facep->mDrawInfo->mTextureList.size() <= index) +								{ +									llerrs << "Face texture index out of bounds." << llendl; +								} +								else if (facep->mDrawInfo->mTextureList[index] != facep->getTexture()) +								{ +									llerrs << "Face texture index incorrect." << llendl; +								}  							}  						}  					} diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 1a93145cc5..f0e4f15a83 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -263,11 +263,10 @@ public:  		SKIP_FRUSTUM_CHECK		= 0x00000020,  		IN_IMAGE_QUEUE			= 0x00000040,  		IMAGE_DIRTY				= 0x00000080, -		OCCLUSION_DIRTY			= 0x00000100, -		MESH_DIRTY				= 0x00000200, -		NEW_DRAWINFO			= 0x00000400, -		IN_BUILD_Q1				= 0x00000800, -		IN_BUILD_Q2				= 0x00001000, +		MESH_DIRTY				= 0x00000100, +		NEW_DRAWINFO			= 0x00000200, +		IN_BUILD_Q1				= 0x00000400, +		IN_BUILD_Q2				= 0x00000800,  		STATE_MASK				= 0x0000FFFF,  	} eSpatialState; @@ -313,10 +312,9 @@ public:  	BOOL boundObjects(BOOL empty, LLVector4a& newMin, LLVector4a& newMax);  	void unbound();  	BOOL rebound(); -	void buildOcclusion(); //rebuild mOcclusionVerts  	void checkOcclusion(); //read back last occlusion query (if any)  	void doOcclusion(LLCamera* camera); //issue occlusion query -	void destroyGL(); +	void destroyGL(bool keep_occlusion = false);  	void updateDistance(LLCamera& camera);  	BOOL needsUpdate(); @@ -415,7 +413,6 @@ public:  	LLSpatialPartition* mSpatialPartition;  	LLPointer<LLVertexBuffer> mVertexBuffer; -	LLPointer<LLVertexBuffer> mOcclusionVerts;  	GLuint					mOcclusionQuery[LLViewerCamera::NUM_CAMERAS];  	U32 mBufferUsage; @@ -657,6 +654,7 @@ class LLParticlePartition : public LLSpatialPartition  {  public:  	LLParticlePartition(); +	virtual void rebuildGeom(LLSpatialGroup* group);  	virtual void getGeometry(LLSpatialGroup* group);  	virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count);  	virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera); @@ -671,10 +669,14 @@ public:  };  //spatial partition for grass (implemented in LLVOGrass.cpp) -class LLGrassPartition : public LLParticlePartition +class LLGrassPartition : public LLSpatialPartition  {  public:  	LLGrassPartition(); +	virtual void getGeometry(LLSpatialGroup* group); +	virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count); +protected: +	U32 mRenderPass;  };  //class for wrangling geometry out of volumes (implemented in LLVOVolume.cpp) diff --git a/indra/newview/lltextureatlas.cpp b/indra/newview/lltextureatlas.cpp index d2e4b01732..f8c1bca8ae 100644 --- a/indra/newview/lltextureatlas.cpp +++ b/indra/newview/lltextureatlas.cpp @@ -116,7 +116,6 @@ LLGLuint LLTextureAtlas::insertSubTexture(LLImageGL* source_gl_tex, S32 discard_  		return 0 ;  	} -	glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, TRUE);  	glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, w, h,  						mGLTexturep->getPrimaryFormat(), mGLTexturep->getFormatType(), raw_image->getData()); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index ed9faa0706..6703ef4a41 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -97,6 +97,7 @@ public:  		LLTextureCtrl* owner,  		const std::string& label,  		PermissionMask immediate_filter_perm_mask, +		PermissionMask dnd_filter_perm_mask,  		PermissionMask non_immediate_filter_perm_mask,  		BOOL can_apply_immediately,  		LLUIImagePtr fallback_image_name); @@ -134,6 +135,9 @@ public:  	void onFilterEdit(const std::string& search_string ); +	void setCanApply(bool can_preview, bool can_apply); +	void setTextureSelectedCallback(texture_selected_callback cb) {mTextureSelectedCallback = cb;} +  	static void		onBtnSetToDefault( void* userdata );  	static void		onBtnSelect( void* userdata );  	static void		onBtnCancel( void* userdata ); @@ -175,6 +179,7 @@ protected:  	LLFilterEditor*		mFilterEdit;  	LLInventoryPanel*	mInventoryPanel;  	PermissionMask		mImmediateFilterPermMask; +	PermissionMask		mDnDFilterPermMask;  	PermissionMask		mNonImmediateFilterPermMask;  	BOOL				mCanApplyImmediately;  	BOOL				mNoCopyTextureSelected; @@ -184,12 +189,18 @@ protected:  	LLRadioGroup*		mModeSelector;  	LLScrollListCtrl*	mLocalScrollCtrl; + +private: +	bool mCanApply; +	bool mCanPreview; +	texture_selected_callback mTextureSelectedCallback;  };  LLFloaterTexturePicker::LLFloaterTexturePicker(	  	LLTextureCtrl* owner,  	const std::string& label,  	PermissionMask immediate_filter_perm_mask, +	PermissionMask dnd_filter_perm_mask,  	PermissionMask non_immediate_filter_perm_mask,  	BOOL can_apply_immediately,  	LLUIImagePtr fallback_image) @@ -205,9 +216,12 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(  	mActive( TRUE ),  	mFilterEdit(NULL),  	mImmediateFilterPermMask(immediate_filter_perm_mask), +	mDnDFilterPermMask(dnd_filter_perm_mask),  	mNonImmediateFilterPermMask(non_immediate_filter_perm_mask),  	mContextConeOpacity(0.f), -	mSelectedItemPinned( FALSE ) +	mSelectedItemPinned( FALSE ), +	mCanApply(true), +	mCanPreview(true)  {  	buildFromFile("floater_texture_ctrl.xml");  	mCanApplyImmediately = can_apply_immediately; @@ -319,7 +333,7 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop(  		if (xfer) item_perm_mask |= PERM_TRANSFER;  		//PermissionMask filter_perm_mask = getFilterPermMask();  Commented out due to no-copy texture loss. -		PermissionMask filter_perm_mask = mImmediateFilterPermMask; +		PermissionMask filter_perm_mask = mDnDFilterPermMask;  		if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask )  		{  			if (drop) @@ -464,7 +478,7 @@ BOOL LLFloaterTexturePicker::postBuild()  	mNoCopyTextureSelected = FALSE; -	getChild<LLUICtrl>("apply_immediate_check")->setValue(gSavedSettings.getBOOL("ApplyTextureImmediately")); +	getChild<LLUICtrl>("apply_immediate_check")->setValue(gSavedSettings.getBOOL("TextureLivePreview"));  	childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this);  	if (!mCanApplyImmediately) @@ -546,7 +560,7 @@ void LLFloaterTexturePicker::draw()  	// if we're inactive, gray out "apply immediate" checkbox  	getChildView("show_folders_check")->setEnabled(mActive && mCanApplyImmediately && !mNoCopyTextureSelected); -	getChildView("Select")->setEnabled(mActive); +	getChildView("Select")->setEnabled(mActive && mCanApply);  	getChildView("Pipette")->setEnabled(mActive);  	getChild<LLUICtrl>("Pipette")->setValue(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()); @@ -702,8 +716,7 @@ PermissionMask LLFloaterTexturePicker::getFilterPermMask()  void LLFloaterTexturePicker::commitIfImmediateSet()  { -	bool apply_immediate = getChild<LLUICtrl>("apply_immediate_check")->getValue().asBoolean(); -	if (!mNoCopyTextureSelected && apply_immediate && mOwner) +	if (!mNoCopyTextureSelected && mOwner && mCanApply)  	{  		mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE);  	} @@ -713,6 +726,7 @@ void LLFloaterTexturePicker::commitIfImmediateSet()  void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata)  {  	LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; +	self->setCanApply(true, true);  	if (self->mOwner)  	{  		self->setImageID( self->mOwner->getDefaultImageAssetID() ); @@ -724,6 +738,7 @@ void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata)  void LLFloaterTexturePicker::onBtnWhite(void* userdata)  {  	LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; +	self->setCanApply(true, true);  	self->setImageID( self->mWhiteImageAssetID );  	self->commitIfImmediateSet();  } @@ -804,13 +819,14 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem  		mNoCopyTextureSelected = FALSE;  		if (itemp)  		{ +			mTextureSelectedCallback(itemp);  			if (!itemp->getPermissions().allowCopyBy(gAgent.getID()))  			{  				mNoCopyTextureSelected = TRUE;  			}  			mImageAssetID = itemp->getAssetUUID();  			mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? -			if (user_action) +			if (user_action && mCanPreview)  			{  				// only commit intentional selections, not implicit ones  				commitIfImmediateSet(); @@ -947,7 +963,7 @@ void LLFloaterTexturePicker::onApplyImmediateCheck(LLUICtrl* ctrl, void *user_da  	LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data;  	LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl; -	gSavedSettings.setBOOL("ApplyTextureImmediately", check_box->get()); +	gSavedSettings.setBOOL("TextureLivePreview", check_box->get());  	picker->updateFilterPermMask();  	picker->commitIfImmediateSet(); @@ -958,6 +974,16 @@ void LLFloaterTexturePicker::updateFilterPermMask()  	//mInventoryPanel->setFilterPermMask( getFilterPermMask() );  Commented out due to no-copy texture loss.  } +void LLFloaterTexturePicker::setCanApply(bool can_preview, bool can_apply) +{ +	getChildRef<LLUICtrl>("Select").setEnabled(can_apply); +	getChildRef<LLUICtrl>("preview_disabled").setVisible(!can_preview); +	getChildRef<LLUICtrl>("apply_immediate_check").setVisible(can_preview); + +	mCanApply = can_apply; +	mCanPreview = can_preview ? gSavedSettings.getBOOL("TextureLivePreview") : false; +} +  void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string )  {  	std::string upper_case_search_string = search_string; @@ -1108,6 +1134,15 @@ void LLTextureCtrl::setCanApplyImmediately(BOOL b)  	}  } +void LLTextureCtrl::setCanApply(bool can_preview, bool can_apply) +{ +	LLFloaterTexturePicker* floaterp = dynamic_cast<LLFloaterTexturePicker*>(mFloaterHandle.get()); +	if( floaterp ) +	{ +		floaterp->setCanApply(can_preview, can_apply); +	} +} +  void LLTextureCtrl::setVisible( BOOL visible )   {  	if( !visible ) @@ -1188,12 +1223,19 @@ void LLTextureCtrl::showPicker(BOOL take_focus)  			this,  			mLabel,  			mImmediateFilterPermMask, +			mDnDFilterPermMask,  			mNonImmediateFilterPermMask,  			mCanApplyImmediately,  			mFallbackImage);  		mFloaterHandle = floaterp->getHandle(); +		LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp); +		if (texture_floaterp && mOnTextureSelectedCallback) +		{ +			texture_floaterp->setTextureSelectedCallback(mOnTextureSelectedCallback); +		} +  		LLFloater* root_floater = gFloaterView->getParentFloater(this);  		if (root_floater)  			root_floater->addDependentFloater(floaterp); @@ -1318,6 +1360,16 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id)  	}  } +void LLTextureCtrl::setOnTextureSelectedCallback(texture_selected_callback cb) +{ +	mOnTextureSelectedCallback = cb; +	LLFloaterTexturePicker* floaterp = dynamic_cast<LLFloaterTexturePicker*>(mFloaterHandle.get()); +	if (floaterp) +	{ +		floaterp->setTextureSelectedCallback(cb); +	} +} +  void	LLTextureCtrl::setImageAssetName(const std::string& name)  {  	LLPointer<LLUIImage> imagep = LLUI::getUIImage(name); diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 3abe84dcc3..599d9c70c5 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -43,6 +43,7 @@ class LLViewerFetchedTexture;  // used for setting drag & drop callbacks.  typedef boost::function<BOOL (LLUICtrl*, LLInventoryItem*)> drag_n_drop_callback; +typedef boost::function<void (LLInventoryItem*)> texture_selected_callback;  ////////////////////////////////////////////////////////////////////////////////////////// @@ -147,8 +148,12 @@ public:  	void			setCaption(const std::string& caption);  	void			setCanApplyImmediately(BOOL b); +	void			setCanApply(bool can_preview, bool can_apply); +  	void			setImmediateFilterPermMask(PermissionMask mask)  					{ mImmediateFilterPermMask = mask; } +	void			setDnDFilterPermMask(PermissionMask mask) +						{ mDnDFilterPermMask = mask; }  	void			setNonImmediateFilterPermMask(PermissionMask mask)  					{ mNonImmediateFilterPermMask = mask; }  	PermissionMask	getImmediateFilterPermMask() { return mImmediateFilterPermMask; } @@ -172,6 +177,11 @@ public:  	void setOnSelectCallback(commit_callback_t cb)	{ mOnSelectCallback = cb; } +	/* +	 * callback for changing texture selection in inventory list of texture floater +	 */ +	void setOnTextureSelectedCallback(texture_selected_callback cb); +  	void setShowLoadingPlaceholder(BOOL showLoadingPlaceholder);  	LLViewerFetchedTexture* getTexture() { return mTexturep; } @@ -185,6 +195,7 @@ private:  	drag_n_drop_callback	 	mDropCallback;  	commit_callback_t		 	mOnCancelCallback;  	commit_callback_t		 	mOnSelectCallback; +	texture_selected_callback	mOnTextureSelectedCallback;  	LLPointer<LLViewerFetchedTexture> mTexturep;  	LLUIColor				 	mBorderColor;  	LLUUID					 	mImageItemID; @@ -198,6 +209,7 @@ private:  	std::string				 	mLabel;  	BOOL					 	mAllowNoTexture; // If true, the user can select "none" as an option  	PermissionMask			 	mImmediateFilterPermMask; +	PermissionMask				mDnDFilterPermMask;  	PermissionMask			 	mNonImmediateFilterPermMask;  	BOOL					 	mCanApplyImmediately;  	BOOL					 	mCommitOnSelection; diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 425bf7ee87..52d085dd2c 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -510,7 +510,7 @@ void LLGLTexMemBar::draw()  	F32 discard_bias = LLViewerTexture::sDesiredDiscardBias;  	F32 cache_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getUsage()) ;  	F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ; -	S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); +	S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();  	S32 v_offset = 0;//(S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f);  	F32 total_texture_downloaded = (F32)gTotalTextureBytes / (1024 * 1024);  	F32 total_object_downloaded = (F32)gTotalObjectBytes / (1024 * 1024); diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 245c2a23e6..41aee484db 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -93,6 +93,13 @@ public:  	static S32 getOperationId() { return sOperationId; } +	// deal with permissions of object, etc. returns TRUE if drop can +	// proceed, otherwise FALSE. +	static BOOL handleDropTextureProtections(LLViewerObject* hit_obj, +						 LLInventoryItem* item, +						 LLToolDragAndDrop::ESource source, +						 const LLUUID& src_id); +  protected:  	enum EDropTarget  	{ @@ -219,13 +226,6 @@ protected:  	// inventory items to determine if a drop would be ok.  	static EAcceptance willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item); -	// deal with permissions of object, etc. returns TRUE if drop can -	// proceed, otherwise FALSE. -	static BOOL handleDropTextureProtections(LLViewerObject* hit_obj, -						 LLInventoryItem* item, -						 LLToolDragAndDrop::ESource source, -						 const LLUUID& src_id); -  public:  	// helper functions  	static BOOL isInventoryDropAcceptable(LLViewerObject* obj, LLInventoryItem* item) { return (ACCEPT_YES_COPY_SINGLE <= willObjectAcceptInventory(obj, item)); } diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp index 718201e381..0d5daf129f 100644 --- a/indra/newview/lltoolmorph.cpp +++ b/indra/newview/lltoolmorph.cpp @@ -225,7 +225,8 @@ BOOL LLVisualParamHint::render()  	LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE); -	if (gAgentAvatarp->mDrawable.notNull()) +	if (gAgentAvatarp->mDrawable.notNull() && +		gAgentAvatarp->mDrawable->getFace(0))  	{  		LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)gAgentAvatarp->mDrawable->getFace(0)->getPool();  		LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 2b4628ea2e..dec1615246 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -329,7 +329,7 @@ static bool handleJoystickChanged(const LLSD& newvalue)  static bool handleUseOcclusionChanged(const LLSD& newvalue)  { -	LLPipeline::sUseOcclusion = (newvalue.asBoolean() && gGLManager.mHasOcclusionQuery  +	LLPipeline::sUseOcclusion = (newvalue.asBoolean() && gGLManager.mHasOcclusionQuery && LLGLSLShader::sNoFixedFunction  		&& LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && !gUseWireframe) ? 2 : 0;  	return true;  } diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 1afe0d4050..4571d08050 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -631,11 +631,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)  		LLSpatialGroup::sNoDelete = TRUE;  		LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName(); -		/*if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred) -		{ //force occlusion on for all render types if doing deferred render (tighter shadow frustum) -			LLPipeline::sUseOcclusion = 3; -		}*/ -  		S32 occlusion = LLPipeline::sUseOcclusion;  		if (gDepthDirty)  		{ //depth buffer is invalid, don't overwrite occlusion state @@ -764,12 +759,12 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)  				gTextureList.updateImages(max_image_decode_time);  			} -			{ +			/*{  				LLFastTimer t(FTM_IMAGE_UPDATE_DELETE);  				//remove dead textures from GL  				LLImageGL::deleteDeadTextures();  				stop_glerror(); -			} +			}*/  		}  		LLGLState::checkStates(); @@ -898,6 +893,28 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)  		{  			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;  			LLMemType mt_rg(LLMemType::MTYPE_DISPLAY_RENDER_GEOM); + +			if (gSavedSettings.getBOOL("RenderDepthPrePass") && LLGLSLShader::sNoFixedFunction) +			{ +				gGL.setColorMask(false, false); +				 +				U32 types[] = {  +					LLRenderPass::PASS_SIMPLE,  +					LLRenderPass::PASS_FULLBRIGHT,  +					LLRenderPass::PASS_SHINY  +				}; + +				U32 num_types = LL_ARRAY_SIZE(types); +				gOcclusionProgram.bind(); +				for (U32 i = 0; i < num_types; i++) +				{ +					gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); +				} + +				gOcclusionProgram.unbind(); +			} + +  			gGL.setColorMask(true, false);  			if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)  			{ diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp index 4e14824e69..3a04bbed4f 100644 --- a/indra/newview/llviewerjointattachment.cpp +++ b/indra/newview/llviewerjointattachment.cpp @@ -127,7 +127,11 @@ void LLViewerJointAttachment::setupDrawable(LLViewerObject *object)  	{  		for (S32 face_num = 0; face_num < object->mDrawable->getNumFaces(); face_num++)  		{ -			object->mDrawable->getFace(face_num)->setState(LLFace::HUD_RENDER); +			LLFace *face = object->mDrawable->getFace(face_num); +			if (face) +			{ +				face->setState(LLFace::HUD_RENDER); +			}  		}  	} @@ -146,7 +150,11 @@ void LLViewerJointAttachment::setupDrawable(LLViewerObject *object)  			{  				for (S32 face_num = 0; face_num < childp->mDrawable->getNumFaces(); face_num++)  				{ -					childp->mDrawable->getFace(face_num)->setState(LLFace::HUD_RENDER); +					LLFace * face = childp->mDrawable->getFace(face_num); +					if (face) +					{ +						face->setState(LLFace::HUD_RENDER); +					}  				}  			}  		} @@ -254,7 +262,11 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object)  		{  			for (S32 face_num = 0; face_num < object->mDrawable->getNumFaces(); face_num++)  			{ -				object->mDrawable->getFace(face_num)->clearState(LLFace::HUD_RENDER); +				LLFace * face = object->mDrawable->getFace(face_num); +				if (face) +				{ +					face->clearState(LLFace::HUD_RENDER); +				}  			}  		}  	} @@ -272,7 +284,11 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object)  			{  				for (S32 face_num = 0; face_num < childp->mDrawable->getNumFaces(); face_num++)  				{ -					childp->mDrawable->getFace(face_num)->clearState(LLFace::HUD_RENDER); +					LLFace * face = childp->mDrawable->getFace(face_num); +					if (face) +					{ +						face->clearState(LLFace::HUD_RENDER); +					}  				}  			}  		} diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index a07dfad0f5..0baf119d70 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2812,7 +2812,11 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			chat.mSourceType = CHAT_SOURCE_OBJECT; -			if(SYSTEM_FROM == name) +			// To conclude that the source type of message is CHAT_SOURCE_SYSTEM it's not +			// enough to check only from name (i.e. fromName = "Second Life"). For example +			// source type of messages from objects called "Second Life" should not be CHAT_SOURCE_SYSTEM. +			bool chat_from_system = (SYSTEM_FROM == name) && region_id.isNull() && position.isNull(); +			if(chat_from_system)  			{  				// System's UUID is NULL (fixes EXT-4766)  				chat.mFromID = LLUUID::null; @@ -2837,7 +2841,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			// Note: lie to Nearby Chat, pretending that this is NOT an IM, because  			// IMs from obejcts don't open IM sessions.  			LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); -			if(SYSTEM_FROM != name && nearby_chat) +			if(!chat_from_system && nearby_chat)  			{  				chat.mOwnerID = from_id;  				LLSD args; @@ -2856,7 +2860,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			//Object IMs send with from name: 'Second Life' need to be displayed also in notification toasts (EXT-1590) -			if (SYSTEM_FROM != name) break; +			if (!chat_from_system) break;  			LLSD substitutions;  			substitutions["NAME"] = name; @@ -4256,6 +4260,8 @@ void send_agent_update(BOOL force_send, BOOL send_reliable)  	head_rot_chg = dot(last_head_rot, head_rotation); +	//static S32 msg_number = 0;		// Used for diagnostic log messages +  	if (force_send ||   		(cam_center_chg.magVec() > TRANSLATE_THRESHOLD) ||   		(head_rot_chg < THRESHOLD_HEAD_ROT_QDOT) ||	 @@ -4264,19 +4270,20 @@ void send_agent_update(BOOL force_send, BOOL send_reliable)  		control_flag_change != 0 ||  		flag_change != 0)    	{ -/* +		/* Diagnotics to show why we send the AgentUpdate message.  Also un-commment the msg_number code above and below this block +		msg_number += 1;  		if (head_rot_chg < THRESHOLD_HEAD_ROT_QDOT)  		{ -			//LL_INFOS("Messaging") << "head rot " << head_rotation << LL_ENDL; -			LL_INFOS("Messaging") << "head_rot_chg = " << head_rot_chg << LL_ENDL; +			//LL_INFOS("Messaging") << " head rot " << head_rotation << LL_ENDL; +			LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", head_rot_chg " << head_rot_chg << LL_ENDL;  		}  		if (cam_rot_chg.magVec() > ROTATION_THRESHOLD)   		{ -			LL_INFOS("Messaging") << "cam rot " <<  cam_rot_chg.magVec() << LL_ENDL; +			LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", cam rot " <<  cam_rot_chg.magVec() << LL_ENDL;  		}  		if (cam_center_chg.magVec() > TRANSLATE_THRESHOLD)  		{ -			LL_INFOS("Messaging") << "cam center " << cam_center_chg.magVec() << LL_ENDL; +			LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", cam center " << cam_center_chg.magVec() << LL_ENDL;  		}  //		if (drag_delta_chg.magVec() > TRANSLATE_THRESHOLD)  //		{ @@ -4284,9 +4291,9 @@ void send_agent_update(BOOL force_send, BOOL send_reliable)  //		}  		if (control_flag_change)  		{ -			LL_INFOS("Messaging") << "dcf = " << control_flag_change << LL_ENDL; +			LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", dcf = " << control_flag_change << LL_ENDL;  		} -*/ +		*/  		duplicate_count = 0;  	} @@ -4321,6 +4328,26 @@ void send_agent_update(BOOL force_send, BOOL send_reliable)  	if (duplicate_count < DUP_MSGS && !gDisconnected)  	{ +		/* More diagnostics to count AgentUpdate messages +		static S32 update_sec = 0; +		static S32 update_count = 0; +		static S32 max_update_count = 0; +		S32 cur_sec = lltrunc( LLTimer::getTotalSeconds() ); +		update_count += 1; +		if (cur_sec != update_sec) +		{ +			if (update_sec != 0) +			{ +				update_sec = cur_sec; +				//msg_number = 0; +				max_update_count = llmax(max_update_count, update_count); +				llinfos << "Sent " << update_count << " AgentUpdate messages per second, max is " << max_update_count << llendl; +			} +			update_sec = cur_sec; +			update_count = 0; +		} +		*/ +  		LLFastTimer t(FTM_AGENT_UPDATE_SEND);  		// Build the message  		msg->newMessageFast(_PREHASH_AgentUpdate); @@ -4489,8 +4516,6 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data)  			LL_DEBUGS("Messaging") << "Kill message for local " << local_id << LL_ENDL;  		} -		LLSelectMgr::getInstance()->removeObjectFromSelections(id); -  		// ...don't kill the avatar  		if (!(id == gAgentID))  		{ @@ -4513,6 +4538,12 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data)  				gObjectList.mNumUnknownKills++;  			}  		} + +		// We should remove the object from selection after it is marked dead by gObjectList to make LLToolGrab, +        // which is using the object, release the mouse capture correctly when the object dies. +        // See LLToolGrab::handleHoverActive() and LLToolGrab::handleHoverNonPhysical(). +		LLSelectMgr::getInstance()->removeObjectFromSelections(id); +  	}  } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index da72f2fdac..72fd3c1a4a 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -432,7 +432,9 @@ void LLViewerObject::dump() const  	llinfos << "PositionAgent: " << getPositionAgent() << llendl;  	llinfos << "PositionGlobal: " << getPositionGlobal() << llendl;  	llinfos << "Velocity: " << getVelocity() << llendl; -	if (mDrawable.notNull() && mDrawable->getNumFaces()) +	if (mDrawable.notNull() &&  +		mDrawable->getNumFaces() &&  +		mDrawable->getFace(0))  	{  		LLFacePool *poolp = mDrawable->getFace(0)->getPool();  		if (poolp) @@ -2799,6 +2801,23 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS  	   (object = gObjectList.findObject(ft->mTaskID)))  	{  		object->loadTaskInvFile(ft->mFilename); + +		LLInventoryObject::object_list_t::iterator it = object->mInventory->begin(); +		LLInventoryObject::object_list_t::iterator end = object->mInventory->end(); +		std::list<LLUUID>& pending_lst = object->mPendingInventoryItemsIDs; + +		for (; it != end && pending_lst.size(); ++it) +		{ +			LLViewerInventoryItem* item = dynamic_cast<LLViewerInventoryItem*>(it->get()); +			if(item && item->getType() != LLAssetType::AT_CATEGORY) +			{ +				std::list<LLUUID>::iterator id_it = std::find(pending_lst.begin(), pending_lst.begin(), item->getAssetUUID()); +				if (id_it != pending_lst.end()) +				{ +					pending_lst.erase(id_it); +				} +			} +		}  	}  	else  	{ @@ -2911,7 +2930,22 @@ void LLViewerObject::updateInventory(  	bool is_new)  {  	LLMemType mt(LLMemType::MTYPE_OBJECT); -	 + +	std::list<LLUUID>::iterator begin = mPendingInventoryItemsIDs.begin(); +	std::list<LLUUID>::iterator end = mPendingInventoryItemsIDs.end(); + +	bool is_fetching = std::find(begin, end, item->getAssetUUID()) != end; +	bool is_fetched = getInventoryItemByAsset(item->getAssetUUID()) != NULL; + +	if (is_fetched || is_fetching) +	{ +		return; +	} +	else +	{ +		mPendingInventoryItemsIDs.push_back(item->getAssetUUID()); +	} +  	// This slices the object into what we're concerned about on the  	// viewer. The simulator will take the permissions and transfer  	// ownership. @@ -4478,7 +4512,11 @@ U32 LLViewerObject::getNumVertices() const  		num_faces = mDrawable->getNumFaces();  		for (i = 0; i < num_faces; i++)  		{ -			num_vertices += mDrawable->getFace(i)->getGeomCount(); +			LLFace * facep = mDrawable->getFace(i); +			if (facep) +			{ +				num_vertices += facep->getGeomCount(); +			}  		}  	}  	return num_vertices; @@ -4493,7 +4531,11 @@ U32 LLViewerObject::getNumIndices() const  		num_faces = mDrawable->getNumFaces();  		for (i = 0; i < num_faces; i++)  		{ -			num_indices += mDrawable->getFace(i)->getIndicesCount(); +			LLFace * facep = mDrawable->getFace(i); +			if (facep) +			{ +				num_indices += facep->getIndicesCount(); +			}  		}  	}  	return num_indices; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index c8152e1539..dc102b666f 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -684,6 +684,10 @@ protected:  	F32				mAppAngle;	// Apparent visual arc in degrees  	F32				mPixelArea; // Apparent area in pixels +	// IDs of of all items in the object's content which are added to the object's content, +	// but not updated on the server yet. After item was updated, its ID will be removed from this list. +	std::list<LLUUID> mPendingInventoryItemsIDs; +  	// This is the object's inventory from the viewer's perspective.  	LLInventoryObject::object_list_t* mInventory;  	class LLInventoryCallbackInfo diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 54ccfb9aae..beb68c1cbb 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -1721,7 +1721,10 @@ void LLViewerObjectList::generatePickList(LLCamera &camera)  			LLViewerObject* last_objectp = NULL;  			for (S32 face_num = 0; face_num < drawablep->getNumFaces(); face_num++)  			{ -				LLViewerObject* objectp = drawablep->getFace(face_num)->getViewerObject(); +				LLFace * facep = drawablep->getFace(face_num); +				if (!facep) continue; + +				LLViewerObject* objectp = facep->getViewerObject();  				if (objectp && objectp != last_objectp)  				{ diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index 6b3e04348a..345023dbfa 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -476,7 +476,7 @@ void LLViewerPartSim::checkParticleCount(U32 size)  LLViewerPartSim::LLViewerPartSim()  {  	LLMemType mt(LLMemType::MTYPE_PARTICLES); -	sMaxParticleCount = gSavedSettings.getS32("RenderMaxPartCount"); +	sMaxParticleCount = llmin(gSavedSettings.getS32("RenderMaxPartCount"), LL_MAX_PARTICLE_COUNT);  	static U32 id_seed = 0;  	mID = ++id_seed;  } diff --git a/indra/newview/llviewerpartsim.h b/indra/newview/llviewerpartsim.h index 3e20f999c0..c9959c63ec 100644 --- a/indra/newview/llviewerpartsim.h +++ b/indra/newview/llviewerpartsim.h @@ -39,6 +39,8 @@ class LLViewerRegion;  class LLViewerTexture;  class LLVOPartGroup; +#define LL_MAX_PARTICLE_COUNT 8192 +  typedef void (*LLVPCallback)(LLViewerPart &part, const F32 dt);  /////////////////// diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 10c61c01d5..a6c564a6a1 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -63,8 +63,16 @@ bool				LLViewerShaderMgr::sSkipReload = false;  LLVector4			gShinyOrigin; +//transform shaders +LLGLSLShader			gTransformPositionProgram; +LLGLSLShader			gTransformTexCoordProgram; +LLGLSLShader			gTransformNormalProgram; +LLGLSLShader			gTransformColorProgram; +LLGLSLShader			gTransformBinormalProgram; +  //utility shaders  LLGLSLShader	gOcclusionProgram; +LLGLSLShader	gOcclusionCubeProgram;  LLGLSLShader	gCustomAlphaProgram;  LLGLSLShader	gGlowCombineProgram;  LLGLSLShader	gSplatTextureRectProgram; @@ -72,6 +80,7 @@ LLGLSLShader	gGlowCombineFXAAProgram;  LLGLSLShader	gTwoTextureAddProgram;  LLGLSLShader	gOneTextureNoColorProgram;  LLGLSLShader	gDebugProgram; +LLGLSLShader	gClipProgram;  LLGLSLShader	gAlphaMaskProgram;  //object shaders @@ -178,6 +187,7 @@ LLGLSLShader			gDeferredSunProgram;  LLGLSLShader			gDeferredBlurLightProgram;  LLGLSLShader			gDeferredSoftenProgram;  LLGLSLShader			gDeferredShadowProgram; +LLGLSLShader			gDeferredShadowCubeProgram;  LLGLSLShader			gDeferredShadowAlphaMaskProgram;  LLGLSLShader			gDeferredAvatarShadowProgram;  LLGLSLShader			gDeferredAttachmentShadowProgram; @@ -437,7 +447,8 @@ void LLViewerShaderMgr::setShaders()  		S32 wl_class = 2;  		S32 water_class = 2;  		S32 deferred_class = 0; -		 +		S32 transform_class = gGLManager.mHasTransformFeedback ? 1 : 0; +  		if (LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&  		    gSavedSettings.getBOOL("RenderDeferred") &&  			gSavedSettings.getBOOL("RenderAvatarVP") && @@ -475,6 +486,7 @@ void LLViewerShaderMgr::setShaders()  			gSky.mVOSkyp->forceSkyUpdate();  		} +		  		// Load lighting shaders  		mVertexShaderLevel[SHADER_LIGHTING] = light_class;  		mVertexShaderLevel[SHADER_INTERFACE] = light_class; @@ -484,6 +496,7 @@ void LLViewerShaderMgr::setShaders()  		mVertexShaderLevel[SHADER_EFFECT] = effect_class;  		mVertexShaderLevel[SHADER_WINDLIGHT] = wl_class;  		mVertexShaderLevel[SHADER_DEFERRED] = deferred_class; +		mVertexShaderLevel[SHADER_TRANSFORM] = transform_class;  		BOOL loaded = loadBasicShaders(); @@ -493,65 +506,109 @@ void LLViewerShaderMgr::setShaders()  			gPipeline.mVertexShadersLoaded = 1;  			// Load all shaders to set max levels -			loadShadersEnvironment(); -			loadShadersWater(); -			loadShadersWindLight(); -			loadShadersEffects(); -			loadShadersInterface(); +			loaded = loadShadersEnvironment(); + +			if (loaded) +			{ +				loaded = loadShadersWater(); +			} + +			if (loaded) +			{ +				loaded = loadShadersWindLight(); +			} + +			if (loaded) +			{ +				loaded = loadShadersEffects(); +			} + +			if (loaded) +			{ +				loaded = loadShadersInterface(); +			} -			// Load max avatar shaders to set the max level -			mVertexShaderLevel[SHADER_AVATAR] = 3; -			mMaxAvatarShaderLevel = 3; -						 -			if (gSavedSettings.getBOOL("RenderAvatarVP") && loadShadersObject()) -			{ //hardware skinning is enabled and rigged attachment shaders loaded correctly -				BOOL avatar_cloth = gSavedSettings.getBOOL("RenderAvatarCloth"); -				S32 avatar_class = 1; -				 -				// cloth is a class3 shader -				if(avatar_cloth) -				{ -					avatar_class = 3; -				} +			if (loaded) +			{ +				loaded = loadTransformShaders(); +			} -				// Set the actual level -				mVertexShaderLevel[SHADER_AVATAR] = avatar_class; -				loadShadersAvatar(); -				if (mVertexShaderLevel[SHADER_AVATAR] != avatar_class) -				{ -					if (mVertexShaderLevel[SHADER_AVATAR] == 0) +			if (loaded) +			{ +				// Load max avatar shaders to set the max level +				mVertexShaderLevel[SHADER_AVATAR] = 3; +				mMaxAvatarShaderLevel = 3; +				 +				if (gSavedSettings.getBOOL("RenderAvatarVP") && loadShadersObject()) +				{ //hardware skinning is enabled and rigged attachment shaders loaded correctly +					BOOL avatar_cloth = gSavedSettings.getBOOL("RenderAvatarCloth"); +					S32 avatar_class = 1; +				 +					// cloth is a class3 shader +					if(avatar_cloth)  					{ -						gSavedSettings.setBOOL("RenderAvatarVP", FALSE); +						avatar_class = 3;  					} -					if(llmax(mVertexShaderLevel[SHADER_AVATAR]-1,0) >= 3) + +					// Set the actual level +					mVertexShaderLevel[SHADER_AVATAR] = avatar_class; +					loadShadersAvatar(); +					if (mVertexShaderLevel[SHADER_AVATAR] != avatar_class)  					{ -						avatar_cloth = true; +						if (mVertexShaderLevel[SHADER_AVATAR] == 0) +						{ +							gSavedSettings.setBOOL("RenderAvatarVP", FALSE); +						} +						if(llmax(mVertexShaderLevel[SHADER_AVATAR]-1,0) >= 3) +						{ +							avatar_cloth = true; +						} +						else +						{ +							avatar_cloth = false; +						} +						gSavedSettings.setBOOL("RenderAvatarCloth", avatar_cloth);  					} -					else +				} +				else +				{ //hardware skinning not possible, neither is deferred rendering +					mVertexShaderLevel[SHADER_AVATAR] = 0; +					mVertexShaderLevel[SHADER_DEFERRED] = 0; + +					if (gSavedSettings.getBOOL("RenderAvatarVP"))  					{ -						avatar_cloth = false; +						gSavedSettings.setBOOL("RenderDeferred", FALSE); +						gSavedSettings.setBOOL("RenderAvatarCloth", FALSE); +						gSavedSettings.setBOOL("RenderAvatarVP", FALSE);  					} -					gSavedSettings.setBOOL("RenderAvatarCloth", avatar_cloth); + +					loadShadersAvatar(); // unloads + +					loaded = loadShadersObject();  				}  			} -			else -			{ //hardware skinning not possible, neither is deferred rendering -				mVertexShaderLevel[SHADER_AVATAR] = 0; -				mVertexShaderLevel[SHADER_DEFERRED] = 0; - -				if (gSavedSettings.getBOOL("RenderAvatarVP")) -				{ -					gSavedSettings.setBOOL("RenderDeferred", FALSE); -					gSavedSettings.setBOOL("RenderAvatarCloth", FALSE); -					gSavedSettings.setBOOL("RenderAvatarVP", FALSE); + +			if (!loaded) +			{ //some shader absolutely could not load, try to fall back to a simpler setting +				if (gSavedSettings.getBOOL("WindLightUseAtmosShaders")) +				{ //disable windlight and try again +					gSavedSettings.setBOOL("WindLightUseAtmosShaders", FALSE); +					reentrance = false; +					setShaders(); +					return;  				} -				loadShadersAvatar(); // unloads -				loadShadersObject(); -			} +				if (gSavedSettings.getBOOL("VertexShaderEnable")) +				{ //disable shaders outright and try again +					gSavedSettings.setBOOL("VertexShaderEnable", FALSE); +					reentrance = false; +					setShaders(); +					return; +				} +			}		 -			if (!loadShadersDeferred()) -			{ +			if (loaded && !loadShadersDeferred()) +			{ //everything else succeeded but deferred failed, disable deferred and try again  				gSavedSettings.setBOOL("RenderDeferred", FALSE);  				reentrance = false;  				setShaders(); @@ -600,7 +657,9 @@ void LLViewerShaderMgr::setShaders()  void LLViewerShaderMgr::unloadShaders()  {  	gOcclusionProgram.unload(); +	gOcclusionCubeProgram.unload();  	gDebugProgram.unload(); +	gClipProgram.unload();  	gAlphaMaskProgram.unload();  	gUIProgram.unload();  	gCustomAlphaProgram.unload(); @@ -692,6 +751,12 @@ void LLViewerShaderMgr::unloadShaders()  	gDeferredSkinnedBumpProgram.unload();  	gDeferredSkinnedAlphaProgram.unload(); +	gTransformPositionProgram.unload(); +	gTransformTexCoordProgram.unload(); +	gTransformNormalProgram.unload(); +	gTransformColorProgram.unload(); +	gTransformBinormalProgram.unload(); +  	mVertexShaderLevel[SHADER_LIGHTING] = 0;  	mVertexShaderLevel[SHADER_OBJECT] = 0;  	mVertexShaderLevel[SHADER_AVATAR] = 0; @@ -700,6 +765,7 @@ void LLViewerShaderMgr::unloadShaders()  	mVertexShaderLevel[SHADER_INTERFACE] = 0;  	mVertexShaderLevel[SHADER_EFFECT] = 0;  	mVertexShaderLevel[SHADER_WINDLIGHT] = 0; +	mVertexShaderLevel[SHADER_TRANSFORM] = 0;  	gPipeline.mVertexShadersLoaded = 0;  } @@ -828,7 +894,7 @@ BOOL LLViewerShaderMgr::loadShadersEnvironment()  	if (mVertexShaderLevel[SHADER_ENVIRONMENT] == 0)  	{  		gTerrainProgram.unload(); -		return FALSE; +		return TRUE;  	}  	if (success) @@ -868,7 +934,7 @@ BOOL LLViewerShaderMgr::loadShadersWater()  		gWaterProgram.unload();  		gUnderWaterProgram.unload();  		gTerrainWaterProgram.unload(); -		return FALSE; +		return TRUE;  	}  	if (success) @@ -953,7 +1019,7 @@ BOOL LLViewerShaderMgr::loadShadersEffects()  		gGlowExtractProgram.unload();  		gPostColorFilterProgram.unload();	  		gPostNightVisionProgram.unload(); -		return FALSE; +		return TRUE;  	}  	if (success) @@ -1013,6 +1079,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  		gDeferredBlurLightProgram.unload();  		gDeferredSoftenProgram.unload();  		gDeferredShadowProgram.unload(); +		gDeferredShadowCubeProgram.unload();  		gDeferredShadowAlphaMaskProgram.unload();  		gDeferredAvatarShadowProgram.unload();  		gDeferredAttachmentShadowProgram.unload(); @@ -1200,7 +1267,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  		gDeferredSpotLightProgram.mName = "Deferred SpotLight Shader";  		gDeferredSpotLightProgram.mShaderFiles.clear();  		gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); -		gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); +		gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/spotLightF.glsl", GL_FRAGMENT_SHADER_ARB));  		gDeferredSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];  		success = gDeferredSpotLightProgram.createShader(NULL, NULL);  	} @@ -1209,7 +1276,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  	{  		gDeferredMultiSpotLightProgram.mName = "Deferred MultiSpotLight Shader";  		gDeferredMultiSpotLightProgram.mShaderFiles.clear(); -		gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); +		gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB));  		gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB));  		gDeferredMultiSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];  		success = gDeferredMultiSpotLightProgram.createShader(NULL, NULL); @@ -1368,6 +1435,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  	if (success)  	{ +		gDeferredShadowCubeProgram.mName = "Deferred Shadow Cube Shader"; +		gDeferredShadowCubeProgram.mShaderFiles.clear(); +		gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowCubeV.glsl", GL_VERTEX_SHADER_ARB)); +		gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER_ARB)); +		gDeferredShadowCubeProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; +		success = gDeferredShadowCubeProgram.createShader(NULL, NULL); +	} + +	if (success) +	{  		gDeferredShadowAlphaMaskProgram.mName = "Deferred Shadow Alpha Mask Shader";  		gDeferredShadowAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;  		gDeferredShadowAlphaMaskProgram.mShaderFiles.clear(); @@ -2410,7 +2487,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()  		gAvatarWaterProgram.unload();  		gAvatarEyeballProgram.unload();  		gAvatarPickProgram.unload(); -		return FALSE; +		return TRUE;  	}  	if (success) @@ -2504,7 +2581,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()  	if (mVertexShaderLevel[SHADER_INTERFACE] == 0)  	{  		gHighlightProgram.unload(); -		return FALSE; +		return TRUE;  	}  	if (success) @@ -2647,6 +2724,16 @@ BOOL LLViewerShaderMgr::loadShadersInterface()  	if (success)  	{ +		gOcclusionCubeProgram.mName = "Occlusion Cube Shader"; +		gOcclusionCubeProgram.mShaderFiles.clear(); +		gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionCubeV.glsl", GL_VERTEX_SHADER_ARB)); +		gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB)); +		gOcclusionCubeProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; +		success = gOcclusionCubeProgram.createShader(NULL, NULL); +	} + +	if (success) +	{  		gDebugProgram.mName = "Debug Shader";  		gDebugProgram.mShaderFiles.clear();  		gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugV.glsl", GL_VERTEX_SHADER_ARB)); @@ -2657,6 +2744,16 @@ BOOL LLViewerShaderMgr::loadShadersInterface()  	if (success)  	{ +		gClipProgram.mName = "Clip Shader"; +		gClipProgram.mShaderFiles.clear(); +		gClipProgram.mShaderFiles.push_back(make_pair("interface/clipV.glsl", GL_VERTEX_SHADER_ARB)); +		gClipProgram.mShaderFiles.push_back(make_pair("interface/clipF.glsl", GL_FRAGMENT_SHADER_ARB)); +		gClipProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; +		success = gClipProgram.createShader(NULL, NULL); +	} + +	if (success) +	{  		gAlphaMaskProgram.mName = "Alpha Mask Shader";  		gAlphaMaskProgram.mShaderFiles.clear();  		gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskV.glsl", GL_VERTEX_SHADER_ARB)); @@ -2682,7 +2779,7 @@ BOOL LLViewerShaderMgr::loadShadersWindLight()  	{  		gWLSkyProgram.unload();  		gWLCloudProgram.unload(); -		return FALSE; +		return TRUE;  	}  	if (success) @@ -2712,6 +2809,95 @@ BOOL LLViewerShaderMgr::loadShadersWindLight()  	return success;  } +BOOL LLViewerShaderMgr::loadTransformShaders() +{ +	BOOL success = TRUE; +	 +	if (mVertexShaderLevel[SHADER_TRANSFORM] < 1) +	{ +		gTransformPositionProgram.unload(); +		gTransformTexCoordProgram.unload(); +		gTransformNormalProgram.unload(); +		gTransformColorProgram.unload(); +		gTransformBinormalProgram.unload(); +		return TRUE; +	} + +	if (success) +	{ +		gTransformPositionProgram.mName = "Position Transform Shader"; +		gTransformPositionProgram.mShaderFiles.clear(); +		gTransformPositionProgram.mShaderFiles.push_back(make_pair("transform/positionV.glsl", GL_VERTEX_SHADER_ARB)); +		gTransformPositionProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + +		const char* varyings[] = { +			"position_out", +			"texture_index_out", +		}; +	 +		success = gTransformPositionProgram.createShader(NULL, NULL, 2, varyings); +	} + +	if (success) +	{ +		gTransformTexCoordProgram.mName = "TexCoord Transform Shader"; +		gTransformTexCoordProgram.mShaderFiles.clear(); +		gTransformTexCoordProgram.mShaderFiles.push_back(make_pair("transform/texcoordV.glsl", GL_VERTEX_SHADER_ARB)); +		gTransformTexCoordProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + +		const char* varyings[] = { +			"texcoord_out", +		}; +	 +		success = gTransformTexCoordProgram.createShader(NULL, NULL, 1, varyings); +	} + +	if (success) +	{ +		gTransformNormalProgram.mName = "Normal Transform Shader"; +		gTransformNormalProgram.mShaderFiles.clear(); +		gTransformNormalProgram.mShaderFiles.push_back(make_pair("transform/normalV.glsl", GL_VERTEX_SHADER_ARB)); +		gTransformNormalProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + +		const char* varyings[] = { +			"normal_out", +		}; +	 +		success = gTransformNormalProgram.createShader(NULL, NULL, 1, varyings); +	} + +	if (success) +	{ +		gTransformColorProgram.mName = "Color Transform Shader"; +		gTransformColorProgram.mShaderFiles.clear(); +		gTransformColorProgram.mShaderFiles.push_back(make_pair("transform/colorV.glsl", GL_VERTEX_SHADER_ARB)); +		gTransformColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + +		const char* varyings[] = { +			"color_out", +		}; +	 +		success = gTransformColorProgram.createShader(NULL, NULL, 1, varyings); +	} + +	if (success) +	{ +		gTransformBinormalProgram.mName = "Binormal Transform Shader"; +		gTransformBinormalProgram.mShaderFiles.clear(); +		gTransformBinormalProgram.mShaderFiles.push_back(make_pair("transform/binormalV.glsl", GL_VERTEX_SHADER_ARB)); +		gTransformBinormalProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + +		const char* varyings[] = { +			"binormal_out", +		}; +	 +		success = gTransformBinormalProgram.createShader(NULL, NULL, 1, varyings); +	} + +	 +	return success; +} +  std::string LLViewerShaderMgr::getShaderDirPrefix(void)  {  	return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/class"); diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 95eb551bf1..8f7ff8dd2f 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -54,6 +54,7 @@ public:  	BOOL loadShadersWater();  	BOOL loadShadersInterface();  	BOOL loadShadersWindLight(); +	BOOL loadTransformShaders();  	std::vector<S32> mVertexShaderLevel;  	S32	mMaxAvatarShaderLevel; @@ -69,6 +70,7 @@ public:  		SHADER_WINDLIGHT,  		SHADER_WATER,  		SHADER_DEFERRED, +		SHADER_TRANSFORM,  		SHADER_COUNT  	}; @@ -209,13 +211,24 @@ inline bool operator != (LLViewerShaderMgr::shader_iter const & a, LLViewerShade  extern LLVector4			gShinyOrigin; +//transform shaders +extern LLGLSLShader			gTransformPositionProgram; +extern LLGLSLShader			gTransformTexCoordProgram; +extern LLGLSLShader			gTransformNormalProgram; +extern LLGLSLShader			gTransformColorProgram; +extern LLGLSLShader			gTransformBinormalProgram; + + +  //utility shaders  extern LLGLSLShader			gOcclusionProgram; +extern LLGLSLShader			gOcclusionCubeProgram;  extern LLGLSLShader			gCustomAlphaProgram;  extern LLGLSLShader			gGlowCombineProgram;  extern LLGLSLShader			gSplatTextureRectProgram;  extern LLGLSLShader			gGlowCombineFXAAProgram;  extern LLGLSLShader			gDebugProgram; +extern LLGLSLShader			gClipProgram;  extern LLGLSLShader			gAlphaMaskProgram;  //output tex0[tc0] + tex1[tc1] @@ -328,6 +341,7 @@ extern LLGLSLShader			gDeferredBlurLightProgram;  extern LLGLSLShader			gDeferredAvatarProgram;  extern LLGLSLShader			gDeferredSoftenProgram;  extern LLGLSLShader			gDeferredShadowProgram; +extern LLGLSLShader			gDeferredShadowCubeProgram;  extern LLGLSLShader			gDeferredShadowAlphaMaskProgram;  extern LLGLSLShader			gDeferredPostProgram;  extern LLGLSLShader			gDeferredCoFProgram; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 497e95c5e3..28f4ec72f3 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -789,6 +789,24 @@ void send_stats()  	system["gpu_class"] = (S32)LLFeatureManager::getInstance()->getGPUClass();  	system["gpu_vendor"] = gGLManager.mGLVendorShort;  	system["gpu_version"] = gGLManager.mDriverVersionVendorString; +	system["opengl_version"] = gGLManager.mGLVersionString; + +	S32 shader_level = 0; +	if (LLPipeline::sRenderDeferred) +	{ +		shader_level = 3; +	} +	else if (gPipeline.canUseWindLightShadersOnObjects()) +	{ +		shader_level = 2; +	} +	else if (gPipeline.canUseVertexShaders()) +	{ +		shader_level = 1; +	} + + +	system["shader_level"] = shader_level;  	LLSD &download = body["downloads"]; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index d844aeb12a..7f638a24bf 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1398,10 +1398,10 @@ void LLViewerFetchedTexture::dump()  // ONLY called from LLViewerFetchedTextureList  void LLViewerFetchedTexture::destroyTexture()   { -	if(LLImageGL::sGlobalTextureMemoryInBytes < sMaxDesiredTextureMemInBytes)//not ready to release unused memory. -	{ -		return ; -	} +	//if(LLImageGL::sGlobalTextureMemoryInBytes < sMaxDesiredTextureMemInBytes)//not ready to release unused memory. +	//{ +	//	return ; +	//}  	if (mNeedsCreateTexture)//return if in the process of generating a new texture.  	{  		return ; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 528e0080b7..9a6c0569a9 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -705,7 +705,7 @@ void LLViewerTextureList::updateImagesDecodePriorities()  			// Flush formatted images using a lazy flush  			//  			const F32 LAZY_FLUSH_TIMEOUT = 30.f; // stop decoding -			const F32 MAX_INACTIVE_TIME  = 50.f; // actually delete +			const F32 MAX_INACTIVE_TIME  = 20.f; // actually delete  			S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference  			S32 num_refs = imagep->getNumRefs(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index fc6ef170c8..7afb135470 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -175,6 +175,7 @@  #include "llviewershadermgr.h"  #include "llviewerstats.h"  #include "llvoavatarself.h" +#include "llvopartgroup.h"  #include "llvovolume.h"  #include "llworld.h"  #include "llworldmapview.h" @@ -613,7 +614,7 @@ public:  				addText(xpos, ypos, llformat("%d/%d Mesh HTTP Requests/Retries", LLMeshRepository::sHTTPRequestCount,  					LLMeshRepository::sHTTPRetryCount));  				ypos += y_inc; - +				  				addText(xpos, ypos, llformat("%d/%d Mesh LOD Pending/Processing", LLMeshRepository::sLODPending, LLMeshRepository::sLODProcessing));  				ypos += y_inc; @@ -1970,12 +1971,12 @@ void LLViewerWindow::shutdownViews()  		gMorphView->setVisible(FALSE);  	}  	llinfos << "Global views cleaned." << llendl ; -	 +  	// DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open  	// will crump with LL_ERRS.  	LLModalDialog::shutdownModals();  	llinfos << "LLModalDialog shut down." << llendl;  - +	  	// destroy the nav bar, not currently part of gViewerWindow  	// *TODO: Make LLNavigationBar part of gViewerWindow  	if (LLNavigationBar::instanceExists()) @@ -1983,17 +1984,17 @@ void LLViewerWindow::shutdownViews()  		delete LLNavigationBar::getInstance();  	}  	llinfos << "LLNavigationBar destroyed." << llendl ; -	 +  	// destroy menus after instantiating navbar above, as it needs  	// access to gMenuHolder  	cleanup_menus();  	llinfos << "menus destroyed." << llendl ; -	 +  	// Delete all child views.  	delete mRootView;  	mRootView = NULL;  	llinfos << "RootView deleted." << llendl ; -	 +  	// Automatically deleted as children of mRootView.  Fix the globals.  	gStatusBar = NULL;  	gIMMgr = NULL; @@ -4657,6 +4658,8 @@ void LLViewerWindow::stopGL(BOOL save_state)  		LLVOAvatar::destroyGL();  		stop_glerror(); +		LLVOPartGroup::destroyGL(); +  		LLViewerDynamicTexture::destroyGL();  		stop_glerror(); @@ -4710,7 +4713,8 @@ void LLViewerWindow::restoreGL(const std::string& progress_message)  		gBumpImageList.restoreGL();  		LLViewerDynamicTexture::restoreGL();  		LLVOAvatar::restoreGL(); -		 +		LLVOPartGroup::restoreGL(); +  		gResizeScreenTexture = TRUE;  		gWindowResized = TRUE; @@ -5193,8 +5197,10 @@ void LLPickInfo::getSurfaceInfo()  			if (objectp->mDrawable.notNull() && mObjectFace > -1)  			{  				LLFace* facep = objectp->mDrawable->getFace(mObjectFace); - -				mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal); +				if (facep) +				{ +					mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal); +				}  			}  			// and XY coords: diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index eada77156e..33dc12c473 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -961,7 +961,7 @@ void LLVOAvatar::deleteLayerSetCaches(bool clearAll)  		}  		if (mBakedTextureDatas[i].mMaskTexName)  		{ -			glDeleteTextures(1, (GLuint*)&(mBakedTextureDatas[i].mMaskTexName)); +			LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, 0, -1, 1, (GLuint*)&(mBakedTextureDatas[i].mMaskTexName));  			mBakedTextureDatas[i].mMaskTexName = 0 ;  		}  	} @@ -2094,11 +2094,17 @@ void LLVOAvatar::releaseMeshData()  	if (mDrawable.notNull())  	{  		LLFace* facep = mDrawable->getFace(0); -		facep->setSize(0, 0); -		for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++) +		if (facep)  		{ -			facep = mDrawable->getFace(i);  			facep->setSize(0, 0); +			for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++) +			{ +				facep = mDrawable->getFace(i); +				if (facep) +				{ +					facep->setSize(0, 0); +				} +			}  		}  	} @@ -2183,15 +2189,20 @@ void LLVOAvatar::updateMeshData()  				part_index-- ;  			} -			LLFace* facep ; +			LLFace* facep = NULL;  			if(f_num < mDrawable->getNumFaces())   			{  				facep = mDrawable->getFace(f_num);  			}  			else  			{ -				facep = mDrawable->addFace(mDrawable->getFace(0)->getPool(), mDrawable->getFace(0)->getTexture()) ; +				facep = mDrawable->getFace(0); +				if (facep) +				{ +					facep = mDrawable->addFace(facep->getPool(), facep->getTexture()) ; +				}  			} +			if (!facep) continue;  			// resize immediately  			facep->setSize(num_vertices, num_indices); @@ -4236,10 +4247,14 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)  			mNeedsSkin = FALSE;  			mLastSkinTime = gFrameTimeSeconds; -			LLVertexBuffer* vb = mDrawable->getFace(0)->getVertexBuffer(); -			if (vb) +			LLFace * face = mDrawable->getFace(0); +			if (face)  			{ -				vb->flush(); +				LLVertexBuffer* vb = face->getVertexBuffer(); +				if (vb) +				{ +					vb->flush(); +				}  			}  		}  	} @@ -7492,7 +7507,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture  			}  			U32 gl_name; -			LLImageGL::generateTextures(1, &gl_name ); +			LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_ALPHA8, 1, &gl_name );  			stop_glerror();  			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, gl_name); @@ -7529,7 +7544,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture  						maskData->mLastDiscardLevel = discard_level;  						if (self->mBakedTextureDatas[baked_index].mMaskTexName)  						{ -							LLImageGL::deleteTextures(1, &(self->mBakedTextureDatas[baked_index].mMaskTexName)); +							LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, 0, -1, 1, &(self->mBakedTextureDatas[baked_index].mMaskTexName));  						}  						self->mBakedTextureDatas[baked_index].mMaskTexName = gl_name;  						found_texture_id = true; @@ -8395,7 +8410,7 @@ BOOL LLVOAvatar::updateLOD()  	BOOL res = updateJointLODs();  	LLFace* facep = mDrawable->getFace(0); -	if (!facep->getVertexBuffer()) +	if (!facep || !facep->getVertexBuffer())  	{  		dirtyMesh(2);  	} diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index d2609e5587..98f7245f8d 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2751,7 +2751,7 @@ void LLVOAvatarSelf::deleteScratchTextures()  		 namep;   		 namep = sScratchTexNames.getNextData() )  	{ -		LLImageGL::deleteTextures(1, (U32 *)namep ); +		LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, 0, -1, 1, (U32 *)namep );  		stop_glerror();  	} diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 8a79d564d3..44968342bf 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -34,6 +34,7 @@  #include "llagentcamera.h"  #include "llnotificationsutil.h"  #include "lldrawable.h" +#include "lldrawpoolalpha.h"  #include "llface.h"  #include "llsky.h"  #include "llsurface.h" @@ -380,8 +381,10 @@ BOOL LLVOGrass::updateLOD()  		{  			mNumBlades <<= 1;  		} - -		face->setSize(mNumBlades*8, mNumBlades*12); +		if (face) +		{ +			face->setSize(mNumBlades*8, mNumBlades*12); +		}  		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);  	}  	else if (num_blades <= (mNumBlades >> 1)) @@ -391,7 +394,10 @@ BOOL LLVOGrass::updateLOD()  			mNumBlades >>=1;  		} -		face->setSize(mNumBlades*8, mNumBlades*12); +		if (face) +		{ +			face->setSize(mNumBlades*8, mNumBlades*12); +		}  		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);  		return TRUE;  	} @@ -449,14 +455,16 @@ void LLVOGrass::plantBlades()  	}  	LLFace *face = mDrawable->getFace(0); +	if (face) +	{ +		face->setTexture(getTEImage(0)); +		face->setState(LLFace::GLOBAL); +		face->setSize(mNumBlades * 8, mNumBlades * 12); +		face->setVertexBuffer(NULL); +		face->setTEOffset(0); +		face->mCenterLocal = mPosition + mRegionp->getOriginAgent(); +	} -	face->setTexture(getTEImage(0)); -	face->setState(LLFace::GLOBAL); -	face->setSize(mNumBlades * 8, mNumBlades * 12); -	face->setVertexBuffer(NULL); -	face->setTEOffset(0); -	face->mCenterLocal = mPosition + mRegionp->getOriginAgent(); -	  	mDepth = (face->mCenterLocal - LLViewerCamera::getInstance()->getOrigin())*LLViewerCamera::getInstance()->getAtAxis();  	mDrawable->setPosition(face->mCenterLocal);  	mDrawable->movePartition(); @@ -486,6 +494,8 @@ void LLVOGrass::getGeometry(S32 idx,  	LLColor4U color(255,255,255,255);  	LLFace *face = mDrawable->getFace(idx); +	if (!face) +		return;  	F32 width  = sSpeciesTable[mSpecies]->mBladeSizeX;  	F32 height = sSpeciesTable[mSpecies]->mBladeSizeY; @@ -594,6 +604,7 @@ U32 LLVOGrass::getPartitionType() const  }  LLGrassPartition::LLGrassPartition() +: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB)  {  	mDrawableType = LLPipeline::RENDER_TYPE_GRASS;  	mPartitionType = LLViewerRegion::PARTITION_GRASS; @@ -604,6 +615,143 @@ LLGrassPartition::LLGrassPartition()  	mBufferUsage = GL_DYNAMIC_DRAW_ARB;  } +void LLGrassPartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count) +{ +	group->mBufferUsage = mBufferUsage; + +	mFaceList.clear(); + +	LLViewerCamera* camera = LLViewerCamera::getInstance(); +	for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) +	{ +		LLDrawable* drawablep = *i; +		 +		if (drawablep->isDead()) +		{ +			continue; +		} + +		LLAlphaObject* obj = (LLAlphaObject*) drawablep->getVObj().get(); +		obj->mDepth = 0.f; +		 +		if (drawablep->isAnimating()) +		{ +			group->mBufferUsage = GL_STREAM_DRAW_ARB; +		} + +		U32 count = 0; +		for (S32 j = 0; j < drawablep->getNumFaces(); ++j) +		{ +			drawablep->updateFaceSize(j); + +			LLFace* facep = drawablep->getFace(j); +			if ( !facep || !facep->hasGeometry()) +			{ +				continue; +			} +			 +			if ((facep->getGeomCount() + vertex_count) <= 65536) +			{ +				count++; +				facep->mDistance = (facep->mCenterLocal - camera->getOrigin()) * camera->getAtAxis(); +				obj->mDepth += facep->mDistance; +			 +				mFaceList.push_back(facep); +				vertex_count += facep->getGeomCount(); +				index_count += facep->getIndicesCount(); +				llassert(facep->getIndicesCount() < 65536); +			} +			else +			{ +				facep->clearVertexBuffer(); +			} +		} +		 +		obj->mDepth /= count; +	} +} + +static LLFastTimer::DeclareTimer FTM_REBUILD_GRASS_VB("Grass VB"); + +void LLGrassPartition::getGeometry(LLSpatialGroup* group) +{ +	LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); +	LLFastTimer ftm(FTM_REBUILD_GRASS_VB); + +	std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); + +	U32 index_count = 0; +	U32 vertex_count = 0; + +	group->clearDrawMap(); + +	LLVertexBuffer* buffer = group->mVertexBuffer; + +	LLStrider<U16> indicesp; +	LLStrider<LLVector4a> verticesp; +	LLStrider<LLVector3> normalsp; +	LLStrider<LLVector2> texcoordsp; +	LLStrider<LLColor4U> colorsp; + +	buffer->getVertexStrider(verticesp); +	buffer->getNormalStrider(normalsp); +	buffer->getColorStrider(colorsp); +	buffer->getTexCoord0Strider(texcoordsp); +	buffer->getIndexStrider(indicesp); + +	LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass];	 + +	for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) +	{ +		LLFace* facep = *i; +		LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); +		facep->setGeomIndex(vertex_count); +		facep->setIndicesIndex(index_count); +		facep->setVertexBuffer(buffer); +		facep->setPoolType(LLDrawPool::POOL_ALPHA); +		object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); +		 +		vertex_count += facep->getGeomCount(); +		index_count += facep->getIndicesCount(); + +		S32 idx = draw_vec.size()-1; + +		BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); +		F32 vsize = facep->getVirtualSize(); + +		if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && +			draw_vec[idx]->mTexture == facep->getTexture() && +			(U16) (draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount()) <= (U32) gGLManager.mGLMaxVertexRange && +			//draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && +			draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() < 4096 && +			draw_vec[idx]->mFullbright == fullbright) +		{ +			draw_vec[idx]->mCount += facep->getIndicesCount(); +			draw_vec[idx]->mEnd += facep->getGeomCount(); +			draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); +		} +		else +		{ +			U32 start = facep->getGeomIndex(); +			U32 end = start + facep->getGeomCount()-1; +			U32 offset = facep->getIndicesStart(); +			U32 count = facep->getIndicesCount(); +			LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(),  +				//facep->getTexture(), +				buffer, fullbright);  +			info->mExtents[0] = group->mObjectExtents[0]; +			info->mExtents[1] = group->mObjectExtents[1]; +			info->mVSize = vsize; +			draw_vec.push_back(info); +			//for alpha sorting +			facep->setDrawInfo(info); +		} +	} + +	buffer->flush(); +	mFaceList.clear(); +} +  // virtual  void LLVOGrass::updateDrawable(BOOL force_damped)  { diff --git a/indra/newview/llvoground.cpp b/indra/newview/llvoground.cpp index 0060f81ab5..6da54435e3 100644 --- a/indra/newview/llvoground.cpp +++ b/indra/newview/llvoground.cpp @@ -82,6 +82,7 @@ LLDrawable *LLVOGround::createDrawable(LLPipeline *pipeline)  	return mDrawable;  } +// TO DO - this always returns TRUE,   BOOL LLVOGround::updateGeometry(LLDrawable *drawable)  {  	LLStrider<LLVector3> verticesp; @@ -96,6 +97,8 @@ BOOL LLVOGround::updateGeometry(LLDrawable *drawable)  	if (drawable->getNumFaces() < 1)  		drawable->addFace(poolp, NULL);  	face = drawable->getFace(0);  +	if (!face) +		return TRUE;  	if (!face->getVertexBuffer())  	{ diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 5c10a80b07..e21358b65a 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -48,6 +48,117 @@ const F32 MAX_PART_LIFETIME = 120.f;  extern U64 gFrameTime; +LLPointer<LLVertexBuffer> LLVOPartGroup::sVB = NULL; +S32 LLVOPartGroup::sVBSlotFree[]; +S32* LLVOPartGroup::sVBSlotCursor = NULL; + +//static +void LLVOPartGroup::restoreGL() +{ +	for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i) +	{ +		sVBSlotFree[i] = i; +	} + +	sVBSlotCursor = sVBSlotFree; + +	sVB = new LLVertexBuffer(VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); +	U32 count = LL_MAX_PARTICLE_COUNT; +	sVB->allocateBuffer(count*4, count*6, true); + +	//indices and texcoords are always the same, set once +	LLStrider<U16> indicesp; + +	LLStrider<LLVector4a> verticesp; + +	sVB->getIndexStrider(indicesp); +	sVB->getVertexStrider(verticesp); + +	LLVector4a v; +	v.set(0,0,0,0); + +	 +	U16 vert_offset = 0; + +	for (U32 i = 0; i < LL_MAX_PARTICLE_COUNT; i++) +	{ +		*indicesp++ = vert_offset + 0; +		*indicesp++ = vert_offset + 1; +		*indicesp++ = vert_offset + 2; + +		*indicesp++ = vert_offset + 1; +		*indicesp++ = vert_offset + 3; +		*indicesp++ = vert_offset + 2; + +		*verticesp++ = v; + +		vert_offset += 4; +	} + +	LLStrider<LLVector2> texcoordsp; +	sVB->getTexCoord0Strider(texcoordsp); + +	for (U32 i = 0; i < LL_MAX_PARTICLE_COUNT; i++) +	{ +		*texcoordsp++ = LLVector2(0.f, 1.f); +		*texcoordsp++ = LLVector2(0.f, 0.f); +		*texcoordsp++ = LLVector2(1.f, 1.f); +		*texcoordsp++ = LLVector2(1.f, 0.f); +	} + +	sVB->flush(); + +} + +//static +void LLVOPartGroup::destroyGL() +{ +	sVB = NULL; +} + +//static +S32 LLVOPartGroup::findAvailableVBSlot() +{ +	if (sVBSlotCursor >= sVBSlotFree+LL_MAX_PARTICLE_COUNT) +	{ //no more available slots +		return -1; +	} + +	S32 ret = *sVBSlotCursor; +	sVBSlotCursor++; + +	return ret; +} + +bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end) +{ +	while (start < end) +	{ +		if (*start == idx) +		{ //not allocated (in free list) +			return false; +		} +		++start; +	} + +	//allocated (not in free list) +	return true; +} + +//static +void LLVOPartGroup::freeVBSlot(S32 idx) +{ +	llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0); +	llassert(sVBSlotCursor > sVBSlotFree); +	llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT)); + +	if (sVBSlotCursor > sVBSlotFree) +	{ +		sVBSlotCursor--; +		*sVBSlotCursor = idx; +	} +} +  LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)  	:	LLAlphaObject(id, pcode, regionp),  		mViewerPartGroupp(NULL) @@ -62,7 +173,6 @@ LLVOPartGroup::~LLVOPartGroup()  {  } -  BOOL LLVOPartGroup::isActive() const  {  	return FALSE; @@ -287,9 +397,6 @@ void LLVOPartGroup::getGeometry(S32 idx,  	const LLViewerPart &part = *((LLViewerPart*) (mViewerPartGroupp->mParticles[idx])); -	U32 vert_offset = mDrawable->getFace(idx)->getGeomIndex(); - -	  	LLVector4a part_pos_agent;  	part_pos_agent.load3(part.mPosAgent.mV);  	LLVector4a camera_agent; @@ -361,33 +468,18 @@ void LLVOPartGroup::getGeometry(S32 idx,  	verticesp->setAdd(ppamu, right);  	(*verticesp++).getF32ptr()[3] = 0.f; -	//*verticesp++ = part_pos_agent + up - right; -	//*verticesp++ = part_pos_agent - up - right; -	//*verticesp++ = part_pos_agent + up + right; -	//*verticesp++ = part_pos_agent - up + right; -  	*colorsp++ = part.mColor;  	*colorsp++ = part.mColor;  	*colorsp++ = part.mColor;  	*colorsp++ = part.mColor; -	*texcoordsp++ = LLVector2(0.f, 1.f); -	*texcoordsp++ = LLVector2(0.f, 0.f); -	*texcoordsp++ = LLVector2(1.f, 1.f); -	*texcoordsp++ = LLVector2(1.f, 0.f); - -	*normalsp++   = normal; -	*normalsp++   = normal; -	*normalsp++   = normal; -	*normalsp++   = normal; - -	*indicesp++ = vert_offset + 0; -	*indicesp++ = vert_offset + 1; -	*indicesp++ = vert_offset + 2; - -	*indicesp++ = vert_offset + 1; -	*indicesp++ = vert_offset + 3; -	*indicesp++ = vert_offset + 2; +	if (!(part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK)) +	{ //not fullbright, needs normal +		*normalsp++   = normal; +		*normalsp++   = normal; +		*normalsp++   = normal; +		*normalsp++   = normal; +	}  }  U32 LLVOPartGroup::getPartitionType() const @@ -412,6 +504,49 @@ LLHUDParticlePartition::LLHUDParticlePartition() :  	mPartitionType = LLViewerRegion::PARTITION_HUD_PARTICLE;  } +static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_VBO("Particle VBO"); + +void LLParticlePartition::rebuildGeom(LLSpatialGroup* group) +{ +	if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY)) +	{ +		return; +	} + +	if (group->changeLOD()) +	{ +		group->mLastUpdateDistance = group->mDistance; +		group->mLastUpdateViewAngle = group->mViewAngle; +	} +	 +	LLFastTimer ftm(FTM_REBUILD_PARTICLE_VBO);	 + +	group->clearDrawMap(); +	 +	//get geometry count +	U32 index_count = 0; +	U32 vertex_count = 0; + +	addGeometryCount(group, vertex_count, index_count); +	 + +	if (vertex_count > 0 && index_count > 0) +	{  +		group->mBuilt = 1.f; +		//use one vertex buffer for all groups +		group->mVertexBuffer = LLVOPartGroup::sVB; +		getGeometry(group); +	} +	else +	{ +		group->mVertexBuffer = NULL; +		group->mBufferMap.clear(); +	} + +	group->mLastUpdateTime = gFrameTimeSeconds; +	group->clearState(LLSpatialGroup::GEOM_DIRTY); +} +  void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count)  {  	group->mBufferUsage = mBufferUsage; @@ -431,11 +566,6 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co  		LLAlphaObject* obj = (LLAlphaObject*) drawablep->getVObj().get();  		obj->mDepth = 0.f; -		if (drawablep->isAnimating()) -		{ -			group->mBufferUsage = GL_STREAM_DRAW_ARB; -		} -  		U32 count = 0;  		for (S32 j = 0; j < drawablep->getNumFaces(); ++j)  		{ @@ -447,13 +577,14 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co  				continue;  			} +			vertex_count += facep->getGeomCount(); +			index_count += facep->getIndicesCount(); +  			count++;  			facep->mDistance = (facep->mCenterLocal - camera->getOrigin()) * camera->getAtAxis();  			obj->mDepth += facep->mDistance;  			mFaceList.push_back(facep); -			vertex_count += facep->getGeomCount(); -			index_count += facep->getIndicesCount();  			llassert(facep->getIndicesCount() < 65536);  		} @@ -461,15 +592,13 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co  	}  } -static LLFastTimer::DeclareTimer FTM_REBUILD_GRASS_VB("Grass VB"); -static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_VB("Particle VB"); + +static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_GEOM("Particle Geom");  void LLParticlePartition::getGeometry(LLSpatialGroup* group)  {  	LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); -	LLFastTimer ftm(mDrawableType == LLPipeline::RENDER_TYPE_GRASS ? -					FTM_REBUILD_GRASS_VB : -					FTM_REBUILD_PARTICLE_VB); +	LLFastTimer ftm(FTM_REBUILD_PARTICLE_GEOM);  	std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); @@ -489,21 +618,44 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  	buffer->getVertexStrider(verticesp);  	buffer->getNormalStrider(normalsp);  	buffer->getColorStrider(colorsp); -	buffer->getTexCoord0Strider(texcoordsp); -	buffer->getIndexStrider(indicesp); - +	  	LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass];	  	for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i)  	{  		LLFace* facep = *i;  		LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); -		facep->setGeomIndex(vertex_count); -		facep->setIndicesIndex(index_count); -		facep->setVertexBuffer(buffer); -		facep->setPoolType(LLDrawPool::POOL_ALPHA); -		object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); + +		if (facep->getIndicesStart() == 0xFFFFFFFF) +		{ //set the indices of this face +			S32 idx = LLVOPartGroup::findAvailableVBSlot(); +			if (idx >= 0) +			{ +				facep->setGeomIndex(idx*4); +				facep->setIndicesIndex(idx*6); +				facep->setVertexBuffer(LLVOPartGroup::sVB); +				facep->setPoolType(LLDrawPool::POOL_ALPHA); +			} +			else +			{ +				continue; //out of space in particle buffer +			}		 +		} + +		S32 geom_idx = (S32) facep->getGeomIndex(); + +		LLStrider<U16> cur_idx = indicesp + facep->getIndicesStart(); +		LLStrider<LLVector4a> cur_vert = verticesp + geom_idx; +		LLStrider<LLVector3> cur_norm = normalsp + geom_idx; +		LLStrider<LLVector2> cur_tc = texcoordsp + geom_idx; +		LLStrider<LLColor4U> cur_col = colorsp + geom_idx; + +		object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc, cur_col, cur_idx); +		llassert(facep->getGeomCount() == 4); +		llassert(facep->getIndicesCount() == 6); + +  		vertex_count += facep->getGeomCount();  		index_count += facep->getIndicesCount(); @@ -512,18 +664,31 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  		BOOL fullbright = facep->isState(LLFace::FULLBRIGHT);  		F32 vsize = facep->getVirtualSize(); -		if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && +		bool batched = false; +	 +		if (idx >= 0 &&  			draw_vec[idx]->mTexture == facep->getTexture() && -			(U16) (draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount()) <= (U32) gGLManager.mGLMaxVertexRange && -			//draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && -			draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() < 4096 &&  			draw_vec[idx]->mFullbright == fullbright)  		{ -			draw_vec[idx]->mCount += facep->getIndicesCount(); -			draw_vec[idx]->mEnd += facep->getGeomCount(); -			draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); +			if (draw_vec[idx]->mEnd == facep->getGeomIndex()-1) +			{ +				batched = true; +				draw_vec[idx]->mCount += facep->getIndicesCount(); +				draw_vec[idx]->mEnd += facep->getGeomCount(); +				draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); +			} +			else if (draw_vec[idx]->mStart == facep->getGeomIndex()+facep->getGeomCount()+1) +			{ +				batched = true; +				draw_vec[idx]->mCount += facep->getIndicesCount(); +				draw_vec[idx]->mStart -= facep->getGeomCount(); +				draw_vec[idx]->mOffset = facep->getIndicesStart(); +				draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); +			}  		} -		else + + +		if (!batched)  		{  			U32 start = facep->getGeomIndex();  			U32 end = start + facep->getGeomCount()-1; @@ -541,7 +706,6 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  		}  	} -	buffer->flush();  	mFaceList.clear();  } diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index e58fed86d9..6160bceb24 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -31,18 +31,32 @@  #include "v3math.h"  #include "v3color.h"  #include "llframetimer.h" +#include "llviewerpartsim.h" +#include "llvertexbuffer.h"  class LLViewerPartGroup;  class LLVOPartGroup : public LLAlphaObject  {  public: + +	//vertex buffer for holding all particles +	static LLPointer<LLVertexBuffer> sVB; +	static S32 sVBSlotFree[LL_MAX_PARTICLE_COUNT]; +	static S32* sVBSlotCursor; + +	static void restoreGL(); +	static void destroyGL(); +	static S32 findAvailableVBSlot(); +	static void freeVBSlot(S32 idx); +  	enum  	{ -		VERTEX_DATA_MASK =	(1 << LLVertexBuffer::TYPE_VERTEX) | -							(1 << LLVertexBuffer::TYPE_NORMAL) | -							(1 << LLVertexBuffer::TYPE_TEXCOORD0) | -							(1 << LLVertexBuffer::TYPE_COLOR) +		VERTEX_DATA_MASK =	LLVertexBuffer::MAP_VERTEX | +							LLVertexBuffer::MAP_NORMAL | +							LLVertexBuffer::MAP_TEXCOORD0 | +							LLVertexBuffer::MAP_COLOR | +							LLVertexBuffer::MAP_TEXTURE_INDEX  	};  	LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index bf6158eeaf..94a3111f4c 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -296,18 +296,20 @@ void LLVOSurfacePatch::updateFaceSize(S32 idx)  	}  	LLFace* facep = mDrawable->getFace(idx); - -	S32 num_vertices = 0; -	S32 num_indices = 0; -	 -	if (mLastStride) +	if (facep)  	{ -		getGeomSizesMain(mLastStride, num_vertices, num_indices); -		getGeomSizesNorth(mLastStride, mLastNorthStride, num_vertices, num_indices); -		getGeomSizesEast(mLastStride, mLastEastStride, num_vertices, num_indices); -	} +		S32 num_vertices = 0; +		S32 num_indices = 0; +	 +		if (mLastStride) +		{ +			getGeomSizesMain(mLastStride, num_vertices, num_indices); +			getGeomSizesNorth(mLastStride, mLastNorthStride, num_vertices, num_indices); +			getGeomSizesEast(mLastStride, mLastEastStride, num_vertices, num_indices); +		} -	facep->setSize(num_vertices, num_indices);	 +		facep->setSize(num_vertices, num_indices);	 +	}  }  BOOL LLVOSurfacePatch::updateLOD() @@ -322,30 +324,32 @@ void LLVOSurfacePatch::getGeometry(LLStrider<LLVector3> &verticesp,  								LLStrider<U16> &indicesp)  {  	LLFace* facep = mDrawable->getFace(0); +	if (facep) +	{ +		U32 index_offset = facep->getGeomIndex(); -	U32 index_offset = facep->getGeomIndex(); - -	updateMainGeometry(facep,  -					verticesp, -					normalsp, -					texCoords0p, -					texCoords1p, -					indicesp, -					index_offset); -	updateNorthGeometry(facep,  -						verticesp, -						normalsp, -						texCoords0p, -						texCoords1p, -						indicesp, -						index_offset); -	updateEastGeometry(facep,  +		updateMainGeometry(facep,   						verticesp,  						normalsp,  						texCoords0p,  						texCoords1p,  						indicesp,  						index_offset); +		updateNorthGeometry(facep,  +							verticesp, +							normalsp, +							texCoords0p, +							texCoords1p, +							indicesp, +							index_offset); +		updateEastGeometry(facep,  +							verticesp, +							normalsp, +							texCoords0p, +							texCoords1p, +							indicesp, +							index_offset); +	}  }  void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, @@ -864,7 +868,11 @@ void LLVOSurfacePatch::dirtyGeom()  	if (mDrawable)  	{  		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); -		mDrawable->getFace(0)->setVertexBuffer(NULL); +		LLFace* facep = mDrawable->getFace(0); +		if (facep) +		{ +			facep->setVertexBuffer(NULL); +		}  		mDrawable->movePartition();  	}  } diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 4564207da4..3556bde9a8 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -490,11 +490,16 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)  	if(mTrunkLOD >= sMAX_NUM_TREE_LOD_LEVELS) //do not display the tree.  	{  		mReferenceBuffer = NULL ; -		mDrawable->getFace(0)->setVertexBuffer(NULL); +		LLFace * facep = drawable->getFace(0); +		if (facep) +		{ +			facep->setVertexBuffer(NULL); +		}  		return TRUE ;  	} -	if (mReferenceBuffer.isNull() || !mDrawable->getFace(0)->getVertexBuffer()) +	if (mDrawable->getFace(0) && +		(mReferenceBuffer.isNull() || !mDrawable->getFace(0)->getVertexBuffer()))  	{  		const F32 SRR3 = 0.577350269f; // sqrt(1/3)  		const F32 SRR2 = 0.707106781f; // sqrt(1/2) @@ -507,6 +512,7 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)  		S32 lod;  		LLFace *face = drawable->getFace(0); +		if (!face) return TRUE;  		face->mCenterAgent = getPositionAgent();  		face->mCenterLocal = face->mCenterAgent; @@ -879,6 +885,7 @@ void LLVOTree::updateMesh()  	calcNumVerts(vert_count, index_count, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, mBranches);  	LLFace* facep = mDrawable->getFace(0); +	if (!facep) return;  	LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);  	buff->allocateBuffer(vert_count, index_count, TRUE);  	facep->setVertexBuffer(buff); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 080d1f774a..c4e7ea44b4 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -520,6 +520,7 @@ void LLVOVolume::animateTextures()  		for (S32 i = start; i <= end; i++)  		{  			LLFace* facep = mDrawable->getFace(i); +			if (!facep) continue;  			if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue;  			const LLTextureEntry* te = facep->getTextureEntry(); @@ -638,7 +639,7 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  {  	LLViewerObject::idleUpdate(agent, world, time); -	static LLFastTimer::DeclareTimer ftm("Volume"); +	static LLFastTimer::DeclareTimer ftm("Volume Idle");  	LLFastTimer t(ftm);  	if (mDead || mDrawable.isNull()) @@ -682,7 +683,21 @@ void LLVOVolume::updateTextures()  	const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds  	if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME)  	{ -		updateTextureVirtualSize();		 +		updateTextureVirtualSize(); + +		if (mDrawable.notNull() && !isVisible() && !mDrawable->isActive()) +		{ //delete vertex buffer to free up some VRAM +			LLSpatialGroup* group  = mDrawable->getSpatialGroup(); +			if (group) +			{ +				group->destroyGL(true); + +				//flag the group as having changed geometry so it gets a rebuild next time +				//it becomes visible +				group->setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); +			} +		} +  	}  } @@ -715,7 +730,18 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)  	if(!forced)  	{  		if(!isVisible()) -		{ +		{ //don't load textures for non-visible faces +			const S32 num_faces = mDrawable->getNumFaces(); +			for (S32 i = 0; i < num_faces; i++) +			{ +				LLFace* face = mDrawable->getFace(i); +				if (face) +				{ +					face->setPixelArea(0.f);  +					face->setVirtualSize(0.f); +				} +			} +  			return ;  		} @@ -743,6 +769,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)  	for (S32 i = 0; i < num_faces; i++)  	{  		LLFace* face = mDrawable->getFace(i); +		if (!face) continue;  		const LLTextureEntry *te = face->getTextureEntry();  		LLViewerTexture *imagep = face->getTexture();  		if (!imagep || !te ||			 @@ -1062,9 +1089,33 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo  			}  		} + +		static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback"); + +		bool cache_in_vram = use_transform_feedback && gTransformPositionProgram.mProgramObject && +			(!mVolumeImpl || !mVolumeImpl->isVolumeUnique()); + +		if (cache_in_vram) +		{ //this volume might be used as source data for a transform object, put it in vram +			LLVolume* volume = getVolume(); +			for (S32 i = 0; i < volume->getNumFaces(); ++i) +			{ +				const LLVolumeFace& face = volume->getVolumeFace(i); +				if (face.mVertexBuffer.notNull()) +				{ //already cached +					break; +				} +				volume->genBinormals(i); +				LLFace::cacheFaceInVRAM(face); +			} +		} +		 +  		return TRUE;  	} + +  	return FALSE;  } @@ -1246,7 +1297,8 @@ BOOL LLVOVolume::calcLOD()  									llround(radius, 0.01f)); -	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO)) +	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) && +		mDrawable->getFace(0))  	{  		//setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail)); @@ -1325,25 +1377,23 @@ void LLVOVolume::updateFaceFlags()  	for (S32 i = 0; i < getVolume()->getNumFaces(); i++)  	{  		LLFace *face = mDrawable->getFace(i); -		if (!face) +		if (face)  		{ -			return; -		} +			BOOL fullbright = getTE(i)->getFullbright(); +			face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); -		BOOL fullbright = getTE(i)->getFullbright(); -		face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); - -		if (fullbright || (mMaterial == LL_MCODE_LIGHT)) -		{ -			face->setState(LLFace::FULLBRIGHT); -		} -		if (mDrawable->isLight()) -		{ -			face->setState(LLFace::LIGHT); -		} -		if (isHUDAttachment()) -		{ -			face->setState(LLFace::HUD_RENDER); +			if (fullbright || (mMaterial == LL_MCODE_LIGHT)) +			{ +				face->setState(LLFace::FULLBRIGHT); +			} +			if (mDrawable->isLight()) +			{ +				face->setState(LLFace::LIGHT); +			} +			if (isHUDAttachment()) +			{ +				face->setState(LLFace::HUD_RENDER); +			}  		}  	}  } @@ -1380,6 +1430,8 @@ void LLVOVolume::regenFaces()  	for (S32 i = 0; i < mNumFaces; i++)  	{  		LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i); +		if (!facep) continue; +  		facep->setTEOffset(i);  		facep->setTexture(getTEImage(i));  		facep->setViewerObject(this); @@ -1416,7 +1468,7 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)  	BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED); -//	bool rigged = false; +	//	bool rigged = false;  	LLVolume* volume = mRiggedVolume;  	if (!volume)  	{ @@ -1471,11 +1523,11 @@ void LLVOVolume::preRebuild()  	}  } -void LLVOVolume::updateRelativeXform() +void LLVOVolume::updateRelativeXform(bool force_identity)  {  	if (mVolumeImpl)  	{ -		mVolumeImpl->updateRelativeXform(); +		mVolumeImpl->updateRelativeXform(force_identity);  		return;  	} @@ -1495,15 +1547,16 @@ void LLVOVolume::updateRelativeXform()  		mRelativeXform.invert();  		mRelativeXformInvTrans.transpose();  	} -	else if (drawable->isActive()) +	else if (drawable->isActive() || force_identity)  	{				  		// setup relative transforms  		LLQuaternion delta_rot;  		LLVector3 delta_pos, delta_scale;  		//matrix from local space to parent relative/global space -		delta_rot = drawable->isSpatialRoot() ? LLQuaternion() : mDrawable->getRotation(); -		delta_pos = drawable->isSpatialRoot() ? LLVector3(0,0,0) : mDrawable->getPosition(); +		bool use_identity = force_identity || drawable->isSpatialRoot(); +		delta_rot = use_identity ? LLQuaternion() : mDrawable->getRotation(); +		delta_pos = use_identity ? LLVector3(0,0,0) : mDrawable->getPosition();  		delta_scale = mDrawable->getScale();  		// Vertex transform (4x4) @@ -1604,7 +1657,11 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)  		return res;  	} -	dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); +	LLSpatialGroup* group = drawable->getSpatialGroup(); +	if (group) +	{ +		group->dirtyMesh(); +	}  	BOOL compiled = FALSE; @@ -1617,6 +1674,8 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)  	if (mVolumeChanged || mFaceMappingChanged )  	{ +		dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); +  		compiled = TRUE;  		if (mVolumeChanged) @@ -1635,6 +1694,8 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)  	}  	else if ((mLODChanged) || (mSculptChanged))  	{ +		dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); +  		LLVolume *old_volumep, *new_volumep;  		F32 old_lod, new_lod;  		S32 old_num_faces, new_num_faces ; @@ -1716,16 +1777,19 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)  void LLVOVolume::updateFaceSize(S32 idx)  {  	LLFace* facep = mDrawable->getFace(idx); -	if (idx >= getVolume()->getNumVolumeFaces()) -	{ -		facep->setSize(0,0, true); -	} -	else +	if (facep)  	{ -		const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); -		facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices,  -						true); // <--- volume faces should be padded for 16-byte alignment +		if (idx >= getVolume()->getNumVolumeFaces()) +		{ +			facep->setSize(0,0, true); +		} +		else +		{ +			const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); +			facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices,  +							true); // <--- volume faces should be padded for 16-byte alignment +		}  	}  } @@ -3098,6 +3162,7 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const  	for (S32 i = 0; i < num_faces; ++i)  	{  		const LLFace* face = drawablep->getFace(i); +		if (!face) continue;  		const LLTextureEntry* te = face->getTextureEntry();  		const LLViewerTexture* img = face->getTexture(); @@ -3369,6 +3434,7 @@ F32 LLVOVolume::getBinRadius()  		for (S32 i = 0; i < mDrawable->getNumFaces(); i++)  		{  			LLFace* face = mDrawable->getFace(i); +			if (!face) continue;  			if (face->getPoolType() == LLDrawPool::POOL_ALPHA &&  			    !face->canRenderAsMask())  			{ @@ -3450,9 +3516,12 @@ LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const  {  	LLVector3 ret = pos - getRenderPosition();  	ret = ret * ~getRenderRotation(); -	LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); -	LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); -	ret.scaleVec(invObjScale); +	if (!isVolumeGlobal()) +	{ +		LLVector3 objScale = getScale(); +		LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); +		ret.scaleVec(invObjScale); +	}  	return ret;  } @@ -3470,8 +3539,12 @@ LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const  LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const  {  	LLVector3 ret = dir; -	LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); -	ret.scaleVec(objScale); +	if (!isVolumeGlobal()) +	{ +		LLVector3 objScale = getScale(); +		ret.scaleVec(objScale); +	} +  	ret = ret * getRenderRotation();  	ret += getRenderPosition(); @@ -3592,7 +3665,8 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e  			{  				LLFace* face = mDrawable->getFace(face_hit);				 -				if (pick_transparent || !face->getTexture() || !face->getTexture()->hasGLTexture() || face->getTexture()->getMask(face->surfaceToTexture(tc, p, n))) +				if (face && +					(pick_transparent || !face->getTexture() || !face->getTexture()->hasGLTexture() || face->getTexture()->getMask(face->surfaceToTexture(tc, p, n))))  				{  					v_end = p;  					if (face_hitp != NULL) @@ -3902,8 +3976,11 @@ bool can_batch_texture(LLFace* facep)  	return true;  } +static LLFastTimer::DeclareTimer FTM_REGISTER_FACE("Register Face"); +  void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type)  { +	LLFastTimer t(FTM_REGISTER_FACE);  	LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);  	if (facep->getViewerObject()->isSelected() && LLSelectMgr::getInstance()->mHideSelectedObjects) @@ -3935,9 +4012,14 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,  	const LLMatrix4* model_mat = NULL;  	LLDrawable* drawable = facep->getDrawable(); -	if (drawable->isActive()) +	 +	if (drawable->isState(LLDrawable::ANIMATED_CHILD)) +	{ +		model_mat = &drawable->getWorldMatrix(); +	} +	else if (drawable->isActive())  	{ -		model_mat = &(drawable->getRenderMatrix()); +		model_mat = &drawable->getRenderMatrix();  	}  	else  	{ @@ -3948,6 +4030,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,  		}  	} +	//drawable->getVObj()->setDebugText(llformat("%d", drawable->isState(LLDrawable::ANIMATED_CHILD))); +  	U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? facep->getTextureEntry()->getBumpmap() : 0;  	LLViewerTexture* tex = facep->getTexture(); @@ -4041,8 +4125,9 @@ void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group)  } -static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_VB("Volume"); -static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt"); +static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_VB("Volume VB"); +static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_FACE_LIST("Build Face List"); +static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_GEN_DRAW_INFO("Gen Draw Info");  static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj)  { @@ -4073,6 +4158,8 @@ static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj)  void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  { +	 +  	if (group->changeLOD())  	{  		group->mLastUpdateDistance = group->mDistance; @@ -4084,19 +4171,15 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  	{  		if (group->isState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate)  		{ -			LLFastTimer ftm(FTM_REBUILD_VBO);	 -			LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB); -		  			rebuildMesh(group);  		}  		return;  	} -	group->mBuilt = 1.f; -	LLFastTimer ftm(FTM_REBUILD_VBO);	 - -	LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB); +	LLFastTimer ftm(FTM_REBUILD_VOLUME_VB); +	group->mBuilt = 1.f; +	  	LLVOAvatar* pAvatarVO = NULL;  	LLSpatialBridge* bridge = group->mSpatialPartition->asBridge(); @@ -4145,359 +4228,375 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  	bool emissive = false; -	//get all the faces into a list -	for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter)  	{ -		LLDrawable* drawablep = *drawable_iter; -		 -		if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) +		LLFastTimer t(FTM_REBUILD_VOLUME_FACE_LIST); + +		//get all the faces into a list +		for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter)  		{ -			continue; -		} +			LLDrawable* drawablep = *drawable_iter; +		 +			if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) +			{ +				continue; +			} -		if (drawablep->isAnimating()) -		{ //fall back to stream draw for animating verts -			useage = GL_STREAM_DRAW_ARB; -		} +			if (drawablep->isAnimating()) +			{ //fall back to stream draw for animating verts +				useage = GL_STREAM_DRAW_ARB; +			} -		LLVOVolume* vobj = drawablep->getVOVolume(); +			LLVOVolume* vobj = drawablep->getVOVolume(); -		if (!vobj) -		{ -			continue; -		} +			if (!vobj) +			{ +				continue; +			} -		if (vobj->isMesh() && -			(vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded() || !gMeshRepo.meshRezEnabled())) -		{ -			continue; -		} +			if (vobj->isMesh() && +				(vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded() || !gMeshRepo.meshRezEnabled())) +			{ +				continue; +			} -		LLVolume* volume = vobj->getVolume(); -		if (volume) -		{ -			const LLVector3& scale = vobj->getScale(); -			group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); -		} +			LLVolume* volume = vobj->getVolume(); +			if (volume) +			{ +				const LLVector3& scale = vobj->getScale(); +				group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); +			} -		llassert_always(vobj); -		vobj->updateTextureVirtualSize(true); -		vobj->preRebuild(); +			llassert_always(vobj); +			vobj->updateTextureVirtualSize(true); +			vobj->preRebuild(); -		drawablep->clearState(LLDrawable::HAS_ALPHA); +			drawablep->clearState(LLDrawable::HAS_ALPHA); -		bool rigged = vobj->isAttachment() &&  -					vobj->isMesh() &&  -					gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID(), vobj); +			bool rigged = vobj->isAttachment() &&  +						vobj->isMesh() &&  +						gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID(), vobj); -		bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); +			bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); -		bool is_rigged = false; +			bool is_rigged = false; -		//for each face -		for (S32 i = 0; i < drawablep->getNumFaces(); i++) -		{ -			LLFace* facep = drawablep->getFace(i); +			//for each face +			for (S32 i = 0; i < drawablep->getNumFaces(); i++) +			{ +				LLFace* facep = drawablep->getFace(i); +				if (!facep) +				{ +					continue; +				} -			//ALWAYS null out vertex buffer on rebuild -- if the face lands in a render -			// batch, it will recover its vertex buffer reference from the spatial group -			facep->setVertexBuffer(NULL); +				//ALWAYS null out vertex buffer on rebuild -- if the face lands in a render +				// batch, it will recover its vertex buffer reference from the spatial group +				facep->setVertexBuffer(NULL); -			//sum up face verts and indices -			drawablep->updateFaceSize(i); +				//sum up face verts and indices +				drawablep->updateFaceSize(i); -			if (rigged)  -			{ -				if (!facep->isState(LLFace::RIGGED)) -				{ //completely reset vertex buffer -					facep->clearVertexBuffer(); -				} +				if (rigged)  +				{ +					if (!facep->isState(LLFace::RIGGED)) +					{ //completely reset vertex buffer +						facep->clearVertexBuffer(); +					} -				facep->setState(LLFace::RIGGED); -				is_rigged = true; +					facep->setState(LLFace::RIGGED); +					is_rigged = true; -				//get drawpool of avatar with rigged face -				LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); +					//get drawpool of avatar with rigged face +					LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); -				//Determine if we've received skininfo that contains an -				//alternate bind matrix - if it does then apply the translational component -				//to the joints of the avatar. -				bool pelvisGotSet = false; +					//Determine if we've received skininfo that contains an +					//alternate bind matrix - if it does then apply the translational component +					//to the joints of the avatar. +					bool pelvisGotSet = false; -				if ( pAvatarVO ) -				{ -					LLUUID currentId = vobj->getVolume()->getParams().getSculptID(); -					const LLMeshSkinInfo*  pSkinData = gMeshRepo.getSkinInfo( currentId, vobj ); -					 -					if ( pSkinData ) +					if ( pAvatarVO )  					{ -						const int bindCnt = pSkinData->mAlternateBindMatrix.size();								 -						if ( bindCnt > 0 ) -						{					 -							const int jointCnt = pSkinData->mJointNames.size(); -							const F32 pelvisZOffset = pSkinData->mPelvisOffset; -							bool fullRig = (jointCnt>=20) ? true : false; -							if ( fullRig ) -							{ -								for ( int i=0; i<jointCnt; ++i ) +						LLUUID currentId = vobj->getVolume()->getParams().getSculptID(); +						const LLMeshSkinInfo*  pSkinData = gMeshRepo.getSkinInfo( currentId, vobj ); +					 +						if ( pSkinData ) +						{ +							const int bindCnt = pSkinData->mAlternateBindMatrix.size();								 +							if ( bindCnt > 0 ) +							{					 +								const int jointCnt = pSkinData->mJointNames.size(); +								const F32 pelvisZOffset = pSkinData->mPelvisOffset; +								bool fullRig = (jointCnt>=20) ? true : false; +								if ( fullRig )  								{ -									std::string lookingForJoint = pSkinData->mJointNames[i].c_str(); -									//llinfos<<"joint name "<<lookingForJoint.c_str()<<llendl; -									LLJoint* pJoint = pAvatarVO->getJoint( lookingForJoint ); -									if ( pJoint && pJoint->getId() != currentId ) -									{   									 -										pJoint->setId( currentId ); -										const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation();									 -										//Set the joint position -										pJoint->storeCurrentXform( jointPos );																																 -										//If joint is a pelvis then handle old/new pelvis to foot values -										if ( lookingForJoint == "mPelvis" ) -										{	 +									for ( int i=0; i<jointCnt; ++i ) +									{ +										std::string lookingForJoint = pSkinData->mJointNames[i].c_str(); +										//llinfos<<"joint name "<<lookingForJoint.c_str()<<llendl; +										LLJoint* pJoint = pAvatarVO->getJoint( lookingForJoint ); +										if ( pJoint && pJoint->getId() != currentId ) +										{   									 +											pJoint->setId( currentId ); +											const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation();									 +											//Set the joint position  											pJoint->storeCurrentXform( jointPos );																																 -											if ( !pAvatarVO->hasPelvisOffset() ) -											{										 -												pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset ); -												//Trigger to rebuild viewer AV -												pelvisGotSet = true;											 +											//If joint is a pelvis then handle old/new pelvis to foot values +											if ( lookingForJoint == "mPelvis" ) +											{	 +												pJoint->storeCurrentXform( jointPos );																																 +												if ( !pAvatarVO->hasPelvisOffset() ) +												{										 +													pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset ); +													//Trigger to rebuild viewer AV +													pelvisGotSet = true;											 +												}										  											}										 -										}										 +										}  									} -								} -							}							 +								}							 +							}  						}  					} -				} -				//If we've set the pelvis to a new position we need to also rebuild some information that the -				//viewer does at launch (e.g. body size etc.) -				if ( pelvisGotSet ) -				{ -					pAvatarVO->postPelvisSetRecalc(); -				} - -				if (pool) -				{ -					const LLTextureEntry* te = facep->getTextureEntry(); - -					//remove face from old pool if it exists -					LLDrawPool* old_pool = facep->getPool(); -					if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR) +					//If we've set the pelvis to a new position we need to also rebuild some information that the +					//viewer does at launch (e.g. body size etc.) +					if ( pelvisGotSet )  					{ -						((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep); +						pAvatarVO->postPelvisSetRecalc();  					} -					//add face to new pool -					LLViewerTexture* tex = facep->getTexture(); -					U32 type = gPipeline.getPoolTypeFromTE(te, tex); - -					if (type == LLDrawPool::POOL_ALPHA) +					if (pool)  					{ -						if (te->getColor().mV[3] > 0.f) +						const LLTextureEntry* te = facep->getTextureEntry(); + +						//remove face from old pool if it exists +						LLDrawPool* old_pool = facep->getPool(); +						if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR) +						{ +							((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep); +						} + +						//add face to new pool +						LLViewerTexture* tex = facep->getTexture(); +						U32 type = gPipeline.getPoolTypeFromTE(te, tex); + +						if (type == LLDrawPool::POOL_ALPHA) +						{ +							if (te->getColor().mV[3] > 0.f) +							{ +								if (te->getFullbright()) +								{ +									pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); +								} +								else +								{ +									pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); +								} +							} +						} +						else if (te->getShiny())  						{  							if (te->getFullbright())  							{ -								pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); +								pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY);  							}  							else  							{ -								pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); +								if (LLPipeline::sRenderDeferred) +								{ +									pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); +								} +								else +								{ +									pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); +								}  							}  						} -					} -					else if (te->getShiny()) -					{ -						if (te->getFullbright()) -						{ -							pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); -						}  						else  						{ -							if (LLPipeline::sRenderDeferred) +							if (te->getFullbright())  							{ -								pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); +								pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT);  							}  							else  							{ -								pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); +								pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE);  							}  						} -					} -					else -					{ -						if (te->getFullbright()) -						{ -							pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); -						} -						else + +						if (te->getGlow())  						{ -							pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); +							pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW);  						} -					} -					if (te->getGlow()) -					{ -						pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); -					} - -					if (LLPipeline::sRenderDeferred) -					{ -						if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) +						if (LLPipeline::sRenderDeferred)  						{ -							if (te->getBumpmap()) -							{ -								pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); -							} -							else +							if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright())  							{ -								pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); +								if (te->getBumpmap()) +								{ +									pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); +								} +								else +								{ +									pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); +								}  							}  						}  					} -				} -				continue; -			} -			else -			{ -				if (facep->isState(LLFace::RIGGED)) -				{ //face is not rigged but used to be, remove from rigged face pool -					LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); -					if (pool) -					{ -						pool->removeRiggedFace(facep); +					continue; +				} +				else +				{ +					if (facep->isState(LLFace::RIGGED)) +					{ //face is not rigged but used to be, remove from rigged face pool +						LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); +						if (pool) +						{ +							pool->removeRiggedFace(facep); +						} +						facep->clearState(LLFace::RIGGED);  					} -					facep->clearState(LLFace::RIGGED);  				} -			} -			if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) -			{ -				facep->clearVertexBuffer(); -				continue; -			} - -			cur_total += facep->getGeomCount(); - -			if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) -			{ -				const LLTextureEntry* te = facep->getTextureEntry(); -				LLViewerTexture* tex = facep->getTexture(); - -				if (te->getGlow() >= 1.f/255.f) +				if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0)  				{ -					emissive = true; +					facep->clearVertexBuffer(); +					continue;  				} -				if (facep->isState(LLFace::TEXTURE_ANIM)) -				{ -					if (!vobj->mTexAnimMode) -					{ -						facep->clearState(LLFace::TEXTURE_ANIM); -					} -				} +				cur_total += facep->getGeomCount(); -				BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA); -				U32 type = gPipeline.getPoolTypeFromTE(te, tex); -				if (type != LLDrawPool::POOL_ALPHA && force_simple) +				if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA)  				{ -					type = LLDrawPool::POOL_SIMPLE; -				} -				facep->setPoolType(type); +					const LLTextureEntry* te = facep->getTextureEntry(); +					LLViewerTexture* tex = facep->getTexture(); -				if (vobj->isHUDAttachment()) -				{ -					facep->setState(LLFace::FULLBRIGHT); -				} +					if (te->getGlow() >= 1.f/255.f) +					{ +						emissive = true; +					} -				if (vobj->mTextureAnimp && vobj->mTexAnimMode) -				{ -					if (vobj->mTextureAnimp->mFace <= -1) +					if (facep->isState(LLFace::TEXTURE_ANIM))  					{ -						S32 face; -						for (face = 0; face < vobj->getNumTEs(); face++) +						if (!vobj->mTexAnimMode)  						{ -							drawablep->getFace(face)->setState(LLFace::TEXTURE_ANIM); +							facep->clearState(LLFace::TEXTURE_ANIM);  						}  					} -					else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) + +					BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA); +					U32 type = gPipeline.getPoolTypeFromTE(te, tex); +					if (type != LLDrawPool::POOL_ALPHA && force_simple)  					{ -						drawablep->getFace(vobj->mTextureAnimp->mFace)->setState(LLFace::TEXTURE_ANIM); +						type = LLDrawPool::POOL_SIMPLE;  					} -				} +					facep->setPoolType(type); -				if (type == LLDrawPool::POOL_ALPHA) -				{ -					if (facep->canRenderAsMask()) -					{ //can be treated as alpha mask -						simple_faces.push_back(facep); -					} -					else +					if (vobj->isHUDAttachment())  					{ -						if (te->getColor().mV[3] > 0.f) -						{ //only treat as alpha in the pipeline if < 100% transparent -							drawablep->setState(LLDrawable::HAS_ALPHA); -						} -						alpha_faces.push_back(facep); +						facep->setState(LLFace::FULLBRIGHT);  					} -				} -				else -				{ -					if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) + +					if (vobj->mTextureAnimp && vobj->mTexAnimMode)  					{ -						facep->mLastUpdateTime = gFrameTimeSeconds; +						if (vobj->mTextureAnimp->mFace <= -1) +						{ +							S32 face; +							for (face = 0; face < vobj->getNumTEs(); face++) +							{ +								LLFace * facep = drawablep->getFace(face); +								if (facep) +								{ +									facep->setState(LLFace::TEXTURE_ANIM); +								} +							} +						} +						else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) +						{ +							LLFace * facep = drawablep->getFace(vobj->mTextureAnimp->mFace); +							if (facep) +							{ +								facep->setState(LLFace::TEXTURE_ANIM); +							} +						}  					} -					if (gPipeline.canUseWindLightShadersOnObjects() -						&& LLPipeline::sRenderBump) +					if (type == LLDrawPool::POOL_ALPHA)  					{ -						if (te->getBumpmap()) -						{ //needs normal + binormal -							bump_faces.push_back(facep); -						} -						else if (te->getShiny() || !te->getFullbright()) -						{ //needs normal +						if (facep->canRenderAsMask()) +						{ //can be treated as alpha mask  							simple_faces.push_back(facep);  						} -						else  -						{ //doesn't need normal -							facep->setState(LLFace::FULLBRIGHT); -							fullbright_faces.push_back(facep); +						else +						{ +							if (te->getColor().mV[3] > 0.f) +							{ //only treat as alpha in the pipeline if < 100% transparent +								drawablep->setState(LLDrawable::HAS_ALPHA); +							} +							alpha_faces.push_back(facep);  						}  					}  					else  					{ -						if (te->getBumpmap() && LLPipeline::sRenderBump) -						{ //needs normal + binormal -							bump_faces.push_back(facep); +						if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) +						{ +							facep->mLastUpdateTime = gFrameTimeSeconds;  						} -						else if ((te->getShiny() && LLPipeline::sRenderBump) || -							!(te->getFullbright() || bake_sunlight)) -						{ //needs normal -							simple_faces.push_back(facep); + +						if (gPipeline.canUseWindLightShadersOnObjects() +							&& LLPipeline::sRenderBump) +						{ +							if (te->getBumpmap()) +							{ //needs normal + binormal +								bump_faces.push_back(facep); +							} +							else if (te->getShiny() || !te->getFullbright()) +							{ //needs normal +								simple_faces.push_back(facep); +							} +							else  +							{ //doesn't need normal +								facep->setState(LLFace::FULLBRIGHT); +								fullbright_faces.push_back(facep); +							}  						} -						else  -						{ //doesn't need normal -							facep->setState(LLFace::FULLBRIGHT); -							fullbright_faces.push_back(facep); +						else +						{ +							if (te->getBumpmap() && LLPipeline::sRenderBump) +							{ //needs normal + binormal +								bump_faces.push_back(facep); +							} +							else if ((te->getShiny() && LLPipeline::sRenderBump) || +								!(te->getFullbright() || bake_sunlight)) +							{ //needs normal +								simple_faces.push_back(facep); +							} +							else  +							{ //doesn't need normal +								facep->setState(LLFace::FULLBRIGHT); +								fullbright_faces.push_back(facep); +							}  						}  					}  				} +				else +				{	//face has no renderable geometry +					facep->clearVertexBuffer(); +				}		  			} -			else -			{	//face has no renderable geometry -				facep->clearVertexBuffer(); -			}		 -		} -		if (is_rigged) -		{ -			drawablep->setState(LLDrawable::RIGGED); -		} -		else -		{ -			drawablep->clearState(LLDrawable::RIGGED); +			if (is_rigged) +			{ +				drawablep->setState(LLDrawable::RIGGED); +			} +			else +			{ +				drawablep->clearState(LLDrawable::RIGGED); +			}  		}  	} @@ -4564,15 +4663,15 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  	}  } -static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM("Volume Geometry"); -static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM_PARTIAL("Terse Rebuild");  void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  {  	llassert(group);  	if (group && group->isState(LLSpatialGroup::MESH_DIRTY) && !group->isState(LLSpatialGroup::GEOM_DIRTY))  	{ -		LLFastTimer tm(FTM_VOLUME_GEOM); +		LLFastTimer ftm(FTM_REBUILD_VOLUME_VB); +		LLFastTimer t(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); //make sure getgeometryvolume shows up in the right place in timers +  		S32 num_mapped_veretx_buffer = LLVertexBuffer::sMappedCount ;  		group->mBuilt = 1.f; @@ -4581,14 +4680,18 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  		for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter)  		{ -			LLFastTimer t(FTM_VOLUME_GEOM_PARTIAL);  			LLDrawable* drawablep = *drawable_iter; -			if (!drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) ) +			if (!drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) )  			{  				LLVOVolume* vobj = drawablep->getVOVolume();  				vobj->preRebuild(); +				if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) +				{ +					vobj->updateRelativeXform(true); +				} +  				LLVolume* volume = vobj->getVolume();  				for (S32 i = 0; i < drawablep->getNumFaces(); ++i)  				{ @@ -4598,6 +4701,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  						LLVertexBuffer* buff = face->getVertexBuffer();  						if (buff)  						{ +							llassert(!face->isState(LLFace::RIGGED));  							face->getGeometryVolume(*volume, face->getTEOffset(),   								vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()); @@ -4608,6 +4712,12 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  						}  					}  				} + +				if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) +				{ +					vobj->updateRelativeXform(); +				} +  				drawablep->clearState(LLDrawable::REBUILD_ALL);  			} @@ -4636,10 +4746,13 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  				for (S32 i = 0; i < drawablep->getNumFaces(); ++i)  				{  					LLFace* face = drawablep->getFace(i); -					LLVertexBuffer* buff = face->getVertexBuffer(); -					if (face && buff && buff->isLocked()) +					if (face)  					{ -						buff->flush(); +						LLVertexBuffer* buff = face->getVertexBuffer(); +						if (buff && buff->isLocked()) +						{ +							buff->flush(); +						}  					}  				}  			}  @@ -4648,7 +4761,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  		group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO);  	} -	llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO)); +//	llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO));  }  struct CompareBatchBreakerModified @@ -4674,8 +4787,20 @@ struct CompareBatchBreakerModified  	}  }; +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_SORT("Draw Info Face Sort"); +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_FACE_SIZE("Face Sizing"); +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_ALLOCATE("Allocate VB"); +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_FIND_VB("Find VB"); +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB"); + + + + +  void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort, BOOL batch_textures)  { +	LLFastTimer t(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); +  	U32 buffer_usage = group->mBufferUsage;  #if LL_DARWIN @@ -4693,15 +4818,18 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  	U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask);  	max_vertices = llmin(max_vertices, (U32) 65535); -	if (!distance_sort) -	{ -		//sort faces by things that break batches -		std::sort(faces.begin(), faces.end(), CompareBatchBreakerModified()); -	} -	else  	{ -		//sort faces by distance -		std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater()); +		LLFastTimer t(FTM_GEN_DRAW_INFO_SORT); +		if (!distance_sort) +		{ +			//sort faces by things that break batches +			std::sort(faces.begin(), faces.end(), CompareBatchBreakerModified()); +		} +		else +		{ +			//sort faces by distance +			std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater()); +		}  	}  	bool hud_group = group->isHUDGroup() ; @@ -4766,57 +4894,86 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  		std::vector<LLViewerTexture*> texture_list; -		if (batch_textures)  		{ -			U8 cur_tex = 0; -			facep->setTextureIndex(cur_tex); -			texture_list.push_back(tex); - -			//if (can_batch_texture(facep)) +			LLFastTimer t(FTM_GEN_DRAW_INFO_FACE_SIZE); +			if (batch_textures)  			{ -				while (i != faces.end()) +				U8 cur_tex = 0; +				facep->setTextureIndex(cur_tex); +				texture_list.push_back(tex); + +				//if (can_batch_texture(facep))  				{ -					facep = *i; -					if (facep->getTexture() != tex) +					while (i != faces.end())  					{ -						if (distance_sort) -						{ //textures might be out of order, see if texture exists in current batch -							bool found = false; -							for (U32 tex_idx = 0; tex_idx < texture_list.size(); ++tex_idx) -							{ -								if (facep->getTexture() == texture_list[tex_idx]) +						facep = *i; +						if (facep->getTexture() != tex) +						{ +							if (distance_sort) +							{ //textures might be out of order, see if texture exists in current batch +								bool found = false; +								for (U32 tex_idx = 0; tex_idx < texture_list.size(); ++tex_idx)  								{ -									cur_tex = tex_idx; -									found = true; -									break; +									if (facep->getTexture() == texture_list[tex_idx]) +									{ +										cur_tex = tex_idx; +										found = true; +										break; +									}  								} -							} -							if (!found) +								if (!found) +								{ +									cur_tex = texture_list.size(); +								} +							} +							else  							{ -								cur_tex = texture_list.size(); +								cur_tex++;  							} -						} -						else -						{ -							cur_tex++; -						} -						if (!can_batch_texture(facep)) -						{ //face is bump mapped or has an animated texture matrix -- can't  -							//batch more than 1 texture at a time -							break; +							if (!can_batch_texture(facep)) +							{ //face is bump mapped or has an animated texture matrix -- can't  +								//batch more than 1 texture at a time +								break; +							} + +							if (cur_tex >= texture_index_channels) +							{ //cut batches when index channels are depleted +								break; +							} + +							tex = facep->getTexture(); + +							texture_list.push_back(tex);  						} -						if (cur_tex >= texture_index_channels) -						{ //cut batches when index channels are depleted +						if (geom_count + facep->getGeomCount() > max_vertices) +						{ //cut batches on geom count too big  							break;  						} -						tex = facep->getTexture(); +						++i; +						index_count += facep->getIndicesCount(); +						geom_count += facep->getGeomCount(); -						texture_list.push_back(tex); +						facep->setTextureIndex(cur_tex);  					} +				} + +				tex = texture_list[0]; +			} +			else +			{ +				while (i != faces.end() &&  +					(LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) +				{ +					facep = *i; +			 + +					//face has no texture index +					facep->mDrawInfo = NULL; +					facep->setTextureIndex(255);  					if (geom_count + facep->getGeomCount() > max_vertices)  					{ //cut batches on geom count too big @@ -4826,69 +4983,18 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  					++i;  					index_count += facep->getIndicesCount();  					geom_count += facep->getGeomCount(); - -					facep->setTextureIndex(cur_tex);  				}  			} - -			tex = texture_list[0];  		} -		else -		{ -			while (i != faces.end() &&  -				(LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) -			{ -				facep = *i; -			 -				//face has no texture index -				facep->mDrawInfo = NULL; -				facep->setTextureIndex(255); - -				if (geom_count + facep->getGeomCount() > max_vertices) -				{ //cut batches on geom count too big -					break; -				} - -				++i; -				index_count += facep->getIndicesCount(); -				geom_count += facep->getGeomCount(); -			} -		} -	 -		//create/delete/resize vertex buffer if needed +		//create vertex buffer  		LLVertexBuffer* buffer = NULL; -		{ //try to find a buffer to reuse -			LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(*face_iter); -		 -			if (found_iter != group->mBufferMap[mask].end()) -			{ -				if ((U32) buffer_index < found_iter->second.size()) -				{ -					buffer = found_iter->second[buffer_index]; -				} -			} -		} -						 -		if (!buffer || !buffer->isWriteable()) -		{ //create new buffer if needed +		{ +			LLFastTimer t(FTM_GEN_DRAW_INFO_ALLOCATE);  			buffer = createVertexBuffer(mask, buffer_usage);  			buffer->allocateBuffer(geom_count, index_count, TRUE);  		} -		else  -		{ //resize pre-existing buffer -			if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != buffer_usage || -				buffer->getTypeMask() != mask) -			{ -				buffer = createVertexBuffer(mask, buffer_usage); -				buffer->allocateBuffer(geom_count, index_count, TRUE); -			} -			else -			{ -				buffer->resizeBuffer(geom_count, index_count); -			} -		}  		group->mGeometryBytes += buffer->getSize() + buffer->getIndicesSize(); @@ -4922,10 +5028,22 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  					LLVOVolume* vobj = drawablep->getVOVolume();  					LLVolume* volume = vobj->getVolume(); +					if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) +					{ +						vobj->updateRelativeXform(true); +					} +  					U32 te_idx = facep->getTEOffset(); +					llassert(!facep->isState(LLFace::RIGGED)); +  					facep->getGeometryVolume(*volume, te_idx,  -						vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset); +						vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset,true); + +					if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) +					{ +						vobj->updateRelativeXform(false); +					}  				}  			} @@ -5089,6 +5207,7 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun  	mFaceList.clear();  	//for each drawable +  	for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter)  	{  		LLDrawable* drawablep = *drawable_iter; @@ -5109,17 +5228,21 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun  			//sum up face verts and indices  			drawablep->updateFaceSize(i);  			LLFace* facep = drawablep->getFace(i); -			if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) +			if (facep)  			{ -				vertex_count += facep->getGeomCount(); -				index_count += facep->getIndicesCount(); -				llassert(facep->getIndicesCount() < 65536); -				//remember face (for sorting) -				mFaceList.push_back(facep); -			} -			else -			{ -				facep->clearVertexBuffer(); +				if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA &&  +					facep->getGeomCount() + vertex_count <= 65536) +				{ +					vertex_count += facep->getGeomCount(); +					index_count += facep->getIndicesCount(); +				 +					//remember face (for sorting) +					mFaceList.push_back(facep); +				} +				else +				{ +					facep->clearVertexBuffer(); +				}  			}  		}  	} diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 3cf434dc26..c4505b4bd8 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -79,7 +79,7 @@ public:  	virtual bool isVolumeGlobal() const = 0; // Are we in global space?  	virtual bool isActive() const = 0; // Is this object currently active?  	virtual const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const = 0; -	virtual void updateRelativeXform() = 0; +	virtual void updateRelativeXform(bool force_identity = false) = 0;  	virtual U32 getID() const = 0;  	virtual void preRebuild() = 0;  }; @@ -203,7 +203,7 @@ public:  														  LLAssetType::EType type,  														  void* user_data, S32 status, LLExtStat ext_status); -				void	updateRelativeXform(); +				void	updateRelativeXform(bool force_identity = false);  	/*virtual*/ BOOL	updateGeometry(LLDrawable *drawable);  	/*virtual*/ void	updateFaceSize(S32 idx);  	/*virtual*/ BOOL	updateLOD(); diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index cd78157944..942eff6171 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -146,6 +146,10 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable)  		drawable->addFace(poolp, NULL);  	}  	face = drawable->getFace(0); +	if (!face) +	{ +		return TRUE; +	}  //	LLVector2 uvs[4];  //	LLVector3 vtx[4]; diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index b061c90d98..fc6b959aa8 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -1195,6 +1195,7 @@ void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positi  			if (!uuid.isNull()  				&& dist_vec_squared(pos_global, relative_to) <= radius_squared) +			dist_vec_squared(pos_global, relative_to) <= radius_squared)  			{  				if(positions != NULL)  				{ diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index ed636a40b2..49c4f37871 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -51,6 +51,10 @@  // newview includes  #include "llagent.h"  #include "llagentcamera.h" +#include "llappviewer.h" +#include "lltexturecache.h" +#include "lltexturefetch.h" +#include "llimageworker.h"  #include "lldrawable.h"  #include "lldrawpoolalpha.h"  #include "lldrawpoolavatar.h" @@ -264,6 +268,7 @@ std::string gPoolNames[] =  void drawBox(const LLVector3& c, const LLVector3& r);  void drawBoxOutline(const LLVector3& pos, const LLVector3& size);  U32 nhpo2(U32 v); +LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage);  glh::matrix4f glh_copy_matrix(F32* src)  { @@ -403,9 +408,11 @@ LLPipeline::LLPipeline() :  	mInitialized(FALSE),  	mVertexShadersEnabled(FALSE),  	mVertexShadersLoaded(0), +	mTransformFeedbackPrimitives(0),  	mRenderDebugFeatureMask(0),  	mRenderDebugMask(0),  	mOldRenderDebugMask(0), +	mMeshDirtyQueryObject(0),  	mGroupQ1Locked(false),  	mGroupQ2Locked(false),  	mResetVertexBuffers(false), @@ -504,6 +511,11 @@ void LLPipeline::init()  		mSpotLightFade[i] = 1.f;  	} +	if (mCubeVB.isNull()) +	{ +		mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); +	} +  	mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0);  	mDeferredVB->allocateBuffer(8, 0, true);  	setLightingDetail(-1); @@ -693,6 +705,12 @@ void LLPipeline::destroyGL()  	{  		LLVertexBuffer::sEnableVBOs = FALSE;  	} + +	if (mMeshDirtyQueryObject) +	{ +		glDeleteQueriesARB(1, &mMeshDirtyQueryObject); +		mMeshDirtyQueryObject = 0; +	}  }  static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture"); @@ -942,6 +960,7 @@ void LLPipeline::refreshCachedSettings()  	LLPipeline::sUseOcclusion =   			(!gUseWireframe +			&& LLGLSLShader::sNoFixedFunction  			&& LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion")   			&& gSavedSettings.getBOOL("UseOcclusion")   			&& gGLManager.mHasOcclusionQuery) ? 2 : 0; @@ -1030,13 +1049,13 @@ void LLPipeline::releaseGLBuffers()  	if (mNoiseMap)  	{ -		LLImageGL::deleteTextures(1, &mNoiseMap); +		LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 0, 1, &mNoiseMap);  		mNoiseMap = 0;  	}  	if (mTrueNoiseMap)  	{ -		LLImageGL::deleteTextures(1, &mTrueNoiseMap); +		LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 0, 1, &mTrueNoiseMap);  		mTrueNoiseMap = 0;  	} @@ -1060,7 +1079,7 @@ void LLPipeline::releaseLUTBuffers()  {  	if (mLightFunc)  	{ -		LLImageGL::deleteTextures(1, &mLightFunc); +		LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, GL_R8, 0, 1, &mLightFunc);  		mLightFunc = 0;  	}  } @@ -1138,7 +1157,7 @@ void LLPipeline::createGLBuffers()  				noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f;  			} -			LLImageGL::generateTextures(1, &mNoiseMap); +			LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 1, &mNoiseMap);  			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap);  			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise, false); @@ -1154,7 +1173,7 @@ void LLPipeline::createGLBuffers()  				noise[i] = ll_frand()*2.0-1.0;  			} -			LLImageGL::generateTextures(1, &mTrueNoiseMap); +			LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 1, &mTrueNoiseMap);  			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap);  			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise, false);  			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); @@ -1210,7 +1229,7 @@ void LLPipeline::createLUTBuffers()  				}  			} -			LLImageGL::generateTextures(1, &mLightFunc); +			LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_R8, 1, &mLightFunc);  			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);  			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, ls, false);  			gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); @@ -1820,6 +1839,16 @@ void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list)  		if (done)  		{  			drawablep->clearState(LLDrawable::ON_MOVE_LIST); +			if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) +			{ //will likely not receive any future world matrix updates +				// -- this keeps attachments from getting stuck in space and falling off your avatar +				drawablep->clearState(LLDrawable::ANIMATED_CHILD); +				markRebuild(drawablep, LLDrawable::REBUILD_VOLUME, TRUE); +				if (drawablep->getVObj()) +				{ +					drawablep->getVObj()->dirtySpatialGroup(TRUE); +				} +			}  			iter = moved_list.erase(curiter);  		}  	} @@ -2214,8 +2243,6 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl  	gGLLastMatrix = NULL;  	gGL.loadMatrix(gGLLastModelView); - -	LLVertexBuffer::unbind();  	LLGLDisable blend(GL_BLEND);  	LLGLDisable test(GL_ALPHA_TEST);  	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -2259,7 +2286,16 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl  	{ //if no shader is currently bound, use the occlusion shader instead of fixed function if we can  		// (shadow render uses a special shader that clamps to clip planes)  		bound_shader = true; -		gOcclusionProgram.bind(); +		gOcclusionCubeProgram.bind(); +	} + +	if (sUseOcclusion > 1) +	{ +		if (mCubeVB.isNull()) +		{ //cube VB will be used for issuing occlusion queries +			mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); +		} +		mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);  	}  	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();  @@ -2291,7 +2327,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl  	if (bound_shader)  	{ -		gOcclusionProgram.unbind(); +		gOcclusionCubeProgram.unbind();  	}  	camera.disableUserClipPlane(); @@ -2424,14 +2460,20 @@ void LLPipeline::doOcclusion(LLCamera& camera)  		{  			if (LLPipeline::sShadowRender)  			{ -				gDeferredShadowProgram.bind(); +				gDeferredShadowCubeProgram.bind();  			}  			else  			{ -				gOcclusionProgram.bind(); +				gOcclusionCubeProgram.bind();  			}  		} +		if (mCubeVB.isNull()) +		{ //cube VB will be used for issuing occlusion queries +			mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); +		} +		mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); +  		for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter)  		{  			LLSpatialGroup* group = *iter; @@ -2443,11 +2485,11 @@ void LLPipeline::doOcclusion(LLCamera& camera)  		{  			if (LLPipeline::sShadowRender)  			{ -				gDeferredShadowProgram.unbind(); +				gDeferredShadowCubeProgram.unbind();  			}  			else  			{ -				gOcclusionProgram.unbind(); +				gOcclusionCubeProgram.unbind();  			}  		} @@ -2466,6 +2508,8 @@ BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority)  	return update_complete;  } +static LLFastTimer::DeclareTimer FTM_SEED_VBO_POOLS("Seed VBO Pool"); +  void LLPipeline::updateGL()  {  	while (!LLGLUpdate::sGLQ.empty()) @@ -2475,6 +2519,11 @@ void LLPipeline::updateGL()  		glu->mInQ = FALSE;  		LLGLUpdate::sGLQ.pop_front();  	} + +	{ //seed VBO Pools +		LLFastTimer t(FTM_SEED_VBO_POOLS); +		LLVertexBuffer::seedPools(); +	}  }  void LLPipeline::rebuildPriorityGroups() @@ -2838,6 +2887,11 @@ void LLPipeline::processPartitionQ()  	mPartitionQ.clear();  } +void LLPipeline::markMeshDirty(LLSpatialGroup* group) +{ +	mMeshDirtyGroup.push_back(group); +} +  void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority)  {  	LLMemType mt(LLMemType::MTYPE_PIPELINE); @@ -3189,7 +3243,11 @@ void renderScriptedBeacons(LLDrawable* drawablep)  			S32 count = drawablep->getNumFaces();  			for (face_id = 0; face_id < count; face_id++)  			{ -				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); +				LLFace * facep = drawablep->getFace(face_id); +				if (facep)  +				{ +					gPipeline.mHighlightFaces.push_back(facep); +				}  			}  		}  	} @@ -3215,7 +3273,11 @@ void renderScriptedTouchBeacons(LLDrawable* drawablep)  			S32 count = drawablep->getNumFaces();  			for (face_id = 0; face_id < count; face_id++)  			{ -				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); +				LLFace * facep = drawablep->getFace(face_id); +				if (facep) +				{ +					gPipeline.mHighlightFaces.push_back(facep); +				}  			}  		}  	} @@ -3240,7 +3302,11 @@ void renderPhysicalBeacons(LLDrawable* drawablep)  			S32 count = drawablep->getNumFaces();  			for (face_id = 0; face_id < count; face_id++)  			{ -				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); +				LLFace * facep = drawablep->getFace(face_id); +				if (facep) +				{ +					gPipeline.mHighlightFaces.push_back(facep); +				}  			}  		}  	} @@ -3276,7 +3342,11 @@ void renderMOAPBeacons(LLDrawable* drawablep)  			S32 count = drawablep->getNumFaces();  			for (face_id = 0; face_id < count; face_id++)  			{ -				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); +				LLFace * facep = drawablep->getFace(face_id); +				if (facep) +				{ +					gPipeline.mHighlightFaces.push_back(facep); +				}  			}  		}  	} @@ -3301,7 +3371,11 @@ void renderParticleBeacons(LLDrawable* drawablep)  			S32 count = drawablep->getNumFaces();  			for (face_id = 0; face_id < count; face_id++)  			{ -				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); +				LLFace * facep = drawablep->getFace(face_id); +				if (facep) +				{ +					gPipeline.mHighlightFaces.push_back(facep); +				}  			}  		}  	} @@ -3319,7 +3393,11 @@ void renderSoundHighlights(LLDrawable* drawablep)  			S32 count = drawablep->getNumFaces();  			for (face_id = 0; face_id < count; face_id++)  			{ -				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); +				LLFace * facep = drawablep->getFace(face_id); +				if (facep) +				{ +					gPipeline.mHighlightFaces.push_back(facep); +				}  			}  		}  	} @@ -3350,21 +3428,7 @@ void LLPipeline::postSort(LLCamera& camera)  	rebuildPriorityGroups();  	llpushcallstacks ; -	const S32 bin_count = 1024*8; -		 -	static LLCullResult::drawinfo_list_t alpha_bins[bin_count]; -	static U32 bin_size[bin_count]; - -	//clear one bin per frame to avoid memory bloat -	static S32 clear_idx = 0; -	clear_idx = (1+clear_idx)%bin_count; -	alpha_bins[clear_idx].clear(); - -	for (U32 j = 0; j < bin_count; j++) -	{ -		bin_size[j] = 0; -	} - +	  	//build render map  	for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)  	{ @@ -3436,11 +3500,43 @@ void LLPipeline::postSort(LLCamera& camera)  			}  		}  	} +	 +	//flush particle VB +	LLVOPartGroup::sVB->flush(); + +	/*bool use_transform_feedback = gTransformPositionProgram.mProgramObject && !mMeshDirtyGroup.empty(); + +	if (use_transform_feedback) +	{ //place a query around potential transform feedback code for synchronization +		mTransformFeedbackPrimitives = 0; + +		if (!mMeshDirtyQueryObject) +		{ +			glGenQueriesARB(1, &mMeshDirtyQueryObject); +		} + +		glBeginQueryARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, mMeshDirtyQueryObject); +	}*/ + +	//pack vertex buffers for groups that chose to delay their updates +	for (LLSpatialGroup::sg_vector_t::iterator iter = mMeshDirtyGroup.begin(); iter != mMeshDirtyGroup.end(); ++iter) +	{ +		(*iter)->rebuildMesh(); +	} + +	/*if (use_transform_feedback) +	{ +		glEndQueryARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); +	}*/ +	 +	mMeshDirtyGroup.clear(); +  	if (!sShadowRender)  	{  		std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater());  	} +  	llpushcallstacks ;  	// only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus  	if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender) @@ -3514,7 +3610,11 @@ void LLPipeline::postSort(LLCamera& camera)  				{  					if (object->mDrawable)  					{ -						gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te)); +						LLFace * facep = object->mDrawable->getFace(te); +						if (facep) +						{ +							gPipeline.mSelectedFaces.push_back(facep); +						}  					}  					return true;  				} @@ -3523,6 +3623,33 @@ void LLPipeline::postSort(LLCamera& camera)  		}  	} +	/*static LLFastTimer::DeclareTimer FTM_TRANSFORM_WAIT("Transform Fence"); +	static LLFastTimer::DeclareTimer FTM_TRANSFORM_DO_WORK("Transform Work"); +	if (use_transform_feedback) +	{ //using transform feedback, wait for transform feedback to complete +		LLFastTimer t(FTM_TRANSFORM_WAIT); + +		S32 done = 0; +		//glGetQueryivARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_CURRENT_QUERY, &count); +		 +		glGetQueryObjectivARB(mMeshDirtyQueryObject, GL_QUERY_RESULT_AVAILABLE, &done); +		 +		while (!done) +		{  +			{ +				LLFastTimer t(FTM_TRANSFORM_DO_WORK); +				F32 max_time = llmin(gFrameIntervalSeconds*10.f, 1.f); +				//do some useful work while we wait +				LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread +				LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread +				LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread +			} +			glGetQueryObjectivARB(mMeshDirtyQueryObject, GL_QUERY_RESULT_AVAILABLE, &done); +		} + +		mTransformFeedbackPrimitives = 0; +	}*/ +						  	//LLSpatialGroup::sNoDelete = FALSE;  	llpushcallstacks ;  } @@ -6219,7 +6346,10 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable)  	for (S32 i = 0; i < drawable->getNumFaces(); i++)  	{  		LLFace* facep = drawable->getFace(i); -		facep->clearVertexBuffer(); +		if (facep) +		{ +			facep->clearVertexBuffer(); +		}  	}  } @@ -6237,6 +6367,8 @@ void LLPipeline::doResetVertexBuffers()  	mResetVertexBuffers = false; +	mCubeVB = NULL; +  	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();   			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)  	{ @@ -6255,11 +6387,15 @@ void LLPipeline::doResetVertexBuffers()  	gSky.resetVertexBuffers(); +	LLVOPartGroup::destroyGL(); +  	LLVertexBuffer::cleanupClass();  	//delete all name pool caches  	LLGLNamePool::cleanupPools(); +	 +  	if (LLVertexBuffer::sGLCount > 0)  	{  		llwarns << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << llendl; @@ -6279,6 +6415,8 @@ void LLPipeline::doResetVertexBuffers()  	LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind");  	LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping); + +	LLVOPartGroup::restoreGL();  }  void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture, BOOL batch_texture) @@ -7466,12 +7604,17 @@ void LLPipeline::renderDeferredLighting()  			std::list<LLVector4> light_colors;  			LLVertexBuffer::unbind(); -			LLVector4a* v = (LLVector4a*) vert.get();  			{  				bindDeferredShader(gDeferredLightProgram); -				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); +				 +				if (mCubeVB.isNull()) +				{ +					mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); +				} +				mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); +				  				LLGLDepthTest depth(GL_TRUE, GL_FALSE);  				for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter)  				{ @@ -7517,25 +7660,7 @@ void LLPipeline::renderDeferredLighting()  					}  					sVisibleLightCount++; - -					glh::vec3f tc(c); -					mat.mult_matrix_vec(tc); -					 -					//vertex positions are encoded so the 3 bits of their vertex index  -					//correspond to their axis facing, with bit position 3,2,1 matching -					//axis facing x,y,z, bit set meaning positive facing, bit clear  -					//meaning negative facing -					mDeferredVB->getVertexStrider(vert); -					v[0].set(c[0]-s,c[1]-s,c[2]-s);  // 0 - 0000  -					v[1].set(c[0]-s,c[1]-s,c[2]+s);  // 1 - 0001 -					v[2].set(c[0]-s,c[1]+s,c[2]-s);  // 2 - 0010 -					v[3].set(c[0]-s,c[1]+s,c[2]+s);  // 3 - 0011 -																									    -					v[4].set(c[0]+s,c[1]-s,c[2]-s); // 4 - 0100 -					v[5].set(c[0]+s,c[1]-s,c[2]+s); // 5 - 0101 -					v[6].set(c[0]+s,c[1]+s,c[2]-s); // 6 - 0110 -					v[7].set(c[0]+s,c[1]+s,c[2]+s); // 7 - 0111 - +										  					if (camera->getOrigin().mV[0] > c[0] + s + 0.2f ||  						camera->getOrigin().mV[0] < c[0] - s - 0.2f ||  						camera->getOrigin().mV[1] > c[1] + s + 0.2f || @@ -7553,16 +7678,13 @@ void LLPipeline::renderDeferredLighting()  							}  							LLFastTimer ftm(FTM_LOCAL_LIGHTS); -							//glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); -							gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); +							gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c);  							gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);  							gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);  							gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); -							//gGL.diffuseColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);  							gGL.syncMatrices(); -							mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); -							glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, -								GL_UNSIGNED_SHORT, get_box_fan_indices_ptr(camera, center)); +							 +							mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center));  							stop_glerror();  						}  					} @@ -7575,6 +7697,9 @@ void LLPipeline::renderDeferredLighting()  							continue;  						} +						glh::vec3f tc(c); +						mat.mult_matrix_vec(tc); +					  						fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s));  						light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f));  					} @@ -7587,7 +7712,7 @@ void LLPipeline::renderDeferredLighting()  				LLGLDepthTest depth(GL_TRUE, GL_FALSE);  				bindDeferredShader(gDeferredSpotLightProgram); -				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); +				mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);  				gDeferredSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION); @@ -7605,36 +7730,17 @@ void LLPipeline::renderDeferredLighting()  					sVisibleLightCount++; -					glh::vec3f tc(c); -					mat.mult_matrix_vec(tc); -					  					setupSpotLight(gDeferredSpotLightProgram, drawablep);  					LLColor3 col = volume->getLightColor(); -					//vertex positions are encoded so the 3 bits of their vertex index  -					//correspond to their axis facing, with bit position 3,2,1 matching -					//axis facing x,y,z, bit set meaning positive facing, bit clear  -					//meaning negative facing -					mDeferredVB->getVertexStrider(vert); -					v[0].set(c[0]-s,c[1]-s,c[2]-s);  // 0 - 0000  -					v[1].set(c[0]-s,c[1]-s,c[2]+s);  // 1 - 0001 -					v[2].set(c[0]-s,c[1]+s,c[2]-s);  // 2 - 0010 -					v[3].set(c[0]-s,c[1]+s,c[2]+s);  // 3 - 0011 -																									    -					v[4].set(c[0]+s,c[1]-s,c[2]-s); // 4 - 0100 -					v[5].set(c[0]+s,c[1]-s,c[2]+s); // 5 - 0101 -					v[6].set(c[0]+s,c[1]+s,c[2]-s); // 6 - 0110 -					v[7].set(c[0]+s,c[1]+s,c[2]+s); // 7 - 0111 -					 -					gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); +					gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c);  					gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);  					gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);  					gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);  					gGL.syncMatrices(); -					mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); -					glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, -							GL_UNSIGNED_SHORT, get_box_fan_indices_ptr(camera, center)); +										 +					mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center));  				}  				gDeferredSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);  				unbindDeferredShader(gDeferredSpotLightProgram); @@ -7666,8 +7772,6 @@ void LLPipeline::renderDeferredLighting()  				LLVector4 light[max_count];  				LLVector4 col[max_count]; -//				glVertexPointer(2, GL_FLOAT, 0, vert); -  				F32 far_z = 0.f;  				while (!fullscreen_lights.empty()) @@ -8324,7 +8428,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera  	if (use_shader)  	{ -		gDeferredShadowProgram.bind(); +		gDeferredShadowCubeProgram.bind();  	}  	updateCull(shadow_cam, result); @@ -8341,17 +8445,10 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera  	stop_glerror();  	gGLLastMatrix = NULL; -	{ -		//LLGLDepthTest depth(GL_TRUE); -		//glClear(GL_DEPTH_BUFFER_BIT); -	} -  	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);  	stop_glerror(); -	//glCullFace(GL_FRONT); -  	LLVertexBuffer::unbind();  	{ @@ -8359,6 +8456,10 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera  		{ //occlusion program is general purpose depth-only no-textures  			gOcclusionProgram.bind();  		} +		else +		{ +			gDeferredShadowProgram.bind(); +		}  		gGL.diffuseColor4f(1,1,1,1);  		gGL.setColorMask(false, false); @@ -8408,7 +8509,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera  	//glCullFace(GL_BACK); -	gDeferredShadowProgram.bind(); +	gDeferredShadowCubeProgram.bind();  	gGLLastMatrix = NULL;  	gGL.loadMatrix(gGLModelView);  	doOcclusion(shadow_cam); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 5c623fc9f2..6ae482fa06 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -163,6 +163,7 @@ public:  	void		markRebuild(LLSpatialGroup* group, BOOL priority = FALSE);  	void        markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, BOOL priority = FALSE);  	void		markPartitionMove(LLDrawable* drawablep); +	void		markMeshDirty(LLSpatialGroup* group);  	//get the object between start and end that's closest to start.  	LLViewerObject* lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end, @@ -544,6 +545,9 @@ public:  	//utility buffer for rendering post effects, gets abused by renderDeferredLighting  	LLPointer<LLVertexBuffer> mDeferredVB; +	//utility buffer for rendering cubes, 8 vertices are corners of a cube [-1, 1] +	LLPointer<LLVertexBuffer> mCubeVB; +  	//sun shadow map  	LLRenderTarget			mShadow[6];  	std::vector<LLVector3>	mShadowFrustPoints[4]; @@ -595,6 +599,7 @@ public:  	BOOL					mVertexShadersEnabled;  	S32						mVertexShadersLoaded; // 0 = no, 1 = yes, -1 = failed +	U32						mTransformFeedbackPrimitives; //number of primitives expected to be generated by transform feedback  protected:  	BOOL					mRenderTypeEnabled[NUM_RENDER_TYPES];  	std::stack<std::string> mRenderTypeEnableStack; @@ -652,6 +657,9 @@ protected:  	LLSpatialGroup::sg_vector_t		mGroupQ1; //priority  	LLSpatialGroup::sg_vector_t		mGroupQ2; // non-priority +	LLSpatialGroup::sg_vector_t		mMeshDirtyGroup; //groups that need rebuildMesh called +	U32 mMeshDirtyQueryObject; +  	LLDrawable::drawable_list_t		mPartitionQ; //drawables that need to update their spatial partition radius   	bool mGroupQ2Locked; diff --git a/indra/newview/skins/default/xui/en/floater_my_inventory.xml b/indra/newview/skins/default/xui/en/floater_my_inventory.xml index 184f296255..ea44fd493e 100644 --- a/indra/newview/skins/default/xui/en/floater_my_inventory.xml +++ b/indra/newview/skins/default/xui/en/floater_my_inventory.xml @@ -6,7 +6,7 @@   height="570"   help_topic="sidebar_inventory"   min_width="333" - min_height="440" + min_height="560"   name="floater_my_inventory"   save_rect="true"   save_visibility="true" diff --git a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml index ffb8b842f0..2e29c61cb2 100644 --- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml @@ -134,6 +134,26 @@       top_delta="-25"       name="Pipette"       width="28" /> +   <check_box +     follows="left|bottom" +     height="20" +     initial_value="true" +     label="Live Preview" +     layout="topleft" +     left="4" +     name="apply_immediate_check" +     top="262" +     width="120" /> +   <text +     follows="left|bottom" +     height="20" +     layout="topleft" +     left="8" +     name="preview_disabled" +     top="266" +     value="Preview Disabled" +     visible="false" +     width="120" />      <filter_editor       follows="left|top|right"       height="23" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 126a32684c..91b4d38e97 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -7478,6 +7478,18 @@ You locally updated a [RESOLUTION] baked texture for '[BODYREGION]' after [TIME]    <notification     icon="alertmodal.tga" +   name="LivePreviewUnavailable" +   type="alert"> +    +We cannot display a preview of this texture because it is no-copy and/or no-transfer. +  <usetemplate +    ignoretext="Warn me that Live Preview mode is not available for no-copy and/or no-transfer textures" +    name="okignore" +    yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga"     name="ConfirmLeaveCall"     type="alert">  Are you sure you want to leave this call? diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml index 6ecb57b41d..14bd349480 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml @@ -48,7 +48,7 @@                        height="300"                        width="330" />               </layout_panel> -			 <layout_panel +			    <layout_panel                   width="330"                   layout="topleft"                   auto_resize="false" diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 56641ba01e..f0a63a009d 100644 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -1054,6 +1054,7 @@ class Linux_i686Manifest(LinuxManifest):              self.path("libopenjpeg.so*")              self.path("libdirectfb-1.4.so.5")              self.path("libfusion-1.4.so.5") +            self.path("libdirect-1.4.so.5.0.4")              self.path("libdirect-1.4.so.5")              self.path("libhunspell-1.3.so")              self.path("libhunspell-1.3.so.0") | 
