TXXLoader.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. #include "TXXLoader.h"
  2. #ifndef _XBOX
  3. //------------- загрузчик для PC
  4. #include "..\..\Common_h\data_swizzle.h"
  5. TXXLoader::SD_TEXFORMAT TXXLoader::TexFormats[] =
  6. {
  7. {txxf_dxt1, D3DFMT_DXT1, true, 4, "D3DFMT_DXT1"},
  8. {txxf_dxt3, D3DFMT_DXT3, true, 4, "D3DFMT_DXT3"},
  9. {txxf_dxt5, D3DFMT_DXT5, true, 4, "D3DFMT_DXT5"},
  10. {txxf_a8r8g8b8, D3DFMT_A8R8G8B8, false, 1, "D3DFMT_A8R8G8B8"},
  11. {txxf_r5g6b5, D3DFMT_R5G6B5, false, 1, "D3DFMT_R5G6B5"},
  12. {txxf_a4r4g4b4, D3DFMT_A4R4G4B4, false, 1, "D3DFMT_A4R4G4B4"},
  13. {txxf_a1r5g5b5, D3DFMT_A1R5G5B5, false, 1, "D3DFMT_A1R5G5B5"},
  14. {txxf_q8w8v8u8, D3DFMT_Q8W8V8U8, false, 1, "D3DFMT_Q8W8V8U8"},
  15. {txxf_v8u8, D3DFMT_V8U8, false, 1, "D3DFMT_V8U8"},
  16. {txxf_a8, D3DFMT_A8, false, 1, "D3DFMT_A8"},
  17. {txxf_l8, D3DFMT_L8, false, 1, "D3DFMT_L8"},
  18. {txxf_unknown, D3DFMT_X8R8G8B8, false, 1, "D3DFMT_X8R8G8B8"},
  19. {txxf_unknown, D3DFMT_D24S8, false, 1, "D3DFMT_D24S8"},
  20. {txxf_unknown, D3DFMT_D16, false, 1, "D3DFMT_D16"},
  21. {txxf_unknown, D3DFMT_D24X8, false, 1, "D3DFMT_D24X8"},
  22. /* X360 unsupported
  23. {txxf_unknown, D3DFMT_D24X4S4, false, 1, "D3DFMT_D24X4S4"},
  24. {txxf_unknown, D3DFMT_D15S1, false, 1, "D3DFMT_D15S1"},
  25. */
  26. {txxf_unknown, D3DFMT_D32, false, 1, "D3DFMT_D32"}
  27. };
  28. TXXLoader::TXXLoader(NGRender* r_srv)
  29. {
  30. bSkipDegradation = false;
  31. pRS = r_srv;
  32. pFS = (IFileService *)api->GetService("FileService");
  33. Assert(pFS);
  34. }
  35. TXXLoader::~TXXLoader()
  36. {
  37. }
  38. TXXLoader::SD_TEXFORMAT* TXXLoader::GetFormat(TXXFormat txFormat)
  39. {
  40. for (dword i=0; i < sizeof(TexFormats) / sizeof(SD_TEXFORMAT); i++)
  41. {
  42. if (TexFormats[i].txFormat == txFormat)
  43. {
  44. return &TexFormats[i];
  45. }
  46. }
  47. return null;
  48. }
  49. void TXXLoader::IgnoreDegradation (bool bIgnore)
  50. {
  51. bSkipDegradation = bIgnore;
  52. }
  53. IBaseTexture* TXXLoader::Load_TXX (const char* fileName, const char* sourceFile, long sourceLine)
  54. {
  55. strFullPath = fileName;
  56. strFullPath.AddExtention(".txx");
  57. IDataFile * file = pFS->OpenDataFile(strFullPath.c_str(), file_open_default, _FL_);
  58. if (!file)
  59. {
  60. api->Trace("DX9Error: Can't find texture : '%s' (%s, line: %d)", strFullPath.c_str(), sourceFile, sourceLine);
  61. return NULL;
  62. }
  63. TxxFileHeader head;
  64. file->Read(&head, sizeof(TxxFileHeader));
  65. XSwizzleULong(head.id);
  66. XSwizzleULong(head.ver);
  67. XSwizzleULong(head.type);
  68. XSwizzleULong(head.format);
  69. XSwizzleULong(head.width);
  70. XSwizzleULong(head.height);
  71. XSwizzleULong(head.depth);
  72. XSwizzleULong(head.num_mips);
  73. XSwizzleULong(head.line_size);
  74. XSwizzleULong(head.bpp);
  75. XSwizzleFloat(head.fps);
  76. /*
  77. #ifdef _XBOX
  78. head.num_mips = 1;
  79. #endif
  80. */
  81. SD_TEXFORMAT * pTexFormat = GetFormat((TXXFormat)head.format);
  82. if (!pTexFormat)
  83. {
  84. api->Trace("DX9Error: unknown texture format: %d, texture: %s (%s, line: %d)", head.format, fileName, sourceFile, sourceLine);
  85. return NULL;
  86. }
  87. // apply texture degradation
  88. dword dwSeekPos = 0;
  89. dword dwDegradation = pRS->GetTextureDegradation();
  90. if (bSkipDegradation)
  91. {
  92. dwDegradation = 0;
  93. }
  94. //dwDegradation = 2;
  95. for (dword i=0; i< dwDegradation; i++)
  96. {
  97. if (head.num_mips <= 1 || head.width <= 32 || head.height <= 32) break; // degradation limit
  98. dwSeekPos += head.line_size * head.height;
  99. head.num_mips--;
  100. head.line_size /= 2;
  101. head.width /= 2;
  102. head.height /= 2;
  103. }
  104. if (dwSeekPos)
  105. {
  106. //file->SetPos(dwSeekPos, FILE_CURRENT);
  107. file->Read(null, dwSeekPos);
  108. }
  109. if (head.type == txxt_volume) // if texture - volume texture
  110. {
  111. file->Release();
  112. return NULL;
  113. }
  114. if (head.type == txxt_cube) // if texture - cubemap texture
  115. {
  116. file->Release();
  117. return NULL;
  118. }
  119. if (head.type == txxt_2d || head.type == txxt_rendertarget) // if simple texture
  120. {
  121. CDX8Texture* pTexture = NULL;
  122. if (pRS->IsMipMapsFillColor() && head.num_mips != 1)
  123. {
  124. pTexture = CreateMipMapColoredTexture(head, *pTexFormat);
  125. } else
  126. {
  127. pTexture = LoadTexture(file, head, *pTexFormat);
  128. }
  129. if (pTexture)
  130. {
  131. pTexture->SetFileLine(sourceFile, sourceLine);
  132. pTexture->SetRef(1);
  133. file->Release();
  134. /*
  135. #ifdef _XBOX
  136. pTexture->ConvertToX360();
  137. #endif
  138. */
  139. return pTexture;
  140. }
  141. }
  142. file->Release();
  143. return NULL;
  144. }
  145. CDX8Texture* TXXLoader::LoadTexture(IDataFile* file, const TxxFileHeader& _head, SD_TEXFORMAT texFormat)
  146. {
  147. TxxFileHeader head = _head;
  148. CDX8Texture * pSysMemTexture = null;
  149. CDX8Texture * pDX8Texture = null;
  150. CDX8Texture * pLockTexture = null;
  151. bool bRenderTarget = (head.type == txxt_rendertarget);
  152. int savedWidth = head.width;
  153. int savedHeight = head.height;
  154. pDX8Texture = (CDX8Texture *)pRS->CreateTexture(head.width, head.height, head.num_mips, (bRenderTarget) ? USAGE_RENDERTARGET : 0, FormatFromDX (texFormat.d3dFormat), null, -1, (bRenderTarget) ? POOL_DEFAULT : POOL_MANAGED);
  155. if (!pDX8Texture) return null;
  156. pLockTexture = pDX8Texture;
  157. if (bRenderTarget)
  158. {
  159. pSysMemTexture = (CDX8Texture *)pRS->CreateTexture(head.width, head.height, head.num_mips, 0, FormatFromDX (texFormat.d3dFormat), null, -1, POOL_SYSTEMMEM);
  160. if (!pSysMemTexture)
  161. {
  162. pDX8Texture->Release();
  163. return null;
  164. }
  165. pDX8Texture->SetSysMemTexture(pSysMemTexture);
  166. pLockTexture = pSysMemTexture;
  167. }
  168. for (dword i=0; i<dword(head.num_mips); i++)
  169. {
  170. RENDERSURFACE_DESC desc;
  171. pLockTexture->GetLevelDesc(i, &desc);
  172. RENDERLOCKED_RECT lr;
  173. if (pLockTexture->LockRect(i, &lr, null, 0))
  174. {
  175. pDX8Texture->AddLoadRef();
  176. LoadSurface(file, pDX8Texture, 0, i, &lr, head, texFormat);
  177. //pDX8Texture->UnlockRect(i);
  178. pDX8Texture->SetSize(pDX8Texture->GetSize() + head.line_size * head.height);
  179. }
  180. head.line_size /= 2;
  181. head.width /= 2;
  182. head.height /= 2;
  183. }
  184. if (bRenderTarget)
  185. {
  186. if (pDX8Texture->IsLoaded())
  187. {
  188. pDX8Texture->UpdateTexture();
  189. } else
  190. {
  191. if (!pDX8Texture->IsError())
  192. {
  193. pDX8Texture->bUpdateTexture = true;
  194. }
  195. }
  196. }
  197. return pDX8Texture;
  198. }
  199. bool TXXLoader::LoadBox(IDataFile * pRF, IBaseTexture * pTexture, RENDERLOCKED_BOX * pLB, const TxxFileHeader & TXHead, const SD_TEXFORMAT & TexFormat)
  200. {
  201. dword dwFullSize = TXHead.line_size * TXHead.height * TXHead.depth;
  202. dword readedBytes = pRF->Read(pLB->pBits, dwFullSize);
  203. if (readedBytes != dwFullSize)
  204. {
  205. return false;
  206. }
  207. return true;
  208. }
  209. bool TXXLoader::LoadSurface(IDataFile * pRF, IBaseTexture * pTexture, dword dwFace, dword dwLevel, RENDERLOCKED_RECT * pLR, const TxxFileHeader & TXHead, const SD_TEXFORMAT & TexFormat)
  210. {
  211. #ifndef _XBOX
  212. //На ПеСи целиком загружаем
  213. dword dwFullSize = TXHead.line_size * TXHead.height;
  214. dword readedBytes = pRF->Read(pLR->pBits, dwFullSize);
  215. if (readedBytes != dwFullSize)
  216. {
  217. return false;
  218. }
  219. #else
  220. //На коробке грузим по линиям текстуру
  221. dword dwMultipler = 1;
  222. switch (TXHead.format)
  223. {
  224. case txxf_dxt1:
  225. dwMultipler = 2;
  226. break;
  227. case txxf_dxt3:
  228. dwMultipler = 4;
  229. break;
  230. case txxf_dxt5:
  231. dwMultipler = 4;
  232. break;
  233. }
  234. byte* destPtr = (byte*)pLR->pBits;
  235. for (dword line = 0; line < (TXHead.height / dwMultipler); line++)
  236. {
  237. dword readedBytes = pRF->Read(destPtr, (TXHead.line_size*dwMultipler));
  238. if (readedBytes != (TXHead.line_size*dwMultipler))
  239. {
  240. return false;
  241. }
  242. destPtr += pLR->Pitch;
  243. }
  244. #endif
  245. //=====================================================================================================
  246. CDX8Texture *p2DTex = (CDX8Texture*)pTexture;
  247. if (p2DTex->IsRenderTarget())
  248. {
  249. p2DTex->GetSysMemTexture()->UnlockRect(dwLevel);
  250. p2DTex->DecLoadRef();
  251. if (p2DTex->IsLoaded() && p2DTex->bUpdateTexture)
  252. {
  253. p2DTex->UpdateTexture();
  254. }
  255. }
  256. else
  257. {
  258. p2DTex->UnlockRect(dwLevel);
  259. p2DTex->DecLoadRef();
  260. }
  261. return true;
  262. }
  263. CDX8Texture* TXXLoader::CreateMipMapColoredTexture(TxxFileHeader TXHead, const SD_TEXFORMAT & TexFormat)
  264. {
  265. CDX8Texture * pDX8Texture = (CDX8Texture *)pRS->CreateTexture(TXHead.width, TXHead.height, TXHead.num_mips, 0, FMT_DXT1, null, -1, POOL_MANAGED);
  266. if (!pDX8Texture) return null;
  267. /*
  268. dword dwColors[] = {0xff00ff00, 0xff0000ff, 0xffffaf00, 0xff00ffff,
  269. 0xffff00ff, 0xffff0000, 0xffdf0000, 0xffbf0000,
  270. 0xff9f0000, 0xff7f0000, 0xff5f0000, 0xff4f0000,
  271. 0xff3f0000, 0xff2f0000, 0xff1f0000, 0xff0f0000 };
  272. */
  273. dword dwColors[] = {0xff00ff00, 0xff0000ff,
  274. 0xffffff00, 0xffffe000, 0xffffc000, 0xffffa000,
  275. 0xffff8000, 0xffff6000, 0xffff4000, 0xffff2000, 0xffff0000 };
  276. word wColors[sizeof(dwColors) / sizeof(dwColors[0])];
  277. for (long i = 0; i<sizeof(dwColors) / sizeof(dwColors[0]); i++)
  278. {
  279. wColors[i] = Color::Make565(dwColors[i]);
  280. }
  281. float colorsCount = ((float)sizeof(dwColors) / (float)sizeof(dwColors[0]));
  282. float step = colorsCount / float(TXHead.num_mips - 1);
  283. float idx = 0.0f;
  284. for (long i=0; i < (long)TXHead.num_mips; i++, idx+=step)
  285. {
  286. RENDERLOCKED_RECT lr;
  287. word wColor = wColors[(int)idx];
  288. if (pDX8Texture->LockRect(i, &lr, null, 0))
  289. {
  290. word * pW = (word*)lr.pBits;
  291. for (long j=0; j<long(TXHead.height * TXHead.width / 16); j++)
  292. {
  293. *pW++ = wColor;
  294. *pW++ = 0;
  295. *pW++ = 0;
  296. *pW++ = 0;
  297. }
  298. pDX8Texture->UnlockRect(i);
  299. pDX8Texture->SetSize(pDX8Texture->GetSize() + TXHead.line_size * TXHead.height);
  300. }
  301. TXHead.line_size /= 2;
  302. TXHead.width /= 2;
  303. TXHead.height /= 2;
  304. }
  305. return pDX8Texture;
  306. }
  307. #else
  308. //------------- загрузчик для X360
  309. TXXLoader::TXXLoader(NGRender* r_srv)
  310. {
  311. pRS = r_srv;
  312. pFS = (IFileService *)api->GetService("FileService");
  313. Assert(pFS);
  314. }
  315. TXXLoader::~TXXLoader()
  316. {
  317. }
  318. IBaseTexture* TXXLoader::Load_TXX (const char* fileName, const char* sourceFile, long sourceLine)
  319. {
  320. //return NULL;
  321. //fileName = "resource\\textures\\inplace_texture.txx360";
  322. strFullPath = fileName;
  323. strFullPath.AddExtention(".txx360");
  324. IDataFile * file = pFS->OpenDataFile(strFullPath.c_str(), file_open_default, _FL_);
  325. if (!file)
  326. {
  327. api->Trace("DX9Error: Can't find texture : '%s' (%s, line: %d)", strFullPath.c_str(), sourceFile, sourceLine);
  328. return NULL;
  329. }
  330. /*
  331. DWORD dwSize = file->GetSize();
  332. BYTE* trashBuffer = NEW BYTE[dwSize*2];
  333. file->Read(trashBuffer, dwSize);
  334. file->Release();
  335. delete [] trashBuffer;
  336. return NULL;
  337. */
  338. CDX8Texture * pDX8Texture = null;
  339. pDX8Texture = (CDX8Texture *)pRS->AddTexture(sourceFile, sourceLine);
  340. if (!pDX8Texture) return null;
  341. DWORD dwSize = file->Size();
  342. dword dwHeaderSize = sizeof(D3DTexture);
  343. DWORD dwTextureDataSize = dwSize - dwHeaderSize;
  344. D3DTexture* texture = (D3DTexture*)malloc(dwHeaderSize);
  345. file->Read(texture, dwHeaderSize);
  346. // Now allocate space for the texture data. This needs to be allocated on 4K boundary in physical memory.
  347. DWORD dwAllocAttributes = MAKE_XALLOC_ATTRIBUTES( 0, FALSE, FALSE, FALSE, 0, XALLOC_PHYSICAL_ALIGNMENT_4K, XALLOC_MEMPROTECT_WRITECOMBINE, FALSE, XALLOC_MEMTYPE_PHYSICAL );
  348. BYTE* pTextureData = ( BYTE* )XMemAlloc( dwTextureDataSize, dwAllocAttributes );
  349. file->Read(pTextureData, dwTextureDataSize);
  350. file->Release();
  351. //texture->Fence = 0;
  352. // Now fix up the texture header to point to the base and mip addresses inside the texture data.
  353. // This is the final step - once this is done, the texture is ready to be used!
  354. D3DBaseTexture *pBaseTexture = ( D3DBaseTexture* )texture;
  355. XGOffsetBaseTextureAddress( pBaseTexture, pTextureData, pTextureData );
  356. //api->Trace("Texture name : '%s'", strFullPath.c_str());
  357. pDX8Texture->CreateFromGPUTexture(texture, pTextureData, dwAllocAttributes, dwTextureDataSize, fileName);
  358. return pDX8Texture;
  359. }
  360. #endif