texture_resource.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. /*
  2. Copyright (c) 2013 Daniele Bartolini, Michele Rossi
  3. Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
  4. Permission is hereby granted, free of charge, to any person
  5. obtaining a copy of this software and associated documentation
  6. files (the "Software"), to deal in the Software without
  7. restriction, including without limitation the rights to use,
  8. copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. copies of the Software, and to permit persons to whom the
  10. Software is furnished to do so, subject to the following
  11. conditions:
  12. The above copyright notice and this permission notice shall be
  13. included in all copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  15. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  16. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  17. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  19. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  21. OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #include "filesystem.h"
  24. #include "texture_resource.h"
  25. #include "reader_writer.h"
  26. #include "json_parser.h"
  27. #include "math_utils.h"
  28. #include "resource_manager.h"
  29. #include "log.h"
  30. #include "compile_options.h"
  31. namespace crown
  32. {
  33. #define FOURCC(a, b, c, d) uint32_t(a | (b << 8) | (c << 16) | (d << 24))
  34. #define DDSD_MAGIC FOURCC('D', 'D', 'S', ' ')
  35. #define DDSD_HEADERSIZE uint32_t(124)
  36. #define DDSD_UNUSED uint32_t(0x00000000)
  37. #define DDSD_CAPS uint32_t(0x00000001) // Required in every .dds file.
  38. #define DDSD_HEIGHT uint32_t(0x00000002) // Required in every .dds file.
  39. #define DDSD_WIDTH uint32_t(0x00000004) // Required in every .dds file.
  40. #define DDSD_PITCH uint32_t(0x00000008) // Required when pitch is provided for an uncompressed texture.
  41. #define DDSD_PIXELFORMAT uint32_t(0x00001000) // Required in every .dds file.
  42. #define DDSD_MIPMAPCOUNT uint32_t(0x00020000) // Required in a mipmapped texture.
  43. #define DDSD_LINEARSIZE uint32_t(0x00080000) // Required when pitch is provided for a compressed texture.
  44. #define DDSD_DEPTH uint32_t(0x00800000) // Required in a depth texture.
  45. #define DDS_HEADER_FLAGS_TEXTURE uint32_t(DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT)
  46. #define DDS_HEADER_FLAGS_MIPMAP uint32_t(DDSD_MIPMAPCOUNT)
  47. #define DDS_HEADER_FLAGS_VOLUME uint32_t(DDSD_DEPTH)
  48. #define DDS_HEADER_FLAGS_PITCH uint32_t(DDSD_PITCH)
  49. #define DDS_HEADER_FLAGS_LINEARSIZE uint32_t(DDSD_LINEARSIZE)
  50. #define DDSCAPS_COMPLEX uint32_t(0x00000008) // Optional; must be used on any file that contains more than one surface (a mipmap, a cubic environment map, or mipmapped volume texture).
  51. #define DDSCAPS_MIPMAP uint32_t(0x00400000) // Optional; should be used for a mipmap.
  52. #define DDSCAPS_TEXTURE uint32_t(0x00001000) // Required
  53. #define DDSCAPS2_CUBEMAP uint32_t(0x00000200) // Required for a cube map.
  54. #define DDSCAPS2_CUBEMAP_POSITIVEX uint32_t(0x00000400) // Required when these surfaces are stored in a cube map.
  55. #define DDSCAPS2_CUBEMAP_NEGATIVEX uint32_t(0x00000800) // Required when these surfaces are stored in a cube map.
  56. #define DDSCAPS2_CUBEMAP_POSITIVEY uint32_t(0x00001000) // Required when these surfaces are stored in a cube map.
  57. #define DDSCAPS2_CUBEMAP_NEGATIVEY uint32_t(0x00002000) // Required when these surfaces are stored in a cube map.
  58. #define DDSCAPS2_CUBEMAP_POSITIVEZ uint32_t(0x00004000) // Required when these surfaces are stored in a cube map.
  59. #define DDSCAPS2_CUBEMAP_NEGATIVEZ uint32_t(0x00008000) // Required when these surfaces are stored in a cube map.
  60. #define DDSCAPS2_VOLUME uint32_t(0x00200000) // Required for a volume texture.
  61. #define DDPF_HEADERSIZE uint32_t(32)
  62. #define DDPF_ALPHAPIXELS uint32_t(0x00000001) // Texture contains alpha data; dwRGBAlphaBitMask contains valid data.
  63. #define DDPF_ALPHA uint32_t(0x00000002) // Used in some older DDS files for alpha channel only uncompressed data (dwRGBBitCount contains the alpha channel bitcount; dwABitMask contains valid data)
  64. #define DDPF_FOURCC uint32_t(0x00000004) // Texture contains compressed RGB data; dwFourCC contains valid data.
  65. #define DDPF_RGB uint32_t(0x00000040) // Texture contains uncompressed RGB data; dwRGBBitCount and the RGB masks (dwRBitMask, dwGBitMask, dwBBitMask) contain valid data.
  66. #define DDPF_YUV uint32_t(0x00000200) // Used in some older DDS files for YUV uncompressed data (dwRGBBitCount contains the YUV bit count; dwRBitMask contains the Y mask, dwGBitMask contains the U mask, dwBBitMask contains the V mask)
  67. #define DDPF_LUMINANCE uint32_t(0x00020000) // Used in some older DDS files for single channel color uncompressed data (dwRGBBitCount contains the luminance channel bit count; dwRBitMask contains the channel mask). Can be combined with DDPF_ALPHAPIXELS for a two channel DDS file.
  68. #define DDS_FOURCC uint32_t(DDPF_FOURCC)
  69. #define DDS_RGB uint32_t(DDPF_RGB)
  70. #define DDS_RGBA uint32_t(DDPF_RGB | DDPF_ALPHAPIXELS)
  71. #define DDS_LUMINANCE uint32_t(DDPF_LUMINANCE)
  72. #define DDS_LUMINANCEA uint32_t(DDPF_LUMINANCE | DDPF_ALPHAPIXELS)
  73. #define DDS_ALPHA uint32_t(DDPF_ALPHA)
  74. #define DDPF_FOURCC_DXT1 FOURCC('D', 'X', 'T', '1')
  75. #define DDPF_FOURCC_DXT2 FOURCC('D', 'X', 'T', '2')
  76. #define DDPF_FOURCC_DXT3 FOURCC('D', 'X', 'T', '3')
  77. #define DDPF_FOURCC_DXT4 FOURCC('D', 'X', 'T', '4')
  78. #define DDPF_FOURCC_DXT5 FOURCC('D', 'X', 'T', '5')
  79. #define DDPF_FOURCC_DX10 FOURCC('D', 'X', '1', '0')
  80. #define DDS_HEADER_OFFSET uint32_t(sizeof(TextureHeader))
  81. #define DDS_DATA_OFFSET uint32_t(DDS_HEADER_OFFSET + DDSD_HEADERSIZE)
  82. struct DdsPixelFormat
  83. {
  84. uint32_t size;
  85. uint32_t flags;
  86. uint32_t fourcc;
  87. uint32_t bitcount;
  88. uint32_t rmask;
  89. uint32_t gmask;
  90. uint32_t bmask;
  91. uint32_t amask;
  92. };
  93. struct DdsHeader
  94. {
  95. uint32_t magic;
  96. uint32_t size;
  97. uint32_t flags;
  98. uint32_t height;
  99. uint32_t width;
  100. uint32_t pitch_or_linear_size;
  101. uint32_t depth;
  102. uint32_t num_mips;
  103. uint32_t reserved[11];
  104. DdsPixelFormat ddspf;
  105. uint32_t caps;
  106. uint32_t caps2;
  107. uint32_t caps3;
  108. uint32_t caps4;
  109. uint32_t reserved2;
  110. };
  111. struct PixelFormat
  112. {
  113. enum Enum
  114. {
  115. DXT1,
  116. DXT3,
  117. DXT5,
  118. R8G8B8,
  119. R8G8B8A8,
  120. D16,
  121. D24,
  122. D32,
  123. D24S8,
  124. COUNT
  125. };
  126. };
  127. namespace pixel_format
  128. {
  129. inline uint32_t size(PixelFormat::Enum fmt)
  130. {
  131. switch (fmt)
  132. {
  133. case PixelFormat::DXT1: return 8;
  134. case PixelFormat::DXT3: return 16;
  135. case PixelFormat::DXT5: return 16;
  136. case PixelFormat::R8G8B8: return 3;
  137. case PixelFormat::R8G8B8A8: return 4;
  138. case PixelFormat::D16: return 2;
  139. case PixelFormat::D24: return 3;
  140. case PixelFormat::D32: return 4;
  141. case PixelFormat::D24S8: return 4;
  142. default: CE_FATAL("Unknown pixel format"); return 0;
  143. }
  144. }
  145. inline bool is_compressed(PixelFormat::Enum fmt)
  146. {
  147. return fmt < PixelFormat::R8G8B8;
  148. }
  149. inline bool is_color(PixelFormat::Enum fmt)
  150. {
  151. return fmt >= PixelFormat::R8G8B8 && fmt < PixelFormat::D16;
  152. }
  153. inline bool is_depth(PixelFormat::Enum fmt)
  154. {
  155. return fmt >= PixelFormat::D16 && fmt < PixelFormat::COUNT;
  156. }
  157. } // namespace pixel_format
  158. namespace texture_resource
  159. {
  160. struct ImageData
  161. {
  162. uint32_t width;
  163. uint32_t height;
  164. uint32_t pitch;
  165. PixelFormat::Enum format;
  166. uint32_t num_mips;
  167. char* data;
  168. };
  169. struct MipData
  170. {
  171. uint32_t width;
  172. uint32_t height;
  173. PixelFormat::Enum format;
  174. uint32_t size;
  175. char* data;
  176. };
  177. void read_mip_image(const ImageData& image, uint8_t mip, MipData& data)
  178. {
  179. uint32_t width = image.width;
  180. uint32_t height = image.height;
  181. //uint32_t pitch = image.pitch;
  182. uint32_t cur_mip = 0;
  183. char* src = image.data;
  184. while (1)
  185. {
  186. const uint32_t size = width * height * pixel_format::size(image.format);
  187. if (cur_mip == mip)
  188. {
  189. data.width = width;
  190. data.height = height;
  191. data.format = image.format;
  192. data.size = size;
  193. data.data = src;
  194. return;
  195. }
  196. width = max(1u, width >> 1);
  197. height = max(1u, height >> 1);
  198. cur_mip++;
  199. src += size;
  200. }
  201. }
  202. void swap_red_blue(uint32_t width, uint32_t height, uint8_t channels, char* data)
  203. {
  204. uint32_t i = 0;
  205. for (uint32_t h = 0; h < height; h++)
  206. {
  207. for (uint32_t w = 0; w < width; w++)
  208. {
  209. const uint8_t tmp = data[i + 0];
  210. data[i + 0] = data[i + 2];
  211. data[i + 2] = tmp;
  212. i += channels;
  213. }
  214. }
  215. }
  216. void read_tga_uncompressed(BinaryReader& br, uint32_t width, uint32_t height, uint8_t channels, ImageData& image)
  217. {
  218. if (channels == 2)
  219. {
  220. uint32_t i = 0;
  221. for (uint32_t h = 0; h < height; h++)
  222. {
  223. for (uint32_t w = 0; w < width; w++)
  224. {
  225. uint16_t data;
  226. br.read(data);
  227. image.data[i + 0] = (data & 0x7c) >> 10;
  228. image.data[i + 1] = (data & 0x3e) >> 5;
  229. image.data[i + 2] = (data & 0x1f);
  230. i += 3;
  231. }
  232. }
  233. }
  234. else
  235. {
  236. br.read(image.data, width * height * channels);
  237. swap_red_blue(width, height, channels, image.data);
  238. }
  239. }
  240. void read_tga_compressed(BinaryReader& br, uint32_t width, uint32_t height, uint8_t channels, ImageData& image)
  241. {
  242. uint8_t rle_id = 0;
  243. uint32_t i = 0;
  244. uint32_t colors_read = 0;
  245. // Can't be more than 4 channels
  246. uint8_t colors[4];
  247. while (i < width * height)
  248. {
  249. br.read(rle_id);
  250. // If MSB == 1
  251. if (rle_id & 0x80)
  252. {
  253. rle_id -= 127;
  254. br.read(colors[0]);
  255. br.read(colors[1]);
  256. br.read(colors[2]);
  257. if (channels == 4)
  258. br.read(colors[3]);
  259. while (rle_id)
  260. {
  261. image.data[colors_read + 0] = colors[2];
  262. image.data[colors_read + 1] = colors[1];
  263. image.data[colors_read + 2] = colors[0];
  264. if (channels == 4)
  265. image.data[colors_read + 3] = colors[3];
  266. rle_id--;
  267. colors_read += channels;
  268. i++;
  269. }
  270. }
  271. else
  272. {
  273. rle_id++;
  274. while (rle_id)
  275. {
  276. br.read(colors[0]);
  277. br.read(colors[1]);
  278. br.read(colors[2]);
  279. if (channels == 4)
  280. br.read(colors[3]);
  281. image.data[colors_read + 0] = colors[2];
  282. image.data[colors_read + 1] = colors[1];
  283. image.data[colors_read + 2] = colors[0];
  284. if (channels == 4)
  285. image.data[colors_read + 3] = colors[3];
  286. rle_id--;
  287. colors_read += channels;
  288. i++;
  289. }
  290. }
  291. }
  292. swap_red_blue(width, height, channels, image.data);
  293. }
  294. void parse_tga(BinaryReader& br, ImageData& image)
  295. {
  296. uint8_t id;
  297. br.read(id);
  298. uint8_t cmap_type;
  299. br.read(cmap_type);
  300. uint8_t image_type;
  301. br.read(image_type);
  302. uint8_t garbage;
  303. for (uint32_t i = 0; i < 5; i++)
  304. br.read(garbage);
  305. uint16_t x_offt;
  306. br.read(x_offt);
  307. uint16_t y_offt;
  308. br.read(y_offt);
  309. uint16_t width;
  310. br.read(width);
  311. uint16_t height;
  312. br.read(height);
  313. uint8_t depth;
  314. br.read(depth);
  315. uint8_t desc;
  316. br.read(desc);
  317. // Skip TGA ID
  318. br.skip(id);
  319. CE_ASSERT(image_type != 0, "TGA does not contain image data");
  320. CE_ASSERT(image_type == 2 || image_type == 10, "TGA image format not supported");
  321. const uint32_t channels = depth / 8;
  322. image.width = width;
  323. image.height = height;
  324. image.num_mips = 1;
  325. switch (channels)
  326. {
  327. case 2: image.format = PixelFormat::R8G8B8; break;
  328. case 3: image.format = PixelFormat::R8G8B8; break;
  329. case 4: image.format = PixelFormat::R8G8B8A8; break;
  330. default: CE_FATAL("TGA channels not supported"); break;
  331. }
  332. image.data = (char*) default_allocator().allocate(pixel_format::size(image.format) * width * height);
  333. if (image_type == 2)
  334. {
  335. read_tga_uncompressed(br, width, height, channels, image);
  336. }
  337. else if (image_type == 10)
  338. {
  339. read_tga_compressed(br, width, height, channels, image);
  340. }
  341. return;
  342. }
  343. void parse_dds(BinaryReader& br, ImageData& image)
  344. {
  345. // Read header
  346. uint32_t magic;
  347. br.read(magic);
  348. CE_ASSERT(magic == DDSD_MAGIC, "DDS bad magic number");
  349. uint32_t hsize;
  350. br.read(hsize);
  351. CE_ASSERT(hsize == DDSD_HEADERSIZE, "DDS bas header size");
  352. uint32_t flags;
  353. br.read(flags);
  354. CE_ASSERT(flags & (DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT), "DDS bad header flags");
  355. uint32_t height;
  356. br.read(height);
  357. uint32_t width;
  358. br.read(width);
  359. uint32_t pitch;
  360. br.read(pitch);
  361. uint32_t depth;
  362. br.read(depth);
  363. uint32_t num_mips;
  364. br.read(num_mips);
  365. // Skip reserved bits
  366. br.skip(sizeof(uint32_t) * 11);
  367. // Read pixel format
  368. uint32_t pf_hsize;
  369. br.read(pf_hsize);
  370. CE_ASSERT(pf_hsize == DDPF_HEADERSIZE, "DDS bad pf header size");
  371. uint32_t pf_flags;
  372. br.read(pf_flags);
  373. uint32_t pf_fourcc;
  374. br.read(pf_fourcc);
  375. uint32_t pf_bitcount;
  376. br.read(pf_bitcount);
  377. uint32_t pf_rmask;
  378. br.read(pf_rmask);
  379. uint32_t pf_gmask;
  380. br.read(pf_gmask);
  381. uint32_t pf_bmask;
  382. br.read(pf_bmask);
  383. uint32_t pf_amask;
  384. br.read(pf_amask);
  385. uint32_t caps;
  386. br.read(caps);
  387. CE_ASSERT((caps & DDSCAPS_TEXTURE), "DDS bad caps");
  388. uint32_t caps2;
  389. br.read(caps2);
  390. uint32_t caps3;
  391. br.read(caps3);
  392. uint32_t caps4;
  393. br.read(caps4);
  394. uint32_t reserved2;
  395. br.read(reserved2);
  396. CE_LOGD("width = %u", width);
  397. CE_LOGD("height = %u", height);
  398. CE_LOGD("mips = %u", num_mips);
  399. CE_LOGD("pitch = %u (valid = %s)", pitch, flags & DDSD_PITCH ? "yes" : "no");
  400. CE_LOGD("pfflags = %.8x", pf_flags);
  401. image.width = width;
  402. image.height = height;
  403. image.pitch = pitch;
  404. image.num_mips = (flags & DDSD_MIPMAPCOUNT) ? num_mips : 1;
  405. image.data = (char*) (uintptr_t) DDS_DATA_OFFSET;
  406. const uint32_t raw_fmt = (pf_flags & DDPF_FOURCC) ? pf_fourcc : pf_flags;
  407. switch (raw_fmt)
  408. {
  409. case DDPF_FOURCC_DXT1: image.format = PixelFormat::DXT1; break;
  410. case DDPF_FOURCC_DXT3: image.format = PixelFormat::DXT3; break;
  411. case DDPF_FOURCC_DXT5: image.format = PixelFormat::DXT5; break;
  412. case DDS_RGB: image.format = PixelFormat::R8G8B8; break;
  413. case DDS_RGBA: image.format = PixelFormat::R8G8B8A8; break;
  414. default: image.format = PixelFormat::COUNT; break;
  415. }
  416. CE_ASSERT(image.format != PixelFormat::COUNT, "DDS pixel format not supported");
  417. CE_LOGD("PixelFormat = %u", image.format);
  418. }
  419. void write_dds(BinaryWriter& bw, const ImageData& image)
  420. {
  421. bw.write(DDSD_MAGIC);
  422. // Header
  423. bw.write(DDSD_HEADERSIZE); // dwSize
  424. bw.write(DDS_HEADER_FLAGS_TEXTURE
  425. | DDSD_MIPMAPCOUNT
  426. | (pixel_format::is_compressed(image.format) ? DDSD_LINEARSIZE : DDSD_PITCH)
  427. | (image.num_mips ? DDSD_MIPMAPCOUNT : 0)); // dwFlags
  428. bw.write(image.height); // dwHeight
  429. bw.write(image.width); // dwWidth
  430. const uint32_t pitch = pixel_format::is_compressed(image.format) ? 0 // fixme
  431. : (image.width * pixel_format::size(image.format) * 8 + 7) / 8;
  432. bw.write(pitch); // dwPitchOrLinearSize
  433. bw.write(DDSD_UNUSED); // dwDepth
  434. bw.write(image.num_mips); // dwMipMapCount;
  435. for (uint32_t i = 0; i < 11; i++)
  436. bw.write(DDSD_UNUSED); // dwReserved1[11];
  437. // Pixel format
  438. bw.write(DDPF_HEADERSIZE); // dwSize;
  439. uint32_t pf = 0;
  440. switch (image.format)
  441. {
  442. case PixelFormat::DXT1: pf = DDPF_FOURCC_DXT1; break;
  443. case PixelFormat::DXT3: pf = DDPF_FOURCC_DXT3; break;
  444. case PixelFormat::DXT5: pf = DDPF_FOURCC_DXT5; break;
  445. case PixelFormat::R8G8B8: pf = DDS_RGB; break;
  446. case PixelFormat::R8G8B8A8: pf = DDS_RGBA; break;
  447. default: CE_FATAL("Pixel format unknown"); break;
  448. }
  449. bw.write(pixel_format::is_compressed(image.format) ? DDPF_FOURCC : pf); // dwFlags;
  450. bw.write(pixel_format::is_compressed(image.format) ? pf : DDSD_UNUSED); // dwFourCC;
  451. bw.write(uint32_t(pixel_format::size(image.format) * 8)); // dwRGBBitCount;
  452. bw.write(uint32_t(0x00FF0000)); // dwRBitMask;
  453. bw.write(uint32_t(0x0000FF00)); // dwGBitMask;
  454. bw.write(uint32_t(0x000000FF)); // dwBBitMask;
  455. bw.write(uint32_t(0xFF000000)); // dwABitMask;
  456. bw.write(DDSCAPS_TEXTURE
  457. | (image.num_mips > 1 ? DDSCAPS_COMPLEX : DDSD_UNUSED) // also for cubemap, depth mipmap
  458. | (image.num_mips > 1 ? DDSCAPS_MIPMAP : DDSD_UNUSED)); // dwCaps;
  459. bw.write(DDSD_UNUSED); // dwCaps2;
  460. bw.write(DDSD_UNUSED); // dwCaps3;
  461. bw.write(DDSD_UNUSED); // dwCaps4;
  462. bw.write(DDSD_UNUSED); // dwReserved2;
  463. // Image data
  464. for (uint32_t i = 0; i < image.num_mips; i++)
  465. {
  466. MipData mip;
  467. read_mip_image(image, i, mip);
  468. // CE_LOGD("Writing mip: (%ux%u) byes = %u", mip.width, mip.height, mip.size);
  469. bw.write(mip.data, mip.size);
  470. }
  471. }
  472. void compile(const char* path, CompileOptions& opts)
  473. {
  474. static const uint32_t VERSION = 1;
  475. Buffer buf = opts.read(path);
  476. JSONParser json(array::begin(buf));
  477. JSONElement root = json.root();
  478. DynamicString name;
  479. root.key("source").to_string(name);
  480. File* source = opts._fs.open(name.c_str(), FOM_READ);
  481. BinaryReader br(*source);
  482. ImageData image;
  483. if (name.ends_with(".tga"))
  484. {
  485. parse_tga(br, image);
  486. }
  487. else if (name.ends_with(".dds"))
  488. {
  489. // parse_dds(br, image);
  490. // size_t size = source->size();
  491. // image.data = (char*) default_allocator().allocate(size);
  492. // source->seek(0);
  493. // source->read(image.data, size);
  494. // image.data += DDS_DATA_OFFSET;
  495. // BinaryWriter bw(*out_file);
  496. // write_dds(bw, image);
  497. }
  498. else
  499. {
  500. CE_FATAL("Source image not supported");
  501. }
  502. opts._fs.close(source);
  503. // Write DDS
  504. opts.write(VERSION); // Version
  505. opts.write(uint32_t(0)); // Size
  506. write_dds(opts._bw, image);
  507. default_allocator().deallocate(image.data);
  508. }
  509. void* load(File& file, Allocator& a)
  510. {
  511. const size_t file_size = file.size();
  512. file.skip(sizeof(TextureHeader));
  513. const bgfx::Memory* mem = bgfx::alloc(file_size);
  514. file.read(mem->data, file_size - sizeof(TextureHeader));
  515. TextureResource* teximg = (TextureResource*) a.allocate(sizeof(TextureResource));
  516. teximg->mem = mem;
  517. teximg->handle.idx = bgfx::invalidHandle;
  518. return teximg;
  519. }
  520. void online(StringId64 id, ResourceManager& rm)
  521. {
  522. TextureResource* teximg = (TextureResource*) rm.get(TEXTURE_TYPE, id);
  523. teximg->handle = bgfx::createTexture(teximg->mem);
  524. }
  525. void offline(StringId64 id, ResourceManager& rm)
  526. {
  527. TextureResource* teximg = (TextureResource*) rm.get(TEXTURE_TYPE, id);
  528. bgfx::destroyTexture(teximg->handle);
  529. }
  530. void unload(Allocator& a, void* resource)
  531. {
  532. a.deallocate(resource);
  533. }
  534. } // namespace texture_resource
  535. } // namespace crown