PageRenderTime 194ms CodeModel.GetById 36ms app.highlight 146ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llrender/llrender.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2297 lines | 1888 code | 327 blank | 82 comment | 367 complexity | 73ffb20d02bfba812f86640f5dd72536 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1 /** 
   2 * @file llrender.cpp
   3 * @brief LLRender implementation
   4 *
   5 * $LicenseInfo:firstyear=2001&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 "llrender.h"
  30
  31#include "llvertexbuffer.h"
  32#include "llcubemap.h"
  33#include "llglslshader.h"
  34#include "llimagegl.h"
  35#include "llrendertarget.h"
  36#include "lltexture.h"
  37#include "llshadermgr.h"
  38
  39LLRender gGL;
  40
  41// Handy copies of last good GL matrices
  42F32	gGLModelView[16];
  43F32	gGLLastModelView[16];
  44F32 gGLLastProjection[16];
  45F32 gGLProjection[16];
  46S32	gGLViewport[4];
  47
  48U32 LLRender::sUICalls = 0;
  49U32 LLRender::sUIVerts = 0;
  50U32 LLTexUnit::sWhiteTexture = 0;
  51bool LLRender::sGLCoreProfile = false;
  52
  53static const U32 LL_NUM_TEXTURE_LAYERS = 32; 
  54static const U32 LL_NUM_LIGHT_UNITS = 8;
  55
  56static GLenum sGLTextureType[] =
  57{
  58	GL_TEXTURE_2D,
  59	GL_TEXTURE_RECTANGLE_ARB,
  60	GL_TEXTURE_CUBE_MAP_ARB,
  61	GL_TEXTURE_2D_MULTISAMPLE
  62};
  63
  64static GLint sGLAddressMode[] =
  65{	
  66	GL_REPEAT,
  67	GL_MIRRORED_REPEAT,
  68	GL_CLAMP_TO_EDGE
  69};
  70
  71static GLenum sGLCompareFunc[] =
  72{
  73	GL_NEVER,
  74	GL_ALWAYS,
  75	GL_LESS,
  76	GL_LEQUAL,
  77	GL_EQUAL,
  78	GL_NOTEQUAL,
  79	GL_GEQUAL,
  80	GL_GREATER
  81};
  82
  83const U32 immediate_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD0;
  84
  85static GLenum sGLBlendFactor[] =
  86{
  87	GL_ONE,
  88	GL_ZERO,
  89	GL_DST_COLOR,
  90	GL_SRC_COLOR,
  91	GL_ONE_MINUS_DST_COLOR,
  92	GL_ONE_MINUS_SRC_COLOR,
  93	GL_DST_ALPHA,
  94	GL_SRC_ALPHA,
  95	GL_ONE_MINUS_DST_ALPHA,
  96	GL_ONE_MINUS_SRC_ALPHA,
  97
  98	GL_ZERO // 'BF_UNDEF'
  99};
 100
 101LLTexUnit::LLTexUnit(S32 index)
 102: mCurrTexType(TT_NONE), mCurrBlendType(TB_MULT), 
 103mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT),
 104mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR),
 105mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA),
 106mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0),
 107mHasMipMaps(false)
 108{
 109	llassert_always(index < (S32)LL_NUM_TEXTURE_LAYERS);
 110	mIndex = index;
 111}
 112
 113//static
 114U32 LLTexUnit::getInternalType(eTextureType type)
 115{
 116	return sGLTextureType[type];
 117}
 118
 119void LLTexUnit::refreshState(void)
 120{
 121	// We set dirty to true so that the tex unit knows to ignore caching
 122	// and we reset the cached tex unit state
 123
 124	gGL.flush();
 125	
 126	glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
 127
 128	//
 129	// Per apple spec, don't call glEnable/glDisable when index exceeds max texture units
 130	// http://www.mailinglistarchive.com/html/mac-opengl@lists.apple.com/2008-07/msg00653.html
 131	//
 132	bool enableDisable = !LLGLSLShader::sNoFixedFunction && 
 133		(mIndex < gGLManager.mNumTextureUnits) && mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE;
 134		
 135	if (mCurrTexType != TT_NONE)
 136	{
 137		if (enableDisable)
 138		{
 139			glEnable(sGLTextureType[mCurrTexType]);
 140		}
 141		
 142		glBindTexture(sGLTextureType[mCurrTexType], mCurrTexture);
 143	}
 144	else
 145	{
 146		if (enableDisable)
 147		{
 148			glDisable(GL_TEXTURE_2D);
 149		}
 150		
 151		glBindTexture(GL_TEXTURE_2D, 0);	
 152	}
 153
 154	if (mCurrBlendType != TB_COMBINE)
 155	{
 156		setTextureBlendType(mCurrBlendType);
 157	}
 158	else
 159	{
 160		setTextureCombiner(mCurrColorOp, mCurrColorSrc1, mCurrColorSrc2, false);
 161		setTextureCombiner(mCurrAlphaOp, mCurrAlphaSrc1, mCurrAlphaSrc2, true);
 162	}
 163}
 164
 165void LLTexUnit::activate(void)
 166{
 167	if (mIndex < 0) return;
 168
 169	if ((S32)gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty)
 170	{
 171		gGL.flush();
 172		glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
 173		gGL.mCurrTextureUnitIndex = mIndex;
 174	}
 175}
 176
 177void LLTexUnit::enable(eTextureType type)
 178{
 179	if (mIndex < 0) return;
 180
 181	if ( (mCurrTexType != type || gGL.mDirty) && (type != TT_NONE) )
 182	{
 183		stop_glerror();
 184		activate();
 185		stop_glerror();
 186		if (mCurrTexType != TT_NONE && !gGL.mDirty)
 187		{
 188			disable(); // Force a disable of a previous texture type if it's enabled.
 189			stop_glerror();
 190		}
 191		mCurrTexType = type;
 192
 193		gGL.flush();
 194		if (!LLGLSLShader::sNoFixedFunction && 
 195			type != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
 196			mIndex < gGLManager.mNumTextureUnits)
 197		{
 198			stop_glerror();
 199			glEnable(sGLTextureType[type]);
 200			stop_glerror();
 201		}
 202	}
 203}
 204
 205void LLTexUnit::disable(void)
 206{
 207	if (mIndex < 0) return;
 208
 209	if (mCurrTexType != TT_NONE)
 210	{
 211		activate();
 212		unbind(mCurrTexType);
 213		gGL.flush();
 214		if (!LLGLSLShader::sNoFixedFunction &&
 215			mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
 216			mIndex < gGLManager.mNumTextureUnits)
 217		{
 218			glDisable(sGLTextureType[mCurrTexType]);
 219		}
 220		
 221		mCurrTexType = TT_NONE;
 222	}
 223}
 224
 225bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
 226{
 227	stop_glerror();
 228	if (mIndex < 0) return false;
 229
 230	gGL.flush();
 231
 232	LLImageGL* gl_tex = NULL ;
 233	if (texture == NULL || !(gl_tex = texture->getGLTexture()))
 234	{
 235		llwarns << "NULL LLTexUnit::bind texture" << llendl;
 236		return false;
 237	}
 238
 239	if (!gl_tex->getTexName()) //if texture does not exist
 240	{
 241		//if deleted, will re-generate it immediately
 242		texture->forceImmediateUpdate() ;
 243
 244		gl_tex->forceUpdateBindStats() ;
 245		return texture->bindDefaultImage(mIndex);
 246	}
 247
 248	//in audit, replace the selected texture by the default one.
 249	if(gAuditTexture && for_rendering && LLImageGL::sCurTexPickSize > 0)
 250	{
 251		if(texture->getWidth() * texture->getHeight() == LLImageGL::sCurTexPickSize)
 252		{
 253			gl_tex->updateBindStats(gl_tex->mTextureMemory);
 254			return bind(LLImageGL::sHighlightTexturep.get());
 255		}
 256	}
 257	if ((mCurrTexture != gl_tex->getTexName()) || forceBind)
 258	{
 259		activate();
 260		enable(gl_tex->getTarget());
 261		mCurrTexture = gl_tex->getTexName();
 262		glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture);
 263		if(gl_tex->updateBindStats(gl_tex->mTextureMemory))
 264		{
 265			texture->setActive() ;
 266			texture->updateBindStatsForTester() ;
 267		}
 268		mHasMipMaps = gl_tex->mHasMipMaps;
 269		if (gl_tex->mTexOptionsDirty)
 270		{
 271			gl_tex->mTexOptionsDirty = false;
 272			setTextureAddressMode(gl_tex->mAddressMode);
 273			setTextureFilteringOption(gl_tex->mFilterOption);
 274		}
 275	}
 276	return true;
 277}
 278
 279bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind)
 280{
 281	stop_glerror();
 282	if (mIndex < 0) return false;
 283
 284	if(!texture)
 285	{
 286		llwarns << "NULL LLTexUnit::bind texture" << llendl;
 287		return false;
 288	}
 289
 290	if(!texture->getTexName())
 291	{
 292		if(LLImageGL::sDefaultGLTexture && LLImageGL::sDefaultGLTexture->getTexName())
 293		{
 294			return bind(LLImageGL::sDefaultGLTexture) ;
 295		}
 296		stop_glerror();
 297		return false ;
 298	}
 299
 300	if ((mCurrTexture != texture->getTexName()) || forceBind)
 301	{
 302		gGL.flush();
 303		stop_glerror();
 304		activate();
 305		stop_glerror();
 306		enable(texture->getTarget());
 307		stop_glerror();
 308		mCurrTexture = texture->getTexName();
 309		glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture);
 310		stop_glerror();
 311		texture->updateBindStats(texture->mTextureMemory);		
 312		mHasMipMaps = texture->mHasMipMaps;
 313		if (texture->mTexOptionsDirty)
 314		{
 315			stop_glerror();
 316			texture->mTexOptionsDirty = false;
 317			setTextureAddressMode(texture->mAddressMode);
 318			setTextureFilteringOption(texture->mFilterOption);
 319			stop_glerror();
 320		}
 321	}
 322
 323	stop_glerror();
 324
 325	return true;
 326}
 327
 328bool LLTexUnit::bind(LLCubeMap* cubeMap)
 329{
 330	if (mIndex < 0) return false;
 331
 332	gGL.flush();
 333
 334	if (cubeMap == NULL)
 335	{
 336		llwarns << "NULL LLTexUnit::bind cubemap" << llendl;
 337		return false;
 338	}
 339
 340	if (mCurrTexture != cubeMap->mImages[0]->getTexName())
 341	{
 342		if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
 343		{
 344			activate();
 345			enable(LLTexUnit::TT_CUBE_MAP);
 346			mCurrTexture = cubeMap->mImages[0]->getTexName();
 347			glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mCurrTexture);
 348			mHasMipMaps = cubeMap->mImages[0]->mHasMipMaps;
 349			cubeMap->mImages[0]->updateBindStats(cubeMap->mImages[0]->mTextureMemory);
 350			if (cubeMap->mImages[0]->mTexOptionsDirty)
 351			{
 352				cubeMap->mImages[0]->mTexOptionsDirty = false;
 353				setTextureAddressMode(cubeMap->mImages[0]->mAddressMode);
 354				setTextureFilteringOption(cubeMap->mImages[0]->mFilterOption);
 355			}
 356			return true;
 357		}
 358		else
 359		{
 360			llwarns << "Using cube map without extension!" << llendl;
 361			return false;
 362		}
 363	}
 364	return true;
 365}
 366
 367// LLRenderTarget is unavailible on the mapserver since it uses FBOs.
 368#if !LL_MESA_HEADLESS
 369bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth)
 370{
 371	if (mIndex < 0) return false;
 372
 373	gGL.flush();
 374
 375	if (bindDepth)
 376	{
 377		if (renderTarget->hasStencil())
 378		{
 379			llerrs << "Cannot bind a render buffer for sampling.  Allocate render target without a stencil buffer if sampling of depth buffer is required." << llendl;
 380		}
 381
 382		bindManual(renderTarget->getUsage(), renderTarget->getDepth());
 383	}
 384	else
 385	{
 386		bindManual(renderTarget->getUsage(), renderTarget->getTexture());
 387	}
 388
 389	return true;
 390}
 391#endif // LL_MESA_HEADLESS
 392
 393bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips)
 394{
 395	if (mIndex < 0)  
 396	{
 397		return false;
 398	}
 399	
 400	if(mCurrTexture != texture)
 401	{
 402		gGL.flush();
 403		
 404		activate();
 405		enable(type);
 406		mCurrTexture = texture;
 407		glBindTexture(sGLTextureType[type], texture);
 408		mHasMipMaps = hasMips;
 409	}
 410	return true;
 411}
 412
 413void LLTexUnit::unbind(eTextureType type)
 414{
 415	stop_glerror();
 416
 417	if (mIndex < 0) return;
 418
 419	// Disabled caching of binding state.
 420	if (mCurrTexType == type)
 421	{
 422		gGL.flush();
 423
 424		activate();
 425		mCurrTexture = 0;
 426		if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE)
 427		{
 428			glBindTexture(sGLTextureType[type], sWhiteTexture);
 429		}
 430		else
 431		{
 432			glBindTexture(sGLTextureType[type], 0);
 433		}
 434		stop_glerror();
 435	}
 436}
 437
 438void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode)
 439{
 440	if (mIndex < 0 || mCurrTexture == 0) return;
 441
 442	gGL.flush();
 443
 444	activate();
 445
 446	glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]);
 447	glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]);
 448	if (mCurrTexType == TT_CUBE_MAP)
 449	{
 450		glTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]);
 451	}
 452}
 453
 454void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option)
 455{
 456	if (mIndex < 0 || mCurrTexture == 0 || mCurrTexType == LLTexUnit::TT_MULTISAMPLE_TEXTURE) return;
 457
 458	gGL.flush();
 459
 460	if (option == TFO_POINT)
 461	{
 462		glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 463	}
 464	else
 465	{
 466		glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 467	}
 468
 469	if (option >= TFO_TRILINEAR && mHasMipMaps)
 470	{
 471		glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
 472	} 
 473	else if (option >= TFO_BILINEAR)
 474	{
 475		glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 476	}
 477	else
 478	{
 479		glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 480	}
 481
 482	if (gGLManager.mHasAnisotropic)
 483	{
 484		if (LLImageGL::sGlobalUseAnisotropic && option == TFO_ANISOTROPIC)
 485		{
 486			if (gGL.mMaxAnisotropy < 1.f)
 487			{
 488				glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gGL.mMaxAnisotropy);
 489
 490				llinfos << "gGL.mMaxAnisotropy: " << gGL.mMaxAnisotropy << llendl ;
 491				gGL.mMaxAnisotropy = llmax(1.f, gGL.mMaxAnisotropy) ;
 492			}
 493			glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, gGL.mMaxAnisotropy);
 494		}
 495		else
 496		{
 497			glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f);
 498		}
 499	}
 500}
 501
 502void LLTexUnit::setTextureBlendType(eTextureBlendType type)
 503{
 504	if (LLGLSLShader::sNoFixedFunction)
 505	{ //texture blend type means nothing when using shaders
 506		return;
 507	}
 508
 509	if (mIndex < 0) return;
 510
 511	// Do nothing if it's already correctly set.
 512	if (mCurrBlendType == type && !gGL.mDirty)
 513	{
 514		return;
 515	}
 516
 517	gGL.flush();
 518
 519	activate();
 520	mCurrBlendType = type;
 521	S32 scale_amount = 1;
 522	switch (type) 
 523	{
 524		case TB_REPLACE:
 525			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 526			break;
 527		case TB_ADD:
 528			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
 529			break;
 530		case TB_MULT:
 531			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 532			break;
 533		case TB_MULT_X2:
 534			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 535			scale_amount = 2;
 536			break;
 537		case TB_ALPHA_BLEND:
 538			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
 539			break;
 540		case TB_COMBINE:
 541			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
 542			break;
 543		default:
 544			llerrs << "Unknown Texture Blend Type: " << type << llendl;
 545			break;
 546	}
 547	setColorScale(scale_amount);
 548	setAlphaScale(1);
 549}
 550
 551GLint LLTexUnit::getTextureSource(eTextureBlendSrc src)
 552{
 553	switch(src)
 554	{
 555		// All four cases should return the same value.
 556		case TBS_PREV_COLOR:
 557		case TBS_PREV_ALPHA:
 558		case TBS_ONE_MINUS_PREV_COLOR:
 559		case TBS_ONE_MINUS_PREV_ALPHA:
 560			return GL_PREVIOUS_ARB;
 561
 562		// All four cases should return the same value.
 563		case TBS_TEX_COLOR:
 564		case TBS_TEX_ALPHA:
 565		case TBS_ONE_MINUS_TEX_COLOR:
 566		case TBS_ONE_MINUS_TEX_ALPHA:
 567			return GL_TEXTURE;
 568
 569		// All four cases should return the same value.
 570		case TBS_VERT_COLOR:
 571		case TBS_VERT_ALPHA:
 572		case TBS_ONE_MINUS_VERT_COLOR:
 573		case TBS_ONE_MINUS_VERT_ALPHA:
 574			return GL_PRIMARY_COLOR_ARB;
 575
 576		// All four cases should return the same value.
 577		case TBS_CONST_COLOR:
 578		case TBS_CONST_ALPHA:
 579		case TBS_ONE_MINUS_CONST_COLOR:
 580		case TBS_ONE_MINUS_CONST_ALPHA:
 581			return GL_CONSTANT_ARB;
 582
 583		default:
 584			llwarns << "Unknown eTextureBlendSrc: " << src << ".  Using Vertex Color instead." << llendl;
 585			return GL_PRIMARY_COLOR_ARB;
 586	}
 587}
 588
 589GLint LLTexUnit::getTextureSourceType(eTextureBlendSrc src, bool isAlpha)
 590{
 591	switch(src)
 592	{
 593		// All four cases should return the same value.
 594		case TBS_PREV_COLOR:
 595		case TBS_TEX_COLOR:
 596		case TBS_VERT_COLOR:
 597		case TBS_CONST_COLOR:
 598			return (isAlpha) ? GL_SRC_ALPHA: GL_SRC_COLOR;
 599
 600		// All four cases should return the same value.
 601		case TBS_PREV_ALPHA:
 602		case TBS_TEX_ALPHA:
 603		case TBS_VERT_ALPHA:
 604		case TBS_CONST_ALPHA:
 605			return GL_SRC_ALPHA;
 606
 607		// All four cases should return the same value.
 608		case TBS_ONE_MINUS_PREV_COLOR:
 609		case TBS_ONE_MINUS_TEX_COLOR:
 610		case TBS_ONE_MINUS_VERT_COLOR:
 611		case TBS_ONE_MINUS_CONST_COLOR:
 612			return (isAlpha) ? GL_ONE_MINUS_SRC_ALPHA : GL_ONE_MINUS_SRC_COLOR;
 613
 614		// All four cases should return the same value.
 615		case TBS_ONE_MINUS_PREV_ALPHA:
 616		case TBS_ONE_MINUS_TEX_ALPHA:
 617		case TBS_ONE_MINUS_VERT_ALPHA:
 618		case TBS_ONE_MINUS_CONST_ALPHA:
 619			return GL_ONE_MINUS_SRC_ALPHA;
 620
 621		default:
 622			llwarns << "Unknown eTextureBlendSrc: " << src << ".  Using Source Color or Alpha instead." << llendl;
 623			return (isAlpha) ? GL_SRC_ALPHA: GL_SRC_COLOR;
 624	}
 625}
 626
 627void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2, bool isAlpha)
 628{
 629	if (LLGLSLShader::sNoFixedFunction)
 630	{ //register combiners do nothing when not using fixed function
 631		return;
 632	}	
 633
 634	if (mIndex < 0) return;
 635
 636	activate();
 637	if (mCurrBlendType != TB_COMBINE || gGL.mDirty)
 638	{
 639		mCurrBlendType = TB_COMBINE;
 640		gGL.flush();
 641		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
 642	}
 643
 644	// We want an early out, because this function does a LOT of stuff.
 645	if ( ( (isAlpha && (mCurrAlphaOp == op) && (mCurrAlphaSrc1 == src1) && (mCurrAlphaSrc2 == src2))
 646			|| (!isAlpha && (mCurrColorOp == op) && (mCurrColorSrc1 == src1) && (mCurrColorSrc2 == src2)) ) && !gGL.mDirty)
 647	{
 648		return;
 649	}
 650
 651	gGL.flush();
 652
 653	// Get the gl source enums according to the eTextureBlendSrc sources passed in
 654	GLint source1 = getTextureSource(src1);
 655	GLint source2 = getTextureSource(src2);
 656	// Get the gl operand enums according to the eTextureBlendSrc sources passed in
 657	GLint operand1 = getTextureSourceType(src1, isAlpha);
 658	GLint operand2 = getTextureSourceType(src2, isAlpha);
 659	// Default the scale amount to 1
 660	S32 scale_amount = 1;
 661	GLenum comb_enum, src0_enum, src1_enum, src2_enum, operand0_enum, operand1_enum, operand2_enum;
 662	
 663	if (isAlpha)
 664	{
 665		// Set enums to ALPHA ones
 666		comb_enum = GL_COMBINE_ALPHA_ARB;
 667		src0_enum = GL_SOURCE0_ALPHA_ARB;
 668		src1_enum = GL_SOURCE1_ALPHA_ARB;
 669		src2_enum = GL_SOURCE2_ALPHA_ARB;
 670		operand0_enum = GL_OPERAND0_ALPHA_ARB;
 671		operand1_enum = GL_OPERAND1_ALPHA_ARB;
 672		operand2_enum = GL_OPERAND2_ALPHA_ARB;
 673
 674		// cache current combiner
 675		mCurrAlphaOp = op;
 676		mCurrAlphaSrc1 = src1;
 677		mCurrAlphaSrc2 = src2;
 678	}
 679	else 
 680	{
 681		// Set enums to RGB ones
 682		comb_enum = GL_COMBINE_RGB_ARB;
 683		src0_enum = GL_SOURCE0_RGB_ARB;
 684		src1_enum = GL_SOURCE1_RGB_ARB;
 685		src2_enum = GL_SOURCE2_RGB_ARB;
 686		operand0_enum = GL_OPERAND0_RGB_ARB;
 687		operand1_enum = GL_OPERAND1_RGB_ARB;
 688		operand2_enum = GL_OPERAND2_RGB_ARB;
 689
 690		// cache current combiner
 691		mCurrColorOp = op;
 692		mCurrColorSrc1 = src1;
 693		mCurrColorSrc2 = src2;
 694	}
 695
 696	switch(op)
 697	{
 698		case TBO_REPLACE:
 699			// Slightly special syntax (no second sources), just set all and return.
 700			glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_REPLACE);
 701			glTexEnvi(GL_TEXTURE_ENV, src0_enum, source1);
 702			glTexEnvi(GL_TEXTURE_ENV, operand0_enum, operand1);
 703			(isAlpha) ? setAlphaScale(1) : setColorScale(1);
 704			return;
 705
 706		case TBO_MULT:
 707			glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_MODULATE);
 708			break;
 709
 710		case TBO_MULT_X2:
 711			glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_MODULATE);
 712			scale_amount = 2;
 713			break;
 714
 715		case TBO_MULT_X4:
 716			glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_MODULATE);
 717			scale_amount = 4;
 718			break;
 719
 720		case TBO_ADD:
 721			glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_ADD);
 722			break;
 723
 724		case TBO_ADD_SIGNED:
 725			glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_ADD_SIGNED_ARB);
 726			break;
 727
 728		case TBO_SUBTRACT:
 729			glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_SUBTRACT_ARB);
 730			break;
 731
 732		case TBO_LERP_VERT_ALPHA:
 733			glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_INTERPOLATE);
 734			glTexEnvi(GL_TEXTURE_ENV, src2_enum, GL_PRIMARY_COLOR_ARB);
 735			glTexEnvi(GL_TEXTURE_ENV, operand2_enum, GL_SRC_ALPHA);
 736			break;
 737
 738		case TBO_LERP_TEX_ALPHA:
 739			glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_INTERPOLATE);
 740			glTexEnvi(GL_TEXTURE_ENV, src2_enum, GL_TEXTURE);
 741			glTexEnvi(GL_TEXTURE_ENV, operand2_enum, GL_SRC_ALPHA);
 742			break;
 743
 744		case TBO_LERP_PREV_ALPHA:
 745			glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_INTERPOLATE);
 746			glTexEnvi(GL_TEXTURE_ENV, src2_enum, GL_PREVIOUS_ARB);
 747			glTexEnvi(GL_TEXTURE_ENV, operand2_enum, GL_SRC_ALPHA);
 748			break;
 749
 750		case TBO_LERP_CONST_ALPHA:
 751			glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_INTERPOLATE);
 752			glTexEnvi(GL_TEXTURE_ENV, src2_enum, GL_CONSTANT_ARB);
 753			glTexEnvi(GL_TEXTURE_ENV, operand2_enum, GL_SRC_ALPHA);
 754			break;
 755
 756		case TBO_LERP_VERT_COLOR:
 757			glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_INTERPOLATE);
 758			glTexEnvi(GL_TEXTURE_ENV, src2_enum, GL_PRIMARY_COLOR_ARB);
 759			glTexEnvi(GL_TEXTURE_ENV, operand2_enum, (isAlpha) ? GL_SRC_ALPHA : GL_SRC_COLOR);
 760			break;
 761
 762		default:
 763			llwarns << "Unknown eTextureBlendOp: " << op << ".  Setting op to replace." << llendl;
 764			// Slightly special syntax (no second sources), just set all and return.
 765			glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_REPLACE);
 766			glTexEnvi(GL_TEXTURE_ENV, src0_enum, source1);
 767			glTexEnvi(GL_TEXTURE_ENV, operand0_enum, operand1);
 768			(isAlpha) ? setAlphaScale(1) : setColorScale(1);
 769			return;
 770	}
 771
 772	// Set sources, operands, and scale accordingly
 773	glTexEnvi(GL_TEXTURE_ENV, src0_enum, source1);
 774	glTexEnvi(GL_TEXTURE_ENV, operand0_enum, operand1);
 775	glTexEnvi(GL_TEXTURE_ENV, src1_enum, source2);
 776	glTexEnvi(GL_TEXTURE_ENV, operand1_enum, operand2);
 777	(isAlpha) ? setAlphaScale(scale_amount) : setColorScale(scale_amount);
 778}
 779
 780void LLTexUnit::setColorScale(S32 scale)
 781{
 782	if (mCurrColorScale != scale || gGL.mDirty)
 783	{
 784		mCurrColorScale = scale;
 785		gGL.flush();
 786		glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, scale );
 787	}
 788}
 789
 790void LLTexUnit::setAlphaScale(S32 scale)
 791{
 792	if (mCurrAlphaScale != scale || gGL.mDirty)
 793	{
 794		mCurrAlphaScale = scale;
 795		gGL.flush();
 796		glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale );
 797	}
 798}
 799
 800// Useful for debugging that you've manually assigned a texture operation to the correct 
 801// texture unit based on the currently set active texture in opengl.
 802void LLTexUnit::debugTextureUnit(void)
 803{
 804	if (mIndex < 0) return;
 805
 806	GLint activeTexture;
 807	glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &activeTexture);
 808	if ((GL_TEXTURE0_ARB + mIndex) != activeTexture)
 809	{
 810		U32 set_unit = (activeTexture - GL_TEXTURE0_ARB);
 811		llwarns << "Incorrect Texture Unit!  Expected: " << set_unit << " Actual: " << mIndex << llendl;
 812	}
 813}
 814
 815LLLightState::LLLightState(S32 index)
 816: mIndex(index),
 817  mEnabled(false),
 818  mConstantAtten(1.f),
 819  mLinearAtten(0.f),
 820  mQuadraticAtten(0.f),
 821  mSpotExponent(0.f),
 822  mSpotCutoff(180.f)
 823{
 824	if (mIndex == 0)
 825	{
 826		mDiffuse.set(1,1,1,1);
 827		mSpecular.set(1,1,1,1);
 828	}
 829
 830	mAmbient.set(0,0,0,1);
 831	mPosition.set(0,0,1,0);
 832	mSpotDirection.set(0,0,-1);
 833}
 834
 835void LLLightState::enable()
 836{
 837	if (!mEnabled)
 838	{
 839		if (!LLGLSLShader::sNoFixedFunction)
 840		{
 841			glEnable(GL_LIGHT0+mIndex);
 842		}
 843		mEnabled = true;
 844	}
 845}
 846
 847void LLLightState::disable()
 848{
 849	if (mEnabled)
 850	{
 851		if (!LLGLSLShader::sNoFixedFunction)
 852		{
 853			glDisable(GL_LIGHT0+mIndex);
 854		}
 855		mEnabled = false;
 856	}
 857}
 858
 859void LLLightState::setDiffuse(const LLColor4& diffuse)
 860{
 861	if (mDiffuse != diffuse)
 862	{
 863		++gGL.mLightHash;
 864		mDiffuse = diffuse;
 865		if (!LLGLSLShader::sNoFixedFunction)
 866		{
 867			glLightfv(GL_LIGHT0+mIndex, GL_DIFFUSE, mDiffuse.mV);
 868		}
 869	}
 870}
 871
 872void LLLightState::setAmbient(const LLColor4& ambient)
 873{
 874	if (mAmbient != ambient)
 875	{
 876		++gGL.mLightHash;
 877		mAmbient = ambient;
 878		if (!LLGLSLShader::sNoFixedFunction)
 879		{
 880			glLightfv(GL_LIGHT0+mIndex, GL_AMBIENT, mAmbient.mV);
 881		}
 882	}
 883}
 884
 885void LLLightState::setSpecular(const LLColor4& specular)
 886{
 887	if (mSpecular != specular)
 888	{
 889		++gGL.mLightHash;
 890		mSpecular = specular;
 891		if (!LLGLSLShader::sNoFixedFunction)
 892		{
 893			glLightfv(GL_LIGHT0+mIndex, GL_SPECULAR, mSpecular.mV);
 894		}
 895	}
 896}
 897
 898void LLLightState::setPosition(const LLVector4& position)
 899{
 900	//always set position because modelview matrix may have changed
 901	++gGL.mLightHash;
 902	mPosition = position;
 903	if (!LLGLSLShader::sNoFixedFunction)
 904	{
 905		glLightfv(GL_LIGHT0+mIndex, GL_POSITION, mPosition.mV);
 906	}
 907	else
 908	{ //transform position by current modelview matrix
 909		glh::vec4f pos(position.mV);
 910
 911		const glh::matrix4f& mat = gGL.getModelviewMatrix();
 912		mat.mult_matrix_vec(pos);
 913
 914		mPosition.set(pos.v);
 915	}
 916
 917}
 918
 919void LLLightState::setConstantAttenuation(const F32& atten)
 920{
 921	if (mConstantAtten != atten)
 922	{
 923		mConstantAtten = atten;
 924		++gGL.mLightHash;
 925		if (!LLGLSLShader::sNoFixedFunction)
 926		{
 927			glLightf(GL_LIGHT0+mIndex, GL_CONSTANT_ATTENUATION, atten);
 928		}
 929	}
 930}
 931
 932void LLLightState::setLinearAttenuation(const F32& atten)
 933{
 934	if (mLinearAtten != atten)
 935	{
 936		++gGL.mLightHash;
 937		mLinearAtten = atten;
 938		if (!LLGLSLShader::sNoFixedFunction)
 939		{
 940			glLightf(GL_LIGHT0+mIndex, GL_LINEAR_ATTENUATION, atten);
 941		}
 942	}
 943}
 944
 945void LLLightState::setQuadraticAttenuation(const F32& atten)
 946{
 947	if (mQuadraticAtten != atten)
 948	{
 949		++gGL.mLightHash;
 950		mQuadraticAtten = atten;
 951		if (!LLGLSLShader::sNoFixedFunction)
 952		{
 953			glLightf(GL_LIGHT0+mIndex, GL_QUADRATIC_ATTENUATION, atten);
 954		}
 955	}
 956}
 957
 958void LLLightState::setSpotExponent(const F32& exponent)
 959{
 960	if (mSpotExponent != exponent)
 961	{
 962		++gGL.mLightHash;
 963		mSpotExponent = exponent;
 964		if (!LLGLSLShader::sNoFixedFunction)
 965		{
 966			glLightf(GL_LIGHT0+mIndex, GL_SPOT_EXPONENT, exponent);
 967		}
 968	}
 969}
 970
 971void LLLightState::setSpotCutoff(const F32& cutoff)
 972{
 973	if (mSpotCutoff != cutoff)
 974	{
 975		++gGL.mLightHash;
 976		mSpotCutoff = cutoff;
 977		if (!LLGLSLShader::sNoFixedFunction)
 978		{
 979			glLightf(GL_LIGHT0+mIndex, GL_SPOT_CUTOFF, cutoff);
 980		}
 981	}
 982}
 983
 984void LLLightState::setSpotDirection(const LLVector3& direction)
 985{
 986	//always set direction because modelview matrix may have changed
 987	++gGL.mLightHash;
 988	mSpotDirection = direction;
 989	if (!LLGLSLShader::sNoFixedFunction)
 990	{
 991		glLightfv(GL_LIGHT0+mIndex, GL_SPOT_DIRECTION, direction.mV);
 992	}
 993	else
 994	{ //transform direction by current modelview matrix
 995		glh::vec3f dir(direction.mV);
 996
 997		const glh::matrix4f& mat = gGL.getModelviewMatrix();
 998		mat.mult_matrix_dir(dir);
 999
1000		mSpotDirection.set(direction);
1001	}
1002}
1003
1004LLRender::LLRender()
1005  : mDirty(false),
1006    mCount(0),
1007	mQuadCycle(0),
1008    mMode(LLRender::TRIANGLES),
1009    mCurrTextureUnitIndex(0),
1010    mMaxAnisotropy(0.f) 
1011{	
1012	mTexUnits.reserve(LL_NUM_TEXTURE_LAYERS);
1013	for (U32 i = 0; i < LL_NUM_TEXTURE_LAYERS; i++)
1014	{
1015		mTexUnits.push_back(new LLTexUnit(i));
1016	}
1017	mDummyTexUnit = new LLTexUnit(-1);
1018
1019	for (U32 i = 0; i < LL_NUM_LIGHT_UNITS; ++i)
1020	{
1021		mLightState.push_back(new LLLightState(i));
1022	}
1023
1024	for (U32 i = 0; i < 4; i++)
1025	{
1026		mCurrColorMask[i] = true;
1027	}
1028
1029	mCurrAlphaFunc = CF_DEFAULT;
1030	mCurrAlphaFuncVal = 0.01f;
1031	mCurrBlendColorSFactor = BF_UNDEF;
1032	mCurrBlendAlphaSFactor = BF_UNDEF;
1033	mCurrBlendColorDFactor = BF_UNDEF;
1034	mCurrBlendAlphaDFactor = BF_UNDEF;
1035
1036	mMatrixMode = LLRender::MM_MODELVIEW;
1037	
1038	for (U32 i = 0; i < NUM_MATRIX_MODES; ++i)
1039	{
1040		mMatIdx[i] = 0;
1041		mMatHash[i] = 0;
1042		mCurMatHash[i] = 0xFFFFFFFF;
1043	}
1044
1045	mLightHash = 0;
1046}
1047
1048LLRender::~LLRender()
1049{
1050	shutdown();
1051}
1052
1053void LLRender::init()
1054{
1055	llassert_always(mBuffer.isNull()) ;
1056	stop_glerror();
1057	mBuffer = new LLVertexBuffer(immediate_mask, 0);
1058	mBuffer->allocateBuffer(4096, 0, TRUE);
1059	mBuffer->getVertexStrider(mVerticesp);
1060	mBuffer->getTexCoord0Strider(mTexcoordsp);
1061	mBuffer->getColorStrider(mColorsp);
1062	stop_glerror();
1063}
1064
1065void LLRender::shutdown()
1066{
1067	for (U32 i = 0; i < mTexUnits.size(); i++)
1068	{
1069		delete mTexUnits[i];
1070	}
1071	mTexUnits.clear();
1072	delete mDummyTexUnit;
1073	mDummyTexUnit = NULL;
1074
1075	for (U32 i = 0; i < mLightState.size(); ++i)
1076	{
1077		delete mLightState[i];
1078	}
1079	mLightState.clear();
1080	mBuffer = NULL ;
1081}
1082
1083void LLRender::refreshState(void)
1084{
1085	mDirty = true;
1086
1087	U32 active_unit = mCurrTextureUnitIndex;
1088
1089	for (U32 i = 0; i < mTexUnits.size(); i++)
1090	{
1091		mTexUnits[i]->refreshState();
1092	}
1093	
1094	mTexUnits[active_unit]->activate();
1095
1096	setColorMask(mCurrColorMask[0], mCurrColorMask[1], mCurrColorMask[2], mCurrColorMask[3]);
1097	
1098	setAlphaRejectSettings(mCurrAlphaFunc, mCurrAlphaFuncVal);
1099
1100	mDirty = false;
1101}
1102
1103void LLRender::syncLightState()
1104{
1105	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
1106
1107	if (!shader)
1108	{
1109		return;
1110	}
1111
1112	if (shader->mLightHash != mLightHash)
1113	{
1114		shader->mLightHash = mLightHash;
1115
1116		LLVector4 position[8];
1117		LLVector3 direction[8];
1118		LLVector3 attenuation[8];
1119		LLVector3 diffuse[8];
1120
1121		for (U32 i = 0; i < 8; i++)
1122		{
1123			LLLightState* light = mLightState[i];
1124
1125			position[i] = light->mPosition;
1126			direction[i] = light->mSpotDirection;
1127			attenuation[i].set(light->mLinearAtten, light->mQuadraticAtten, light->mSpecular.mV[3]);
1128			diffuse[i].set(light->mDiffuse.mV);
1129		}
1130
1131		shader->uniform4fv(LLShaderMgr::LIGHT_POSITION, 8, position[0].mV);
1132		shader->uniform3fv(LLShaderMgr::LIGHT_DIRECTION, 8, direction[0].mV);
1133		shader->uniform3fv(LLShaderMgr::LIGHT_ATTENUATION, 8, attenuation[0].mV);
1134		shader->uniform3fv(LLShaderMgr::LIGHT_DIFFUSE, 8, diffuse[0].mV);
1135		shader->uniform4fv(LLShaderMgr::LIGHT_AMBIENT, 1, mAmbientLightColor.mV);
1136		//HACK -- duplicate sunlight color for compatibility with drivers that can't deal with multiple shader objects referencing the same uniform
1137		shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, 1, diffuse[0].mV);
1138	}
1139}
1140
1141void LLRender::syncMatrices()
1142{
1143	stop_glerror();
1144
1145	U32 name[] = 
1146	{
1147		LLShaderMgr::MODELVIEW_MATRIX,
1148		LLShaderMgr::PROJECTION_MATRIX,
1149		LLShaderMgr::TEXTURE_MATRIX0,
1150		LLShaderMgr::TEXTURE_MATRIX1,
1151		LLShaderMgr::TEXTURE_MATRIX2,
1152		LLShaderMgr::TEXTURE_MATRIX3,
1153	};
1154
1155	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
1156
1157	static glh::matrix4f cached_mvp;
1158	static U32 cached_mvp_mdv_hash = 0xFFFFFFFF;
1159	static U32 cached_mvp_proj_hash = 0xFFFFFFFF;
1160	
1161	static glh::matrix4f cached_normal;
1162	static U32 cached_normal_hash = 0xFFFFFFFF;
1163
1164	if (shader)
1165	{
1166		llassert(shader);
1167
1168		bool mvp_done = false;
1169
1170		U32 i = MM_MODELVIEW;
1171		if (mMatHash[i] != shader->mMatHash[i])
1172		{ //update modelview, normal, and MVP
1173			glh::matrix4f& mat = mMatrix[i][mMatIdx[i]];
1174
1175			shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mat.m);
1176			shader->mMatHash[i] = mMatHash[i];
1177
1178			//update normal matrix
1179			S32 loc = shader->getUniformLocation(LLShaderMgr::NORMAL_MATRIX);
1180			if (loc > -1)
1181			{
1182				if (cached_normal_hash != mMatHash[i])
1183				{
1184					cached_normal = mat.inverse().transpose();
1185					cached_normal_hash = mMatHash[i];
1186				}
1187
1188				glh::matrix4f& norm = cached_normal;
1189
1190				F32 norm_mat[] = 
1191				{
1192					norm.m[0], norm.m[1], norm.m[2],
1193					norm.m[4], norm.m[5], norm.m[6],
1194					norm.m[8], norm.m[9], norm.m[10] 
1195				};
1196
1197				shader->uniformMatrix3fv(LLShaderMgr::NORMAL_MATRIX, 1, GL_FALSE, norm_mat);
1198			}
1199
1200			//update MVP matrix
1201			mvp_done = true;
1202			loc = shader->getUniformLocation(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX);
1203			if (loc > -1)
1204			{
1205				U32 proj = MM_PROJECTION;
1206
1207				if (cached_mvp_mdv_hash != mMatHash[i] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION])
1208				{
1209					cached_mvp = mat;
1210					cached_mvp.mult_left(mMatrix[proj][mMatIdx[proj]]);
1211					cached_mvp_mdv_hash = mMatHash[i];
1212					cached_mvp_proj_hash = mMatHash[MM_PROJECTION];
1213				}
1214
1215				shader->uniformMatrix4fv(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX, 1, GL_FALSE, cached_mvp.m);
1216			}
1217		}
1218
1219
1220		i = MM_PROJECTION;
1221		if (mMatHash[i] != shader->mMatHash[i])
1222		{ //update projection matrix, normal, and MVP
1223			glh::matrix4f& mat = mMatrix[i][mMatIdx[i]];
1224
1225			shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mat.m);
1226			shader->mMatHash[i] = mMatHash[i];
1227
1228			if (!mvp_done)
1229			{
1230				//update MVP matrix
1231				S32 loc = shader->getUniformLocation(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX);
1232				if (loc > -1)
1233				{
1234					if (cached_mvp_mdv_hash != mMatHash[i] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION])
1235					{
1236						U32 mdv = MM_MODELVIEW;
1237						cached_mvp = mat;
1238						cached_mvp.mult_right(mMatrix[mdv][mMatIdx[mdv]]);
1239						cached_mvp_mdv_hash = mMatHash[MM_MODELVIEW];
1240						cached_mvp_proj_hash = mMatHash[MM_PROJECTION];
1241					}
1242									
1243					shader->uniformMatrix4fv(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX, 1, GL_FALSE, cached_mvp.m);
1244				}
1245			}
1246		}
1247
1248		for (i = MM_TEXTURE0; i < NUM_MATRIX_MODES; ++i)
1249		{
1250			if (mMatHash[i] != shader->mMatHash[i])
1251			{
1252				shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mMatrix[i][mMatIdx[i]].m);
1253				shader->mMatHash[i] = mMatHash[i];
1254			}
1255		}
1256
1257
1258		if (shader->mFeatures.hasLighting || shader->mFeatures.calculatesLighting)
1259		{ //also sync light state
1260			syncLightState();
1261		}
1262	}
1263	else if (!LLGLSLShader::sNoFixedFunction)
1264	{
1265		GLenum mode[] = 
1266		{
1267			GL_MODELVIEW,
1268			GL_PROJECTION,
1269			GL_TEXTURE,
1270			GL_TEXTURE,
1271			GL_TEXTURE,
1272			GL_TEXTURE,
1273		};
1274
1275		for (U32 i = 0; i < 2; ++i)
1276		{
1277			if (mMatHash[i] != mCurMatHash[i])
1278			{
1279				glMatrixMode(mode[i]);
1280				glLoadMatrixf(mMatrix[i][mMatIdx[i]].m);
1281				mCurMatHash[i] = mMatHash[i];
1282			}
1283		}
1284
1285		for (U32 i = 2; i < NUM_MATRIX_MODES; ++i)
1286		{
1287			if (mMatHash[i] != mCurMatHash[i])
1288			{
1289				gGL.getTexUnit(i-2)->activate();
1290				glMatrixMode(mode[i]);
1291				glLoadMatrixf(mMatrix[i][mMatIdx[i]].m);
1292				mCurMatHash[i] = mMatHash[i];
1293			}
1294		}
1295	}
1296
1297	stop_glerror();
1298}
1299
1300void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z)
1301{
1302	flush();
1303
1304	{
1305		glh::matrix4f trans_mat(1,0,0,x,
1306								0,1,0,y,
1307								0,0,1,z,
1308								0,0,0,1);
1309	
1310		mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(trans_mat);
1311		mMatHash[mMatrixMode]++;
1312	}
1313}
1314
1315void LLRender::scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z)
1316{
1317	flush();
1318	
1319	{
1320		glh::matrix4f scale_mat(x,0,0,0,
1321								0,y,0,0,
1322								0,0,z,0,
1323								0,0,0,1);
1324	
1325		mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(scale_mat);
1326		mMatHash[mMatrixMode]++;
1327	}
1328}
1329
1330void LLRender::ortho(F32 left, F32 right, F32 bottom, F32 top, F32 zNear, F32 zFar)
1331{
1332	flush();
1333
1334	{
1335
1336		glh::matrix4f ortho_mat(2.f/(right-left),0,0,	-(right+left)/(right-left),
1337								0,2.f/(top-bottom),0,	-(top+bottom)/(top-bottom),
1338								0,0,-2.f/(zFar-zNear),	-(zFar+zNear)/(zFar-zNear),
1339								0,0,0,1);
1340	
1341		mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(ortho_mat);
1342		mMatHash[mMatrixMode]++;
1343	}
1344}
1345
1346void LLRender::rotatef(const GLfloat& a, const GLfloat& x, const GLfloat& y, const GLfloat& z)
1347{
1348	flush();
1349
1350	{
1351		F32 r = a * DEG_TO_RAD;
1352
1353		F32 c = cosf(r);
1354		F32 s = sinf(r);
1355
1356		F32 ic = 1.f-c;
1357
1358		glh::matrix4f rot_mat(x*x*ic+c,		x*y*ic-z*s,		x*z*ic+y*s,		0,
1359							  x*y*ic+z*s,	y*y*ic+c,		y*z*ic-x*s,		0,
1360							  x*z*ic-y*s,	y*z*ic+x*s,		z*z*ic+c,		0,
1361							  0,0,0,1);
1362	
1363		mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(rot_mat);
1364		mMatHash[mMatrixMode]++;
1365	}
1366}
1367
1368void LLRender::pushMatrix()
1369{
1370	flush();
1371	
1372	{
1373		if (mMatIdx[mMatrixMode] < LL_MATRIX_STACK_DEPTH-1)
1374		{
1375			mMatrix[mMatrixMode][mMatIdx[mMatrixMode]+1] = mMatrix[mMatrixMode][mMatIdx[mMatrixMode]];
1376			++mMatIdx[mMatrixMode];
1377		}
1378		else
1379		{
1380			llwarns << "Matrix stack overflow." << llendl;
1381		}
1382	}
1383}
1384
1385void LLRender::popMatrix()
1386{
1387	flush();
1388	{
1389		if (mMatIdx[mMatrixMode] > 0)
1390		{
1391			--mMatIdx[mMatrixMode];
1392			mMatHash[mMatrixMode]++;
1393		}
1394		else
1395		{
1396			llwarns << "Matrix stack underflow." << llendl;
1397		}
1398	}
1399}
1400
1401void LLRender::loadMatrix(const GLfloat* m)
1402{
1403	flush();
1404	{
1405		mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].set_value((GLfloat*) m);
1406		mMatHash[mMatrixMode]++;
1407	}
1408}
1409
1410void LLRender::multMatrix(const GLfloat* m)
1411{
1412	flush();
1413	{
1414		glh::matrix4f mat((GLfloat*) m);
1415	
1416		mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(mat);
1417		mMatHash[mMatrixMode]++;
1418	}
1419}
1420
1421void LLRender::matrixMode(U32 mode)
1422{
1423	if (mode == MM_TEXTURE)
1424	{
1425		mode = MM_TEXTURE0 + gGL.getCurrentTexUnitIndex();
1426	}
1427
1428	llassert(mode < NUM_MATRIX_MODES);
1429	mMatrixMode = mode;
1430}
1431
1432void LLRender::loadIdentity()
1433{
1434	flush();
1435
1436	{
1437		llassert_always(mMatrixMode < NUM_MATRIX_MODES) ;
1438
1439		mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].make_identity();
1440		mMatHash[mMatrixMode]++;
1441	}
1442}
1443
1444const glh::matrix4f& LLRender::getModelviewMatrix()
1445{
1446	return mMatrix[MM_MODELVIEW][mMatIdx[MM_MODELVIEW]];
1447}
1448
1449const glh::matrix4f& LLRender::getProjectionMatrix()
1450{
1451	return mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]];
1452}
1453
1454void LLRender::translateUI(F32 x, F32 y, F32 z)
1455{
1456	if (mUIOffset.empty())
1457	{
1458		llerrs << "Need to push a UI translation frame before offsetting" << llendl;
1459	}
1460
1461	mUIOffset.back().mV[0] += x;
1462	mUIOffset.back().mV[1] += y;
1463	mUIOffset.back().mV[2] += z;
1464}
1465
1466void LLRender::scaleUI(F32 x, F32 y, F32 z)
1467{
1468	if (mUIScale.empty())
1469	{
1470		llerrs << "Need to push a UI transformation frame before scaling." << llendl;
1471	}
1472
1473	mUIScale.back().scaleVec(LLVector3(x,y,z));
1474}
1475
1476void LLRender::pushUIMatrix()
1477{
1478	if (mUIOffset.empty())
1479	{
1480		mUIOffset.push_back(LLVector3(0,0,0));
1481	}
1482	else
1483	{
1484		mUIOffset.push_back(mUIOffset.back());
1485	}
1486	
1487	if (mUIScale.empty())
1488	{
1489		mUIScale.push_back(LLVector3(1,1,1));
1490	}
1491	else
1492	{
1493		mUIScale.push_back(mUIScale.back());
1494	}
1495}
1496
1497void LLRender::popUIMatrix()
1498{
1499	if (mUIOffset.empty())
1500	{
1501		llerrs << "UI offset stack blown." << llendl;
1502	}
1503	mUIOffset.pop_back();
1504	mUIScale.pop_back();
1505}
1506
1507LLVector3 LLRender::getUITranslation()
1508{
1509	if (mUIOffset.empty())
1510	{
1511		return LLVector3(0,0,0);
1512	}
1513	return mUIOffset.back();
1514}
1515
1516LLVector3 LLRender::getUIScale()
1517{
1518	if (mUIScale.empty())
1519	{
1520		return LLVector3(1,1,1);
1521	}
1522	return mUIScale.back();
1523}
1524
1525
1526void LLRender::loadUIIdentity()
1527{
1528	if (mUIOffset.empty())
1529	{
1530		llerrs << "Need to push UI translation frame before clearing offset." << llendl;
1531	}
1532	mUIOffset.back().setVec(0,0,0);
1533	mUIScale.back().setVec(1,1,1);
1534}
1535
1536void LLRender::setColorMask(bool writeColor, bool writeAlpha)
1537{
1538	setColorMask(writeColor, writeColor, writeColor, writeAlpha);
1539}
1540
1541void LLRender::setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha)
1542{
1543	flush();
1544
1545	if (mCurrColorMask[0] != writeColorR ||
1546		mCurrColorMask[1] != writeColorG ||
1547		mCurrColorMask[2] != writeColorB ||
1548		mCurrColorMask[3] != writeAlpha)
1549	{
1550		mCurrColorMask[0] = writeColorR;
1551		mCurrColorMask[1] = writeColorG;
1552		mCurrColorMask[2] = writeColorB;
1553		mCurrColorMask[3] = writeAlpha;
1554
1555		glColorMask(writeColorR ? GL_TRUE : GL_FALSE, 
1556					writeColorG ? GL_TRUE : GL_FALSE,
1557					writeColorB ? GL_TRUE : GL_FALSE,
1558					writeAlpha ? GL_TRUE : GL_FALSE);
1559	}
1560}
1561
1562void LLRender::setSceneBlendType(eBlendType type)
1563{
1564	switch (type) 
1565	{
1566		case BT_ALPHA:
1567			blendFunc(BF_SOURCE_ALPHA, BF_ONE_MINUS_SOURCE_ALPHA);
1568			break;
1569		case BT_ADD:
1570			blendFunc(BF_ONE, BF_ONE);
1571			break;
1572		case BT_ADD_WITH_ALPHA:
1573			blendFunc(BF_SOURCE_ALPHA, BF_ONE);
1574			break;
1575		case BT_MULT:
1576			blendFunc(BF_DEST_COLOR, BF_ZERO);
1577			break;
1578		case BT_MULT_ALPHA:
1579			blendFunc(BF_DEST_ALPHA, BF_ZERO);
1580			break;
1581		case BT_MULT_X2:
1582			blendFunc(BF_DEST_COLOR, BF_SOURCE_COLOR);
1583			break;
1584		case BT_REPLACE:
1585			blendFunc(BF_ONE, BF_ZERO);
1586			break;
1587		default:
1588			llerrs << "Unknown Scene Blend Type: " << type << llendl;
1589			break;
1590	}
1591}
1592
1593void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value)
1594{
1595	flush();
1596
1597	if (LLGLSLShader::sNoFixedFunction)
1598	{ //glAlphaFunc is deprecated in OpenGL 3.3
1599		return;
1600	}
1601
1602	if (mCurrAlphaFunc != func ||
1603		mCurrAlphaFuncVal != value)
1604	{
1605		mCurrAlphaFunc = func;
1606		mCurrAlphaFuncVal = value;
1607		if (func == CF_DEFAULT)
1608		{
1609			glAlphaFunc(GL_GREATER, 0.01f);
1610		} 
1611		else
1612		{
1613			glAlphaFunc(sGLCompareFunc[func], value);
1614		}
1615	}
1616
1617	if (gDebugGL)
1618	{ //make sure cached state is correct
1619		GLint cur_func = 0;
1620		glGetIntegerv(GL_ALPHA_TEST_FUNC, &cur_func);
1621
1622		if (func == CF_DEFAULT)
1623		{
1624			func = CF_GREATER;
1625		}
1626
1627		if (cur_func != sGLCompareFunc[func])
1628		{
1629			llerrs << "Alpha test function corrupted!" << llendl;
1630		}
1631
1632		F32 ref = 0.f;
1633		glGetFloatv(GL_ALPHA_TEST_REF, &ref);
1634
1635		if (ref != value)
1636		{
1637			llerrs << "Alpha test value corrupted!" << llendl;
1638		}
1639	}
1640}
1641
1642void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor)
1643{
1644	llassert(sfactor < BF_UNDEF);
1645	llassert(dfactor < BF_UNDEF);
1646	if (mCurrBlendColorSFactor != sfactor || mCurrBlendColorDFactor != dfactor ||
1647	    mCurrBlendAlphaSFactor != sfactor || mCurrBlendAlphaDFactor != dfactor)
1648	{
1649		mCurrBlendColorSFactor = sfactor;
1650		mCurrBlendAlphaSFactor = sfactor;
1651		mCurrBlendColorDFactor = dfactor;
1652		mCurrBlendAlphaDFactor = dfactor;
1653		flush();
1654		glBlendFunc(sGLBlendFactor[sfactor], sGLBlendFactor[dfactor]);
1655	}
1656}
1657
1658void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor,
1659			 eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor)
1660{
1661	llassert(color_sfactor < BF_UNDEF);
1662	llassert(color_dfactor < BF_UNDEF);
1663	llassert(alpha_sfactor < BF_UNDEF);
1664	llassert(alpha_dfactor < BF_UNDEF);
1665	if (!gGLManager.mHasBlendFuncSeparate)
1666	{
1667		LL_WARNS_ONCE("render") << "no glBlendFuncSeparateEXT(), using color-only blend func" << llendl;
1668		blendFunc(color_sfactor, color_dfactor);
1669		return;
1670	}
1671	if (mCurrBlendColorSFactor != color_sfactor || mCurrBlendColorDFactor != color_dfactor ||
1672	    mCurrBlendAlphaSFactor != alpha_sfactor || mCurrBlendAlphaDFactor != alpha_dfactor)
1673	{
1674		mCurrBlendColorSFactor = color_sfactor;
1675		mCurrBlendAlphaSFactor = alpha_sfactor;
1676		mCurrBlendColorDFactor = color_dfactor;
1677		mCurrBlendAlphaDFactor = alpha_dfactor;
1678		flush();
1679		glBlendFuncSeparateEXT(sGLBlendFactor[color_sfactor], sGLBlendFactor[color_dfactor],
1680				       sGLBlendFactor[alpha_sfactor], sGLBlendFactor[alpha_dfactor]);
1681	}
1682}
1683
1684LLTexUnit* LLRender::getTexUnit(U32 index)
1685{
1686	if (index < mTexUnits.size())
1687	{
1688		return mTexUnits[index];
1689	}
1690	else 
1691	{
1692		lldebugs << "Non-existing texture unit layer requested: " << index << llendl;
1693		return mDummyTexUnit;
1694	}
1695}
1696
1697LLLightState* LLRender::getLight(U32 index)
1698{
1699	if (index < mLightState.size())
1700	{
1701		return mLightState[index];
1702	}
1703	
1704	return NULL;
1705}
1706
1707void LLRender::setAmbientLightColor(const LLColor4& color)
1708{
1709	if (color != mAmbientLightColor)
1710	{
1711		++mLightHash;
1712		mAmbientLightColor = color;
1713		if (!LLGLSLShader::sNoFixedFunction)
1714		{
1715			glLightModelfv(GL_LIGHT_MODEL_AMBIENT, color.mV);
1716		}
1717	}
1718}
1719
1720bool LLRender::verifyTexUnitActive(U32 unitToVerify)
1721{
1722	if (mCurrTextureUnitIndex == unitToVerify)
1723	{
1724		return true;
1725	}
1726	else 
1727	{
1728		llwarns << "TexUnit currently active: " << mCurrTextureUnitIndex << " (expecting " << unitToVerify << ")" << llendl;
1729		return false;
1730	}
1731}
1732
1733void LLRender::clearErrors()
1734{
1735	while (glGetError())
1736	{
1737		//loop until no more error flags left
1738	}
1739}
1740
1741void LLRender::begin(const GLuint& mode)
1742{
1743	if (mode != mMode)
1744	{
1745		if (mode == LLRender::QUADS)
1746		{
1747			mQuadCycle = 1;
1748		}
1749
1750		if (mMode == LLRender::QUADS ||
1751			mMode == LLRender::LINES ||
1752			mMode == LLRender::TRIANGLES ||
1753			mMode == LLRender::POINTS)
1754		{
1755			flush();
1756		}
1757		else if (mCount != 0)
1758		{
1759			llerrs << "gGL.begin() called redundantly." << llendl;
1760		}
1761		
1762		mMode = mode;
1763	}
1764}
1765
1766void LLRender::end()
1767{ 
1768	if (mCount == 0)
1769	{
1770		return;
1771		//IMM_ERRS << "GL begin and end called with no vertices specified." << llendl;
1772	}
1773
1774	if ((mMode != LLRender::QUADS && 
1775		mMode != LLRender::LINES &&
1776		mMode != LLRender::TRIANGLES &&
1777		mMode != LLRender::POINTS) ||
1778		mCount > 2048)
1779	{
1780		flush();
1781	}
1782}
1783void LLRender::flush()
1784{
1785	if (mCount > 0)
1786	{
1787#if 0
1788		if (!glIsEnabled(GL_VERTEX_ARRAY))
1789		{
1790			llerrs << "foo 1" << llendl;
1791		}
1792
1793		if (!glIsEnabled(GL_COLOR_ARRAY))
1794		{
1795			llerrs << "foo 2" << llendl;
1796		}
1797
1798		if (!glIsEnabled(GL_TEXTURE_COORD_ARRAY))
1799		{
1800			llerrs << "foo 3" << llendl;
1801		}
1802
1803		if (glIsEnabled(GL_NORMAL_ARRAY))
1804		{
1805			llerrs << "foo 7" << llendl;
1806		}
1807
1808		GLvoid* pointer;
1809
1810		glGetPointerv(GL_VERTEX_ARRAY_POINTER, &pointer);
1811		if (pointer != &(mBuffer[0].v))
1812		{
1813			llerrs << "foo 4" << llendl;
1814		}
1815
1816		glGetPointerv(GL_COLOR_ARRAY_POINTER, &pointer);
1817		if (pointer != &(mBuffer[0].c))
1818		{
1819			llerrs << "foo 5" << llendl;
1820		}
1821
1822		glGetPointerv(GL_TEXTURE_COORD_ARRAY_POINTER, &pointer);
1823		if (pointer != &(mBuffer[0].uv))
1824		{
1825			llerrs << "foo 6" << llendl;
1826		}
1827#endif
1828				
1829		if (!mUIOffset.empty())
1830		{
1831			sUICalls++;
1832			sUIVerts += mCount;
1833		}
1834		
1835		if (gDebugGL)
1836		{
1837			if (mMode == LLRender::QUADS && !sGLCoreProfile)
1838			{
1839				if (mCount%4 != 0)
1840				{
1841					llerrs << "Incomplete quad rendered." << llendl;
1842				}
1843			}
1844			
1845			if (mMode == LLRender::TRIANGLES)
1846			{
1847				if (mCount%3 != 0)
1848				{
1849					llerrs << "Incomplete triangle rendered." << llendl;
1850				}
1851			}
1852			
1853			if (mMode == LLRender::LINES)
1854			{
1855				if (mCount%2 != 0)
1856				{
1857					llerrs << "Incomplete line rendered." << llendl;
1858				}
1859			}
1860		}
1861
1862		//store mCount in a local variable to avoid re-entrance (drawArrays may call flush)
1863		U32 count = mCount;
1864		mCount = 0;
1865
1866		if (mBuffer->useVBOs() && !mBuffer->isLocked())
1867		{ //hack to only flush the part of the buffer that was updated (relies on stream draw using buffersubdata)
1868			mBuffer->getVertexStrider(mVerticesp, 0, count);
1869			mBuffer->getTexCoord0Strider(mTexcoordsp, 0, count);
1870			mBuffer->getColorStrider(mColorsp, 0, count);
1871		}
1872		
1873		mBuffer->flush();
1874		mBuffer->setBuffer(immediate_mask);
1875
1876		if (mMode == LLRender::QUADS && sGLCoreProfile)
1877		{
1878			mBuffer->drawArrays(LLRender::TRIANGLES, 0, count);
1879			mQuadCycle = 1;
1880		}
1881		else
1882		{
1883			mBuffer->drawArrays(mMode, 0, count);
1884		}
1885		
1886		mVerticesp[0] = mVerticesp[count];
1887		mTexcoordsp[0] = mTexcoordsp[count];
1888		mColorsp[0] = mColorsp[count];
1889		
1890		mCount = 0;
1891	}
1892}
1893
1894void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z)
1895{ 
1896	//the range of mVerticesp, mColorsp and mTexcoordsp is [0, 4095]
1897	if (mCount > 2048)
1898	{ //break when buffer gets reasonably full to keep GL command buffers happy and avoid overflow below
1899		switch (mMode)
1900		{
1901			case LLRender::POINTS: flush(); break;
1902			case LLRender::TRIANGLES: if (mCount%3==0) flush(); break;
1903			case LLRender::QUADS: if(mCount%4 == 0) flush(); break; 
1904			case LLRender::LINES: if (mCount%2 == 0) flush(); break;
1905		}
1906	}
1907			
1908	if (mCount > 4094)
1909	{
1910	//	llwarns << "GL immediate mode overflow.  Some geometry not drawn." << llendl;
1911		return;
1912	}
1913
1914	if (mUIOffset.empty())
1915	{
1916		mVerticesp[mCount] = LLVector3(x,y,z);
1917	}
1918	else
1919	{
1920		LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.back()).scaledVec(mUIScale.back());
1921		mVerticesp[mCount] = vert;
1922	}
1923
1924	if (mMode == LLRender::QUADS && LLRender::sGLCoreProfile)
1925	{
1926		mQuadCycle++;
1927		if (mQuadCycle == 4)
1928		{ //copy two vertices so fourth quad element will add a triangle
1929			mQuadCycle = 0;
1930	
1931			mCount++;
1932			mVerticesp[mCount] = mVerticesp[mCount-3];
1933			mColorsp[mCount] = mColorsp[mCount-3];
1934			mTexcoordsp[mCount] = mTexcoordsp[mCount-3];
1935
1936			mCount++;
1937			mVerticesp[mCount] = mVerticesp[mCount-2];
1938			mColorsp[mCount] = mColorsp[mCount-2];
1939			mTexcoordsp[mCount] = mTexcoordsp[mCount-2];
1940		}
1941	}
1942
1943	mCount++;
1944	mVerticesp[mCount] = mVerticesp[mCount-1];
1945	mColorsp[mCount] = mColorsp[mCount-1];
1946	mTexcoordsp[mCount] = mTexcoordsp[mCount-1];	
1947}
1948
1949void LLRender::vertexBatchPreTransformed(LLVector3* verts, S32 vert_count)
1950{
1951	if (mCount + vert_count > 4094)
1952	{
1953		//	llwarns << "GL immediate mode overflow.  Some geometry not drawn." << llendl;
1954		return;
1955	}
1956
1957	if (sGLCoreProfile && mMode == LLRender::QUADS)
1958	{ //quads are deprecated, convert to triangle list
1959		S32 i = 0;
1960		
1961		while (i < vert_count)
1962		{
1963			//read first three
1964			mVerticesp[mCount++] = verts[i++];
1965			mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
1966			mColorsp[mCount] = mColorsp[mCount-1];
1967
1968			mVerticesp[mCount++] = verts[i++];
1969			mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
1970			mColorsp[mCount] = mColorsp[mCount-1];
1971
1972			mVerticesp[mCount++] = verts[i++];
1973			mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
1974			mColorsp[mCount] = mColorsp[mCount-1];
1975
1976			//copy two
1977			mVerticesp[mCount++] = verts[i-3];
1978			mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
1979			mColorsp[mCount] = mColorsp[mCount-1];
1980
1981			mVerticesp[mCount++] = verts[i-1];
1982			mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
1983			mColorsp[mCount] = mColorsp[mCount-1];
1984			
1985			//copy last one
1986			mVerticesp[mCount++] = verts[i++];
1987			mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
1988			mColorsp[mCount] = mColorsp[mCount-1];
1989		}
1990	}
1991	else
1992	{
1993		for (S32 i = 0; i < vert_count; i++)
1994		{
1995			mVerticesp[mCount] = verts[i];
1996
1997			mCount++;
1998			mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
1999			mColorsp[mCount] = mColorsp[mCount-1];
2000		}
2001	}
2002
2003	mVerticesp[mCount] = mVerticesp[mCount-1];
2004}
2005
2006void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count)
2007{
2008	if (mCount + vert_count > 4094)
2009	{
2010		//	llwarns << "GL immediate mode overflow.  Some geometry not drawn." << llendl;
2011		return;
2012	}
2013
2014	if (sGLCoreProfile && mMode == LLRender::QUADS)
2015	{ //quads are deprecated, convert to triangle list
2016		S32 i = 0;
2017
2018		while (i < vert_count)
2019		{
2020			//read first three
2021			mVerticesp[mCount] = verts[i];
2022			mTexcoordsp[mCount++] = uvs[i++];
2023			mColorsp[mCount] = mColorsp[mCount-1];
2024
2025			mVerticesp[mCount] = verts[i];
2026			mTexcoordsp[mCount++] = uvs[i++];
2027			mColorsp[mCount] = mColorsp[mCount-1];
2028
2029			mVerticesp[mCount] = verts[i];
2030			mTexcoordsp[mCount++] = uvs[i++];
2031			mColorsp[mCount] = mColorsp[mCount-1];
2032
2033			//copy last two
2034			mVerticesp[mCount] = verts[i-3];
2035			mTexcoordsp[mCount++] = uvs[i-3];
2036			mColorsp[mCount] = mColorsp[mCount-1];
2037
2038			mVerticesp[mCount] = verts[i-1];
2039			mTexcoordsp[mCount++] = uvs[i-1];
2040			mColorsp[mCount] = mColorsp[mCount-1];
2041
2042			//copy last one
2043			mVerticesp[mCount] = verts[i];
2044			mTexcoordsp[mCount++] = uvs[i++];
2045			mColorsp[mCount] = mColorsp[mCount-1];
2046		}
2047	}
2048	else
2049	{
2050		for (S32 i = 0; i < vert_count; i++)
2051		{
2052			mVerticesp[mCount] = verts[i];
2053			mTexcoordsp[mCount] = uvs[i];
2054
2055			mCount++;
2056			mColorsp[mCount] = mColorsp[mCount-1];
2057		}
2058	}
2059
2060	mVerticesp[mCount] = mVerticesp[mCount-1];
2061	mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
2062}
2063
2064void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, LLColor4U* colors, S32 vert_count)
2065{
2066	if (mCount + vert_count > 4094)
2067	{
2068		//	llwarns << "GL immediate mode overflow.  Some geometry not drawn." << llendl;
2069		return;
2070	}
2071
2072	
2073	if (sGLCoreProfile && mMode == LLRender::QUADS)
2074	{ //quads are deprecated, convert to triangle list
2075		S32 i = 0;
2076
2077		while (i < vert_count)
2078		{
2079			//read first three
2080			mVerticesp[mCount] = verts[i];
2081			mTexcoordsp[mCount] = uvs[i];
2082			mColorsp[mCount++] = colors[i++];
2083
2084			mVerticesp[mCount] = verts[i];
2085			mTexcoordsp[mCount] = uvs[i];
2086			mColorsp[mCount++] = colors[i++];
2087
2088			mVerticesp[mCount] = verts[i];
2089			mTexcoordsp[mCount] = uvs[i];
2090			mColorsp[mCount++] = colors[i++];
2091
2092			//copy last two
2093			mVerticesp[mCount] = verts[i-3];
2094			mTexcoordsp[mCount] = uvs[i-3];
2095			mColorsp[mCount++] = colors[i-3];
2096
2097			mVerticesp[mCount] = verts[i-1];
2098			mTexcoordsp[mCount] = uvs[i-1];
2099			mColorsp[mCount++] = colors[i-1];
2100
2101			//copy last one
2102			mVerticesp[mCount] = verts[i];
2103			mTexcoordsp[mCount] = uvs[i];
2104			mColorsp[mCount++] = colors[i++];
2105		}
2106	}
2107	else
2108	{
2109		for (S32 i = 0; i < vert_count; i++)
2110		{
2111			mVerticesp[mCount] = verts[i];
2112			mTexcoordsp[mCount] = uvs[i];
2113			mColorsp[mCount] = colors[i];
2114
2115			mCount++;
2116		}
2117	}
2118
2119	mVerticesp[mCount] = mVerticesp[mCount-1];
2120	mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
2121	mColorsp[mCount] = mColorsp[mCount-1];
2122}
2123
2124void LLRender::vertex2i(const GLint& x, const GLint& y)
2125{
2126	vertex3f((GLfloat) x, (GLfloat) y, 0);	
2127}
2128
2129void LLRender::vertex2f(const GLfloat& x, const GLfloat& y)
2130{ 
2131	vertex3f(x,y,0);
2132}
2133
2134void LLRender::vertex2fv(const GLfloat* v)
2135{ 
2136	vertex3f(v[0], v[1], 0);
2137}
2138
2139void LLRender::vertex3fv(const GLfloat* v)
2140{
2141	vertex3f(v[0], v[1], v[2]);
2142}
2143
2144void LLRender::texCoord2f(const GLfloat& x, const GLfloat& y)
2145{ 
2146	mTexcoordsp[mCount] = LLVector2(x,y);
2147}
2148
2149void LLRender::texCoord2i(const GLint& x, const GLint& y)
2150{ 
2151	texCoord2f((GLfloat) x, (GLfloat) y);
2152}
2153
2154void LLRender::texCoord2fv(const GLfloat* tc)
2155{ 
2156	texCoord2f(tc[0], tc[1]);
2157}
2158
2159void LLRender::color4ub(const GLubyte& r, const GLubyte& g, const GLubyte& b, const GLubyte& a)
2160{
2161	mColorsp[mCount] = LLColor4U(r,g,b,a);
2162}
2163void LLRender::color4ubv(const GLubyte* c)
2164{
2165	color4ub(c[0], c[1], c[2], c[3]);
2166}
2167
2168void LLRender::color4f(const GLfloat& r, const GLfloat& g, const GLfloat& b, const GLfloat& a)
2169{
2170	color4ub((GLubyte) (llclamp(r, 0.f, 1.f)*255),
2171		(GLubyte) (llclamp(g, 0.f, 1.f)*255),
2172		(GLubyte) (llclamp(b, 0.f, 1.f)*255),
2173		(GLubyte) (llclamp(a, 0.f, 1.f)*255));
2174}
2175
2176void LLRender::color4fv(const GLfloat* c)
2177{ 
2178	color4f(c[0],c[1],c[2],c[3]);
2179}
2180
2181void LLRender::color3f(const GLfloat& r, const GLfloat& g, const 

Large files files are truncated, but you can click here to view the full file