PageRenderTime 184ms CodeModel.GetById 54ms app.highlight 116ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/llrender/llimagegl.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2107 lines | 1646 code | 262 blank | 199 comment | 336 complexity | 31511605346d848af0f09388be50ce81 MD5 | raw file

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

   1/** 
   2 * @file llimagegl.cpp
   3 * @brief Generic GL image handler
   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
  28// TODO: create 2 classes for images w/ and w/o discard levels?
  29
  30#include "linden_common.h"
  31
  32#include "llimagegl.h"
  33
  34#include "llerror.h"
  35#include "llimage.h"
  36
  37#include "llmath.h"
  38#include "llgl.h"
  39#include "llglslshader.h"
  40#include "llrender.h"
  41
  42//----------------------------------------------------------------------------
  43const F32 MIN_TEXTURE_LIFETIME = 10.f;
  44
  45//statics
  46LLGLuint LLImageGL::sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS] = { 0 };
  47
  48U32 LLImageGL::sUniqueCount				= 0;
  49U32 LLImageGL::sBindCount				= 0;
  50S32 LLImageGL::sGlobalTextureMemoryInBytes		= 0;
  51S32 LLImageGL::sBoundTextureMemoryInBytes		= 0;
  52S32 LLImageGL::sCurBoundTextureMemory	= 0;
  53S32 LLImageGL::sCount					= 0;
  54std::list<U32> LLImageGL::sDeadTextureList;
  55
  56BOOL LLImageGL::sGlobalUseAnisotropic	= FALSE;
  57F32 LLImageGL::sLastFrameTime			= 0.f;
  58BOOL LLImageGL::sAllowReadBackRaw       = FALSE ;
  59LLImageGL* LLImageGL::sDefaultGLTexture = NULL ;
  60
  61std::set<LLImageGL*> LLImageGL::sImageList;
  62
  63//****************************************************************************************************
  64//The below for texture auditing use only
  65//****************************************************************************************************
  66//-----------------------
  67//debug use
  68BOOL gAuditTexture = FALSE ;
  69#define MAX_TEXTURE_LOG_SIZE 22 //2048 * 2048
  70std::vector<S32> LLImageGL::sTextureLoadedCounter(MAX_TEXTURE_LOG_SIZE + 1) ;
  71std::vector<S32> LLImageGL::sTextureBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ;
  72std::vector<S32> LLImageGL::sTextureCurBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ;
  73S32 LLImageGL::sCurTexSizeBar = -1 ;
  74S32 LLImageGL::sCurTexPickSize = -1 ;
  75LLPointer<LLImageGL> LLImageGL::sHighlightTexturep = NULL;
  76S32 LLImageGL::sMaxCatagories = 1 ;
  77
  78std::vector<S32> LLImageGL::sTextureMemByCategory;
  79std::vector<S32> LLImageGL::sTextureMemByCategoryBound ;
  80std::vector<S32> LLImageGL::sTextureCurMemByCategoryBound ;
  81//------------------------
  82//****************************************************************************************************
  83//End for texture auditing use only
  84//****************************************************************************************************
  85
  86//**************************************************************************************
  87//below are functions for debug use
  88//do not delete them even though they are not currently being used.
  89void check_all_images()
  90{
  91	for (std::set<LLImageGL*>::iterator iter = LLImageGL::sImageList.begin();
  92		 iter != LLImageGL::sImageList.end(); iter++)
  93	{
  94		LLImageGL* glimage = *iter;
  95		if (glimage->getTexName() && glimage->isGLTextureCreated())
  96		{
  97			gGL.getTexUnit(0)->bind(glimage) ;
  98			glimage->checkTexSize() ;
  99			gGL.getTexUnit(0)->unbind(glimage->getTarget()) ;
 100		}
 101	}
 102}
 103
 104void LLImageGL::checkTexSize(bool forced) const
 105{
 106	if ((forced || gDebugGL) && mTarget == GL_TEXTURE_2D)
 107	{
 108		{
 109			//check viewport
 110			GLint vp[4] ;
 111			glGetIntegerv(GL_VIEWPORT, vp) ;
 112			llcallstacks << "viewport: " << vp[0] << " : " << vp[1] << " : " << vp[2] << " : " << vp[3] << llcallstacksendl ;
 113		}
 114
 115		GLint texname;
 116		glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname);
 117		BOOL error = FALSE;
 118		if (texname != mTexName)
 119		{
 120			llinfos << "Bound: " << texname << " Should bind: " << mTexName << " Default: " << LLImageGL::sDefaultGLTexture->getTexName() << llendl;
 121
 122			error = TRUE;
 123			if (gDebugSession)
 124			{
 125				gFailLog << "Invalid texture bound!" << std::endl;
 126			}
 127			else
 128			{
 129				llerrs << "Invalid texture bound!" << llendl;
 130			}
 131		}
 132		stop_glerror() ;
 133		LLGLint x = 0, y = 0 ;
 134		glGetTexLevelParameteriv(mTarget, 0, GL_TEXTURE_WIDTH, (GLint*)&x);
 135		glGetTexLevelParameteriv(mTarget, 0, GL_TEXTURE_HEIGHT, (GLint*)&y) ;
 136		stop_glerror() ;
 137		llcallstacks << "w: " << x << " h: " << y << llcallstacksendl ;
 138
 139		if(!x || !y)
 140		{
 141			return ;
 142		}
 143		if(x != (mWidth >> mCurrentDiscardLevel) || y != (mHeight >> mCurrentDiscardLevel))
 144		{
 145			error = TRUE;
 146			if (gDebugSession)
 147			{
 148				gFailLog << "wrong texture size and discard level!" << 
 149					mWidth << " Height: " << mHeight << " Current Level: " << (S32)mCurrentDiscardLevel << std::endl;
 150			}
 151			else
 152			{
 153				llerrs << "wrong texture size and discard level: width: " << 
 154					mWidth << " Height: " << mHeight << " Current Level: " << (S32)mCurrentDiscardLevel << llendl ;
 155			}
 156		}
 157
 158		if (error)
 159		{
 160			ll_fail("LLImageGL::checkTexSize failed.");
 161		}
 162	}
 163}
 164//end of debug functions
 165//**************************************************************************************
 166
 167//----------------------------------------------------------------------------
 168BOOL is_little_endian()
 169{
 170	S32 a = 0x12345678;
 171    U8 *c = (U8*)(&a);
 172    
 173	return (*c == 0x78) ;
 174}
 175//static 
 176void LLImageGL::initClass(S32 num_catagories) 
 177{
 178	sMaxCatagories = num_catagories ;
 179
 180	sTextureMemByCategory.resize(sMaxCatagories);
 181	sTextureMemByCategoryBound.resize(sMaxCatagories) ;
 182	sTextureCurMemByCategoryBound.resize(sMaxCatagories) ;
 183}
 184
 185//static 
 186void LLImageGL::cleanupClass() 
 187{	
 188	sTextureMemByCategory.clear() ;
 189	sTextureMemByCategoryBound.clear() ;
 190	sTextureCurMemByCategoryBound.clear() ;
 191}
 192
 193//static 
 194void LLImageGL::setHighlightTexture(S32 category) 
 195{
 196	const S32 dim = 128;
 197	sHighlightTexturep = new LLImageGL() ;
 198	LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim,dim,3);
 199	U8* data = image_raw->getData();
 200	for (S32 i = 0; i<dim; i++)
 201	{
 202		for (S32 j = 0; j<dim; j++)
 203		{
 204			const S32 border = 2;
 205			if (i<border || j<border || i>=(dim-border) || j>=(dim-border))
 206			{
 207				*data++ = 0xff;
 208				*data++ = 0xff;
 209				*data++ = 0xff;
 210			}
 211			else
 212			{
 213				*data++ = 0xff;
 214				*data++ = 0xff;
 215				*data++ = 0x00;
 216			}
 217		}
 218	}
 219	sHighlightTexturep->createGLTexture(0, image_raw, 0, TRUE, category);
 220	image_raw = NULL;
 221}
 222
 223//static
 224S32 LLImageGL::dataFormatBits(S32 dataformat)
 225{
 226	switch (dataformat)
 227	{
 228	  case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:	return 4;
 229	  case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:	return 8;
 230	  case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:	return 8;
 231	  case GL_LUMINANCE:						return 8;
 232	  case GL_ALPHA:							return 8;
 233	  case GL_COLOR_INDEX:						return 8;
 234	  case GL_LUMINANCE_ALPHA:					return 16;
 235	  case GL_RGB:								return 24;
 236	  case GL_RGB8:								return 24;
 237	  case GL_RGBA:								return 32;
 238	  case GL_BGRA:								return 32;		// Used for QuickTime media textures on the Mac
 239	  default:
 240		llerrs << "LLImageGL::Unknown format: " << dataformat << llendl;
 241		return 0;
 242	}
 243}
 244
 245//static
 246S32 LLImageGL::dataFormatBytes(S32 dataformat, S32 width, S32 height)
 247{
 248	if (dataformat >= GL_COMPRESSED_RGB_S3TC_DXT1_EXT &&
 249		dataformat <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
 250	{
 251		if (width < 4) width = 4;
 252		if (height < 4) height = 4;
 253	}
 254	S32 bytes ((width*height*dataFormatBits(dataformat)+7)>>3);
 255	S32 aligned = (bytes+3)&~3;
 256	return aligned;
 257}
 258
 259//static
 260S32 LLImageGL::dataFormatComponents(S32 dataformat)
 261{
 262	switch (dataformat)
 263	{
 264	  case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:	return 3;
 265	  case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:	return 4;
 266	  case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:	return 4;
 267	  case GL_LUMINANCE:						return 1;
 268	  case GL_ALPHA:							return 1;
 269	  case GL_COLOR_INDEX:						return 1;
 270	  case GL_LUMINANCE_ALPHA:					return 2;
 271	  case GL_RGB:								return 3;
 272	  case GL_RGBA:								return 4;
 273	  case GL_BGRA:								return 4;		// Used for QuickTime media textures on the Mac
 274	  default:
 275		llerrs << "LLImageGL::Unknown format: " << dataformat << llendl;
 276		return 0;
 277	}
 278}
 279
 280//----------------------------------------------------------------------------
 281
 282// static
 283void LLImageGL::updateStats(F32 current_time)
 284{
 285	sLastFrameTime = current_time;
 286	sBoundTextureMemoryInBytes = sCurBoundTextureMemory;
 287	sCurBoundTextureMemory = 0;
 288
 289	if(gAuditTexture)
 290	{
 291		for(U32 i = 0 ; i < sTextureCurBoundCounter.size() ; i++)
 292		{
 293			sTextureBoundCounter[i] = sTextureCurBoundCounter[i] ;
 294			sTextureCurBoundCounter[i] = 0 ;
 295		}
 296		for(U32 i = 0 ; i < sTextureCurMemByCategoryBound.size() ; i++)
 297		{
 298			sTextureMemByCategoryBound[i] = sTextureCurMemByCategoryBound[i] ;
 299			sTextureCurMemByCategoryBound[i] = 0 ;
 300		}
 301	}
 302}
 303
 304//static
 305S32 LLImageGL::updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 category)
 306{
 307	if(gAuditTexture && ncomponents > 0 && category > -1)
 308	{
 309		sTextureCurBoundCounter[getTextureCounterIndex(mem / ncomponents)]++ ;
 310		sTextureCurMemByCategoryBound[category] += mem ;
 311	}
 312	
 313	LLImageGL::sCurBoundTextureMemory += mem ;
 314	return LLImageGL::sCurBoundTextureMemory;
 315}
 316
 317//----------------------------------------------------------------------------
 318
 319//static 
 320void LLImageGL::destroyGL(BOOL save_state)
 321{
 322	for (S32 stage = 0; stage < gGLManager.mNumTextureUnits; stage++)
 323	{
 324		gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE);
 325	}
 326	
 327	sAllowReadBackRaw = true ;
 328	for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
 329		 iter != sImageList.end(); iter++)
 330	{
 331		LLImageGL* glimage = *iter;
 332		if (glimage->mTexName)
 333		{
 334			if (save_state && glimage->isGLTextureCreated() && glimage->mComponents)
 335			{
 336				glimage->mSaveData = new LLImageRaw;
 337				if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false)) //necessary, keep it.
 338				{
 339					glimage->mSaveData = NULL ;
 340				}
 341			}
 342
 343			glimage->destroyGLTexture();
 344			stop_glerror();
 345		}
 346	}
 347	sAllowReadBackRaw = false ;
 348}
 349
 350//static 
 351void LLImageGL::restoreGL()
 352{
 353	for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
 354		 iter != sImageList.end(); iter++)
 355	{
 356		LLImageGL* glimage = *iter;
 357		if(glimage->getTexName())
 358		{
 359			llerrs << "tex name is not 0." << llendl ;
 360		}
 361		if (glimage->mSaveData.notNull())
 362		{
 363			if (glimage->getComponents() && glimage->mSaveData->getComponents())
 364			{
 365				glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData, 0, TRUE, glimage->getCategory());
 366				stop_glerror();
 367			}
 368			glimage->mSaveData = NULL; // deletes data
 369		}
 370	}
 371}
 372
 373//static 
 374void LLImageGL::dirtyTexOptions()
 375{
 376	for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
 377		 iter != sImageList.end(); iter++)
 378	{
 379		LLImageGL* glimage = *iter;
 380		glimage->mTexOptionsDirty = true;
 381		stop_glerror();
 382	}
 383	
 384}
 385//----------------------------------------------------------------------------
 386
 387//for server side use only.
 388//static 
 389BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, BOOL usemipmaps)
 390{
 391	dest = new LLImageGL(usemipmaps);
 392	return TRUE;
 393}
 394
 395//for server side use only.
 396BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, U32 width, U32 height, U8 components, BOOL usemipmaps)
 397{
 398	dest = new LLImageGL(width, height, components, usemipmaps);
 399	return TRUE;
 400}
 401
 402//for server side use only.
 403BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, BOOL usemipmaps)
 404{
 405	dest = new LLImageGL(imageraw, usemipmaps);
 406	return TRUE;
 407}
 408
 409//----------------------------------------------------------------------------
 410
 411LLImageGL::LLImageGL(BOOL usemipmaps)
 412	: mSaveData(0)
 413{
 414	init(usemipmaps);
 415	setSize(0, 0, 0);
 416	sImageList.insert(this);
 417	sCount++;
 418}
 419
 420LLImageGL::LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps)
 421	: mSaveData(0)
 422{
 423	llassert( components <= 4 );
 424	init(usemipmaps);
 425	setSize(width, height, components);
 426	sImageList.insert(this);
 427	sCount++;
 428}
 429
 430LLImageGL::LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps)
 431	: mSaveData(0)
 432{
 433	init(usemipmaps);
 434	setSize(0, 0, 0);
 435	sImageList.insert(this);
 436	sCount++;
 437
 438	createGLTexture(0, imageraw); 
 439}
 440
 441LLImageGL::~LLImageGL()
 442{
 443	LLImageGL::cleanup();
 444	sImageList.erase(this);
 445	delete [] mPickMask;
 446	mPickMask = NULL;
 447	sCount--;
 448}
 449
 450void LLImageGL::init(BOOL usemipmaps)
 451{
 452	// keep these members in the same order as declared in llimagehl.h
 453	// so that it is obvious by visual inspection if we forgot to
 454	// init a field.
 455
 456	mTextureMemory = 0;
 457	mLastBindTime = 0.f;
 458
 459	mPickMask = NULL;
 460	mPickMaskWidth = 0;
 461	mPickMaskHeight = 0;
 462	mUseMipMaps = usemipmaps;
 463	mHasExplicitFormat = FALSE;
 464	mAutoGenMips = FALSE;
 465
 466	mIsMask = FALSE;
 467	mNeedsAlphaAndPickMask = TRUE ;
 468	mAlphaStride = 0 ;
 469	mAlphaOffset = 0 ;
 470
 471	mGLTextureCreated = FALSE ;
 472	mTexName = 0;
 473	mWidth = 0;
 474	mHeight	= 0;
 475	mCurrentDiscardLevel = -1;	
 476
 477	mDiscardLevelInAtlas = -1 ;
 478	mTexelsInAtlas = 0 ;
 479	mTexelsInGLTexture = 0 ;
 480	
 481	mTarget = GL_TEXTURE_2D;
 482	mBindTarget = LLTexUnit::TT_TEXTURE;
 483	mHasMipMaps = false;
 484
 485	mIsResident = 0;
 486
 487	mComponents = 0;
 488	mMaxDiscardLevel = MAX_DISCARD_LEVEL;
 489
 490	mTexOptionsDirty = true;
 491	mAddressMode = LLTexUnit::TAM_WRAP;
 492	mFilterOption = LLTexUnit::TFO_ANISOTROPIC;
 493	
 494	mFormatInternal = -1;
 495	mFormatPrimary = (LLGLenum) 0;
 496	mFormatType = GL_UNSIGNED_BYTE;
 497	mFormatSwapBytes = FALSE;
 498
 499#ifdef DEBUG_MISS
 500	mMissed	= FALSE;
 501#endif
 502
 503	mCategory = -1;
 504}
 505
 506void LLImageGL::cleanup()
 507{
 508	if (!gGLManager.mIsDisabled)
 509	{
 510		destroyGLTexture();
 511	}
 512	mSaveData = NULL; // deletes data
 513}
 514
 515//----------------------------------------------------------------------------
 516
 517//this function is used to check the size of a texture image.
 518//so dim should be a positive number
 519static bool check_power_of_two(S32 dim)
 520{
 521	if(dim < 0)
 522	{
 523		return false ;
 524	}
 525	if(!dim)//0 is a power-of-two number
 526	{
 527		return true ;
 528	}
 529	return !(dim & (dim - 1)) ;
 530}
 531
 532//static
 533bool LLImageGL::checkSize(S32 width, S32 height)
 534{
 535	return check_power_of_two(width) && check_power_of_two(height);
 536}
 537
 538void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents)
 539{
 540	if (width != mWidth || height != mHeight || ncomponents != mComponents)
 541	{
 542		// Check if dimensions are a power of two!
 543		if (!checkSize(width,height))
 544		{
 545			llerrs << llformat("Texture has non power of two dimension: %dx%d",width,height) << llendl;
 546		}
 547		
 548		if (mTexName)
 549		{
 550// 			llwarns << "Setting Size of LLImageGL with existing mTexName = " << mTexName << llendl;
 551			destroyGLTexture();
 552		}
 553
 554		// pickmask validity depends on old image size, delete it
 555		delete [] mPickMask;
 556		mPickMask = NULL;
 557		mPickMaskWidth = mPickMaskHeight = 0;
 558
 559		mWidth = width;
 560		mHeight = height;
 561		mComponents = ncomponents;
 562		if (ncomponents > 0)
 563		{
 564			mMaxDiscardLevel = 0;
 565			while (width > 1 && height > 1 && mMaxDiscardLevel < MAX_DISCARD_LEVEL)
 566			{
 567				mMaxDiscardLevel++;
 568				width >>= 1;
 569				height >>= 1;
 570			}
 571		}
 572		else
 573		{
 574			mMaxDiscardLevel = MAX_DISCARD_LEVEL;
 575		}
 576	}
 577}
 578
 579//----------------------------------------------------------------------------
 580
 581// virtual
 582void LLImageGL::dump()
 583{
 584	llinfos << "mMaxDiscardLevel " << S32(mMaxDiscardLevel)
 585			<< " mLastBindTime " << mLastBindTime
 586			<< " mTarget " << S32(mTarget)
 587			<< " mBindTarget " << S32(mBindTarget)
 588			<< " mUseMipMaps " << S32(mUseMipMaps)
 589			<< " mHasMipMaps " << S32(mHasMipMaps)
 590			<< " mCurrentDiscardLevel " << S32(mCurrentDiscardLevel)
 591			<< " mFormatInternal " << S32(mFormatInternal)
 592			<< " mFormatPrimary " << S32(mFormatPrimary)
 593			<< " mFormatType " << S32(mFormatType)
 594			<< " mFormatSwapBytes " << S32(mFormatSwapBytes)
 595			<< " mHasExplicitFormat " << S32(mHasExplicitFormat)
 596#if DEBUG_MISS
 597			<< " mMissed " << mMissed
 598#endif
 599			<< llendl;
 600
 601	llinfos << " mTextureMemory " << mTextureMemory
 602			<< " mTexNames " << mTexName
 603			<< " mIsResident " << S32(mIsResident)
 604			<< llendl;
 605}
 606
 607//----------------------------------------------------------------------------
 608void LLImageGL::forceUpdateBindStats(void) const
 609{
 610	mLastBindTime = sLastFrameTime;
 611}
 612
 613BOOL LLImageGL::updateBindStats(S32 tex_mem) const
 614{	
 615	if (mTexName != 0)
 616	{
 617#ifdef DEBUG_MISS
 618		mMissed = ! getIsResident(TRUE);
 619#endif
 620		sBindCount++;
 621		if (mLastBindTime != sLastFrameTime)
 622		{
 623			// we haven't accounted for this texture yet this frame
 624			sUniqueCount++;
 625			updateBoundTexMem(tex_mem, mComponents, mCategory);
 626			mLastBindTime = sLastFrameTime;
 627
 628			return TRUE ;
 629		}
 630	}
 631	return FALSE ;
 632}
 633
 634F32 LLImageGL::getTimePassedSinceLastBound()
 635{
 636	return sLastFrameTime - mLastBindTime ;
 637}
 638
 639void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes )
 640{
 641	// Note: must be called before createTexture()
 642	// Note: it's up to the caller to ensure that the format matches the number of components.
 643	mHasExplicitFormat = TRUE;
 644	mFormatInternal = internal_format;
 645	mFormatPrimary = primary_format;
 646	if(type_format == 0)
 647		mFormatType = GL_UNSIGNED_BYTE;
 648	else
 649		mFormatType = type_format;
 650	mFormatSwapBytes = swap_bytes;
 651
 652	calcAlphaChannelOffsetAndStride() ;
 653}
 654
 655//----------------------------------------------------------------------------
 656
 657void LLImageGL::setImage(const LLImageRaw* imageraw)
 658{
 659	llassert((imageraw->getWidth() == getWidth(mCurrentDiscardLevel)) &&
 660			 (imageraw->getHeight() == getHeight(mCurrentDiscardLevel)) &&
 661			 (imageraw->getComponents() == getComponents()));
 662	const U8* rawdata = imageraw->getData();
 663	setImage(rawdata, FALSE);
 664}
 665
 666void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
 667{
 668	bool is_compressed = false;
 669	if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
 670	{
 671		is_compressed = true;
 672	}
 673
 674	llverify(gGL.getTexUnit(0)->bind(this));
 675	
 676	if (mUseMipMaps)
 677	{
 678		if (data_hasmips)
 679		{
 680			// NOTE: data_in points to largest image; smaller images
 681			// are stored BEFORE the largest image
 682			for (S32 d=mCurrentDiscardLevel; d<=mMaxDiscardLevel; d++)
 683			{
 684				
 685				S32 w = getWidth(d);
 686				S32 h = getHeight(d);
 687				S32 gl_level = d-mCurrentDiscardLevel;
 688				if (d > mCurrentDiscardLevel)
 689				{
 690					data_in -= dataFormatBytes(mFormatPrimary, w, h); // see above comment
 691				}
 692				if (is_compressed)
 693				{
 694 					S32 tex_size = dataFormatBytes(mFormatPrimary, w, h);
 695					glCompressedTexImage2DARB(mTarget, gl_level, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in);
 696					stop_glerror();
 697				}
 698				else
 699				{
 700// 					LLFastTimer t2(FTM_TEMP4);
 701
 702					if(mFormatSwapBytes)
 703					{
 704						glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
 705						stop_glerror();
 706					}
 707						
 708					LLImageGL::setManualImage(mTarget, gl_level, mFormatInternal, w, h, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in);
 709					if (gl_level == 0)
 710					{
 711						analyzeAlpha(data_in, w, h);
 712					}
 713					updatePickMask(w, h, data_in);
 714
 715					if(mFormatSwapBytes)
 716					{
 717						glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
 718						stop_glerror();
 719					}
 720						
 721					stop_glerror();
 722				}
 723				stop_glerror();
 724			}			
 725		}
 726		else if (!is_compressed)
 727		{
 728			if (mAutoGenMips)
 729			{
 730				if (!gGLManager.mHasFramebufferObject)
 731				{
 732					glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_GENERATE_MIPMAP_SGIS, TRUE);
 733				}
 734				stop_glerror();
 735				{
 736// 					LLFastTimer t2(FTM_TEMP4);
 737
 738					if(mFormatSwapBytes)
 739					{
 740						glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
 741						stop_glerror();
 742					}
 743
 744					S32 w = getWidth(mCurrentDiscardLevel);
 745					S32 h = getHeight(mCurrentDiscardLevel);
 746
 747					LLImageGL::setManualImage(mTarget, 0, mFormatInternal,
 748								 w, h, 
 749								 mFormatPrimary, mFormatType,
 750								 data_in);
 751					analyzeAlpha(data_in, w, h);
 752					stop_glerror();
 753
 754					updatePickMask(w, h, data_in);
 755
 756					if(mFormatSwapBytes)
 757					{
 758						glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
 759						stop_glerror();
 760					}
 761				}
 762
 763				if (gGLManager.mHasFramebufferObject)
 764				{
 765					glGenerateMipmap(LLTexUnit::getInternalType(mBindTarget));
 766				}
 767			}
 768			else
 769			{
 770				// Create mips by hand
 771				// about 30% faster than autogen on ATI 9800, 50% slower on nVidia 4800
 772				// ~4x faster than gluBuild2DMipmaps
 773				S32 width = getWidth(mCurrentDiscardLevel);
 774				S32 height = getHeight(mCurrentDiscardLevel);
 775				S32 nummips = mMaxDiscardLevel - mCurrentDiscardLevel + 1;
 776				S32 w = width, h = height;
 777				const U8* prev_mip_data = 0;
 778				const U8* cur_mip_data = 0;
 779				S32 prev_mip_size = 0;
 780				S32 cur_mip_size = 0;
 781				for (int m=0; m<nummips; m++)
 782				{
 783					if (m==0)
 784					{
 785						cur_mip_data = data_in;
 786						cur_mip_size = width * height * mComponents; 
 787					}
 788					else
 789					{
 790						S32 bytes = w * h * mComponents;
 791						llassert(prev_mip_data);
 792						llassert(prev_mip_size == bytes*4);
 793						U8* new_data = new U8[bytes];
 794						llassert_always(new_data);
 795						LLImageBase::generateMip(prev_mip_data, new_data, w, h, mComponents);
 796						cur_mip_data = new_data;
 797						cur_mip_size = bytes; 
 798					}
 799					llassert(w > 0 && h > 0 && cur_mip_data);
 800					{
 801// 						LLFastTimer t1(FTM_TEMP4);
 802						if(mFormatSwapBytes)
 803						{
 804							glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
 805							stop_glerror();
 806						}
 807
 808						LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data);
 809						if (m == 0)
 810						{
 811							analyzeAlpha(data_in, w, h);
 812						}
 813						stop_glerror();
 814						if (m == 0)
 815						{
 816							updatePickMask(w, h, cur_mip_data);
 817						}
 818
 819						if(mFormatSwapBytes)
 820						{
 821							glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
 822							stop_glerror();
 823						}
 824					}
 825					if (prev_mip_data && prev_mip_data != data_in)
 826					{
 827						delete[] prev_mip_data;
 828					}
 829					prev_mip_data = cur_mip_data;
 830					prev_mip_size = cur_mip_size;
 831					w >>= 1;
 832					h >>= 1;
 833				}
 834				if (prev_mip_data && prev_mip_data != data_in)
 835				{
 836					delete[] prev_mip_data;
 837					prev_mip_data = NULL;
 838				}
 839			}
 840		}
 841		else
 842		{
 843			llerrs << "Compressed Image has mipmaps but data does not (can not auto generate compressed mips)" << llendl;
 844		}
 845		mHasMipMaps = true;
 846	}
 847	else
 848	{
 849		S32 w = getWidth();
 850		S32 h = getHeight();
 851		if (is_compressed)
 852		{
 853			S32 tex_size = dataFormatBytes(mFormatPrimary, w, h);
 854			glCompressedTexImage2DARB(mTarget, 0, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in);
 855			stop_glerror();
 856		}
 857		else
 858		{
 859			if(mFormatSwapBytes)
 860			{
 861				glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
 862				stop_glerror();
 863			}
 864
 865			LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h,
 866						 mFormatPrimary, mFormatType, (GLvoid *)data_in);
 867			analyzeAlpha(data_in, w, h);
 868			
 869			updatePickMask(w, h, data_in);
 870
 871			stop_glerror();
 872
 873			if(mFormatSwapBytes)
 874			{
 875				glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
 876				stop_glerror();
 877			}
 878
 879		}
 880		mHasMipMaps = false;
 881	}
 882	stop_glerror();
 883	mGLTextureCreated = true;
 884}
 885
 886BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image)
 887{
 888	//not compatible with core GL profile
 889	llassert(!LLRender::sGLCoreProfile);
 890
 891	if (gGLManager.mIsDisabled)
 892	{
 893		llwarns << "Trying to create a texture while GL is disabled!" << llendl;
 894		return FALSE;
 895	}
 896	llassert(gGLManager.mInited);
 897	stop_glerror();
 898
 899	if (discard_level < 0)
 900	{
 901		llassert(mCurrentDiscardLevel >= 0);
 902		discard_level = mCurrentDiscardLevel;
 903	}
 904	discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
 905
 906	// Actual image width/height = raw image width/height * 2^discard_level
 907	S32 w = raw_image->getWidth() << discard_level;
 908	S32 h = raw_image->getHeight() << discard_level;
 909
 910	// setSize may call destroyGLTexture if the size does not match
 911	setSize(w, h, raw_image->getComponents());
 912
 913	if( !mHasExplicitFormat )
 914	{
 915		switch (mComponents)
 916		{
 917			case 1:
 918			// Use luminance alpha (for fonts)
 919			mFormatInternal = GL_LUMINANCE8;
 920			mFormatPrimary = GL_LUMINANCE;
 921			mFormatType = GL_UNSIGNED_BYTE;
 922			break;
 923			case 2:
 924			// Use luminance alpha (for fonts)
 925			mFormatInternal = GL_LUMINANCE8_ALPHA8;
 926			mFormatPrimary = GL_LUMINANCE_ALPHA;
 927			mFormatType = GL_UNSIGNED_BYTE;
 928			break;
 929			case 3:
 930			mFormatInternal = GL_RGB8;
 931			mFormatPrimary = GL_RGB;
 932			mFormatType = GL_UNSIGNED_BYTE;
 933			break;
 934			case 4:
 935			mFormatInternal = GL_RGBA8;
 936			mFormatPrimary = GL_RGBA;
 937			mFormatType = GL_UNSIGNED_BYTE;
 938			break;
 939			default:
 940			llerrs << "Bad number of components for texture: " << (U32)getComponents() << llendl;
 941		}
 942	}
 943
 944	mCurrentDiscardLevel = discard_level;	
 945	mDiscardLevelInAtlas = discard_level;
 946	mTexelsInAtlas = raw_image->getWidth() * raw_image->getHeight() ;
 947	mLastBindTime = sLastFrameTime;
 948	mGLTextureCreated = false ;
 949	
 950	glPixelStorei(GL_UNPACK_ROW_LENGTH, raw_image->getWidth());
 951	stop_glerror();
 952
 953	if(mFormatSwapBytes)
 954	{
 955		glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
 956		stop_glerror();
 957	}
 958
 959	return TRUE ;
 960}
 961
 962void LLImageGL::postAddToAtlas()
 963{
 964	if(mFormatSwapBytes)
 965	{
 966		glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
 967		stop_glerror();
 968	}
 969
 970	glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
 971	gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption);	
 972	stop_glerror();	
 973}
 974
 975BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update)
 976{
 977	if (!width || !height)
 978	{
 979		return TRUE;
 980	}
 981	if (mTexName == 0)
 982	{
 983		// *TODO: Re-enable warning?  Ran into thread locking issues? DK 2011-02-18
 984		//llwarns << "Setting subimage on image without GL texture" << llendl;
 985		return FALSE;
 986	}
 987	if (datap == NULL)
 988	{
 989		// *TODO: Re-enable warning?  Ran into thread locking issues? DK 2011-02-18
 990		//llwarns << "Setting subimage on image with NULL datap" << llendl;
 991		return FALSE;
 992	}
 993	
 994	// HACK: allow the caller to explicitly force the fast path (i.e. using glTexSubImage2D here instead of calling setImage) even when updating the full texture.
 995	if (!force_fast_update && x_pos == 0 && y_pos == 0 && width == getWidth() && height == getHeight() && data_width == width && data_height == height)
 996	{
 997		setImage(datap, FALSE);
 998	}
 999	else
1000	{
1001		if (mUseMipMaps)
1002		{
1003			dump();
1004			llerrs << "setSubImage called with mipmapped image (not supported)" << llendl;
1005		}
1006		llassert_always(mCurrentDiscardLevel == 0);
1007		llassert_always(x_pos >= 0 && y_pos >= 0);
1008		
1009		if (((x_pos + width) > getWidth()) || 
1010			(y_pos + height) > getHeight())
1011		{
1012			dump();
1013			llerrs << "Subimage not wholly in target image!" 
1014				   << " x_pos " << x_pos
1015				   << " y_pos " << y_pos
1016				   << " width " << width
1017				   << " height " << height
1018				   << " getWidth() " << getWidth()
1019				   << " getHeight() " << getHeight()
1020				   << llendl;
1021		}
1022
1023		if ((x_pos + width) > data_width || 
1024			(y_pos + height) > data_height)
1025		{
1026			dump();
1027			llerrs << "Subimage not wholly in source image!" 
1028				   << " x_pos " << x_pos
1029				   << " y_pos " << y_pos
1030				   << " width " << width
1031				   << " height " << height
1032				   << " source_width " << data_width
1033				   << " source_height " << data_height
1034				   << llendl;
1035		}
1036
1037
1038		glPixelStorei(GL_UNPACK_ROW_LENGTH, data_width);
1039		stop_glerror();
1040
1041		if(mFormatSwapBytes)
1042		{
1043			glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
1044			stop_glerror();
1045		}
1046
1047		datap += (y_pos * data_width + x_pos) * getComponents();
1048		// Update the GL texture
1049		BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, mTexName);
1050		if (!res) llerrs << "LLImageGL::setSubImage(): bindTexture failed" << llendl;
1051		stop_glerror();
1052
1053		glTexSubImage2D(mTarget, 0, x_pos, y_pos, 
1054						width, height, mFormatPrimary, mFormatType, datap);
1055		gGL.getTexUnit(0)->disable();
1056		stop_glerror();
1057
1058		if(mFormatSwapBytes)
1059		{
1060			glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
1061			stop_glerror();
1062		}
1063
1064		glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1065		stop_glerror();
1066		mGLTextureCreated = true;
1067	}
1068	return TRUE;
1069}
1070
1071BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update)
1072{
1073	return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update);
1074}
1075
1076// Copy sub image from frame buffer
1077BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height)
1078{
1079	if (gGL.getTexUnit(0)->bind(this, false, true))
1080	{
1081		glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height);
1082		mGLTextureCreated = true;
1083		stop_glerror();
1084		return TRUE;
1085	}
1086	else
1087	{
1088		return FALSE;
1089	}
1090}
1091
1092// static
1093void LLImageGL::generateTextures(S32 numTextures, U32 *textures)
1094{
1095	glGenTextures(numTextures, (GLuint*)textures);
1096}
1097
1098// static
1099void LLImageGL::deleteTextures(S32 numTextures, U32 *textures, bool immediate)
1100{
1101	for (S32 i = 0; i < numTextures; i++)
1102	{
1103		sDeadTextureList.push_back(textures[i]);
1104	}
1105
1106	if (immediate)
1107	{
1108		LLImageGL::deleteDeadTextures();
1109	}
1110}
1111
1112// static
1113void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels)
1114{
1115	bool use_scratch = false;
1116	U32* scratch = NULL;
1117	if (LLRender::sGLCoreProfile)
1118	{
1119		if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE) 
1120		{ //GL_ALPHA is deprecated, convert to RGBA
1121			use_scratch = true;
1122			scratch = new U32[width*height];
1123
1124			U32 pixel_count = (U32) (width*height);
1125			for (U32 i = 0; i < pixel_count; i++)
1126			{
1127				U8* pix = (U8*) &scratch[i];
1128				pix[0] = pix[1] = pix[2] = 0;
1129				pix[3] = ((U8*) pixels)[i];
1130			}				
1131			
1132			pixformat = GL_RGBA;
1133			intformat = GL_RGBA8;
1134		}
1135
1136		if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE) 
1137		{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA
1138			use_scratch = true;
1139			scratch = new U32[width*height];
1140
1141			U32 pixel_count = (U32) (width*height);
1142			for (U32 i = 0; i < pixel_count; i++)
1143			{
1144				U8 lum = ((U8*) pixels)[i*2+0];
1145				U8 alpha = ((U8*) pixels)[i*2+1];
1146
1147				U8* pix = (U8*) &scratch[i];
1148				pix[0] = pix[1] = pix[2] = lum;
1149				pix[3] = alpha;
1150			}				
1151			
1152			pixformat = GL_RGBA;
1153			intformat = GL_RGBA8;
1154		}
1155
1156		if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE) 
1157		{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGB
1158			use_scratch = true;
1159			scratch = new U32[width*height];
1160
1161			U32 pixel_count = (U32) (width*height);
1162			for (U32 i = 0; i < pixel_count; i++)
1163			{
1164				U8 lum = ((U8*) pixels)[i];
1165				
1166				U8* pix = (U8*) &scratch[i];
1167				pix[0] = pix[1] = pix[2] = lum;
1168				pix[3] = 255;
1169			}				
1170			
1171			pixformat = GL_RGBA;
1172			intformat = GL_RGB8;
1173		}
1174	}
1175
1176	stop_glerror();
1177	glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels);
1178	stop_glerror();
1179
1180	if (use_scratch)
1181	{
1182		delete [] scratch;
1183	}
1184}
1185
1186//create an empty GL texture: just create a texture name
1187//the texture is assiciate with some image by calling glTexImage outside LLImageGL
1188BOOL LLImageGL::createGLTexture()
1189{
1190	if (gHeadlessClient) return FALSE;
1191	if (gGLManager.mIsDisabled)
1192	{
1193		llwarns << "Trying to create a texture while GL is disabled!" << llendl;
1194		return FALSE;
1195	}
1196	
1197	mGLTextureCreated = false ; //do not save this texture when gl is destroyed.
1198
1199	llassert(gGLManager.mInited);
1200	stop_glerror();
1201
1202	if(mTexName)
1203	{
1204		glDeleteTextures(1, (reinterpret_cast<GLuint*>(&mTexName))) ;
1205	}
1206	
1207	glGenTextures(1, (GLuint*)&mTexName);
1208	stop_glerror();
1209	if (!mTexName)
1210	{
1211		llerrs << "LLImageGL::createGLTexture failed to make an empty texture" << llendl;
1212	}
1213
1214	return TRUE ;
1215}
1216
1217BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category)
1218{
1219	if (gHeadlessClient) return FALSE;
1220	if (gGLManager.mIsDisabled)
1221	{
1222		llwarns << "Trying to create a texture while GL is disabled!" << llendl;
1223		return FALSE;
1224	}
1225
1226	mGLTextureCreated = false ;
1227	llassert(gGLManager.mInited);
1228	stop_glerror();
1229
1230	if (discard_level < 0)
1231	{
1232		llassert(mCurrentDiscardLevel >= 0);
1233		discard_level = mCurrentDiscardLevel;
1234	}
1235	discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
1236
1237	// Actual image width/height = raw image width/height * 2^discard_level
1238	S32 raw_w = imageraw->getWidth() ;
1239	S32 raw_h = imageraw->getHeight() ;
1240	S32 w = raw_w << discard_level;
1241	S32 h = raw_h << discard_level;
1242
1243	// setSize may call destroyGLTexture if the size does not match
1244	setSize(w, h, imageraw->getComponents());
1245
1246	if( !mHasExplicitFormat )
1247	{
1248		switch (mComponents)
1249		{
1250			case 1:
1251			// Use luminance alpha (for fonts)
1252			mFormatInternal = GL_LUMINANCE8;
1253			mFormatPrimary = GL_LUMINANCE;
1254			mFormatType = GL_UNSIGNED_BYTE;
1255			break;
1256			case 2:
1257			// Use luminance alpha (for fonts)
1258			mFormatInternal = GL_LUMINANCE8_ALPHA8;
1259			mFormatPrimary = GL_LUMINANCE_ALPHA;
1260			mFormatType = GL_UNSIGNED_BYTE;
1261			break;
1262			case 3:
1263			mFormatInternal = GL_RGB8;
1264			mFormatPrimary = GL_RGB;
1265			mFormatType = GL_UNSIGNED_BYTE;
1266			break;
1267			case 4:
1268			mFormatInternal = GL_RGBA8;
1269			mFormatPrimary = GL_RGBA;
1270			mFormatType = GL_UNSIGNED_BYTE;
1271			break;
1272			default:
1273			llerrs << "Bad number of components for texture: " << (U32)getComponents() << llendl;
1274		}
1275
1276		calcAlphaChannelOffsetAndStride() ;
1277	}
1278
1279	if(!to_create) //not create a gl texture
1280	{
1281		destroyGLTexture();
1282		mCurrentDiscardLevel = discard_level;	
1283		mLastBindTime = sLastFrameTime;
1284		return TRUE ;
1285	}
1286
1287	setCategory(category) ;
1288 	const U8* rawdata = imageraw->getData();
1289	return createGLTexture(discard_level, rawdata, FALSE, usename);
1290}
1291
1292BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename)
1293{
1294	llassert(data_in);
1295	stop_glerror();
1296
1297	if (discard_level < 0)
1298	{
1299		llassert(mCurrentDiscardLevel >= 0);
1300		discard_level = mCurrentDiscardLevel;
1301	}
1302	discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
1303
1304	if (mTexName != 0 && discard_level == mCurrentDiscardLevel)
1305	{
1306		// This will only be true if the size has not changed
1307		setImage(data_in, data_hasmips);
1308		return TRUE;
1309	}
1310	
1311	U32 old_name = mTexName;
1312// 	S32 old_discard = mCurrentDiscardLevel;
1313	
1314	if (usename != 0)
1315	{
1316		mTexName = usename;
1317	}
1318	else
1319	{
1320		LLImageGL::generateTextures(1, &mTexName);
1321		stop_glerror();
1322		{
1323			llverify(gGL.getTexUnit(0)->bind(this));
1324			stop_glerror();
1325			glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0);
1326			stop_glerror();
1327			glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL,  mMaxDiscardLevel-discard_level);
1328			stop_glerror();
1329		}
1330	}
1331	if (!mTexName)
1332	{
1333		llerrs << "LLImageGL::createGLTexture failed to make texture" << llendl;
1334	}
1335
1336	if (mUseMipMaps)
1337	{
1338		mAutoGenMips = gGLManager.mHasMipMapGeneration;
1339#if LL_DARWIN
1340		// On the Mac GF2 and GF4MX drivers, auto mipmap generation doesn't work right with alpha-only textures.
1341		if(gGLManager.mIsGF2or4MX && (mFormatInternal == GL_ALPHA8) && (mFormatPrimary == GL_ALPHA))
1342		{
1343			mAutoGenMips = FALSE;
1344		}
1345#endif
1346	}
1347
1348	mCurrentDiscardLevel = discard_level;	
1349
1350	setImage(data_in, data_hasmips);
1351
1352	// Set texture options to our defaults.
1353	gGL.getTexUnit(0)->setHasMipMaps(mHasMipMaps);
1354	gGL.getTexUnit(0)->setTextureAddressMode(mAddressMode);
1355	gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption);
1356
1357	// things will break if we don't unbind after creation
1358	gGL.getTexUnit(0)->unbind(mBindTarget);
1359	stop_glerror();
1360
1361	if (old_name != 0)
1362	{
1363		sGlobalTextureMemoryInBytes -= mTextureMemory;
1364
1365		if(gAuditTexture)
1366		{
1367			decTextureCounter(mTextureMemory, mComponents, mCategory) ;
1368		}
1369
1370		LLImageGL::deleteTextures(1, &old_name);
1371
1372		stop_glerror();
1373	}
1374
1375	mTextureMemory = getMipBytes(discard_level);
1376	sGlobalTextureMemoryInBytes += mTextureMemory;
1377	mTexelsInGLTexture = getWidth() * getHeight() ;
1378
1379	if(gAuditTexture)
1380	{
1381		incTextureCounter(mTextureMemory, mComponents, mCategory) ;
1382	}
1383	// mark this as bound at this point, so we don't throw it out immediately
1384	mLastBindTime = sLastFrameTime;
1385	return TRUE;
1386}
1387
1388BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const
1389{
1390	llassert_always(sAllowReadBackRaw) ;
1391	//llerrs << "should not call this function!" << llendl ;
1392	
1393	if (discard_level < 0)
1394	{
1395		discard_level = mCurrentDiscardLevel;
1396	}
1397	
1398	if (mTexName == 0 || discard_level < mCurrentDiscardLevel || discard_level > mMaxDiscardLevel )
1399	{
1400		return FALSE;
1401	}
1402
1403	S32 gl_discard = discard_level - mCurrentDiscardLevel;
1404
1405	//explicitly unbind texture 
1406	gGL.getTexUnit(0)->unbind(mBindTarget);
1407	llverify(gGL.getTexUnit(0)->bindManual(mBindTarget, mTexName));	
1408
1409	//debug code, leave it there commented.
1410	//checkTexSize() ;
1411
1412	LLGLint glwidth = 0;
1413	glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_WIDTH, (GLint*)&glwidth);
1414	if (glwidth == 0)
1415	{
1416		// No mip data smaller than current discard level
1417		return FALSE;
1418	}
1419	
1420	S32 width = getWidth(discard_level);
1421	S32 height = getHeight(discard_level);
1422	S32 ncomponents = getComponents();
1423	if (ncomponents == 0)
1424	{
1425		return FALSE;
1426	}
1427	if(width < glwidth)
1428	{
1429		llwarns << "texture size is smaller than it should be." << llendl ;
1430		llwarns << "width: " << width << " glwidth: " << glwidth << " mWidth: " << mWidth << 
1431			" mCurrentDiscardLevel: " << (S32)mCurrentDiscardLevel << " discard_level: " << (S32)discard_level << llendl ;
1432		return FALSE ;
1433	}
1434
1435	if (width <= 0 || width > 2048 || height <= 0 || height > 2048 || ncomponents < 1 || ncomponents > 4)
1436	{
1437		llerrs << llformat("LLImageGL::readBackRaw: bogus params: %d x %d x %d",width,height,ncomponents) << llendl;
1438	}
1439	
1440	LLGLint is_compressed = 0;
1441	if (compressed_ok)
1442	{
1443		glGetTexLevelParameteriv(mTarget, is_compressed, GL_TEXTURE_COMPRESSED, (GLint*)&is_compressed);
1444	}
1445	
1446	//-----------------------------------------------------------------------------------------------
1447	GLenum error ;
1448	while((error = glGetError()) != GL_NO_ERROR)
1449	{
1450		llwarns << "GL Error happens before reading back texture. Error code: " << error << llendl ;
1451	}
1452	//-----------------------------------------------------------------------------------------------
1453
1454	if (is_compressed)
1455	{
1456		LLGLint glbytes;
1457		glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, (GLint*)&glbytes);
1458		if(!imageraw->allocateDataSize(width, height, ncomponents, glbytes))
1459		{
1460			llwarns << "Memory allocation failed for reading back texture. Size is: " << glbytes << llendl ;
1461			llwarns << "width: " << width << "height: " << height << "components: " << ncomponents << llendl ;
1462			return FALSE ;
1463		}
1464
1465		glGetCompressedTexImageARB(mTarget, gl_discard, (GLvoid*)(imageraw->getData()));		
1466		//stop_glerror();
1467	}
1468	else
1469	{
1470		if(!imageraw->allocateDataSize(width, height, ncomponents))
1471		{
1472			llwarns << "Memory allocation failed for reading back texture." << llendl ;
1473			llwarns << "width: " << width << "height: " << height << "components: " << ncomponents << llendl ;
1474			return FALSE ;
1475		}
1476		
1477		glGetTexImage(GL_TEXTURE_2D, gl_discard, mFormatPrimary, mFormatType, (GLvoid*)(imageraw->getData()));		
1478		//stop_glerror();
1479	}
1480		
1481	//-----------------------------------------------------------------------------------------------
1482	if((error = glGetError()) != GL_NO_ERROR)
1483	{
1484		llwarns << "GL Error happens after reading back texture. Error code: " << error << llendl ;
1485		imageraw->deleteData() ;
1486
1487		while((error = glGetError()) != GL_NO_ERROR)
1488		{
1489			llwarns << "GL Error happens after reading back texture. Error code: " << error << llendl ;
1490		}
1491
1492		return FALSE ;
1493	}
1494	//-----------------------------------------------------------------------------------------------
1495
1496	return TRUE ;
1497}
1498
1499void LLImageGL::deleteDeadTextures()
1500{
1501	bool reset = false;
1502
1503	while (!sDeadTextureList.empty())
1504	{
1505		GLuint tex = sDeadTextureList.front();
1506		sDeadTextureList.pop_front();
1507		for (int i = 0; i < gGLManager.mNumTextureImageUnits; i++)
1508		{
1509			LLTexUnit* tex_unit = gGL.getTexUnit(i);
1510
1511			if (tex_unit && tex_unit->getCurrTexture() == tex)
1512			{
1513				tex_unit->unbind(tex_unit->getCurrType());
1514				stop_glerror();
1515
1516				if (i > 0)
1517				{
1518					reset = true;
1519				}
1520			}
1521		}
1522		
1523		glDeleteTextures(1, &tex);
1524		stop_glerror();
1525	}
1526
1527	if (reset)
1528	{
1529		gGL.getTexUnit(0)->activate();
1530	}
1531}
1532		
1533void LLImageGL::destroyGLTexture()
1534{
1535	if (mTexName != 0)
1536	{
1537		if(mTextureMemory)
1538		{
1539			if(gAuditTexture)
1540			{
1541				decTextureCounter(mTextureMemory, mComponents, mCategory) ;
1542			}
1543			sGlobalTextureMemoryInBytes -= mTextureMemory;
1544			mTextureMemory = 0;
1545		}
1546		
1547		LLImageGL::deleteTextures(1, &mTexName);			
1548		mTexName = 0;
1549		mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.
1550		mGLTextureCreated = FALSE ;
1551	}
1552}
1553
1554
1555
1556//----------------------------------------------------------------------------
1557
1558void LLImageGL::setAddressMode(LLTexUnit::eTextureAddressMode mode)
1559{
1560	if (mAddressMode != mode)
1561	{
1562		mTexOptionsDirty = true;
1563		mAddressMode = mode;
1564	}
1565
1566	if (gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName)
1567	{
1568		gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureAddressMode(mode);
1569		mTexOptionsDirty = false;
1570	}
1571}
1572
1573void LLImageGL::setFilteringOption(LLTexUnit::eTextureFilterOptions option)
1574{
1575	if (mFilterOption != option)
1576	{
1577		mTexOptionsDirty = true;
1578		mFilterOption = option;
1579	}
1580
1581	if (mTexName != 0 && gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName)
1582	{
1583		gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureFilteringOption(option);
1584		mTexOptionsDirty = false;
1585		stop_glerror();
1586	}
1587}
1588
1589BOOL LLImageGL::getIsResident(BOOL test_now)
1590{
1591	if (test_now)
1592	{
1593		if (mTexName != 0)
1594		{
1595			glAreTexturesResident(1, (GLuint*)&mTexName, &mIsResident);
1596		}
1597		else
1598		{
1599			mIsResident = FALSE;
1600		}
1601	}
1602
1603	return mIsResident;
1604}
1605
1606S32 LLImageGL::getHeight(S32 discard_level) const
1607{
1608	if (discard_level < 0)
1609	{
1610		discard_level = mCurrentDiscardLevel;
1611	}
1612	S32 height = mHeight >> discard_level;
1613	if (height < 1) height = 1;
1614	return height;
1615}
1616
1617S32 LLImageGL::getWidth(S32 discard_level) const
1618{
1619	if (discard_level < 0)
1620	{
1621		discard_level = mCurrentDiscardLevel;
1622	}
1623	S32 width = mWidth >> discard_level;
1624	if (width < 1) width = 1;
1625	return width;
1626}
1627
1628S32 LLImageGL::getBytes(S32 discard_level) const
1629{
1630	if (discard_level < 0)
1631	{
1632		discard_level = mCurrentDiscardLevel;
1633	}
1634	S32 w = mWidth>>discard_level;
1635	S32 h = mHeight>>discard_level;
1636	if (w == 0) w = 1;
1637	if (h == 0) h = 1;
1638	return dataFormatBytes(mFormatPrimary, w, h);
1639}
1640
1641S32 LLImageGL::getMipBytes(S32 discard_level) const
1642{
1643	if (discard_level < 0)
1644	{
1645		discard_level = mCurrentDiscardLevel;
1646	}
1647	S32 w = mWidth>>discard_level;
1648	S32 h = mHeight>>discard_level;
1649	S32 res = dataFormatBytes(mFormatPrimary, w, h);
1650	if (mUseMipMaps)
1651	{
1652		while (w > 1 && h > 1)
1653		{
1654			w >>= 1; if (w == 0) w = 1;
1655			h >>= 1; if (h == 0) h = 1;
1656			res += dataFormatBytes(mFormatPrimary, w, h);
1657		}
1658	}
1659	return res;
1660}
1661
1662BOOL LLImageGL::isJustBound() const
1663{
1664	return (BOOL)(sLastFrameTime - mLastBindTime < 0.5f);
1665}
1666
1667BOOL LLImageGL::getBoundRecently() const
1668{
1669	return (BOOL)(sLastFrameTime - mLastBindTime < MIN_TEXTURE_LIFETIME);
1670}
1671
1672void LLImageGL::setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target)
1673{
1674	mTarget = target;
1675	mBindTarget = bind_target;
1676}
1677
1678const S8 INVALID_OFFSET = -99 ;
1679void LLImageGL::setNeedsAlphaAndPickMask(BOOL need_mask) 
1680{
1681	if(mNeedsAlphaAndPickMask != need_mask)
1682	{
1683		mNeedsAlphaAndPickMask = need_mask;
1684
1685		if(mNeedsAlphaAndPickMask)
1686		{
1687			mAlphaOffset = 0 ;
1688		}
1689		else //do not need alpha mask
1690		{
1691			mAlphaOffset = INVALID_OFFSET ;
1692			mIsMask = FALSE;
1693		}
1694	}
1695}
1696
1697void LLImageGL::calcAlphaChannelOffsetAndStride()
1698{
1699	if(mAlphaOffset == INVALID_OFFSET)//do not need alpha mask
1700	{
1701		return ;
1702	}
1703
1704	mAlphaStride = -1 ;
1705	switch (mFormatPrimary)
1706	{
1707	case GL_LUMINANCE:
1708	case GL_ALPHA:
1709		mAlphaStride = 1;
1710		break;
1711	case GL_LUMINANCE_ALPHA:
1712		mAlphaStride = 2;
1713		break;
1714	case GL_RGB:
1715		mNeedsAlphaAndPickMask = FALSE ;
1716		mIsMask = FALSE;
1717		return ; //no alpha channel.
1718	case GL_RGBA:
1719		mAlphaStride = 4;
1720		break;
1721	case GL_BGRA_EXT:
1722		mAlphaStride = 4;
1723		break;
1724	default:
1725		break;
1726	}
1727
1728	mAlphaOffset = -1 ;
1729	if (mFormatType == GL_UNSIGNED_BYTE)
1730	{
1731		mAlphaOffset = mAlphaStride - 1 ;
1732	}
1733	else if(is_little_endian())
1734	{
1735		if (mFormatType == GL_UNSIGNED_INT_8_8_8_8)
1736		{
1737			mAlphaOffset = 0 ;
1738		}
1739		else if (mFormatType == GL_UNSIGNED_INT_8_8_8_8_REV)
1740		{
1741			mAlphaOffset = 3 ;
1742		}
1743	}
1744	else //big endian
1745	{
1746		if (mFormatType == GL_UNSIGNED_INT_8_8_8_8)
1747		{
1748			mAlphaOffset = 3 ;
1749		}
1750		else if (mFormatType == GL_UNSIGNED_INT_8_8_8_8_REV)
1751		{
1752			mAlphaOffset = 0 ;
1753		}
1754	}
1755
1756	if( mAlphaStride < 1 || //unsupported format
1757		mAlphaOffset < 0 || //unsupported type
1758		(mFormatPrimary == GL_BGRA_EXT && mFormatType != GL_UNSIGNED_BYTE)) //unknown situation
1759	{
1760		llwarns << "Cannot analyze alpha for image with format type " << std::hex << mFormatType << std::dec << llendl;
1761
1762		mNeedsAlphaAndPickMask = FALSE ;
1763		mIsMask = FALSE;
1764	}
1765}
1766
1767void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
1768{
1769	if(!mNeedsAlphaAndPickMask)
1770	{
1771		return ;
1772	}
1773
1774	U32 length = w * h;
1775	U32 alphatotal = 0;
1776	
1777	U32 sample[16];
1778	memset(sample, 0, sizeof(U32)*16);
1779
1780	// generate histogram of quantized alpha.
1781	// also add-in the histogram of a 2x2 box-sampled version.  The idea is
1782	// this will mid-skew the data (and thus increase the chances of not
1783	// being used as a mask) from high-frequency alpha maps which
1784	// suffer the worst from aliasing when used as alpha masks.
1785	if (w >= 2 && h >= 2)
1786	{
1787		llassert(w%2 == 0);
1788		llassert(h%2 == 0);
1789		const GLubyte* rowstart = ((const GLubyte*) data_in) + mAlphaOffset;
1790		for (U32 y = 0; y < h; y+=2)
1791		{
1792			const GLubyte* current = rowstart;
1793			for (U32 x = 0; x < w; x+=2)
1794			{
1795				const U32 s1 = current[0];
1796				alphatotal += s1;
1797				const U32 s2 = current[w * mAlphaStride];
1798				alphatotal += s2;
1799				current += mAlphaStride;
1800				const U32 s3 = current[0];
1801				alphatotal += s3;
1802				const U32 s4 = current[w * mAlphaStride];
1803				alphatotal += s4;
1804				current += mAlphaStride;
1805
1806				++sample[s1/16];
1807				++sample[s2/16];
1808				++sample[s3/16];
1809				++sample[s4/16];
1810
1811				const U32 asum = (s1+s2+s3+s4);
1812				alphatotal += asum;
1813				sample[asum/(16*4)] += 4;
1814			}
1815			
1816			
1817			rowstart += 2 * w * mAlphaStride;
1818		}
1819		length *= 2; // we sampled everything twice, essentially
1820	}
1821	else
1822	{
1823		const GLubyte* current = ((const GLubyte*) data_in) + mAlphaOffset;
1824		for (U32 i = 0; i < length; i++)
1825		{
1826			const U32 s1 = *current;
1827			alphatotal += s1;
1828			++sample[s1/16];
1829			current += mAlphaStride;
1830		}
1831	}
1832	
1833	// if more than 1/16th of alpha samples are mid-range, this
1834	// shouldn't be treated as a 1-bit mask
1835
1836	// also, if all of the alpha samples are clumped on one half
1837	// of the range (but not at an absolute extreme), then consider
1838	// this to be an intentional effect and don't treat as a mask.
1839
1840	U32 midrangetotal = 0;
1841	for (U32 i = 2; i < 13; i++)
1842	{
1843		midrangetotal += sample[i];
1844	}
1845	U32 lowerhalftotal = 0;
1846	for (U32 i = 0; i < 8; i++)
1847	{
1848		lowerhalftotal += sample[i];
1849	}
1850	U32 upperhalftotal = 0;
1851	for (U32 i = 8; i < 16; i++)
1852	{
1853		upperhalftotal += sample[i];
1854	}
1855
1856	if (midrangetotal > length/48 || // lots of midrange, or
1857	    (lowerhalftotal == length && alphatotal != 0) || // all close to transparent but not all totally transparent, or
1858	    (upperhalftotal == length && alphatotal != 255*length)) // all close to opaque but not all totally opaque
1859	{
1860		mIsMask = FALSE; // not suitable for masking
1861	}
1862	else
1863	{
1864		mIsMask = TRUE;
1865	}
1866}
1867
1868//----------------------------------------------------------------------------
1869void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
1870{
1871	if(!mNeedsAlphaAndPickMask)
1872	{
1873		return ;
1874	}
1875
1876	delete [] mPickMask;
1877	mPickMask = NULL;
1878	mPickMaskWidth = mPickMaskHeight = 0;
1879
1880	if (mFormatType != GL_UNSIGNED_BYTE ||
1881	    mFormatPrimary != GL_RGBA)
1882	{
1883		//cannot generate a pick mask for this texture
1884		return;
1885	}
1886
1887	U32 pick_width = width/2 + 1;
1888	U32 pick_height = height/2 + 1;
1889
1890	U32 size = pick_width * pick_height;
1891	size = (size + 7) / 8; // pixelcount-to-bits
1892	mPickMask = new U8[size];
1893	mPickMaskWidth = pick_width - 1;
1894	mPickMaskHeight = pick_height - 1;
1895
1896	memset(mPickMask, 0, sizeof(U8) * size);
1897
1898	U32 pick_bit = 0;
1899	
1900	for (S32 y = 0; y < height; y += 2)
1901	{
1902		for (S32 x = 0; x < width; x += 2)
1903		{
1904			U8 alpha = data_in[(y*width+x)*4+3];
1905
1906			if (alpha > 32)
1907			{
1908				U32 pick_idx = pick_bit/8;
1909				U32 pick_offset = pick_bit%8;
1910				llassert(pick_idx < size);
1911
1912				mPickMask[pick_idx] |= 1 << pick_offset;
1913			}
1914			
1915			++pick_bit;
1916		}
1917	}
1918}
1919
1920BOOL LLImageGL::getMask(const LLVector2 &tc)
1921{
1922	BOOL res = TRUE;
1923
1924	if (mPickMask)
1925	{
1926		F32 u,v;
1927		if (LL_LIKELY(tc.isFinite()))
1928		{
1929			u = tc.mV[0] - floorf(tc.mV[0]);
1930			v = tc.mV[1] - floorf(tc.mV[1]);
1931		}
1932		else
1933		{
1934			LL_WARNS_ONCE("render") << "Ugh, non-finite u/v in mask pick" << LL_ENDL;
1935			u = v = 0.f;
1936			// removing assert per EXT-4388
1937			// llassert(false);
1938		}
1939
1940		if (LL_UNLIKELY(u < 0.f || u > 1.f ||
1941				v < 0.f || v > 1.f))
1942		{
1943			LL_WARNS_ONCE("render") << "Ugh, u/v out of range in image mask pick" << LL_ENDL;
1944			u = v = 0.f;
1945			// removing assert per EXT-4388
1946			// llassert(false);
1947		}
1948
1949		S32 x = llfloor(u * mPickMaskWidth);
1950		S32 y = llfloor(v * mPickMaskHeight);
1951
1952		if (LL_UNLIKELY(x > mPickMaskWidth))
1953		{
1954			LL_WARNS_ONCE("render") << "Ooh, width overrun on pick mask read, that coulda been bad." << LL_ENDL;
1955			x = llmax((U16)0, mPickMaskWidth);
1956		}
1957		if (LL_UNLIKELY(y > mPickMaskHeight))
1958		{
1959			LL_WARNS_ONCE("render") << "Ooh, height overrun on pick mask read, that woulda been bad." << LL_ENDL;
1960			y = llmax((U16)0, mPickMaskHeight);
1961		}
1962
1963		S32 idx = y*mPickMaskWidth+x;
1964		S32 offset = idx%8;
1965
1966		res = mPickMask[idx/8] & (1 << offset) ? TRUE : FALSE;
1967	}
1968	
1969	return res;
1970}
1971
1972void LLImageGL::setCategory(S32 category) 
1973{
1974#if 0 //turn this off temporarily because it is not in use now.
1975	if(!gAuditTexture)
1976	{
1977		return ;
1978	}
1979	if(mCategory != category)
1980	{		
1981		if(mCategory > -1)
1982		{
1983			sTextureMemByCategory[mCategory] -= mTextureMemory ;
1984		}
1985		if(category > -1 && category < sMaxCatagories)
1986		{
1987			sTextureMemByCategory[category] += mTextureMemory ;		
1988			mCategory = category;
1989		}
1990		else
1991		{
1992			mCategory = -1 ;
1993		}
1994	}
1995#endif
1996}
1997
1998//for debug use 
1999//val is a "power of two" number
2000S32 LLImageGL::getTextureCounterIndex(U32 val) 
2001{
2002	//index range is [0, MAX_TEXTURE_LOG_SIZE].
2003	if(val < 2)
2004	{
2005		return 0 ;
2006	}
2007	else if(val >= (1 << MAX_TEXTURE_LOG_SIZE))
2008	{
2009		return MAX_TEXTURE_LOG_SIZE ;
2010	}
2011	else
2012	{
2013		S32 ret = 0 ;
2014		while(val >>= 1)
2015		{
2016			++ret;
2017		}
2018		return ret ;
2019	}
2020}
2021
2022//static
2023void LLImageGL::incTextureCounter(U32 val, S32 ncomponents, S32 category) 
2024{
2025	sTextu

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