texture.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WW3D *
  23. * *
  24. * $Archive:: /Commando/Code/ww3d2/texture.cpp $*
  25. * *
  26. * $Author:: Jani_p $*
  27. * *
  28. * $Modtime:: 8/29/01 7:06p $*
  29. * *
  30. * $Revision:: 65 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * FileListTextureClass::Load_Frame_Surface -- Load source texture *
  35. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  36. #include "texture.h"
  37. #include <d3d8.h>
  38. #include <stdio.h>
  39. #include <D3dx8core.h>
  40. #include "dx8wrapper.h"
  41. #include "targa.h"
  42. #include <nstrdup.h>
  43. #include "w3d_file.h"
  44. #include "assetmgr.h"
  45. #include "formconv.h"
  46. #include "textureloader.h"
  47. #include "missingtexture.h"
  48. #include "ffactory.h"
  49. #include "dx8caps.h"
  50. #include "dx8texman.h"
  51. #include "meshmatdesc.h"
  52. /*
  53. ** Definitions of static members:
  54. */
  55. static unsigned unused_texture_id;
  56. unsigned _MinTextureFilters[TextureClass::FILTER_TYPE_COUNT];
  57. unsigned _MagTextureFilters[TextureClass::FILTER_TYPE_COUNT];
  58. unsigned _MipMapFilters[TextureClass::FILTER_TYPE_COUNT];
  59. // ----------------------------------------------------------------------------
  60. static int Calculate_Texture_Memory_Usage(const TextureClass* texture,int red_factor=0)
  61. {
  62. // Set performance statistics
  63. int size=0;
  64. IDirect3DTexture8* d3d_texture=const_cast<TextureClass*>(texture)->Peek_DX8_Texture();
  65. if (!d3d_texture) return 0;
  66. for (unsigned i=red_factor;i<d3d_texture->GetLevelCount();++i) {
  67. D3DSURFACE_DESC desc;
  68. DX8_ErrorCode(d3d_texture->GetLevelDesc(i,&desc));
  69. size+=desc.Size;
  70. }
  71. return size;
  72. }
  73. /*************************************************************************
  74. ** TextureClass
  75. *************************************************************************/
  76. TextureClass::TextureClass(unsigned width, unsigned height, WW3DFormat format, MipCountType mip_level_count, PoolType pool,bool rendertarget)
  77. :
  78. D3DTexture(NULL),
  79. texture_id(unused_texture_id++),
  80. Initialized(true),
  81. TextureMinFilter(FILTER_TYPE_DEFAULT),
  82. TextureMagFilter(FILTER_TYPE_DEFAULT),
  83. MipMapFilter((mip_level_count!=MIP_LEVELS_1) ? FILTER_TYPE_DEFAULT : FILTER_TYPE_NONE),
  84. UAddressMode(TEXTURE_ADDRESS_REPEAT),
  85. VAddressMode(TEXTURE_ADDRESS_REPEAT),
  86. MipLevelCount(mip_level_count),
  87. Pool(pool),
  88. Dirty(false),
  89. IsLightmap(false),
  90. IsProcedural(true),
  91. Name(""),
  92. TextureFormat(format),
  93. IsCompressionAllowed(false),
  94. TextureLoadTask(NULL)
  95. {
  96. switch (format) {
  97. case WW3D_FORMAT_DXT1:
  98. case WW3D_FORMAT_DXT2:
  99. case WW3D_FORMAT_DXT3:
  100. case WW3D_FORMAT_DXT4:
  101. case WW3D_FORMAT_DXT5:
  102. IsCompressionAllowed=true;
  103. break;
  104. default:
  105. break;
  106. }
  107. D3DPOOL d3dpool=(D3DPOOL) 0;
  108. switch(pool)
  109. {
  110. case POOL_DEFAULT:
  111. d3dpool=D3DPOOL_DEFAULT;
  112. break;
  113. case POOL_MANAGED:
  114. d3dpool=D3DPOOL_MANAGED;
  115. break;
  116. case POOL_SYSTEMMEM:
  117. d3dpool=D3DPOOL_SYSTEMMEM;
  118. break;
  119. default:
  120. WWASSERT(0);
  121. }
  122. D3DTexture = DX8Wrapper::_Create_DX8_Texture(width, height, format, mip_level_count,d3dpool,rendertarget);
  123. if (pool==POOL_DEFAULT)
  124. {
  125. Dirty=true;
  126. DX8TextureTrackerClass *track=W3DNEW
  127. DX8TextureTrackerClass(width, height, format, mip_level_count,rendertarget,
  128. this);
  129. DX8TextureManagerClass::Add(track);
  130. }
  131. LastAccessed=WW3D::Get_Sync_Time();
  132. }
  133. // ----------------------------------------------------------------------------
  134. TextureClass::TextureClass(
  135. const char *name,
  136. const char *full_path,
  137. MipCountType mip_level_count,
  138. WW3DFormat texture_format,
  139. bool allow_compression)
  140. :
  141. D3DTexture(NULL),
  142. texture_id(unused_texture_id++),
  143. Initialized(false),
  144. TextureMinFilter(FILTER_TYPE_DEFAULT),
  145. TextureMagFilter(FILTER_TYPE_DEFAULT),
  146. MipMapFilter((mip_level_count!=MIP_LEVELS_1) ? FILTER_TYPE_DEFAULT : FILTER_TYPE_NONE),
  147. UAddressMode(TEXTURE_ADDRESS_REPEAT),
  148. VAddressMode(TEXTURE_ADDRESS_REPEAT),
  149. MipLevelCount(mip_level_count),
  150. Pool(POOL_MANAGED),
  151. Dirty(false),
  152. IsLightmap(false),
  153. IsProcedural(false),
  154. TextureFormat(texture_format),
  155. IsCompressionAllowed(allow_compression),
  156. TextureLoadTask(NULL)
  157. {
  158. switch (TextureFormat) {
  159. case WW3D_FORMAT_DXT1:
  160. case WW3D_FORMAT_DXT2:
  161. case WW3D_FORMAT_DXT3:
  162. case WW3D_FORMAT_DXT4:
  163. case WW3D_FORMAT_DXT5:
  164. IsCompressionAllowed=true;
  165. break;
  166. case WW3D_FORMAT_U8V8: // Bumpmap
  167. case WW3D_FORMAT_L6V5U5: // Bumpmap
  168. case WW3D_FORMAT_X8L8V8U8: // Bumpmap
  169. // If requesting bumpmap format that isn't available we'll just return the surface in whatever color
  170. // format the texture file is in. (This is illegal case, the format support should always be queried
  171. // before creating a bump texture!)
  172. if (!DX8Caps::Support_Texture_Format(TextureFormat)) {
  173. TextureFormat=WW3D_FORMAT_UNKNOWN;
  174. }
  175. // If bump format is valid, make sure compression is not allowed so that we don't even attempt to load
  176. // from a compressed file (quality isn't good enough for bump map). Also disable mipmapping.
  177. else {
  178. IsCompressionAllowed=false;
  179. MipLevelCount=MIP_LEVELS_1;
  180. MipMapFilter=FILTER_TYPE_NONE;
  181. }
  182. break;
  183. default:
  184. break;
  185. }
  186. WWASSERT_PRINT(name && name[0], "TextureClass CTor: NULL or empty texture name\n");
  187. int len=strlen(name);
  188. for (int i=0;i<len;++i) {
  189. if (name[i]=='+') {
  190. IsLightmap=true;
  191. // Set bilinear filtering for lightmaps (they are very stretched and
  192. // low detail so we don't care for anisotropic or trilinear filtering...)
  193. TextureMinFilter=FILTER_TYPE_FAST;
  194. TextureMagFilter=FILTER_TYPE_FAST;
  195. if (mip_level_count!=MIP_LEVELS_1) MipMapFilter=FILTER_TYPE_FAST;
  196. break;
  197. }
  198. }
  199. Set_Texture_Name(name);
  200. Set_Full_Path(full_path);
  201. WWASSERT(name[0]!='\0');
  202. if (!WW3D::Is_Texturing_Enabled()) {
  203. Initialized=true;
  204. D3DTexture=0;
  205. }
  206. else if (WW3D::Get_Texture_Thumbnail_Mode()==WW3D::TEXTURE_THUMBNAIL_MODE_OFF || mip_level_count==MIP_LEVELS_1)
  207. {
  208. Initialized=true;
  209. D3DTexture=0;
  210. TextureLoader::Request_High_Priority_Loading(this,mip_level_count);
  211. }
  212. else {
  213. Load_Locked_Surface();
  214. TextureFormat=texture_format; // Locked surface may be in a wrong format
  215. }
  216. LastAccessed=WW3D::Get_Sync_Time();
  217. }
  218. // ----------------------------------------------------------------------------
  219. TextureClass::TextureClass(SurfaceClass *surface, MipCountType mip_level_count)
  220. :
  221. D3DTexture(NULL),
  222. texture_id(unused_texture_id++),
  223. Initialized(true),
  224. TextureMinFilter(FILTER_TYPE_DEFAULT),
  225. TextureMagFilter(FILTER_TYPE_DEFAULT),
  226. MipMapFilter((mip_level_count!=MIP_LEVELS_1) ? FILTER_TYPE_DEFAULT : FILTER_TYPE_NONE),
  227. UAddressMode(TEXTURE_ADDRESS_REPEAT),
  228. VAddressMode(TEXTURE_ADDRESS_REPEAT),
  229. MipLevelCount(mip_level_count),
  230. Pool(POOL_MANAGED),
  231. Dirty(false),
  232. IsLightmap(false),
  233. Name(""),
  234. IsProcedural(true),
  235. TextureFormat(surface->Get_Surface_Format()),
  236. IsCompressionAllowed(false),
  237. TextureLoadTask(NULL)
  238. {
  239. SurfaceClass::SurfaceDescription sd;
  240. surface->Get_Description(sd);
  241. switch (sd.Format) {
  242. case WW3D_FORMAT_DXT1:
  243. case WW3D_FORMAT_DXT2:
  244. case WW3D_FORMAT_DXT3:
  245. case WW3D_FORMAT_DXT4:
  246. case WW3D_FORMAT_DXT5:
  247. IsCompressionAllowed=true;
  248. break;
  249. default:
  250. break;
  251. }
  252. D3DTexture = DX8Wrapper::_Create_DX8_Texture(surface->Peek_D3D_Surface(), mip_level_count);
  253. LastAccessed=WW3D::Get_Sync_Time();
  254. }
  255. // ----------------------------------------------------------------------------
  256. TextureClass::TextureClass(IDirect3DTexture8* d3d_texture)
  257. :
  258. D3DTexture(d3d_texture),
  259. texture_id(unused_texture_id++),
  260. Initialized(true),
  261. TextureMinFilter(FILTER_TYPE_DEFAULT),
  262. TextureMagFilter(FILTER_TYPE_DEFAULT),
  263. MipMapFilter((d3d_texture->GetLevelCount()!=1) ? FILTER_TYPE_DEFAULT : FILTER_TYPE_NONE),
  264. UAddressMode(TEXTURE_ADDRESS_REPEAT),
  265. VAddressMode(TEXTURE_ADDRESS_REPEAT),
  266. MipLevelCount((MipCountType)d3d_texture->GetLevelCount()),
  267. Pool(POOL_MANAGED),
  268. Dirty(false),
  269. IsLightmap(false),
  270. Name(""),
  271. IsProcedural(true),
  272. IsCompressionAllowed(false),
  273. TextureLoadTask(NULL)
  274. {
  275. D3DTexture->AddRef();
  276. IDirect3DSurface8* surface;
  277. DX8_ErrorCode(D3DTexture->GetSurfaceLevel(0,&surface));
  278. D3DSURFACE_DESC d3d_desc;
  279. ::ZeroMemory(&d3d_desc, sizeof(D3DSURFACE_DESC));
  280. DX8_ErrorCode(surface->GetDesc(&d3d_desc));
  281. TextureFormat=D3DFormat_To_WW3DFormat(d3d_desc.Format);
  282. switch (TextureFormat) {
  283. case WW3D_FORMAT_DXT1:
  284. case WW3D_FORMAT_DXT2:
  285. case WW3D_FORMAT_DXT3:
  286. case WW3D_FORMAT_DXT4:
  287. case WW3D_FORMAT_DXT5:
  288. IsCompressionAllowed=true;
  289. break;
  290. default:
  291. break;
  292. }
  293. LastAccessed=WW3D::Get_Sync_Time();
  294. }
  295. // ----------------------------------------------------------------------------
  296. TextureClass::~TextureClass(void)
  297. {
  298. TextureLoadTaskClass::Release_Instance(TextureLoadTask);
  299. TextureLoadTask=NULL;
  300. if (!Initialized) {
  301. WWDEBUG_SAY(("Warning: Texture %s was loaded but never used\n",Get_Texture_Name()));
  302. }
  303. if (D3DTexture) {
  304. D3DTexture->Release();
  305. D3DTexture = NULL;
  306. }
  307. DX8TextureManagerClass::Remove(this);
  308. }
  309. // ----------------------------------------------------------------------------
  310. void TextureClass::Init()
  311. {
  312. // If the texture has already been initialised we should exit now
  313. if (Initialized) return;
  314. TextureLoader::Add_Load_Task(this);
  315. LastAccessed=WW3D::Get_Sync_Time();
  316. }
  317. void TextureClass::Invalidate()
  318. {
  319. // Don't invalidate procedural textures
  320. if (IsProcedural) return;
  321. // Don't invalidate missing texture
  322. if (Is_Missing_Texture()) return;
  323. if (D3DTexture) {
  324. D3DTexture->Release();
  325. D3DTexture = NULL;
  326. }
  327. if (!WW3D::Is_Texturing_Enabled()) {
  328. Initialized=true;
  329. D3DTexture=0;
  330. }
  331. else if (WW3D::Get_Texture_Thumbnail_Mode()==WW3D::TEXTURE_THUMBNAIL_MODE_OFF || MipLevelCount==MIP_LEVELS_1)
  332. {
  333. Initialized=true;
  334. D3DTexture=0;
  335. TextureLoader::Request_High_Priority_Loading(this,MipLevelCount);
  336. }
  337. else {
  338. Initialized=false;
  339. Load_Locked_Surface();
  340. }
  341. }
  342. // ----------------------------------------------------------------------------
  343. void TextureClass::Load_Locked_Surface()
  344. {
  345. if (D3DTexture) D3DTexture->Release();
  346. D3DTexture=0;
  347. TextureLoader::Request_Thumbnail(this);
  348. Initialized=false;
  349. }
  350. // ----------------------------------------------------------------------------
  351. bool TextureClass::Is_Missing_Texture()
  352. {
  353. bool flag = false;
  354. IDirect3DTexture8 *missing_texture = MissingTexture::_Get_Missing_Texture();
  355. if(D3DTexture == missing_texture)
  356. flag = true;
  357. if(missing_texture)
  358. missing_texture->Release();
  359. return flag;
  360. }
  361. // ----------------------------------------------------------------------------
  362. void TextureClass::Set_Texture_Name(const char * name)
  363. {
  364. Name=name;
  365. }
  366. // ----------------------------------------------------------------------------
  367. unsigned int TextureClass::Get_Mip_Level_Count(void)
  368. {
  369. if (!D3DTexture) {
  370. WWASSERT_PRINT(0, "Get_Mip_Level_Count: D3DTexture is NULL!\n");
  371. return 0;
  372. }
  373. return D3DTexture->GetLevelCount();
  374. }
  375. // ----------------------------------------------------------------------------
  376. void TextureClass::Get_Level_Description(SurfaceClass::SurfaceDescription &surface_desc, unsigned int level)
  377. {
  378. if (!D3DTexture) {
  379. WWASSERT_PRINT(0, "Get_Surface_Description: D3DTexture is NULL!\n");
  380. }
  381. D3DSURFACE_DESC d3d_surf_desc;
  382. DX8_ErrorCode(D3DTexture->GetLevelDesc(level, &d3d_surf_desc));
  383. surface_desc.Format = D3DFormat_To_WW3DFormat(d3d_surf_desc.Format);
  384. surface_desc.Height = d3d_surf_desc.Height;
  385. surface_desc.Width = d3d_surf_desc.Width;
  386. }
  387. // ----------------------------------------------------------------------------
  388. SurfaceClass *TextureClass::Get_Surface_Level(unsigned int level)
  389. {
  390. IDirect3DSurface8 *d3d_surface = NULL;
  391. DX8_ErrorCode(D3DTexture->GetSurfaceLevel(level, &d3d_surface));
  392. SurfaceClass *surface = W3DNEW SurfaceClass(d3d_surface);
  393. d3d_surface->Release();
  394. return surface;
  395. }
  396. // ----------------------------------------------------------------------------
  397. unsigned int TextureClass::Get_Priority(void)
  398. {
  399. if (!D3DTexture) {
  400. WWASSERT_PRINT(0, "Get_Priority: D3DTexture is NULL!\n");
  401. return 0;
  402. }
  403. return D3DTexture->GetPriority();
  404. }
  405. // ----------------------------------------------------------------------------
  406. unsigned int TextureClass::Set_Priority(unsigned int priority)
  407. {
  408. if (!D3DTexture) {
  409. WWASSERT_PRINT(0, "Set_Priority: D3DTexture is NULL!\n");
  410. return 0;
  411. }
  412. return D3DTexture->SetPriority(priority);
  413. }
  414. // ----------------------------------------------------------------------------
  415. void TextureClass::Set_Mip_Mapping(FilterType mipmap)
  416. {
  417. if (mipmap != FILTER_TYPE_NONE && Get_Mip_Level_Count() <= 1) {
  418. WWASSERT_PRINT(0, "Trying to enable MipMapping on texture w/o Mip levels!\n");
  419. return;
  420. }
  421. MipMapFilter=mipmap;
  422. }
  423. unsigned TextureClass::Get_Reduction() const
  424. {
  425. if (MipLevelCount==MIP_LEVELS_1) return 0;
  426. int reduction=WW3D::Get_Texture_Reduction();
  427. if (MipLevelCount && reduction>MipLevelCount) {
  428. reduction=MipLevelCount;
  429. }
  430. return reduction;
  431. }
  432. // ----------------------------------------------------------------------------
  433. void TextureClass::Apply(unsigned int stage)
  434. {
  435. if (!Initialized) {
  436. Init();
  437. }
  438. LastAccessed=WW3D::Get_Sync_Time();
  439. DX8_RECORD_TEXTURE(this);
  440. // Set texture itself
  441. if (WW3D::Is_Texturing_Enabled()) {
  442. DX8Wrapper::Set_DX8_Texture(stage, D3DTexture);
  443. } else {
  444. DX8Wrapper::Set_DX8_Texture(stage, NULL);
  445. }
  446. DX8Wrapper::Set_DX8_Texture_Stage_State(stage,D3DTSS_MINFILTER,_MinTextureFilters[TextureMinFilter]);
  447. DX8Wrapper::Set_DX8_Texture_Stage_State(stage,D3DTSS_MAGFILTER,_MagTextureFilters[TextureMagFilter]);
  448. DX8Wrapper::Set_DX8_Texture_Stage_State(stage,D3DTSS_MIPFILTER,_MipMapFilters[MipMapFilter]);
  449. switch (Get_U_Addr_Mode()) {
  450. case TEXTURE_ADDRESS_REPEAT:
  451. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  452. break;
  453. case TEXTURE_ADDRESS_CLAMP:
  454. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
  455. break;
  456. }
  457. switch (Get_V_Addr_Mode()) {
  458. case TEXTURE_ADDRESS_REPEAT:
  459. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  460. break;
  461. case TEXTURE_ADDRESS_CLAMP:
  462. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
  463. break;
  464. }
  465. }
  466. // ----------------------------------------------------------------------------
  467. void TextureClass::Apply_Null(unsigned int stage)
  468. {
  469. // This function sets the render states for a "NULL" texture
  470. DX8Wrapper::Set_DX8_Texture(stage, NULL);
  471. }
  472. // ----------------------------------------------------------------------------
  473. void TextureClass::Apply_New_Surface(bool initialized)
  474. {
  475. if (D3DTexture) D3DTexture->Release();
  476. D3DTexture=TextureLoadTask->Peek_D3D_Texture();
  477. D3DTexture->AddRef();
  478. if (initialized) Initialized=true;
  479. WWASSERT(D3DTexture);
  480. IDirect3DSurface8* surface;
  481. DX8_ErrorCode(D3DTexture->GetSurfaceLevel(0,&surface));
  482. D3DSURFACE_DESC d3d_desc;
  483. ::ZeroMemory(&d3d_desc, sizeof(D3DSURFACE_DESC));
  484. DX8_ErrorCode(surface->GetDesc(&d3d_desc));
  485. // if (TextureFormat==WW3D_FORMAT_UNKNOWN) {
  486. TextureFormat=D3DFormat_To_WW3DFormat(d3d_desc.Format);
  487. // }
  488. // else {
  489. // WWASSERT(D3DFormat_To_WW3DFormat(d3d_desc.Format)==TextureFormat);
  490. // }
  491. surface->Release();
  492. }
  493. // ----------------------------------------------------------------------------
  494. unsigned TextureClass::Get_Texture_Memory_Usage() const
  495. {
  496. if (/*!ReductionEnabled || */!Initialized) return Calculate_Texture_Memory_Usage(this,0);
  497. // unsigned reduction=WW3D::Get_Texture_Reduction();
  498. // if (CurrentReductionFactor>reduction) reduction=CurrentReductionFactor;
  499. return Calculate_Texture_Memory_Usage(this,0);//reduction);
  500. }
  501. // ----------------------------------------------------------------------------
  502. int TextureClass::_Get_Total_Locked_Surface_Size()
  503. {
  504. int total_locked_surface_size=0;
  505. HashTemplateIterator<StringClass,TextureClass*> ite(WW3DAssetManager::Get_Instance()->Texture_Hash());
  506. // Loop through all the textures in the manager
  507. for (ite.First ();!ite.Is_Done();ite.Next ()) {
  508. // Get the current texture
  509. TextureClass* tex=ite.Peek_Value();
  510. if (!tex->Initialized) {
  511. // total_locked_surface_size+=tex->Get_Non_Reduced_Texture_Memory_Usage();
  512. total_locked_surface_size+=tex->Get_Texture_Memory_Usage();
  513. }
  514. }
  515. return total_locked_surface_size;
  516. }
  517. // ----------------------------------------------------------------------------
  518. int TextureClass::_Get_Total_Texture_Size()
  519. {
  520. int total_texture_size=0;
  521. HashTemplateIterator<StringClass,TextureClass*> ite(WW3DAssetManager::Get_Instance()->Texture_Hash());
  522. // Loop through all the textures in the manager
  523. for (ite.First ();!ite.Is_Done();ite.Next ()) {
  524. // Get the current texture
  525. TextureClass* tex=ite.Peek_Value();
  526. total_texture_size+=tex->Get_Texture_Memory_Usage();
  527. }
  528. return total_texture_size;
  529. }
  530. // ----------------------------------------------------------------------------
  531. int TextureClass::_Get_Total_Lightmap_Texture_Size()
  532. {
  533. int total_texture_size=0;
  534. HashTemplateIterator<StringClass,TextureClass*> ite(WW3DAssetManager::Get_Instance()->Texture_Hash());
  535. // Loop through all the textures in the manager
  536. for (ite.First ();!ite.Is_Done();ite.Next ()) {
  537. // Get the current texture
  538. TextureClass* tex=ite.Peek_Value();
  539. if (tex->Is_Lightmap()) {
  540. total_texture_size+=tex->Get_Texture_Memory_Usage();
  541. }
  542. }
  543. return total_texture_size;
  544. }
  545. // ----------------------------------------------------------------------------
  546. int TextureClass::_Get_Total_Procedural_Texture_Size()
  547. {
  548. int total_texture_size=0;
  549. HashTemplateIterator<StringClass,TextureClass*> ite(WW3DAssetManager::Get_Instance()->Texture_Hash());
  550. // Loop through all the textures in the manager
  551. for (ite.First ();!ite.Is_Done();ite.Next ()) {
  552. // Get the current texture
  553. TextureClass* tex=ite.Peek_Value();
  554. if (tex->Is_Procedural()) {
  555. total_texture_size+=tex->Get_Texture_Memory_Usage();
  556. }
  557. }
  558. return total_texture_size;
  559. }
  560. // ----------------------------------------------------------------------------
  561. int TextureClass::_Get_Total_Texture_Count()
  562. {
  563. int texture_count=0;
  564. HashTemplateIterator<StringClass,TextureClass*> ite(WW3DAssetManager::Get_Instance()->Texture_Hash());
  565. // Loop through all the textures in the manager
  566. for (ite.First ();!ite.Is_Done();ite.Next ()) {
  567. texture_count++;
  568. }
  569. return texture_count;
  570. }
  571. // ----------------------------------------------------------------------------
  572. int TextureClass::_Get_Total_Lightmap_Texture_Count()
  573. {
  574. int texture_count=0;
  575. HashTemplateIterator<StringClass,TextureClass*> ite(WW3DAssetManager::Get_Instance()->Texture_Hash());
  576. // Loop through all the textures in the manager
  577. for (ite.First ();!ite.Is_Done();ite.Next ()) {
  578. if (ite.Peek_Value()->Is_Lightmap()) {
  579. texture_count++;
  580. }
  581. }
  582. return texture_count;
  583. }
  584. // ----------------------------------------------------------------------------
  585. int TextureClass::_Get_Total_Procedural_Texture_Count()
  586. {
  587. int texture_count=0;
  588. HashTemplateIterator<StringClass,TextureClass*> ite(WW3DAssetManager::Get_Instance()->Texture_Hash());
  589. // Loop through all the textures in the manager
  590. for (ite.First ();!ite.Is_Done();ite.Next ()) {
  591. if (ite.Peek_Value()->Is_Procedural()) {
  592. texture_count++;
  593. }
  594. }
  595. return texture_count;
  596. }
  597. // ----------------------------------------------------------------------------
  598. int TextureClass::_Get_Total_Locked_Surface_Count()
  599. {
  600. int texture_count=0;
  601. HashTemplateIterator<StringClass,TextureClass*> ite(WW3DAssetManager::Get_Instance()->Texture_Hash());
  602. // Loop through all the textures in the manager
  603. for (ite.First ();!ite.Is_Done();ite.Next ()) {
  604. // Get the current texture
  605. TextureClass* tex=ite.Peek_Value();
  606. if (!tex->Initialized) {
  607. texture_count++;
  608. }
  609. }
  610. return texture_count;
  611. }
  612. /*
  613. bool Validate_Filters(unsigned type)
  614. {
  615. ShaderClass shader=ShaderClass::_PresetOpaqueShader;
  616. shader.Apply();
  617. DX8Wrapper::Set_DX8_Texture(0, MissingTexture::_Get_Missing_Texture());
  618. DX8Wrapper::Set_DX8_Texture_Stage_State(0,D3DTSS_MINFILTER,_MinTextureFilters[type]);
  619. DX8Wrapper::Set_DX8_Texture_Stage_State(0,D3DTSS_MAGFILTER,_MagTextureFilters[type]);
  620. DX8Wrapper::Set_DX8_Texture_Stage_State(0,D3DTSS_MIPFILTER,_MipMapFilters[type]);
  621. unsigned long passes;
  622. HRESULT hres=DX8Wrapper::_Get_D3D_Device8()->ValidateDevice(&passes);
  623. return !FAILED(hres);
  624. }
  625. */
  626. void TextureClass::_Init_Filters()
  627. {
  628. const D3DCAPS8& dx8caps=DX8Caps::Get_Default_Caps();
  629. _MinTextureFilters[FILTER_TYPE_NONE]=D3DTEXF_POINT;
  630. _MagTextureFilters[FILTER_TYPE_NONE]=D3DTEXF_POINT;
  631. _MipMapFilters[FILTER_TYPE_NONE]=D3DTEXF_NONE;
  632. _MinTextureFilters[FILTER_TYPE_FAST]=D3DTEXF_LINEAR;
  633. _MagTextureFilters[FILTER_TYPE_FAST]=D3DTEXF_LINEAR;
  634. _MipMapFilters[FILTER_TYPE_FAST]=D3DTEXF_POINT;
  635. // Jani: Disabling anisotropic filtering as it doesn't seem to work with the latest nVidia drivers.
  636. if (dx8caps.TextureFilterCaps&D3DPTFILTERCAPS_MAGFAFLATCUBIC) _MagTextureFilters[FILTER_TYPE_BEST]=D3DTEXF_FLATCUBIC;
  637. else if (dx8caps.TextureFilterCaps&D3DPTFILTERCAPS_MAGFANISOTROPIC) _MagTextureFilters[FILTER_TYPE_BEST]=D3DTEXF_ANISOTROPIC;
  638. else if (dx8caps.TextureFilterCaps&D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC) _MagTextureFilters[FILTER_TYPE_BEST]=D3DTEXF_GAUSSIANCUBIC;
  639. else if (dx8caps.TextureFilterCaps&D3DPTFILTERCAPS_MAGFLINEAR) _MagTextureFilters[FILTER_TYPE_BEST]=D3DTEXF_LINEAR;
  640. else if (dx8caps.TextureFilterCaps&D3DPTFILTERCAPS_MAGFPOINT) _MagTextureFilters[FILTER_TYPE_BEST]=D3DTEXF_POINT;
  641. else {
  642. WWASSERT_PRINT(0,("No magnification filter found!"));
  643. }
  644. if (dx8caps.TextureFilterCaps&D3DPTFILTERCAPS_MINFANISOTROPIC) _MinTextureFilters[FILTER_TYPE_BEST]=D3DTEXF_ANISOTROPIC;
  645. else if (dx8caps.TextureFilterCaps&D3DPTFILTERCAPS_MINFLINEAR) _MinTextureFilters[FILTER_TYPE_BEST]=D3DTEXF_LINEAR;
  646. else if (dx8caps.TextureFilterCaps&D3DPTFILTERCAPS_MINFPOINT) _MinTextureFilters[FILTER_TYPE_BEST]=D3DTEXF_POINT;
  647. else {
  648. WWASSERT_PRINT(0,("No minification filter found!"));
  649. }
  650. if (dx8caps.TextureFilterCaps&D3DPTFILTERCAPS_MIPFLINEAR) _MipMapFilters[FILTER_TYPE_BEST]=D3DTEXF_LINEAR;
  651. else if (dx8caps.TextureFilterCaps&D3DPTFILTERCAPS_MIPFPOINT) _MipMapFilters[FILTER_TYPE_BEST]=D3DTEXF_POINT;
  652. else {
  653. WWASSERT_PRINT(0,("No mip filter found!"));
  654. }
  655. //_MagTextureFilters[FILTER_TYPE_BEST]=D3DTEXF_FLATCUBIC;
  656. // WWASSERT(Validate_Filters(FILTER_TYPE_BEST));
  657. _MinTextureFilters[FILTER_TYPE_DEFAULT]=_MinTextureFilters[FILTER_TYPE_BEST];
  658. _MagTextureFilters[FILTER_TYPE_DEFAULT]=_MagTextureFilters[FILTER_TYPE_BEST];
  659. _MipMapFilters[FILTER_TYPE_DEFAULT]=_MipMapFilters[FILTER_TYPE_BEST];
  660. for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
  661. DX8Wrapper::Set_DX8_Texture_Stage_State(stage,D3DTSS_MAXANISOTROPY,2);
  662. }
  663. }
  664. void TextureClass::_Set_Default_Min_Filter(FilterType filter)
  665. {
  666. _MinTextureFilters[FILTER_TYPE_DEFAULT]=_MinTextureFilters[filter];
  667. }
  668. void TextureClass::_Set_Default_Mag_Filter(FilterType filter)
  669. {
  670. _MagTextureFilters[FILTER_TYPE_DEFAULT]=_MagTextureFilters[filter];
  671. }
  672. void TextureClass::_Set_Default_Mip_Filter(FilterType filter)
  673. {
  674. _MipMapFilters[FILTER_TYPE_DEFAULT]=_MipMapFilters[filter];
  675. }
  676. // Utility functions
  677. TextureClass *Load_Texture(ChunkLoadClass & cload)
  678. {
  679. // Assume failure
  680. TextureClass *newtex = NULL;
  681. char name[256];
  682. if (cload.Open_Chunk () && (cload.Cur_Chunk_ID () == W3D_CHUNK_TEXTURE)) {
  683. W3dTextureInfoStruct texinfo;
  684. bool hastexinfo = false;
  685. /*
  686. ** Read in the texture filename, and a possible texture info structure.
  687. */
  688. while (cload.Open_Chunk()) {
  689. switch (cload.Cur_Chunk_ID()) {
  690. case W3D_CHUNK_TEXTURE_NAME:
  691. cload.Read(&name,cload.Cur_Chunk_Length());
  692. break;
  693. case W3D_CHUNK_TEXTURE_INFO:
  694. cload.Read(&texinfo,sizeof(W3dTextureInfoStruct));
  695. hastexinfo = true;
  696. break;
  697. };
  698. cload.Close_Chunk();
  699. }
  700. cload.Close_Chunk();
  701. /*
  702. ** Get the texture from the asset manager
  703. */
  704. if (hastexinfo) {
  705. TextureClass::MipCountType mipcount;
  706. bool no_lod = ((texinfo.Attributes & W3DTEXTURE_NO_LOD) == W3DTEXTURE_NO_LOD);
  707. if (no_lod) {
  708. mipcount = TextureClass::MIP_LEVELS_1;
  709. } else {
  710. switch (texinfo.Attributes & W3DTEXTURE_MIP_LEVELS_MASK) {
  711. case W3DTEXTURE_MIP_LEVELS_ALL:
  712. mipcount = TextureClass::MIP_LEVELS_ALL;
  713. break;
  714. case W3DTEXTURE_MIP_LEVELS_2:
  715. mipcount = TextureClass::MIP_LEVELS_2;
  716. break;
  717. case W3DTEXTURE_MIP_LEVELS_3:
  718. mipcount = TextureClass::MIP_LEVELS_3;
  719. break;
  720. case W3DTEXTURE_MIP_LEVELS_4:
  721. mipcount = TextureClass::MIP_LEVELS_4;
  722. break;
  723. default:
  724. WWASSERT (false);
  725. mipcount = TextureClass::MIP_LEVELS_ALL;
  726. break;
  727. }
  728. }
  729. newtex = WW3DAssetManager::Get_Instance()->Get_Texture (name, mipcount);
  730. if (no_lod) {
  731. newtex->Set_Mip_Mapping(TextureClass::FILTER_TYPE_NONE);
  732. }
  733. bool u_clamp = ((texinfo.Attributes & W3DTEXTURE_CLAMP_U) != 0);
  734. newtex->Set_U_Addr_Mode(u_clamp ? TextureClass::TEXTURE_ADDRESS_CLAMP : TextureClass::TEXTURE_ADDRESS_REPEAT);
  735. bool v_clamp = ((texinfo.Attributes & W3DTEXTURE_CLAMP_V) != 0);
  736. newtex->Set_V_Addr_Mode(v_clamp ? TextureClass::TEXTURE_ADDRESS_CLAMP : TextureClass::TEXTURE_ADDRESS_REPEAT);
  737. switch (texinfo.Attributes & W3DTEXTURE_TYPE_MASK) {
  738. case W3DTEXTURE_TYPE_COLORMAP:
  739. // Do nothing.
  740. break;
  741. case W3DTEXTURE_TYPE_BUMPMAP:
  742. {
  743. TextureClass *releasetex = newtex;
  744. // Format is assumed to be a grayscale heightmap. Convert it to a bump map.
  745. newtex = WW3DAssetManager::Get_Instance()->Get_Bumpmap_Based_On_Texture (newtex);
  746. WW3DAssetManager::Get_Instance()->Release_Texture (releasetex);
  747. break;
  748. }
  749. default:
  750. WWASSERT (false);
  751. break;
  752. }
  753. } else {
  754. newtex = WW3DAssetManager::Get_Instance()->Get_Texture(name);
  755. }
  756. WWASSERT(newtex);
  757. }
  758. // Return a pointer to the new texture
  759. return newtex;
  760. }
  761. // Utility function used by Save_Texture
  762. void setup_texture_attributes(TextureClass * tex, W3dTextureInfoStruct * texinfo)
  763. {
  764. texinfo->Attributes = 0;
  765. if (tex->Get_Mip_Mapping() == TextureClass::FILTER_TYPE_NONE) texinfo->Attributes |= W3DTEXTURE_NO_LOD;
  766. if (tex->Get_U_Addr_Mode() == TextureClass::TEXTURE_ADDRESS_CLAMP) texinfo->Attributes |= W3DTEXTURE_CLAMP_U;
  767. if (tex->Get_V_Addr_Mode() == TextureClass::TEXTURE_ADDRESS_CLAMP) texinfo->Attributes |= W3DTEXTURE_CLAMP_V;
  768. }
  769. void Save_Texture(TextureClass * texture,ChunkSaveClass & csave)
  770. {
  771. const char * filename;
  772. W3dTextureInfoStruct texinfo;
  773. memset(&texinfo,0,sizeof(texinfo));
  774. filename = texture->Get_Full_Path();
  775. setup_texture_attributes(texture, &texinfo);
  776. csave.Begin_Chunk(W3D_CHUNK_TEXTURE_NAME);
  777. csave.Write(filename,strlen(filename)+1);
  778. csave.End_Chunk();
  779. if ((texinfo.Attributes != 0) || (texinfo.AnimType != 0) || (texinfo.FrameCount != 0)) {
  780. csave.Begin_Chunk(W3D_CHUNK_TEXTURE_INFO);
  781. csave.Write(&texinfo, sizeof(texinfo));
  782. csave.End_Chunk();
  783. }
  784. }
  785. // ----------------------------------------------------------------------------
  786. BumpmapTextureClass::BumpmapTextureClass(TextureClass* texture)
  787. :
  788. // TextureClass(texture->Get_Width(),texture->Get_Height(),texture->Get_Textur4e_Format(),MIP_LEVELS_1)
  789. TextureClass(TextureLoader::Generate_Bumpmap(texture))
  790. {
  791. // D3DTexture=TextureLoader::Generate_Bumpmap(texture);
  792. // TextureLoader:::Generage_Bumpmap
  793. }
  794. BumpmapTextureClass::~BumpmapTextureClass()
  795. {
  796. }