texture_resource.cpp 17 KB

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