PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

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