lltextureatlasmanager.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:8k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lltextureatlasmanager.cpp
  3.  * @brief LLTextureAtlasManager class implementation.
  4.  *
  5.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2002-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "linden_common.h"
  34. #include "llerror.h"
  35. #include "llmath.h"
  36. #include "lltextureatlas.h"
  37. #include "lltextureatlasmanager.h"
  38. #include "llspatialpartition.h"
  39. const S8 MAX_NUM_EMPTY_ATLAS = 2 ;
  40. const F32 MIN_ATLAS_FULLNESS = 0.6f ;
  41. //*********************************************************************************************
  42. //implementation of class LLTextureAtlasInfo
  43. //*********************************************************************************************
  44. LLTextureAtlasSlot::LLTextureAtlasSlot(LLTextureAtlas* atlasp, LLSpatialGroup* groupp, S16 col, S16 row, F32 xoffset, F32 yoffset, S8 slot_width) : 
  45. mAtlasp(atlasp),
  46. mGroupp(groupp),
  47. mCol(col),
  48. mRow(row),
  49. mReservedSlotWidth(slot_width),
  50. mValid(FALSE),
  51. mUpdatedTime(0),
  52. mTexCoordOffset(xoffset, yoffset),
  53. mTexCoordScale(1.f, 1.f)
  54. {
  55. llassert_always(mAtlasp || mGroupp || mReservedSlotWidth) ;
  56. }
  57. LLTextureAtlasSlot::~LLTextureAtlasSlot()
  58. {
  59. if(mAtlasp)
  60. {
  61. mAtlasp->releaseSlot(mCol, mRow, mReservedSlotWidth) ;
  62. if(mAtlasp->isEmpty())
  63. {
  64. LLTextureAtlasManager::getInstance()->releaseAtlas(mAtlasp) ;
  65. }
  66. mAtlasp = NULL ;
  67. }
  68. }
  69. //void LLTextureAtlasSlot::setAtlas(LLTextureAtlas* atlasp) 
  70. //{
  71. // mAtlasp = atlasp ;
  72. //}
  73. //void LLTextureAtlasSlot::setSlotPos(S16 col, S16 row) 
  74. //{
  75. // mCol = col ;
  76. // mRow = row ;
  77. //}
  78. //void LLTextureAtlasSlot::setSlotWidth(S8 width) 
  79. //{
  80. // //slot is a square with each edge length a power-of-two number
  81. // mReservedSlotWidth = width ;
  82. //}
  83. //void LLTextureAtlasSlot::setTexCoordOffset(F32 xoffset, F32 yoffset) 
  84. //{
  85. // mTexCoordOffset.mV[0] = xoffset ;
  86. // mTexCoordOffset.mV[1] = yoffset ;
  87. //}
  88. void LLTextureAtlasSlot::setSpatialGroup(LLSpatialGroup* groupp) 
  89. {
  90. mGroupp = groupp ;
  91. }
  92. void LLTextureAtlasSlot::setTexCoordScale(F32 xscale, F32 yscale) 
  93. {
  94. mTexCoordScale.mV[0] = xscale ;
  95. mTexCoordScale.mV[1] = yscale ;
  96. }
  97. //*********************************************************************************************
  98. //END of implementation of class LLTextureAtlasInfo
  99. //*********************************************************************************************
  100. //*********************************************************************************************
  101. //implementation of class LLTextureAtlasManager
  102. //*********************************************************************************************
  103. LLTextureAtlasManager::LLTextureAtlasManager() :
  104. mAtlasMap(4),
  105. mEmptyAtlasMap(4) 
  106. {
  107. }
  108. LLTextureAtlasManager::~LLTextureAtlasManager()
  109. {
  110. for(S32 i = 0 ; i < 4 ; i++)
  111. {
  112. for(ll_texture_atlas_list_t::iterator j = mAtlasMap[i].begin() ; j != mAtlasMap[i].end() ; ++j)
  113. {
  114. *j = NULL ;
  115. }
  116. for(ll_texture_atlas_list_t::iterator j = mEmptyAtlasMap[i].begin() ; j != mEmptyAtlasMap[i].end() ; ++j)
  117. {
  118. *j = NULL ;
  119. }
  120. mAtlasMap[i].clear() ;
  121. mEmptyAtlasMap[i].clear() ;
  122. }
  123. mAtlasMap.clear() ;
  124. mEmptyAtlasMap.clear() ;
  125. }
  126. //return TRUE if qualified
  127. BOOL LLTextureAtlasManager::canAddToAtlas(S32 w, S32 h, S8 ncomponents, LLGLenum target) 
  128. {
  129. if(ncomponents < 1 || ncomponents > 4)
  130. {
  131. return FALSE ;
  132. }
  133. //only support GL_TEXTURE_2D
  134. if(GL_TEXTURE_2D != target)
  135. {
  136. return FALSE ;
  137. }
  138. //real image size overflows
  139. if(w < 8 || w > LLTextureAtlas::sMaxSubTextureSize || h < 8 || h > LLTextureAtlas::sMaxSubTextureSize)
  140. {
  141. return FALSE ;
  142. }
  143. //if non-power-of-two number
  144. if((w & (w - 1)) || (h & (h - 1)))
  145. {
  146. return FALSE ;
  147. }
  148. return TRUE ;
  149. }
  150. void LLTextureAtlasManager::releaseAtlas(LLTextureAtlas* atlasp)
  151. {
  152. LLSpatialGroup* groupp = atlasp->getLastSpatialGroup() ;
  153. while(groupp)
  154. {
  155. groupp->removeAtlas(atlasp, FALSE) ;
  156. atlasp->removeLastSpatialGroup() ;
  157. groupp = atlasp->getLastSpatialGroup() ;
  158. }
  159. S8 type = atlasp->getComponents() - 1 ;
  160. //insert to the empty list
  161. if(mEmptyAtlasMap[type].size() < MAX_NUM_EMPTY_ATLAS)
  162. {
  163. mEmptyAtlasMap[type].push_back(atlasp) ;
  164. }
  165. //delete the atlasp
  166. mAtlasMap[type].remove(atlasp) ;
  167. }
  168. //
  169. //this function reserves an appropriate slot from atlas pool for an image.
  170. //return non-NULL if succeeds.
  171. //Note:
  172. //1, this function does not check if the image this slot assigned for qualifies for atlas or not, 
  173. //       call LLTextureAtlasManager::canAddToAtlas(...) to do the check before calling this function.
  174. //2, this function also dose not check if the image is already in atlas. It always assigns a new slot anyway.
  175. //3, this function tries to group sub-textures from same spatial group into ONE atlas to improve render batching.
  176. //
  177. LLPointer<LLTextureAtlasSlot> LLTextureAtlasManager::reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents, 
  178.   LLSpatialGroup* groupp, LLViewerTexture* imagep)
  179. {
  180. if(!groupp)
  181. {
  182. //do not insert to atlas if does not have a group.
  183. return NULL ;
  184. }
  185. //bits_len must <= 8 and is a power of two number, i.e.: must be one of these numbers: 1, 2, 4, 8.
  186. if(sub_texture_size > LLTextureAtlas::sMaxSubTextureSize)
  187. {
  188. sub_texture_size = LLTextureAtlas::sMaxSubTextureSize ;
  189. }
  190. S8 bits_len = sub_texture_size / LLTextureAtlas::sSlotSize ;
  191. if(bits_len < 1)
  192. {
  193.    bits_len = 1 ;
  194. }
  195. S16 col = -1, row = -1;
  196. S8 total_bits = bits_len * bits_len ;
  197. //insert to the atlas reserved by the same spatial group
  198. LLPointer<LLTextureAtlas> atlasp = groupp->getAtlas(ncomponents, total_bits) ;
  199. if(atlasp.notNull())
  200. {
  201. if(!atlasp->getNextAvailableSlot(bits_len, col, row))
  202. {
  203. //failed
  204. atlasp = NULL ;
  205. }
  206. }
  207.    //search an atlas to fit for 'size'
  208. if(!atlasp)
  209. {
  210. S8 atlas_index = ncomponents - 1 ;
  211. ll_texture_atlas_list_t::iterator iter = mAtlasMap[atlas_index].begin() ;
  212. for(; iter != mAtlasMap[atlas_index].end(); ++iter) 
  213. {
  214. LLTextureAtlas* cur = (LLTextureAtlas*)*iter ;
  215. if(cur->getFullness() < MIN_ATLAS_FULLNESS)//this atlas is empty enough for this group to insert more sub-textures later if necessary.
  216. {
  217. if(cur->getNextAvailableSlot(bits_len, col, row))
  218. {
  219. atlasp = cur ;
  220. groupp->addAtlas(atlasp) ;
  221. break ;
  222. }
  223. }
  224. }
  225. }
  226. //create a new atlas if necessary
  227. if(!atlasp)
  228. {
  229. if(mEmptyAtlasMap[ncomponents - 1].size() > 0)
  230. {
  231. //there is an empty one
  232. atlasp = mEmptyAtlasMap[ncomponents - 1].back() ;
  233. mEmptyAtlasMap[ncomponents - 1].pop_back() ;
  234. }
  235. else
  236. {
  237. atlasp = new LLTextureAtlas(ncomponents, 16) ;
  238. }
  239. mAtlasMap[ncomponents - 1].push_back(atlasp) ;
  240. atlasp->getNextAvailableSlot(bits_len, col, row) ;
  241. groupp->addAtlas(atlasp) ;
  242. }
  243. F32 xoffset, yoffset ;
  244. atlasp->getTexCoordOffset(col, row, xoffset, yoffset) ;
  245. LLPointer<LLTextureAtlasSlot> slot_infop = new LLTextureAtlasSlot(atlasp, groupp, col, row, xoffset, yoffset, bits_len) ;
  246. return slot_infop ;
  247. }
  248. //*********************************************************************************************
  249. //END of implementation of class LLTextureAtlasManager
  250. //*********************************************************************************************