PageRenderTime 126ms CodeModel.GetById 28ms app.highlight 91ms RepoModel.GetById 2ms app.codeStats 0ms

/indra/llrender/llglslshader.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1016 lines | 849 code | 120 blank | 47 comment | 214 complexity | 67c34fbe454be8e626f7306073ab8eea MD5 | raw file
   1/** 
   2 * @file llglslshader.cpp
   3 * @brief GLSL helper functions and state.
   4 *
   5 * $LicenseInfo:firstyear=2005&license=viewerlgpl$
   6 * Second Life Viewer Source Code
   7 * Copyright (C) 2010, Linden Research, Inc.
   8 * 
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation;
  12 * version 2.1 of the License only.
  13 * 
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 * 
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  22 * 
  23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  24 * $/LicenseInfo$
  25 */
  26
  27#include "linden_common.h"
  28
  29#include "llglslshader.h"
  30
  31#include "llshadermgr.h"
  32#include "llfile.h"
  33#include "llrender.h"
  34#include "llvertexbuffer.h"
  35
  36#if LL_DARWIN
  37#include "OpenGL/OpenGL.h"
  38#endif
  39
  40#ifdef LL_RELEASE_FOR_DOWNLOAD
  41#define UNIFORM_ERRS LL_WARNS_ONCE("Shader")
  42#else
  43#define UNIFORM_ERRS LL_ERRS("Shader")
  44#endif
  45
  46// Lots of STL stuff in here, using namespace std to keep things more readable
  47using std::vector;
  48using std::pair;
  49using std::make_pair;
  50using std::string;
  51
  52GLhandleARB LLGLSLShader::sCurBoundShader = 0;
  53LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL;
  54S32 LLGLSLShader::sIndexedTextureChannels = 0;
  55bool LLGLSLShader::sNoFixedFunction = false;
  56
  57//UI shader -- declared here so llui_libtest will link properly
  58LLGLSLShader	gUIProgram;
  59LLGLSLShader	gSolidColorProgram;
  60
  61BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
  62{
  63	return v1 != v2;
  64}
  65
  66LLShaderFeatures::LLShaderFeatures()
  67: calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false),
  68hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false),
  69hasGamma(false), hasLighting(false), isAlphaLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false),
  70hasAlphaMask(false)
  71{
  72}
  73
  74//===============================
  75// LLGLSL Shader implementation
  76//===============================
  77LLGLSLShader::LLGLSLShader()
  78	: mProgramObject(0), mActiveTextureChannels(0), mShaderLevel(0), mShaderGroup(SG_DEFAULT), mUniformsDirty(FALSE)
  79{
  80
  81}
  82
  83void LLGLSLShader::unload()
  84{
  85	stop_glerror();
  86	mAttribute.clear();
  87	mTexture.clear();
  88	mUniform.clear();
  89	mShaderFiles.clear();
  90
  91	if (mProgramObject)
  92	{
  93		GLhandleARB obj[1024];
  94		GLsizei count;
  95
  96		glGetAttachedObjectsARB(mProgramObject, 1024, &count, obj);
  97		for (GLsizei i = 0; i < count; i++)
  98		{
  99			glDeleteObjectARB(obj[i]);
 100		}
 101
 102		glDeleteObjectARB(mProgramObject);
 103
 104		mProgramObject = 0;
 105	}
 106	
 107	//hack to make apple not complain
 108	glGetError();
 109	
 110	stop_glerror();
 111}
 112
 113BOOL LLGLSLShader::createShader(vector<string> * attributes,
 114								vector<string> * uniforms)
 115{
 116	//reloading, reset matrix hash values
 117	for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i)
 118	{
 119		mMatHash[i] = 0xFFFFFFFF;
 120	}
 121	mLightHash = 0xFFFFFFFF;
 122
 123	llassert_always(!mShaderFiles.empty());
 124	BOOL success = TRUE;
 125
 126	// Create program
 127	mProgramObject = glCreateProgramObjectARB();
 128	
 129	//compile new source
 130	vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin();
 131	for ( ; fileIter != mShaderFiles.end(); fileIter++ )
 132	{
 133		GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, mFeatures.mIndexedTextureChannels);
 134		LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL;
 135		if (shaderhandle > 0)
 136		{
 137			attachObject(shaderhandle);
 138		}
 139		else
 140		{
 141			success = FALSE;
 142		}
 143	}
 144
 145	// Attach existing objects
 146	if (!LLShaderMgr::instance()->attachShaderFeatures(this))
 147	{
 148		return FALSE;
 149	}
 150
 151	if (gGLManager.mGLVersion < 3.1f)
 152	{ //attachShaderFeatures may have set the number of indexed texture channels, so set to 1 again
 153		mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1);
 154	}
 155
 156	// Map attributes and uniforms
 157	if (success)
 158	{
 159		success = mapAttributes(attributes);
 160	}
 161	if (success)
 162	{
 163		success = mapUniforms(uniforms);
 164	}
 165	if( !success )
 166	{
 167		LL_WARNS("ShaderLoading") << "Failed to link shader: " << mName << LL_ENDL;
 168
 169		// Try again using a lower shader level;
 170		if (mShaderLevel > 0)
 171		{
 172			LL_WARNS("ShaderLoading") << "Failed to link using shader level " << mShaderLevel << " trying again using shader level " << (mShaderLevel - 1) << LL_ENDL;
 173			mShaderLevel--;
 174			return createShader(attributes,uniforms);
 175		}
 176	}
 177	else if (mFeatures.mIndexedTextureChannels > 0)
 178	{ //override texture channels for indexed texture rendering
 179		bind();
 180		S32 channel_count = mFeatures.mIndexedTextureChannels;
 181
 182		for (S32 i = 0; i < channel_count; i++)
 183		{
 184			uniform1i(llformat("tex%d", i), i);
 185		}
 186
 187		S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten
 188		for (U32 i = 0; i < mTexture.size(); i++)
 189		{
 190			if (mTexture[i] > -1 && mTexture[i] < channel_count)
 191			{
 192				llassert(cur_tex < gGLManager.mNumTextureImageUnits);
 193				uniform1i(i, cur_tex);
 194				mTexture[i] = cur_tex++;
 195			}
 196		}
 197		unbind();
 198	}
 199
 200	return success;
 201}
 202
 203BOOL LLGLSLShader::attachObject(std::string object)
 204{
 205	if (LLShaderMgr::instance()->mShaderObjects.count(object) > 0)
 206	{
 207		stop_glerror();
 208		glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mShaderObjects[object]);
 209		stop_glerror();
 210		return TRUE;
 211	}
 212	else
 213	{
 214		LL_WARNS("ShaderLoading") << "Attempting to attach shader object that hasn't been compiled: " << object << LL_ENDL;
 215		return FALSE;
 216	}
 217}
 218
 219void LLGLSLShader::attachObject(GLhandleARB object)
 220{
 221	if (object != 0)
 222	{
 223		stop_glerror();
 224		glAttachObjectARB(mProgramObject, object);
 225		stop_glerror();
 226	}
 227	else
 228	{
 229		LL_WARNS("ShaderLoading") << "Attempting to attach non existing shader object. " << LL_ENDL;
 230	}
 231}
 232
 233void LLGLSLShader::attachObjects(GLhandleARB* objects, S32 count)
 234{
 235	for (S32 i = 0; i < count; i++)
 236	{
 237		attachObject(objects[i]);
 238	}
 239}
 240
 241BOOL LLGLSLShader::mapAttributes(const vector<string> * attributes)
 242{
 243	//before linking, make sure reserved attributes always have consistent locations
 244	for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++)
 245	{
 246		const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str();
 247		glBindAttribLocationARB(mProgramObject, i, (const GLcharARB *) name);
 248	}
 249	
 250	//link the program
 251	BOOL res = link();
 252
 253	mAttribute.clear();
 254	U32 numAttributes = (attributes == NULL) ? 0 : attributes->size();
 255	mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, -1);
 256	
 257	if (res)
 258	{ //read back channel locations
 259
 260		//read back reserved channels first
 261		for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++)
 262		{
 263			const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str();
 264			S32 index = glGetAttribLocationARB(mProgramObject, (const GLcharARB *)name);
 265			if (index != -1)
 266			{
 267				mAttribute[i] = index;
 268				LL_DEBUGS("ShaderLoading") << "Attribute " << name << " assigned to channel " << index << LL_ENDL;
 269			}
 270		}
 271		if (attributes != NULL)
 272		{
 273			for (U32 i = 0; i < numAttributes; i++)
 274			{
 275				const char* name = (*attributes)[i].c_str();
 276				S32 index = glGetAttribLocationARB(mProgramObject, name);
 277				if (index != -1)
 278				{
 279					mAttribute[LLShaderMgr::instance()->mReservedAttribs.size() + i] = index;
 280					LL_DEBUGS("ShaderLoading") << "Attribute " << name << " assigned to channel " << index << LL_ENDL;
 281				}
 282			}
 283		}
 284
 285		return TRUE;
 286	}
 287	
 288	return FALSE;
 289}
 290
 291void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms)
 292{
 293	if (index == -1)
 294	{
 295		return;
 296	}
 297
 298	GLenum type;
 299	GLsizei length;
 300	GLint size;
 301	char name[1024];		/* Flawfinder: ignore */
 302	name[0] = 0;
 303
 304	glGetActiveUniformARB(mProgramObject, index, 1024, &length, &size, &type, (GLcharARB *)name);
 305	S32 location = glGetUniformLocationARB(mProgramObject, name);
 306	if (location != -1)
 307	{
 308		//chop off "[0]" so we can always access the first element
 309		//of an array by the array name
 310		char* is_array = strstr(name, "[0]");
 311		if (is_array)
 312		{
 313			is_array[0] = 0;
 314		}
 315
 316		mUniformMap[name] = location;
 317		LL_DEBUGS("ShaderLoading") << "Uniform " << name << " is at location " << location << LL_ENDL;
 318	
 319		//find the index of this uniform
 320		for (S32 i = 0; i < (S32) LLShaderMgr::instance()->mReservedUniforms.size(); i++)
 321		{
 322			if ( (mUniform[i] == -1)
 323				&& (LLShaderMgr::instance()->mReservedUniforms[i] == name))
 324			{
 325				//found it
 326				mUniform[i] = location;
 327				mTexture[i] = mapUniformTextureChannel(location, type);
 328				return;
 329			}
 330		}
 331
 332		if (uniforms != NULL)
 333		{
 334			for (U32 i = 0; i < uniforms->size(); i++)
 335			{
 336				if ( (mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] == -1)
 337					&& ((*uniforms)[i] == name))
 338				{
 339					//found it
 340					mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] = location;
 341					mTexture[i+LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type);
 342					return;
 343				}
 344			}
 345		}
 346	}
 347 }
 348
 349GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
 350{
 351	if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB ||
 352		type == GL_SAMPLER_2D_MULTISAMPLE)
 353	{	//this here is a texture
 354		glUniform1iARB(location, mActiveTextureChannels);
 355		LL_DEBUGS("ShaderLoading") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL;
 356		return mActiveTextureChannels++;
 357	}
 358	return -1;
 359}
 360
 361BOOL LLGLSLShader::mapUniforms(const vector<string> * uniforms)
 362{
 363	BOOL res = TRUE;
 364	
 365	mActiveTextureChannels = 0;
 366	mUniform.clear();
 367	mUniformMap.clear();
 368	mTexture.clear();
 369	mValue.clear();
 370	//initialize arrays
 371	U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size();
 372	mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1);
 373	mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1);
 374	
 375	bind();
 376
 377	//get the number of active uniforms
 378	GLint activeCount;
 379	glGetObjectParameterivARB(mProgramObject, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &activeCount);
 380
 381	for (S32 i = 0; i < activeCount; i++)
 382	{
 383		mapUniform(i, uniforms);
 384	}
 385
 386	unbind();
 387
 388	return res;
 389}
 390
 391BOOL LLGLSLShader::link(BOOL suppress_errors)
 392{
 393	return LLShaderMgr::instance()->linkProgramObject(mProgramObject, suppress_errors);
 394}
 395
 396void LLGLSLShader::bind()
 397{
 398	gGL.flush();
 399	if (gGLManager.mHasShaderObjects)
 400	{
 401		LLVertexBuffer::unbind();
 402		glUseProgramObjectARB(mProgramObject);
 403		sCurBoundShader = mProgramObject;
 404		sCurBoundShaderPtr = this;
 405		if (mUniformsDirty)
 406		{
 407			LLShaderMgr::instance()->updateShaderUniforms(this);
 408			mUniformsDirty = FALSE;
 409		}
 410	}
 411}
 412
 413void LLGLSLShader::unbind()
 414{
 415	gGL.flush();
 416	if (gGLManager.mHasShaderObjects)
 417	{
 418		stop_glerror();
 419		if (gGLManager.mIsNVIDIA)
 420		{
 421			for (U32 i = 0; i < mAttribute.size(); ++i)
 422			{
 423				vertexAttrib4f(i, 0,0,0,1);
 424				stop_glerror();
 425			}
 426		}
 427		LLVertexBuffer::unbind();
 428		glUseProgramObjectARB(0);
 429		sCurBoundShader = 0;
 430		sCurBoundShaderPtr = NULL;
 431		stop_glerror();
 432	}
 433}
 434
 435void LLGLSLShader::bindNoShader(void)
 436{
 437	LLVertexBuffer::unbind();
 438	if (gGLManager.mHasShaderObjects)
 439	{
 440		glUseProgramObjectARB(0);
 441		sCurBoundShader = 0;
 442		sCurBoundShaderPtr = NULL;
 443	}
 444}
 445
 446S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode)
 447{
 448	if (uniform < 0 || uniform >= (S32)mTexture.size())
 449	{
 450		UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
 451		return -1;
 452	}
 453	S32 index = mTexture[uniform];
 454	if (index != -1)
 455	{
 456		gGL.getTexUnit(index)->activate();
 457		gGL.getTexUnit(index)->enable(mode);
 458	}
 459	return index;
 460}
 461
 462S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode)
 463{
 464	if (uniform < 0 || uniform >= (S32)mTexture.size())
 465	{
 466		UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
 467		return -1;
 468	}
 469	S32 index = mTexture[uniform];
 470	if (index != -1 && gGL.getTexUnit(index)->getCurrType() != LLTexUnit::TT_NONE)
 471	{
 472		if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode)
 473		{
 474			if (gDebugSession)
 475			{
 476				gFailLog << "Texture channel " << index << " texture type corrupted." << std::endl;
 477				ll_fail("LLGLSLShader::disableTexture failed");
 478			}
 479			else
 480			{
 481				llerrs << "Texture channel " << index << " texture type corrupted." << llendl;
 482			}
 483		}
 484		gGL.getTexUnit(index)->disable();
 485	}
 486	return index;
 487}
 488
 489void LLGLSLShader::uniform1i(U32 index, GLint x)
 490{
 491	if (mProgramObject > 0)
 492	{	
 493		if (mUniform.size() <= index)
 494		{
 495			UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
 496			return;
 497		}
 498
 499		if (mUniform[index] >= 0)
 500		{
 501			std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
 502			if (iter == mValue.end() || iter->second.mV[0] != x)
 503			{
 504				glUniform1iARB(mUniform[index], x);
 505				mValue[mUniform[index]] = LLVector4(x,0.f,0.f,0.f);
 506			}
 507		}
 508	}
 509}
 510
 511void LLGLSLShader::uniform1f(U32 index, GLfloat x)
 512{
 513	if (mProgramObject > 0)
 514	{	
 515		if (mUniform.size() <= index)
 516		{
 517			UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
 518			return;
 519		}
 520
 521		if (mUniform[index] >= 0)
 522		{
 523			std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
 524			if (iter == mValue.end() || iter->second.mV[0] != x)
 525			{
 526				glUniform1fARB(mUniform[index], x);
 527				mValue[mUniform[index]] = LLVector4(x,0.f,0.f,0.f);
 528			}
 529		}
 530	}
 531}
 532
 533void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y)
 534{
 535	if (mProgramObject > 0)
 536	{	
 537		if (mUniform.size() <= index)
 538		{
 539			UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
 540			return;
 541		}
 542
 543		if (mUniform[index] >= 0)
 544		{
 545			std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
 546			LLVector4 vec(x,y,0.f,0.f);
 547			if (iter == mValue.end() || shouldChange(iter->second,vec))
 548			{
 549				glUniform2fARB(mUniform[index], x, y);
 550				mValue[mUniform[index]] = vec;
 551			}
 552		}
 553	}
 554}
 555
 556void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z)
 557{
 558	if (mProgramObject > 0)
 559	{	
 560		if (mUniform.size() <= index)
 561		{
 562			UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
 563			return;
 564		}
 565
 566		if (mUniform[index] >= 0)
 567		{
 568			std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
 569			LLVector4 vec(x,y,z,0.f);
 570			if (iter == mValue.end() || shouldChange(iter->second,vec))
 571			{
 572				glUniform3fARB(mUniform[index], x, y, z);
 573				mValue[mUniform[index]] = vec;
 574			}
 575		}
 576	}
 577}
 578
 579void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
 580{
 581	if (mProgramObject > 0)
 582	{	
 583		if (mUniform.size() <= index)
 584		{
 585			UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
 586			return;
 587		}
 588
 589		if (mUniform[index] >= 0)
 590		{
 591			std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
 592			LLVector4 vec(x,y,z,w);
 593			if (iter == mValue.end() || shouldChange(iter->second,vec))
 594			{
 595				glUniform4fARB(mUniform[index], x, y, z, w);
 596				mValue[mUniform[index]] = vec;
 597			}
 598		}
 599	}
 600}
 601
 602void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v)
 603{
 604	if (mProgramObject > 0)
 605	{	
 606		if (mUniform.size() <= index)
 607		{
 608			UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
 609			return;
 610		}
 611
 612		if (mUniform[index] >= 0)
 613		{
 614			std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
 615			LLVector4 vec(v[0],0.f,0.f,0.f);
 616			if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
 617			{
 618				glUniform1ivARB(mUniform[index], count, v);
 619				mValue[mUniform[index]] = vec;
 620			}
 621		}
 622	}
 623}
 624
 625void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v)
 626{
 627	if (mProgramObject > 0)
 628	{	
 629		if (mUniform.size() <= index)
 630		{
 631			UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
 632			return;
 633		}
 634
 635		if (mUniform[index] >= 0)
 636		{
 637			std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
 638			LLVector4 vec(v[0],0.f,0.f,0.f);
 639			if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
 640			{
 641				glUniform1fvARB(mUniform[index], count, v);
 642				mValue[mUniform[index]] = vec;
 643			}
 644		}
 645	}
 646}
 647
 648void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v)
 649{
 650	if (mProgramObject > 0)
 651	{	
 652		if (mUniform.size() <= index)
 653		{
 654			UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
 655			return;
 656		}
 657
 658		if (mUniform[index] >= 0)
 659		{
 660			std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
 661			LLVector4 vec(v[0],v[1],0.f,0.f);
 662			if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
 663			{
 664				glUniform2fvARB(mUniform[index], count, v);
 665				mValue[mUniform[index]] = vec;
 666			}
 667		}
 668	}
 669}
 670
 671void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v)
 672{
 673	if (mProgramObject > 0)
 674	{	
 675		if (mUniform.size() <= index)
 676		{
 677			UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
 678			return;
 679		}
 680
 681		if (mUniform[index] >= 0)
 682		{
 683			std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
 684			LLVector4 vec(v[0],v[1],v[2],0.f);
 685			if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
 686			{
 687				glUniform3fvARB(mUniform[index], count, v);
 688				mValue[mUniform[index]] = vec;
 689			}
 690		}
 691	}
 692}
 693
 694void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v)
 695{
 696	if (mProgramObject > 0)
 697	{	
 698		if (mUniform.size() <= index)
 699		{
 700			UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
 701			return;
 702		}
 703
 704		if (mUniform[index] >= 0)
 705		{
 706			std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
 707			LLVector4 vec(v[0],v[1],v[2],v[3]);
 708			if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
 709			{
 710				glUniform4fvARB(mUniform[index], count, v);
 711				mValue[mUniform[index]] = vec;
 712			}
 713		}
 714	}
 715}
 716
 717void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v)
 718{
 719	if (mProgramObject > 0)
 720	{	
 721		if (mUniform.size() <= index)
 722		{
 723			UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
 724			return;
 725		}
 726
 727		if (mUniform[index] >= 0)
 728		{
 729			glUniformMatrix2fvARB(mUniform[index], count, transpose, v);
 730		}
 731	}
 732}
 733
 734void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v)
 735{
 736	if (mProgramObject > 0)
 737	{	
 738		if (mUniform.size() <= index)
 739		{
 740			UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
 741			return;
 742		}
 743
 744		if (mUniform[index] >= 0)
 745		{
 746			glUniformMatrix3fvARB(mUniform[index], count, transpose, v);
 747		}
 748	}
 749}
 750
 751void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v)
 752{
 753	if (mProgramObject > 0)
 754	{	
 755		if (mUniform.size() <= index)
 756		{
 757			UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
 758			return;
 759		}
 760
 761		if (mUniform[index] >= 0)
 762		{
 763			glUniformMatrix4fvARB(mUniform[index], count, transpose, v);
 764		}
 765	}
 766}
 767
 768GLint LLGLSLShader::getUniformLocation(const string& uniform)
 769{
 770	GLint ret = -1;
 771	if (mProgramObject > 0)
 772	{
 773		std::map<string, GLint>::iterator iter = mUniformMap.find(uniform);
 774		if (iter != mUniformMap.end())
 775		{
 776			if (gDebugGL)
 777			{
 778				stop_glerror();
 779				if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.c_str()))
 780				{
 781					llerrs << "Uniform does not match." << llendl;
 782				}
 783				stop_glerror();
 784			}
 785			ret = iter->second;
 786		}
 787	}
 788
 789	return ret;
 790}
 791
 792GLint LLGLSLShader::getUniformLocation(U32 index)
 793{
 794	GLint ret = -1;
 795	if (mProgramObject > 0)
 796	{
 797		llassert(index < mUniform.size());
 798		return mUniform[index];
 799	}
 800
 801	return ret;
 802}
 803
 804GLint LLGLSLShader::getAttribLocation(U32 attrib)
 805{
 806	if (attrib < mAttribute.size())
 807	{
 808		return mAttribute[attrib];
 809	}
 810	else
 811	{
 812		return -1;
 813	}
 814}
 815
 816void LLGLSLShader::uniform1i(const string& uniform, GLint v)
 817{
 818	GLint location = getUniformLocation(uniform);
 819				
 820	if (location >= 0)
 821	{
 822		std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
 823		LLVector4 vec(v,0.f,0.f,0.f);
 824		if (iter == mValue.end() || shouldChange(iter->second,vec))
 825		{
 826			glUniform1iARB(location, v);
 827			mValue[location] = vec;
 828		}
 829	}
 830}
 831
 832void LLGLSLShader::uniform1f(const string& uniform, GLfloat v)
 833{
 834	GLint location = getUniformLocation(uniform);
 835				
 836	if (location >= 0)
 837	{
 838		std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
 839		LLVector4 vec(v,0.f,0.f,0.f);
 840		if (iter == mValue.end() || shouldChange(iter->second,vec))
 841		{
 842			glUniform1fARB(location, v);
 843			mValue[location] = vec;
 844		}
 845	}
 846}
 847
 848void LLGLSLShader::uniform2f(const string& uniform, GLfloat x, GLfloat y)
 849{
 850	GLint location = getUniformLocation(uniform);
 851				
 852	if (location >= 0)
 853	{
 854		std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
 855		LLVector4 vec(x,y,0.f,0.f);
 856		if (iter == mValue.end() || shouldChange(iter->second,vec))
 857		{
 858			glUniform2fARB(location, x,y);
 859			mValue[location] = vec;
 860		}
 861	}
 862
 863}
 864
 865void LLGLSLShader::uniform3f(const string& uniform, GLfloat x, GLfloat y, GLfloat z)
 866{
 867	GLint location = getUniformLocation(uniform);
 868				
 869	if (location >= 0)
 870	{
 871		std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
 872		LLVector4 vec(x,y,z,0.f);
 873		if (iter == mValue.end() || shouldChange(iter->second,vec))
 874		{
 875			glUniform3fARB(location, x,y,z);
 876			mValue[location] = vec;
 877		}
 878	}
 879}
 880
 881void LLGLSLShader::uniform4f(const string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
 882{
 883	GLint location = getUniformLocation(uniform);
 884
 885	if (location >= 0)
 886	{
 887		std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
 888		LLVector4 vec(x,y,z,w);
 889		if (iter == mValue.end() || shouldChange(iter->second,vec))
 890		{
 891			glUniform4fARB(location, x,y,z,w);
 892			mValue[location] = vec;
 893		}
 894	}
 895}
 896
 897void LLGLSLShader::uniform1fv(const string& uniform, U32 count, const GLfloat* v)
 898{
 899	GLint location = getUniformLocation(uniform);
 900
 901	if (location >= 0)
 902	{
 903		std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
 904		LLVector4 vec(v[0],0.f,0.f,0.f);
 905		if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
 906		{
 907			glUniform1fvARB(location, count, v);
 908			mValue[location] = vec;
 909		}
 910	}
 911}
 912
 913void LLGLSLShader::uniform2fv(const string& uniform, U32 count, const GLfloat* v)
 914{
 915	GLint location = getUniformLocation(uniform);
 916				
 917	if (location >= 0)
 918	{
 919		std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
 920		LLVector4 vec(v[0],v[1],0.f,0.f);
 921		if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
 922		{
 923			glUniform2fvARB(location, count, v);
 924			mValue[location] = vec;
 925		}
 926	}
 927}
 928
 929void LLGLSLShader::uniform3fv(const string& uniform, U32 count, const GLfloat* v)
 930{
 931	GLint location = getUniformLocation(uniform);
 932				
 933	if (location >= 0)
 934	{
 935		std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
 936		LLVector4 vec(v[0],v[1],v[2],0.f);
 937		if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
 938		{
 939			glUniform3fvARB(location, count, v);
 940			mValue[location] = vec;
 941		}
 942	}
 943}
 944
 945void LLGLSLShader::uniform4fv(const string& uniform, U32 count, const GLfloat* v)
 946{
 947	GLint location = getUniformLocation(uniform);
 948
 949	if (location >= 0)
 950	{
 951		LLVector4 vec(v);
 952		std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
 953		if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
 954		{
 955			stop_glerror();
 956			glUniform4fvARB(location, count, v);
 957			stop_glerror();
 958			mValue[location] = vec;
 959		}
 960	}
 961}
 962
 963void LLGLSLShader::uniformMatrix2fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v)
 964{
 965	GLint location = getUniformLocation(uniform);
 966				
 967	if (location >= 0)
 968	{
 969		glUniformMatrix2fvARB(location, count, transpose, v);
 970	}
 971}
 972
 973void LLGLSLShader::uniformMatrix3fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v)
 974{
 975	GLint location = getUniformLocation(uniform);
 976				
 977	if (location >= 0)
 978	{
 979		glUniformMatrix3fvARB(location, count, transpose, v);
 980	}
 981}
 982
 983void LLGLSLShader::uniformMatrix4fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v)
 984{
 985	GLint location = getUniformLocation(uniform);
 986				
 987	if (location >= 0)
 988	{
 989		stop_glerror();
 990		glUniformMatrix4fvARB(location, count, transpose, v);
 991		stop_glerror();
 992	}
 993}
 994
 995
 996void LLGLSLShader::vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
 997{
 998	if (mAttribute[index] > 0)
 999	{
1000		glVertexAttrib4fARB(mAttribute[index], x, y, z, w);
1001	}
1002}
1003
1004void LLGLSLShader::vertexAttrib4fv(U32 index, GLfloat* v)
1005{
1006	if (mAttribute[index] > 0)
1007	{
1008		glVertexAttrib4fvARB(mAttribute[index], v);
1009	}
1010}
1011
1012void LLGLSLShader::setMinimumAlpha(F32 minimum)
1013{
1014	gGL.flush();
1015	uniform1f(LLShaderMgr::MINIMUM_ALPHA, minimum);
1016}