PageRenderTime 137ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/newview/lltextureatlas.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 417 lines | 307 code | 49 blank | 61 comment | 46 complexity | 479d6ea3e8e83dd6b2ec3c4966afe88a MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lltextureatlas.cpp
  3. * @brief LLTextureAtlas class implementation.
  4. *
  5. * $LicenseInfo:firstyear=2002&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. #include "llviewerprecompiledheaders.h"
  27. #include "linden_common.h"
  28. #include "llerror.h"
  29. #include "llimage.h"
  30. #include "llmath.h"
  31. #include "llgl.h"
  32. #include "llrender.h"
  33. #include "lltextureatlas.h"
  34. //-------------------
  35. S16 LLTextureAtlas::sMaxSubTextureSize = 64 ;
  36. S16 LLTextureAtlas::sSlotSize = 32 ;
  37. #ifndef DEBUG_ATLAS
  38. #define DEBUG_ATLAS 0
  39. #endif
  40. #ifndef DEBUG_USAGE_BITS
  41. #define DEBUG_USAGE_BITS 0
  42. #endif
  43. //**************************************************************************************************************
  44. LLTextureAtlas::LLTextureAtlas(U8 ncomponents, S16 atlas_dim) :
  45. LLViewerTexture(atlas_dim * sSlotSize, atlas_dim * sSlotSize, ncomponents, TRUE),
  46. mAtlasDim(atlas_dim),
  47. mNumSlotsReserved(0),
  48. mMaxSlotsInAtlas(atlas_dim * atlas_dim)
  49. {
  50. generateEmptyUsageBits() ;
  51. //generate an empty texture
  52. generateGLTexture() ;
  53. LLPointer<LLImageRaw> image_raw = new LLImageRaw(mFullWidth, mFullHeight, mComponents);
  54. createGLTexture(0, image_raw, 0);
  55. image_raw = NULL;
  56. }
  57. LLTextureAtlas::~LLTextureAtlas()
  58. {
  59. if(mSpatialGroupList.size() > 0)
  60. {
  61. llerrs << "Not clean up the spatial groups!" << llendl ;
  62. }
  63. releaseUsageBits() ;
  64. }
  65. //virtual
  66. S8 LLTextureAtlas::getType() const
  67. {
  68. return LLViewerTexture::ATLAS_TEXTURE ;
  69. }
  70. void LLTextureAtlas::getTexCoordOffset(S16 col, S16 row, F32& xoffset, F32& yoffset)
  71. {
  72. xoffset = (F32)col / mAtlasDim ;
  73. yoffset = (F32)row / mAtlasDim ;
  74. }
  75. void LLTextureAtlas::getTexCoordScale(S32 w, S32 h, F32& xscale, F32& yscale)
  76. {
  77. xscale = (F32)w / (mAtlasDim * sSlotSize) ;
  78. yscale = (F32)h / (mAtlasDim * sSlotSize) ;
  79. }
  80. //insert a texture piece into the atlas
  81. LLGLuint LLTextureAtlas::insertSubTexture(LLImageGL* source_gl_tex, S32 discard_level, const LLImageRaw* raw_image, S16 slot_col, S16 slot_row)
  82. {
  83. if(!getTexName())
  84. {
  85. return 0 ;
  86. }
  87. S32 w = raw_image->getWidth() ;
  88. S32 h = raw_image->getHeight() ;
  89. if(w < 8 || w > sMaxSubTextureSize || h < 8 || h > sMaxSubTextureSize)
  90. {
  91. //size overflow
  92. return 0 ;
  93. }
  94. BOOL res = gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getTexName());
  95. if (!res)
  96. {
  97. llerrs << "bindTexture failed" << llendl;
  98. }
  99. GLint xoffset = sSlotSize * slot_col ;
  100. GLint yoffset = sSlotSize * slot_row ;
  101. if(!source_gl_tex->preAddToAtlas(discard_level, raw_image))
  102. {
  103. return 0 ;
  104. }
  105. glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, TRUE);
  106. glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, w, h,
  107. mGLTexturep->getPrimaryFormat(), mGLTexturep->getFormatType(), raw_image->getData());
  108. source_gl_tex->postAddToAtlas() ;
  109. return getTexName();
  110. }
  111. //release a sub-texture slot from the atlas
  112. void LLTextureAtlas::releaseSlot(S16 slot_col, S16 slot_row, S8 slot_width)
  113. {
  114. unmarkUsageBits(slot_width, slot_col, slot_row) ;
  115. mNumSlotsReserved -= slot_width * slot_width ;
  116. }
  117. BOOL LLTextureAtlas::isEmpty() const
  118. {
  119. return !mNumSlotsReserved ;
  120. }
  121. BOOL LLTextureAtlas::isFull(S8 to_be_reserved) const
  122. {
  123. return mNumSlotsReserved + to_be_reserved > mMaxSlotsInAtlas ;
  124. }
  125. F32 LLTextureAtlas::getFullness() const
  126. {
  127. return (F32)mNumSlotsReserved / mMaxSlotsInAtlas ;
  128. }
  129. void LLTextureAtlas::addSpatialGroup(LLSpatialGroup* groupp)
  130. {
  131. if(groupp && !hasSpatialGroup(groupp))
  132. {
  133. mSpatialGroupList.push_back(groupp);
  134. }
  135. }
  136. void LLTextureAtlas::removeSpatialGroup(LLSpatialGroup* groupp)
  137. {
  138. if(groupp)
  139. {
  140. mSpatialGroupList.remove(groupp);
  141. }
  142. }
  143. void LLTextureAtlas::clearSpatialGroup()
  144. {
  145. mSpatialGroupList.clear();
  146. }
  147. void LLTextureAtlas::removeLastSpatialGroup()
  148. {
  149. mSpatialGroupList.pop_back() ;
  150. }
  151. LLSpatialGroup* LLTextureAtlas::getLastSpatialGroup()
  152. {
  153. if(mSpatialGroupList.size() > 0)
  154. {
  155. return mSpatialGroupList.back() ;
  156. }
  157. return NULL ;
  158. }
  159. BOOL LLTextureAtlas::hasSpatialGroup(LLSpatialGroup* groupp)
  160. {
  161. for(std::list<LLSpatialGroup*>::iterator iter = mSpatialGroupList.begin(); iter != mSpatialGroupList.end() ; ++iter)
  162. {
  163. if(*iter == groupp)
  164. {
  165. return TRUE ;
  166. }
  167. }
  168. return FALSE ;
  169. }
  170. //--------------------------------------------------------------------------------------
  171. //private
  172. void LLTextureAtlas::generateEmptyUsageBits()
  173. {
  174. S32 col_len = (mAtlasDim + 7) >> 3 ;
  175. mUsageBits = new U8*[mAtlasDim] ;
  176. *mUsageBits = new U8[mAtlasDim * col_len] ;
  177. mUsageBits[0] = *mUsageBits ;
  178. for(S32 i = 1 ; i < mAtlasDim ; i++)
  179. {
  180. mUsageBits[i] = mUsageBits[i-1] + col_len ;
  181. for(S32 j = 0 ; j < col_len ; j++)
  182. {
  183. //init by 0 for all bits.
  184. mUsageBits[i][j] = 0 ;
  185. }
  186. }
  187. //do not forget mUsageBits[0]!
  188. for(S32 j = 0 ; j < col_len ; j++)
  189. {
  190. //init by 0 for all bits.
  191. mUsageBits[0][j] = 0 ;
  192. }
  193. mTestBits = NULL ;
  194. #if DEBUG_USAGE_BITS
  195. //------------
  196. //test
  197. mTestBits = new U8*[mAtlasDim] ;
  198. *mTestBits = new U8[mAtlasDim * mAtlasDim] ;
  199. mTestBits[0] = *mTestBits ;
  200. for(S32 i = 1 ; i < mAtlasDim ; i++)
  201. {
  202. mTestBits[i] = mTestBits[i-1] + mAtlasDim ;
  203. for(S32 j = 0 ; j < mAtlasDim ; j++)
  204. {
  205. //init by 0 for all bits.
  206. mTestBits[i][j] = 0 ;
  207. }
  208. }
  209. for(S32 j = 0 ; j < mAtlasDim ; j++)
  210. {
  211. //init by 0 for all bits.
  212. mTestBits[0][j] = 0 ;
  213. }
  214. #endif
  215. }
  216. void LLTextureAtlas::releaseUsageBits()
  217. {
  218. if(mUsageBits)
  219. {
  220. delete[] *mUsageBits ;
  221. delete[] mUsageBits ;
  222. }
  223. mUsageBits = NULL ;
  224. //test
  225. if( mTestBits)
  226. {
  227. delete[] *mTestBits;
  228. delete[] mTestBits;
  229. }
  230. mTestBits = NULL ;
  231. }
  232. void LLTextureAtlas::markUsageBits(S8 bits_len, U8 mask, S16 col, S16 row)
  233. {
  234. S16 x = col >> 3 ;
  235. for(S8 i = 0 ; i < bits_len ; i++)
  236. {
  237. mUsageBits[row + i][x] |= mask ;
  238. }
  239. #if DEBUG_USAGE_BITS
  240. //test
  241. for(S8 i = row ; i < row + bits_len ; i++)
  242. {
  243. for(S8 j = col ; j < col + bits_len ; j++)
  244. {
  245. mTestBits[i][j] = 1 ;
  246. }
  247. }
  248. #endif
  249. }
  250. void LLTextureAtlas::unmarkUsageBits(S8 bits_len, S16 col, S16 row)
  251. {
  252. S16 x = col >> 3 ;
  253. U8 mask = 1 ;
  254. for(S8 i = 1 ; i < bits_len ; i++)
  255. {
  256. mask |= (1 << i) ;
  257. }
  258. mask <<= (col & 7) ;
  259. mask = ~mask ;
  260. for(S8 i = 0 ; i < bits_len ; i++)
  261. {
  262. mUsageBits[row + i][x] &= mask ;
  263. }
  264. #if DEBUG_USAGE_BITS
  265. //test
  266. for(S8 i = row ; i < row + bits_len ; i++)
  267. {
  268. for(S8 j = col ; j < col + bits_len ; j++)
  269. {
  270. mTestBits[i][j] = 0 ;
  271. }
  272. }
  273. #endif
  274. }
  275. //return true if any of bits in the range marked.
  276. BOOL LLTextureAtlas::areUsageBitsMarked(S8 bits_len, U8 mask, S16 col, S16 row)
  277. {
  278. BOOL ret = FALSE ;
  279. S16 x = col >> 3 ;
  280. for(S8 i = 0 ; i < bits_len ; i++)
  281. {
  282. if(mUsageBits[row + i][x] & mask)
  283. {
  284. ret = TRUE ;
  285. break ;
  286. //return TRUE ;
  287. }
  288. }
  289. #if DEBUG_USAGE_BITS
  290. //test
  291. BOOL ret2 = FALSE ;
  292. for(S8 i = row ; i < row + bits_len ; i++)
  293. {
  294. for(S8 j = col ; j < col + bits_len ; j++)
  295. {
  296. if(mTestBits[i][j])
  297. {
  298. ret2 = TRUE ;
  299. }
  300. }
  301. }
  302. if(ret != ret2)
  303. {
  304. llerrs << "bits map corrupted." << llendl ;
  305. }
  306. #endif
  307. return ret ;//FALSE ;
  308. }
  309. //----------------------------------------------------------------------
  310. //
  311. //index order: Z order, i.e.:
  312. // |-----|-----|-----|-----|
  313. // | 10 | 11 | 14 | 15 |
  314. // |-----|-----|-----|-----|
  315. // | 8 | 9 | 12 | 13 |
  316. // |-----|-----|-----|-----|
  317. // | 2 | 3 | 6 | 7 |
  318. // |-----|-----|-----|-----|
  319. // | 0 | 1 | 4 | 5 |
  320. // |-----|-----|-----|-----|
  321. void LLTextureAtlas::getPositionFromIndex(S16 index, S16& col, S16& row)
  322. {
  323. col = 0 ;
  324. row = 0 ;
  325. S16 index_copy = index ;
  326. for(S16 i = 0 ; index_copy && i < 16 ; i += 2)
  327. {
  328. col |= ((index & (1 << i)) >> i) << (i >> 1) ;
  329. row |= ((index & (1 << (i + 1))) >> (i + 1)) << (i >> 1) ;
  330. index_copy >>= 2 ;
  331. }
  332. }
  333. void LLTextureAtlas::getIndexFromPosition(S16 col, S16 row, S16& index)
  334. {
  335. index = 0 ;
  336. S16 col_copy = col ;
  337. S16 row_copy = row ;
  338. for(S16 i = 0 ; (col_copy || row_copy) && i < 16 ; i++)
  339. {
  340. index |= ((col & 1 << i) << i) | ((row & 1 << i) << ( i + 1)) ;
  341. col_copy >>= 1 ;
  342. row_copy >>= 1 ;
  343. }
  344. }
  345. //----------------------------------------------------------------------
  346. //return TRUE if succeeds.
  347. BOOL LLTextureAtlas::getNextAvailableSlot(S8 bits_len, S16& col, S16& row)
  348. {
  349. S16 index_step = bits_len * bits_len ;
  350. U8 mask = 1 ;
  351. for(S8 i = 1 ; i < bits_len ; i++)
  352. {
  353. mask |= (1 << i) ;
  354. }
  355. U8 cur_mask ;
  356. for(S16 index = 0 ; index < mMaxSlotsInAtlas ; index += index_step)
  357. {
  358. getPositionFromIndex(index, col, row) ;
  359. cur_mask = mask << (col & 7) ;
  360. if(!areUsageBitsMarked(bits_len, cur_mask, col, row))
  361. {
  362. markUsageBits(bits_len, cur_mask, col, row) ;
  363. mNumSlotsReserved += bits_len * bits_len ;
  364. return TRUE ;
  365. }
  366. }
  367. return FALSE ;
  368. }